a fork of iceshrimp.net but a tweaked frontend to my personal liking. waow
fediverse social-media social iceshrimp fedi
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[backend] Code cleanup

+274 -209
+3 -1
Iceshrimp.Backend/Controllers/Federation/NodeInfoController.cs
··· 55 55 //FIXME Implement members 56 56 Users = new NodeInfoResponse.NodeInfoUsers 57 57 { 58 - Total = totalUsers, ActiveMonth = activeMonth, ActiveHalfYear = activeHalfYear 58 + Total = totalUsers, 59 + ActiveMonth = activeMonth, 60 + ActiveHalfYear = activeHalfYear 59 61 }, 60 62 LocalComments = 0, 61 63 LocalPosts = localPosts
+6 -6
Iceshrimp.Backend/Controllers/Federation/Schemas/HostMetaXmlResponse.cs
··· 6 6 [XmlRoot("XRD", Namespace = "http://docs.oasis-open.org/ns/xri/xrd-1.0", IsNullable = false)] 7 7 public class HostMetaXmlResponse() 8 8 { 9 + [XmlElement("Link")] public required HostMetaXmlResponseLink Link; 10 + 9 11 [SetsRequiredMembers] 10 12 public HostMetaXmlResponse(string webDomain) : this() => Link = new HostMetaXmlResponseLink(webDomain); 11 - 12 - [XmlElement("Link")] public required HostMetaXmlResponseLink Link; 13 13 } 14 14 15 15 public class HostMetaXmlResponseLink() 16 16 { 17 + [XmlAttribute("rel")] public string Rel = "lrdd"; 18 + [XmlAttribute("template")] public required string Template; 19 + [XmlAttribute("type")] public string Type = "application/xrd+xml"; 20 + 17 21 [SetsRequiredMembers] 18 22 public HostMetaXmlResponseLink(string webDomain) : this() => 19 23 Template = $"https://{webDomain}/.well-known/webfinger?resource={{uri}}"; 20 - 21 - [XmlAttribute("rel")] public string Rel = "lrdd"; 22 - [XmlAttribute("type")] public string Type = "application/xrd+xml"; 23 - [XmlAttribute("template")] public required string Template; 24 24 }
+3 -1
Iceshrimp.Backend/Controllers/Federation/WellKnownController.cs
··· 59 59 [ 60 60 new WebFingerLink 61 61 { 62 - Rel = "self", Type = "application/activity+json", Href = user.GetPublicUri(config.Value) 62 + Rel = "self", 63 + Type = "application/activity+json", 64 + Href = user.GetPublicUri(config.Value) 63 65 }, 64 66 new WebFingerLink 65 67 {
+25 -16
Iceshrimp.Backend/Controllers/Mastodon/AccountController.cs
··· 76 76 if (request.Fields?.Where(p => p is { Name: not null, Value: not null }).ToList() is { Count: > 0 } fields) 77 77 { 78 78 user.UserProfile.Fields = 79 - fields.Select(p => new UserProfile.Field { Name = p.Name!, Value = p.Value!, IsVerified = false }) 79 + fields.Select(p => new UserProfile.Field 80 + { 81 + Name = p.Name!, 82 + Value = p.Value!, 83 + IsVerified = false 84 + }) 80 85 .ToArray(); 81 86 } 82 87 ··· 87 92 { 88 93 var rq = new DriveFileCreationRequest 89 94 { 90 - Filename = request.Avatar.FileName, IsSensitive = false, MimeType = request.Avatar.ContentType 95 + Filename = request.Avatar.FileName, 96 + IsSensitive = false, 97 + MimeType = request.Avatar.ContentType 91 98 }; 92 99 var avatar = await driveSvc.StoreFile(request.Avatar.OpenReadStream(), user, rq); 93 100 user.Avatar = avatar; ··· 99 106 { 100 107 var rq = new DriveFileCreationRequest 101 108 { 102 - Filename = request.Banner.FileName, IsSensitive = false, MimeType = request.Banner.ContentType 109 + Filename = request.Banner.FileName, 110 + IsSensitive = false, 111 + MimeType = request.Banner.ContentType 103 112 }; 104 113 var banner = await driveSvc.StoreFile(request.Banner.OpenReadStream(), user, rq); 105 114 user.Banner = banner; ··· 248 257 249 258 return Ok(res); 250 259 } 251 - 260 + 252 261 [HttpPost("{id}/unmute")] 253 262 [Authorize("write:mutes")] 254 263 [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(RelationshipEntity))] ··· 271 280 272 281 return Ok(res); 273 282 } 274 - 283 + 275 284 [HttpPost("{id}/block")] 276 285 [Authorize("write:blocks")] 277 286 [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(RelationshipEntity))] ··· 282 291 throw GracefulException.BadRequest("You cannot block yourself"); 283 292 284 293 var blockee = await db.Users 285 - .Where(p => p.Id == id) 286 - .IncludeCommonProperties() 287 - .PrecomputeRelationshipData(user) 288 - .FirstOrDefaultAsync() ?? 289 - throw GracefulException.RecordNotFound(); 294 + .Where(p => p.Id == id) 295 + .IncludeCommonProperties() 296 + .PrecomputeRelationshipData(user) 297 + .FirstOrDefaultAsync() ?? 298 + throw GracefulException.RecordNotFound(); 290 299 291 300 await userSvc.BlockUserAsync(user, blockee); 292 301 ··· 294 303 295 304 return Ok(res); 296 305 } 297 - 306 + 298 307 [HttpPost("{id}/unblock")] 299 308 [Authorize("write:blocks")] 300 309 [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(RelationshipEntity))] ··· 305 314 throw GracefulException.BadRequest("You cannot unblock yourself"); 306 315 307 316 var blockee = await db.Users 308 - .Where(p => p.Id == id) 309 - .IncludeCommonProperties() 310 - .PrecomputeRelationshipData(user) 311 - .FirstOrDefaultAsync() ?? 312 - throw GracefulException.RecordNotFound(); 317 + .Where(p => p.Id == id) 318 + .IncludeCommonProperties() 319 + .PrecomputeRelationshipData(user) 320 + .FirstOrDefaultAsync() ?? 321 + throw GracefulException.RecordNotFound(); 313 322 314 323 await userSvc.UnblockUserAsync(user, blockee); 315 324
+2 -2
Iceshrimp.Backend/Controllers/Mastodon/ConversationsController.cs
··· 145 145 146 146 private class Conversation 147 147 { 148 - public required string Id { get; init; } 149 148 public required Note LastNote; 150 - public required List<User> Users; 151 149 public required bool Unread; 150 + public required List<User> Users; 151 + public required string Id { get; init; } 152 152 } 153 153 }
+1 -1
Iceshrimp.Backend/Controllers/Mastodon/InstanceController.cs
··· 71 71 72 72 return Ok(res); 73 73 } 74 - 74 + 75 75 [HttpGet("/api/v1/instance/translation_languages")] 76 76 [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Dictionary<string, IEnumerable<string>>))] 77 77 public IActionResult GetTranslationLanguages()
+24 -4
Iceshrimp.Backend/Controllers/Mastodon/ListController.cs
··· 34 34 35 35 var res = await db.UserLists 36 36 .Where(p => p.User == user) 37 - .Select(p => new ListEntity { Id = p.Id, Title = p.Name, Exclusive = p.HideFromHomeTl }) 37 + .Select(p => new ListEntity 38 + { 39 + Id = p.Id, 40 + Title = p.Name, 41 + Exclusive = p.HideFromHomeTl 42 + }) 38 43 .ToListAsync(); 39 44 40 45 return Ok(res); ··· 50 55 51 56 var res = await db.UserLists 52 57 .Where(p => p.User == user && p.Id == id) 53 - .Select(p => new ListEntity { Id = p.Id, Title = p.Name, Exclusive = p.HideFromHomeTl }) 58 + .Select(p => new ListEntity 59 + { 60 + Id = p.Id, 61 + Title = p.Name, 62 + Exclusive = p.HideFromHomeTl 63 + }) 54 64 .FirstOrDefaultAsync() ?? 55 65 throw GracefulException.RecordNotFound(); 56 66 ··· 79 89 await db.AddAsync(list); 80 90 await db.SaveChangesAsync(); 81 91 82 - var res = new ListEntity { Id = list.Id, Title = list.Name, Exclusive = list.HideFromHomeTl }; 92 + var res = new ListEntity 93 + { 94 + Id = list.Id, 95 + Title = list.Name, 96 + Exclusive = list.HideFromHomeTl 97 + }; 83 98 return Ok(res); 84 99 } 85 100 ··· 105 120 db.Update(list); 106 121 await db.SaveChangesAsync(); 107 122 108 - var res = new ListEntity { Id = list.Id, Title = list.Name, Exclusive = list.HideFromHomeTl }; 123 + var res = new ListEntity 124 + { 125 + Id = list.Id, 126 + Title = list.Name, 127 + Exclusive = list.HideFromHomeTl 128 + }; 109 129 return Ok(res); 110 130 } 111 131
+1 -1
Iceshrimp.Backend/Controllers/Mastodon/PushController.cs
··· 165 165 Status = sub.Types.Contains("status"), 166 166 Update = sub.Types.Contains("update"), 167 167 FollowRequest = sub.Types.Contains("follow_request") 168 - }, 168 + } 169 169 }; 170 170 } 171 171 }
+5 -5
Iceshrimp.Backend/Controllers/Mastodon/Renderers/NoteRenderer.cs
··· 273 273 public class NoteRendererDto 274 274 { 275 275 public List<AccountEntity>? Accounts; 276 - public List<MentionEntity>? Mentions; 277 276 public List<AttachmentEntity>? Attachments; 278 - public List<PollEntity>? Polls; 279 - public List<string>? LikedNotes; 280 277 public List<string>? BookmarkedNotes; 281 - public List<string>? PinnedNotes; 282 - public List<string>? Renotes; 283 278 public List<EmojiEntity>? Emoji; 279 + public List<string>? LikedNotes; 280 + public List<MentionEntity>? Mentions; 281 + public List<string>? PinnedNotes; 282 + public List<PollEntity>? Polls; 284 283 public List<ReactionEntity>? Reactions; 284 + public List<string>? Renotes; 285 285 286 286 public bool Source; 287 287 }
+4 -4
Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/AnnouncementEntity.cs
··· 4 4 5 5 public class AnnouncementEntity 6 6 { 7 + [J("reactions")] public List<object> Reactions = []; //FIXME 8 + 9 + [J("statuses")] public List<object> Statuses = []; //FIXME 10 + [J("tags")] public List<object> Tags = []; //FIXME 7 11 [J("id")] public required string Id { get; set; } 8 12 [J("content")] public required string Content { get; set; } 9 13 [J("published_at")] public required string PublishedAt { get; set; } ··· 11 15 [J("read")] public required bool IsRead { get; set; } 12 16 [J("mentions")] public required List<MentionEntity> Mentions { get; set; } 13 17 [J("emojis")] public required List<EmojiEntity> Emoji { get; set; } 14 - 15 - [J("statuses")] public List<object> Statuses = []; //FIXME 16 - [J("reactions")] public List<object> Reactions = []; //FIXME 17 - [J("tags")] public List<object> Tags = []; //FIXME 18 18 19 19 [J("published")] public bool Published => true; 20 20 [J("all_day")] public bool AllDay => false;
+1 -1
Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/ConversationEntity.cs
··· 5 5 6 6 public class ConversationEntity : IEntity 7 7 { 8 - [J("id")] public required string Id { get; set; } 9 8 [J("unread")] public required bool Unread { get; set; } 10 9 [J("accounts")] public required List<AccountEntity> Accounts { get; set; } 11 10 [J("last_status")] public required StatusEntity LastStatus { get; set; } 11 + [J("id")] public required string Id { get; set; } 12 12 }
+1 -1
Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/PollEntity.cs
··· 5 5 6 6 public class PollEntity : IEntity 7 7 { 8 - [J("id")] public required string Id { get; set; } 9 8 [J("expires_at")] public required string? ExpiresAt { get; set; } 10 9 [J("expired")] public required bool Expired { get; set; } 11 10 [J("multiple")] public required bool Multiple { get; set; } ··· 16 15 17 16 [J("options")] public required List<PollOptionEntity> Options { get; set; } 18 17 [J("emojis")] public List<EmojiEntity> Emoji => []; //TODO 18 + [J("id")] public required string Id { get; set; } 19 19 } 20 20 21 21 public class PollOptionEntity
+2 -2
Iceshrimp.Backend/Controllers/Mastodon/Schemas/Entities/StatusEntity.cs
··· 9 9 10 10 public class StatusEntity : IEntity 11 11 { 12 - [J("id")] public required string Id { get; set; } 13 12 [J("content")] public required string? Content { get; set; } 14 13 [J("uri")] public required string Uri { get; set; } 15 14 [J("url")] public required string Url { get; set; } ··· 52 51 [J("card")] public object? Card => null; //FIXME 53 52 [J("application")] public object? Application => null; //FIXME 54 53 55 - [J("language")] public string? Language => null; //FIXME 54 + [J("language")] public string? Language => null; //FIXME 55 + [J("id")] public required string Id { get; set; } 56 56 57 57 public static string EncodeVisibility(Note.NoteVisibility visibility) 58 58 {
+1 -1
Iceshrimp.Backend/Controllers/Mastodon/Schemas/StatusSchemas.cs
··· 82 82 [B(Name = "media_ids")] 83 83 [J("media_ids")] 84 84 public List<string>? MediaIds { get; set; } 85 - 85 + 86 86 [B(Name = "media_attributes")] 87 87 [J("media_attributes")] 88 88 public List<MediaAttributesEntry>? MediaAttributes { get; set; }
+1 -1
Iceshrimp.Backend/Controllers/Mastodon/SearchController.cs
··· 209 209 { 210 210 Name = p.Name, 211 211 Url = $"https://{config.Value.WebDomain}/tags/{p.Name}", 212 - Following = false, //TODO 212 + Following = false //TODO 213 213 }) 214 214 .ToListAsync(); 215 215 }
+7 -2
Iceshrimp.Backend/Controllers/Mastodon/StatusController.cs
··· 324 324 { 325 325 Choices = request.Poll.Options, 326 326 Multiple = request.Poll.Multiple, 327 - ExpiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(request.Poll.ExpiresIn), 327 + ExpiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(request.Poll.ExpiresIn) 328 328 } 329 329 : null; 330 330 ··· 465 465 { 466 466 var user = HttpContext.GetUserOrFail(); 467 467 var res = await db.Notes.Where(p => p.Id == id && p.User == user) 468 - .Select(p => new StatusSource { Id = p.Id, ContentWarning = p.Cw ?? "", Text = p.Text ?? "" }) 468 + .Select(p => new StatusSource 469 + { 470 + Id = p.Id, 471 + ContentWarning = p.Cw ?? "", 472 + Text = p.Text ?? "" 473 + }) 469 474 .FirstOrDefaultAsync() ?? 470 475 throw GracefulException.RecordNotFound(); 471 476
+15 -6
Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/PublicChannel.cs
··· 12 12 bool onlyMedia 13 13 ) : IChannel 14 14 { 15 + public readonly ILogger<PublicChannel> Logger = 16 + connection.ScopeFactory.CreateScope().ServiceProvider.GetRequiredService<ILogger<PublicChannel>>(); 17 + 15 18 public string Name => name; 16 19 public List<string> Scopes => ["read:statuses"]; 17 20 public bool IsSubscribed { get; private set; } 18 - 19 - public readonly ILogger<PublicChannel> Logger = 20 - connection.ScopeFactory.CreateScope().ServiceProvider.GetRequiredService<ILogger<PublicChannel>>(); 21 21 22 22 public Task Subscribe(StreamingRequestMessage _) 23 23 { ··· 65 65 var rendered = await renderer.RenderAsync(note, connection.Token.User); 66 66 var message = new StreamingUpdateMessage 67 67 { 68 - Stream = [Name], Event = "update", Payload = JsonSerializer.Serialize(rendered) 68 + Stream = [Name], 69 + Event = "update", 70 + Payload = JsonSerializer.Serialize(rendered) 69 71 }; 70 72 await connection.SendMessageAsync(JsonSerializer.Serialize(message)); 71 73 } ··· 85 87 var rendered = await renderer.RenderAsync(note, connection.Token.User); 86 88 var message = new StreamingUpdateMessage 87 89 { 88 - Stream = [Name], Event = "status.update", Payload = JsonSerializer.Serialize(rendered) 90 + Stream = [Name], 91 + Event = "status.update", 92 + Payload = JsonSerializer.Serialize(rendered) 89 93 }; 90 94 await connection.SendMessageAsync(JsonSerializer.Serialize(message)); 91 95 } ··· 100 104 try 101 105 { 102 106 if (!IsApplicable(note)) return; 103 - var message = new StreamingUpdateMessage { Stream = [Name], Event = "delete", Payload = note.Id }; 107 + var message = new StreamingUpdateMessage 108 + { 109 + Stream = [Name], 110 + Event = "delete", 111 + Payload = note.Id 112 + }; 104 113 await connection.SendMessageAsync(JsonSerializer.Serialize(message)); 105 114 } 106 115 catch (Exception e)
+18 -7
Iceshrimp.Backend/Controllers/Mastodon/Streaming/Channels/UserChannel.cs
··· 10 10 11 11 public class UserChannel(WebSocketConnection connection, bool notificationsOnly) : IChannel 12 12 { 13 + public readonly ILogger<UserChannel> Logger = 14 + connection.ScopeFactory.CreateScope().ServiceProvider.GetRequiredService<ILogger<UserChannel>>(); 15 + 13 16 private List<string> _followedUsers = []; 14 17 public string Name => notificationsOnly ? "user:notification" : "user"; 15 18 public List<string> Scopes => ["read:statuses", "read:notifications"]; 16 19 public bool IsSubscribed { get; private set; } 17 - 18 - public readonly ILogger<UserChannel> Logger = 19 - connection.ScopeFactory.CreateScope().ServiceProvider.GetRequiredService<ILogger<UserChannel>>(); 20 20 21 21 public async Task Subscribe(StreamingRequestMessage _) 22 22 { ··· 74 74 var rendered = await renderer.RenderAsync(note, connection.Token.User); 75 75 var message = new StreamingUpdateMessage 76 76 { 77 - Stream = [Name], Event = "update", Payload = JsonSerializer.Serialize(rendered) 77 + Stream = [Name], 78 + Event = "update", 79 + Payload = JsonSerializer.Serialize(rendered) 78 80 }; 79 81 await connection.SendMessageAsync(JsonSerializer.Serialize(message)); 80 82 } ··· 94 96 var rendered = await renderer.RenderAsync(note, connection.Token.User); 95 97 var message = new StreamingUpdateMessage 96 98 { 97 - Stream = [Name], Event = "status.update", Payload = JsonSerializer.Serialize(rendered) 99 + Stream = [Name], 100 + Event = "status.update", 101 + Payload = JsonSerializer.Serialize(rendered) 98 102 }; 99 103 await connection.SendMessageAsync(JsonSerializer.Serialize(message)); 100 104 } ··· 109 113 try 110 114 { 111 115 if (!IsApplicable(note)) return; 112 - var message = new StreamingUpdateMessage { Stream = [Name], Event = "delete", Payload = note.Id }; 116 + var message = new StreamingUpdateMessage 117 + { 118 + Stream = [Name], 119 + Event = "delete", 120 + Payload = note.Id 121 + }; 113 122 await connection.SendMessageAsync(JsonSerializer.Serialize(message)); 114 123 } 115 124 catch (Exception e) ··· 139 148 140 149 var message = new StreamingUpdateMessage 141 150 { 142 - Stream = [Name], Event = "notification", Payload = JsonSerializer.Serialize(rendered) 151 + Stream = [Name], 152 + Event = "notification", 153 + Payload = JsonSerializer.Serialize(rendered) 143 154 }; 144 155 await connection.SendMessageAsync(JsonSerializer.Serialize(message)); 145 156 }
+3 -4
Iceshrimp.Backend/Controllers/NotificationController.cs
··· 3 3 using Iceshrimp.Backend.Controllers.Renderers; 4 4 using Iceshrimp.Backend.Controllers.Schemas; 5 5 using Iceshrimp.Backend.Core.Database; 6 - using Iceshrimp.Backend.Core.Database.Tables; 7 6 using Iceshrimp.Backend.Core.Extensions; 8 7 using Iceshrimp.Backend.Core.Middleware; 9 - using Iceshrimp.Backend.Core.Services; 10 8 using Microsoft.AspNetCore.Mvc; 11 9 using Microsoft.AspNetCore.RateLimiting; 12 10 using Microsoft.EntityFrameworkCore; ··· 14 12 namespace Iceshrimp.Backend.Controllers; 15 13 16 14 [ApiController] 17 - [Authenticate, Authorize] 15 + [Authenticate] 16 + [Authorize] 18 17 [EnableRateLimiting("sliding")] 19 18 [Route("/api/iceshrimp/v1/notification")] 20 19 [Produces(MediaTypeNames.Application.Json)] ··· 67 66 68 67 return Ok(new object()); 69 68 } 70 - 69 + 71 70 [HttpDelete("{id}")] 72 71 [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(object))] 73 72 [ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponse))]
+2 -2
Iceshrimp.Backend/Controllers/Renderers/NoteRenderer.cs
··· 73 73 i.Reaction == p.First().Reaction && 74 74 i.User == user), 75 75 Name = p.First().Reaction, 76 - Url = null, 76 + Url = null 77 77 }) 78 78 .ToListAsync(); 79 79 ··· 102 102 103 103 public class NoteRendererDto 104 104 { 105 - public List<UserResponse>? Users; 106 105 public List<NoteAttachment>? Attachments; 107 106 public List<NoteReactionSchema>? Reactions; 107 + public List<UserResponse>? Users; 108 108 } 109 109 }
+1 -4
Iceshrimp.Backend/Controllers/Renderers/NotificationRenderer.cs
··· 1 1 using Iceshrimp.Backend.Controllers.Schemas; 2 - using Iceshrimp.Backend.Core.Database; 3 2 using Iceshrimp.Backend.Core.Database.Tables; 4 3 using Iceshrimp.Backend.Core.Extensions; 5 - using Iceshrimp.Backend.Core.Services; 6 - using Microsoft.EntityFrameworkCore; 7 4 8 5 namespace Iceshrimp.Backend.Controllers.Renderers; 9 6 ··· 81 78 82 79 public class NotificationRendererDto 83 80 { 84 - public List<UserResponse>? Users; 85 81 public List<NoteResponse>? Notes; 82 + public List<UserResponse>? Users; 86 83 } 87 84 }
+1 -1
Iceshrimp.Backend/Controllers/Renderers/UserProfileRenderer.cs
··· 36 36 Fields = user.UserProfile?.Fields, 37 37 Location = user.UserProfile?.Location, 38 38 Followers = followers, 39 - Following = following, 39 + Following = following 40 40 }; 41 41 } 42 42
-1
Iceshrimp.Backend/Controllers/Schemas/NotificationResponse.cs
··· 1 1 using J = System.Text.Json.Serialization.JsonPropertyNameAttribute; 2 - using JI = System.Text.Json.Serialization.JsonIgnoreAttribute; 3 2 4 3 namespace Iceshrimp.Backend.Controllers.Schemas; 5 4
+1 -1
Iceshrimp.Backend/Controllers/UserController.cs
··· 34 34 35 35 return Ok(await userRenderer.RenderOne(await userResolver.GetUpdatedUser(user))); 36 36 } 37 - 37 + 38 38 [HttpGet("profile")] 39 39 [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserProfileResponse))] 40 40 [ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(ErrorResponse))]
+1 -1
Iceshrimp.Backend/Core/Database/DatabaseContext.cs
··· 84 84 public virtual DbSet<Webhook> Webhooks { get; init; } = null!; 85 85 public virtual DbSet<AllowedInstance> AllowedInstances { get; init; } = null!; 86 86 public virtual DbSet<BlockedInstance> BlockedInstances { get; init; } = null!; 87 - public virtual DbSet<DataProtectionKey> DataProtectionKeys { get; init; } = null!; 88 87 public virtual DbSet<MetaStoreEntry> MetaStore { get; init; } = null!; 88 + public virtual DbSet<DataProtectionKey> DataProtectionKeys { get; init; } = null!; 89 89 90 90 public static NpgsqlDataSource GetDataSource(Config.DatabaseSection? config) 91 91 {
+1 -1
Iceshrimp.Backend/Core/Database/Tables/Announcement.cs
··· 42 42 public virtual ICollection<AnnouncementRead> AnnouncementReads { get; set; } = new List<AnnouncementRead>(); 43 43 44 44 [NotMapped] [Projectable] public virtual IEnumerable<User> ReadBy => AnnouncementReads.Select(p => p.User); 45 - 45 + 46 46 [Projectable] 47 47 public bool IsReadBy(User user) => ReadBy.Contains(user); 48 48 }
+3 -3
Iceshrimp.Backend/Core/Database/Tables/DriveFile.cs
··· 184 184 [InverseProperty(nameof(Tables.User.Banner))] 185 185 public virtual User? UserBanner { get; set; } 186 186 187 + [NotMapped] public string PublicUrl => WebpublicUrl ?? Url; 188 + [NotMapped] public string PublicThumbnailUrl => ThumbnailUrl ?? WebpublicUrl ?? Url; 189 + 187 190 [Key] 188 191 [Column("id")] 189 192 [StringLength(32)] 190 193 public string Id { get; set; } = null!; 191 - 192 - [NotMapped] public string PublicUrl => WebpublicUrl ?? Url; 193 - [NotMapped] public string PublicThumbnailUrl => ThumbnailUrl ?? WebpublicUrl ?? Url; 194 194 195 195 public class FileProperties 196 196 {
+2 -2
Iceshrimp.Backend/Core/Database/Tables/Hashtag.cs
··· 8 8 [Index("Name", IsUnique = true)] 9 9 public class Hashtag : IEntity 10 10 { 11 + [Column("name")] [StringLength(128)] public string Name { get; set; } = null!; 12 + 11 13 [Key] 12 14 [Column("id")] 13 15 [StringLength(32)] 14 16 public string Id { get; set; } = null!; 15 - 16 - [Column("name")] [StringLength(128)] public string Name { get; set; } = null!; 17 17 }
+9 -13
Iceshrimp.Backend/Core/Database/Tables/Marker.cs
··· 11 11 [PrimaryKey("UserId", "Type")] 12 12 public class Marker 13 13 { 14 - [Column("userId")] 15 - [StringLength(32)] 16 - public string UserId { get; set; } = null!; 14 + [PgName("marker_type_enum")] 15 + public enum MarkerType 16 + { 17 + [PgName("home")] Home, 18 + [PgName("notifications")] Notifications 19 + } 17 20 18 - [Column("type")] 19 - [StringLength(32)] 20 - public MarkerType Type { get; set; } 21 + [Column("userId")] [StringLength(32)] public string UserId { get; set; } = null!; 22 + 23 + [Column("type")] [StringLength(32)] public MarkerType Type { get; set; } 21 24 22 25 [Column("position")] 23 26 [StringLength(32)] ··· 30 33 [ForeignKey("UserId")] 31 34 [InverseProperty(nameof(Tables.User.Markers))] 32 35 public virtual User User { get; set; } = null!; 33 - 34 - [PgName("marker_type_enum")] 35 - public enum MarkerType 36 - { 37 - [PgName("home")] Home, 38 - [PgName("notifications")] Notifications 39 - } 40 36 }
+3 -3
Iceshrimp.Backend/Core/Database/Tables/Note.cs
··· 241 241 public string RawAttachments 242 242 => InternalRawAttachments(Id); 243 243 244 - public static string InternalRawAttachments(string id) 245 - => throw new NotSupportedException(); 246 - 247 244 [NotMapped] [Projectable] public bool IsPureRenote => (RenoteId != null || Renote != null) && !IsQuote; 248 245 249 246 [NotMapped] ··· 264 261 [Column("id")] 265 262 [StringLength(32)] 266 263 public string Id { get; set; } = null!; 264 + 265 + public static string InternalRawAttachments(string id) 266 + => throw new NotSupportedException(); 267 267 268 268 [Projectable] 269 269 public bool TextContainsCaseInsensitive(string str) =>
+4 -4
Iceshrimp.Backend/Core/Database/Tables/Notification.cs
··· 117 117 [InverseProperty(nameof(Tables.UserGroupInvitation.Notifications))] 118 118 public virtual UserGroupInvitation? UserGroupInvitation { get; set; } 119 119 120 + [Column("masto_id")] 121 + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 122 + public long MastoId { get; set; } 123 + 120 124 [Key] 121 125 [Column("id")] 122 126 [StringLength(32)] 123 127 public string Id { get; set; } = null!; 124 - 125 - [Column("masto_id")] 126 - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 127 - public long MastoId { get; set; } 128 128 129 129 public Notification WithPrecomputedNoteVisibilities(bool reply, bool renote) 130 130 {
+4 -4
Iceshrimp.Backend/Core/Database/Tables/PushSubscription.cs
··· 16 16 [PgName("all")] All, 17 17 [PgName("followed")] Followed, 18 18 [PgName("follower")] Follower, 19 - [PgName("none")] None, 19 + [PgName("none")] None 20 20 } 21 + 22 + [Column("types", TypeName = "character varying(32)[]")] 23 + public List<string> Types = null!; 21 24 22 25 [Key] 23 26 [Column("id")] ··· 41 44 [Column("publickey")] 42 45 [StringLength(128)] 43 46 public string PublicKey { get; set; } = null!; 44 - 45 - [Column("types", TypeName = "character varying(32)[]")] 46 - public List<string> Types = null!; 47 47 48 48 [Column("policy")] public PushPolicy Policy { get; set; } 49 49
+3 -3
Iceshrimp.Backend/Core/Database/Tables/User.cs
··· 494 494 [NotMapped] public bool? PrecomputedIsRequested { get; set; } 495 495 [NotMapped] public bool? PrecomputedIsRequestedBy { get; set; } 496 496 497 + public bool IsLocalUser => Host == null; 498 + public bool IsRemoteUser => Host != null; 499 + 497 500 [Key] 498 501 [Column("id")] 499 502 [StringLength(32)] ··· 616 619 : throw new Exception("Cannot access PublicUrl for remote user"); 617 620 618 621 public string GetIdenticonUrl(string webDomain) => $"https://{webDomain}/identicon/{Id}"; 619 - 620 - public bool IsLocalUser => Host == null; 621 - public bool IsRemoteUser => Host != null; 622 622 }
+2 -3
Iceshrimp.Backend/Core/Database/Tables/UserProfile.cs
··· 20 20 [PgName("private")] Private 21 21 } 22 22 23 + [Column("mentionsResolved")] public bool MentionsResolved; 24 + 23 25 [Key] 24 26 [Column("userId")] 25 27 [StringLength(32)] ··· 175 177 [ForeignKey("UserId")] 176 178 [InverseProperty(nameof(Tables.User.UserProfile))] 177 179 public virtual User User { get; set; } = null!; 178 - 179 - [Column("mentionsResolved")] 180 - public bool MentionsResolved; 181 180 182 181 public class Field 183 182 {
+1 -1
Iceshrimp.Backend/Core/Extensions/DistributedCacheExtensions.cs
··· 124 124 if (res != null) return; 125 125 await SetAsync(cache, key, fetcher(), type, ttl, renew); 126 126 } 127 - 127 + 128 128 public static async Task CacheAsync( 129 129 this IDistributedCache cache, string key, TimeSpan ttl, object? value, Type type, bool renew = false 130 130 )
+9 -10
Iceshrimp.Backend/Core/Extensions/MvcBuilderExtensions.cs
··· 28 28 29 29 if (!opts.OutputFormatters.OfType<SystemTextJsonOutputFormatter>().Any()) 30 30 opts.OutputFormatters.Add(new SystemTextJsonOutputFormatter(jsonOpts.Value 31 - .JsonSerializerOptions)); 31 + .JsonSerializerOptions)); 32 32 33 33 opts.InputFormatters.Insert(0, new JsonInputMultiFormatter()); 34 34 opts.OutputFormatters.Insert(0, new JsonOutputMultiFormatter()); ··· 39 39 40 40 public static IMvcBuilder AddModelBindingProviders(this IMvcBuilder builder) 41 41 { 42 - builder.Services.AddOptions<MvcOptions>().PostConfigure(options => 43 - { 44 - options.ModelBinderProviders.AddHybridBindingProvider(); 45 - }); 42 + builder.Services.AddOptions<MvcOptions>() 43 + .PostConfigure(options => { options.ModelBinderProviders.AddHybridBindingProvider(); }); 46 44 47 45 return builder; 48 46 } 49 - 47 + 50 48 public static IMvcBuilder AddValueProviderFactories(this IMvcBuilder builder) 51 49 { 52 - builder.Services.AddOptions<MvcOptions>().PostConfigure(options => 53 - { 54 - options.ValueProviderFactories.Add(new JQueryQueryStringValueProviderFactory()); 55 - }); 50 + builder.Services.AddOptions<MvcOptions>() 51 + .PostConfigure(options => 52 + { 53 + options.ValueProviderFactories.Add(new JQueryQueryStringValueProviderFactory()); 54 + }); 56 55 57 56 return builder; 58 57 }
+3 -1
Iceshrimp.Backend/Core/Extensions/QueryableExtensions.cs
··· 289 289 .Where(note => note.Reply == null || !note.Reply.User.IsMuting(user)); 290 290 } 291 291 292 - public static IQueryable<Note> FilterBlockedConversations(this IQueryable<Note> query, User user, DatabaseContext db) 292 + public static IQueryable<Note> FilterBlockedConversations( 293 + this IQueryable<Note> query, User user, DatabaseContext db 294 + ) 293 295 { 294 296 return query.Where(p => !db.Blockings.Any(i => i.Blocker == user && p.VisibleUserIds.Contains(i.BlockeeId))); 295 297 }
+1 -1
Iceshrimp.Backend/Core/Extensions/WebApplicationExtensions.cs
··· 173 173 var keypair = VapidHelper.GenerateVapidKeys(); 174 174 return [keypair.PublicKey, keypair.PrivateKey]; 175 175 }); 176 - 176 + 177 177 app.Logger.LogInformation("Warming up meta cache..."); 178 178 await meta.WarmupCache(); 179 179
+3 -1
Iceshrimp.Backend/Core/Federation/ActivityPub/UserRenderer.cs
··· 79 79 Endpoints = new ASEndpoints { SharedInbox = new ASObjectBase($"https://{config.Value.WebDomain}/inbox") }, 80 80 PublicKey = new ASPublicKey 81 81 { 82 - Id = $"{id}#main-key", Owner = new ASObjectBase(id), PublicKey = keypair.PublicKey 82 + Id = $"{id}#main-key", 83 + Owner = new ASObjectBase(id), 84 + PublicKey = keypair.PublicKey 83 85 }, 84 86 Tags = tags 85 87 };
+3 -3
Iceshrimp.Backend/Core/Federation/ActivityStreams/LDHelpers.cs
··· 64 64 JToken.Parse(File.ReadAllText(Path.Combine("Core", "Federation", "ActivityStreams", "Contexts", 65 65 "as-extensions.json"))); 66 66 67 - private static IEnumerable<string> ASForceArray => ["tag", "to", "cc", "bcc", "bto"]; 68 - 69 67 private static readonly JsonLdProcessorOptions Options = new() 70 68 { 71 69 DocumentLoader = CustomLoader, ··· 75 73 ForceArray = ASForceArray.Select(p => $"{Constants.ActivityStreamsNs}#{p}").ToList(), 76 74 77 75 // separated for readability 78 - RemoveUnusedInlineContextProperties = true, 76 + RemoveUnusedInlineContextProperties = true 79 77 }; 80 78 81 79 public static readonly JsonSerializerSettings JsonSerializerSettings = new() ··· 87 85 { 88 86 NullValueHandling = NullValueHandling.Ignore, DateTimeZoneHandling = DateTimeZoneHandling.Local 89 87 }; 88 + 89 + private static IEnumerable<string> ASForceArray => ["tag", "to", "cc", "bcc", "bto"]; 90 90 91 91 private static RemoteDocument CustomLoader(Uri uri, JsonLdLoaderOptions jsonLdLoaderOptions) 92 92 {
+1 -1
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASActivity.cs
··· 37 37 38 38 // Extensions 39 39 public const string Bite = "https://ns.mia.jetzt/as#Bite"; 40 - public const string EmojiReact = $"http://litepub.social/ns#EmojiReact"; 40 + public const string EmojiReact = "http://litepub.social/ns#EmojiReact"; 41 41 } 42 42 } 43 43
+1 -1
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASActor.cs
··· 120 120 [J($"{Constants.ActivityStreamsNs}#tag")] 121 121 [JC(typeof(ASTagConverter))] 122 122 public List<ASTag>? Tags { get; set; } 123 - 123 + 124 124 [J($"{Constants.ActivityStreamsNs}#attachment")] 125 125 [JC(typeof(ASAttachmentConverter))] 126 126 public List<ASAttachment>? Attachments { get; set; }
+2 -2
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASAttachment.cs
··· 36 36 37 37 public class ASField : ASAttachment 38 38 { 39 - public ASField() => Type = $"{Constants.SchemaNs}#PropertyValue"; 40 - 41 39 [J($"{Constants.ActivityStreamsNs}#name")] [JC(typeof(ValueObjectConverter))] 42 40 public string? Name; 43 41 44 42 [J($"{Constants.SchemaNs}#value")] [JC(typeof(ValueObjectConverter))] 45 43 public string? Value; 44 + 45 + public ASField() => Type = $"{Constants.SchemaNs}#PropertyValue"; 46 46 } 47 47 48 48 public sealed class ASAttachmentConverter : JsonConverter
+2 -2
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASCollection.cs
··· 10 10 11 11 public class ASCollection : ASObject 12 12 { 13 + public const string ObjectType = $"{Constants.ActivityStreamsNs}#Collection"; 14 + 13 15 [JsonConstructor] 14 16 public ASCollection(bool withType = true) => Type = withType ? ObjectType : null; 15 17 ··· 37 39 public ASLink? Last { get; set; } 38 40 39 41 public new bool IsUnresolved => !TotalItems.HasValue; 40 - 41 - public const string ObjectType = $"{Constants.ActivityStreamsNs}#Collection"; 42 42 } 43 43 44 44 public sealed class ASCollectionConverter : JsonConverter
+2 -2
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASCollectionBase.cs
··· 7 7 8 8 public class ASCollectionBase : ASObjectBase 9 9 { 10 + public const string ObjectType = $"{Constants.ActivityStreamsNs}#Collection"; 11 + 10 12 [J("@type")] 11 13 [JC(typeof(StringListSingleConverter))] 12 14 public string Type => ObjectType; ··· 14 16 [J($"{Constants.ActivityStreamsNs}#totalItems")] 15 17 [JC(typeof(VC))] 16 18 public ulong? TotalItems { get; set; } 17 - 18 - public const string ObjectType = $"{Constants.ActivityStreamsNs}#Collection"; 19 19 } 20 20 21 21 public sealed class ASCollectionBaseConverter : ASSerializer.ListSingleObjectConverter<ASCollectionBase>;
+2 -2
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASCollectionPage.cs
··· 10 10 11 11 public class ASCollectionPage : ASObject 12 12 { 13 + public const string ObjectType = $"{Constants.ActivityStreamsNs}#CollectionPage"; 14 + 13 15 [JsonConstructor] 14 16 public ASCollectionPage(bool withType = true) => Type = withType ? ObjectType : null; 15 17 ··· 35 37 [J($"{Constants.ActivityStreamsNs}#next")] 36 38 [JC(typeof(ASLinkConverter))] 37 39 public ASLink? Next { get; set; } 38 - 39 - public const string ObjectType = $"{Constants.ActivityStreamsNs}#CollectionPage"; 40 40 } 41 41 42 42 public sealed class ASCollectionPageConverter : JsonConverter
+2 -2
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASImage.cs
··· 10 10 [J("@type")] 11 11 [JC(typeof(StringListSingleConverter))] 12 12 public string Type => $"{Constants.ActivityStreamsNs}#Image"; 13 - 13 + 14 14 [J($"{Constants.ActivityStreamsNs}#url")] 15 15 [JC(typeof(ASLinkConverter))] 16 16 public ASLink? Url { get; set; } ··· 20 20 public bool? Sensitive { get; set; } 21 21 } 22 22 23 - public class ASImageConverter : ASSerializer.ListSingleObjectConverter<ASImage>; 23 + public class ASImageConverter : ASSerializer.ListSingleObjectConverter<ASImage>;
+8 -8
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASNote.cs
··· 42 42 [J($"{Constants.ActivityStreamsNs}#summary")] 43 43 [JC(typeof(VC))] 44 44 public string? Summary { get; set; } 45 - 45 + 46 46 [J($"{Constants.ActivityStreamsNs}#name")] 47 47 [JC(typeof(VC))] 48 48 public string? Name { get; set; } ··· 94 94 { 95 95 if (actor.Host == null) throw new Exception("Can't get recipients for local actor"); 96 96 return (To ?? []).Concat(Cc ?? []) 97 - .Select(p => p.Id) 98 - .Distinct() 99 - .Where(p => p != $"{Constants.ActivityStreamsNs}#Public" && 100 - p != (actor.FollowersUri ?? actor.Uri + "/followers")) 101 - .Where(p => p != null) 102 - .Select(p => p!) 103 - .ToList(); 97 + .Select(p => p.Id) 98 + .Distinct() 99 + .Where(p => p != $"{Constants.ActivityStreamsNs}#Public" && 100 + p != (actor.FollowersUri ?? actor.Uri + "/followers")) 101 + .Where(p => p != null) 102 + .Select(p => p!) 103 + .ToList(); 104 104 } 105 105 106 106 public new static class Types
+2 -2
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASOrderedCollection.cs
··· 9 9 10 10 public class ASOrderedCollection : ASCollection 11 11 { 12 + public new const string ObjectType = $"{Constants.ActivityStreamsNs}#OrderedCollection"; 13 + 12 14 [JsonConstructor] 13 15 public ASOrderedCollection(bool withType = true) => Type = withType ? ObjectType : null; 14 16 ··· 22 24 get => base.Items; 23 25 set => base.Items = value; 24 26 } 25 - 26 - public new const string ObjectType = $"{Constants.ActivityStreamsNs}#OrderedCollection"; 27 27 } 28 28 29 29 internal sealed class ASOrderedCollectionItemsConverter : ASCollectionItemsConverter
+3 -3
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASOrderedCollectionPage.cs
··· 10 10 11 11 public class ASOrderedCollectionPage : ASObject 12 12 { 13 + public const string ObjectType = $"{Constants.ActivityStreamsNs}#OrderedCollectionPage"; 14 + 13 15 [JsonConstructor] 14 16 public ASOrderedCollectionPage(bool withType = true) => Type = withType ? ObjectType : null; 15 - 17 + 16 18 [SetsRequiredMembers] 17 19 public ASOrderedCollectionPage(string id, bool withType = false) : this(withType) => Id = id; 18 20 ··· 35 37 [J($"{Constants.ActivityStreamsNs}#next")] 36 38 [JC(typeof(ASLinkConverter))] 37 39 public ASLink? Next { get; set; } 38 - 39 - public const string ObjectType = $"{Constants.ActivityStreamsNs}#OrderedCollectionPage"; 40 40 } 41 41 42 42 public sealed class ASOrderedCollectionPageConverter : JsonConverter
+1 -2
Iceshrimp.Backend/Core/Federation/ActivityStreams/Types/ASQuestion.cs
··· 7 7 8 8 public class ASQuestion : ASNote 9 9 { 10 - public ASQuestion() => Type = Types.Question; 11 - 12 10 private List<ASQuestionOption>? _anyOf; 13 11 private List<ASQuestionOption>? _oneOf; 12 + public ASQuestion() => Type = Types.Question; 14 13 15 14 [J($"{Constants.ActivityStreamsNs}#oneOf")] 16 15 public List<ASQuestionOption>? OneOf
+3 -1
Iceshrimp.Backend/Core/Helpers/LibMfm/Parsing/MfmParser.cs
··· 306 306 307 307 var node = new MfmMentionNode 308 308 { 309 - Username = split[0], Host = split.Length == 2 ? split[1] : null, Acct = $"@{buffer[start..end]}" 309 + Username = split[0], 310 + Host = split.Length == 2 ? split[1] : null, 311 + Acct = $"@{buffer[start..end]}" 310 312 }; 311 313 312 314 return (node, chars);
+1 -1
Iceshrimp.Backend/Core/Middleware/AuthenticationMiddleware.cs
··· 59 59 60 60 userSvc.UpdateOauthTokenMetadata(oauthToken); 61 61 ctx.SetOauthToken(oauthToken); 62 - 62 + 63 63 mfmConverter.SupportsHtmlFormatting = oauthToken.SupportsHtmlFormatting; 64 64 } 65 65 else
+1 -1
Iceshrimp.Backend/Core/Middleware/InboxValidationMiddleware.cs
··· 90 90 if (user == null) throw AuthFetchException.NotFound("Delete activity actor is unknown"); 91 91 key = await db.UserPublickeys.Include(p => p.User) 92 92 .FirstOrDefaultAsync(p => p.User == user, ct); 93 - 93 + 94 94 // If the key is still null here, we have a data consistency issue and need to update the key manually 95 95 key ??= await userSvc.UpdateUserPublicKeyAsync(user).WaitAsync(ct); 96 96 }
+3 -3
Iceshrimp.Backend/Core/Queues/BackgroundTaskQueue.cs
··· 146 146 ) 147 147 { 148 148 var db = scope.GetRequiredService<DatabaseContext>(); 149 - var poll = await db.Polls.FirstOrDefaultAsync(p => p.NoteId == job.NoteId, cancellationToken: token); 149 + var poll = await db.Polls.FirstOrDefaultAsync(p => p.NoteId == job.NoteId, token); 150 150 if (poll == null) return; 151 151 if (poll.ExpiresAt > DateTime.UtcNow + TimeSpan.FromSeconds(30)) return; 152 152 var note = await db.Notes.IncludeCommonProperties() 153 - .FirstOrDefaultAsync(p => p.Id == poll.NoteId, cancellationToken: token); 153 + .FirstOrDefaultAsync(p => p.Id == poll.NoteId, token); 154 154 if (note == null) return; 155 155 156 156 var notificationSvc = scope.GetRequiredService<NotificationService>(); ··· 159 159 { 160 160 var voters = await db.PollVotes.Where(p => p.Note == note && p.User.Host != null) 161 161 .Select(p => p.User) 162 - .ToListAsync(cancellationToken: token); 162 + .ToListAsync(token); 163 163 164 164 if (voters.Count == 0) return; 165 165
+1 -1
Iceshrimp.Backend/Core/Services/InstanceService.cs
··· 30 30 Id = IdHelpers.GenerateSlowflakeId(), 31 31 Host = host, 32 32 CaughtAt = DateTime.UtcNow, 33 - LastCommunicatedAt = DateTime.UtcNow, 33 + LastCommunicatedAt = DateTime.UtcNow 34 34 }; 35 35 await db.AddAsync(instance); 36 36 await db.SaveChangesAsync();
+1 -1
Iceshrimp.Backend/Core/Services/NoteService.cs
··· 191 191 } 192 192 193 193 /// <remarks> 194 - /// This needs to be called before SaveChangesAsync on create & after on delete 194 + /// This needs to be called before SaveChangesAsync on create & after on delete 195 195 /// </remarks> 196 196 private async Task UpdateNoteCountersAsync(Note note, bool create) 197 197 {
+6 -1
Iceshrimp.Backend/Core/Services/SystemUserService.cs
··· 76 76 PublicKey = keypair.ExportSubjectPublicKeyInfoPem() 77 77 }; 78 78 79 - var userProfile = new UserProfile { UserId = user.Id, AutoAcceptFollowed = false, Password = null }; 79 + var userProfile = new UserProfile 80 + { 81 + UserId = user.Id, 82 + AutoAcceptFollowed = false, 83 + Password = null 84 + }; 80 85 81 86 var usedUsername = new UsedUsername { CreatedAt = DateTime.UtcNow, Username = username.ToLowerInvariant() }; 82 87
+2 -2
Iceshrimp.Backend/Core/Services/UserService.cs
··· 298 298 db.Update(user); 299 299 await db.SaveChangesAsync(); 300 300 await processPendingDeletes(); 301 - user = await UpdateProfileMentions(user, actor, force: true); 302 - UpdateUserPinnedNotesInBackground(actor, user, force: true); 301 + user = await UpdateProfileMentions(user, actor, true); 302 + UpdateUserPinnedNotesInBackground(actor, user, true); 303 303 return user; 304 304 } 305 305
+31 -31
Iceshrimp.Backend/Iceshrimp.Backend.csproj
··· 16 16 </PropertyGroup> 17 17 18 18 <ItemGroup> 19 - <PackageReference Include="Amazon.S3" Version="0.31.2" /> 20 - <PackageReference Include="AngleSharp" Version="1.1.0" /> 21 - <PackageReference Include="Asp.Versioning.Http" Version="8.0.0" /> 22 - <PackageReference Include="AsyncKeyedLock" Version="6.3.4" /> 23 - <PackageReference Include="Blurhash.ImageSharp" Version="3.0.0" /> 24 - <PackageReference Include="cuid.net" Version="5.0.2" /> 25 - <PackageReference Include="dotNetRdf.Core" Version="3.2.6-iceshrimp" /> 26 - <PackageReference Include="EntityFrameworkCore.Exceptions.PostgreSQL" Version="8.0.0" /> 27 - <PackageReference Include="EntityFrameworkCore.Projectables" Version="3.0.4" /> 28 - <PackageReference Include="Isopoh.Cryptography.Argon2" Version="2.0.0" /> 29 - <PackageReference Include="libsodium" Version="1.0.18.4" /> 30 - <PackageReference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="8.0.1" /> 31 - <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.0" /> 32 - <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" /> 19 + <PackageReference Include="Amazon.S3" Version="0.31.2"/> 20 + <PackageReference Include="AngleSharp" Version="1.1.0"/> 21 + <PackageReference Include="Asp.Versioning.Http" Version="8.0.0"/> 22 + <PackageReference Include="AsyncKeyedLock" Version="6.3.4"/> 23 + <PackageReference Include="Blurhash.ImageSharp" Version="3.0.0"/> 24 + <PackageReference Include="cuid.net" Version="5.0.2"/> 25 + <PackageReference Include="dotNetRdf.Core" Version="3.2.6-iceshrimp"/> 26 + <PackageReference Include="EntityFrameworkCore.Exceptions.PostgreSQL" Version="8.0.0"/> 27 + <PackageReference Include="EntityFrameworkCore.Projectables" Version="3.0.4"/> 28 + <PackageReference Include="Isopoh.Cryptography.Argon2" Version="2.0.0"/> 29 + <PackageReference Include="libsodium" Version="1.0.18.4"/> 30 + <PackageReference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="8.0.1"/> 31 + <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.0"/> 32 + <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0"/> 33 33 <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0"> 34 34 <PrivateAssets>all</PrivateAssets> 35 35 <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> 36 36 </PackageReference> 37 - <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.1" /> 38 - <PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="8.0.0" /> 39 - <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" /> 40 - <PackageReference Include="protobuf-net" Version="3.2.30" /> 41 - <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.1" /> 42 - <PackageReference Include="StackExchange.Redis" Version="2.7.17" /> 43 - <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> 44 - <PackageReference Include="System.IO.Hashing" Version="8.0.0" /> 45 - <PackageReference Include="Vite.AspNetCore" Version="1.11.0" /> 46 - <PackageReference Include="WebPush" Version="1.0.24-iceshrimp" /> 37 + <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.1"/> 38 + <PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="8.0.0"/> 39 + <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0"/> 40 + <PackageReference Include="protobuf-net" Version="3.2.30"/> 41 + <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.1"/> 42 + <PackageReference Include="StackExchange.Redis" Version="2.7.17"/> 43 + <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0"/> 44 + <PackageReference Include="System.IO.Hashing" Version="8.0.0"/> 45 + <PackageReference Include="Vite.AspNetCore" Version="1.11.0"/> 46 + <PackageReference Include="WebPush" Version="1.0.24-iceshrimp"/> 47 47 </ItemGroup> 48 48 49 49 <ItemGroup> 50 - <AdditionalFiles Include="Pages\Error.cshtml" /> 51 - <AdditionalFiles Include="Pages\Shared\_Layout.cshtml" /> 52 - <AdditionalFiles Include="Pages\_ViewImports.cshtml" /> 53 - <AdditionalFiles Include="Pages\_ViewStart.cshtml" /> 50 + <AdditionalFiles Include="Pages\Error.cshtml"/> 51 + <AdditionalFiles Include="Pages\Shared\_Layout.cshtml"/> 52 + <AdditionalFiles Include="Pages\_ViewImports.cshtml"/> 53 + <AdditionalFiles Include="Pages\_ViewStart.cshtml"/> 54 54 </ItemGroup> 55 55 56 56 <ItemGroup> 57 - <Content Include="wwwroot\.vite\manifest.json" CopyToPublishDirectory="PreserveNewest" /> 57 + <Content Include="wwwroot\.vite\manifest.json" CopyToPublishDirectory="PreserveNewest"/> 58 58 </ItemGroup> 59 59 60 60 <ItemGroup> 61 - <None Remove="migrate.sql" /> 61 + <None Remove="migrate.sql"/> 62 62 </ItemGroup> 63 63 64 64 <ItemGroup> 65 - <ProjectReference Include="..\Iceshrimp.Parsing\Iceshrimp.Parsing.fsproj" /> 65 + <ProjectReference Include="..\Iceshrimp.Parsing\Iceshrimp.Parsing.fsproj"/> 66 66 </ItemGroup> 67 67 68 68 </Project>
+2 -2
Iceshrimp.Parsing/Iceshrimp.Parsing.fsproj
··· 6 6 </PropertyGroup> 7 7 8 8 <ItemGroup> 9 - <Compile Include="SearchQuery.fs" /> 9 + <Compile Include="SearchQuery.fs"/> 10 10 </ItemGroup> 11 11 12 12 <ItemGroup> 13 - <PackageReference Include="FParsec" Version="1.1.1" /> 13 + <PackageReference Include="FParsec" Version="1.1.1"/> 14 14 </ItemGroup> 15 15 16 16 </Project>
+17 -9
Iceshrimp.Tests/Parsing/SearchQueryTests.cs
··· 16 16 } 17 17 18 18 [TestMethod] 19 - [DataRow(false), DataRow(true)] 19 + [DataRow(false)] 20 + [DataRow(true)] 20 21 public void TestParseFrom(bool negated) 21 22 { 22 23 List<string> candidates = ["from", "author", "by", "user"]; ··· 27 28 } 28 29 29 30 [TestMethod] 30 - [DataRow(false), DataRow(true)] 31 + [DataRow(false)] 32 + [DataRow(true)] 31 33 public void TestParseMention(bool negated) 32 34 { 33 35 List<string> candidates = ["mention", "mentions", "mentioning"]; ··· 38 40 } 39 41 40 42 [TestMethod] 41 - [DataRow(false), DataRow(true)] 43 + [DataRow(false)] 44 + [DataRow(true)] 42 45 public void TestParseReply(bool negated) 43 46 { 44 47 List<string> candidates = ["reply", "replying", "to"]; ··· 49 52 } 50 53 51 54 [TestMethod] 52 - [DataRow(false), DataRow(true)] 55 + [DataRow(false)] 56 + [DataRow(true)] 53 57 public void TestParseInstance(bool negated) 54 58 { 55 59 List<string> candidates = ["instance", "domain", "host"]; ··· 78 82 } 79 83 80 84 [TestMethod] 81 - [DataRow(false), DataRow(true)] 85 + [DataRow(false)] 86 + [DataRow(true)] 82 87 public void TestParseAttachment(bool negated) 83 88 { 84 89 List<string> keyCandidates = ["has", "attachment", "attached"]; ··· 127 132 } 128 133 129 134 [TestMethod] 130 - [DataRow(false), DataRow(true)] 135 + [DataRow(false)] 136 + [DataRow(true)] 131 137 public void TestParseIn(bool negated) 132 138 { 133 139 var key = negated ? "-in" : "in"; ··· 147 153 } 148 154 149 155 [TestMethod] 150 - [DataRow(false), DataRow(true)] 156 + [DataRow(false)] 157 + [DataRow(true)] 151 158 public void TestParseMisc(bool negated) 152 159 { 153 160 var key = negated ? "-filter" : "filter"; ··· 165 172 new MiscFilter(negated, "renotes"), 166 173 new MiscFilter(negated, "renotes"), 167 174 new MiscFilter(negated, "renotes"), 168 - new MiscFilter(negated, "renotes"), 175 + new MiscFilter(negated, "renotes") 169 176 ]; 170 177 results.Should() 171 178 .HaveCount(expectedResults.Count) ··· 173 180 } 174 181 175 182 [TestMethod] 176 - [DataRow(false), DataRow(true)] 183 + [DataRow(false)] 184 + [DataRow(true)] 177 185 public void TestParseWord(bool negated) 178 186 { 179 187 List<string> candidates = ["test", "word", "since:2023-10-10invalid", "in:bookmarkstypo"];