diff options
| author | Jake Mannens <jake@asger.xyz> | 2026-05-16 18:35:15 +1000 |
|---|---|---|
| committer | Jake Mannens <jake@asger.xyz> | 2026-05-16 18:35:15 +1000 |
| commit | df4bfad33e1b3fc2ce35af8000380029ecb444cf (patch) | |
| tree | 65ac6d8644528c7aaeee992671cf24fe13486098 /Controllers | |
| parent | c2b3c05f027d315f4e553ff656d1f06e99a82488 (diff) | |
Diffstat (limited to 'Controllers')
| -rw-r--r-- | Controllers/ApiTagController.cs | 217 |
1 files changed, 216 insertions, 1 deletions
diff --git a/Controllers/ApiTagController.cs b/Controllers/ApiTagController.cs index 26e3dc4..f48cc05 100644 --- a/Controllers/ApiTagController.cs +++ b/Controllers/ApiTagController.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Authorization; +using HyperBooru.ApiModels; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -35,4 +36,218 @@ public class ApiTagController : Controller { return tagDefinition is not null ? Ok(tagDefinition) : NotFound(); } + + [HttpPost("definition")] + public async Task<IActionResult> CreateTagDefinitionAsync([FromBody] TagCreateRequest request) { + using var db = dbFactory.CreateDbContext(); + using var transaction = await db.Database.BeginTransactionAsync(); + + if(db.TagDefinitions.Any(td => td.Name == request.Name)) + return BadRequest("Name already exists"); + + if(request.Alias is not null) + if(db.TagDefinitions.Any(td => td.Alias == request.Alias)) + return BadRequest("Alias already exists"); + + List<TagDefinition> implicitTags = new(); + if(request.ImplicitTags is not null) { + implicitTags = await db.TagDefinitions + .Where(td => request.ImplicitTags.Distinct().Contains(td.Guid)) + .ToListAsync(); + } + + var tagDefinition = new TagDefinition { + Source = TagSource.UserTag, + Namespace = request.Namespace, + Name = request.Name, + Alias = request.Alias, + ImplicitTags = implicitTags + }; + + db.TagDefinitions.Add(tagDefinition); + + await db.SaveChangesAsync(); + await transaction.CommitAsync(); + + return Ok((ApiModels.TagDefinition) tagDefinition); + } + + [HttpDelete("definition/{tagDefinitionId}")] + public async Task<IActionResult> DeleteTagDefinitionAsync([FromRoute] Guid tagDefinitionId) { + using var db = dbFactory.CreateDbContext(); + using var transaction = await db.Database.BeginTransactionAsync(); + + var tagDefinition = await db.TagDefinitions + .FirstOrDefaultAsync(td => td.Guid == tagDefinitionId); + + if(tagDefinition is null) + return NotFound("Tag definition not found"); + + if(tagDefinition.ObjectId < 0) + return BadRequest("Cannot delete built-in tag definition"); + + db.TagDefinitions.Remove(tagDefinition); + + await db.SaveChangesAsync(); + await transaction.CommitAsync(); + + return Ok(); + } + + [HttpPatch("definition/{tagDefinitionId}")] + public async Task<IActionResult> UpdateTagDefinitionAsync( + [FromRoute] Guid tagDefinitionId, + [FromBody] TagUpdateRequest request) { + + using var db = dbFactory.CreateDbContext(); + using var transaction = await db.Database.BeginTransactionAsync(); + + var tagDefinition = await db.TagDefinitions + .FirstOrDefaultAsync(td => td.Guid == tagDefinitionId); + + if(tagDefinition is null) + return NotFound("Tag definition not found"); + + if(tagDefinition.ObjectId < 0) + return BadRequest("Cannot update built-in tag definition"); + + if(request.Name is not null) + if(db.TagDefinitions.Any(td => td.Name == request.Name)) + return BadRequest("Name already exists"); + + if(request.Alias is not null) + if(db.TagDefinitions.Any(td => td.Alias == request.Alias)) + return BadRequest("Alias already exists"); + + tagDefinition.Namespace = request.Namespace ?? tagDefinition.Namespace; + tagDefinition.Name = request.Name ?? tagDefinition.Name; + tagDefinition.Alias = request.Alias ?? tagDefinition.Alias; + + await db.SaveChangesAsync(); + await transaction.CommitAsync(); + + return Ok((ApiModels.TagDefinition) tagDefinition); + } + + [HttpPatch("definition/{tagDefinitionId}/implicit")] + public async Task<IActionResult> AddImplicitTagsAsync( + [FromRoute] Guid tagDefinitionId, + [FromBody] Guid[] implicitTagIds) { + + using var db = dbFactory.CreateDbContext(); + using var transaction = await db.Database.BeginTransactionAsync(); + + var tagDefinition = await db.TagDefinitions + .Include(td => td.ImplicitTags) + .FirstOrDefaultAsync(td => td.Guid == tagDefinitionId); + + if(tagDefinition is null) + return NotFound("Tag definition not found"); + + if(tagDefinition.ObjectId < 0) + return BadRequest("Cannot update built-in tag definition"); + + implicitTagIds = implicitTagIds.Distinct().ToArray(); + + var implicitTags = db.TagDefinitions + .Where(td => implicitTagIds.Contains(td.Guid)) + .ToArray(); + + var missingTags = implicitTagIds.Except(implicitTags.Select(td => td.Guid)); + var missingTagsString = string.Join(", ", missingTags.Select(td => td.ToString())); + if(missingTags.Any()) + return BadRequest($"Invalid tag IDs specified: {missingTagsString}"); + + tagDefinition.ImplicitTags.AddRange( + implicitTags.ExceptBy(tagDefinition.ImplicitTags.Select(td => td.Guid), td => td.Guid)); + + await db.SaveChangesAsync(); + await transaction.CommitAsync(); + + return Ok(); + } + + [HttpPut("definition/{tagDefinitionId}/implicit")] + public async Task<IActionResult> ReplaceImplicitTagsAsync( + [FromRoute] Guid tagDefinitionId, + [FromBody] Guid[] implicitTagIds) { + + using var db = dbFactory.CreateDbContext(); + using var transaction = await db.Database.BeginTransactionAsync(); + + var tagDefinition = await db.TagDefinitions + .Include(td => td.ImplicitTags) + .FirstOrDefaultAsync(td => td.Guid == tagDefinitionId); + + if(tagDefinition is null) + return NotFound("Tag definition not found"); + + if(tagDefinition.ObjectId < 0) + return BadRequest("Cannot update built-in tag definition"); + + implicitTagIds = implicitTagIds.Distinct().ToArray(); + + var implicitTags = db.TagDefinitions + .Where(td => implicitTagIds.Contains(td.Guid)) + .ToArray(); + + var missingTags = implicitTagIds.Except(implicitTags.Select(td => td.Guid)); + var missingTagsString = string.Join(", ", missingTags.Select(td => td.ToString())); + if(missingTags.Any()) + return BadRequest($"Invalid tag IDs specified: {missingTagsString}"); + + tagDefinition.ImplicitTags.AddRange( + implicitTags.ExceptBy(tagDefinition.ImplicitTags.Select(td => td.Guid), td => td.Guid)); + + var toRemove = tagDefinition.ImplicitTags + .Where(td => !implicitTags.Select(td => td.Guid).Contains(td.Guid)) + .ToArray(); + + foreach(var td in toRemove) + tagDefinition.ImplicitTags.Remove(td); + + await db.SaveChangesAsync(); + await transaction.CommitAsync(); + + return Ok(); + } + + [HttpPost("definition/{tagDefinitionId}/implicit/delete")] + public async Task<IActionResult> DeleteImplicitTagAsync( + [FromRoute] Guid tagDefinitionId, + [FromBody] Guid[] implicitTagIds) { + + using var db = dbFactory.CreateDbContext(); + using var transaction = await db.Database.BeginTransactionAsync(); + + var tagDefinition = await db.TagDefinitions + .Include(td => td.ImplicitTags) + .FirstOrDefaultAsync(td => td.Guid == tagDefinitionId); + + if(tagDefinition is null) + return NotFound("Tag definition not found"); + + if(tagDefinition.ObjectId < 0) + return BadRequest("Cannot update built-in tag definition"); + + implicitTagIds = implicitTagIds.Distinct().ToArray(); + + var missingTagIds = implicitTagIds + .Except(tagDefinition.ImplicitTags.Select(td => td.Guid)); + var missingTagsString = string.Join(", ", missingTagIds.Select(td => td.ToString())); + if(missingTagIds.Any()) + return BadRequest($"Invalid tag IDs specified: {missingTagsString}"); + + var toRemove = tagDefinition.ImplicitTags + .Where(td => !implicitTagIds.Contains(td.Guid)) + .ToArray(); + + foreach(var td in toRemove) + tagDefinition.ImplicitTags.Remove(td); + + await db.SaveChangesAsync(); + await transaction.CommitAsync(); + + return Ok(); + } } |
