From 0a0fb9bfb453996a38b23c9528b29c82fecfc7e6 Mon Sep 17 00:00:00 2001 From: pancakes Date: Thu, 13 Mar 2025 11:46:03 +1000 Subject: [PATCH] [backend/api] Add note import endpoint --- .../Controllers/Web/SettingsController.cs | 14 ++++++ .../Core/Services/ImportExportService.cs | 50 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/Iceshrimp.Backend/Controllers/Web/SettingsController.cs b/Iceshrimp.Backend/Controllers/Web/SettingsController.cs index 7f61a4e8..32ccdb5e 100644 --- a/Iceshrimp.Backend/Controllers/Web/SettingsController.cs +++ b/Iceshrimp.Backend/Controllers/Web/SettingsController.cs @@ -210,6 +210,20 @@ public class SettingsController( return Accepted(); } + [HttpPost("import/notes")] + [EnableRateLimiting("imports")] + [ProducesResults(HttpStatusCode.OK)] + [ProducesErrors(HttpStatusCode.BadRequest)] + public async Task ImportNotes(IFormFile file) + { + var user = HttpContext.GetUserOrFail(); + + if (file.ContentType != "application/json") + throw GracefulException.BadRequest("File must be JSON"); + + await importExportSvc.ImportNotesAsync(user, file); + } + private async Task GetOrInitUserSettings() { var user = HttpContext.GetUserOrFail(); diff --git a/Iceshrimp.Backend/Core/Services/ImportExportService.cs b/Iceshrimp.Backend/Core/Services/ImportExportService.cs index c3303f2e..a7648482 100644 --- a/Iceshrimp.Backend/Core/Services/ImportExportService.cs +++ b/Iceshrimp.Backend/Core/Services/ImportExportService.cs @@ -1,7 +1,12 @@ +using System.Text.Json; +using Iceshrimp.Backend.Controllers.Web.Schemas; using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; +using Iceshrimp.Backend.Core.Middleware; +using Iceshrimp.MfmSharp; +using Iceshrimp.Shared.Configuration; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using static Iceshrimp.Backend.Core.Federation.ActivityPub.UserResolver; @@ -14,6 +19,8 @@ public class ImportExportService( IOptions instance, CacheService cacheSvc, UserService userSvc, + NoteService noteSvc, + DriveService driveSvc, ActivityPub.UserResolver userResolver ) : IScopedService { @@ -50,4 +57,47 @@ public class ImportExportService( await QueryableTimelineExtensions.ResetHeuristicAsync(user, cacheSvc); } + + public async Task ImportNotesAsync(User user, IFormFile file) + { + var notes = await JsonSerializer.DeserializeAsync>(file.OpenReadStream(), JsonSerialization.Options); + + if (notes == null) + throw GracefulException.BadRequest("File is not an Iceshrimp note export"); + + notes = notes.Where(p => p is + { + LocalOnly: false, + Poll: null, + RenoteId: null, + ReplyId: null, + Visibility: Note.NoteVisibility.Public or Note.NoteVisibility.Home, + VisibleUserIds: [] + }) + .OrderByDescending(p => p.Id) + .ToList(); + + foreach (var exportNote in notes) + { + var attachments = new List(); + foreach (var exportNoteFile in exportNote.Files) + { + var attachment = await driveSvc.StoreFileAsync(exportNoteFile.Url, user, exportNoteFile.IsSensitive, + exportNoteFile.Comment, exportNoteFile.Type); + if (attachment != null) attachments.Add(attachment); + } + + var note = new NoteService.NoteCreationData + { + User = user, + Visibility = exportNote.Visibility, + Text = exportNote.Text, + Cw = exportNote.Cw, + Attachments = attachments.Count != 0 ? attachments : null, + CreatedAt = exportNote.CreatedAt + }; + + await noteSvc.CreateNoteAsync(note); + } + } } \ No newline at end of file