using AobaCore.Models; using MaybeError.Errors; using MongoDB.Bson; using MongoDB.Driver; using MongoDB.Driver.GridFS; namespace AobaCore.Services; public class AobaService(IMongoDatabase db) { private readonly IMongoCollection _media = db.GetCollection("media"); private readonly GridFSBucket _gridFs = new(db); public async Task GetMediaAsync(ObjectId id, CancellationToken cancellationToken = default) { return await _media.Find(m => m.Id == id).FirstOrDefaultAsync(cancellationToken); } public async Task GetMediaFromFileAsync(ObjectId id, CancellationToken cancellationToken = default) { return await _media.Find(m => m.MediaId == id).FirstOrDefaultAsync(cancellationToken); } public async Task> FindMediaAsync(string? query, ObjectId userId, int page = 1, int pageSize = 100) { var filter = Builders.Filter.And([ string.IsNullOrWhiteSpace(query) ? "{}" : Builders.Filter.Text(query), Builders.Filter.Eq(m => m.Owner, userId) ]); var sort = Builders.Sort.Descending(m => m.UploadDate); var find = _media.Find(filter); var total = await find.CountDocumentsAsync(); page -= 1; var items = await find.Sort(sort).Skip(page * pageSize).Limit(pageSize).ToListAsync(); return new PagedResult(items, page, pageSize, total); } public Task AddMediaAsync(Media media, CancellationToken cancellationToken = default) { return _media.InsertOneAsync(media, null, cancellationToken); } public Task IncrementViewCountAsync(ObjectId id, CancellationToken cancellationToken = default) { return _media.UpdateOneAsync(m => m.Id == id, Builders.Update.Inc(m => m.ViewCount, 1), cancellationToken: cancellationToken); } public Task IncrementFileViewCountAsync(ObjectId fileId, CancellationToken cancellationToken = default) { return _media.UpdateOneAsync(m => m.MediaId == fileId, Builders.Update.Inc(m => m.ViewCount, 1), cancellationToken: cancellationToken); } public async Task> UploadFileAsync(Stream data, string filename, ObjectId owner, CancellationToken cancellationToken = default) { try { var fileId = await _gridFs.UploadFromStreamAsync(filename, data, cancellationToken: cancellationToken); var media = new Media(fileId, filename, owner); await AddMediaAsync(media, cancellationToken); return media; } catch (Exception ex) { return ex; } } public async Task> GetFileStreamAsync(ObjectId id, bool seekable = false, CancellationToken cancellationToken = default) { try { return await _gridFs.OpenDownloadStreamAsync(id, new GridFSDownloadOptions { Seekable = seekable }, cancellationToken); } catch (GridFSException ex) { return ex; } } public async Task DeleteFileAsync(ObjectId fileId, CancellationToken cancellationToken = default) { try { cancellationToken.ThrowIfCancellationRequested(); await _gridFs.DeleteAsync(fileId, CancellationToken.None); await _media.DeleteOneAsync(m => m.MediaId == fileId, CancellationToken.None); } catch (GridFSFileNotFoundException) { //ignore if file was not found } } public async Task DeriveTagsAsync(CancellationToken cancellationToken = default) { var mediaItems = await _media.Find(Builders.Filter.Exists(m => m.Tags, false)) .ToListAsync(cancellationToken); Console.WriteLine($"Derving Tag for {mediaItems.Count} items"); foreach (var mediaItem in mediaItems) { mediaItem.Tags = Media.DeriveTags(mediaItem.Filename); await _media.UpdateOneAsync(m => m.Id == mediaItem.Id, Builders.Update.Set(m => m.Tags, mediaItem.Tags), null, cancellationToken); } Console.WriteLine("All Tags Derived"); } }