[backend/masto-client] Add bookmark endpoints, render note bookmark status (ISH-121)
This commit is contained in:
parent
d343c7f469
commit
c2f8f7ff31
3 changed files with 73 additions and 8 deletions
|
@ -35,6 +35,8 @@ public class NoteRenderer(
|
|||
|
||||
var liked = data?.LikedNotes?.Contains(note.Id) ??
|
||||
await db.NoteLikes.AnyAsync(p => p.Note == note && p.User == user);
|
||||
var bookmarked = data?.BookmarkedNotes?.Contains(note.Id) ??
|
||||
await db.NoteBookmarks.AnyAsync(p => p.Note == note && p.User == user);
|
||||
var renoted = data?.Renotes?.Contains(note.Id) ??
|
||||
await db.Notes.AnyAsync(p => p.Renote == note && p.User == user && p.IsPureRenote);
|
||||
|
||||
|
@ -83,8 +85,8 @@ public class NoteRenderer(
|
|||
FavoriteCount = note.LikeCount,
|
||||
IsFavorited = liked,
|
||||
IsRenoted = renoted,
|
||||
IsBookmarked = false, //FIXME
|
||||
IsMuted = null, //FIXME
|
||||
IsBookmarked = bookmarked,
|
||||
IsMuted = null, //FIXME
|
||||
IsSensitive = note.Cw != null,
|
||||
ContentWarning = note.Cw ?? "",
|
||||
Visibility = StatusEntity.EncodeVisibility(note.Visibility),
|
||||
|
@ -139,6 +141,14 @@ public class NoteRenderer(
|
|||
.ToListAsync();
|
||||
}
|
||||
|
||||
private async Task<List<string>> GetBookmarkedNotes(IEnumerable<Note> notes, User? user)
|
||||
{
|
||||
if (user == null) return [];
|
||||
return await db.NoteBookmarks.Where(p => p.User == user && notes.Contains(p.Note))
|
||||
.Select(p => p.NoteId)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
private async Task<List<string>> GetRenotes(IEnumerable<Note> notes, User? user)
|
||||
{
|
||||
if (user == null) return [];
|
||||
|
@ -180,12 +190,13 @@ public class NoteRenderer(
|
|||
|
||||
var data = new NoteRendererDto
|
||||
{
|
||||
Accounts = accounts ?? await GetAccounts(noteList.Select(p => p.User)),
|
||||
Mentions = await GetMentions(noteList),
|
||||
Attachments = await GetAttachments(noteList),
|
||||
LikedNotes = await GetLikedNotes(noteList, user),
|
||||
Renotes = await GetRenotes(noteList, user),
|
||||
Emoji = await GetEmoji(noteList)
|
||||
Accounts = accounts ?? await GetAccounts(noteList.Select(p => p.User)),
|
||||
Mentions = await GetMentions(noteList),
|
||||
Attachments = await GetAttachments(noteList),
|
||||
LikedNotes = await GetLikedNotes(noteList, user),
|
||||
BookmarkedNotes = await GetBookmarkedNotes(noteList, user),
|
||||
Renotes = await GetRenotes(noteList, user),
|
||||
Emoji = await GetEmoji(noteList)
|
||||
};
|
||||
|
||||
return await noteList.Select(p => RenderAsync(p, user, data)).AwaitAllAsync();
|
||||
|
@ -197,6 +208,7 @@ public class NoteRenderer(
|
|||
public List<MentionEntity>? Mentions;
|
||||
public List<AttachmentEntity>? Attachments;
|
||||
public List<string>? LikedNotes;
|
||||
public List<string>? BookmarkedNotes;
|
||||
public List<string>? Renotes;
|
||||
public List<EmojiEntity>? Emoji;
|
||||
public bool Source;
|
||||
|
|
|
@ -118,6 +118,40 @@ public class StatusController(
|
|||
return await GetNote(id);
|
||||
}
|
||||
|
||||
[HttpPost("{id}/bookmark")]
|
||||
[Authorize("write:bookmarks")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(StatusEntity))]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(MastodonErrorResponse))]
|
||||
public async Task<IActionResult> BookmarkNote(string id)
|
||||
{
|
||||
var user = HttpContext.GetUserOrFail();
|
||||
var note = await db.Notes.Where(p => p.Id == id)
|
||||
.IncludeCommonProperties()
|
||||
.EnsureVisibleFor(user)
|
||||
.FirstOrDefaultAsync() ??
|
||||
throw GracefulException.RecordNotFound();
|
||||
|
||||
await noteSvc.BookmarkNoteAsync(note, user);
|
||||
return await GetNote(id);
|
||||
}
|
||||
|
||||
[HttpPost("{id}/unbookmark")]
|
||||
[Authorize("write:bookmarks")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(StatusEntity))]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(MastodonErrorResponse))]
|
||||
public async Task<IActionResult> UnbookmarkNote(string id)
|
||||
{
|
||||
var user = HttpContext.GetUserOrFail();
|
||||
var note = await db.Notes.Where(p => p.Id == id)
|
||||
.IncludeCommonProperties()
|
||||
.EnsureVisibleFor(user)
|
||||
.FirstOrDefaultAsync() ??
|
||||
throw GracefulException.RecordNotFound();
|
||||
|
||||
await noteSvc.BookmarkNoteAsync(note, user);
|
||||
return await GetNote(id);
|
||||
}
|
||||
|
||||
[HttpPost("{id}/reblog")]
|
||||
[Authorize("write:favourites")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(StatusEntity))]
|
||||
|
|
|
@ -776,6 +776,25 @@ public class NoteService(
|
|||
await UnlikeNoteAsync(dbNote, actor);
|
||||
}
|
||||
|
||||
public async Task BookmarkNoteAsync(Note note, User user)
|
||||
{
|
||||
if (!await db.NoteBookmarks.AnyAsync(p => p.Note == note && p.User == user))
|
||||
{
|
||||
var bookmark = new NoteBookmark
|
||||
{
|
||||
Id = IdHelpers.GenerateSlowflakeId(), CreatedAt = DateTime.UtcNow, User = user, Note = note
|
||||
};
|
||||
|
||||
await db.NoteBookmarks.AddAsync(bookmark);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UnbookmarkNoteAsync(Note note, User actor)
|
||||
{
|
||||
await db.NoteBookmarks.Where(p => p.Note == note && p.User == actor).ExecuteDeleteAsync();
|
||||
}
|
||||
|
||||
public async Task UpdatePinnedNotesAsync(ASActor actor, User user)
|
||||
{
|
||||
logger.LogDebug("Updating pinned notes for user {user}", user.Id);
|
||||
|
|
Loading…
Add table
Reference in a new issue