Files
Swarm/DysonNetwork.Sphere/Startup/ServiceCollectionExtensions.cs

232 lines
8.4 KiB
C#

using System.Globalization;
using DysonNetwork.Sphere.Activity;
using DysonNetwork.Sphere.Chat;
using DysonNetwork.Sphere.Chat.Realtime;
using DysonNetwork.Sphere.Connection;
using DysonNetwork.Sphere.Connection.Handlers;
using DysonNetwork.Sphere.Email;
using DysonNetwork.Sphere.Localization;
using DysonNetwork.Sphere.Post;
using DysonNetwork.Sphere.Publisher;
using DysonNetwork.Sphere.Realm;
using DysonNetwork.Sphere.Sticker;
using DysonNetwork.Sphere.Storage;
using DysonNetwork.Sphere.Storage.Handlers;
using DysonNetwork.Sphere.Wallet;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.OpenApi.Models;
using NodaTime;
using NodaTime.Serialization.SystemTextJson;
using StackExchange.Redis;
using System.Text.Json;
using System.Threading.RateLimiting;
using DysonNetwork.Common.Services;
using DysonNetwork.Sphere.Connection.WebReader;
using DysonNetwork.Sphere.Developer;
using DysonNetwork.Sphere.Discovery;
using DysonNetwork.Sphere.Safety;
using DysonNetwork.Sphere.Wallet.PaymentHandlers;
using tusdotnet.Stores;
using DysonNetwork.Common.Interfaces;
using DysonNetwork.Common.Clients;
using DysonNetwork.Sphere.Data;
using Npgsql.EntityFrameworkCore.PostgreSQL;
using Microsoft.EntityFrameworkCore;
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<AppDatabase>(options =>
options.UseNpgsql(
configuration.GetConnectionString("DefaultConnection"),
o => o.UseNodaTime()
)
.UseSnakeCaseNamingConvention()
);
services.AddSingleton<IConnectionMultiplexer>(_ =>
{
var connection = configuration.GetConnectionString("FastRetrieve")!;
return ConnectionMultiplexer.Connect(connection);
});
services.AddSingleton<IClock>(SystemClock.Instance);
services.AddHttpContextAccessor();
services.AddSingleton<ICacheService, CacheServiceRedis>();
services.AddHttpClient<PassClient>();
services.AddScoped<PassClient>();
// Register HTTP clients for Drive microservice
services.AddHttpClient<IFileServiceClient, FileServiceClient>(client =>
{
var baseUrl = configuration["DriveService:BaseUrl"] ?? throw new InvalidOperationException("DriveService:BaseUrl is not configured");
client.BaseAddress = new Uri(baseUrl);
});
services.AddHttpClient<IFileReferenceServiceClient, FileReferenceServiceClient>(client =>
{
var baseUrl = configuration["DriveService:BaseUrl"] ?? throw new InvalidOperationException("DriveService:BaseUrl is not configured");
client.BaseAddress = new Uri(baseUrl);
});
// Register OIDC services
services.AddControllers().AddJsonOptions(options =>
{
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));
});
services.AddRazorPages();
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("zh-Hans"),
};
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
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 AddAppSwagger(this IServiceCollection services)
{
services.AddEndpointsApiExplorer();
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "Solar Network API",
Description = "An open-source social network",
TermsOfService = new Uri("https://solsynth.dev/terms"),
License = new OpenApiLicense
{
Name = "APGLv3",
Url = new Uri("https://www.gnu.org/licenses/agpl-3.0.html")
}
});
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Please enter a valid token",
Name = "Authorization",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "Bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
[]
}
});
});
services.AddOpenApi();
return services;
}
public static IServiceCollection AddAppFileStorage(this IServiceCollection services, IConfiguration configuration)
{
var tusStorePath = configuration.GetSection("Tus").GetValue<string>("StorePath")!;
Directory.CreateDirectory(tusStorePath);
var tusDiskStore = new TusDiskStore(tusStorePath);
services.AddSingleton(tusDiskStore);
return services;
}
public static IServiceCollection AddAppFlushHandlers(this IServiceCollection services)
{
services.AddSingleton<FlushBufferService>();
services.AddScoped<ActionLogFlushHandler>();
services.AddScoped<MessageReadReceiptFlushHandler>();
services.AddScoped<LastActiveFlushHandler>();
services.AddScoped<PostViewFlushHandler>();
// The handlers for websocket
services.AddScoped<IWebSocketPacketHandler, MessageReadHandler>();
services.AddScoped<IWebSocketPacketHandler, MessageTypingHandler>();
services.AddScoped<IWebSocketPacketHandler, MessagesSubscribeHandler>();
services.AddScoped<IWebSocketPacketHandler, MessagesUnsubscribeHandler>();
return services;
}
public static IServiceCollection AddAppBusinessServices(this IServiceCollection services,
IConfiguration configuration)
{
services.AddScoped<RazorViewRenderer>();
services.Configure<GeoIpOptions>(configuration.GetSection("GeoIP"));
services.AddScoped<GeoIpService>();
services.AddScoped<WebSocketService>();
services.AddScoped<EmailService>();
services.AddScoped<FileService>();
services.AddScoped<FileReferenceMigrationService>();
services.AddScoped<PublisherService>();
services.AddScoped<PublisherSubscriptionService>();
services.AddScoped<ActivityService>();
services.AddScoped<PostService>();
services.AddScoped<RealmService>();
services.AddScoped<ChatRoomService>();
services.AddScoped<ChatService>();
services.AddScoped<StickerService>();
services.AddScoped<WalletService>();
services.AddScoped<SubscriptionService>();
services.AddScoped<PaymentService>();
services.AddScoped<IRealtimeService, LivekitRealtimeService>();
services.AddScoped<WebReaderService>();
services.AddScoped<WebFeedService>();
services.AddScoped<AfdianPaymentHandler>();
services.AddScoped<SafetyService>();
services.AddScoped<DiscoveryService>();
services.AddScoped<CustomAppService>();
return services;
}
}