diff options
| -rw-r--r-- | Controllers/ApiMediaController.cs | 24 | ||||
| -rw-r--r-- | Controllers/ApiUserController.cs | 2 | ||||
| -rw-r--r-- | HBContext.cs | 15 | ||||
| -rw-r--r-- | Pages/Component/AboutDialog.razor | 2 | ||||
| -rw-r--r-- | Pages/Component/TagSelectDialog.razor | 2 | ||||
| -rw-r--r-- | Pages/TagDefinitions.razor | 8 | ||||
| -rw-r--r-- | Server.csproj | 4 | ||||
| -rw-r--r-- | Services/FeedService.cs | 2 | ||||
| -rw-r--r-- | Services/MediaService.cs | 33 |
9 files changed, 60 insertions, 32 deletions
diff --git a/Controllers/ApiMediaController.cs b/Controllers/ApiMediaController.cs index bb6c81e..8ca6121 100644 --- a/Controllers/ApiMediaController.cs +++ b/Controllers/ApiMediaController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using System.Text.Json; +using System.Text.RegularExpressions; namespace HyperBooru.Controllers; @@ -15,6 +16,9 @@ public class ApiMediaController : Controller { private IDbContextFactory<HBContext> dbFactory; private IMediaService mediaService; + private readonly Regex checksumRegex = + new Regex("^[0-9a-f]{32}$", RegexOptions.IgnoreCase | RegexOptions.Compiled); + public ApiMediaController(IDbContextFactory<HBContext> dbFactory, IMediaService mediaService) { this.dbFactory = dbFactory; this.mediaService = mediaService; @@ -32,6 +36,26 @@ public class ApiMediaController : Controller { return Ok((ApiModels.Media) media); } + [HttpGet("checksum/{checksum}")] + public async Task<IActionResult> GetChecksum([FromRoute] string checksum) { + if(!checksumRegex.IsMatch(checksum)) + throw new ApiModels.ArgumentException("Invalid checksum string"); + + using var db = dbFactory.CreateDbContext(); + + var media = await db.UploadedFiles + .Include(uf => uf.Media) + .Where(uf => uf.Checksum == checksum.ToLower()) + .Select(uf => uf.Media) + .Distinct() + .ToArrayAsync(); + + if(media.Count() == 0) + throw new ObjectNotFoundException([ Guid.Empty ]); + + return Ok(media.Select(m => (ApiModels.Media) m).ToArray()); + } + [HttpGet("{mediaId}/files")] public async Task<IActionResult> GetUploadedFiles([FromRoute] Guid mediaId) { using var db = dbFactory.CreateDbContext(); diff --git a/Controllers/ApiUserController.cs b/Controllers/ApiUserController.cs index 3230218..c581956 100644 --- a/Controllers/ApiUserController.cs +++ b/Controllers/ApiUserController.cs @@ -92,7 +92,7 @@ public class ApiUserController : Controller { [HttpDelete("{userId}")] public async Task<IActionResult> DeleteUserAsync([FromRoute] Guid userId) { - if(userId == HBContext.AdminUser) + if(userId == InternalTag.AdminUser) throw new ApiModels.ArgumentException("Cannot delete the admin user"); using var db = dbFactory.CreateDbContext(); diff --git a/HBContext.cs b/HBContext.cs index 766c0a3..d13378d 100644 --- a/HBContext.cs +++ b/HBContext.cs @@ -4,16 +4,7 @@ using Microsoft.EntityFrameworkCore; namespace HyperBooru; -enum HBObjectId { - NsfwTag = -1, - IngestTag = -2, - AdminUser = -3 -} - public class HBContext : DbContext { - public static readonly Guid NsfwTag = new("EBDAD4F8-455A-4351-8017-1D4854D6FA38"); - public static readonly Guid IngestTag = new("EA212801-5BCC-4C0E-814F-FB9D30DB58BC"); - public static readonly Guid AdminUser = new("4FA948F4-7C45-4F81-BB6B-E417491E6C96"); public DbSet<HBObject> Objects { get; set; } public DbSet<User> Users { get; set; } @@ -49,13 +40,13 @@ public class HBContext : DbContext { modelBuilder.Entity<TagDefinition>().HasData(new TagDefinition[] { new() { ObjectId = (int) HBObjectId.NsfwTag, - Guid = NsfwTag, + Guid = InternalTag.NsfwTag, Source = TagSource.Internal, Name = "nsfw" }, new() { ObjectId = (int) HBObjectId.IngestTag, - Guid = IngestTag, + Guid = InternalTag.IngestTag, Source = TagSource.Internal, Name = "ingest" } @@ -65,7 +56,7 @@ public class HBContext : DbContext { modelBuilder.Entity<User>().HasData(new User[] { new() { ObjectId = (int) HBObjectId.AdminUser, - Guid = AdminUser, + Guid = InternalTag.AdminUser, Username = "admin", PasswordHash = UserService.HashPassword("admin") } diff --git a/Pages/Component/AboutDialog.razor b/Pages/Component/AboutDialog.razor index 1229dc7..d1082bc 100644 --- a/Pages/Component/AboutDialog.razor +++ b/Pages/Component/AboutDialog.razor @@ -702,7 +702,7 @@ using var db = dbFactory.CreateDbContext(); progress = ( Untagged: db.Media - .Where(m => m.Tags.Any(t => t.TagDefinition.ObjectId == (int) HBObjectId.IngestTag)) + .Where(m => m.Tags.Any(t => t.TagDefinition.ObjectId == (int) ApiModels.HBObjectId.IngestTag)) .Count(), Total: db.Media.Count() ); diff --git a/Pages/Component/TagSelectDialog.razor b/Pages/Component/TagSelectDialog.razor index d33b178..26a35a2 100644 --- a/Pages/Component/TagSelectDialog.razor +++ b/Pages/Component/TagSelectDialog.razor @@ -91,7 +91,7 @@ int[] nsfwTags = Array.Empty<int>(); if(!userService.UserSessionState.ShowNsfw) - nsfwTags = tagService.TagsThatImply(HBContext.NsfwTag) + nsfwTags = tagService.TagsThatImply(ApiModels.InternalTag.NsfwTag) .Select(td => td.ObjectId) .ToArray(); diff --git a/Pages/TagDefinitions.razor b/Pages/TagDefinitions.razor index 5d02e03..c86fc81 100644 --- a/Pages/TagDefinitions.razor +++ b/Pages/TagDefinitions.razor @@ -53,7 +53,7 @@ <a href="javascript:;" @onclick=@(() => PromptImplicitTags(tagDef))> Implicit Tags </a> - @if(tagDef.ImplicitTags.Select(td => td.Guid).Contains(HBContext.NsfwTag)) { + @if(tagDef.ImplicitTags.Select(td => td.Guid).Contains(ApiModels.InternalTag.NsfwTag)) { <a href="javascript:;" @onclick=@(() => SetNsfw(tagDef, false))>Make SFW</a> } else { <a href="javascript:;" @onclick=@(() => SetNsfw(tagDef, true))>Make NSFW</a> @@ -102,7 +102,7 @@ private void LoadTags() { int[] nsfwTags = Array.Empty<int>(); if(!userService.UserSessionState.ShowNsfw) - nsfwTags = tagService.TagsThatImply(HBContext.NsfwTag) + nsfwTags = tagService.TagsThatImply(ApiModels.InternalTag.NsfwTag) .Select(td => td.ObjectId) .ToArray(); @@ -169,9 +169,9 @@ private void SetNsfw(TagDefinition tagDef, bool nsfw) { if(nsfw) - tagService.AddImplicitTag(tagDef.Guid, HBContext.NsfwTag); + tagService.AddImplicitTag(tagDef.Guid, ApiModels.InternalTag.NsfwTag); else - tagService.RemoveImplicitTag(tagDef.Guid, HBContext.NsfwTag); + tagService.RemoveImplicitTag(tagDef.Guid, ApiModels.InternalTag.NsfwTag); LoadTags(); StateHasChanged(); } diff --git a/Server.csproj b/Server.csproj index 8de0960..1099c7a 100644 --- a/Server.csproj +++ b/Server.csproj @@ -6,9 +6,9 @@ <ImplicitUsings>enable</ImplicitUsings> <AssemblyName>HyperBooru</AssemblyName> <RootNamespace>HyperBooru</RootNamespace> - <AssemblyVersion>0.19.0.0</AssemblyVersion> + <AssemblyVersion>0.20.0.0</AssemblyVersion> <FileVersion>$(AssemblyVersion)</FileVersion> - <Version>0.19-alpha</Version> + <Version>0.20-alpha</Version> <UserSecretsId>2907567f-4640-4581-8f4d-0977952d26bd</UserSecretsId> </PropertyGroup> diff --git a/Services/FeedService.cs b/Services/FeedService.cs index 3744e73..112b3c0 100644 --- a/Services/FeedService.cs +++ b/Services/FeedService.cs @@ -116,7 +116,7 @@ public class FeedService : IFeedService { if(!includeNsfw) media = media - .Where(m => !TagsThatImply(db, HBContext.NsfwTag) + .Where(m => !TagsThatImply(db, InternalTag.NsfwTag) .Intersect(m.Tags.Select(t => t.TagDefinitionId)) .Any()); diff --git a/Services/MediaService.cs b/Services/MediaService.cs index a0521db..9974802 100644 --- a/Services/MediaService.cs +++ b/Services/MediaService.cs @@ -4,7 +4,6 @@ using ImageMagick; using Microsoft.EntityFrameworkCore; using MimeDetective; using MimeDetective.Definitions; -using System.Diagnostics.CodeAnalysis; using System.Security.Cryptography; using System.Text.RegularExpressions; @@ -78,13 +77,13 @@ public class MediaService : IMediaService { .ThenInclude(t => t.TagDefinition) .First(m => m.Guid == media.Guid); var ingestTag = db.TagDefinitions - .First(td => td.Guid == HBContext.IngestTag); + .First(td => td.Guid == InternalTag.IngestTag); if(ingest) { - if(!media.Tags.Select(t => t.TagDefinition.Guid).Contains(HBContext.IngestTag)) + if(!media.Tags.Select(t => t.TagDefinition.Guid).Contains(InternalTag.IngestTag)) media.Tags.Add(new(ingestTag)); } else { - media.Tags.RemoveAll(t => t.TagDefinition.Guid == HBContext.IngestTag); + media.Tags.RemoveAll(t => t.TagDefinition.Guid == InternalTag.IngestTag); } db.SaveChanges(); @@ -190,7 +189,7 @@ public class MediaService : IMediaService { if(media is null) { var ingestTagDef = db.TagDefinitions - .First(td => td.Guid == HBContext.IngestTag); + .First(td => td.Guid == InternalTag.IngestTag); media = new() { UploadedFiles = new() { @@ -299,23 +298,37 @@ public class MediaService : IMediaService { public Stream GetThumbnail(Guid mediaId, int? width, int? height) { if(width is null && height is null) - throw new ThumbnailException( - "Both width and height cannot be null!", - mediaId); + throw new ApiModels.ArgumentException("Both width and height cannot be null!"); var thumbPath = GetThumbnailPath(mediaId, width, height); if(File.Exists(thumbPath)) - return System.IO.File.OpenRead(thumbPath); + return File.OpenRead(thumbPath); if(!File.Exists(GetPath(mediaId))) throw new ObjectNotFoundException([ mediaId ]); using var image = new MagickImage(GetPath(mediaId)); - if(width > image.Width || height > image.Height) { + if(width > image.Width) width = (int) image.Width; + if(height > image.Height) height = (int) image.Height; + + // Crop the image if a different aspect ratio is specified + if(width is not null && height is not null) { + double requestedRatio = (double) width / (double) height; + double currentRatio = (double) image.Width / (double) image.Height; + + double w = image.Width; + double h = image.Height; + + if(requestedRatio < currentRatio) + w = w / currentRatio * requestedRatio; + if(requestedRatio > currentRatio) + h = h / requestedRatio * currentRatio; + + image.Extent((uint) w, (uint) h, Gravity.Center); } image.Thumbnail((uint) (width ?? -1), (uint) (height ?? -1)); |
