[backend/masto-client] Add edit history endpoint (ISH-274)

This commit is contained in:
Laura Hausmann 2024-04-25 02:01:43 +02:00
parent 10a1a13918
commit 5f86ffeffe
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
5 changed files with 109 additions and 4 deletions

View file

@ -77,8 +77,9 @@ public class MediaController(DriveService driveSvc, DatabaseContext db) : Contro
Blurhash = file.Blurhash, Blurhash = file.Blurhash,
Description = file.Comment, Description = file.Comment,
PreviewUrl = file.ThumbnailUrl, PreviewUrl = file.ThumbnailUrl,
RemoteUrl = file.Uri RemoteUrl = file.Uri,
//Metadata = TODO Sensitive = file.IsSensitive,
//Metadata = TODO,
}; };
} }
} }

View file

@ -129,6 +129,57 @@ public class NoteRenderer(
return res; return res;
} }
public async Task<List<StatusEdit>> RenderHistoryAsync(Note note)
{
var edits = await db.NoteEdits.Where(p => p.Note == note).OrderBy(p => p.Id).ToListAsync();
edits.Add(RenderEdit(note));
var attachments = await GetAttachments(note.FileIds.Concat(edits.SelectMany(p => p.FileIds)));
var mentions = await GetMentions([note]);
var mentionedUsers = mentions.Select(p => new Note.MentionedUser
{
Host = p.Host ?? config.Value.AccountDomain,
Uri = p.Uri,
Username = p.Username,
Url = p.Url
})
.ToList();
var account = await userRenderer.RenderAsync(note.User);
var lastDate = note.CreatedAt;
List<StatusEdit> history = [];
foreach (var edit in edits)
{
var files = attachments.Where(p => edit.FileIds.Contains(p.Id)).ToList();
var entry = new StatusEdit
{
Account = account,
Content = await mfmConverter.ToHtmlAsync(edit.Text ?? "", mentionedUsers, note.UserHost),
CreatedAt = lastDate.ToStringIso8601Like(),
Emojis = [],
IsSensitive = files.Any(p => p.Sensitive),
Attachments = files,
Poll = null,
ContentWarning = edit.Cw ?? ""
};
history.Add(entry);
}
return history;
}
private NoteEdit RenderEdit(Note note)
{
return new NoteEdit
{
Text = note.Text,
Cw = note.Cw,
FileIds = note.FileIds,
UpdatedAt = note.UpdatedAt ?? note.CreatedAt
};
}
private static List<FilterResultEntity> GetFilterResult((Filter filter, string keyword)? filtered) private static List<FilterResultEntity> GetFilterResult((Filter filter, string keyword)? filtered)
{ {
if (filtered == null) return []; if (filtered == null) return [];
@ -161,7 +212,28 @@ public class NoteRenderer(
Description = f.Comment, Description = f.Comment,
Metadata = null, Metadata = null,
RemoteUrl = f.Uri, RemoteUrl = f.Uri,
Type = AttachmentEntity.GetType(f.Type) Type = AttachmentEntity.GetType(f.Type),
Sensitive = f.IsSensitive
})
.ToListAsync();
}
private async Task<List<AttachmentEntity>> GetAttachments(IEnumerable<string> fileIds)
{
var ids = fileIds.Distinct().ToList();
if (ids.Count == 0) return [];
return await db.DriveFiles.Where(p => ids.Contains(p.Id))
.Select(f => new AttachmentEntity
{
Id = f.Id,
Url = f.PublicUrl,
Blurhash = f.Blurhash,
PreviewUrl = f.PublicThumbnailUrl,
Description = f.Comment,
Metadata = null,
RemoteUrl = f.Uri,
Type = AttachmentEntity.GetType(f.Type),
Sensitive = f.IsSensitive
}) })
.ToListAsync(); .ToListAsync();
} }

View file

@ -1,10 +1,12 @@
using J = System.Text.Json.Serialization.JsonPropertyNameAttribute; using J = System.Text.Json.Serialization.JsonPropertyNameAttribute;
using JI = System.Text.Json.Serialization.JsonIgnoreAttribute;
namespace Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities; namespace Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities;
public class AttachmentEntity public class AttachmentEntity
{ {
public required AttachmentType Type; [JI] public required bool Sensitive;
[JI] public required AttachmentType Type;
[J("id")] public required string Id { get; set; } [J("id")] public required string Id { get; set; }
[J("url")] public required string Url { get; set; } [J("url")] public required string Url { get; set; }
[J("remote_url")] public string? RemoteUrl { get; set; } [J("remote_url")] public string? RemoteUrl { get; set; }

View file

@ -96,3 +96,15 @@ public class StatusSource
[J("text")] public required string Text { get; set; } [J("text")] public required string Text { get; set; }
[J("spoiler_text")] public required string ContentWarning { get; set; } [J("spoiler_text")] public required string ContentWarning { get; set; }
} }
public class StatusEdit
{
[J("content")] public required string? Content { get; set; }
[J("spoiler_text")] public required string ContentWarning { get; set; }
[J("sensitive")] public required bool IsSensitive { get; set; }
[J("created_at")] public required string CreatedAt { get; set; }
[J("account")] public required AccountEntity Account { get; set; }
[J("poll")] public required PollEntity? Poll { get; set; }
[J("media_attachments")] public required List<AttachmentEntity> Attachments { get; set; }
[J("emojis")] public required List<EmojiEntity> Emojis { get; set; }
}

View file

@ -552,4 +552,22 @@ public class StatusController(
return Ok(res); return Ok(res);
} }
[HttpGet("{id}/history")]
[Authenticate("read:statuses")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IEnumerable<AccountEntity>))]
[ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(MastodonErrorResponse))]
public async Task<IActionResult> GetNoteEditHistory(string id)
{
var user = HttpContext.GetUser();
var note = await db.Notes
.Where(p => p.Id == id)
.EnsureVisibleFor(user)
.FilterHidden(user, db, filterMutes: false)
.FirstOrDefaultAsync() ??
throw GracefulException.RecordNotFound();
var res = await noteRenderer.RenderHistoryAsync(note);
return Ok(res);
}
} }