From bfc36cbc48274c22921a30d2b4b8ebad1a4b5daa Mon Sep 17 00:00:00 2001 From: pancakes Date: Sun, 27 Oct 2024 19:29:21 +1000 Subject: [PATCH] [backend/api] Add follow list export endpoint --- .../Controllers/Web/SettingsController.cs | 18 ++++++++++++++ .../Core/Services/UserService.cs | 24 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/Iceshrimp.Backend/Controllers/Web/SettingsController.cs b/Iceshrimp.Backend/Controllers/Web/SettingsController.cs index b3e413e6..e6b29219 100644 --- a/Iceshrimp.Backend/Controllers/Web/SettingsController.cs +++ b/Iceshrimp.Backend/Controllers/Web/SettingsController.cs @@ -9,6 +9,7 @@ using Iceshrimp.Backend.Core.Services; using Iceshrimp.Shared.Schemas.Web; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; +using Microsoft.EntityFrameworkCore; namespace Iceshrimp.Backend.Controllers.Web; @@ -65,6 +66,23 @@ public class SettingsController(DatabaseContext db, UserService userSvc) : Contr await db.ReloadEntityAsync(settings); return settings; } + + [HttpPost("export/following")] + [ProducesResults(HttpStatusCode.Accepted)] + [ProducesErrors(HttpStatusCode.BadRequest)] + public async Task ExportFollowing() + { + var user = HttpContext.GetUserOrFail(); + + var followCount = await db.Followings + .CountAsync(p => p.FollowerId == user.Id); + if (followCount < 1) + throw GracefulException.BadRequest("You do not follow any users"); + + await userSvc.ExportFollowingAsync(user); + + return Accepted(); + } [HttpPost("import/following")] [ProducesResults(HttpStatusCode.Accepted)] diff --git a/Iceshrimp.Backend/Core/Services/UserService.cs b/Iceshrimp.Backend/Core/Services/UserService.cs index 21af6d7d..ff2e181c 100644 --- a/Iceshrimp.Backend/Core/Services/UserService.cs +++ b/Iceshrimp.Backend/Core/Services/UserService.cs @@ -1,6 +1,7 @@ using System.Diagnostics.CodeAnalysis; using System.Net; using System.Security.Cryptography; +using System.Text; using System.Text.RegularExpressions; using AsyncKeyedLock; using EntityFramework.Exceptions.Common; @@ -946,6 +947,29 @@ public class UserService( await db.UserListMembers.Where(p => p.UserList.User == user && p.User == followee).ExecuteDeleteAsync(); } + public async Task ExportFollowingAsync(User user) + { + var followees = await db.Followings + .Include(p => p.Followee) + .Where(p => p.FollowerId == user.Id) + .Select(p => p.Followee) + .Where(p => !p.IsDeleted && !p.IsSystemUser && p.MovedToUri == null) + .OrderBy(p => p.Host) + .ThenBy(p => p.UsernameLower) + .Select(p => p.GetFqn(instance.Value.AccountDomain)) + .ToListAsync(); + + var stream = new MemoryStream(Encoding.UTF8.GetBytes(string.Join("\n", followees))); + + await driveSvc.StoreFile(stream, user, + new DriveFileCreationRequest + { + Filename = $"following-{DateTime.UtcNow:yyyy-MM-dd-HH-mm-ss}.csv", + IsSensitive = false, + MimeType = "text/csv" + }, true); + } + public async Task ImportFollowingAsync(User user, List fqns) { foreach (var fqn in fqns.Select(fqn => fqn.Split("@")))