public ICompileResult CreateModules(Snowflake id, string code) { Logger.LogInformation("Compiling module code..."); var sw = Stopwatch.StartNew(); var result = CompileUtils.CompileCommandModule(id.ToString(), code); sw.Stop(); Logger.LogInformation("Finished compiling module code in {0}ms.", sw.ElapsedMilliseconds); if (result is SuccessfulCompileResult successfulResult) { var context = successfulResult.AssemblyLoadContext; if (context.Assemblies.Count() != 1) { throw new Exception("Assemblies loaded in load context is not equal to 1. This should not happen."); } var assembly = context.Assemblies.First(); var modules = _commandService.AddModules(assembly); Logger.LogInformation("Added {0} module(s).", modules.Count); _loadedModules.Add(id, new CommandModuleLoadContext(context, modules)); } return(result); }
private void LoadCommands() { _prefixes.Add(_config.Prefix); if (_config.AllowMentionPrefix) { _prefixes.Add($"<@{discordClient.CurrentUser.Id}>"); _prefixes.Add($"<@!{discordClient.CurrentUser.Id}>"); } _logger.LogInformation($"Using {_prefixes.Count} prefix{(_prefixes.Count > 1 ? "es" : "")}; {string.Join(", ", _prefixes)}."); _commands.AddTypeParser(new SocketUserParser <SocketUser>()); _commands.AddTypeParser(new SocketUserParser <SocketGuildUser>()); _commands.AddTypeParser(new SocketGuildChannelParser <SocketGuildChannel>()); _commands.AddTypeParser(new SocketGuildChannelParser <SocketTextChannel>()); _commands.AddTypeParser(new SocketGuildChannelParser <SocketCategoryChannel>()); _commands.AddTypeParser(new SocketGuildChannelParser <SocketVoiceChannel>()); _commands.AddTypeParser(new SocketRoleParser()); _commands.AddTypeParser(new CaseParser()); _commands.AddTypeParser(new TimeSpanParser()); _commands.AddTypeParser(new BanParser()); _commands.AddModules(Assembly.GetEntryAssembly(), action: m => { }); }
private IReadOnlyList <(Plugin Plugin, int ModuleCount, int CommandCount)> AddPluginCommands() { void MutateModule(ModuleBuilder moduleBuilder) { var methods = moduleBuilder.Type.GetMethods(BindingFlags.Static | BindingFlags.Public); var method = methods.FirstOrDefault(x => x.GetCustomAttribute <MutateModuleAttribute>() != null); if (method == null) { return; } method.Invoke(null, new object[] { moduleBuilder }); } var addedCommands = new List <(Plugin, int, int)>(); foreach (var plugin in Plugins) { var addedModules = _commandService.AddModules(plugin.Assembly, action: MutateModule); addedCommands.Add((plugin, addedModules.Count, addedModules.SelectMany(CommandUtilities.EnumerateAllCommands).Count())); } return(addedCommands); }
public async Task InitializeAsync() { var clientConfig = new DiscordSocketConfig() { AlwaysDownloadUsers = true, DefaultRetryMode = RetryMode.Retry502, MessageCacheSize = 50, LogLevel = LogSeverity.Info }; var commandConfig = new CommandServiceConfiguration() { DefaultRunMode = RunMode.Parallel, StringComparison = StringComparison.OrdinalIgnoreCase, IgnoresExtraArguments = true }; Client = new DiscordShardedClient(clientConfig); CommandService = new CommandService(commandConfig); Config = MakeConfig(); ScrapClient = new ScrapClient(Config["scrapApi"]); Provider = MakeProvider(); Logger = Provider.GetRequiredService <LoggerService>(); CommandService.AddModules(Assembly.GetEntryAssembly()); InitializeTypeParsers(); await InitializeServicesAsync(); }
public BotStartup(IServiceProvider services) { Services = services; DiscordClient = services.GetRequiredService <DiscordClient>(); CommandService = services.GetRequiredService <CommandService>(); CommandService.AddModules(services.GetRequiredService <Assembly>()); DiscordClient.MemberJoined += DiscordClient_UserJoined; }
async Task ICommandHandler.Initialize(ISlackConnection connection) { _connection = connection; _connection.OnMessageReceived += MessageReceived; _commandService.AddModules(Assembly.GetEntryAssembly()); _commandService.CommandErrored += CommandServiceOnCommandErrored; await Task.CompletedTask; }
public void Initialize() { IServiceCollection services = new ServiceCollection(); Provider = ConfigureServices(services); Commands = Provider.GetRequiredService <CommandService>(); Commands.AddModules(Assembly.GetEntryAssembly()); //Add Modules to the CommandService Client = Provider.GetRequiredService <DiscordSocketClient>(); }
public async Task InitializeAsync() { _service.AddTypeParsers(); var sw = Stopwatch.StartNew(); var loaded = _service.AddModules(Assembly.GetEntryAssembly()); sw.Stop(); await _logger.Log(LogSeverity.Info, LogSource.DepressedBot, $"Loaded {loaded.Count} modules and {loaded.Sum(m => m.Commands.Count)} commands loaded in {sw.ElapsedMilliseconds}ms."); _client.Log += async(m) => await _logger.Log(new LogEventArgs(m)); _client.Ready += async() => await OnReady(new ReadyEventArgs(_client)); _client.MessageReceived += async(s) => { if (!(s is SocketUserMessage msg)) { return; } if (msg.Author.IsBot) { return; } if (msg.Channel is IDMChannel dm) { if (msg.Content.StartsWith($"{Config.CommandPrefix}confess", StringComparison.OrdinalIgnoreCase)) { return; } await dm.SendMessageAsync("I do not support commands via DM."); return; } var args = new MessageReceivedEventArgs(msg); await HandleMessageReceivedAsync(args); }; _client.MessageReceived += async(s) => { if (!(s is SocketUserMessage msg)) { return; } if (msg.Author.IsBot) { return; } await _confessional.HandleMessageAsync(new DepressedBotContext(_client, msg, _provider)); }; }
public async Task InitializeAsync() { await _client.LoginAsync(TokenType.Bot, (await _database.BotConfigs.AsNoTracking().FirstAsync()).BotToken); await _client.StartAsync(); _commands.AddModules(Assembly.GetEntryAssembly()); _events.Initialize(); _reaction.Initialize(); _jobs.Initialize(); await Task.Delay(-1); }
public async Task InitializeAsync(IServiceProvider provider) { var sw = Stopwatch.StartNew(); var l = await _service.AddTypeParsersAsync(); sw.Stop(); _logger.Info(LogSource.Volte, $"Loaded TypeParsers: [{l.Select(x => x.SanitizeParserName()).Join(", ")}] in {sw.ElapsedMilliseconds}ms."); sw = Stopwatch.StartNew(); var loaded = _service.AddModules(GetType().Assembly); sw.Stop(); _logger.Info(LogSource.Volte, $"Loaded {loaded.Count} modules and {loaded.Sum(m => m.Commands.Count)} commands loaded in {sw.ElapsedMilliseconds}ms."); await _client.RegisterVolteEventHandlersAsync(provider); }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { var assembly = Assembly.GetEntryAssembly(); while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation("Worker running at: {time}", DateTimeOffset.UtcNow); _command.AddModules(assembly); _provider.GetRequiredService <CommandHandling>(); _provider.GetRequiredService <LogService>(); await _client.LoginAsync(TokenType.Bot, _config["Token"]); await _client.StartAsync(); await Task.Delay(-1, stoppingToken); } }
public void Initialize() { _commands.AddModules(Assembly.GetEntryAssembly()); _client.MessageCreated += OnMessageReceivedAsync; _commands.CommandExecuted += OnCommandExecuted; _commands.CommandErrored += OnCommandErrored; _commands.AddTypeParser(new DiscordMemberTypeParser()); _commands.AddTypeParser(new DiscordGuildTypeParser()); _commands.AddTypeParser(new DiscordUserTypeParser()); _commands.AddTypeParser(new DiscordChannelTypeParser()); _commands.AddTypeParser(new DiscordRoleTypeParser()); _commands.AddTypeParser(new SkeletonUserTypeParser()); _commands.AddTypeParser(new UriTypeParser()); _commands.AddTypeParser(new TimeSpanTypeParser()); _commands.AddTypeParser(new RegionTypeParser()); }
private void LoadCommands() { var sw = Stopwatch.StartNew(); var modulesInfo = JObject.Parse(File.ReadAllText(_commandsPath)) .SelectToken("modules")? .ToObject <List <ModuleInfo> >(); if (modulesInfo is null) { throw new KeyNotFoundException("The modules node array couldn't be loaded"); } var assembly = Assembly.GetAssembly(typeof(Rias)); _commandService.AddModules(assembly, null, module => SetUpModule(module, modulesInfo)); sw.Stop(); Log.Information($"Commands loaded: {sw.ElapsedMilliseconds} ms"); }
public async Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("Service starting up"); #warning If your commands are in a different assembly, you should edit this line appropriately. var modules = _commands.AddModules(Assembly.GetEntryAssembly()); _logger.LogInformation("Registered {0} commands in {1} modules", _commands.GetAllCommands().Count, modules.Count); _logger.LogInformation("Connecting the Discord client"); #warning Ensure that this configuration variable is set. await _client.LoginAsync(TokenType.Bot, _config["token"], true); await _client.StartAsync(); _logger.LogInformation("Client started up successfully"); }
private async Task RunAsync(StatsContext stats) { _stats = stats; _client = new DiscordSocketClient(); _commands = new CommandService(); await _commands.AddModules(Assembly.GetEntryAssembly()); _map = new DependencyMap(); _map.Add(_client); _map.Add(_stats); _client.MessageReceived += HandleCommand; _client.MessageReceived += HandleMessage; Console.WriteLine("Logging in..."); await _client.LoginAsync(TokenType.Bot, config["Token"]); await _client.ConnectAsync(); Console.WriteLine("Bot is ready."); await Task.Delay(-1); }
public async Task InitializeAsync() { var commandConfig = new CommandServiceConfiguration() { DefaultRunMode = RunMode.Parallel, StringComparison = StringComparison.OrdinalIgnoreCase, IgnoresExtraArguments = true }; CommandService = new CommandService(commandConfig); Config = MakeConfig(); Client = new TelegramBotClient(Config["tokens:telegram"]) { Timeout = TimeSpan.FromSeconds(20), }; Provider = MakeProvider(); await InitializeServicesAsync(); CommandService.AddModules(Assembly.GetEntryAssembly()); InitializeTypeParsers(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // API/Website Config services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Faforever.Qai", Version = "v1", Description = "The API for the Faforever.Qai and Dostya bots." }); }); // Bot Services Config DatabaseConfiguration dbConfig = new() { DataSource = $"Data Source={Configuration["Config:DataSource"]}" }; #if DEBUG // For use when the DB is Database/db-name.db if (!Directory.Exists("Database")) { Directory.CreateDirectory("Database"); } #endif string json = File.ReadAllText(Path.Join("Config", "games_config.json")); var botFunConfig = JsonConvert.DeserializeObject <BotFunConfiguration>(json); json = File.ReadAllText(Path.Join("Config", "url_config.json")); var urlConfig = JsonConvert.DeserializeObject <UrlConfiguration>(json); TwitchClientConfig twitchCfg = new() { ClientId = Configuration["Config:TwitchClientId"], ClientSecret = Environment.GetEnvironmentVariable("TWITCH_CLIENT_SECRET") }; services.AddLogging(options => options.AddConsole()) .AddDbContext <QAIDatabaseModel>(options => { options.UseSqlite(dbConfig.DataSource); }, ServiceLifetime.Singleton, ServiceLifetime.Singleton) .AddSingleton <RelayService>() // Command Service Registration .AddSingleton((x) => { var options = new CommandService(new CommandServiceConfiguration() { // Additional configuration for the command service goes here. }); // Command modules go here. options.AddModules(System.Reflection.Assembly.GetAssembly(typeof(CustomCommandContext))); // Argument converters go here. options.AddTypeParser(new DiscordChannelTypeConverter()); options.AddTypeParser(new DiscordRoleTypeConverter()); options.AddTypeParser(new BotUserCapsuleConverter()); options.AddTypeParser(new DiscordMemberConverter()); options.AddTypeParser(new DiscordUserConverter()); return(options); }) .AddSingleton <QCommandsHandler>() .AddSingleton(typeof(TwitchClientConfig), twitchCfg) // Operation Service Registration .AddSingleton <IBotFunService>(new BotFunService(botFunConfig)) .AddSingleton <IUrlService>(new UrlService(urlConfig)) .AddSingleton <DiscordEventHandler>() .AddSingleton <AccountLinkService>() .AddTransient <IFetchPlayerStatsOperation, ApiFetchPlayerStatsOperation>() .AddTransient <IFindPlayerOperation, ApiFindPlayerOperation>() .AddTransient <ISearchUnitDatabaseOperation, UnitDbSearchUnitDatabaseOpeartion>() .AddTransient <IPlayerService, OperationPlayerService>() .AddTransient <GameService>() .AddTransient <ISearchMapOperation, ApiSearchMapOperation>() .AddTransient <IFetchLadderPoolOperation, ApiFetchLadderPoolOperation>() .AddTransient <IFetchReplayOperation, ApiFetchReplayOperation>() .AddTransient <IFetchClanOperation, ApiFetchClanOperation>() .AddTransient <IFetchTwitchStreamsOperation, FetchTwitchStreamsOperation>() .AddTransient <FafApiClient>(); // HTTP Client Mapping services.AddHttpClient <ApiHttpClient>(client => { client.BaseAddress = ApiUri; }); services.AddHttpClient <UnitClient>(client => { client.BaseAddress = new Uri(UnitDbUtils.UnitApi); }); services.AddHttpClient <TwitchClient>(); // Discord Information Setup DiscordBotConfiguration discordConfig = new() { Prefix = Configuration["Config:BotPrefix"], Shards = 1, Token = Environment.GetEnvironmentVariable("DISCORD_TOKEN") }; var dcfg = new DiscordConfiguration { Token = discordConfig.Token, TokenType = TokenType.Bot, MinimumLogLevel = LogLevel.Debug, ShardCount = discordConfig.Shards, // Default to 1 for automatic sharding. Intents = DiscordIntents.Guilds | DiscordIntents.GuildMessages | DiscordIntents.DirectMessages, }; services.AddSingleton(discordConfig) .AddSingleton <DiscordShardedClient>(x => { return(new(dcfg)); }) .AddSingleton <DiscordRestClient>(x => { return(new(dcfg)); }) .AddSingleton <DiscordBot>(); // IRC Information Setup var user = Configuration["Config:Irc:User"]; var pass = Environment.GetEnvironmentVariable("IRC_PASS"); IrcConfiguration ircConfig = new() { Connection = Configuration["Config:Irc:Connection"], Channels = Configuration["Config:Irc:Channels"].Split(',').Select(s => s.Trim()).ToArray(), UserName = user, NickName = user, RealName = user, Password = pass }; var ircConnInfo = new IrcUserRegistrationInfo { NickName = ircConfig.NickName, RealName = ircConfig.RealName, Password = ircConfig.Password, UserName = ircConfig.UserName }; services.AddSingleton(ircConfig) .AddSingleton(ircConnInfo as IrcRegistrationInfo) .AddSingleton <QaIrc>(); // Setup the OAuth2 settings services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = "FAF"; }) .AddCookie() .AddOAuth("FAF", options => { options.AuthorizationEndpoint = $"{ApiUri}oauth/authorize"; // FAF API Endpoint. options.CallbackPath = new PathString("/authorization-code/callback"); // local auth endpoint options.AccessDeniedPath = new PathString("/api/link/denied"); // Other FAF OAtuh configuration settings options.ClientId = Configuration["Config:Faf:ClientId"]; options.ClientSecret = Environment.GetEnvironmentVariable("FAF_CLIENT_SECRET"); options.TokenEndpoint = $"{ApiUri}oauth/token"; options.Scope.Add("public_profile"); options.Events = new OAuthEvents { OnCreatingTicket = async context => { // Get the FAF user information var req = new HttpRequestMessage(HttpMethod.Get, $"{ApiUri}me"); req.Headers.Authorization = new("Bearer", context.AccessToken); var res = await context.Backchannel.SendAsync(req); if (res.IsSuccessStatusCode) { // if the request is valid, get the JSON data from it var rawJson = await res.Content.ReadAsStreamAsync(); var faf = await System.Text.Json.JsonSerializer.DeserializeAsync <FafUser>(rawJson); if (context.Request.Cookies.TryGetValue("token", out var token)) { var link = context.HttpContext.RequestServices.GetRequiredService <AccountLinkService>(); try { // bind the information to the link with the token from the cookies link.BindFafUser(token, faf.Data.Attributes.UserId, faf.Data.Attributes.UserName); } catch (Exception ex) { context.Response.Cookies.Append("error", ex.Message); } context.Success(); } else { context.Response.Cookies.Append("error", "No token found."); } } else { context.Response.Cookies.Append("error", "Failed to get user information from access token"); } }, OnRemoteFailure = context => { // TODO remove token from cookies and delete server token cache. Console.WriteLine(context.Failure.Message); return(Task.CompletedTask); } }; }) // OAuth2 setup for authenticating with Discord. .AddOAuth("DISCORD", options => { options.AuthorizationEndpoint = $"{Configuration["Config:Discord:Api"]}/oauth2/authorize"; options.CallbackPath = new PathString("/authorization-code/discord-callback"); // local auth endpoint options.AccessDeniedPath = new PathString("/api/link/denied"); options.ClientId = Configuration["Config:Discord:ClientId"]; options.ClientSecret = Environment.GetEnvironmentVariable("DISCORD_CLIENT_SECRET"); options.TokenEndpoint = $"{Configuration["Config:Discord:TokenEndpoint"]}"; options.Scope.Add("identify"); options.Events = new OAuthEvents { OnCreatingTicket = async context => { // get user data var client = new DiscordRestClient(new() { Token = context.AccessToken, TokenType = TokenType.Bearer }); var user = await client.GetCurrentUserAsync(); if (context.Request.Cookies.TryGetValue("token", out var token)) { var link = context.HttpContext.RequestServices.GetRequiredService <AccountLinkService>(); try { // verify the user information grabbed matches the user info // saved from the inital command if (!link.VerifyDiscord(token, user.Id)) { context.Response.Cookies.Append("error", "Discord ID used for sign in did not match Discord ID from the Discord Application."); } } catch (Exception ex) { context.Response.Cookies.Append("error", ex.Message); } context.Success(); } else { context.Response.Cookies.Append("error", "No token found."); } }, OnRemoteFailure = context => { // TODO remove token from cookies and delete server token cache. return(Task.CompletedTask); } }; }); }
private static void Main(string[] args) { var configuration = new ConfigurationBuilder() .AddCommandLine(args) .Build(); if (configuration.GetSection("GenerateMarkdown").Exists()) { var service = new CommandService(); service.AddModules(typeof(CharacterMainCommands).Assembly); GenerateCommandMarkdown(service); return; } using var host = new HostBuilder() .ConfigureAppConfiguration(x => { x.AddEnvironmentVariables("SHINE_"); }) .ConfigureLogging(x => { var logger = new LoggerConfiguration() .MinimumLevel.Override("Microsoft", LogEventLevel.Error) .WriteTo.Console( outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}") .WriteTo.File("Logs/log_.txt", outputTemplate: "{Timestamp:HH:mm:ss} [{Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}", rollingInterval: RollingInterval.Day) .CreateLogger(); x.AddSerilog(logger, true); x.Services.Remove(x.Services.First(y => y.ServiceType == typeof(ILogger <>))); x.Services.AddSingleton(typeof(ILogger <>), typeof(DummyLogger <>)); }) .ConfigureServices((context, services) => { services.AddSingleton <Random>(); services.AddSingleton <HttpClient>(); services.AddDbContext <ShineDbContext>(options => { var connectionString = context.Configuration["DB_CONNECTION_STRING"]; options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); }); }) .ConfigureDiscordBot((context, bot) => { bot.Token = context.Configuration["TOKEN"]; bot.OwnerIds = new Snowflake[] { 167452465317281793, 114926832440180738, 176081685702639616 }; bot.Prefixes = new[] { PREFIX }; bot.Activities = new[] { new LocalActivity(PREFIX, ActivityType.Playing) }; }) .Build(); host.Run(); }
public async Task RunBotAsync() { var config = new Config("./config.json"); var clashClient = new ClashClient(new ClashClientConfig { Token = config.ClashToken }); var bandClient = new BandClient(new BandClientConfig { Token = config.BandToken }); var asm = Assembly.GetEntryAssembly(); _services = new ServiceCollection() .AddSingleton(_client = new DiscordSocketClient(new DiscordSocketConfig { LogLevel = LogSeverity.Verbose, AlwaysDownloadUsers = true, MessageCacheSize = 100 })) .AddSingleton(_commands = new CommandService(new CommandServiceConfiguration { StringComparison = StringComparison.InvariantCultureIgnoreCase }) .AddTypeParsers(asm)) .AddSingleton(clashClient) .AddSingleton(bandClient) .AddSingleton <TaskQueue>() .AddServices(asm.FindTypesWithAttribute <ServiceAttribute>()) .BuildServiceProvider(); var tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); Task OnReadyAsync() { tcs.SetResult(true); _client.Ready -= OnReadyAsync; return(Task.CompletedTask); } _client.Ready += OnReadyAsync; _client.UserJoined += user => { Task.Run(async() => { var guild = _services.GetService <DatabaseService>().Guild; var dGuild = _client.GetGuild(guild.Id); var channel = dGuild.GetTextChannel(guild.WelcomeChannelId); var role = dGuild.GetRole(guild.NotVerifiedRoleId); await user.AddRoleAsync(role); var builder = new EmbedBuilder { Color = new Color(0x11f711), ThumbnailUrl = dGuild.CurrentUser.GetAvatarUrl(), Title = "Welcome to the Discord!", Description = $"{user.GetDisplayName()} welcome to Reddit Rise!\nHere are some premade, perfect FWA bases. Please click the link that corresponds to your TH.\n" + $"{Format.Url("TH12", "https://link.clashofclans.com/en?action=OpenLayout&id=TH12%3AWB%3AAAAAHQAAAAFw3gmOJJOUocokY9SNAt9V")}\n" + $"{Format.Url("TH11", "https://link.clashofclans.com/en?action=OpenLayout&id=TH11%3AWB%3AAAAAOwAAAAE4a6sCQApcIa9kDl5W1N3C")}\n" + $"{Format.Url("TH10", "https://link.clashofclans.com/en?action=OpenLayout&id=TH10%3AWB%3AAAAAFgAAAAF-L9A_pnLR3BtoRk7SZjD_")}\n" + $"{Format.Url("TH9", "https://link.clashofclans.com/en?action=OpenLayout&id=TH9%3AWB%3AAAAAHQAAAAFw3chc3wBw2ipMxGm6Mq8P")}\n" + "and if you're feeling nice post your in game player tag (e.g. #YRQ2Y0UC) so we know who you are!" }; await channel.SendMessageAsync(user.Mention, embed: builder.Build()); }); return(Task.CompletedTask); }; var logger = _services.GetService <LogService>(); _client.Log += message => { var(source, severity, lMessage, exception) = LogFactory.FromDiscord(message); return(logger.LogAsync(source, severity, lMessage, exception)); }; //TODO do this properly _client.UserLeft += (user) => { var channel = _client.GetChannel(533650294509404181) as SocketTextChannel; return(channel.SendMessageAsync($"{user.GetDisplayName()} left")); }; clashClient.Log += message => logger.LogAsync(Source.Clash, Severity.Verbose, message); clashClient.Error += error => logger.LogAsync(Source.Clash, Severity.Error, error.Message); bandClient.Log += message => logger.LogAsync(Source.Band, Severity.Verbose, message); bandClient.Error += error => logger.LogAsync(Source.Band, Severity.Error, error.Message); await _client.LoginAsync(TokenType.Bot, config.BotToken); await _client.StartAsync(); _commands.AddModules(Assembly.GetEntryAssembly()); await tcs.Task; _services.GetService <MessageService>(); //Task.Run(() => _services.GetService<BigBrotherService>().RunServiceAsync()); #if !DEBUG Task.Run(() => _services.GetService <WarReminderService>().StartRemindersAsync()); Task.Run(() => _services.GetService <WarReminderService>().StartPollingServiceAsync()); Task.Run(() => _services.GetService <StartTimeService>().StartServiceAsync()); #endif await Task.Delay(-1); }