diff --git a/Iceshrimp.Backend/Controllers/AdminController.cs b/Iceshrimp.Backend/Controllers/AdminController.cs index 797857b1..33751b50 100644 --- a/Iceshrimp.Backend/Controllers/AdminController.cs +++ b/Iceshrimp.Backend/Controllers/AdminController.cs @@ -3,7 +3,6 @@ using System.Net.Mime; using Iceshrimp.Backend.Controllers.Attributes; using Iceshrimp.Backend.Controllers.Federation; using Iceshrimp.Backend.Core.Configuration; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; @@ -12,6 +11,7 @@ using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; using Iceshrimp.Backend.Core.Helpers; using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Services; +using Iceshrimp.Shared.Schemas; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; @@ -125,7 +125,7 @@ public class AdminController( .FirstOrDefaultAsync(p => p.Id == id && p.UserHost == null); if (note == null) return NotFound(); var rendered = await noteRenderer.RenderAsync(note); - var compacted = LdHelpers.Compact(rendered); + var compacted = rendered.Compact(); return Ok(compacted); } @@ -209,4 +209,4 @@ public class AdminController( await Response.WriteAsync(activity); } -} +} \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/AuthController.cs b/Iceshrimp.Backend/Controllers/AuthController.cs index 6b2bc639..1315d0f5 100644 --- a/Iceshrimp.Backend/Controllers/AuthController.cs +++ b/Iceshrimp.Backend/Controllers/AuthController.cs @@ -1,12 +1,12 @@ using System.Diagnostics.CodeAnalysis; using System.Net.Mime; using Iceshrimp.Backend.Controllers.Renderers; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Helpers; using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Services; +using Iceshrimp.Shared.Schemas; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; using Microsoft.EntityFrameworkCore; diff --git a/Iceshrimp.Backend/Controllers/FallbackController.cs b/Iceshrimp.Backend/Controllers/FallbackController.cs index b457cf15..76e539e1 100644 --- a/Iceshrimp.Backend/Controllers/FallbackController.cs +++ b/Iceshrimp.Backend/Controllers/FallbackController.cs @@ -1,7 +1,7 @@ using System.Net; using System.Net.Mime; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Middleware; +using Iceshrimp.Shared.Schemas; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; diff --git a/Iceshrimp.Backend/Controllers/Federation/ActivityPubController.cs b/Iceshrimp.Backend/Controllers/Federation/ActivityPubController.cs index 86cb197c..94d151b7 100644 --- a/Iceshrimp.Backend/Controllers/Federation/ActivityPubController.cs +++ b/Iceshrimp.Backend/Controllers/Federation/ActivityPubController.cs @@ -1,7 +1,6 @@ using System.Text; using Iceshrimp.Backend.Controllers.Attributes; using Iceshrimp.Backend.Controllers.Federation.Attributes; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Extensions; @@ -10,6 +9,7 @@ using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Queues; using Iceshrimp.Backend.Core.Services; +using Iceshrimp.Shared.Schemas; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; diff --git a/Iceshrimp.Backend/Controllers/Federation/WellKnownController.cs b/Iceshrimp.Backend/Controllers/Federation/WellKnownController.cs index aed1f0c1..e35a6f8a 100644 --- a/Iceshrimp.Backend/Controllers/Federation/WellKnownController.cs +++ b/Iceshrimp.Backend/Controllers/Federation/WellKnownController.cs @@ -4,11 +4,11 @@ using System.Text; using System.Xml.Serialization; using Iceshrimp.Backend.Controllers.Federation.Attributes; using Iceshrimp.Backend.Controllers.Federation.Schemas; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Federation.WebFinger; +using Iceshrimp.Shared.Schemas; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; diff --git a/Iceshrimp.Backend/Controllers/Mastodon/MediaController.cs b/Iceshrimp.Backend/Controllers/Mastodon/MediaController.cs index c5a614b7..fbd50b0a 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/MediaController.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/MediaController.cs @@ -88,7 +88,7 @@ public class MediaController(DriveService driveSvc, DatabaseContext db) : Contro Description = file.Comment, PreviewUrl = file.PublicThumbnailUrl, RemoteUrl = file.Uri, - Sensitive = file.IsSensitive, + Sensitive = file.IsSensitive //Metadata = TODO, }; } diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs index 5090c14d..642588e4 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs @@ -20,6 +20,20 @@ public class NoteRenderer( EmojiService emojiSvc ) { + private static readonly FilterResultEntity InaccessibleFilter = new() + { + Filter = new FilterEntity + { + Title = "HideInaccessible", + FilterAction = "hide", + Id = "0", + Context = ["home", "thread", "notifications", "account", "public"], + Keywords = [new FilterKeyword("RE: \ud83d\udd12", 0, 0)], + ExpiresAt = null + }, + KeywordMatches = ["RE: \ud83d\udd12"] // lock emoji + }; + public async Task RenderAsync( Note note, User? user, Filter.FilterContext? filterContext = null, NoteRendererDto? data = null, int recurse = 2 ) @@ -150,20 +164,6 @@ public class NoteRenderer( return res; } - private static readonly FilterResultEntity InaccessibleFilter = new() - { - Filter = new FilterEntity - { - Title = "HideInaccessible", - FilterAction = "hide", - Id = "0", - Context = ["home", "thread", "notifications", "account", "public"], - Keywords = [new FilterKeyword("RE: \ud83d\udd12", 0, 0)], - ExpiresAt = null - }, - KeywordMatches = ["RE: \ud83d\udd12"] // lock emoji - }; - public async Task> RenderHistoryAsync(Note note) { var edits = await db.NoteEdits.Where(p => p.Note == note).OrderBy(p => p.Id).ToListAsync(); @@ -430,13 +430,13 @@ public class NoteRenderer( public List? Attachments; public List? BookmarkedNotes; public List? Emoji; + public List? Filters; public List? LikedNotes; public List? Mentions; public List? PinnedNotes; public List? Polls; public List? Reactions; public List? Renotes; - public List? Filters; public bool Source; } diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/StatusEntity.cs b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/StatusEntity.cs index e153efe6..d495111d 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/StatusEntity.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/StatusEntity.cs @@ -9,7 +9,7 @@ namespace Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities; public class StatusEntity : IEntity, ICloneable { - [J("id")] public required string Id { get; set; } + [JI] public string? MastoReplyUserId; [J("text")] public required string? Text { get; set; } [J("content")] public required string? Content { get; set; } [J("uri")] public required string Uri { get; set; } @@ -52,7 +52,8 @@ public class StatusEntity : IEntity, ICloneable [J("language")] public string? Language => null; //FIXME - [JI] public string? MastoReplyUserId; + public object Clone() => MemberwiseClone(); + [J("id")] public required string Id { get; set; } public static string EncodeVisibility(Note.NoteVisibility visibility) { @@ -77,8 +78,6 @@ public class StatusEntity : IEntity, ICloneable _ => throw GracefulException.BadRequest($"Unknown visibility: {visibility}") }; } - - public object Clone() => MemberwiseClone(); } public class StatusContext diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV1Response.cs b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV1Response.cs index 67a13674..e8e85638 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV1Response.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/InstanceInfoV1Response.cs @@ -44,7 +44,7 @@ public class InstanceUrls(Config.InstanceSection config) public class InstanceStats(long userCount, long noteCount, long instanceCount) { - [J("user_count")] public long UserCount => userCount; + [J("user_count")] public long UserCount => userCount; [J("status_count")] public long NoteCount => noteCount; [J("domain_count")] public long InstanceCount => instanceCount; } diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/StatusSchemas.cs b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/StatusSchemas.cs index 7bbdc86e..5ce6ae6b 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Schemas/StatusSchemas.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Schemas/StatusSchemas.cs @@ -97,6 +97,8 @@ public abstract class StatusSchemas public class ReblogRequest { - [B(Name = "visibility")] [J("visibility")] public string? Visibility { get; set; } + [B(Name = "visibility")] + [J("visibility")] + public string? Visibility { get; set; } } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/Mastodon/StatusController.cs b/Iceshrimp.Backend/Controllers/Mastodon/StatusController.cs index 17580a14..1ed2db7b 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/StatusController.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/StatusController.cs @@ -12,7 +12,6 @@ using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Helpers; using Iceshrimp.Backend.Core.Helpers.LibMfm.Parsing; using Iceshrimp.Backend.Core.Helpers.LibMfm.Serialization; -using static Iceshrimp.Parsing.MfmNodeTypes; using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Services; using Microsoft.AspNetCore.Cors; @@ -20,6 +19,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; +using static Iceshrimp.Parsing.MfmNodeTypes; namespace Iceshrimp.Backend.Controllers.Mastodon; @@ -58,7 +58,7 @@ public class StatusController( var note = await db.Notes .Where(p => p.Id == id) .IncludeCommonProperties() - .FilterHidden(user, db, filterOutgoingBlocks: false, filterMutes: false, + .FilterHidden(user, db, false, false, filterMentions: false) .EnsureVisibleFor(user) .PrecomputeVisibilities(user) @@ -89,7 +89,7 @@ public class StatusController( var note = await db.Notes .Where(p => p.Id == id) .EnsureVisibleFor(user) - .FilterHidden(user, db, filterOutgoingBlocks: false, filterMutes: false) + .FilterHidden(user, db, false, false) .FirstOrDefaultAsync() ?? throw GracefulException.RecordNotFound(); diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/DirectChannel.cs b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/DirectChannel.cs index 1d2264ff..76ce545f 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/DirectChannel.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/DirectChannel.cs @@ -63,12 +63,6 @@ public class DirectChannel(WebSocketConnection connection) : IChannel return wrapped; } - private class NoteWithVisibilities(Note note) - { - public readonly Note Note = note; - public Note? Renote = note.Renote; - } - private static StatusEntity EnforceRenoteReplyVisibility(StatusEntity rendered, NoteWithVisibilities note) { var renote = note.Renote == null && rendered.Renote != null; @@ -149,4 +143,10 @@ public class DirectChannel(WebSocketConnection connection) : IChannel _logger.LogError("Event handler OnNoteUpdated threw exception: {e}", e); } } + + private class NoteWithVisibilities(Note note) + { + public readonly Note Note = note; + public Note? Renote = note.Renote; + } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/HashtagChannel.cs b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/HashtagChannel.cs index c3fba36b..d5ed6829 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/HashtagChannel.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/HashtagChannel.cs @@ -13,13 +13,13 @@ public class HashtagChannel(WebSocketConnection connection, bool local) : IChann private readonly ILogger _logger = connection.Scope.ServiceProvider.GetRequiredService>(); + private readonly WriteLockingList _tags = []; + public string Name => local ? "hashtag:local" : "hashtag"; public List Scopes => ["read:statuses"]; public bool IsSubscribed => _tags.Count != 0; public bool IsAggregate => true; - private readonly WriteLockingList _tags = []; - public async Task Subscribe(StreamingRequestMessage msg) { if (msg.Tag == null) @@ -79,12 +79,6 @@ public class HashtagChannel(WebSocketConnection connection, bool local) : IChann return wrapped; } - private class NoteWithVisibilities(Note note) - { - public readonly Note Note = note; - public Note? Renote = note.Renote; - } - private static StatusEntity EnforceRenoteReplyVisibility(StatusEntity rendered, NoteWithVisibilities note) { var renote = note.Renote == null && rendered.Renote != null; @@ -169,4 +163,10 @@ public class HashtagChannel(WebSocketConnection connection, bool local) : IChann _logger.LogError("Event handler OnNoteDeleted threw exception: {e}", e); } } + + private class NoteWithVisibilities(Note note) + { + public readonly Note Note = note; + public Note? Renote = note.Renote; + } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/ListChannel.cs b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/ListChannel.cs index c1d300db..e4578e46 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/ListChannel.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/ListChannel.cs @@ -12,18 +12,19 @@ namespace Iceshrimp.Backend.Controllers.Mastodon.Streaming.Channels; public class ListChannel(WebSocketConnection connection) : IChannel { + private readonly WriteLockingList _lists = []; + private readonly ILogger _logger = connection.Scope.ServiceProvider.GetRequiredService>(); + private readonly ConcurrentDictionary> _members = []; + private IEnumerable _applicableUserIds = []; + public string Name => "list"; public List Scopes => ["read:statuses"]; public bool IsSubscribed => _lists.Count != 0; public bool IsAggregate => true; - private readonly WriteLockingList _lists = []; - private readonly ConcurrentDictionary> _members = []; - private IEnumerable _applicableUserIds = []; - public async Task Subscribe(StreamingRequestMessage msg) { if (msg.List == null) @@ -101,12 +102,6 @@ public class ListChannel(WebSocketConnection connection) : IChannel return wrapped; } - private class NoteWithVisibilities(Note note) - { - public readonly Note Note = note; - public Note? Renote = note.Renote; - } - private static StatusEntity EnforceRenoteReplyVisibility(StatusEntity rendered, NoteWithVisibilities note) { var renote = note.Renote == null && rendered.Renote != null; @@ -218,4 +213,10 @@ public class ListChannel(WebSocketConnection connection) : IChannel _logger.LogError("Event handler OnListUpdated threw exception: {e}", e); } } + + private class NoteWithVisibilities(Note note) + { + public readonly Note Note = note; + public Note? Renote = note.Renote; + } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/PublicChannel.cs b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/PublicChannel.cs index 698e5681..ebe04dbd 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/PublicChannel.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/PublicChannel.cs @@ -71,12 +71,6 @@ public class PublicChannel( return wrapped; } - private class NoteWithVisibilities(Note note) - { - public readonly Note Note = note; - public Note? Renote = note.Renote; - } - private static StatusEntity EnforceRenoteReplyVisibility(StatusEntity rendered, NoteWithVisibilities note) { var renote = note.Renote == null && rendered.Renote != null; @@ -160,4 +154,10 @@ public class PublicChannel( _logger.LogError("Event handler OnNoteDeleted threw exception: {e}", e); } } + + private class NoteWithVisibilities(Note note) + { + public readonly Note Note = note; + public Note? Renote = note.Renote; + } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/UserChannel.cs b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/UserChannel.cs index 0e17b66b..07d92228 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/UserChannel.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/UserChannel.cs @@ -83,12 +83,6 @@ public class UserChannel(WebSocketConnection connection, bool notificationsOnly) return wrapped; } - private class NoteWithVisibilities(Note note) - { - public readonly Note Note = note; - public Note? Renote = note.Renote; - } - private static StatusEntity EnforceRenoteReplyVisibility(StatusEntity rendered, NoteWithVisibilities note) { var renote = note.Renote == null && rendered.Renote != null; @@ -206,4 +200,10 @@ public class UserChannel(WebSocketConnection connection, bool notificationsOnly) _logger.LogError("Event handler OnNotification threw exception: {e}", e); } } + + private class NoteWithVisibilities(Note note) + { + public readonly Note Note = note; + public Note? Renote = note.Renote; + } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/WebSocketConnection.cs b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/WebSocketConnection.cs index a0962024..4c1e316c 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/Streaming/WebSocketConnection.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/Streaming/WebSocketConnection.cs @@ -23,18 +23,18 @@ public sealed class WebSocketConnection( CancellationToken ct ) : IDisposable { + private readonly WriteLockingList _blockedBy = []; + private readonly WriteLockingList _blocking = []; private readonly SemaphoreSlim _lock = new(1); + private readonly WriteLockingList _muting = []; public readonly List Channels = []; public readonly EventService EventService = eventSvc; + public readonly WriteLockingList Filters = []; + public readonly WriteLockingList Following = []; public readonly IServiceScope Scope = scopeFactory.CreateScope(); public readonly IServiceScopeFactory ScopeFactory = scopeFactory; public readonly OauthToken Token = token; public List HiddenFromHome = []; - public readonly WriteLockingList Filters = []; - public readonly WriteLockingList Following = []; - private readonly WriteLockingList _blocking = []; - private readonly WriteLockingList _blockedBy = []; - private readonly WriteLockingList _muting = []; public void Dispose() { @@ -362,9 +362,9 @@ public sealed class WebSocketConnection( (note.Renote?.User != null && (IsFiltered(note.Renote.User) || IsFilteredMentions(note.Renote.Mentions))) || - note.Renote?.Renote?.User != null && - (IsFiltered(note.Renote.Renote.User) || - IsFilteredMentions(note.Renote.Renote.Mentions)); + (note.Renote?.Renote?.User != null && + (IsFiltered(note.Renote.Renote.User) || + IsFilteredMentions(note.Renote.Renote.Mentions))); public async Task CloseAsync(WebSocketCloseStatus status) { diff --git a/Iceshrimp.Backend/Controllers/Mastodon/TimelineController.cs b/Iceshrimp.Backend/Controllers/Mastodon/TimelineController.cs index 4b6ce814..3c190c6b 100644 --- a/Iceshrimp.Backend/Controllers/Mastodon/TimelineController.cs +++ b/Iceshrimp.Backend/Controllers/Mastodon/TimelineController.cs @@ -107,4 +107,4 @@ public class TimelineController(DatabaseContext db, NoteRenderer noteRenderer, C return Ok(res); } -} +} \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/NoteController.cs b/Iceshrimp.Backend/Controllers/NoteController.cs index 1fac6d62..a458e3db 100644 --- a/Iceshrimp.Backend/Controllers/NoteController.cs +++ b/Iceshrimp.Backend/Controllers/NoteController.cs @@ -4,13 +4,13 @@ using System.Net.Mime; using AsyncKeyedLock; using Iceshrimp.Backend.Controllers.Attributes; using Iceshrimp.Backend.Controllers.Renderers; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Helpers; using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Services; +using Iceshrimp.Shared.Schemas; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; using Microsoft.EntityFrameworkCore; @@ -45,7 +45,7 @@ public class NoteController( var note = await db.Notes.Where(p => p.Id == id) .IncludeCommonProperties() .EnsureVisibleFor(user) - .FilterHidden(user, db, filterOutgoingBlocks: false, filterMutes: false) + .FilterHidden(user, db, false, false) .PrecomputeVisibilities(user) .FirstOrDefaultAsync() ?? throw GracefulException.NotFound("Note not found"); @@ -65,7 +65,7 @@ public class NoteController( var note = await db.Notes.Where(p => p.Id == id) .EnsureVisibleFor(user) - .FilterHidden(user, db, filterOutgoingBlocks: false, filterMutes: false) + .FilterHidden(user, db, false, false) .FirstOrDefaultAsync() ?? throw GracefulException.NotFound("Note not found"); @@ -94,7 +94,7 @@ public class NoteController( var note = await db.Notes.Where(p => p.Id == id) .EnsureVisibleFor(user) - .FilterHidden(user, db, filterOutgoingBlocks: false, filterMutes: false) + .FilterHidden(user, db, false, false) .FirstOrDefaultAsync() ?? throw GracefulException.NotFound("Note not found"); diff --git a/Iceshrimp.Backend/Controllers/NotificationController.cs b/Iceshrimp.Backend/Controllers/NotificationController.cs index 93bb8314..dd5257a6 100644 --- a/Iceshrimp.Backend/Controllers/NotificationController.cs +++ b/Iceshrimp.Backend/Controllers/NotificationController.cs @@ -2,10 +2,10 @@ using System.Net.Mime; using Iceshrimp.Backend.Controllers.Attributes; using Iceshrimp.Backend.Controllers.Renderers; using Iceshrimp.Backend.Controllers.Schemas; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Middleware; +using Iceshrimp.Shared.Schemas; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; using Microsoft.EntityFrameworkCore; diff --git a/Iceshrimp.Backend/Controllers/Renderers/NoteRenderer.cs b/Iceshrimp.Backend/Controllers/Renderers/NoteRenderer.cs index 1f7983f4..06e9deb5 100644 --- a/Iceshrimp.Backend/Controllers/Renderers/NoteRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Renderers/NoteRenderer.cs @@ -1,10 +1,10 @@ using Iceshrimp.Backend.Core.Configuration; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Helpers; using Iceshrimp.Backend.Core.Services; +using Iceshrimp.Shared.Schemas; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; @@ -219,10 +219,10 @@ public class NoteRenderer( public class NoteRendererDto { public List? Attachments; - public List? Reactions; - public List? Users; + public List? Emoji; public List? Filters; public List? LikedNotes; - public List? Emoji; + public List? Reactions; + public List? Users; } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Controllers/Renderers/NotificationRenderer.cs b/Iceshrimp.Backend/Controllers/Renderers/NotificationRenderer.cs index 17139a7e..93ece7ed 100644 --- a/Iceshrimp.Backend/Controllers/Renderers/NotificationRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Renderers/NotificationRenderer.cs @@ -1,6 +1,6 @@ -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; +using Iceshrimp.Shared.Schemas; namespace Iceshrimp.Backend.Controllers.Renderers; diff --git a/Iceshrimp.Backend/Controllers/Renderers/UserProfileRenderer.cs b/Iceshrimp.Backend/Controllers/Renderers/UserProfileRenderer.cs index 43aea633..e6b47958 100644 --- a/Iceshrimp.Backend/Controllers/Renderers/UserProfileRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Renderers/UserProfileRenderer.cs @@ -1,7 +1,7 @@ -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; +using Iceshrimp.Shared.Schemas; using Microsoft.EntityFrameworkCore; namespace Iceshrimp.Backend.Controllers.Renderers; @@ -91,14 +91,14 @@ public class UserProfileRenderer(DatabaseContext db) public class RelationData { - public required string UserId; - public required bool IsSelf; - public required bool IsFollowing; + public required bool IsBlocking; public required bool IsFollowedBy; + public required bool IsFollowing; + public required bool IsMuting; public required bool IsRequested; public required bool IsRequestedBy; - public required bool IsBlocking; - public required bool IsMuting; + public required bool IsSelf; + public required string UserId; public static implicit operator Relations(RelationData data) { diff --git a/Iceshrimp.Backend/Controllers/Renderers/UserRenderer.cs b/Iceshrimp.Backend/Controllers/Renderers/UserRenderer.cs index 1cb1dc3d..232cbba4 100644 --- a/Iceshrimp.Backend/Controllers/Renderers/UserRenderer.cs +++ b/Iceshrimp.Backend/Controllers/Renderers/UserRenderer.cs @@ -1,8 +1,8 @@ -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; +using Iceshrimp.Shared.Schemas; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; diff --git a/Iceshrimp.Backend/Controllers/TimelineController.cs b/Iceshrimp.Backend/Controllers/TimelineController.cs index ff9b1f2f..e6487766 100644 --- a/Iceshrimp.Backend/Controllers/TimelineController.cs +++ b/Iceshrimp.Backend/Controllers/TimelineController.cs @@ -2,12 +2,12 @@ using System.Net.Mime; using Iceshrimp.Backend.Controllers.Attributes; using Iceshrimp.Backend.Controllers.Renderers; using Iceshrimp.Backend.Controllers.Schemas; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Services; +using Iceshrimp.Shared.Schemas; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; using Microsoft.EntityFrameworkCore; diff --git a/Iceshrimp.Backend/Controllers/UserController.cs b/Iceshrimp.Backend/Controllers/UserController.cs index 1cb1e31a..11cda682 100644 --- a/Iceshrimp.Backend/Controllers/UserController.cs +++ b/Iceshrimp.Backend/Controllers/UserController.cs @@ -2,12 +2,12 @@ using System.Net.Mime; using Iceshrimp.Backend.Controllers.Attributes; using Iceshrimp.Backend.Controllers.Renderers; using Iceshrimp.Backend.Controllers.Schemas; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Services; +using Iceshrimp.Shared.Schemas; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.RateLimiting; using Microsoft.EntityFrameworkCore; diff --git a/Iceshrimp.Backend/Core/Configuration/Config.cs b/Iceshrimp.Backend/Core/Configuration/Config.cs index bec80eae..c2ae9760 100644 --- a/Iceshrimp.Backend/Core/Configuration/Config.cs +++ b/Iceshrimp.Backend/Core/Configuration/Config.cs @@ -17,10 +17,10 @@ public sealed class Config public sealed class InstanceSection { - public readonly string Version; public readonly string Codename; public readonly string? CommitHash; public readonly string RawVersion; + public readonly string Version; public InstanceSection() { @@ -100,9 +100,9 @@ public sealed class Config public sealed class StorageSection { - public readonly TimeSpan? MediaRetentionTimeSpan; public readonly int? MaxCacheSizeBytes; public readonly int? MaxUploadSizeBytes; + public readonly TimeSpan? MediaRetentionTimeSpan; public bool CleanAvatars = false; public bool CleanBanners = false; diff --git a/Iceshrimp.Backend/Core/Configuration/Enums.cs b/Iceshrimp.Backend/Core/Configuration/Enums.cs index 71aa51f6..7954fcb1 100644 --- a/Iceshrimp.Backend/Core/Configuration/Enums.cs +++ b/Iceshrimp.Backend/Core/Configuration/Enums.cs @@ -14,6 +14,13 @@ public static class Enums ObjectStorage = 1 } + public enum ImageProcessor + { + ImageSharp, + LibVips, + None + } + public enum ItemVisibility { Hide = 0, @@ -21,25 +28,18 @@ public static class Enums Public = 2 } + public enum PublicPreview + { + Lockdown = 0, + RestrictedNoMedia = 1, + Restricted = 2, + Public = 3 + } + public enum Registrations { Closed = 0, Invite = 1, Open = 2 } - - public enum PublicPreview - { - Lockdown = 0, - RestrictedNoMedia = 1, - Restricted = 2, - Public = 3 - } - - public enum ImageProcessor - { - ImageSharp, - LibVips, - None - } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Database/IEntity.cs b/Iceshrimp.Backend/Core/Database/IEntity.cs index c6021709..088ee262 100644 --- a/Iceshrimp.Backend/Core/Database/IEntity.cs +++ b/Iceshrimp.Backend/Core/Database/IEntity.cs @@ -7,6 +7,6 @@ public interface IEntity public class EntityWrapper : IEntity { - public required string Id { get; init; } public required T Entity { get; init; } + public required string Id { get; init; } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Database/Tables/Emoji.cs b/Iceshrimp.Backend/Core/Database/Tables/Emoji.cs index 0e69accb..470946ad 100644 --- a/Iceshrimp.Backend/Core/Database/Tables/Emoji.cs +++ b/Iceshrimp.Backend/Core/Database/Tables/Emoji.cs @@ -56,7 +56,7 @@ public class Emoji /// [Column("height")] public int? Height { get; set; } - + public string GetPublicUri(Config.InstanceSection config) => Host == null ? $"https://{config.WebDomain}/emoji/{Name}" : throw new Exception("Cannot access PublicUri for remote emoji"); diff --git a/Iceshrimp.Backend/Core/Database/Tables/Filter.cs b/Iceshrimp.Backend/Core/Database/Tables/Filter.cs index 89747e13..97b8a273 100644 --- a/Iceshrimp.Backend/Core/Database/Tables/Filter.cs +++ b/Iceshrimp.Backend/Core/Database/Tables/Filter.cs @@ -10,6 +10,13 @@ namespace Iceshrimp.Backend.Core.Database.Tables; [Index("user_id")] public class Filter { + [PgName("filter_action_enum")] + public enum FilterAction + { + [PgName("warn")] Warn, + [PgName("hide")] Hide + } + [PgName("filter_context_enum")] public enum FilterContext { @@ -18,17 +25,11 @@ public class Filter [PgName("threads")] Threads, [PgName("notifications")] Notifications, [PgName("accounts")] Accounts, - [PgName("public")] Public, + [PgName("public")] Public } - [PgName("filter_action_enum")] - public enum FilterAction - { - [PgName("warn")] Warn, - [PgName("hide")] Hide, - } - - [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] [Column("id")] public long Id { get; set; } diff --git a/Iceshrimp.Backend/Core/Database/Tables/FollowRequest.cs b/Iceshrimp.Backend/Core/Database/Tables/FollowRequest.cs index dd1df03e..16e63420 100644 --- a/Iceshrimp.Backend/Core/Database/Tables/FollowRequest.cs +++ b/Iceshrimp.Backend/Core/Database/Tables/FollowRequest.cs @@ -36,9 +36,8 @@ public class FollowRequest : IEntity [Column("requestId")] [StringLength(128)] public string? RequestId { get; set; } - - [Column("relationshipId")] - public Guid? RelationshipId { get; set; } + + [Column("relationshipId")] public Guid? RelationshipId { get; set; } /// /// [Denormalized] diff --git a/Iceshrimp.Backend/Core/Database/Tables/Following.cs b/Iceshrimp.Backend/Core/Database/Tables/Following.cs index 964491e9..823d5817 100644 --- a/Iceshrimp.Backend/Core/Database/Tables/Following.cs +++ b/Iceshrimp.Backend/Core/Database/Tables/Following.cs @@ -79,9 +79,8 @@ public class Following [Column("followeeSharedInbox")] [StringLength(512)] public string? FolloweeSharedInbox { get; set; } - - [Column("relationshipId")] - public Guid? RelationshipId { get; set; } + + [Column("relationshipId")] public Guid? RelationshipId { get; set; } [ForeignKey(nameof(FolloweeId))] [InverseProperty(nameof(User.IncomingFollowRelationships))] diff --git a/Iceshrimp.Backend/Core/Database/Tables/Note.cs b/Iceshrimp.Backend/Core/Database/Tables/Note.cs index 88daf498..49fff2f9 100644 --- a/Iceshrimp.Backend/Core/Database/Tables/Note.cs +++ b/Iceshrimp.Backend/Core/Database/Tables/Note.cs @@ -63,14 +63,14 @@ public class Note : IEntity public string? RenoteId { get; set; } /// - /// The URI of the reply target, if it couldn't be resolved at time of ingestion. + /// The URI of the reply target, if it couldn't be resolved at time of ingestion. /// [Column("replyUri")] [StringLength(512)] public string? ReplyUri { get; set; } /// - /// The URI of the renote target, if it couldn't be resolved at time of ingestion. + /// The URI of the renote target, if it couldn't be resolved at time of ingestion. /// [Column("renoteUri")] [StringLength(512)] @@ -155,7 +155,8 @@ public class Note : IEntity public string? ReplyUserId { get; set; } /// - /// Mastodon requires a slightly differently computed replyUserId field. To save processing time, we do this ahead of time. + /// Mastodon requires a slightly differently computed replyUserId field. To save processing time, we do this ahead of + /// time. /// [Column("mastoReplyUserId")] [StringLength(32)] diff --git a/Iceshrimp.Backend/Core/Database/Tables/User.cs b/Iceshrimp.Backend/Core/Database/Tables/User.cs index 8aed2daf..7e0296a2 100644 --- a/Iceshrimp.Backend/Core/Database/Tables/User.cs +++ b/Iceshrimp.Backend/Core/Database/Tables/User.cs @@ -265,9 +265,8 @@ public class User : IEntity [Column("bannerBlurhash")] [StringLength(128)] public string? BannerBlurhash { get; set; } - - [Column("splitDomainResolved")] - public bool SplitDomainResolved { get; set; } + + [Column("splitDomainResolved")] public bool SplitDomainResolved { get; set; } [InverseProperty(nameof(AbuseUserReport.Assignee))] public virtual ICollection AbuseUserReportAssignees { get; set; } = new List(); @@ -485,7 +484,7 @@ public class User : IEntity [InverseProperty(nameof(Webhook.User))] public virtual ICollection Webhooks { get; set; } = new List(); - + [InverseProperty(nameof(Filter.User))] public virtual ICollection Filters { get; set; } = new List(); @@ -577,7 +576,7 @@ public class User : IEntity [Projectable] public bool HasReplied(Note note) => Notes.Any(p => p.Reply == note && p.User == this); - + [Projectable] public bool HasVoted(Note note) => PollVotes.Any(p => p.Note == note && p.User == this); diff --git a/Iceshrimp.Backend/Core/Extensions/ConsoleLoggerExtensions.cs b/Iceshrimp.Backend/Core/Extensions/ConsoleLoggerExtensions.cs index 27d87015..47b47603 100644 --- a/Iceshrimp.Backend/Core/Extensions/ConsoleLoggerExtensions.cs +++ b/Iceshrimp.Backend/Core/Extensions/ConsoleLoggerExtensions.cs @@ -260,7 +260,7 @@ file sealed class CustomFormatter() : ConsoleFormatter("custom") file sealed class CustomSystemdConsoleFormatter() : ConsoleFormatter("systemd-custom") { - private static readonly string MessagePadding = new(' ', 6); + private static readonly string MessagePadding = new(' ', 6); public override void Write( in LogEntry logEntry, diff --git a/Iceshrimp.Backend/Core/Extensions/DateTimeExtensions.cs b/Iceshrimp.Backend/Core/Extensions/DateTimeExtensions.cs index 3f121181..17b9a7cd 100644 --- a/Iceshrimp.Backend/Core/Extensions/DateTimeExtensions.cs +++ b/Iceshrimp.Backend/Core/Extensions/DateTimeExtensions.cs @@ -6,12 +6,12 @@ public static class DateTimeExtensions { return dateTime.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffK"); } - + public static string ToDisplayString(this DateTime dateTime) { return dateTime.ToString("yyyy'-'MM'-'dd' 'HH':'mm"); } - + public static string ToDisplayStringTz(this DateTime dateTime) { return dateTime.ToString("yyyy'-'MM'-'dd' 'HH':'mm':'sszz"); diff --git a/Iceshrimp.Backend/Core/Extensions/MvcBuilderExtensions.cs b/Iceshrimp.Backend/Core/Extensions/MvcBuilderExtensions.cs index d408b4e8..e80c00b5 100644 --- a/Iceshrimp.Backend/Core/Extensions/MvcBuilderExtensions.cs +++ b/Iceshrimp.Backend/Core/Extensions/MvcBuilderExtensions.cs @@ -1,7 +1,6 @@ using System.Buffers; using System.Net; using System.Text.Encodings.Web; -using System.Text.Json; using Iceshrimp.Backend.Controllers.Attributes; using Iceshrimp.Backend.Core.Middleware; using Microsoft.AspNetCore.Mvc; @@ -9,6 +8,8 @@ using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.Extensions.ObjectPool; using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using JsonSerializer = System.Text.Json.JsonSerializer; namespace Iceshrimp.Backend.Core.Extensions; @@ -42,9 +43,9 @@ public static class MvcBuilderExtensions public static IMvcBuilder ConfigureNewtonsoftJson(this IMvcBuilder builder) { - Newtonsoft.Json.JsonConvert.DefaultSettings = () => new Newtonsoft.Json.JsonSerializerSettings + JsonConvert.DefaultSettings = () => new JsonSerializerSettings { - DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc + DateTimeZoneHandling = DateTimeZoneHandling.Utc }; return builder; diff --git a/Iceshrimp.Backend/Core/Extensions/QueryableFtsExtensions.cs b/Iceshrimp.Backend/Core/Extensions/QueryableFtsExtensions.cs index 7ab05af4..b1fc7fb1 100644 --- a/Iceshrimp.Backend/Core/Extensions/QueryableFtsExtensions.cs +++ b/Iceshrimp.Backend/Core/Extensions/QueryableFtsExtensions.cs @@ -55,7 +55,7 @@ public static class QueryableFtsExtensions } /// - /// The input variable host, or null if it matches the configured web or account domain. + /// The input variable host, or null if it matches the configured web or account domain. /// [SuppressMessage("ReSharper", "MemberCanBePrivate.Global", Justification = "Projectable chain must have consistent visibility")] diff --git a/Iceshrimp.Backend/Core/Extensions/ServiceExtensions.cs b/Iceshrimp.Backend/Core/Extensions/ServiceExtensions.cs index 82ef9b8d..19043ba1 100644 --- a/Iceshrimp.Backend/Core/Extensions/ServiceExtensions.cs +++ b/Iceshrimp.Backend/Core/Extensions/ServiceExtensions.cs @@ -4,7 +4,6 @@ using System.Xml.Linq; using Iceshrimp.Backend.Controllers.Federation; using Iceshrimp.Backend.Controllers.Mastodon.Renderers; using Iceshrimp.Backend.Controllers.Renderers; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Federation.WebFinger; @@ -13,6 +12,7 @@ using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Services; using Iceshrimp.Backend.Hubs.Authentication; using Iceshrimp.Shared.Configuration; +using Iceshrimp.Shared.Schemas; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; @@ -20,6 +20,7 @@ using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationM using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; using Microsoft.AspNetCore.DataProtection.KeyManagement; using Microsoft.AspNetCore.DataProtection.Repositories; +using Microsoft.AspNetCore.Http.Json; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging.Abstractions; @@ -120,7 +121,7 @@ public static class ServiceExtensions .ConfigureWithValidation(configuration, "Storage:Local") .ConfigureWithValidation(configuration, "Storage:ObjectStorage"); - services.Configure(options => + services.Configure(options => { options.SerializerOptions.PropertyNamingPolicy = JsonSerialization.Options.PropertyNamingPolicy; foreach (var converter in JsonSerialization.Options.Converters) @@ -323,8 +324,9 @@ public static class HttpContextExtensions #region AsyncDataProtection handlers /// -/// Async equivalent of EntityFrameworkCoreDataProtectionExtensions.PersistKeysToDbContext. -/// Required because Npgsql doesn't support the non-async APIs when using connection multiplexing, and the stock version EFCore API calls their blocking equivalents. +/// Async equivalent of EntityFrameworkCoreDataProtectionExtensions.PersistKeysToDbContext. +/// Required because Npgsql doesn't support the non-async APIs when using connection multiplexing, and the stock +/// version EFCore API calls their blocking equivalents. /// file static class DataProtectionExtensions { diff --git a/Iceshrimp.Backend/Core/Extensions/SwaggerGenOptionsExtensions.cs b/Iceshrimp.Backend/Core/Extensions/SwaggerGenOptionsExtensions.cs index 80b55057..d2c6186a 100644 --- a/Iceshrimp.Backend/Core/Extensions/SwaggerGenOptionsExtensions.cs +++ b/Iceshrimp.Backend/Core/Extensions/SwaggerGenOptionsExtensions.cs @@ -23,22 +23,6 @@ public static class SwaggerGenOptionsExtensions options.DocInclusionPredicate(DocInclusionPredicate); } - [SuppressMessage("ReSharper", "ClassNeverInstantiated.Local", - Justification = "SwaggerGenOptions.SchemaFilter instantiates this class at runtime")] - private class RequireNonNullablePropertiesSchemaFilter : ISchemaFilter - { - public void Apply(OpenApiSchema model, SchemaFilterContext context) - { - var additionalRequiredProps = model.Properties - .Where(x => !x.Value.Nullable && !model.Required.Contains(x.Key)) - .Select(x => x.Key); - foreach (var propKey in additionalRequiredProps) - { - model.Required.Add(propKey); - } - } - } - private static bool DocInclusionPredicate(string docName, ApiDescription apiDesc) { if (!apiDesc.TryGetMethodInfo(out var methodInfo)) return false; @@ -61,6 +45,22 @@ public static class SwaggerGenOptionsExtensions }; } + [SuppressMessage("ReSharper", "ClassNeverInstantiated.Local", + Justification = "SwaggerGenOptions.SchemaFilter instantiates this class at runtime")] + private class RequireNonNullablePropertiesSchemaFilter : ISchemaFilter + { + public void Apply(OpenApiSchema model, SchemaFilterContext context) + { + var additionalRequiredProps = model.Properties + .Where(x => !x.Value.Nullable && !model.Required.Contains(x.Key)) + .Select(x => x.Key); + foreach (var propKey in additionalRequiredProps) + { + model.Required.Add(propKey); + } + } + } + [SuppressMessage("ReSharper", "ClassNeverInstantiated.Local", Justification = "SwaggerGenOptions.OperationFilter instantiates this class at runtime")] private class AuthorizeCheckOperationFilter : IOperationFilter diff --git a/Iceshrimp.Backend/Core/Extensions/WebApplicationExtensions.cs b/Iceshrimp.Backend/Core/Extensions/WebApplicationExtensions.cs index 252751f3..9697d7ec 100644 --- a/Iceshrimp.Backend/Core/Extensions/WebApplicationExtensions.cs +++ b/Iceshrimp.Backend/Core/Extensions/WebApplicationExtensions.cs @@ -4,11 +4,11 @@ using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Migrations; using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Services; +using Iceshrimp.WebPush; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.Extensions.Configuration.Ini; using Microsoft.Extensions.Options; -using Iceshrimp.WebPush; namespace Iceshrimp.Backend.Core.Extensions; diff --git a/Iceshrimp.Backend/Core/Federation/ActivityPub/MentionsResolver.cs b/Iceshrimp.Backend/Core/Federation/ActivityPub/MentionsResolver.cs index fbcd9d9b..deb69a85 100644 --- a/Iceshrimp.Backend/Core/Federation/ActivityPub/MentionsResolver.cs +++ b/Iceshrimp.Backend/Core/Federation/ActivityPub/MentionsResolver.cs @@ -3,9 +3,9 @@ using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Helpers.LibMfm.Parsing; using Iceshrimp.Backend.Core.Helpers.LibMfm.Serialization; -using static Iceshrimp.Parsing.MfmNodeTypes; using Microsoft.Extensions.Options; using Microsoft.FSharp.Collections; +using static Iceshrimp.Parsing.MfmNodeTypes; namespace Iceshrimp.Backend.Core.Federation.ActivityPub; diff --git a/Iceshrimp.Backend/Core/Federation/ActivityStreams/LdHelpers.cs b/Iceshrimp.Backend/Core/Federation/ActivityStreams/LdHelpers.cs index 07cac4f9..2fefd39b 100644 --- a/Iceshrimp.Backend/Core/Federation/ActivityStreams/LdHelpers.cs +++ b/Iceshrimp.Backend/Core/Federation/ActivityStreams/LdHelpers.cs @@ -18,14 +18,6 @@ public static class LdHelpers private static readonly string Prefix = Path.Combine(AssemblyLocation, "contexts"); - private static JToken GetPreloadedDocument(string filename) => - JToken.Parse(File.ReadAllText(Path.Combine(Prefix, filename))); - - private static RemoteDocument GetPreloadedContext(string filename) => new() - { - Document = GetPreloadedDocument(filename) - }; - private static readonly Dictionary PreloadedContexts = new() { { "https://www.w3.org/ns/activitystreams", GetPreloadedContext("as.json") }, @@ -66,6 +58,14 @@ public static class LdHelpers private static IEnumerable ASForceArray => ["tag", "attachment", "to", "cc", "bcc", "bto"]; + private static JToken GetPreloadedDocument(string filename) => + JToken.Parse(File.ReadAllText(Path.Combine(Prefix, filename))); + + private static RemoteDocument GetPreloadedContext(string filename) => new() + { + Document = GetPreloadedDocument(filename) + }; + private static RemoteDocument CustomLoader(Uri uri, JsonLdLoaderOptions jsonLdLoaderOptions) { var key = uri.AbsolutePath == "/schemas/litepub-0.1.jsonld" ? "litepub-0.1" : uri.ToString(); diff --git a/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASNote.cs b/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASNote.cs index 50a7ea74..cfa33bae 100644 --- a/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASNote.cs +++ b/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASNote.cs @@ -9,11 +9,10 @@ namespace Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; public class ASNote : ASObject { - public ASNote(bool withType = true) => Type = withType ? Types.Note : null; + private string? _mkContent; [JI] public bool VerifiedFetch = false; - - private string? _mkContent; + public ASNote(bool withType = true) => Type = withType ? Types.Note : null; [J("https://misskey-hub.net/ns#_misskey_content")] [JC(typeof(VC))] diff --git a/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASQuestion.cs b/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASQuestion.cs index 1d29e6f4..68559c4c 100644 --- a/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASQuestion.cs +++ b/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASQuestion.cs @@ -32,7 +32,7 @@ public class ASQuestion : ASNote [J($"{Constants.ActivityStreamsNs}#closed")] [JC(typeof(VC))] public DateTime? Closed { get; set; } - + [J($"{Constants.MastodonNs}#votersCount")] [JC(typeof(VC))] public int? VotersCount { get; set; } diff --git a/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/LDValueObject.cs b/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/LDValueObject.cs index 88f3091b..1ae65c8d 100644 --- a/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/LDValueObject.cs +++ b/Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/LDValueObject.cs @@ -64,7 +64,7 @@ public class ValueObjectConverter : JsonConverter var val = obj?.Value; return val != null ? Convert.ToUInt64(val) : null; } - + if (objectType == typeof(int?)) { var val = obj?.Value; diff --git a/Iceshrimp.Backend/Core/Federation/Cryptography/HttpSignature.cs b/Iceshrimp.Backend/Core/Federation/Cryptography/HttpSignature.cs index ca042107..707f829f 100644 --- a/Iceshrimp.Backend/Core/Federation/Cryptography/HttpSignature.cs +++ b/Iceshrimp.Backend/Core/Federation/Cryptography/HttpSignature.cs @@ -184,11 +184,11 @@ public static class HttpSignature ) { public readonly string Algo = algo; - public readonly IEnumerable Headers = headers; - public readonly string KeyId = keyId; - public readonly byte[] Signature = signature; public readonly string? Created = created; public readonly string? Expires = expires; + public readonly IEnumerable Headers = headers; + public readonly string KeyId = keyId; public readonly string? Opaque = opaque; + public readonly byte[] Signature = signature; } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Helpers/CryptographyHelpers.cs b/Iceshrimp.Backend/Core/Helpers/CryptographyHelpers.cs index 4a5ec90e..7587bbdf 100644 --- a/Iceshrimp.Backend/Core/Helpers/CryptographyHelpers.cs +++ b/Iceshrimp.Backend/Core/Helpers/CryptographyHelpers.cs @@ -4,12 +4,6 @@ namespace Iceshrimp.Backend.Core.Helpers; public static class CryptographyHelpers { - public static string GenerateRandomHexString(int length) - => RandomNumberGenerator.GetHexString(length, true); - - public static string GenerateRandomString(int length, Charset charset = Charset.AlphaNum) - => RandomNumberGenerator.GetString(GetCharset(charset), length); - public enum Charset { AlphaNum, @@ -18,6 +12,17 @@ public static class CryptographyHelpers CrockfordBase32Lower } + private const string AlphaNumCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private const string AlphaNumLowerCharset = "abcdefghijklmnopqrstuvwxyz0123456789"; + private const string CrockfordBase32Charset = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; + private const string CrockfordBase32LowerCharset = "0123456789abcdefghjkmnpqrstvwxyz"; + + public static string GenerateRandomHexString(int length) + => RandomNumberGenerator.GetHexString(length, true); + + public static string GenerateRandomString(int length, Charset charset = Charset.AlphaNum) + => RandomNumberGenerator.GetString(GetCharset(charset), length); + private static string GetCharset(Charset charset) => charset switch { Charset.AlphaNum => AlphaNumCharset, @@ -26,9 +31,4 @@ public static class CryptographyHelpers Charset.CrockfordBase32Lower => CrockfordBase32LowerCharset, _ => throw new ArgumentOutOfRangeException(nameof(charset), charset, null) }; - - private const string AlphaNumCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - private const string AlphaNumLowerCharset = "abcdefghijklmnopqrstuvwxyz0123456789"; - private const string CrockfordBase32Charset = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; - private const string CrockfordBase32LowerCharset = "0123456789abcdefghjkmnpqrstvwxyz"; } \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Helpers/EventHelpers.cs b/Iceshrimp.Backend/Core/Helpers/EventHelpers.cs index c0310977..f390f174 100644 --- a/Iceshrimp.Backend/Core/Helpers/EventHelpers.cs +++ b/Iceshrimp.Backend/Core/Helpers/EventHelpers.cs @@ -2,8 +2,8 @@ namespace Iceshrimp.Backend.Core.Helpers; public sealed class AsyncAutoResetEvent(bool signaled = false) { - private readonly List> _taskCompletionSources = []; private readonly List> _noResetTaskCompletionSources = []; + private readonly List> _taskCompletionSources = []; public bool Signaled => signaled; public Task WaitAsync(CancellationToken cancellationToken = default) @@ -49,7 +49,7 @@ public sealed class AsyncAutoResetEvent(bool signaled = false) } if (_taskCompletionSources.Count == 0) return; - + signaled = false; foreach (var tcs in _taskCompletionSources.ToList()) { diff --git a/Iceshrimp.Backend/Core/Helpers/FilterHelper.cs b/Iceshrimp.Backend/Core/Helpers/FilterHelper.cs index edde3aa2..07780382 100644 --- a/Iceshrimp.Backend/Core/Helpers/FilterHelper.cs +++ b/Iceshrimp.Backend/Core/Helpers/FilterHelper.cs @@ -77,7 +77,7 @@ public static class FilterHelper return keyword; } else if ((note.Text != null && note.Text.Contains(keyword, StringComparison.InvariantCultureIgnoreCase)) || - note.Cw != null && note.Cw.Contains(keyword, StringComparison.InvariantCultureIgnoreCase)) + (note.Cw != null && note.Cw.Contains(keyword, StringComparison.InvariantCultureIgnoreCase))) { return keyword; } diff --git a/Iceshrimp.Backend/Core/Helpers/LibMfm/Conversion/MfmConverter.cs b/Iceshrimp.Backend/Core/Helpers/LibMfm/Conversion/MfmConverter.cs index 5e83f26a..ff24da38 100644 --- a/Iceshrimp.Backend/Core/Helpers/LibMfm/Conversion/MfmConverter.cs +++ b/Iceshrimp.Backend/Core/Helpers/LibMfm/Conversion/MfmConverter.cs @@ -8,9 +8,9 @@ using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Helpers.LibMfm.Parsing; -using static Iceshrimp.Parsing.MfmNodeTypes; using Microsoft.Extensions.Options; using Microsoft.FSharp.Collections; +using static Iceshrimp.Parsing.MfmNodeTypes; using MfmHtmlParser = Iceshrimp.Backend.Core.Helpers.LibMfm.Parsing.HtmlParser; using HtmlParser = AngleSharp.Html.Parser.HtmlParser; diff --git a/Iceshrimp.Backend/Core/Helpers/NoteThreadHelpers.cs b/Iceshrimp.Backend/Core/Helpers/NoteThreadHelpers.cs index 3c333984..6e563b7d 100644 --- a/Iceshrimp.Backend/Core/Helpers/NoteThreadHelpers.cs +++ b/Iceshrimp.Backend/Core/Helpers/NoteThreadHelpers.cs @@ -6,13 +6,6 @@ namespace Iceshrimp.Backend.Core.Helpers; public static class NoteThreadHelpers { - public class TreeNode(T self) - { - public readonly T Self = self; - public List> Descendants = []; - public TreeNode? Parent; - } - public static List OrderAncestors(this List notes) { var final = new List(); @@ -139,4 +132,11 @@ public static class NoteThreadHelpers return nodes; } + + public class TreeNode(T self) + { + public readonly T Self = self; + public List> Descendants = []; + public TreeNode? Parent; + } } \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Helpers/WriteLockingList.cs b/Iceshrimp.Backend/Core/Helpers/WriteLockingList.cs index a75f42b0..31ba95be 100644 --- a/Iceshrimp.Backend/Core/Helpers/WriteLockingList.cs +++ b/Iceshrimp.Backend/Core/Helpers/WriteLockingList.cs @@ -17,6 +17,23 @@ public class WriteLockingList(IEnumerable? sourceCollection = null) : ICol lock (_list) _list.Add(item); } + public void Clear() + { + lock (_list) _list.Clear(); + } + + public bool Contains(T item) => _list.Contains(item); + + public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex); + + public bool Remove(T item) + { + lock (_list) return _list.Remove(item); + } + + public int Count => _list.Count; + public bool IsReadOnly => ((ICollection)_list).IsReadOnly; + public bool AddIfMissing(T item) { lock (_list) @@ -32,25 +49,8 @@ public class WriteLockingList(IEnumerable? sourceCollection = null) : ICol lock (_list) _list.AddRange(item); } - public void Clear() - { - lock (_list) _list.Clear(); - } - - public bool Contains(T item) => _list.Contains(item); - - public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex); - - public bool Remove(T item) - { - lock (_list) return _list.Remove(item); - } - public int RemoveAll(Predicate predicate) { lock (_list) return _list.RemoveAll(predicate); } - - public int Count => _list.Count; - public bool IsReadOnly => ((ICollection)_list).IsReadOnly; } \ No newline at end of file diff --git a/Iceshrimp.Backend/Core/Middleware/AuthorizedFetchMiddleware.cs b/Iceshrimp.Backend/Core/Middleware/AuthorizedFetchMiddleware.cs index 503bfa58..c9ceacb8 100644 --- a/Iceshrimp.Backend/Core/Middleware/AuthorizedFetchMiddleware.cs +++ b/Iceshrimp.Backend/Core/Middleware/AuthorizedFetchMiddleware.cs @@ -93,7 +93,7 @@ public class AuthorizedFetchMiddleware( suppressLog: true); List headers = ["(request-target)", "host"]; - + if (sig.Created != null && !sig.Headers.Contains("date")) headers.Add("(created)"); else diff --git a/Iceshrimp.Backend/Core/Middleware/ErrorHandlerMiddleware.cs b/Iceshrimp.Backend/Core/Middleware/ErrorHandlerMiddleware.cs index 3703eb8d..9dff8dfc 100644 --- a/Iceshrimp.Backend/Core/Middleware/ErrorHandlerMiddleware.cs +++ b/Iceshrimp.Backend/Core/Middleware/ErrorHandlerMiddleware.cs @@ -2,8 +2,8 @@ using System.Diagnostics.CodeAnalysis; using System.Net; using Iceshrimp.Backend.Controllers.Mastodon.Attributes; using Iceshrimp.Backend.Controllers.Mastodon.Schemas; -using Iceshrimp.Shared.Schemas; using Iceshrimp.Backend.Core.Configuration; +using Iceshrimp.Shared.Schemas; using Microsoft.Extensions.Options; namespace Iceshrimp.Backend.Core.Middleware; diff --git a/Iceshrimp.Backend/Core/Queues/BackgroundTaskQueue.cs b/Iceshrimp.Backend/Core/Queues/BackgroundTaskQueue.cs index 16d6f93c..06ecf45c 100644 --- a/Iceshrimp.Backend/Core/Queues/BackgroundTaskQueue.cs +++ b/Iceshrimp.Backend/Core/Queues/BackgroundTaskQueue.cs @@ -70,7 +70,7 @@ public class BackgroundTaskQueue(int parallelism) await db.DriveFiles.AnyAsync(p => p.Id != file.Id && p.AccessKey == file.AccessKey && !p.IsLink, - cancellationToken: token); + token); if (!deduplicated) { @@ -128,7 +128,7 @@ public class BackgroundTaskQueue(int parallelism) if (file.AccessKey == null) return; var deduplicated = await db.DriveFiles.AnyAsync(p => p.Id != file.Id && p.AccessKey == file.AccessKey && !p.IsLink, - cancellationToken: token); + token); if (deduplicated) return; @@ -267,7 +267,7 @@ public class BackgroundTaskQueue(int parallelism) var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(user); await bgDb.Instances.Where(p => p.Id == dbInstance.Id) .ExecuteUpdateAsync(p => p.SetProperty(i => i.UsersCount, i => i.UsersCount - 1), - cancellationToken: token); + token); }); logger.LogDebug("User {id} deleted successfully", jobData.UserId); diff --git a/Iceshrimp.Backend/Core/Services/CustomHttpClient.cs b/Iceshrimp.Backend/Core/Services/CustomHttpClient.cs index fd64fb10..d2d0a5ac 100644 --- a/Iceshrimp.Backend/Core/Services/CustomHttpClient.cs +++ b/Iceshrimp.Backend/Core/Services/CustomHttpClient.cs @@ -208,15 +208,15 @@ public class CustomHttpClient : HttpClient private class RedirectHandler : DelegatingHandler { - private int MaxAutomaticRedirections { get; set; } - private bool InitialAutoRedirect { get; set; } - public RedirectHandler(HttpMessageHandler innerHandler) : base(innerHandler) { var mostInnerHandler = innerHandler.GetMostInnerHandler(); SetupCustomAutoRedirect(mostInnerHandler); } + private int MaxAutomaticRedirections { get; set; } + private bool InitialAutoRedirect { get; set; } + private void SetupCustomAutoRedirect(HttpMessageHandler? mostInnerHandler) { //Store the initial auto-redirect & max-auto-redirect values. diff --git a/Iceshrimp.Backend/Core/Services/ImageProcessor.cs b/Iceshrimp.Backend/Core/Services/ImageProcessor.cs index ff833d9b..c1570784 100644 --- a/Iceshrimp.Backend/Core/Services/ImageProcessor.cs +++ b/Iceshrimp.Backend/Core/Services/ImageProcessor.cs @@ -73,11 +73,11 @@ public class ImageProcessor public class Result { - public string? Blurhash; - public Func? RenderThumbnail; - public Func? RenderWebpublic; + public string? Blurhash; public required DriveFile.FileProperties Properties; + public Func? RenderThumbnail; + public Func? RenderWebpublic; } public async Task ProcessImage(Stream data, DriveFileCreationRequest request, bool genThumb, bool genWebp) @@ -218,7 +218,7 @@ public class ImageProcessor ) { var properties = new DriveFile.FileProperties { Width = ident.Size.Width, Height = ident.Size.Height }; - var res = new Result { Properties = properties }; + var res = new Result { Properties = properties }; // Calculate blurhash using a x200px image for improved performance using var blurhashImageSource = @@ -229,7 +229,7 @@ public class ImageProcessor var blurBuf = blurhashImage.WriteToMemory(); var blurArr = new Pixel[blurhashImage.Width, blurhashImage.Height]; - var idx = 0; + var idx = 0; var incr = blurhashImage.Bands - 3; for (var i = 0; i < blurhashImage.Height; i++) { diff --git a/Iceshrimp.Backend/Core/Services/InstanceService.cs b/Iceshrimp.Backend/Core/Services/InstanceService.cs index 32c66c16..8b729569 100644 --- a/Iceshrimp.Backend/Core/Services/InstanceService.cs +++ b/Iceshrimp.Backend/Core/Services/InstanceService.cs @@ -21,7 +21,7 @@ public class InstanceService(DatabaseContext db, HttpClient httpClient, ILogger< logger.LogDebug("Updating instance metadata for {host}", host); else logger.LogDebug("Updating instance metadata for {host} ({domain})", host, webDomain); - + host = host.ToLowerInvariant(); var instance = await db.Instances.FirstOrDefaultAsync(p => p.Host == host); if (instance == null) diff --git a/Iceshrimp.Backend/Core/Services/MetaService.cs b/Iceshrimp.Backend/Core/Services/MetaService.cs index ebe0129d..1a5f7447 100644 --- a/Iceshrimp.Backend/Core/Services/MetaService.cs +++ b/Iceshrimp.Backend/Core/Services/MetaService.cs @@ -65,7 +65,7 @@ public class MetaService([FromKeyedServices("cache")] DatabaseContext db) { await db.MetaStore.Upsert(new MetaStoreEntry { Key = key, Value = value }) .On(p => p.Key) - .WhenMatched((_, orig) => new MetaStoreEntry { Value = orig.Value, }) + .WhenMatched((_, orig) => new MetaStoreEntry { Value = orig.Value }) .RunAsync(); } } diff --git a/Iceshrimp.Backend/Core/Services/NoteService.cs b/Iceshrimp.Backend/Core/Services/NoteService.cs index c2e81147..2718da8c 100644 --- a/Iceshrimp.Backend/Core/Services/NoteService.cs +++ b/Iceshrimp.Backend/Core/Services/NoteService.cs @@ -9,11 +9,11 @@ using Iceshrimp.Backend.Core.Helpers; using Iceshrimp.Backend.Core.Helpers.LibMfm.Conversion; using Iceshrimp.Backend.Core.Helpers.LibMfm.Parsing; using Iceshrimp.Backend.Core.Helpers.LibMfm.Serialization; -using static Iceshrimp.Parsing.MfmNodeTypes; using Iceshrimp.Backend.Core.Middleware; using Iceshrimp.Backend.Core.Queues; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; +using static Iceshrimp.Parsing.MfmNodeTypes; namespace Iceshrimp.Backend.Core.Services; @@ -48,9 +48,7 @@ public class NoteService( ActivityPub.FederationControlService fedCtrlSvc ) { - private const int DefaultRecursionLimit = 100; - private readonly List _resolverHistory = []; - private int _recursionLimit = DefaultRecursionLimit; + private const int DefaultRecursionLimit = 100; private static readonly AsyncKeyedLocker KeyedLocker = new(o => { @@ -58,6 +56,9 @@ public class NoteService( o.PoolInitialFill = 5; }); + private readonly List _resolverHistory = []; + private int _recursionLimit = DefaultRecursionLimit; + public async Task CreateNoteAsync( User user, Note.NoteVisibility visibility, string? text = null, string? cw = null, Note? reply = null, Note? renote = null, IReadOnlyCollection? attachments = null, Poll? poll = null, @@ -632,7 +633,8 @@ public class NoteService( note.Visibility, note.User.GetPublicUri(config.Value) + "/followers")) - : ActivityPub.ActivityRenderer.RenderDelete(actor, new ASTombstone { Id = note.GetPublicUri(config.Value) }); + : ActivityPub.ActivityRenderer.RenderDelete(actor, + new ASTombstone { Id = note.GetPublicUri(config.Value) }); if (note.Visibility == Note.NoteVisibility.Specified) await deliverSvc.DeliverToAsync(activity, note.User, recipients.ToArray()); diff --git a/Iceshrimp.Backend/Core/Services/ObjectStorageService.cs b/Iceshrimp.Backend/Core/Services/ObjectStorageService.cs index 351b9fc9..ef45b29d 100644 --- a/Iceshrimp.Backend/Core/Services/ObjectStorageService.cs +++ b/Iceshrimp.Backend/Core/Services/ObjectStorageService.cs @@ -14,14 +14,14 @@ public class ObjectStorageService(IOptions config, HttpCl { private readonly string? _accessUrl = config.Value.ObjectStorage?.AccessUrl; - private readonly S3Bucket? _bucket = GetBucketSafely(config); - - private readonly string? _prefix = config.Value.ObjectStorage?.Prefix?.Trim('/'); - private readonly IReadOnlyDictionary? _acl = config.Value.ObjectStorage?.SetAcl != null ? new Dictionary { { "x-amz-acl", config.Value.ObjectStorage.SetAcl } }.AsReadOnly() : null; + private readonly S3Bucket? _bucket = GetBucketSafely(config); + + private readonly string? _prefix = config.Value.ObjectStorage?.Prefix?.Trim('/'); + private static S3Bucket? GetBucketSafely(IOptions config) { if (config.Value.Provider != Enums.FileStorage.Local) return GetBucket(config); diff --git a/Iceshrimp.Backend/Core/Services/PushService.cs b/Iceshrimp.Backend/Core/Services/PushService.cs index 3ef2d718..1f9e4841 100644 --- a/Iceshrimp.Backend/Core/Services/PushService.cs +++ b/Iceshrimp.Backend/Core/Services/PushService.cs @@ -8,9 +8,9 @@ using Iceshrimp.Backend.Core.Database; using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Middleware; +using Iceshrimp.WebPush; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; -using Iceshrimp.WebPush; using PushSubscription = Iceshrimp.Backend.Core.Database.Tables.PushSubscription; using WebPushSubscription = Iceshrimp.WebPush.PushSubscription; diff --git a/Iceshrimp.Backend/Core/Services/QueueService.cs b/Iceshrimp.Backend/Core/Services/QueueService.cs index f322422c..c9178cf3 100644 --- a/Iceshrimp.Backend/Core/Services/QueueService.cs +++ b/Iceshrimp.Backend/Core/Services/QueueService.cs @@ -21,15 +21,15 @@ public class QueueService( IOptions queueConcurrency ) : BackgroundService { - private readonly List _queues = []; + private readonly List _queues = []; + public readonly BackgroundTaskQueue BackgroundTaskQueue = new(queueConcurrency.Value.BackgroundTask); + public readonly DeliverQueue DeliverQueue = new(queueConcurrency.Value.Deliver); + + public readonly InboxQueue InboxQueue = new(queueConcurrency.Value.Inbox); + public readonly PreDeliverQueue PreDeliverQueue = new(queueConcurrency.Value.PreDeliver); public IEnumerable QueueNames => _queues.Select(p => p.Name); - public readonly InboxQueue InboxQueue = new(queueConcurrency.Value.Inbox); - public readonly DeliverQueue DeliverQueue = new(queueConcurrency.Value.Deliver); - public readonly PreDeliverQueue PreDeliverQueue = new(queueConcurrency.Value.PreDeliver); - public readonly BackgroundTaskQueue BackgroundTaskQueue = new(queueConcurrency.Value.BackgroundTask); - private static async Task GetNpgsqlConnection(IServiceScope scope) { var config = scope.ServiceProvider.GetRequiredService>(); @@ -263,13 +263,13 @@ public interface IPostgresJobQueue { public string Name { get; } + public TimeSpan Timeout { get; } + public Task ExecuteAsync(IServiceScopeFactory scopeFactory, CancellationToken token, CancellationToken queueToken); public Task RecoverOrPrepareForExitAsync(); public void RaiseJobQueuedEvent(); public void RaiseJobDelayedEvent(); - - public TimeSpan Timeout { get; } } public class PostgresJobQueue( @@ -279,14 +279,13 @@ public class PostgresJobQueue( TimeSpan timeout ) : IPostgresJobQueue where T : class { - public string Name => name; - public TimeSpan Timeout => timeout; - private readonly AsyncAutoResetEvent _delayedChannel = new(); private readonly AsyncAutoResetEvent _queuedChannel = new(); - private IServiceScopeFactory _scopeFactory = null!; private ILogger _logger = null!; + private IServiceScopeFactory _scopeFactory = null!; private string? _workerId; + public string Name => name; + public TimeSpan Timeout => timeout; public void RaiseJobQueuedEvent() => QueuedChannelEvent?.Invoke(null, EventArgs.Empty); public void RaiseJobDelayedEvent() => DelayedChannelEvent?.Invoke(null, EventArgs.Empty); diff --git a/Iceshrimp.Backend/Core/Services/StreamingService.cs b/Iceshrimp.Backend/Core/Services/StreamingService.cs index c77c487a..be7f50dc 100644 --- a/Iceshrimp.Backend/Core/Services/StreamingService.cs +++ b/Iceshrimp.Backend/Core/Services/StreamingService.cs @@ -12,20 +12,17 @@ namespace Iceshrimp.Backend.Core.Services; public sealed class StreamingService { - private readonly ConcurrentDictionary _connections = []; - private readonly IHubContext _hub; - private readonly EventService _eventSvc; - private readonly IServiceScopeFactory _scopeFactory; - private readonly ILogger _logger; - private static readonly AsyncKeyedLocker Locker = new(o => { o.PoolSize = 100; o.PoolInitialFill = 5; }); - public event EventHandler<(Note note, Func> rendered)>? NotePublished; - public event EventHandler<(Note note, Func> rendered)>? NoteUpdated; + private readonly ConcurrentDictionary _connections = []; + private readonly EventService _eventSvc; + private readonly IHubContext _hub; + private readonly ILogger _logger; + private readonly IServiceScopeFactory _scopeFactory; public StreamingService( IHubContext hub, @@ -43,6 +40,9 @@ public sealed class StreamingService eventSvc.NoteUpdated += OnNoteUpdated; } + public event EventHandler<(Note note, Func> rendered)>? NotePublished; + public event EventHandler<(Note note, Func> rendered)>? NoteUpdated; + public void Connect(string userId, User user, string connectionId) { _connections diff --git a/Iceshrimp.Backend/Core/Services/UserProfileMentionsResolver.cs b/Iceshrimp.Backend/Core/Services/UserProfileMentionsResolver.cs index d819d75a..9b0b92f6 100644 --- a/Iceshrimp.Backend/Core/Services/UserProfileMentionsResolver.cs +++ b/Iceshrimp.Backend/Core/Services/UserProfileMentionsResolver.cs @@ -5,8 +5,8 @@ using Iceshrimp.Backend.Core.Extensions; using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; using Iceshrimp.Backend.Core.Helpers.LibMfm.Conversion; using Iceshrimp.Backend.Core.Helpers.LibMfm.Parsing; -using static Iceshrimp.Parsing.MfmNodeTypes; using Microsoft.Extensions.Options; +using static Iceshrimp.Parsing.MfmNodeTypes; namespace Iceshrimp.Backend.Core.Services; diff --git a/Iceshrimp.Backend/Core/Services/UserService.cs b/Iceshrimp.Backend/Core/Services/UserService.cs index 4557861b..f7b42394 100644 --- a/Iceshrimp.Backend/Core/Services/UserService.cs +++ b/Iceshrimp.Backend/Core/Services/UserService.cs @@ -166,7 +166,7 @@ public class UserService( //TODO: FollowersCount //TODO: FollowingCount Emojis = emoji.Select(p => p.Id).ToList(), - Tags = tags, + Tags = tags }; var profile = new UserProfile diff --git a/Iceshrimp.Backend/Hubs/ExampleHub.cs b/Iceshrimp.Backend/Hubs/ExampleHub.cs index 52b27715..614cb7ed 100644 --- a/Iceshrimp.Backend/Hubs/ExampleHub.cs +++ b/Iceshrimp.Backend/Hubs/ExampleHub.cs @@ -1,5 +1,6 @@ using Iceshrimp.Shared.HubSchemas; using Microsoft.AspNetCore.SignalR; + namespace Iceshrimp.Backend.Hubs; public class ExampleHub : Hub, IExampleHubServer diff --git a/Iceshrimp.Backend/Hubs/Helpers/StreamingConnectionAggregate.cs b/Iceshrimp.Backend/Hubs/Helpers/StreamingConnectionAggregate.cs index 919f8fd3..3d3c52fe 100644 --- a/Iceshrimp.Backend/Hubs/Helpers/StreamingConnectionAggregate.cs +++ b/Iceshrimp.Backend/Hubs/Helpers/StreamingConnectionAggregate.cs @@ -18,114 +18,49 @@ namespace Iceshrimp.Backend.Hubs.Helpers; [MustDisposeResource] public sealed class StreamingConnectionAggregate : IDisposable { - private readonly User _user; - private readonly string _userId; + private readonly WriteLockingList _blockedBy = []; + private readonly WriteLockingList _blocking = []; private readonly WriteLockingList _connectionIds = []; + private readonly EventService _eventService; + + private readonly WriteLockingList _following = []; + private readonly IHubContext _hub; - - private readonly EventService _eventService; - private readonly IServiceScope _scope; - private readonly IServiceScopeFactory _scopeFactory; - private readonly StreamingService _streamingService; - private readonly ILogger _logger; - - private readonly WriteLockingList _following = []; - private readonly WriteLockingList _muting = []; - private readonly WriteLockingList _blocking = []; - private readonly WriteLockingList _blockedBy = []; - private List _hiddenFromHome = []; + private readonly ILogger _logger; + private readonly WriteLockingList _muting = []; + private readonly IServiceScope _scope; + private readonly IServiceScopeFactory _scopeFactory; + private readonly StreamingService _streamingService; private readonly ConcurrentDictionary> _subscriptions = []; + private readonly User _user; + private readonly string _userId; + private List _hiddenFromHome = []; public bool HasSubscribers => _connectionIds.Count != 0; + #region Destruction + + public void Dispose() + { + DisconnectAll(); + _streamingService.NotePublished -= OnNotePublished; + _streamingService.NoteUpdated -= OnNoteUpdated; + _eventService.Notification -= OnNotification; + _eventService.UserBlocked -= OnUserBlock; + _eventService.UserUnblocked -= OnUserUnblock; + _eventService.UserMuted -= OnUserMute; + _eventService.UserUnmuted -= OnUserUnmute; + _eventService.UserFollowed -= OnUserFollow; + _eventService.UserUnfollowed -= OnUserUnfollow; + _scope.Dispose(); + } + + #endregion + private AsyncServiceScope GetTempScope() => _scopeFactory.CreateAsyncScope(); - #region Initialization - - public StreamingConnectionAggregate( - string userId, - User user, - IHubContext hub, - EventService eventSvc, - IServiceScopeFactory scopeFactory, StreamingService streamingService - ) - { - if (userId != user.Id) - throw new Exception("userId doesn't match user.Id"); - - _userId = userId; - _user = user; - _hub = hub; - _eventService = eventSvc; - _scope = scopeFactory.CreateScope(); - _scopeFactory = scopeFactory; - _streamingService = streamingService; - _logger = _scope.ServiceProvider.GetRequiredService>(); - - _ = InitializeAsync(); - } - - private async Task InitializeAsync() - { - _eventService.UserBlocked += OnUserBlock; - _eventService.UserUnblocked += OnUserUnblock; - _eventService.UserMuted += OnUserMute; - _eventService.UserUnmuted += OnUserUnmute; - _eventService.UserFollowed += OnUserFollow; - _eventService.UserUnfollowed += OnUserUnfollow; - - await InitializeRelationships(); - - _eventService.Notification += OnNotification; - _streamingService.NotePublished += OnNotePublished; - _streamingService.NoteUpdated += OnNoteUpdated; - } - - private async Task InitializeRelationships() - { - await using var scope = GetTempScope(); - await using var db = scope.ServiceProvider.GetRequiredService(); - _following.AddRange(await db.Followings.Where(p => p.Follower == _user) - .Select(p => p.FolloweeId) - .ToListAsync()); - _blocking.AddRange(await db.Blockings.Where(p => p.Blocker == _user) - .Select(p => p.BlockeeId) - .ToListAsync()); - _blockedBy.AddRange(await db.Blockings.Where(p => p.Blockee == _user) - .Select(p => p.BlockerId) - .ToListAsync()); - _muting.AddRange(await db.Mutings.Where(p => p.Muter == _user) - .Select(p => p.MuteeId) - .ToListAsync()); - - _hiddenFromHome = await db.UserListMembers - .Where(p => p.UserList.User == _user && p.UserList.HideFromHomeTl) - .Select(p => p.UserId) - .Distinct() - .ToListAsync(); - } - - #endregion - - #region Channel subscription handlers - - public void Subscribe(string connectionId, StreamingTimeline timeline) - { - if (!_connectionIds.Contains(connectionId)) return; - _subscriptions.GetOrAdd(connectionId, []).Add(timeline); - } - - public void Unsubscribe(string connectionId, StreamingTimeline timeline) - { - if (!_connectionIds.Contains(connectionId)) return; - _subscriptions.TryGetValue(connectionId, out var collection); - collection?.Remove(timeline); - } - - #endregion - private async void OnNotification(object? _, Notification notification) { try @@ -228,13 +163,6 @@ public sealed class StreamingConnectionAggregate : IDisposable return wrapped; } - private class NoteWithVisibilities(Note note) - { - public readonly Note Note = note; - public Note? Reply = note.Reply; - public Note? Renote = note.Renote; - } - private (List connectionIds, List timelines) FindRecipients(Note note) { List timelines = []; @@ -260,6 +188,97 @@ public sealed class StreamingConnectionAggregate : IDisposable return (connectionIds, timelines); } + private class NoteWithVisibilities(Note note) + { + public readonly Note Note = note; + public Note? Renote = note.Renote; + public Note? Reply = note.Reply; + } + + #region Initialization + + public StreamingConnectionAggregate( + string userId, + User user, + IHubContext hub, + EventService eventSvc, + IServiceScopeFactory scopeFactory, StreamingService streamingService + ) + { + if (userId != user.Id) + throw new Exception("userId doesn't match user.Id"); + + _userId = userId; + _user = user; + _hub = hub; + _eventService = eventSvc; + _scope = scopeFactory.CreateScope(); + _scopeFactory = scopeFactory; + _streamingService = streamingService; + _logger = _scope.ServiceProvider.GetRequiredService>(); + + _ = InitializeAsync(); + } + + private async Task InitializeAsync() + { + _eventService.UserBlocked += OnUserBlock; + _eventService.UserUnblocked += OnUserUnblock; + _eventService.UserMuted += OnUserMute; + _eventService.UserUnmuted += OnUserUnmute; + _eventService.UserFollowed += OnUserFollow; + _eventService.UserUnfollowed += OnUserUnfollow; + + await InitializeRelationships(); + + _eventService.Notification += OnNotification; + _streamingService.NotePublished += OnNotePublished; + _streamingService.NoteUpdated += OnNoteUpdated; + } + + private async Task InitializeRelationships() + { + await using var scope = GetTempScope(); + await using var db = scope.ServiceProvider.GetRequiredService(); + _following.AddRange(await db.Followings.Where(p => p.Follower == _user) + .Select(p => p.FolloweeId) + .ToListAsync()); + _blocking.AddRange(await db.Blockings.Where(p => p.Blocker == _user) + .Select(p => p.BlockeeId) + .ToListAsync()); + _blockedBy.AddRange(await db.Blockings.Where(p => p.Blockee == _user) + .Select(p => p.BlockerId) + .ToListAsync()); + _muting.AddRange(await db.Mutings.Where(p => p.Muter == _user) + .Select(p => p.MuteeId) + .ToListAsync()); + + _hiddenFromHome = await db.UserListMembers + .Where(p => p.UserList.User == _user && p.UserList.HideFromHomeTl) + .Select(p => p.UserId) + .Distinct() + .ToListAsync(); + } + + #endregion + + #region Channel subscription handlers + + public void Subscribe(string connectionId, StreamingTimeline timeline) + { + if (!_connectionIds.Contains(connectionId)) return; + _subscriptions.GetOrAdd(connectionId, []).Add(timeline); + } + + public void Unsubscribe(string connectionId, StreamingTimeline timeline) + { + if (!_connectionIds.Contains(connectionId)) return; + _subscriptions.TryGetValue(connectionId, out var collection); + collection?.Remove(timeline); + } + + #endregion + #region Relationship change event handlers private void OnUserBlock(object? _, UserInteraction interaction) @@ -373,23 +392,4 @@ public sealed class StreamingConnectionAggregate : IDisposable } #endregion - - #region Destruction - - public void Dispose() - { - DisconnectAll(); - _streamingService.NotePublished -= OnNotePublished; - _streamingService.NoteUpdated -= OnNoteUpdated; - _eventService.Notification -= OnNotification; - _eventService.UserBlocked -= OnUserBlock; - _eventService.UserUnblocked -= OnUserUnblock; - _eventService.UserMuted -= OnUserMute; - _eventService.UserUnmuted -= OnUserUnmute; - _eventService.UserFollowed -= OnUserFollow; - _eventService.UserUnfollowed -= OnUserUnfollow; - _scope.Dispose(); - } - - #endregion } \ No newline at end of file diff --git a/Iceshrimp.Backend/Iceshrimp.Backend.csproj b/Iceshrimp.Backend/Iceshrimp.Backend.csproj index 59910931..9771e169 100644 --- a/Iceshrimp.Backend/Iceshrimp.Backend.csproj +++ b/Iceshrimp.Backend/Iceshrimp.Backend.csproj @@ -14,8 +14,8 @@ - - + + @@ -25,63 +25,63 @@ - - - + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - + + + + + + + + + + - + $(DefineConstants);EnableLibVips - + - + - + - + Never @@ -95,14 +95,14 @@ - + - - - + + + diff --git a/Iceshrimp.Backend/Pages/Index.cshtml b/Iceshrimp.Backend/Pages/Index.cshtml index 4d362257..ddb902f3 100644 --- a/Iceshrimp.Backend/Pages/Index.cshtml +++ b/Iceshrimp.Backend/Pages/Index.cshtml @@ -1,5 +1,5 @@ @page "/" -@model Iceshrimp.Backend.Pages.IndexModel +@model IndexModel @{ ViewData["title"] = $"Home - {Model.InstanceName}"; diff --git a/Iceshrimp.Backend/Pages/Index.cshtml.cs b/Iceshrimp.Backend/Pages/Index.cshtml.cs index 033f9f16..46f627cd 100644 --- a/Iceshrimp.Backend/Pages/Index.cshtml.cs +++ b/Iceshrimp.Backend/Pages/Index.cshtml.cs @@ -7,9 +7,9 @@ namespace Iceshrimp.Backend.Pages; public class IndexModel(MetaService meta) : PageModel { - public string InstanceName = null!; - public string InstanceDescription = null!; public string? ContactEmail; + public string InstanceDescription = null!; + public string InstanceName = null!; public async Task OnGet() { diff --git a/Iceshrimp.Backend/Pages/Note.cshtml b/Iceshrimp.Backend/Pages/Note.cshtml index 8f702adf..7ee7831e 100644 --- a/Iceshrimp.Backend/Pages/Note.cshtml +++ b/Iceshrimp.Backend/Pages/Note.cshtml @@ -1,7 +1,7 @@ @page "/notes/{id}" @using Iceshrimp.Backend.Core.Database.Tables @using Iceshrimp.Backend.Core.Extensions -@model Iceshrimp.Backend.Pages.NoteModel +@model NoteModel @if (Model.Note == null) { diff --git a/Iceshrimp.Backend/Pages/Note.cshtml.cs b/Iceshrimp.Backend/Pages/Note.cshtml.cs index ebfbd0c9..d39d6f9e 100644 --- a/Iceshrimp.Backend/Pages/Note.cshtml.cs +++ b/Iceshrimp.Backend/Pages/Note.cshtml.cs @@ -19,13 +19,13 @@ public class NoteModel( MfmConverter mfmConverter ) : PageModel { + public Dictionary> MediaAttachments = new(); public Note? Note; public string? QuoteUrl; - public Dictionary TextContent = new(); - public Dictionary> MediaAttachments = new(); - public bool ShowMedia = security.Value.PublicPreview > Enums.PublicPreview.RestrictedNoMedia; - public bool ShowRemoteReplies = security.Value.PublicPreview > Enums.PublicPreview.Restricted; + public bool ShowMedia = security.Value.PublicPreview > Enums.PublicPreview.RestrictedNoMedia; + public bool ShowRemoteReplies = security.Value.PublicPreview > Enums.PublicPreview.Restricted; + public Dictionary TextContent = new(); [SuppressMessage("ReSharper", "EntityFramework.NPlusOne.IncompleteDataQuery", Justification = "IncludeCommonProperties")] diff --git a/Iceshrimp.Backend/Pages/Note.cshtml.css b/Iceshrimp.Backend/Pages/Note.cshtml.css index dcb1a866..ef1255ae 100644 --- a/Iceshrimp.Backend/Pages/Note.cshtml.css +++ b/Iceshrimp.Backend/Pages/Note.cshtml.css @@ -24,6 +24,7 @@ width: 3em; max-height: 3em; } + .title { grid-column: 2/-1; grid-row: 1; @@ -31,6 +32,7 @@ color: var(--text-bright); font-weight: 600; } + .acct { grid-column: 2/-1; grid-row: 2; diff --git a/Iceshrimp.Backend/Pages/Queue.cshtml b/Iceshrimp.Backend/Pages/Queue.cshtml index 1840248d..97ee97bf 100644 --- a/Iceshrimp.Backend/Pages/Queue.cshtml +++ b/Iceshrimp.Backend/Pages/Queue.cshtml @@ -1,8 +1,8 @@ @page "/queue/{queue?}/{pagination:int?}/{status?}" +@inject QueueService QueueSvc @using Iceshrimp.Backend.Core.Database.Tables @using Iceshrimp.Backend.Core.Extensions @using Iceshrimp.Backend.Core.Services -@inject QueueService QueueSvc @model QueueModel @{ diff --git a/Iceshrimp.Backend/Pages/Queue.cshtml.cs b/Iceshrimp.Backend/Pages/Queue.cshtml.cs index 8d54828f..c0aa0bac 100644 --- a/Iceshrimp.Backend/Pages/Queue.cshtml.cs +++ b/Iceshrimp.Backend/Pages/Queue.cshtml.cs @@ -10,15 +10,15 @@ namespace Iceshrimp.Backend.Pages; public class QueueModel(DatabaseContext db, QueueService queueSvc) : PageModel { - public List Jobs = []; - public string? Queue; + public int? DelayedCount; public Job.JobStatus? Filter; - public int? TotalCount; + public List Jobs = []; + public int? NextPage; + public int? PrevPage; + public string? Queue; public int? QueuedCount; public int? RunningCount; - public int? DelayedCount; - public int? PrevPage; - public int? NextPage; + public int? TotalCount; public async Task OnGet( [FromRoute] string? queue, [FromRoute(Name = "pagination")] int? page, [FromRoute] string? status @@ -51,7 +51,7 @@ public class QueueModel(DatabaseContext db, QueueService queueSvc) : PageModel .Skip((page.Value - 1) * 50) .Take(50) .ToListAsync(); - + if (Filter == null) { TotalCount = await db.Jobs.CountAsync(p => p.Queue == queue); diff --git a/Iceshrimp.Backend/Pages/QueueJob.cshtml b/Iceshrimp.Backend/Pages/QueueJob.cshtml index c856f2a0..4c4946f1 100644 --- a/Iceshrimp.Backend/Pages/QueueJob.cshtml +++ b/Iceshrimp.Backend/Pages/QueueJob.cshtml @@ -42,7 +42,9 @@ { Actions - Retry + + Retry + } @@ -161,4 +163,4 @@ } } - + \ No newline at end of file diff --git a/Iceshrimp.Backend/Pages/QueueJob.cshtml.cs b/Iceshrimp.Backend/Pages/QueueJob.cshtml.cs index f35c90da..f28a8c7e 100644 --- a/Iceshrimp.Backend/Pages/QueueJob.cshtml.cs +++ b/Iceshrimp.Backend/Pages/QueueJob.cshtml.cs @@ -9,8 +9,17 @@ namespace Iceshrimp.Backend.Pages; public class QueueJobModel(DatabaseContext db) : PageModel { + private static Dictionary _lookup = new() + { + { "inbox", "body" }, + { "deliver", "payload" }, + { "pre-deliver", "serializedActivity" } + }; + public Job Job = null!; + public Dictionary Lookup => _lookup; + public async Task OnGet([FromRoute] Guid id) { if (!Request.Cookies.TryGetValue("admin_session", out var cookie)) @@ -22,13 +31,4 @@ public class QueueJobModel(DatabaseContext db) : PageModel throw GracefulException.NotFound($"Job {id} not found"); return Page(); } - - private static Dictionary _lookup = new() - { - { "inbox", "body" }, - { "deliver", "payload" }, - { "pre-deliver", "serializedActivity" } - }; - - public Dictionary Lookup => _lookup; } \ No newline at end of file diff --git a/Iceshrimp.Backend/Pages/Shared/FrontendSPA.cshtml b/Iceshrimp.Backend/Pages/Shared/FrontendSPA.cshtml index 48e7b385..761e9ef5 100644 --- a/Iceshrimp.Backend/Pages/Shared/FrontendSPA.cshtml +++ b/Iceshrimp.Backend/Pages/Shared/FrontendSPA.cshtml @@ -1,7 +1,7 @@ @page @using Iceshrimp.Backend.Core.Configuration @using Microsoft.Extensions.Options -@inject IOptions Config +@inject IOptions Config @{ Layout = null; } @@ -46,4 +46,4 @@ -@* ReSharper restore Html.PathError *@ +@* ReSharper restore Html.PathError *@ \ No newline at end of file diff --git a/Iceshrimp.Backend/Pages/_ViewImports.cshtml b/Iceshrimp.Backend/Pages/_ViewImports.cshtml index bd862a99..8c8aa579 100644 --- a/Iceshrimp.Backend/Pages/_ViewImports.cshtml +++ b/Iceshrimp.Backend/Pages/_ViewImports.cshtml @@ -1,2 +1,2 @@ @namespace Iceshrimp.Backend.Pages -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers \ No newline at end of file