From 25c328b02f1b1a3f91b83bd516fcdc9cb8cb3fe0 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Wed, 24 Jan 2024 02:21:48 +0100 Subject: [PATCH] Implement basic AP note serializer --- .../Controllers/ActivityPubController.cs | 13 ++++--- .../Renderers/ActivityPub/NoteRenderer.cs | 35 ++++++++++++------- .../{APUserRenderer.cs => UserRenderer.cs} | 2 +- .../Core/Helpers/ServiceExtensions.cs | 3 +- Iceshrimp.NET.sln.DotSettings | 1 + 5 files changed, 35 insertions(+), 19 deletions(-) rename Iceshrimp.Backend/Controllers/Renderers/ActivityPub/{APUserRenderer.cs => UserRenderer.cs} (95%) diff --git a/Iceshrimp.Backend/Controllers/ActivityPubController.cs b/Iceshrimp.Backend/Controllers/ActivityPubController.cs index f0ce2eba..5aa2a33a 100644 --- a/Iceshrimp.Backend/Controllers/ActivityPubController.cs +++ b/Iceshrimp.Backend/Controllers/ActivityPubController.cs @@ -13,18 +13,21 @@ namespace Iceshrimp.Backend.Controllers; [UseNewtonsoftJson] [MediaTypeRouteFilter("application/activity+json", "application/ld+json")] [Produces("application/activity+json", "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"")] -public class ActivityPubController(DatabaseContext db, APUserRenderer userRenderer) : Controller { - /* +public class ActivityPubController( + DatabaseContext db, + UserRenderer userRenderer, + NoteRenderer noteRenderer) : Controller { [HttpGet("/notes/{id}")] - [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Note))] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ASNote))] [ProducesResponseType(StatusCodes.Status401Unauthorized, Type = typeof(ErrorResponse))] [ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponse))] public async Task GetNote(string id) { var note = await db.Notes.FirstOrDefaultAsync(p => p.Id == id); if (note == null) return NotFound(); - return Ok(note); + var rendered = noteRenderer.Render(note); + var compacted = LdHelpers.Compact(rendered); + return Ok(compacted); } - */ [HttpGet("/users/{id}")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ASActor))] diff --git a/Iceshrimp.Backend/Controllers/Renderers/ActivityPub/NoteRenderer.cs b/Iceshrimp.Backend/Controllers/Renderers/ActivityPub/NoteRenderer.cs index 8c234cca..50a14ff8 100644 --- a/Iceshrimp.Backend/Controllers/Renderers/ActivityPub/NoteRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Renderers/ActivityPub/NoteRenderer.cs @@ -1,19 +1,30 @@ -using Iceshrimp.Backend.Controllers.Renderers.Entity; -using Iceshrimp.Backend.Controllers.Schemas; +using Iceshrimp.Backend.Core.Configuration; +using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; +using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; +using Microsoft.Extensions.Options; namespace Iceshrimp.Backend.Controllers.Renderers.ActivityPub; -public static class ActivityPubNoteRenderer { - public static NoteResponse RenderOne(Note note) { - return new NoteResponse { - Id = note.Id, - Text = note.Text, - User = UserRenderer.RenderOne(note.User) +public class NoteRenderer(IOptions config, DatabaseContext db, UserRenderer userRenderer) { + public ASNote Render(Note note) { + var id = $"https://{config.Value.WebDomain}/notes/{note.Id}"; + var userId = $"https://{config.Value.WebDomain}/users/{note.User.Id}"; + + return new ASNote { + Id = id, + Content = note.Text, //FIXME: render to html + AttributedTo = [new LDIdObject(userId)], + Type = "as:Note", + MkContent = note.Text, + PublishedAt = note.CreatedAt, + Sensitive = note.Cw != null, + Source = new ASNoteSource { + Content = note.Text, + MediaType = "text/x.misskeymarkdown" + }, + Cc = [new ASLink("https://www.w3.org/ns/activitystreams#Public")], + To = [] }; } - - public static IEnumerable RenderMany(IEnumerable notes) { - return notes.Select(RenderOne); - } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/Renderers/ActivityPub/APUserRenderer.cs b/Iceshrimp.Backend/Controllers/Renderers/ActivityPub/UserRenderer.cs similarity index 95% rename from Iceshrimp.Backend/Controllers/Renderers/ActivityPub/APUserRenderer.cs rename to Iceshrimp.Backend/Controllers/Renderers/ActivityPub/UserRenderer.cs index 3b97adad..82c570c1 100644 --- a/Iceshrimp.Backend/Controllers/Renderers/ActivityPub/APUserRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Renderers/ActivityPub/UserRenderer.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.Options; namespace Iceshrimp.Backend.Controllers.Renderers.ActivityPub; -public class APUserRenderer(IOptions config, DatabaseContext db) { +public class UserRenderer(IOptions config, DatabaseContext db) { public async Task Render(User user) { if (user.Host != null) throw new Exception("Refusing to render remote user"); diff --git a/Iceshrimp.Backend/Core/Helpers/ServiceExtensions.cs b/Iceshrimp.Backend/Core/Helpers/ServiceExtensions.cs index cb947e4d..075b0b13 100644 --- a/Iceshrimp.Backend/Core/Helpers/ServiceExtensions.cs +++ b/Iceshrimp.Backend/Core/Helpers/ServiceExtensions.cs @@ -15,7 +15,8 @@ public static class ServiceExtensions { services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); + services.AddScoped(); + services.AddScoped(); services.AddScoped(); // Singleton = instantiated once across application lifetime diff --git a/Iceshrimp.NET.sln.DotSettings b/Iceshrimp.NET.sln.DotSettings index bc346e3f..f7d27287 100644 --- a/Iceshrimp.NET.sln.DotSettings +++ b/Iceshrimp.NET.sln.DotSettings @@ -36,5 +36,6 @@ True True True + True True True \ No newline at end of file