using System.Reflection; using Discord; using Discord.Commands; using Discord.WebSocket; using Geekbot.Bot.Handlers; using Geekbot.Core; using Geekbot.Core.Database; using Geekbot.Core.GlobalSettings; using Geekbot.Core.GuildSettingsManager; using Geekbot.Core.Logger; using Geekbot.Core.ReactionListener; using Geekbot.Core.UserRepository; using Microsoft.Extensions.DependencyInjection; namespace Geekbot.Bot; public class BotStartup { private readonly IServiceCollection _serviceCollection; private readonly GeekbotLogger _logger; private readonly RunParameters _runParameters; private readonly IGlobalSettings _globalSettings; private DiscordSocketClient _client; public BotStartup(IServiceCollection serviceCollection, GeekbotLogger logger, RunParameters runParameters, IGlobalSettings globalSettings) { _serviceCollection = serviceCollection; _logger = logger; _runParameters = runParameters; _globalSettings = globalSettings; } public async Task Start() { _logger.Information(LogSource.Geekbot, "Connecting to Discord"); SetupDiscordClient(); await Login(); await _client.SetGameAsync(_globalSettings.GetKey("Game")); _logger.Information(LogSource.Geekbot, $"Now Connected as {_client.CurrentUser.Username} to {_client.Guilds.Count} Servers"); _logger.Information(LogSource.Geekbot, "Registering Gateway Handlers"); await RegisterHandlers(); _logger.Information(LogSource.Geekbot, "Done and ready for use"); await Task.Delay(-1); } private void SetupDiscordClient() { _client = new DiscordSocketClient(new DiscordSocketConfig { LogLevel = LogSeverity.Verbose, MessageCacheSize = 1000, ExclusiveBulkDelete = true }); var discordLogger = new DiscordLogger(_logger); _client.Log += discordLogger.Log; } private async Task Login() { try { var token = await GetToken(); await _client.LoginAsync(TokenType.Bot, token); await _client.StartAsync(); while (!_client.ConnectionState.Equals(ConnectionState.Connected)) await Task.Delay(25); } catch (Exception e) { _logger.Error(LogSource.Geekbot, "Could not connect to Discord", e); Environment.Exit(GeekbotExitCode.CouldNotLogin.GetHashCode()); } } private async Task GetToken() { var token = _runParameters.Token ?? _globalSettings.GetKey("DiscordToken"); if (string.IsNullOrEmpty(token)) { Console.Write("Your bot Token: "); var newToken = Console.ReadLine(); await _globalSettings.SetKey("DiscordToken", newToken); await _globalSettings.SetKey("Game", "Ping Pong"); token = newToken; } return token; } private async Task RegisterHandlers() { var applicationInfo = await _client.GetApplicationInfoAsync(); _serviceCollection.AddSingleton(_client); var serviceProvider = _serviceCollection.BuildServiceProvider(); var commands = new CommandService(); await commands.AddModulesAsync(Assembly.GetAssembly(typeof(BotStartup)), serviceProvider); var commandHandler = new CommandHandler(_client, _logger, serviceProvider, commands, applicationInfo, serviceProvider.GetService()); var userHandler = new UserHandler(serviceProvider.GetService(), _logger, serviceProvider.GetService(), _client); var reactionHandler = new ReactionHandler(serviceProvider.GetService()); var statsHandler = new StatsHandler(_logger, serviceProvider.GetService()); var messageDeletedHandler = new MessageDeletedHandler(serviceProvider.GetService(), _logger, _client); _client.MessageReceived += commandHandler.RunCommand; _client.MessageDeleted += messageDeletedHandler.HandleMessageDeleted; _client.UserJoined += userHandler.Joined; _client.UserUpdated += userHandler.Updated; _client.UserLeft += userHandler.Left; _client.ReactionAdded += reactionHandler.Added; _client.ReactionRemoved += reactionHandler.Removed; if (!_runParameters.InMemory) _client.MessageReceived += statsHandler.UpdateStats; } }