[backend/asp] Make services runtime-discoverable
This commit is contained in:
parent
705e061f74
commit
4356a47b9d
56 changed files with 255 additions and 213 deletions
|
@ -1,9 +1,11 @@
|
|||
using AngleSharp.Io;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Microsoft.AspNetCore.Routing.Matching;
|
||||
|
||||
namespace Iceshrimp.Backend.Components.PublicPreview.Attributes;
|
||||
|
||||
public class PublicPreviewRouteMatcher : MatcherPolicy, IEndpointSelectorPolicy
|
||||
public class PublicPreviewRouteMatcher : MatcherPolicy, IEndpointSelectorPolicy, ISingletonService,
|
||||
IService<MatcherPolicy>
|
||||
{
|
||||
public override int Order => 99999; // That's ActionConstraintMatcherPolicy - 1
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Helpers.LibMfm.Conversion;
|
||||
using Iceshrimp.Parsing;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
@ -7,7 +8,7 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Iceshrimp.Backend.Components.PublicPreview.Renderers;
|
||||
|
||||
public class MfmRenderer(IOptions<Config.InstanceSection> config)
|
||||
public class MfmRenderer(IOptions<Config.InstanceSection> config) : ISingletonService
|
||||
{
|
||||
private readonly MfmConverter _converter = new(config);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ public class NoteRenderer(
|
|||
MfmRenderer mfm,
|
||||
IOptions<Config.InstanceSection> instance,
|
||||
IOptionsSnapshot<Config.SecuritySection> security
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task<PreviewNote?> RenderOne(Note? note)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ public class UserRenderer(
|
|||
MfmRenderer mfm,
|
||||
IOptions<Config.InstanceSection> instance,
|
||||
IOptionsSnapshot<Config.SecuritySection> security
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task<PreviewUser?> RenderOne(User? user)
|
||||
{
|
||||
|
|
|
@ -29,7 +29,7 @@ public class ActivityPubController(
|
|||
ActivityPub.NoteRenderer noteRenderer,
|
||||
ActivityPub.UserRenderer userRenderer,
|
||||
IOptions<Config.InstanceSection> config
|
||||
) : ControllerBase
|
||||
) : ControllerBase, IScopedService
|
||||
{
|
||||
[HttpGet("/notes/{id}")]
|
||||
[AuthorizedFetch]
|
||||
|
|
|
@ -20,7 +20,7 @@ public class NoteRenderer(
|
|||
MfmConverter mfmConverter,
|
||||
DatabaseContext db,
|
||||
EmojiService emojiSvc
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
private static readonly FilterResultEntity InaccessibleFilter = new()
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
|
||||
namespace Iceshrimp.Backend.Controllers.Mastodon.Renderers;
|
||||
|
||||
public class NotificationRenderer(DatabaseContext db, NoteRenderer noteRenderer, UserRenderer userRenderer)
|
||||
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,
|
||||
|
|
|
@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
|
||||
namespace Iceshrimp.Backend.Controllers.Mastodon.Renderers;
|
||||
|
||||
public class PollRenderer(DatabaseContext db)
|
||||
public class PollRenderer(DatabaseContext db) : IScopedService
|
||||
{
|
||||
public async Task<PollEntity> RenderAsync(Poll poll, User? user, PollRendererDto? data = null)
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@ public class UserRenderer(
|
|||
IOptionsSnapshot<Config.SecuritySection> security,
|
||||
MfmConverter mfmConverter,
|
||||
DatabaseContext db
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
private readonly string _transparent = $"https://{config.Value.WebDomain}/assets/transparent.png";
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ public class NoteRenderer(
|
|||
DatabaseContext db,
|
||||
EmojiService emojiSvc,
|
||||
IOptions<Config.InstanceSection> config
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task<NoteResponse> RenderOne(
|
||||
Note note, User? user, Filter.FilterContext? filterContext = null, NoteRendererDto? data = null
|
||||
|
|
|
@ -5,7 +5,7 @@ using static Iceshrimp.Shared.Schemas.Web.NotificationResponse;
|
|||
|
||||
namespace Iceshrimp.Backend.Controllers.Web.Renderers;
|
||||
|
||||
public class NotificationRenderer(UserRenderer userRenderer, NoteRenderer noteRenderer)
|
||||
public class NotificationRenderer(UserRenderer userRenderer, NoteRenderer noteRenderer) : IScopedService
|
||||
{
|
||||
private static NotificationResponse Render(Notification notification, NotificationRendererDto data)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
|
||||
namespace Iceshrimp.Backend.Controllers.Web.Renderers;
|
||||
|
||||
public class UserProfileRenderer(DatabaseContext db)
|
||||
public class UserProfileRenderer(DatabaseContext db) : IScopedService
|
||||
{
|
||||
public async Task<UserProfileResponse> RenderOne(User user, User? localUser, UserRendererDto? data = null)
|
||||
{
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
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.Web;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Iceshrimp.Backend.Controllers.Web.Renderers;
|
||||
|
||||
public class UserRenderer(IOptions<Config.InstanceSection> config, DatabaseContext db)
|
||||
public class UserRenderer(IOptions<Config.InstanceSection> config, DatabaseContext db) : IScopedService
|
||||
{
|
||||
private UserResponse Render(User user, UserRendererDto data)
|
||||
{
|
||||
|
|
|
@ -3,19 +3,10 @@ using System.Reflection;
|
|||
using System.Threading.RateLimiting;
|
||||
using System.Xml.Linq;
|
||||
using Iceshrimp.AssemblyUtils;
|
||||
using Iceshrimp.Backend.Components.PublicPreview.Attributes;
|
||||
using Iceshrimp.Backend.Components.PublicPreview.Renderers;
|
||||
using Iceshrimp.Backend.Controllers.Federation;
|
||||
using Iceshrimp.Backend.Controllers.Mastodon.Renderers;
|
||||
using Iceshrimp.Backend.Controllers.Web.Renderers;
|
||||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Federation.WebFinger;
|
||||
using Iceshrimp.Backend.Core.Helpers;
|
||||
using Iceshrimp.Backend.Core.Helpers.LibMfm.Conversion;
|
||||
using Iceshrimp.Backend.Core.Middleware;
|
||||
using Iceshrimp.Backend.Core.Services;
|
||||
using Iceshrimp.Backend.Core.Services.ImageProcessing;
|
||||
using Iceshrimp.Backend.SignalR.Authentication;
|
||||
using Iceshrimp.Shared.Configuration;
|
||||
using Iceshrimp.Shared.Schemas.Web;
|
||||
|
@ -33,9 +24,6 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
|
|||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using NoteRenderer = Iceshrimp.Backend.Controllers.Web.Renderers.NoteRenderer;
|
||||
using NotificationRenderer = Iceshrimp.Backend.Controllers.Web.Renderers.NotificationRenderer;
|
||||
using UserRenderer = Iceshrimp.Backend.Controllers.Web.Renderers.UserRenderer;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Extensions;
|
||||
|
||||
|
@ -43,91 +31,40 @@ public static class ServiceExtensions
|
|||
{
|
||||
public static void AddServices(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
// Transient = instantiated per request and class
|
||||
var config = configuration.Get<Config>() ?? throw new Exception("Failed to read storage config section");
|
||||
|
||||
// Scoped = instantiated per request
|
||||
services
|
||||
.AddScoped<ActivityPub.ActivityRenderer>()
|
||||
.AddScoped<ActivityPub.UserRenderer>()
|
||||
.AddScoped<ActivityPub.NoteRenderer>()
|
||||
.AddScoped<ActivityPub.UserResolver>()
|
||||
.AddScoped<ActivityPub.ObjectResolver>()
|
||||
.AddScoped<ActivityPub.MentionsResolver>()
|
||||
.AddScoped<ActivityPub.ActivityDeliverService>()
|
||||
.AddScoped<ActivityPub.FederationControlService>()
|
||||
.AddScoped<ActivityPub.ActivityHandlerService>()
|
||||
.AddScoped<ActivityPub.ActivityFetcherService>()
|
||||
.AddScoped<UserService>()
|
||||
.AddScoped<NoteService>()
|
||||
.AddScoped<EmojiService>()
|
||||
.AddScoped<EmojiImportService>()
|
||||
.AddScoped<WebFingerService>()
|
||||
.AddScoped<SystemUserService>()
|
||||
.AddScoped<DriveService>()
|
||||
.AddScoped<NotificationService>()
|
||||
.AddScoped<DatabaseMaintenanceService>()
|
||||
.AddScoped<BiteService>()
|
||||
.AddScoped<ImportExportService>()
|
||||
.AddScoped<UserProfileMentionsResolver>()
|
||||
.AddScoped<Controllers.Mastodon.Renderers.UserRenderer>()
|
||||
.AddScoped<Controllers.Mastodon.Renderers.NoteRenderer>()
|
||||
.AddScoped<Controllers.Mastodon.Renderers.NotificationRenderer>()
|
||||
.AddScoped<PollRenderer>()
|
||||
.AddScoped<PollService>()
|
||||
.AddScoped<NoteRenderer>()
|
||||
.AddScoped<UserRenderer>()
|
||||
.AddScoped<NotificationRenderer>()
|
||||
.AddScoped<ActivityPubController>()
|
||||
.AddScoped<FollowupTaskService>()
|
||||
.AddScoped<InstanceService>()
|
||||
.AddScoped<MfmConverter>()
|
||||
.AddScoped<UserProfileRenderer>()
|
||||
.AddScoped<CacheService>()
|
||||
.AddScoped<MetaService>()
|
||||
.AddScoped<StorageMaintenanceService>()
|
||||
.AddScoped<RelayService>()
|
||||
.AddScoped<Components.PublicPreview.Renderers.UserRenderer>()
|
||||
.AddScoped<Components.PublicPreview.Renderers.NoteRenderer>();
|
||||
var serviceTypes = PluginLoader
|
||||
.Assemblies.Prepend(Assembly.GetExecutingAssembly())
|
||||
.SelectMany(AssemblyLoader.GetImplementationsOfInterface<IService>)
|
||||
.OrderBy(type => type.GetInterfaceProperty<IService, int?>(nameof(IService.Priority)) ?? 0)
|
||||
.ToArray();
|
||||
|
||||
// Singleton = instantiated once across application lifetime
|
||||
services
|
||||
.AddSingleton<HttpClient, CustomHttpClient>()
|
||||
.AddSingleton<HttpRequestService>()
|
||||
.AddSingleton<CronService>()
|
||||
.AddSingleton<QueueService>()
|
||||
.AddSingleton<ObjectStorageService>()
|
||||
.AddSingleton<EventService>()
|
||||
.AddSingleton<PushService>()
|
||||
.AddSingleton<StreamingService>()
|
||||
.AddSingleton<ImageProcessor>()
|
||||
.AddSingleton<RazorViewRenderService>()
|
||||
.AddSingleton<MfmRenderer>()
|
||||
.AddSingleton<MatcherPolicy, PublicPreviewRouteMatcher>()
|
||||
.AddSingleton<PolicyService>();
|
||||
|
||||
var config = configuration.GetSection("Storage").Get<Config.StorageSection>() ??
|
||||
throw new Exception("Failed to read storage config section");
|
||||
|
||||
switch (config.MediaProcessing.ImageProcessor)
|
||||
foreach (var type in serviceTypes)
|
||||
{
|
||||
case Enums.ImageProcessor.LibVips:
|
||||
services.AddSingleton<IImageProcessor, VipsProcessor>();
|
||||
services.AddSingleton<IImageProcessor, ImageSharpProcessor>();
|
||||
break;
|
||||
case Enums.ImageProcessor.ImageSharp:
|
||||
services.AddSingleton<IImageProcessor, ImageSharpProcessor>();
|
||||
break;
|
||||
case Enums.ImageProcessor.None:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
if (type.GetInterfaceProperty<IService, ServiceLifetime?>(nameof(IService.Lifetime)) is not { } lifetime)
|
||||
continue;
|
||||
|
||||
if (type.GetInterface(nameof(IConditionalService)) != null)
|
||||
if (type.CallInterfaceMethod(nameof(IConditionalService.Predicate), config) is not true)
|
||||
continue;
|
||||
|
||||
var serviceType = type.GetInterfaceProperty<IService, Type>(nameof(IService.ServiceType)) ?? type;
|
||||
services.Add(new ServiceDescriptor(serviceType, type, lifetime));
|
||||
}
|
||||
|
||||
// Hosted services = long running background tasks
|
||||
// Note: These need to be added as a singleton as well to ensure data consistency
|
||||
services.AddHostedService<CronService>(provider => provider.GetRequiredService<CronService>());
|
||||
services.AddHostedService<QueueService>(provider => provider.GetRequiredService<QueueService>());
|
||||
services.AddHostedService<PushService>(provider => provider.GetRequiredService<PushService>());
|
||||
var hostedServiceTypes = PluginLoader
|
||||
.Assemblies.Prepend(Assembly.GetExecutingAssembly())
|
||||
.SelectMany(AssemblyLoader.GetImplementationsOfInterface<IHostedService>)
|
||||
.ToArray();
|
||||
|
||||
foreach (var type in hostedServiceTypes)
|
||||
{
|
||||
if (type.GetInterface(nameof(IService)) == null)
|
||||
services.Add(new ServiceDescriptor(type, type, ServiceLifetime.Singleton));
|
||||
|
||||
services.Add(new ServiceDescriptor(typeof(IHostedService), provider => provider.GetRequiredService(type),
|
||||
ServiceLifetime.Singleton));
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddMiddleware(this IServiceCollection services)
|
||||
|
@ -413,6 +350,51 @@ public static partial class HttpContextExtensions
|
|||
ctx.Items.TryGetValue(CacheKey, out var s) && s is true;
|
||||
}
|
||||
|
||||
public interface IService
|
||||
{
|
||||
// This should be abstract instead of virtual but the runtime team said https://github.com/dotnet/runtime/issues/79331
|
||||
public static virtual ServiceLifetime Lifetime => throw new Exception("Missing IService.Lifetime override");
|
||||
|
||||
public static virtual Type? ServiceType => null;
|
||||
public static virtual int Priority => 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiated per request and class
|
||||
/// </summary>
|
||||
public interface ITransientService : IService
|
||||
{
|
||||
static ServiceLifetime IService.Lifetime => ServiceLifetime.Transient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiated per request
|
||||
/// </summary>
|
||||
public interface IScopedService : IService
|
||||
{
|
||||
static ServiceLifetime IService.Lifetime => ServiceLifetime.Scoped;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiated once across application lifetime
|
||||
/// </summary>
|
||||
public interface ISingletonService : IService
|
||||
{
|
||||
static ServiceLifetime IService.Lifetime => ServiceLifetime.Singleton;
|
||||
}
|
||||
|
||||
public interface IService<TService> : IService
|
||||
{
|
||||
static Type IService.ServiceType => typeof(TService);
|
||||
}
|
||||
|
||||
public interface IConditionalService : IService
|
||||
{
|
||||
// This should be abstract instead of virtual but the runtime team said https://github.com/dotnet/runtime/issues/79331
|
||||
public static virtual bool Predicate(Config ctx) =>
|
||||
throw new Exception("Missing IConditionalService.Predicate override");
|
||||
}
|
||||
|
||||
#region AsyncDataProtection handlers
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Federation.ActivityStreams;
|
||||
using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
|
||||
using Iceshrimp.Backend.Core.Queues;
|
||||
|
@ -13,7 +14,7 @@ public class ActivityDeliverService(
|
|||
ILogger<ActivityDeliverService> logger,
|
||||
QueueService queueService,
|
||||
DatabaseContext db
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task DeliverToFollowersAsync(ASActivity activity, User actor, IEnumerable<User> recipients)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,7 @@ public class ActivityFetcherService(
|
|||
DatabaseContext db,
|
||||
ILogger<ActivityFetcherService> logger,
|
||||
FederationControlService fedCtrlSvc
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
private static readonly IReadOnlyCollection<string> AcceptableActivityTypes =
|
||||
[
|
||||
|
|
|
@ -29,7 +29,7 @@ public class ActivityHandlerService(
|
|||
EmojiService emojiSvc,
|
||||
EventService eventSvc,
|
||||
RelayService relaySvc
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task PerformActivityAsync(ASActivity activity, string? inboxUserId, string? authenticatedUserId)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@ public class ActivityRenderer(
|
|||
IOptions<Config.InstanceSection> config,
|
||||
UserRenderer userRenderer,
|
||||
NoteRenderer noteRenderer
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
private string GenerateActivityId() =>
|
||||
$"https://{config.Value.WebDomain}/activities/ephemeral/{Guid.NewGuid().ToStringLower()}";
|
||||
|
|
|
@ -13,7 +13,7 @@ public class FederationControlService(
|
|||
IOptionsSnapshot<Config.SecuritySection> options,
|
||||
IOptions<Config.InstanceSection> instance,
|
||||
DatabaseContext db
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
//TODO: we need some level of caching here
|
||||
public async Task<bool> ShouldBlockAsync(params string?[] hosts)
|
||||
|
|
|
@ -16,9 +16,7 @@ using SplitDomainMapping = IReadOnlyDictionary<(string usernameLower, string web
|
|||
/// Resolves mentions into their canonical form. This is required for handling split domain mentions correctly, as it
|
||||
/// cannot be guaranteed that remote instances handle split domain users correctly.
|
||||
/// </summary>
|
||||
public class MentionsResolver(
|
||||
IOptions<Config.InstanceSection> config
|
||||
)
|
||||
public class MentionsResolver(IOptions<Config.InstanceSection> config) : ISingletonService
|
||||
{
|
||||
public string ResolveMentions(
|
||||
string mfm, string? host,
|
||||
|
|
|
@ -10,7 +10,11 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Iceshrimp.Backend.Core.Federation.ActivityPub;
|
||||
|
||||
public class NoteRenderer(IOptions<Config.InstanceSection> config, MfmConverter mfmConverter, DatabaseContext db)
|
||||
public class NoteRenderer(
|
||||
IOptions<Config.InstanceSection> config,
|
||||
MfmConverter mfmConverter,
|
||||
DatabaseContext db
|
||||
) : IScopedService
|
||||
{
|
||||
/// <summary>
|
||||
/// This function is meant for compacting a note into the @id form as specified in ActivityStreams
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
|
||||
using Iceshrimp.Backend.Core.Middleware;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
@ -14,7 +15,7 @@ public class ObjectResolver(
|
|||
DatabaseContext db,
|
||||
FederationControlService federationCtrl,
|
||||
IOptions<Config.InstanceSection> config
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task<ASObject?> ResolveObject(
|
||||
ASObjectBase baseObj, string? actorUri = null, int recurse = 5, bool force = false, User? user = null
|
||||
|
|
|
@ -2,6 +2,7 @@ using AngleSharp.Text;
|
|||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
|
||||
using Iceshrimp.Backend.Core.Helpers.LibMfm.Conversion;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
@ -9,7 +10,11 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Iceshrimp.Backend.Core.Federation.ActivityPub;
|
||||
|
||||
public class UserRenderer(IOptions<Config.InstanceSection> config, DatabaseContext db, MfmConverter mfmConverter)
|
||||
public class UserRenderer(
|
||||
IOptions<Config.InstanceSection> config,
|
||||
DatabaseContext db,
|
||||
MfmConverter mfmConverter
|
||||
) : IScopedService
|
||||
{
|
||||
/// <summary>
|
||||
/// This function is meant for compacting an actor into the @id form as specified in ActivityStreams
|
||||
|
|
|
@ -3,6 +3,7 @@ using AsyncKeyedLock;
|
|||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Federation.WebFinger;
|
||||
using Iceshrimp.Backend.Core.Helpers;
|
||||
using Iceshrimp.Backend.Core.Middleware;
|
||||
|
@ -20,7 +21,7 @@ public class UserResolver(
|
|||
ActivityFetcherService fetchSvc,
|
||||
IOptions<Config.InstanceSection> config,
|
||||
DatabaseContext db
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
private static readonly AsyncKeyedLocker<string> KeyedLocker = new(o =>
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Text.Encodings.Web;
|
|||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Middleware;
|
||||
using Iceshrimp.Backend.Core.Services;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
@ -27,7 +28,7 @@ public class WebFingerService(
|
|||
HttpRequestService httpRqSvc,
|
||||
IHostApplicationLifetime appLifetime,
|
||||
IOptions<Config.InstanceSection> config
|
||||
)
|
||||
) : ISingletonService
|
||||
{
|
||||
private static readonly ImmutableArray<string> Accept =
|
||||
[
|
||||
|
|
|
@ -16,7 +16,9 @@ using HtmlParser = AngleSharp.Html.Parser.HtmlParser;
|
|||
|
||||
namespace Iceshrimp.Backend.Core.Helpers.LibMfm.Conversion;
|
||||
|
||||
public class MfmConverter(IOptions<Config.InstanceSection> config)
|
||||
public class MfmConverter(
|
||||
IOptions<Config.InstanceSection> config
|
||||
) : IScopedService // <- this is intentional, see property below
|
||||
{
|
||||
public bool SupportsHtmlFormatting { private get; set; } = true;
|
||||
|
||||
|
|
|
@ -1,79 +1,88 @@
|
|||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Helpers;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class BiteService(DatabaseContext db, ActivityPub.ActivityRenderer activityRenderer, ActivityPub.ActivityDeliverService deliverSvc, NotificationService notificationSvc, IOptions<Config.InstanceSection> config)
|
||||
public class BiteService(
|
||||
DatabaseContext db,
|
||||
ActivityPub.ActivityRenderer activityRenderer,
|
||||
ActivityPub.ActivityDeliverService deliverSvc,
|
||||
NotificationService notificationSvc,
|
||||
IOptions<Config.InstanceSection> config
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task BiteAsync(User user, Bite target)
|
||||
{
|
||||
var bite = new Bite
|
||||
{
|
||||
Id = IdHelpers.GenerateSnowflakeId(),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
User = user,
|
||||
TargetBite = target
|
||||
};
|
||||
bite.Uri = bite.GetPublicUri(config.Value);
|
||||
public async Task BiteAsync(User user, Bite target)
|
||||
{
|
||||
var bite = new Bite
|
||||
{
|
||||
Id = IdHelpers.GenerateSnowflakeId(),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
User = user,
|
||||
TargetBite = target
|
||||
};
|
||||
bite.Uri = bite.GetPublicUri(config.Value);
|
||||
|
||||
await db.Bites.AddAsync(bite);
|
||||
await db.SaveChangesAsync();
|
||||
await db.Bites.AddAsync(bite);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
if (target.UserHost != null)
|
||||
{
|
||||
var activity = activityRenderer.RenderBite(bite, target.Uri ?? target.GetPublicUri(config.Value), target.User);
|
||||
await deliverSvc.DeliverToAsync(activity, user, target.User);
|
||||
}
|
||||
if (target.UserHost != null)
|
||||
{
|
||||
var activity =
|
||||
activityRenderer.RenderBite(bite, target.Uri ?? target.GetPublicUri(config.Value), target.User);
|
||||
await deliverSvc.DeliverToAsync(activity, user, target.User);
|
||||
}
|
||||
|
||||
await notificationSvc.GenerateBiteNotification(bite);
|
||||
}
|
||||
|
||||
public async Task BiteAsync(User user, Note target)
|
||||
{
|
||||
var bite = new Bite
|
||||
{
|
||||
Id = IdHelpers.GenerateSnowflakeId(),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
User = user,
|
||||
TargetNote = target
|
||||
};
|
||||
bite.Uri = bite.GetPublicUri(config.Value);
|
||||
await notificationSvc.GenerateBiteNotification(bite);
|
||||
}
|
||||
|
||||
await db.Bites.AddAsync(bite);
|
||||
await db.SaveChangesAsync();
|
||||
public async Task BiteAsync(User user, Note target)
|
||||
{
|
||||
var bite = new Bite
|
||||
{
|
||||
Id = IdHelpers.GenerateSnowflakeId(),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
User = user,
|
||||
TargetNote = target
|
||||
};
|
||||
bite.Uri = bite.GetPublicUri(config.Value);
|
||||
|
||||
if (target.UserHost != null)
|
||||
{
|
||||
var activity = activityRenderer.RenderBite(bite, target.Uri ?? target.GetPublicUri(config.Value), target.User);
|
||||
await deliverSvc.DeliverToAsync(activity, user, target.User);
|
||||
}
|
||||
await db.Bites.AddAsync(bite);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
await notificationSvc.GenerateBiteNotification(bite);
|
||||
}
|
||||
|
||||
public async Task BiteAsync(User user, User target)
|
||||
{
|
||||
var bite = new Bite
|
||||
{
|
||||
Id = IdHelpers.GenerateSnowflakeId(),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
User = user,
|
||||
TargetUser = target
|
||||
};
|
||||
bite.Uri = bite.GetPublicUri(config.Value);
|
||||
if (target.UserHost != null)
|
||||
{
|
||||
var activity =
|
||||
activityRenderer.RenderBite(bite, target.Uri ?? target.GetPublicUri(config.Value), target.User);
|
||||
await deliverSvc.DeliverToAsync(activity, user, target.User);
|
||||
}
|
||||
|
||||
await db.Bites.AddAsync(bite);
|
||||
await db.SaveChangesAsync();
|
||||
await notificationSvc.GenerateBiteNotification(bite);
|
||||
}
|
||||
|
||||
if (target.Host != null)
|
||||
{
|
||||
var activity = activityRenderer.RenderBite(bite, target.Uri ?? target.GetPublicUri(config.Value), target);
|
||||
await deliverSvc.DeliverToAsync(activity, user, target);
|
||||
}
|
||||
public async Task BiteAsync(User user, User target)
|
||||
{
|
||||
var bite = new Bite
|
||||
{
|
||||
Id = IdHelpers.GenerateSnowflakeId(),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
User = user,
|
||||
TargetUser = target
|
||||
};
|
||||
bite.Uri = bite.GetPublicUri(config.Value);
|
||||
|
||||
await notificationSvc.GenerateBiteNotification(bite);
|
||||
}
|
||||
await db.Bites.AddAsync(bite);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
if (target.Host != null)
|
||||
{
|
||||
var activity = activityRenderer.RenderBite(bite, target.Uri ?? target.GetPublicUri(config.Value), target);
|
||||
await deliverSvc.DeliverToAsync(activity, user, target);
|
||||
}
|
||||
|
||||
await notificationSvc.GenerateBiteNotification(bite);
|
||||
}
|
||||
}
|
|
@ -3,12 +3,12 @@ using System.Text.Json.Serialization;
|
|||
using AsyncKeyedLock;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
//TODO: named caches (with prefix)
|
||||
public class CacheService([FromKeyedServices("cache")] DatabaseContext db)
|
||||
public class CacheService([FromKeyedServices("cache")] DatabaseContext db) : IScopedService
|
||||
{
|
||||
private static readonly AsyncKeyedLocker<string> KeyedLocker = new(o =>
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class CustomHttpClient : HttpClient
|
||||
public class CustomHttpClient : HttpClient, IService<HttpClient>, ISingletonService
|
||||
{
|
||||
private static readonly FastFallback FastFallbackHandler = new();
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class DatabaseMaintenanceService(DatabaseContext db)
|
||||
public class DatabaseMaintenanceService(DatabaseContext db) : IScopedService
|
||||
{
|
||||
public async Task RecomputeNoteCountersAsync()
|
||||
{
|
||||
|
|
|
@ -27,7 +27,7 @@ public class DriveService(
|
|||
QueueService queueSvc,
|
||||
ILogger<DriveService> logger,
|
||||
ImageProcessor imageProcessor
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task<DriveFile?> StoreFile(
|
||||
string? uri, User user, bool sensitive, string? description = null, string? mimeType = null,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Middleware;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
|
||||
|
@ -30,7 +31,7 @@ public record EmojiZip(EmojiZipMeta Metadata, ZipArchive Archive);
|
|||
public class EmojiImportService(
|
||||
EmojiService emojiSvc,
|
||||
ILogger<EmojiImportService> logger
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web);
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ public partial class EmojiService(
|
|||
DriveService driveSvc,
|
||||
SystemUserService sysUserSvc,
|
||||
IOptions<Config.InstanceSection> config
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
private static readonly AsyncKeyedLocker<string> KeyedLocker = new(o =>
|
||||
{
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Events;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class EventService
|
||||
public class EventService : ISingletonService
|
||||
{
|
||||
public event EventHandler<Note>? NotePublished;
|
||||
public event EventHandler<Note>? NoteUpdated;
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
using Iceshrimp.Backend.Core.Extensions;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class FollowupTaskService(IServiceScopeFactory serviceScopeFactory, ILogger<FollowupTaskService> logger)
|
||||
public class FollowupTaskService(
|
||||
IServiceScopeFactory serviceScopeFactory,
|
||||
ILogger<FollowupTaskService> logger
|
||||
) : IScopedService
|
||||
{
|
||||
public bool IsBackgroundWorker { get; private set; }
|
||||
|
||||
|
|
|
@ -3,12 +3,13 @@ using System.Net.Http.Headers;
|
|||
using System.Security.Cryptography;
|
||||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Federation.Cryptography;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class HttpRequestService(IOptions<Config.InstanceSection> options)
|
||||
public class HttpRequestService(IOptions<Config.InstanceSection> options) : ISingletonService
|
||||
{
|
||||
private static HttpRequestMessage GenerateRequest(
|
||||
string url, HttpMethod method,
|
||||
|
|
|
@ -2,13 +2,14 @@ using System.Collections.Immutable;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Helpers;
|
||||
using Microsoft.Extensions.Options;
|
||||
using static Iceshrimp.Backend.Core.Services.ImageProcessing.ImageVersion;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services.ImageProcessing;
|
||||
|
||||
public class ImageProcessor
|
||||
public class ImageProcessor : ISingletonService
|
||||
{
|
||||
private readonly IOptionsMonitor<Config.StorageSection> _config;
|
||||
//TODO: support stripping of exif/icc metadata (without re-encoding)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using CommunityToolkit.HighPerformance;
|
||||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Helpers;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SixLabors.ImageSharp;
|
||||
|
@ -13,7 +14,8 @@ using ImageSharpConfig = SixLabors.ImageSharp.Configuration;
|
|||
|
||||
namespace Iceshrimp.Backend.Core.Services.ImageProcessing;
|
||||
|
||||
public class ImageSharpProcessor : ImageProcessorBase, IImageProcessor
|
||||
public class ImageSharpProcessor : ImageProcessorBase, IImageProcessor,
|
||||
ISingletonService, IConditionalService, IService<IImageProcessor>
|
||||
{
|
||||
private readonly ILogger<ImageSharpProcessor> _logger;
|
||||
private readonly ImageSharpConfig _sharpConfig;
|
||||
|
@ -22,6 +24,9 @@ public class ImageSharpProcessor : ImageProcessorBase, IImageProcessor
|
|||
public bool CanIdentify => true;
|
||||
public bool CanGenerateBlurhash => true;
|
||||
|
||||
public static bool Predicate(Config ctx) =>
|
||||
ctx.Storage.MediaProcessing.ImageProcessor is Enums.ImageProcessor.ImageSharp or Enums.ImageProcessor.LibVips;
|
||||
|
||||
public ImageSharpProcessor(
|
||||
ILogger<ImageSharpProcessor> logger, IOptions<Config.StorageSection> config
|
||||
) : base("ImageSharp", 1)
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using CommunityToolkit.HighPerformance;
|
||||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Helpers;
|
||||
using NetVips;
|
||||
using Iceshrimp.MimeTypes;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using Enums = NetVips.Enums;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services.ImageProcessing;
|
||||
|
||||
public class VipsProcessor : ImageProcessorBase, IImageProcessor
|
||||
public class VipsProcessor : ImageProcessorBase, IImageProcessor,
|
||||
ISingletonService, IConditionalService, IService<IImageProcessor>
|
||||
{
|
||||
private readonly ILogger<VipsProcessor> _logger;
|
||||
|
||||
public bool CanIdentify => true;
|
||||
public bool CanGenerateBlurhash => true;
|
||||
|
||||
static int IService.Priority => -1;
|
||||
|
||||
public static bool Predicate(Config ctx) =>
|
||||
ctx.Storage.MediaProcessing.ImageProcessor == Configuration.Enums.ImageProcessor.LibVips;
|
||||
|
||||
public VipsProcessor(ILogger<VipsProcessor> logger) : base("LibVips", 0)
|
||||
{
|
||||
_logger = logger;
|
||||
|
|
|
@ -15,7 +15,7 @@ public class ImportExportService(
|
|||
CacheService cacheSvc,
|
||||
UserService userSvc,
|
||||
ActivityPub.UserResolver userResolver
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task<string> ExportFollowingAsync(User user)
|
||||
{
|
||||
|
|
|
@ -8,7 +8,11 @@ using Microsoft.EntityFrameworkCore;
|
|||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class InstanceService(DatabaseContext db, HttpClient httpClient, ILogger<InstanceService> logger)
|
||||
public class InstanceService(
|
||||
DatabaseContext db,
|
||||
HttpClient httpClient,
|
||||
ILogger<InstanceService> logger
|
||||
) : IScopedService
|
||||
{
|
||||
private static readonly AsyncKeyedLocker<string> KeyedLocker = new(o =>
|
||||
{
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class MetaService([FromKeyedServices("cache")] DatabaseContext db)
|
||||
public class MetaService([FromKeyedServices("cache")] DatabaseContext db) : IScopedService
|
||||
{
|
||||
public async Task<T> Get<T>(Meta<T> meta) => meta.ConvertGet(await Fetch(meta.Key));
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@ using static Iceshrimp.Parsing.MfmNodeTypes;
|
|||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
[SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor",
|
||||
Justification = "We need IOptionsSnapshot for config hot reload")]
|
||||
public class NoteService(
|
||||
ILogger<NoteService> logger,
|
||||
DatabaseContext db,
|
||||
|
@ -43,7 +41,7 @@ public class NoteService(
|
|||
PollService pollSvc,
|
||||
ActivityPub.FederationControlService fedCtrlSvc,
|
||||
PolicyService policySvc
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
private const int DefaultRecursionLimit = 100;
|
||||
|
||||
|
|
|
@ -8,10 +8,9 @@ using Microsoft.EntityFrameworkCore;
|
|||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class NotificationService(
|
||||
[SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor")]
|
||||
DatabaseContext db,
|
||||
EventService eventSvc
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task GenerateMentionNotifications(Note note, IReadOnlyCollection<string> mentionedLocalUserIds)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Net.Http.Headers;
|
|||
using System.Text;
|
||||
using Carbon.Storage;
|
||||
using Iceshrimp.Backend.Core.Configuration;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Helpers;
|
||||
using Iceshrimp.ObjectStorage.Core.Models;
|
||||
using Iceshrimp.ObjectStorage.Core.Security;
|
||||
|
@ -11,7 +12,7 @@ using Microsoft.Extensions.Options;
|
|||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class ObjectStorageService(IOptions<Config.StorageSection> config, HttpClient httpClient)
|
||||
public class ObjectStorageService(IOptions<Config.StorageSection> config, HttpClient httpClient) : ISingletonService
|
||||
{
|
||||
private readonly string? _accessUrl = config.Value.ObjectStorage?.AccessUrl;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Text.Json;
|
|||
using Iceshrimp.AssemblyUtils;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
|
||||
using Iceshrimp.Backend.Core.Helpers;
|
||||
using Iceshrimp.Shared.Configuration;
|
||||
|
@ -11,7 +12,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class PolicyService(IServiceScopeFactory scopeFactory)
|
||||
public class PolicyService(IServiceScopeFactory scopeFactory) : ISingletonService
|
||||
{
|
||||
private bool _initialized;
|
||||
private IRejectPolicy[] _rejectPolicies = [];
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
@ -9,7 +10,7 @@ public class PollService(
|
|||
ActivityPub.ActivityRenderer activityRenderer,
|
||||
ActivityPub.UserRenderer userRenderer,
|
||||
ActivityPub.ActivityDeliverService deliverSvc
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task RegisterPollVote(PollVote pollVote, Poll poll, Note note, bool updateVotersCount = true)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Diagnostics;
|
||||
using System.Text.Encodings.Web;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
@ -15,7 +16,7 @@ public class RazorViewRenderService(
|
|||
ITempDataProvider tempDataProvider,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IRazorPageActivator activator
|
||||
)
|
||||
) : ISingletonService
|
||||
{
|
||||
private async Task RenderAsync<T>(string path, T model, TextWriter writer) where T : PageModel
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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 Microsoft.EntityFrameworkCore;
|
||||
|
@ -12,7 +13,7 @@ public class RelayService(
|
|||
ActivityPub.ActivityRenderer activityRenderer,
|
||||
ActivityPub.ActivityDeliverService deliverSvc,
|
||||
ActivityPub.UserRenderer userRenderer
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task SubscribeToRelay(string uri)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@ public class StorageMaintenanceService(
|
|||
[SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor")]
|
||||
IOptionsSnapshot<Config.StorageSection> options,
|
||||
ILogger<StorageMaintenanceService> logger
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task MigrateLocalFiles(bool purge)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Concurrent;
|
||||
using Iceshrimp.Backend.Controllers.Web.Renderers;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.SignalR;
|
||||
using Iceshrimp.Backend.SignalR.Helpers;
|
||||
using Iceshrimp.Shared.Schemas.SignalR;
|
||||
|
@ -9,7 +10,7 @@ using Microsoft.AspNetCore.SignalR;
|
|||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public sealed class StreamingService
|
||||
public sealed class StreamingService : ISingletonService
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, StreamingConnectionAggregate> _connections = [];
|
||||
private readonly EventService _eventSvc;
|
||||
|
|
|
@ -2,12 +2,13 @@ using System.Security.Cryptography;
|
|||
using AsyncKeyedLock;
|
||||
using Iceshrimp.Backend.Core.Database;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Iceshrimp.Backend.Core.Extensions;
|
||||
using Iceshrimp.Backend.Core.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class SystemUserService(ILogger<SystemUserService> logger, DatabaseContext db)
|
||||
public class SystemUserService(ILogger<SystemUserService> logger, DatabaseContext db) : IScopedService
|
||||
{
|
||||
private static readonly AsyncKeyedLocker<string> KeyedLocker = new(o =>
|
||||
{
|
||||
|
|
|
@ -14,7 +14,10 @@ namespace Iceshrimp.Backend.Core.Services;
|
|||
using MentionTuple = (List<Note.MentionedUser> mentions,
|
||||
Dictionary<(string usernameLower, string webDomain), string> splitDomainMapping);
|
||||
|
||||
public class UserProfileMentionsResolver(ActivityPub.UserResolver userResolver, IOptions<Config.InstanceSection> config)
|
||||
public class UserProfileMentionsResolver(
|
||||
ActivityPub.UserResolver userResolver,
|
||||
IOptions<Config.InstanceSection> config
|
||||
) : IScopedService
|
||||
{
|
||||
public async Task<MentionTuple> ResolveMentions(ASActor actor, string? host)
|
||||
{
|
||||
|
|
|
@ -22,7 +22,6 @@ using static Iceshrimp.Parsing.MfmNodeTypes;
|
|||
namespace Iceshrimp.Backend.Core.Services;
|
||||
|
||||
public class UserService(
|
||||
[SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor")]
|
||||
IOptionsSnapshot<Config.SecuritySection> security,
|
||||
IOptions<Config.InstanceSection> instance,
|
||||
ILogger<UserService> logger,
|
||||
|
@ -40,7 +39,7 @@ public class UserService(
|
|||
EventService eventSvc,
|
||||
WebFingerService webFingerSvc,
|
||||
ActivityPub.FederationControlService fedCtrlSvc
|
||||
)
|
||||
) : IScopedService
|
||||
{
|
||||
private static readonly AsyncKeyedLocker<string> KeyedLocker = new(o =>
|
||||
{
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<PackageReference Include="System.Text.Json" Version="9.0.0" />
|
||||
<PackageReference Include="Ulid" Version="1.3.4" />
|
||||
<PackageReference Include="Iceshrimp.AssemblyUtils" Version="1.0.2" />
|
||||
<PackageReference Include="Iceshrimp.AssemblyUtils" Version="1.0.3" />
|
||||
<PackageReference Include="Iceshrimp.MimeTypes" Version="1.0.1" />
|
||||
<PackageReference Include="Iceshrimp.WebPush" Version="2.1.0" />
|
||||
<PackageReference Include="NetVips" Version="3.0.0" />
|
||||
|
|
|
@ -38,7 +38,6 @@ builder.Services.AddRazorPages();
|
|||
builder.Services.AddRazorComponents();
|
||||
builder.Services.AddAntiforgery(o => o.Cookie.Name = "CSRF-Token");
|
||||
builder.Services.AddMiddleware();
|
||||
|
||||
builder.Services.AddServices(builder.Configuration);
|
||||
builder.Services.ConfigureServices(builder.Configuration);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue