7 Commits

Author SHA1 Message Date
f98429159f Fix incorrect dispose
Some checks failed
Build and Push Image / build-and-push (push) Has been cancelled
2025-07-23 16:22:09 -04:00
3dca408356 Cleanup potential memory leaks
Some checks failed
Build and Push Image / build-and-push (push) Has been cancelled
2025-07-23 15:45:35 -04:00
1655e342b7 Removed avif + heif support 2025-07-17 20:02:41 -04:00
7223c35658 Added avif + heif support
Some checks failed
Build and Push Image / build-and-push (push) Has been cancelled
2025-07-17 15:09:16 -04:00
b85bcd1c7a Add media url to MediaModel+Start work on tonenized search query model
Some checks failed
Build and Push Image / build-and-push (push) Has been cancelled
2025-07-12 18:10:21 -04:00
8536d335bc Make Search Sticky 2025-07-12 13:52:32 -04:00
b34f7436c2 fix cirucular deps
Some checks failed
Build and Push Image / build-and-push (push) Has been cancelled
added additonal file types
2025-07-09 21:08:10 -04:00
10 changed files with 67 additions and 17 deletions

View File

@@ -2,6 +2,8 @@
@import "colors";
* {
box-sizing: border-box;
scrollbar-color: $accentColor transparent;
scrollbar-width: thin;
}
:root {
@@ -18,6 +20,7 @@
.stickyTop {
top: 0;
position: sticky;
z-index: 100;
}
body {
@@ -34,6 +37,8 @@ body {
#content {
grid-area: Content;
overflow-x: hidden;
overflow-y: auto;
height: 100dvh;
padding: 10px;
/* margin-left: $navBarSize; */
}

View File

@@ -14,8 +14,13 @@ pub fn MediaItem(props: MediaItemProps) -> Element {
let filename = item.file_name;
let id = item.id.unwrap().value;
let thumb = item.thumb_url;
let url = item.media_url;
return rsx! {
a { class: "mediaItem", href: "{HOST}/m/{id}", target: "_blank",
a {
class: "mediaItem",
href: "{HOST}/{url}",
target: "_blank",
"data-id" : id,
img { src: "{HOST}{thumb}" }
span { class: "info",
span { class: "name", "{filename}" }

View File

@@ -9,14 +9,14 @@
<ItemGroup>
<PackageReference Include="FFMpegCore" Version="5.2.0" />
<PackageReference Include="Isopoh.Cryptography.Argon2" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.6" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.7" />
<PackageReference Include="MaybeError" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.6" />
<PackageReference Include="MongoDB.Driver" Version="3.4.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.7" />
<PackageReference Include="MongoDB.Driver" Version="3.4.1" />
<PackageReference Include="MongoDB.Driver.Core.Extensions.DiagnosticSources" Version="2.1.0" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.6" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.12.1" />
<PackageReference Include="ZLinq" Version="1.4.12" />
<PackageReference Include="ZLinq" Version="1.5.1" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,8 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using SixLabors.ImageSharp;
namespace AobaCore.Models;
[BsonIgnoreExtraElements]
@@ -16,23 +18,27 @@ public class Media
public ObjectId Owner { get; set; }
public DateTime UploadDate { get; set; }
public string[] Tags { get; set; } = [];
public Size? Dimensions { get; set; }
public Dictionary<ThumbnailSize, ObjectId> Thumbnails { get; set; } = [];
public static readonly Dictionary<string, MediaType> KnownTypes = new()
{
{ ".jpg", MediaType.Image },
{ ".avif", MediaType.Image },
{ ".jpeg", MediaType.Image },
{ ".jxr", MediaType.Image },
{ ".avif", MediaType.Image },
{ ".png", MediaType.Image },
{ ".apng", MediaType.Image },
{ ".webp", MediaType.Image },
{ ".qoi", MediaType.Image },
{ ".ico", MediaType.Image },
{ ".gif", MediaType.Image },
{ ".mp3", MediaType.Audio },
{ ".flac", MediaType.Audio },
{ ".alac", MediaType.Audio },
{ ".mp4", MediaType.Video },
{ ".m4v", MediaType.Video },
{ ".webm", MediaType.Video },
{ ".mov", MediaType.Video },
{ ".avi", MediaType.Video },
@@ -79,7 +85,7 @@ public class Media
{
return this switch
{
//Media { MediaType: MediaType.Raw or MediaType.Text or MediaType.Code} => $"/i/dl/{MediaId}/{Filename}",
Media { MediaType: MediaType.Raw or MediaType.Text or MediaType.Code } => $"/m/{MediaId}/{Uri.EscapeDataString(Filename)}",
_ => $"/m/{MediaId}"
};
}

View File

@@ -10,7 +10,7 @@ using MongoDB.Driver.GridFS;
namespace AobaCore.Services;
public class AobaService(IMongoDatabase db, ThumbnailService thumbnailService, ILogger<AobaService> logger)
public class AobaService(IMongoDatabase db)
{
private readonly IMongoCollection<Media> _media = db.GetCollection<Media>("media");
private readonly GridFSBucket _gridFs = new(db);
@@ -79,6 +79,10 @@ public class AobaService(IMongoDatabase db, ThumbnailService thumbnailService, I
{
return ex;
}
finally
{
data.Dispose();
}
}
public async Task<MaybeEx<GridFSDownloadStream, GridFSException>> GetFileStreamAsync(ObjectId mediaId, bool seekable = false, CancellationToken cancellationToken = default)

View File

@@ -3,6 +3,7 @@
using FFMpegCore;
using FFMpegCore.Pipes;
using MaybeError.Errors;
using MongoDB.Bson;
@@ -10,6 +11,7 @@ using MongoDB.Driver;
using MongoDB.Driver.GridFS;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Processing;
using System;
@@ -91,17 +93,29 @@ public class ThumbnailService(IMongoDatabase db, AobaService aobaService)
{
return type switch
{
MediaType.Image => await GenerateImageThumbnailAsync(stream, size, cancellationToken),
MediaType.Image => await GenerateImageThumbnailAsync(stream, size, ext, cancellationToken),
MediaType.Video => GenerateVideoThumbnail(stream, size, cancellationToken),
MediaType.Text or MediaType.Code => await GenerateDocumentThumbnailAsync(stream, size, cancellationToken),
_ => new Error($"No Thumbnail for {type}"),
};
}
public static async Task<Stream> GenerateImageThumbnailAsync(Stream stream, ThumbnailSize size, CancellationToken cancellationToken = default)
private static Maybe<Image> LoadImage(Stream stream, string ext)
{
var img = Image.Load(stream);
img.Mutate(o =>
if (ext is ".heif" or ".avif")
{
return new Error("Unsupported image type");
}
else
return Image.Load(stream);
}
public static async Task<Maybe<Stream>> GenerateImageThumbnailAsync(Stream stream, ThumbnailSize size, string ext, CancellationToken cancellationToken = default)
{
var img = LoadImage(stream, ext);
if (img.HasError)
return img.Error;
img.Value.Mutate(o =>
{
var size =
o.Resize(new ResizeOptions
@@ -112,7 +126,8 @@ public class ThumbnailService(IMongoDatabase db, AobaService aobaService)
});
});
var result = new MemoryStream();
await img.SaveAsWebpAsync(result, cancellationToken);
await img.Value.SaveAsWebpAsync(result, cancellationToken);
img.Value.Dispose();
result.Position = 0;
return result;
}
@@ -141,7 +156,7 @@ public class ThumbnailService(IMongoDatabase db, AobaService aobaService)
output.Position = 0;
return output;
}
catch(Exception ex)
catch (Exception ex)
{
return ex;
}

View File

@@ -16,7 +16,7 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Isopoh.Cryptography.Argon2" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.7" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.12.1" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />
<PackageReference Include="MimeTypesMap" Version="1.0.9" />
@@ -24,7 +24,7 @@
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.9.0-beta.2" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.12.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -14,6 +14,7 @@ namespace AobaServer.Controllers;
public class MediaController(AobaService aobaService, ILogger<MediaController> logger) : Controller
{
[HttpGet("{id}")]
[HttpGet("{id}/*")]
[ResponseCache(Duration = int.MaxValue)]
public async Task<IActionResult> MediaAsync(ObjectId id, [FromServices] MongoClient client, CancellationToken cancellationToken)
{
@@ -58,6 +59,7 @@ public class MediaController(AobaService aobaService, ILogger<MediaController> l
}
[HttpGet("/t/{id}")]
[ResponseCache(Duration = int.MaxValue)]
public async Task<IActionResult> ThumbAsync(ObjectId id, [FromServices] ThumbnailService thumbnailService, CancellationToken cancellationToken = default)
{
var thumb = await thumbnailService.GetThumbnailByFileIdAsync(id, cancellationToken);

View File

@@ -82,6 +82,7 @@ message MediaModel {
int32 viewCount = 5;
Id owner = 6;
string thumbUrl = 7;
string mediaUrl = 8;
}
enum MediaType {
@@ -99,3 +100,14 @@ message ShareXResponse {
string error = 2;
}
}
message SearchQuery {
optional string queryText = 1;
repeated Filter filters = 2;
}
message Filter {
string key = 1;
repeated string values = 2;
}

View File

@@ -56,6 +56,7 @@ public static class ProtoExtensions
Owner = media.Owner.ToId(),
ViewCount = media.ViewCount,
ThumbUrl = thumbUrl,
MediaUrl = media.GetMediaUrl()
};
}