[backend/federation] Handle quotes
This commit is contained in:
parent
a02af802f1
commit
27b3be774e
5 changed files with 40 additions and 13 deletions
|
@ -23,10 +23,15 @@ public class NoteRenderer(
|
|||
)
|
||||
{
|
||||
var uri = note.Uri ?? note.GetPublicUri(config.Value);
|
||||
var renote = note.Renote != null && recurse > 0
|
||||
var renote = note is { Renote: not null, IsQuote: false } && recurse > 0
|
||||
? await RenderAsync(note.Renote, user, accounts, mentions, attachments, likeCounts, likedNotes, 0)
|
||||
: null;
|
||||
var quote = note is { Renote: not null, IsQuote: true } && recurse > 0
|
||||
? await RenderAsync(note.Renote, user, accounts, mentions, attachments, likeCounts, likedNotes, --recurse)
|
||||
: null;
|
||||
var text = note.Text; //TODO: append quote uri
|
||||
var text = note.Text;
|
||||
if (quote != null && text != null && !text.EndsWith(quote.Url) && !text.EndsWith(quote.Uri))
|
||||
text += $"\n\nRE: {quote.Url}"; //TODO: render as inline quote
|
||||
|
||||
var likeCount = likeCounts?.GetValueOrDefault(note.Id, 0) ?? await db.NoteLikes.CountAsync(p => p.Note == note);
|
||||
var liked = likedNotes?.Contains(note.Id) ?? await db.NoteLikes.AnyAsync(p => p.Note == note && p.User == user);
|
||||
|
@ -87,8 +92,8 @@ public class NoteRenderer(
|
|||
Account = account,
|
||||
ReplyId = note.ReplyId,
|
||||
ReplyUserId = note.ReplyUserId,
|
||||
Renote = renote, //TODO: check if it's a pure renote
|
||||
Quote = renote, //TODO: see above
|
||||
Renote = renote,
|
||||
Quote = quote,
|
||||
ContentType = "text/x.misskeymarkdown",
|
||||
CreatedAt = note.CreatedAt.ToStringMastodon(),
|
||||
EditedAt = note.UpdatedAt?.ToStringMastodon(),
|
||||
|
|
|
@ -236,9 +236,7 @@ public class ActivityHandlerService(
|
|||
throw GracefulException.UnprocessableEntity("Invalid or unsupported announce object");
|
||||
|
||||
var dbNote = await noteSvc.ResolveNoteAsync(note.Id, note.VerifiedFetch ? note : null);
|
||||
var renote = await noteSvc.CreateNoteAsync(resolvedActor, announce.GetVisibility(activity.Actor),
|
||||
renote: dbNote);
|
||||
await notificationSvc.GenerateRenoteNotification(renote);
|
||||
await noteSvc.CreateNoteAsync(resolvedActor, announce.GetVisibility(activity.Actor), renote: dbNote);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
|
@ -421,4 +419,4 @@ public class ActivityHandlerService(
|
|||
p.Notifier == actor)
|
||||
.ExecuteDeleteAsync();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,18 @@ public class ASNote : ASObject
|
|||
[JC(typeof(VC))]
|
||||
public string? MkContent { get; set; }
|
||||
|
||||
[J("https://misskey-hub.net/ns#_misskey_quote")]
|
||||
[JC(typeof(VC))]
|
||||
public string? MkQuote { get; set; }
|
||||
|
||||
[J($"{Constants.ActivityStreamsNs}#quoteUrl")]
|
||||
[JC(typeof(VC))]
|
||||
public string? QuoteUrl { get; set; }
|
||||
|
||||
[J("http://fedibird.com/ns#quoteUri")]
|
||||
[JC(typeof(VC))]
|
||||
public string? QuoteUri { get; set; }
|
||||
|
||||
[J($"{Constants.ActivityStreamsNs}#content")]
|
||||
[JC(typeof(VC))]
|
||||
public string? Content { get; set; }
|
||||
|
|
|
@ -99,6 +99,8 @@ public class NoteService(
|
|||
await db.SaveChangesAsync();
|
||||
eventSvc.RaiseNotePublished(this, note);
|
||||
await notificationSvc.GenerateMentionNotifications(note, mentionedLocalUserIds);
|
||||
await notificationSvc.GenerateReplyNotifications(note, mentionedLocalUserIds);
|
||||
await notificationSvc.GenerateRenoteNotification(note);
|
||||
|
||||
if (user.Host != null) return note;
|
||||
|
||||
|
@ -300,7 +302,7 @@ public class NoteService(
|
|||
if (actor.IsSuspended)
|
||||
throw GracefulException.Forbidden("User is suspended");
|
||||
|
||||
//TODO: resolve anything related to the note as well (attachments, emoji, etc)
|
||||
//TODO: resolve emoji
|
||||
|
||||
var (mentionedUserIds, mentionedLocalUserIds, mentions, remoteMentions, splitDomainMapping) =
|
||||
await ResolveNoteMentionsAsync(note);
|
||||
|
@ -308,6 +310,8 @@ public class NoteService(
|
|||
var createdAt = note.PublishedAt?.ToUniversalTime() ??
|
||||
throw GracefulException.UnprocessableEntity("Missing or invalid PublishedAt field");
|
||||
|
||||
var quoteUrl = note.MkQuote ?? note.QuoteUri ?? note.QuoteUrl;
|
||||
|
||||
var dbNote = new Note
|
||||
{
|
||||
Id = IdHelpers.GenerateSlowflakeId(createdAt),
|
||||
|
@ -319,7 +323,8 @@ public class NoteService(
|
|||
CreatedAt = createdAt,
|
||||
UserHost = actor.Host,
|
||||
Visibility = note.GetVisibility(actor),
|
||||
Reply = note.InReplyTo?.Id != null ? await ResolveNoteAsync(note.InReplyTo.Id) : null
|
||||
Reply = note.InReplyTo?.Id != null ? await ResolveNoteAsync(note.InReplyTo.Id) : null,
|
||||
Renote = quoteUrl != null ? await ResolveNoteAsync(quoteUrl) : null
|
||||
};
|
||||
|
||||
if (dbNote.Reply != null)
|
||||
|
@ -327,6 +332,12 @@ public class NoteService(
|
|||
dbNote.ReplyUserId = dbNote.Reply.UserId;
|
||||
dbNote.ReplyUserHost = dbNote.Reply.UserHost;
|
||||
}
|
||||
|
||||
if (dbNote.Renote != null)
|
||||
{
|
||||
dbNote.RenoteUserId = dbNote.Renote.UserId;
|
||||
dbNote.RenoteUserHost = dbNote.Renote.UserHost;
|
||||
}
|
||||
|
||||
if (dbNote.Text is { Length: > 100000 })
|
||||
throw GracefulException.UnprocessableEntity("Content cannot be longer than 100.000 characters");
|
||||
|
@ -369,6 +380,7 @@ public class NoteService(
|
|||
eventSvc.RaiseNotePublished(this, dbNote);
|
||||
await notificationSvc.GenerateMentionNotifications(dbNote, mentionedLocalUserIds);
|
||||
await notificationSvc.GenerateReplyNotifications(dbNote, mentionedLocalUserIds);
|
||||
await notificationSvc.GenerateRenoteNotification(dbNote);
|
||||
logger.LogDebug("Note {id} created successfully", dbNote.Id);
|
||||
return dbNote;
|
||||
}
|
||||
|
@ -655,4 +667,4 @@ public class NoteService(
|
|||
var dbNote = await ResolveNoteAsync(note) ?? throw new Exception("Cannot unregister like for unknown note");
|
||||
await UnlikeNoteAsync(dbNote, actor);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -185,7 +185,7 @@ public class NotificationService(
|
|||
{
|
||||
if (note.Renote is not { UserHost: null }) return;
|
||||
if (!note.VisibilityIsPublicOrHome &&
|
||||
await db.Notes.AnyAsync(p => p.Id == note.Id && p.IsVisibleFor(note.Renote.User)))
|
||||
!await db.Notes.AnyAsync(p => p.Id == note.Id && p.IsVisibleFor(note.Renote.User)))
|
||||
return;
|
||||
|
||||
var notification = new Notification
|
||||
|
@ -195,7 +195,7 @@ public class NotificationService(
|
|||
Note = note,
|
||||
Notifiee = note.Renote.User,
|
||||
Notifier = note.User,
|
||||
Type = Notification.NotificationType.Renote
|
||||
Type = note.IsQuote ? Notification.NotificationType.Quote : Notification.NotificationType.Renote
|
||||
};
|
||||
|
||||
await db.AddAsync(notification);
|
||||
|
|
Loading…
Add table
Reference in a new issue