[sln] Reformat code
This commit is contained in:
parent
7dec2514da
commit
24b412bd75
41 changed files with 220 additions and 177 deletions
|
@ -37,15 +37,15 @@ public class NoteRenderer(
|
|||
{
|
||||
var res = new PreviewNote
|
||||
{
|
||||
User = users.First(p => p.Id == note.User.Id),
|
||||
Text = await mfm.RenderAsync(note.Text, note.User.Host, mentions[note.Id], emoji[note.Id], "span"),
|
||||
Cw = note.Cw,
|
||||
RawText = note.Text,
|
||||
QuoteUrl = note.Renote?.Url ?? note.Renote?.Uri ?? note.Renote?.GetPublicUriOrNull(instance.Value),
|
||||
User = users.First(p => p.Id == note.User.Id),
|
||||
Text = await mfm.RenderAsync(note.Text, note.User.Host, mentions[note.Id], emoji[note.Id], "span"),
|
||||
Cw = note.Cw,
|
||||
RawText = note.Text,
|
||||
QuoteUrl = note.Renote?.Url ?? note.Renote?.Uri ?? note.Renote?.GetPublicUriOrNull(instance.Value),
|
||||
QuoteInaccessible = note.Renote?.VisibilityIsPublicOrHome == false,
|
||||
Attachments = attachments[note.Id],
|
||||
CreatedAt = note.CreatedAt.ToDisplayStringTz(),
|
||||
UpdatedAt = note.UpdatedAt?.ToDisplayStringTz()
|
||||
Attachments = attachments[note.Id],
|
||||
CreatedAt = note.CreatedAt.ToDisplayStringTz(),
|
||||
UpdatedAt = note.UpdatedAt?.ToDisplayStringTz()
|
||||
};
|
||||
|
||||
return res;
|
||||
|
@ -92,18 +92,19 @@ public class NoteRenderer(
|
|||
|
||||
var ids = notes.SelectMany(p => p.FileIds).ToList();
|
||||
var files = await db.DriveFiles.Where(p => ids.Contains(p.Id)).ToListAsync();
|
||||
return notes.ToDictionary<Note, string, List<PreviewAttachment>?>(p => p.Id,
|
||||
p => files
|
||||
.Where(f => p.FileIds.Contains(f.Id))
|
||||
.Select(f => new PreviewAttachment
|
||||
{
|
||||
MimeType = f.Type,
|
||||
Url = f.AccessUrl,
|
||||
Name = f.Name,
|
||||
Alt = f.Comment,
|
||||
Sensitive = f.IsSensitive
|
||||
})
|
||||
.ToList());
|
||||
return notes
|
||||
.ToDictionary<Note, string, List<PreviewAttachment>?>(p => p.Id,
|
||||
p => files
|
||||
.Where(f => p.FileIds.Contains(f.Id))
|
||||
.Select(f => new PreviewAttachment
|
||||
{
|
||||
MimeType = f.Type,
|
||||
Url = f.AccessUrl,
|
||||
Name = f.Name,
|
||||
Alt = f.Comment,
|
||||
Sensitive = f.IsSensitive
|
||||
})
|
||||
.ToList());
|
||||
}
|
||||
|
||||
public async Task<List<PreviewNote>> RenderManyAsync(List<Note> notes)
|
||||
|
@ -114,6 +115,8 @@ public class NoteRenderer(
|
|||
var mentions = await GetMentionsAsync(allNotes);
|
||||
var emoji = await GetEmojiAsync(allNotes);
|
||||
var attachments = await GetAttachmentsAsync(allNotes);
|
||||
return await notes.Select(p => RenderAsync(p, users, mentions, emoji, attachments)).AwaitAllAsync().ToListAsync();
|
||||
return await notes.Select(p => RenderAsync(p, users, mentions, emoji, attachments))
|
||||
.AwaitAllAsync()
|
||||
.ToListAsync();
|
||||
}
|
||||
}
|
|
@ -253,14 +253,14 @@ public class AccountController(
|
|||
var user = HttpContext.GetUserOrFail();
|
||||
if (user.Id == id)
|
||||
throw GracefulException.BadRequest("You cannot unfollow yourself");
|
||||
|
||||
|
||||
var follower = await db.Followings
|
||||
.Where(p => p.FolloweeId == user.Id && p.FollowerId == id)
|
||||
.Select(p => p.Follower)
|
||||
.PrecomputeRelationshipData(user)
|
||||
.FirstOrDefaultAsync() ??
|
||||
throw GracefulException.RecordNotFound();
|
||||
|
||||
|
||||
await userSvc.RemoveFromFollowersAsync(user, follower);
|
||||
return RenderRelationship(follower);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ public class InstanceController(DatabaseContext db, MetaService meta) : Controll
|
|||
var instanceCount = await db.Instances.LongCountAsync();
|
||||
|
||||
var (instanceName, instanceDescription, adminContact) =
|
||||
await meta.GetManyAsync(MetaEntity.InstanceName, MetaEntity.InstanceDescription, MetaEntity.AdminContactEmail);
|
||||
await meta.GetManyAsync(MetaEntity.InstanceName, MetaEntity.InstanceDescription,
|
||||
MetaEntity.AdminContactEmail);
|
||||
|
||||
// can't merge with above call since they're all nullable and this is not.
|
||||
var vapidKey = await meta.GetAsync(MetaEntity.VapidPublicKey);
|
||||
|
@ -55,7 +56,8 @@ public class InstanceController(DatabaseContext db, MetaService meta) : Controll
|
|||
p.LastActiveDate > cutoff);
|
||||
|
||||
var (instanceName, instanceDescription, adminContact) =
|
||||
await meta.GetManyAsync(MetaEntity.InstanceName, MetaEntity.InstanceDescription, MetaEntity.AdminContactEmail);
|
||||
await meta.GetManyAsync(MetaEntity.InstanceName, MetaEntity.InstanceDescription,
|
||||
MetaEntity.AdminContactEmail);
|
||||
|
||||
return new InstanceInfoV2Response(config.Value, instanceName, instanceDescription, adminContact)
|
||||
{
|
||||
|
|
|
@ -129,7 +129,7 @@ public class NoteRenderer(
|
|||
|
||||
if ((user?.UserSettings?.FilterInaccessible ?? false) && (replyInaccessible || quoteInaccessible))
|
||||
filterResult.Insert(0, InaccessibleFilter);
|
||||
|
||||
|
||||
if (user == null && security.Value.PublicPreview == Enums.PublicPreview.RestrictedNoMedia) //TODO
|
||||
attachments = [];
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ using Microsoft.EntityFrameworkCore;
|
|||
|
||||
namespace Iceshrimp.Backend.Controllers.Mastodon.Renderers;
|
||||
|
||||
public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer, UserRenderer userRenderer) : IScopedService
|
||||
public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer, UserRenderer userRenderer)
|
||||
: IScopedService
|
||||
{
|
||||
public async Task<NotificationEntity> RenderAsync(
|
||||
Notification notification, User user, bool isPleroma, List<AccountEntity>? accounts = null,
|
||||
|
@ -68,24 +69,23 @@ public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer,
|
|||
var notificationList = notifications.ToList();
|
||||
if (notificationList.Count == 0) return [];
|
||||
|
||||
var accounts = await noteRenderer.GetAccountsAsync(notificationList.Where(p => p.Notifier != null)
|
||||
.Select(p => p.Notifier)
|
||||
.Concat(notificationList.Select(p => p.Notifiee))
|
||||
.Concat(notificationList
|
||||
.Select(p => p.Note?.Renote?.User)
|
||||
.Where(p => p != null))
|
||||
.Cast<User>()
|
||||
.DistinctBy(p => p.Id)
|
||||
.ToList(), user);
|
||||
var accounts = await noteRenderer
|
||||
.GetAccountsAsync(notificationList
|
||||
.Where(p => p.Notifier != null)
|
||||
.Select(p => p.Notifier)
|
||||
.Concat(notificationList.Select(p => p.Notifiee))
|
||||
.Concat(notificationList.Select(p => p.Note?.Renote?.User).Where(p => p != null))
|
||||
.Cast<User>()
|
||||
.DistinctBy(p => p.Id)
|
||||
.ToList(), user);
|
||||
|
||||
var notes = await noteRenderer.RenderManyAsync(notificationList.Where(p => p.Note != null)
|
||||
.Select(p => p.Note)
|
||||
.Concat(notificationList
|
||||
.Select(p => p.Note?.Renote)
|
||||
.Where(p => p != null))
|
||||
.Cast<Note>()
|
||||
.DistinctBy(p => p.Id),
|
||||
user, Filter.FilterContext.Notifications, accounts);
|
||||
var notes = await noteRenderer
|
||||
.RenderManyAsync(notificationList.Where(p => p.Note != null)
|
||||
.Select(p => p.Note)
|
||||
.Concat(notificationList.Select(p => p.Note?.Renote).Where(p => p != null))
|
||||
.Cast<Note>()
|
||||
.DistinctBy(p => p.Id),
|
||||
user, Filter.FilterContext.Notifications, accounts);
|
||||
|
||||
var parts = notificationList.Where(p => p.Reaction != null && EmojiService.IsCustomEmoji(p.Reaction))
|
||||
.Select(p =>
|
||||
|
@ -108,7 +108,7 @@ public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer,
|
|||
})
|
||||
.ToArrayAsync()
|
||||
.ContinueWithResultAsync(res => res.DistinctBy(e => e.Name)
|
||||
.ToDictionary(e => e.Name, e => e.Url));
|
||||
.ToDictionary(e => e.Name, e => e.Url));
|
||||
|
||||
return await notificationList
|
||||
.Select(p => RenderAsync(p, user, isPleroma, accounts, notes, emojiUrls))
|
||||
|
|
|
@ -13,9 +13,9 @@ public class PollRenderer(DatabaseContext db) : IScopedService
|
|||
var voted = (data?.Voted ?? await GetVotedAsync([poll], user)).Contains(poll.NoteId);
|
||||
|
||||
var ownVotes = (data?.OwnVotes ?? await GetOwnVotesAsync([poll], user)).Where(p => p.Key == poll.NoteId)
|
||||
.Select(p => p.Value)
|
||||
.DefaultIfEmpty([])
|
||||
.First();
|
||||
.Select(p => p.Value)
|
||||
.DefaultIfEmpty([])
|
||||
.First();
|
||||
|
||||
var res = new PollEntity
|
||||
{
|
||||
|
|
|
@ -118,11 +118,14 @@ public class SearchController(
|
|||
var host = match.Groups["host"].Value;
|
||||
|
||||
var result = await userResolver.ResolveOrNullAsync(GetQuery(username, host), ResolveFlags.Acct);
|
||||
|
||||
// @formatter:off
|
||||
return result switch
|
||||
{
|
||||
not null => [await userRenderer.RenderAsync(await userResolver.GetUpdatedUserAsync(result), user)],
|
||||
_ => []
|
||||
};
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,8 +99,8 @@ public class StatusController(
|
|||
throw GracefulException.Forbidden("Public preview is disabled on this instance");
|
||||
|
||||
var res = (await noteRenderer.GetReactionsAsync([note], user)).Where(r => r.Name.Split("@").First() ==
|
||||
Regex.Unescape(reaction))
|
||||
.ToArray();
|
||||
Regex.Unescape(reaction))
|
||||
.ToArray();
|
||||
|
||||
foreach (var item in res)
|
||||
{
|
||||
|
|
|
@ -264,12 +264,12 @@ public class AdminController(
|
|||
return await db.Relays
|
||||
.ToArrayAsync()
|
||||
.ContinueWithResultAsync(res => res.Select(p => new RelaySchemas.RelayResponse
|
||||
{
|
||||
Id = p.Id,
|
||||
Inbox = p.Inbox,
|
||||
Status = (RelaySchemas.RelayStatus)p.Status
|
||||
})
|
||||
.ToList());
|
||||
{
|
||||
Id = p.Id,
|
||||
Inbox = p.Inbox,
|
||||
Status = (RelaySchemas.RelayStatus)p.Status
|
||||
})
|
||||
.ToList());
|
||||
}
|
||||
|
||||
[HttpPost("relays")]
|
||||
|
@ -317,7 +317,8 @@ public class AdminController(
|
|||
string name, [SwaggerBodyExample("{\n \"enabled\": true\n}")] JsonDocument body
|
||||
)
|
||||
{
|
||||
var type = await policySvc.GetConfigurationTypeAsync(name) ?? throw GracefulException.NotFound("Policy not found");
|
||||
var type = await policySvc.GetConfigurationTypeAsync(name) ??
|
||||
throw GracefulException.NotFound("Policy not found");
|
||||
var data = body.Deserialize(type, JsonSerialization.Options) as IPolicyConfiguration;
|
||||
if (data?.GetType() != type) throw GracefulException.BadRequest("Invalid policy config");
|
||||
var serialized = JsonSerializer.Serialize(data, type, JsonSerialization.Options);
|
||||
|
|
|
@ -129,7 +129,7 @@ public class EmojiController(
|
|||
public async Task<EmojiResponse> UpdateEmoji(string id, UpdateEmojiRequest request)
|
||||
{
|
||||
var emoji = await emojiSvc.UpdateLocalEmojiAsync(id, request.Name, request.Aliases, request.Category,
|
||||
request.License, request.Sensitive) ??
|
||||
request.License, request.Sensitive) ??
|
||||
throw GracefulException.NotFound("Emoji not found");
|
||||
|
||||
return new EmojiResponse
|
||||
|
|
|
@ -17,24 +17,24 @@ namespace Iceshrimp.Backend.Controllers.Web;
|
|||
[Produces(MediaTypeNames.Application.Json)]
|
||||
public class InstanceController(DatabaseContext db, UserRenderer userRenderer) : ControllerBase
|
||||
{
|
||||
[HttpGet("staff")]
|
||||
[Authenticate]
|
||||
[Authorize]
|
||||
[ProducesResults(HttpStatusCode.OK)]
|
||||
public async Task<StaffResponse> GetStaff()
|
||||
{
|
||||
var admins = db.Users
|
||||
.Where(p => p.IsAdmin == true)
|
||||
.OrderBy(p => p.UsernameLower);
|
||||
var adminList = await userRenderer.RenderManyAsync(admins)
|
||||
.ToListAsync();
|
||||
[HttpGet("staff")]
|
||||
[Authenticate]
|
||||
[Authorize]
|
||||
[ProducesResults(HttpStatusCode.OK)]
|
||||
public async Task<StaffResponse> GetStaff()
|
||||
{
|
||||
var admins = db.Users
|
||||
.Where(p => p.IsAdmin == true)
|
||||
.OrderBy(p => p.UsernameLower);
|
||||
var adminList = await userRenderer.RenderManyAsync(admins)
|
||||
.ToListAsync();
|
||||
|
||||
var moderators = db.Users
|
||||
.Where(p => p.IsAdmin == false && p.IsModerator == true)
|
||||
.OrderBy(p => p.UsernameLower);
|
||||
var moderatorList = await userRenderer.RenderManyAsync(moderators)
|
||||
.ToListAsync();
|
||||
var moderators = db.Users
|
||||
.Where(p => p.IsAdmin == false && p.IsModerator == true)
|
||||
.OrderBy(p => p.UsernameLower);
|
||||
var moderatorList = await userRenderer.RenderManyAsync(moderators)
|
||||
.ToListAsync();
|
||||
|
||||
return new StaffResponse { Admins = adminList, Moderators = moderatorList };
|
||||
}
|
||||
return new StaffResponse { Admins = adminList, Moderators = moderatorList };
|
||||
}
|
||||
}
|
|
@ -71,7 +71,9 @@ public class MigrationController(
|
|||
aliasUri ??= await db.Users.IncludeCommonProperties()
|
||||
.Where(p => p.Id == rq.UserId)
|
||||
.FirstOrDefaultAsync()
|
||||
.ContinueWithResultAsync(p => p is null ? null : p.Uri ?? p.GetPublicUri(config.Value));
|
||||
.ContinueWithResultAsync(p => p is null
|
||||
? null
|
||||
: p.Uri ?? p.GetPublicUri(config.Value));
|
||||
}
|
||||
|
||||
if (aliasUri is null) throw GracefulException.NotFound("Alias user not found");
|
||||
|
|
|
@ -46,7 +46,7 @@ public class MiscController(DatabaseContext db, NoteRenderer noteRenderer, BiteS
|
|||
|
||||
await biteSvc.BiteAsync(user, target);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("muted_threads")]
|
||||
[LinkPagination(20, 40)]
|
||||
[ProducesResults(HttpStatusCode.OK)]
|
||||
|
|
|
@ -344,7 +344,7 @@ public class NoteController(
|
|||
.ToListAsync();
|
||||
|
||||
var res = await noteRenderer.RenderManyAsync(renotes.EnforceRenoteReplyVisibility(), user,
|
||||
Filter.FilterContext.Threads);
|
||||
Filter.FilterContext.Threads);
|
||||
return HttpContext.CreatePaginationWrapper(pq, renotes, res);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ public class NotificationController(DatabaseContext db, NotificationRenderer not
|
|||
.PrecomputeNoteVisibilities(user)
|
||||
.ToListAsync();
|
||||
|
||||
return await notificationRenderer.RenderManyAsync(notifications.EnforceRenoteReplyVisibility(p => p.Note), user);
|
||||
return await notificationRenderer.RenderManyAsync(notifications.EnforceRenoteReplyVisibility(p => p.Note),
|
||||
user);
|
||||
}
|
||||
|
||||
[HttpPost("{id}/read")]
|
||||
|
|
|
@ -71,9 +71,10 @@ public class NoteRenderer(
|
|||
|
||||
private async Task<NoteResponse> RenderBaseInternalAsync(Note note, User? user, NoteRendererDto? data = null)
|
||||
{
|
||||
var noteUser = (data?.Users ?? await GetUsersAsync([note])).First(p => p.Id == note.User.Id);
|
||||
var attachments = (data?.Attachments ?? await GetAttachmentsAsync([note])).Where(p => note.FileIds.Contains(p.Id));
|
||||
var reactions = (data?.Reactions ?? await GetReactionsAsync([note], user)).Where(p => p.NoteId == note.Id);
|
||||
var noteUser = (data?.Users ?? await GetUsersAsync([note])).First(p => p.Id == note.User.Id);
|
||||
var attachments =
|
||||
(data?.Attachments ?? await GetAttachmentsAsync([note])).Where(p => note.FileIds.Contains(p.Id));
|
||||
var reactions = (data?.Reactions ?? await GetReactionsAsync([note], user)).Where(p => p.NoteId == note.Id);
|
||||
var liked = data?.LikedNotes?.Contains(note.Id) ??
|
||||
await db.NoteLikes.AnyAsync(p => p.Note == note && p.User == user);
|
||||
var emoji = data?.Emoji?.Where(p => note.Emojis.Contains(p.Id)).ToList() ?? await GetEmojiAsync([note]);
|
||||
|
@ -138,8 +139,8 @@ public class NoteRenderer(
|
|||
Reacted = db.NoteReactions.Any(i => i.NoteId == p.First().NoteId &&
|
||||
i.Reaction == p.First().Reaction &&
|
||||
i.User == user),
|
||||
Name = p.First().Reaction,
|
||||
Url = null,
|
||||
Name = p.First().Reaction,
|
||||
Url = null,
|
||||
Sensitive = false,
|
||||
})
|
||||
.ToListAsync();
|
||||
|
|
|
@ -89,7 +89,9 @@ public class NotificationRenderer(UserRenderer userRenderer, NoteRenderer noteRe
|
|||
return bites.Select(p => new BiteResponse { Id = p.Id, BiteBack = p.TargetBiteId != null }).ToList();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<NotificationResponse>> RenderManyAsync(IEnumerable<Notification> notifications, User user)
|
||||
public async Task<IEnumerable<NotificationResponse>> RenderManyAsync(
|
||||
IEnumerable<Notification> notifications, User user
|
||||
)
|
||||
{
|
||||
var notificationsList = notifications.ToList();
|
||||
var data = new NotificationRendererDto
|
||||
|
|
|
@ -39,6 +39,7 @@ public class TimelineController(DatabaseContext db, NoteRenderer noteRenderer, C
|
|||
.PrecomputeVisibilities(user)
|
||||
.ToListAsync();
|
||||
|
||||
return await noteRenderer.RenderManyAsync(notes.EnforceRenoteReplyVisibility(), user, Filter.FilterContext.Home);
|
||||
return await noteRenderer.RenderManyAsync(notes.EnforceRenoteReplyVisibility(), user,
|
||||
Filter.FilterContext.Home);
|
||||
}
|
||||
}
|
|
@ -712,7 +712,7 @@ public static class QueryableExtensions
|
|||
{
|
||||
return query.Include(p => p.UserProfile);
|
||||
}
|
||||
|
||||
|
||||
public static IQueryable<Bite> IncludeCommonProperties(this IQueryable<Bite> query)
|
||||
{
|
||||
return query.Include(p => p.TargetNote)
|
||||
|
|
|
@ -64,7 +64,9 @@ public static class TaskExtensions
|
|||
continuation();
|
||||
}
|
||||
|
||||
public static async Task<TNewResult> ContinueWithResultAsync<TNewResult>(this Task task, Func<TNewResult> continuation)
|
||||
public static async Task<TNewResult> ContinueWithResultAsync<TNewResult>(
|
||||
this Task task, Func<TNewResult> continuation
|
||||
)
|
||||
{
|
||||
await task;
|
||||
return continuation();
|
||||
|
|
|
@ -212,7 +212,8 @@ public static class WebApplicationExtensions
|
|||
{
|
||||
app.Logger.LogInformation("Migrating files to object storage, this will take a while...");
|
||||
db.Database.SetCommandTimeout(0);
|
||||
await provider.GetRequiredService<StorageMaintenanceService>().MigrateLocalFilesAsync(args.Contains("--purge"));
|
||||
await provider.GetRequiredService<StorageMaintenanceService>()
|
||||
.MigrateLocalFilesAsync(args.Contains("--purge"));
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
|
@ -224,7 +225,8 @@ public static class WebApplicationExtensions
|
|||
|
||||
if (args.Contains("--cleanup-storage"))
|
||||
{
|
||||
await provider.GetRequiredService<StorageMaintenanceService>().CleanupStorageAsync(args.Contains("--dry-run"));
|
||||
await provider.GetRequiredService<StorageMaintenanceService>()
|
||||
.CleanupStorageAsync(args.Contains("--dry-run"));
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,8 +47,9 @@ public class ObjectResolver(
|
|||
logger.LogDebug("Refusing to resolve object with null id property");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!Uri.TryCreate(baseObj.Id, UriKind.Absolute, out var uri) || uri.Scheme != "https"){
|
||||
|
||||
if (!Uri.TryCreate(baseObj.Id, UriKind.Absolute, out var uri) || uri.Scheme != "https")
|
||||
{
|
||||
logger.LogDebug("Refusing to resolve object with invalid id property");
|
||||
return null;
|
||||
}
|
||||
|
@ -61,7 +62,8 @@ public class ObjectResolver(
|
|||
return new ASActor { Id = baseObj.Id };
|
||||
if (uri.AbsolutePath.StartsWith("/follows/"))
|
||||
return new ASFollow { Id = baseObj.Id };
|
||||
throw GracefulException.UnprocessableEntity($"Unable to resolve local object of unknown type: {baseObj.Id}");
|
||||
throw GracefulException
|
||||
.UnprocessableEntity($"Unable to resolve local object of unknown type: {baseObj.Id}");
|
||||
}
|
||||
|
||||
if (await federationCtrl.ShouldBlockAsync(baseObj.Id))
|
||||
|
@ -90,7 +92,9 @@ public class ObjectResolver(
|
|||
}
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<ASObject> IterateCollectionAsync(ASCollection? collection, User? user = null, int pageLimit = 10)
|
||||
public async IAsyncEnumerable<ASObject> IterateCollectionAsync(
|
||||
ASCollection? collection, User? user = null, int pageLimit = 10
|
||||
)
|
||||
{
|
||||
if (collection == null) yield break;
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public interface IPlugin
|
|||
public string Name { get; }
|
||||
public string Version { get; }
|
||||
|
||||
public Task InitializeAsync() => Task.CompletedTask;
|
||||
public Task InitializeAsync() => Task.CompletedTask;
|
||||
public WebApplicationBuilder BuilderHook(WebApplicationBuilder builder) => builder;
|
||||
public WebApplication AppHook(WebApplication app) => app;
|
||||
}
|
|
@ -21,7 +21,7 @@ public class ErrorHandlerMiddleware(
|
|||
) : IMiddlewareService
|
||||
{
|
||||
public static ServiceLifetime Lifetime => ServiceLifetime.Singleton;
|
||||
|
||||
|
||||
private static readonly XmlSerializer XmlSerializer = new(typeof(ErrorResponse));
|
||||
|
||||
public async Task InvokeAsync(HttpContext ctx, RequestDelegate next)
|
||||
|
|
|
@ -53,7 +53,8 @@ public class DeliverQueue(int parallelism)
|
|||
_ = followup.ExecuteTaskAsync("UpdateInstanceMetadata", async provider =>
|
||||
{
|
||||
var instanceSvc = provider.GetRequiredService<InstanceService>();
|
||||
await instanceSvc.MarkInstanceAsUnresponsiveAsync(jobData.RecipientHost, new Uri(jobData.InboxUrl).Host);
|
||||
var inboxHost = new Uri(jobData.InboxUrl).Host;
|
||||
await instanceSvc.MarkInstanceAsUnresponsiveAsync(jobData.RecipientHost, inboxHost);
|
||||
});
|
||||
|
||||
throw;
|
||||
|
|
|
@ -53,7 +53,9 @@ public class CustomHttpClient : HttpClient, IService<HttpClient>, ISingletonServ
|
|||
private bool AllowLocalIPv4 => Security?.CurrentValue.AllowLocalIPv4 ?? false;
|
||||
private bool AllowLocalIPv6 => Security?.CurrentValue.AllowLocalIPv6 ?? false;
|
||||
|
||||
public async ValueTask<Stream> ConnectCallbackAsync(SocketsHttpConnectionContext context, CancellationToken token)
|
||||
public async ValueTask<Stream> ConnectCallbackAsync(
|
||||
SocketsHttpConnectionContext context, CancellationToken token
|
||||
)
|
||||
{
|
||||
var sortedRecords = await GetSortedAddressesAsync(context.DnsEndPoint.Host, token);
|
||||
|
||||
|
|
|
@ -283,7 +283,8 @@ public class DriveService(
|
|||
blurhash = res.Blurhash;
|
||||
|
||||
var processed = await res.RequestedFormats
|
||||
.Select(p => ProcessAndStoreFileVersionAsync(p.Key, p.Value, request.Filename))
|
||||
.Select(p => ProcessAndStoreFileVersionAsync(p.Key, p.Value,
|
||||
request.Filename))
|
||||
.AwaitAllNoConcurrencyAsync()
|
||||
.ContinueWithResultAsync(p => p.ToImmutableArray());
|
||||
|
||||
|
@ -399,12 +400,14 @@ public class DriveService(
|
|||
|
||||
private Task<string> StoreFileVersionAsync(Stream stream, string accessKey, string fileName, string mimeType)
|
||||
{
|
||||
// @formatter:off
|
||||
return storageConfig.Value.Provider switch
|
||||
{
|
||||
Enums.FileStorage.Local => StoreFileVersionLocalStorageAsync(stream, accessKey),
|
||||
Enums.FileStorage.ObjectStorage => StoreFileVersionObjectStorageAsync(stream, accessKey, fileName, mimeType),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private async Task<string> StoreFileVersionLocalStorageAsync(Stream stream, string filename)
|
||||
|
|
|
@ -91,13 +91,8 @@ public class EmojiImportService(
|
|||
|
||||
try
|
||||
{
|
||||
await emojiSvc.CreateEmojiFromStreamAsync(
|
||||
buffer,
|
||||
name,
|
||||
mimeType,
|
||||
emoji.Emoji.Aliases,
|
||||
emoji.Emoji.Category
|
||||
);
|
||||
await emojiSvc.CreateEmojiFromStreamAsync(buffer, name, mimeType, emoji.Emoji.Aliases,
|
||||
emoji.Emoji.Category);
|
||||
|
||||
logger.LogDebug("Imported emoji {emoji}", name);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ public partial class EmojiService(
|
|||
{
|
||||
var user = await sysUserSvc.GetInstanceActorAsync();
|
||||
var driveFile = await driveSvc.StoreFileAsync(existing.OriginalUrl, user, false, forceStore: true,
|
||||
skipImageProcessing: false) ??
|
||||
skipImageProcessing: false) ??
|
||||
throw new Exception("Error storing emoji file");
|
||||
|
||||
var emoji = new Emoji
|
||||
|
@ -245,4 +245,4 @@ public partial class EmojiService(
|
|||
|
||||
[GeneratedRegex(@"^:?([\w+-]+)@([a-zA-Z0-9._\-]+\.[a-zA-Z0-9._\-]+):?$", RegexOptions.Compiled)]
|
||||
private static partial Regex RemoteCustomEmojiRegex { get; }
|
||||
}
|
||||
}
|
|
@ -9,45 +9,45 @@ using static Iceshrimp.Backend.Core.Federation.ActivityPub.UserResolver;
|
|||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class ImportExportService(
|
||||
DatabaseContext db,
|
||||
ILogger<UserService> logger,
|
||||
IOptions<Config.InstanceSection> instance,
|
||||
CacheService cacheSvc,
|
||||
UserService userSvc,
|
||||
ActivityPub.UserResolver userResolver
|
||||
DatabaseContext db,
|
||||
ILogger<UserService> logger,
|
||||
IOptions<Config.InstanceSection> instance,
|
||||
CacheService cacheSvc,
|
||||
UserService userSvc,
|
||||
ActivityPub.UserResolver userResolver
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task<string> ExportFollowingAsync(User user)
|
||||
{
|
||||
var followees = await db.Followings
|
||||
.Include(p => p.Followee)
|
||||
.Where(p => p.FollowerId == user.Id)
|
||||
.Select(p => p.Followee)
|
||||
.Where(p => !p.IsDeleted && !p.IsSystemUser && p.MovedToUri == null)
|
||||
.OrderBy(p => p.Host)
|
||||
.ThenBy(p => p.UsernameLower)
|
||||
.Select(p => p.GetFqn(instance.Value.AccountDomain))
|
||||
.ToListAsync();
|
||||
public async Task<string> ExportFollowingAsync(User user)
|
||||
{
|
||||
var followees = await db.Followings
|
||||
.Include(p => p.Followee)
|
||||
.Where(p => p.FollowerId == user.Id)
|
||||
.Select(p => p.Followee)
|
||||
.Where(p => !p.IsDeleted && !p.IsSystemUser && p.MovedToUri == null)
|
||||
.OrderBy(p => p.Host)
|
||||
.ThenBy(p => p.UsernameLower)
|
||||
.Select(p => p.GetFqn(instance.Value.AccountDomain))
|
||||
.ToListAsync();
|
||||
|
||||
return string.Join("\n", followees);
|
||||
}
|
||||
return string.Join("\n", followees);
|
||||
}
|
||||
|
||||
public async Task ImportFollowingAsync(User user, List<string> fqns)
|
||||
{
|
||||
foreach (var fqn in fqns)
|
||||
{
|
||||
try
|
||||
{
|
||||
var followee = await userResolver.ResolveAsync($"acct:{fqn}", ResolveFlags.Acct);
|
||||
await userSvc.FollowUserAsync(user, followee);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogWarning("Failed to import follow {followee} for user {follower}: {error}",
|
||||
fqn, user.Id, e);
|
||||
}
|
||||
}
|
||||
public async Task ImportFollowingAsync(User user, List<string> fqns)
|
||||
{
|
||||
foreach (var fqn in fqns)
|
||||
{
|
||||
try
|
||||
{
|
||||
var followee = await userResolver.ResolveAsync($"acct:{fqn}", ResolveFlags.Acct);
|
||||
await userSvc.FollowUserAsync(user, followee);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogWarning("Failed to import follow {followee} for user {follower}: {error}",
|
||||
fqn, user.Id, e);
|
||||
}
|
||||
}
|
||||
|
||||
await QueryableTimelineExtensions.ResetHeuristicAsync(user, cacheSvc);
|
||||
}
|
||||
await QueryableTimelineExtensions.ResetHeuristicAsync(user, cacheSvc);
|
||||
}
|
||||
}
|
|
@ -1119,8 +1119,8 @@ public class NoteService(
|
|||
var result = await attachments
|
||||
.OfType<ASDocument>()
|
||||
.Take(10)
|
||||
.Select(p => driveSvc.StoreFileAsync(p.Url?.Id, user, p.Sensitive ?? sensitive, p.Description,
|
||||
p.MediaType, logExisting))
|
||||
.Select(p => driveSvc.StoreFileAsync(p.Url?.Id, user, p.Sensitive ?? sensitive,
|
||||
p.Description, p.MediaType, logExisting))
|
||||
.AwaitAllNoConcurrencyAsync();
|
||||
|
||||
return result.Where(p => p != null).Cast<DriveFile>().ToList();
|
||||
|
|
|
@ -248,14 +248,14 @@ public class StorageMaintenanceService(
|
|||
})
|
||||
.ToArrayAsync()
|
||||
.ContinueWithResultAsync(res => res.SelectMany(p => new List<string?>
|
||||
{
|
||||
p.AccessKey,
|
||||
p.ThumbnailAccessKey,
|
||||
p.PublicAccessKey
|
||||
})
|
||||
.NotNull()
|
||||
.Append(".iceshrimp-test")
|
||||
.ToHashSet());
|
||||
{
|
||||
p.AccessKey,
|
||||
p.ThumbnailAccessKey,
|
||||
p.PublicAccessKey
|
||||
})
|
||||
.NotNull()
|
||||
.Append(".iceshrimp-test")
|
||||
.ToHashSet());
|
||||
|
||||
logger.LogInformation("Loaded {count} files from database.", filenames.Count);
|
||||
var count = 0;
|
||||
|
|
|
@ -72,7 +72,9 @@ public class UserProfileMentionsResolver(
|
|||
return (mentions, splitDomainMapping);
|
||||
}
|
||||
|
||||
public async Task<List<Note.MentionedUser>> ResolveMentionsAsync(UserProfile.Field[]? fields, string? bio, string? host)
|
||||
public async Task<List<Note.MentionedUser>> ResolveMentionsAsync(
|
||||
UserProfile.Field[]? fields, string? bio, string? host
|
||||
)
|
||||
{
|
||||
if (fields is not { Length: > 0 } && bio == null) return [];
|
||||
var input = (fields ?? [])
|
||||
|
|
|
@ -448,9 +448,9 @@ public class UserService(
|
|||
private async Task<Func<Task>> ResolveAvatarAndBannerAsync(User user, ASActor actor)
|
||||
{
|
||||
var avatar = await driveSvc.StoreFileAsync(actor.Avatar?.Url?.Link, user, actor.Avatar?.Sensitive ?? false,
|
||||
logExisting: false);
|
||||
logExisting: false);
|
||||
var banner = await driveSvc.StoreFileAsync(actor.Banner?.Url?.Link, user, actor.Banner?.Sensitive ?? false,
|
||||
logExisting: false);
|
||||
logExisting: false);
|
||||
|
||||
var prevAvatarId = user.AvatarId;
|
||||
var prevBannerId = user.BannerId;
|
||||
|
@ -782,15 +782,16 @@ public class UserService(
|
|||
|
||||
if (follower.IsRemoteUser)
|
||||
{
|
||||
// @formatter:off
|
||||
_ = followupTaskSvc.ExecuteTaskAsync("IncrementInstanceIncomingFollowsCounter", async provider =>
|
||||
{
|
||||
var bgDb = provider.GetRequiredService<DatabaseContext>();
|
||||
var bgInstanceSvc = provider.GetRequiredService<InstanceService>();
|
||||
var dbInstance = await bgInstanceSvc.GetUpdatedInstanceMetadataAsync(follower);
|
||||
await bgDb.Instances.Where(p => p.Id == dbInstance.Id)
|
||||
.ExecuteUpdateAsync(p => p.SetProperty(i => i.IncomingFollows,
|
||||
i => i.IncomingFollows + 1));
|
||||
.ExecuteUpdateAsync(p => p.SetProperty(i => i.IncomingFollows, i => i.IncomingFollows + 1));
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -1037,7 +1038,9 @@ public class UserService(
|
|||
[SuppressMessage("ReSharper", "EntityFramework.NPlusOne.IncompleteDataQuery", Justification = "Projectables")]
|
||||
[SuppressMessage("ReSharper", "EntityFramework.NPlusOne.IncompleteDataUsage", Justification = "Same as above")]
|
||||
[SuppressMessage("ReSharper", "SuggestBaseTypeForParameter", Justification = "Method only makes sense for users")]
|
||||
private async Task<User> UpdateProfileMentionsAsync(User user, ASActor? actor, bool force = false, bool wait = false)
|
||||
private async Task<User> UpdateProfileMentionsAsync(
|
||||
User user, ASActor? actor, bool force = false, bool wait = false
|
||||
)
|
||||
{
|
||||
if (followupTaskSvc.IsBackgroundWorker.Value && !force) return user;
|
||||
if (KeyedLocker.IsInUse($"profileMentions:{user.Id}")) return user;
|
||||
|
@ -1056,7 +1059,8 @@ public class UserService(
|
|||
|
||||
if (actor != null)
|
||||
{
|
||||
var (mentions, splitDomainMapping) = await bgMentionsResolver.ResolveMentionsAsync(actor, bgUser.Host);
|
||||
var (mentions, splitDomainMapping) =
|
||||
await bgMentionsResolver.ResolveMentionsAsync(actor, bgUser.Host);
|
||||
var fields = actor.Attachments != null
|
||||
? await actor.Attachments
|
||||
.OfType<ASField>()
|
||||
|
@ -1079,8 +1083,9 @@ public class UserService(
|
|||
}
|
||||
else
|
||||
{
|
||||
bgUser.UserProfile.Mentions = await bgMentionsResolver.ResolveMentionsAsync(bgUser.UserProfile.Fields,
|
||||
bgUser.UserProfile.Description, bgUser.Host);
|
||||
bgUser.UserProfile.Mentions =
|
||||
await bgMentionsResolver.ResolveMentionsAsync(bgUser.UserProfile.Fields,
|
||||
bgUser.UserProfile.Description, bgUser.Host);
|
||||
}
|
||||
|
||||
bgUser.UserProfile.MentionsResolved = true;
|
||||
|
@ -1379,7 +1384,8 @@ public class UserService(
|
|||
var followers = db.Followings
|
||||
.Where(p => p.Followee == source && p.Follower.IsLocalUser)
|
||||
.Select(p => p.Follower)
|
||||
.AsChunkedAsyncEnumerableAsync(50, p => p.Id, hook: p => p.PrecomputeRelationshipData(source));
|
||||
.AsChunkedAsyncEnumerableAsync(50, p => p.Id,
|
||||
hook: p => p.PrecomputeRelationshipData(source));
|
||||
|
||||
await foreach (var follower in followers)
|
||||
{
|
||||
|
@ -1407,7 +1413,8 @@ public class UserService(
|
|||
var following = db.Followings
|
||||
.Where(p => p.Follower == source)
|
||||
.Select(p => p.Follower)
|
||||
.AsChunkedAsyncEnumerableAsync(50, p => p.Id, hook: p => p.PrecomputeRelationshipData(source));
|
||||
.AsChunkedAsyncEnumerableAsync(50, p => p.Id,
|
||||
hook: p => p.PrecomputeRelationshipData(source));
|
||||
|
||||
await foreach (var followee in following)
|
||||
{
|
||||
|
|
|
@ -22,7 +22,8 @@ public class IndexModel(MetaService meta, IOptionsSnapshot<Config.InstanceSectio
|
|||
return Redirect(dest);
|
||||
|
||||
var (instanceName, instanceDescription, contactEmail) =
|
||||
await meta.GetManyAsync(MetaEntity.InstanceName, MetaEntity.InstanceDescription, MetaEntity.AdminContactEmail);
|
||||
await meta.GetManyAsync(MetaEntity.InstanceName, MetaEntity.InstanceDescription,
|
||||
MetaEntity.AdminContactEmail);
|
||||
|
||||
InstanceName = instanceName ?? "Iceshrimp.NET";
|
||||
InstanceDescription =
|
||||
|
|
|
@ -91,4 +91,4 @@ var elapsed = (DateTime.Now - Process.GetCurrentProcess().StartTime).GetTotalMil
|
|||
app.Logger.LogInformation("Startup complete after {ms} ms.", elapsed);
|
||||
await app.StartAsync();
|
||||
app.SetKestrelUnixSocketPermissions();
|
||||
await app.WaitForShutdownAsync();
|
||||
await app.WaitForShutdownAsync();
|
|
@ -33,7 +33,7 @@ internal class NoteControllerModel(ApiClient api)
|
|||
|
||||
public Task BiteNoteAsync(string id) =>
|
||||
api.CallAsync(HttpMethod.Post, $"/notes/{id}/bite");
|
||||
|
||||
|
||||
public Task<ValueResponse?> LikeNoteAsync(string id) =>
|
||||
api.CallNullableAsync<ValueResponse>(HttpMethod.Post, $"/notes/{id}/like");
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ namespace Iceshrimp.Frontend.Core.ControllerModels;
|
|||
|
||||
internal class SettingsControllerModel(ApiClient api)
|
||||
{
|
||||
public Task<UserSettingsEntity> GetSettingsAsync() => api.CallAsync<UserSettingsEntity>(HttpMethod.Get, "/settings");
|
||||
public Task<UserSettingsEntity> GetSettingsAsync() =>
|
||||
api.CallAsync<UserSettingsEntity>(HttpMethod.Get, "/settings");
|
||||
|
||||
public Task<bool> UpdateSettingsAsync(UserSettingsEntity settings) =>
|
||||
api.CallNullableAsync(HttpMethod.Put, "/settings", data: settings);
|
||||
|
|
|
@ -26,8 +26,11 @@ internal class UserControllerModel(ApiClient api)
|
|||
|
||||
public Task BiteUserAsync(string id) =>
|
||||
api.CallAsync(HttpMethod.Post, $"/users/{id}/bite");
|
||||
|
||||
|
||||
public Task<bool> FollowUserAsync(string id) => api.CallNullableAsync(HttpMethod.Post, $"/users/{id}/follow");
|
||||
public Task<bool> RemoveUserFromFollowersAsync(string id) => api.CallNullableAsync(HttpMethod.Post, $"/users/{id}/remove_from_followers");
|
||||
|
||||
public Task<bool> RemoveUserFromFollowersAsync(string id) =>
|
||||
api.CallNullableAsync(HttpMethod.Post, $"/users/{id}/remove_from_followers");
|
||||
|
||||
public Task<bool> UnfollowUserAsync(string id) => api.CallNullableAsync(HttpMethod.Post, $"/users/{id}/unfollow");
|
||||
}
|
|
@ -8,7 +8,9 @@ namespace Iceshrimp.Frontend.Core.Miscellaneous;
|
|||
|
||||
public static class MfmRenderer
|
||||
{
|
||||
public static async Task<MarkupString> RenderStringAsync(string text, List<EmojiResponse> emoji, bool simple = false)
|
||||
public static async Task<MarkupString> RenderStringAsync(
|
||||
string text, List<EmojiResponse> emoji, bool simple = false
|
||||
)
|
||||
{
|
||||
var res = simple ? Mfm.parseSimple(text) : Mfm.parse(text);
|
||||
var context = BrowsingContext.New();
|
||||
|
@ -42,7 +44,9 @@ public static class MfmRenderer
|
|||
return el;
|
||||
}
|
||||
|
||||
private static INode RenderNode(MfmNodeTypes.MfmNode node, IDocument document, List<EmojiResponse> emoji, bool simple)
|
||||
private static INode RenderNode(
|
||||
MfmNodeTypes.MfmNode node, IDocument document, List<EmojiResponse> emoji, bool simple
|
||||
)
|
||||
{
|
||||
// Hard wrap makes this impossible to read
|
||||
// @formatter:off
|
||||
|
|
|
@ -31,9 +31,9 @@ internal class UpdateService
|
|||
_nav = nav;
|
||||
|
||||
_moduleTask = new Lazy<Task<IJSObjectReference>>(() => js.InvokeAsync<IJSObjectReference>(
|
||||
"import",
|
||||
"./Core/Services/UpdateService.cs.js")
|
||||
.AsTask());
|
||||
"import",
|
||||
"./Core/Services/UpdateService.cs.js")
|
||||
.AsTask());
|
||||
Timer = new Timer(CallbackAsync, null, TimeSpan.Zero, TimeSpan.FromSeconds(60));
|
||||
_ = RegisterUpdateCallbackAsync();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue