using AnsonBot.Core; using Discord; using Discord.Interactions; using Discord.WebSocket; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Reflection; using System.Text; namespace AnsonBot.Bot; public class BotHostedService : IHostedService { private readonly DiscordSocketClient _client; private readonly InteractionService _interactions; private readonly IServiceProvider _services; private readonly DiscordOptions _options; private readonly ILogger _logger; public BotHostedService( DiscordSocketClient client, InteractionService interactions, IServiceProvider services, IOptions options, ILogger logger) { _client = client; _interactions = interactions; _services = services; _options = options.Value; _logger = logger; } public async Task StartAsync(CancellationToken ct) { _client.Log += LogAsync; _interactions.Log += LogAsync; _client.Ready += ReadyAsync; _client.InteractionCreated += InteractionCreatedAsync; await _interactions.AddModulesAsync(Assembly.GetExecutingAssembly(), _services); if (string.IsNullOrWhiteSpace(_options.Token)) throw new InvalidOperationException("Discord token is not configured."); _logger.LogInformation("Token loaded, length {Length}", _options.Token.Length); await _client.LoginAsync(TokenType.Bot, _options.Token); await _client.StartAsync(); } private async Task ReadyAsync() { if (_options.GuildId != 0) { await _interactions.RegisterCommandsToGuildAsync(_options.GuildId); _logger.LogInformation("Commands registered to guild {GuildId}", _options.GuildId); } else { await _interactions.RegisterCommandsGloballyAsync(); _logger.LogInformation("Commands registered globally"); } _logger.LogInformation("Connected as {User}", _client.CurrentUser); } private async Task InteractionCreatedAsync(SocketInteraction interaction) { var context = new SocketInteractionContext(_client, interaction); await _interactions.ExecuteCommandAsync(context, _services); } private Task LogAsync(LogMessage message) { var level = message.Severity switch { LogSeverity.Critical => LogLevel.Critical, LogSeverity.Error => LogLevel.Error, LogSeverity.Warning => LogLevel.Warning, LogSeverity.Info => LogLevel.Information, _ => LogLevel.Debug }; _logger.Log(level, message.Exception, "{Source}: {Message}", message.Source, message.Message); return Task.CompletedTask; } public async Task StopAsync(CancellationToken ct) { await _client.LogoutAsync(); await _client.StopAsync(); } }