diff --git a/AobaCore/Models/Media.cs b/AobaCore/Models/Media.cs index cb44cef..a7baea5 100644 --- a/AobaCore/Models/Media.cs +++ b/AobaCore/Models/Media.cs @@ -20,6 +20,7 @@ public class Media public string[] Tags { get; set; } = []; public Size? Dimensions { get; set; } public Dictionary Thumbnails { get; set; } = []; + public MediaClass Class { get; set; } public static readonly Dictionary KnownTypes = new() @@ -116,4 +117,11 @@ public enum MediaType Text, Code, Raw +} + +public enum MediaClass +{ + Standard, + NSFW, + Secret } \ No newline at end of file diff --git a/AobaCore/Services/AobaService.cs b/AobaCore/Services/AobaService.cs index 66591cf..a2a1636 100644 --- a/AobaCore/Services/AobaService.cs +++ b/AobaCore/Services/AobaService.cs @@ -25,25 +25,28 @@ public class AobaService(IMongoDatabase db) return await _media.Find(m => m.MediaId == id).FirstOrDefaultAsync(cancellationToken); } - public async Task> FindMediaAsync(string? query, ObjectId userId, int page = 1, int pageSize = 100) + public async Task> FindMediaAsync(string? query, ObjectId userId, int page = 1, int pageSize = 100, CancellationToken cancellationToken = default) { - var filter = Builders.Filter.And([ + var filters = new List>() + { string.IsNullOrWhiteSpace(query) ? "{}" : Builders.Filter.Text(query), Builders.Filter.Eq(m => m.Owner, userId) - ]); + }; + if (string.IsNullOrWhiteSpace(query)) + filters.Add(Builders.Filter.Ne(m => m.Class, MediaClass.Secret)); var sort = Builders.Sort.Descending(m => m.UploadDate); - var find = _media.Find(filter); + var find = _media.Find(Builders.Filter.And(filters)); - var total = await find.CountDocumentsAsync(); + var total = await find.CountDocumentsAsync(cancellationToken); page -= 1; - var items = await find.Sort(sort).Skip(page * pageSize).Limit(pageSize).ToListAsync(); + var items = await find.Sort(sort).Skip(page * pageSize).Limit(pageSize).ToListAsync(cancellationToken); return new PagedResult(items, page, pageSize, (int)total); } public async Task> FindMediaWithExtAsync(string ext, CancellationToken cancellationToken = default) { var filter = Builders.Filter.Eq(m => m.Ext, ext); - return await _media.Find(filter).ToListAsync(); + return await _media.Find(filter).ToListAsync(cancellationToken); } public Task AddMediaAsync(Media media, CancellationToken cancellationToken = default) @@ -51,6 +54,13 @@ public class AobaService(IMongoDatabase db) return _media.InsertOneAsync(media, null, cancellationToken); } + public async Task SetMediaClassAsync(ObjectId mediaId, MediaClass mediaClass, CancellationToken cancellationToken = default) + { + var update = Builders.Update + .Set(m => m.Class, mediaClass); + await _media.UpdateOneAsync(m => m.MediaId == mediaId, update, cancellationToken: cancellationToken); + } + public async Task AddThumbnailAsync(ObjectId mediaId, ObjectId thumbId, ThumbnailSize size, CancellationToken cancellationToken = default) { var upate = Builders.Update.Set(m => m.Thumbnails[size], thumbId); diff --git a/AobaServer/Proto/Aoba.proto b/AobaServer/Proto/Aoba.proto index 6013df8..526e6bb 100644 --- a/AobaServer/Proto/Aoba.proto +++ b/AobaServer/Proto/Aoba.proto @@ -12,5 +12,6 @@ service AobaRpc { rpc ListMedia(PageFilter) returns (ListResponse); rpc GetUser(Id) returns (UserResponse); rpc GetShareXDestination(google.protobuf.Empty) returns (ShareXResponse); + rpc SetMediaClass(SetMediaClassRequest) returns(google.protobuf.Empty); } diff --git a/AobaServer/Proto/Types.proto b/AobaServer/Proto/Types.proto index b110e41..6eb416b 100644 --- a/AobaServer/Proto/Types.proto +++ b/AobaServer/Proto/Types.proto @@ -9,7 +9,10 @@ message Credentials{ string password = 2; } - +message SetMediaClassRequest{ + Id id = 1; + MediaClass class = 2; +} message Jwt{ @@ -81,6 +84,7 @@ message MediaModel { Id owner = 6; string thumbUrl = 7; string mediaUrl = 8; + MediaClass class = 9; } enum MediaType { @@ -92,6 +96,12 @@ enum MediaType { Raw = 5; } +enum MediaClass { + Standard = 0; + NSFW = 1; + Secret = 2; +} + message ShareXResponse { oneof dstResult { string destination = 1; diff --git a/AobaServer/Services/AobaRpcService.cs b/AobaServer/Services/AobaRpcService.cs index 939849a..0b863b8 100644 --- a/AobaServer/Services/AobaRpcService.cs +++ b/AobaServer/Services/AobaRpcService.cs @@ -9,10 +9,7 @@ using Google.Protobuf.WellKnownTypes; using Grpc.Core; -using MongoDB.Bson.IO; - using System.Text.Json; -using System.Text.Json.Serialization; namespace AobaServer.Services; @@ -20,7 +17,7 @@ public class AobaRpcService(AobaService aobaService, AccountsService accountsSer { public override async Task GetMedia(Id request, ServerCallContext context) { - var media = await aobaService.GetMediaFromLegacyIdAsync(request.ToObjectId()); + var media = await aobaService.GetMediaFromLegacyIdAsync(request.ToObjectId(), context.CancellationToken); return media.ToResponse(); } @@ -31,6 +28,12 @@ public class AobaRpcService(AobaService aobaService, AccountsService accountsSer return result.ToResponse(); } + public override async Task SetMediaClass(SetMediaClassRequest request, ServerCallContext context) + { + await aobaService.SetMediaClassAsync(request.Id.ToObjectId(), (AobaCore.Models.MediaClass)request.Class, context.CancellationToken); + return new Empty(); + } + public override async Task GetShareXDestination(Empty request, ServerCallContext context) { var userId = context.GetHttpContext().User.GetId(); @@ -50,10 +53,7 @@ public class AobaRpcService(AobaService aobaService, AccountsService accountsSer }; return new ShareXResponse { - Destination = JsonSerializer.Serialize(dest, new JsonSerializerOptions - { - WriteIndented = true - }) + Destination = JsonSerializer.Serialize(dest) }; } diff --git a/AobaServer/Utils/ProtoExtensions.cs b/AobaServer/Utils/ProtoExtensions.cs index 4ef0cdd..8a1b571 100644 --- a/AobaServer/Utils/ProtoExtensions.cs +++ b/AobaServer/Utils/ProtoExtensions.cs @@ -56,7 +56,8 @@ public static class ProtoExtensions Owner = media.Owner.ToId(), ViewCount = media.ViewCount, ThumbUrl = thumbUrl, - MediaUrl = media.GetMediaUrl() + MediaUrl = media.GetMediaUrl(), + Class = (Aoba.RPC.MediaClass)media.Class, }; }