542f15f2d6
PR Checks / test-and-build (pull_request) Successful in 13m48s
- Extract CreateSessionHandler, ListSessionsHandler, DeleteSessionHandler, ExportCalendarHandler, HandleRescheduleTimeInputHandler, HandleRescheduleVoteHandler to GmRelay.Shared - Add IPlatformMessenger methods: SendScheduleAsync, UpdateScheduleAsync, SendGroupMessageAsync with actions, CreateThreadAsync, DeleteThreadAsync - Rewrite Telegram Bot wrappers as thin adapters delegating to shared handlers - Rewrite DiscordRescheduleVoteHandler to use shared HandleRescheduleVoteHandler - Update UpdateRouter with explicit type aliases for ambiguous handler names - Add contract and source-inspection tests for extracted handlers - Bump version 3.1.1 → 3.2.0 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
101 lines
4.5 KiB
C#
101 lines
4.5 KiB
C#
using GmRelay.DiscordBot;
|
|
using GmRelay.DiscordBot.Features.Sessions;
|
|
using GmRelay.DiscordBot.Infrastructure;
|
|
using GmRelay.DiscordBot.Infrastructure.Discord;
|
|
using GmRelay.DiscordBot.Infrastructure.Health;
|
|
using GmRelay.DiscordBot.Infrastructure.Logging;
|
|
using GmRelay.Shared.Features.Confirmation.HandleRsvp;
|
|
using GmRelay.Shared.Features.Confirmation.SendConfirmation;
|
|
using GmRelay.Shared.Features.Notifications;
|
|
using GmRelay.Shared.Features.Reminders.SendJoinLink;
|
|
using GmRelay.Shared.Features.Reminders.SendOneHourReminder;
|
|
using GmRelay.Shared.Features.Sessions.CreateSession;
|
|
using GmRelay.Shared.Features.Sessions.RescheduleSession;
|
|
using GmRelay.Shared.Infrastructure.Scheduling;
|
|
using GmRelay.Shared.Platform;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using NetCord;
|
|
using NetCord.Gateway;
|
|
using NetCord.Hosting.Gateway;
|
|
using NetCord.Hosting.Services;
|
|
using NetCord.Hosting.Services.ApplicationCommands;
|
|
using NetCord.Hosting.Services.ComponentInteractions;
|
|
using NetCord.Services.ApplicationCommands;
|
|
using NetCord.Services.ComponentInteractions;
|
|
using Npgsql;
|
|
|
|
var builder = Host.CreateApplicationBuilder(args);
|
|
|
|
builder.AddServiceDefaults();
|
|
|
|
var discordOptions = builder.Configuration
|
|
.GetRequiredSection("Discord")
|
|
.Get<DiscordOptions>() ?? new DiscordOptions();
|
|
discordOptions.Validate();
|
|
|
|
builder.Services.AddSingleton(discordOptions);
|
|
|
|
builder.Logging.AddConsole();
|
|
|
|
builder.Services.AddSingleton<NpgsqlDataSource>(sp =>
|
|
{
|
|
var config = sp.GetRequiredService<IConfiguration>();
|
|
var loggerFactory = sp.GetRequiredService<ILoggerFactory>();
|
|
var connectionString = config.GetConnectionString("gmrelaydb")
|
|
?? throw new InvalidOperationException(
|
|
"ConnectionStrings:gmrelaydb is required. Set via environment variable ConnectionStrings__gmrelaydb.");
|
|
|
|
var logger = loggerFactory.CreateLogger("GmRelay.DiscordBot.Startup");
|
|
logger.LogInformation(
|
|
"Configured PostgreSQL data source with connection string {ConnectionString}",
|
|
SecretRedactor.RedactConnectionString(connectionString));
|
|
|
|
return NpgsqlDataSource.Create(connectionString);
|
|
});
|
|
|
|
builder.Services.AddSingleton<DiscordPermissionChecker>();
|
|
builder.Services.AddSingleton<DiscordListSessionsHandler>();
|
|
builder.Services.AddSingleton<DiscordDeleteSessionHandler>();
|
|
builder.Services.AddSingleton<DiscordNewSessionHandler>();
|
|
builder.Services.AddSingleton<DiscordRescheduleHandler>();
|
|
builder.Services.AddSingleton<GmRelay.Shared.Features.Sessions.RescheduleSession.HandleRescheduleVoteHandler>();
|
|
builder.Services.AddSingleton<DiscordRescheduleVoteHandler>();
|
|
builder.Services.AddSingleton<IScheduleMessageUpdateLock, ScheduleMessageUpdateLock>();
|
|
builder.Services.AddSingleton<JoinSessionHandler>();
|
|
builder.Services.AddSingleton<LeaveSessionHandler>();
|
|
builder.Services.AddSingleton<DiscordInteractionReplyCache>();
|
|
builder.Services.AddSingleton<IPlatformMessenger, DiscordPlatformMessenger>();
|
|
builder.Services.AddSingleton<ISystemClock, SystemClock>();
|
|
builder.Services.AddSingleton(new PlatformSchedulerOptions(PlatformKind.Discord));
|
|
builder.Services.AddSingleton<ISessionTriggerStore, DbSessionTriggerStore>();
|
|
builder.Services.AddSingleton<PlatformDirectNotificationSender>();
|
|
builder.Services.AddSingleton<SendConfirmationHandler>();
|
|
builder.Services.AddSingleton<ISendConfirmationHandler>(sp => sp.GetRequiredService<SendConfirmationHandler>());
|
|
builder.Services.AddSingleton<SendJoinLinkHandler>();
|
|
builder.Services.AddSingleton<ISendJoinLinkHandler>(sp => sp.GetRequiredService<SendJoinLinkHandler>());
|
|
builder.Services.AddSingleton<SendOneHourReminderHandler>();
|
|
builder.Services.AddSingleton<ISendOneHourReminderHandler>(sp => sp.GetRequiredService<SendOneHourReminderHandler>());
|
|
builder.Services.AddSingleton<HandleRsvpHandler>();
|
|
builder.Services.AddSingleton<RescheduleVotingFinalizer>();
|
|
builder.Services.AddHostedService<SessionSchedulerService>();
|
|
builder.Services.AddHostedService<DiscordRescheduleVotingDeadlineService>();
|
|
builder.Services.AddHostedService<DiscordHealthCheckHostedService>();
|
|
|
|
builder.Services
|
|
.AddDiscordGateway(options =>
|
|
{
|
|
options.Token = discordOptions.Token;
|
|
options.Intents = GatewayIntents.Guilds;
|
|
})
|
|
.AddApplicationCommands<SlashCommandInteraction, SlashCommandContext>()
|
|
.AddComponentInteractions<ButtonInteraction, ButtonInteractionContext>()
|
|
.AddGatewayHandlers(typeof(Program).Assembly);
|
|
|
|
var host = builder.Build();
|
|
|
|
host.AddSlashCommand("ping", "Checks whether GM-Relay Discord is online.", () => "Pong!");
|
|
host.AddModules(typeof(Program).Assembly);
|
|
|
|
await host.RunAsync();
|