using System.Globalization; using DysonNetwork.Sphere.Activity; using DysonNetwork.Sphere.Chat; using DysonNetwork.Sphere.Chat.Realtime; using DysonNetwork.Sphere.Localization; using DysonNetwork.Sphere.Post; using DysonNetwork.Sphere.Publisher; using DysonNetwork.Sphere.Realm; using DysonNetwork.Sphere.Sticker; using Microsoft.AspNetCore.RateLimiting; using NodaTime; using NodaTime.Serialization.SystemTextJson; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.RateLimiting; using DysonNetwork.Shared.Cache; using DysonNetwork.Shared.GeoIp; using DysonNetwork.Sphere.WebReader; using DysonNetwork.Sphere.Discovery; using DysonNetwork.Sphere.Poll; using DysonNetwork.Sphere.Translation; namespace DysonNetwork.Sphere.Startup; public static class ServiceCollectionExtensions { public static IServiceCollection AddAppServices(this IServiceCollection services, IConfiguration configuration) { services.AddLocalization(options => options.ResourcesPath = "Resources"); services.AddDbContext(); services.AddSingleton(SystemClock.Instance); services.AddHttpContextAccessor(); services.AddSingleton(); services.AddHttpClient(); services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals; options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower; options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.SnakeCaseLower; options.JsonSerializerOptions.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); }).AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(typeof(SharedResource)); }).ConfigureApplicationPartManager(opts => { var mockingPart = opts.ApplicationParts.FirstOrDefault(a => a.Name == "DysonNetwork.Pass"); if (mockingPart != null) opts.ApplicationParts.Remove(mockingPart); }); services.AddRazorPages(); services.AddGrpc(options => { options.EnableDetailedErrors = true; }); services.Configure(options => { var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("zh-Hans"), }; options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; }); services.AddHostedService(); return services; } public static IServiceCollection AddAppRateLimiting(this IServiceCollection services) { services.AddRateLimiter(o => o.AddFixedWindowLimiter(policyName: "fixed", opts => { opts.Window = TimeSpan.FromMinutes(1); opts.PermitLimit = 120; opts.QueueLimit = 2; opts.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; })); return services; } public static IServiceCollection AddAppAuthentication(this IServiceCollection services) { services.AddAuthorization(); return services; } public static IServiceCollection AddAppFlushHandlers(this IServiceCollection services) { services.AddSingleton(); services.AddScoped(); return services; } public static IServiceCollection AddAppBusinessServices(this IServiceCollection services, IConfiguration configuration) { services.Configure(configuration.GetSection("GeoIP")); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); var translationProvider = configuration["Translation:Provider"]?.ToLower(); switch (translationProvider) { case "tencent": services.AddScoped(); break; } return services; } }