From ab3f3783e897dfa68540c06162972bb53b0852f3 Mon Sep 17 00:00:00 2001 From: Kopper Date: Sat, 29 Jun 2024 05:08:29 +0300 Subject: [PATCH] [backend/api] Create endpoint to clone remote emoji --- .../Controllers/EmojiController.cs | 16 +++++++++++++ .../Core/Services/DriveService.cs | 7 ++++-- .../Core/Services/EmojiService.cs | 23 +++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/Iceshrimp.Backend/Controllers/EmojiController.cs b/Iceshrimp.Backend/Controllers/EmojiController.cs index 26719e36..b818c19b 100644 --- a/Iceshrimp.Backend/Controllers/EmojiController.cs +++ b/Iceshrimp.Backend/Controllers/EmojiController.cs @@ -88,6 +88,22 @@ public class EmojiController( return Ok(res); } + [HttpPost("clone/{name}@{host}")] + [Authorize("role:admin")] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(EmojiResponse))] + [ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponse))] + [ProducesResponseType(StatusCodes.Status409Conflict, Type = typeof(ErrorResponse))] + public async Task CloneEmoji(string name, string host) + { + var localEmojo = await db.Emojis.FirstOrDefaultAsync(e => e.Name == name && e.Host == null); + if (localEmojo != null) return Conflict(); + + var emojo = await db.Emojis.FirstOrDefaultAsync(e => e.Name == name && e.Host == host); + if (emojo == null) return NotFound(); + + return Ok(await emojiSvc.CloneEmoji(emojo)); + } + [HttpPatch("{id}")] [Authorize("role:admin")] [Consumes(MediaTypeNames.Application.Json)] diff --git a/Iceshrimp.Backend/Core/Services/DriveService.cs b/Iceshrimp.Backend/Core/Services/DriveService.cs index 616e3bdb..0c2346d4 100644 --- a/Iceshrimp.Backend/Core/Services/DriveService.cs +++ b/Iceshrimp.Backend/Core/Services/DriveService.cs @@ -25,7 +25,7 @@ public class DriveService( { public async Task StoreFile( string? uri, User user, bool sensitive, string? description = null, string? mimeType = null, - bool logExisting = true + bool logExisting = true, bool forceStore = false ) { if (uri == null) return null; @@ -36,7 +36,10 @@ public class DriveService( try { // Do we already have the file? - var file = await db.DriveFiles.FirstOrDefaultAsync(p => p.Uri == uri); + DriveFile? file = null; + if (!forceStore) + file = await db.DriveFiles.FirstOrDefaultAsync(p => p.Uri == uri); + if (file != null) { // If the user matches, return the existing file diff --git a/Iceshrimp.Backend/Core/Services/EmojiService.cs b/Iceshrimp.Backend/Core/Services/EmojiService.cs index 90a9db85..08db99f0 100644 --- a/Iceshrimp.Backend/Core/Services/EmojiService.cs +++ b/Iceshrimp.Backend/Core/Services/EmojiService.cs @@ -61,6 +61,29 @@ public partial class EmojiService(DatabaseContext db, DriveService driveSvc, Sys return emoji; } + public async Task CloneEmoji(Emoji existing) + { + var user = await sysUserSvc.GetInstanceActorAsync(); + var driveFile = await driveSvc.StoreFile(existing.OriginalUrl, user, sensitive: false, forceStore: true) ?? + throw new Exception("Error storing emoji file"); + + var emoji = new Emoji + { + Id = IdHelpers.GenerateSlowflakeId(), + Name = existing.Name, + UpdatedAt = DateTime.UtcNow, + OriginalUrl = driveFile.Url, + PublicUrl = driveFile.PublicUrl, + Width = driveFile.Properties.Width, + Height = driveFile.Properties.Height + }; + + await db.AddAsync(emoji); + await db.SaveChangesAsync(); + + return emoji; + } + public async Task DeleteEmoji(string id) { var emoji = await db.Emojis.FirstOrDefaultAsync(p => p.Host == null && p.Id == id);