using Catalogger.Backend.Bot.Commands; using Catalogger.Backend.Database; using Catalogger.Backend.Extensions; using Catalogger.Backend.Services; using Newtonsoft.Json.Serialization; using Prometheus; using Remora.Commands.Extensions; using Remora.Discord.API.Abstractions.Gateway.Commands; using Remora.Discord.Commands.Extensions; using Remora.Discord.Extensions.Extensions; using Remora.Discord.Gateway; using Remora.Discord.Hosting.Extensions; using Remora.Discord.Interactivity.Extensions; using Remora.Discord.Pagination.Extensions; using Serilog; using Metrics = Prometheus.Metrics; var builder = WebApplication.CreateBuilder(args); var config = builder.AddConfiguration(); builder.AddSerilog(config); builder.Services .AddControllers() .AddNewtonsoftJson(o => o.SerializerSettings.ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() }); builder.Host .AddDiscordService(_ => config.Discord.Token) .ConfigureServices(s => s.AddRespondersFromAssembly(typeof(Program).Assembly) .Configure(g => g.Intents = GatewayIntents.Guilds | GatewayIntents.GuildBans | GatewayIntents.GuildInvites | GatewayIntents.GuildMembers | GatewayIntents.GuildMessages | GatewayIntents.GuildWebhooks | GatewayIntents.MessageContents | GatewayIntents.GuildEmojisAndStickers) .AddDiscordCommands(enableSlash: true, useDefaultCommandResponder: false) .AddCommandTree() // Start command tree .WithCommandGroup() .WithCommandGroup() // End command tree .Finish() .AddPagination() .AddInteractivity() .AddInteractionGroup() ); // Add metric server // If metrics are disabled (Logging.EnableMetrics = false), also add a background service that updates // metrics every minute, as some commands rely on them. builder.Services.AddMetricServer(o => o.Port = (ushort)config.Logging.MetricsPort); if (!config.Logging.EnableMetrics) builder.Services.AddHostedService(); builder.Services .AddDbContext() .MaybeAddRedisCaches(config) .AddCustomServices() .AddEndpointsApiExplorer() .AddSwaggerGen(); var app = builder.Build(); await app.Initialize(); app.UseSerilogRequestLogging(); app.UseRouting(); app.UseHttpMetrics(); app.UseSwagger(); app.UseSwaggerUI(); app.UseCors(); app.MapControllers(); app.Urls.Clear(); app.Urls.Add(config.Web.Address); // Make sure metrics are updated whenever Prometheus scrapes them Metrics.DefaultRegistry.AddBeforeCollectCallback(async ct => await app.Services.GetRequiredService().CollectMetricsAsync(ct)); app.Run(); Log.CloseAndFlush();