[backend/federation] Support Misskey-style emoji reactions (ISH-148)

This commit is contained in:
Laura Hausmann 2024-03-11 02:49:03 +01:00
parent 12bec02cfd
commit 58a514394c
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
4 changed files with 28 additions and 8 deletions

View file

@ -8,6 +8,7 @@ public static class Constants
public const string XsdNs = "http://www.w3.org/2001/XMLSchema"; public const string XsdNs = "http://www.w3.org/2001/XMLSchema";
public const string SchemaNs = "http://schema.org"; public const string SchemaNs = "http://schema.org";
public const string MastodonNs = "http://joinmastodon.org/ns"; public const string MastodonNs = "http://joinmastodon.org/ns";
public const string MisskeyNs = "https://misskey-hub.net/ns";
public static readonly string[] SystemUsers = ["instance.actor", "relay.actor"]; public static readonly string[] SystemUsers = ["instance.actor", "relay.actor"];
public static readonly string[] BrowserSafeMimeTypes = public static readonly string[] BrowserSafeMimeTypes =

View file

@ -144,11 +144,13 @@ public class ActivityHandlerService(
case ASFollow { Object: ASActor followee }: case ASFollow { Object: ASActor followee }:
await UnfollowAsync(followee, resolvedActor); await UnfollowAsync(followee, resolvedActor);
return; return;
case ASLike { Object: ASNote likedNote }: case ASLike { Object: ASNote note } like:
await noteSvc.UnlikeNoteAsync(likedNote, resolvedActor); var dbNote = await noteSvc.UnlikeNoteAsync(note, resolvedActor);
if (like.MisskeyReaction != null)
await noteSvc.RemoveReactionFromNoteAsync(dbNote, resolvedActor, like.MisskeyReaction);
return; return;
case ASAnnounce { Object: ASNote likedNote }: case ASAnnounce { Object: ASNote note }:
await noteSvc.UndoAnnounceAsync(likedNote, resolvedActor); await noteSvc.UndoAnnounceAsync(note, resolvedActor);
return; return;
case ASEmojiReact { Object: ASNote note } react: case ASEmojiReact { Object: ASNote note } react:
await noteSvc.RemoveReactionFromNoteAsync(note, resolvedActor, react.Content); await noteSvc.RemoveReactionFromNoteAsync(note, resolvedActor, react.Content);
@ -157,11 +159,18 @@ public class ActivityHandlerService(
throw GracefulException.UnprocessableEntity("Undo activity object is invalid"); throw GracefulException.UnprocessableEntity("Undo activity object is invalid");
} }
} }
case ASLike: case ASLike like:
{ {
if (activity.Object is not ASNote note) if (activity.Object is not ASNote note)
throw GracefulException.UnprocessableEntity("Like activity object is invalid"); throw GracefulException.UnprocessableEntity("Like activity object is invalid");
await noteSvc.LikeNoteAsync(note, resolvedActor); var dbNote = await noteSvc.LikeNoteAsync(note, resolvedActor);
if (like.MisskeyReaction != null)
{
await emojiSvc.ProcessEmojiAsync(like.Tags?.OfType<ASEmoji>().ToList(), resolvedActor.Host);
await noteSvc.ReactToNoteAsync(dbNote, resolvedActor, like.MisskeyReaction);
}
return; return;
} }
case ASUpdate: case ASUpdate:

View file

@ -119,6 +119,14 @@ public class ASUndo : ASActivity
public class ASLike : ASActivity public class ASLike : ASActivity
{ {
public ASLike() => Type = Types.Like; public ASLike() => Type = Types.Like;
[J($"{Constants.MisskeyNs}#_misskey_reaction")]
[JC(typeof(VC))]
public string? MisskeyReaction { get; set; }
[J($"{Constants.ActivityStreamsNs}#tag")]
[JC(typeof(ASTagConverter))]
public List<ASTag>? Tags { get; set; }
} }
public class ASUpdate : ASActivity public class ASUpdate : ASActivity

View file

@ -1041,16 +1041,18 @@ public class NoteService(
return true; return true;
} }
public async Task LikeNoteAsync(ASNote note, User actor) public async Task<Note> LikeNoteAsync(ASNote note, User actor)
{ {
var dbNote = await ResolveNoteAsync(note) ?? throw new Exception("Cannot register like for unknown note"); var dbNote = await ResolveNoteAsync(note) ?? throw new Exception("Cannot register like for unknown note");
await LikeNoteAsync(dbNote, actor); await LikeNoteAsync(dbNote, actor);
return dbNote;
} }
public async Task UnlikeNoteAsync(ASNote note, User user) public async Task<Note> UnlikeNoteAsync(ASNote note, User user)
{ {
var dbNote = await ResolveNoteAsync(note) ?? throw new Exception("Cannot unregister like for unknown note"); var dbNote = await ResolveNoteAsync(note) ?? throw new Exception("Cannot unregister like for unknown note");
await UnlikeNoteAsync(dbNote, user); await UnlikeNoteAsync(dbNote, user);
return dbNote;
} }
public async Task BookmarkNoteAsync(Note note, User user) public async Task BookmarkNoteAsync(Note note, User user)