protected virtual ValueTask <(string Prefix, string Output)> FindPrefixAsync(CachedUserMessage message) { if (CommandUtilities.HasAnyPrefix(message.Content, Prefixes, out var prefix, out var output)) { return(new ValueTask <(string, string)>((prefix, output))); } return(default);
public async Task HandleAsync(MessageReceivedEventArgs args) { if (!(args.Message is CachedUserMessage message) || message.Author.IsBot || string.IsNullOrWhiteSpace(message.Content)) { return; } var prefixes = new List <string> { _config.DefaultPrefix }; LocalizedLanguage language; using var ctx = new AdminDatabaseContext(_provider); if (message.Channel is IGuildChannel guildChannel) { Guild guild = null; if (!_languages.TryGetValue(guildChannel.GuildId, out language)) { guild = await ctx.GetOrCreateGuildAsync(guildChannel.GuildId); _languages[guild.Id] = language = guild.Language; } if (!_guildPrefixes.TryGetValue(guildChannel.GuildId, out var customPrefixes)) { guild ??= await ctx.GetOrCreateGuildAsync(guildChannel.GuildId); _guildPrefixes[guild.Id] = customPrefixes = guild.CustomPrefixes; } prefixes.AddRange(customPrefixes); } else if (!_languages.TryGetValue(message.Author.Id, out language)) { var user = await ctx.GetOrCreateGlobalUserAsync(message.Author.Id); _languages[user.Id] = language = user.Language; } if (!CommandUtilities.HasAnyPrefix(message.Content, prefixes, StringComparison.OrdinalIgnoreCase, out var prefix, out var input)) { return; } var context = new AdminCommandContext(message, prefix, language, _provider); IResult result; if (!context.IsPrivate && await ctx.CommandAliases .FirstOrDefaultAsync(x => x.GuildId == context.Guild.Id && input.StartsWith(x.Alias, StringComparison.InvariantCultureIgnoreCase)) is { } alias) { result = await _commands.ExecuteAsync(alias, input, context); }
public async Task StartAsync() { string discordToken = ""; await Client.LoginAsync(TokenType.Bot, discordToken); // Login to discord await Client.StartAsync(); // Start message receiving Client.Log += x => { Console.WriteLine(x.Message); return(Task.CompletedTask); }; Commands.CommandErrored += (result, ctx, provider) => { Console.WriteLine(result.Exception.ToString()); return(Task.CompletedTask); }; Client.MessageReceived += async s => { if (!(s is SocketUserMessage msg)) { return; //Do some checks } if (msg.Author.IsBot) { return; } if (msg.Author.Id == Client.CurrentUser.Id) { return; } var context = new ExampleCommandContext(msg); if (!CommandUtilities.HasAnyPrefix(msg.Content, new[] { "!" }, StringComparison.OrdinalIgnoreCase, out string usedPrefix, out string cmd)) { return; } var result = await Commands.ExecuteAsync(cmd, context, Provider); //Try to run Command if (result is FailedResult failResult) { await context.Channel.SendMessageAsync(failResult.Reason); } return; }; await Task.Delay(-1); //Wait forever to keep the bot running }
public async Task <bool> TryExecuteCommandAsync(SocketUserMessage userMessage) { if (userMessage.Source != MessageSource.User || string.IsNullOrWhiteSpace(userMessage.Content)) { return(false); } var prefixes = new List <string> { _config.DefaultPrefix, $"<@{_client.CurrentUser.Id}> ", $"<@!{_client.CurrentUser.Id}> " }; LocalizedLanguage language; using (var ctx = new AdminDatabaseContext(_provider)) { if (userMessage.Channel is IGuildChannel guildChannel) { var guild = await ctx.GetOrCreateGuildAsync(guildChannel.GuildId); prefixes.AddRange(guild.CustomPrefixes); language = guild.Language; } else { var user = await ctx.GetOrCreateGlobalUserAsync(userMessage.Author.Id); language = user.Language; } } if (!CommandUtilities.HasAnyPrefix(userMessage.Content, prefixes, StringComparison.OrdinalIgnoreCase, out var prefix, out var input)) { return(false); } var context = new AdminCommandContext(userMessage, prefix, language, _provider); var result = await _commands.ExecuteAsync(input, context, _provider); if (!(result is FailedResult failedResult)) { return(true); } // TODO: localized error messages, log var error = new StringBuilder() .Append(failedResult switch { ParameterChecksFailedResult parameterChecksResult => string.Join('\n', parameterChecksResult.FailedChecks.Select(x => x.Error)), ChecksFailedResult checkResult => string.Join('\n', checkResult.FailedChecks.Select(x => x.Error)), ExecutionFailedResult execResult => GenerateException(execResult.Exception), CommandNotFoundResult _ => string.Empty, _ => failedResult.Reason }).ToString();
public async Task HandleMessageAsync(MessageReceivedEventArgs args) { if (Config.EnabledFeatures.Blacklist) { await _blacklist.DoAsync(args); } if (Config.EnabledFeatures.Antilink) { await _antilink.DoAsync(args); } if (Config.EnabledFeatures.PingChecks) { await _pingchecks.DoAsync(args); } var prefixes = new List <string> { args.Data.Configuration.CommandPrefix, $"<@{args.Context.Client.CurrentUser.Id}> ", $"<@!{args.Context.Client.CurrentUser.Id}> " }; if (CommandUtilities.HasAnyPrefix(args.Message.Content, prefixes, StringComparison.OrdinalIgnoreCase, out _, out var cmd)) { var sw = Stopwatch.StartNew(); var result = await _commandService.ExecuteAsync(cmd, args.Context); if (result is CommandNotFoundResult) { return; } sw.Stop(); await _commandsService.OnCommandAsync(new CommandCalledEventArgs(result, args.Context, sw)); if (args.Data.Configuration.DeleteMessageOnCommand) { if (!await args.Message.TryDeleteAsync()) { _logger.Warn(LogSource.Service, $"Could not act upon the DeleteMessageOnCommand setting for {args.Context.Guild.Name} as the bot is missing the required permission, or another error occured."); } } } else { await _quoteService.DoAsync(args); } }
private async Task OnMessageReceivedAsync(MessageCreateEventArgs e) { if (e.Author.IsBot) { return; } try { var ctxBase = new FoxContext(e, _services); _ = Task.Run(() => ExecuteReminderAsync(e)); _ = Task.Run(() => ExecuteCustomCommandAsync(ctxBase)); if (ctxBase.DatabaseContext.User.IsBlacklisted) { return; } var prefixes = ctxBase.DatabaseContext.Guild.Prefixes; if (ctxBase.Message.MentionedUsers.Contains(ctxBase.Client.CurrentUser) && ctxBase.Message.Content.Contains("prefix", StringComparison.OrdinalIgnoreCase)) { await ctxBase.RespondAsync($"Prefixes for this guild: {string.Join(", ", prefixes.Select(x => $"`{x}`"))}"); } if (!CommandUtilities.HasAnyPrefix(e.Message.Content, prefixes, StringComparison.OrdinalIgnoreCase, out var prefix, out var content)) { return; } var context = new FoxCommandContext(ctxBase, prefix); var result = await _commands.ExecuteAsync(content, context, _services); if (result.IsSuccessful) { return; } await HandleCommandErroredAsync(result, context); } catch (Exception ex) { _logger.Print(LogLevel.Critical, "Handler", ex.StackTrace); } }
public async Task HandleMessageAsync(MessageReceivedEventArgs args) { if (Config.EnabledFeatures.Blacklist) { await _blacklist.CheckMessageAsync(args); } if (Config.EnabledFeatures.Antilink) { await _antilink.CheckMessageAsync(args); } if (Config.EnabledFeatures.PingChecks) { await _pingchecks.CheckMessageAsync(args); } var prefixes = new List <string> { args.Data.Configuration.CommandPrefix, $"<@{args.Context.Client.CurrentUser.Id}> ", $"<@!{args.Context.Client.CurrentUser.Id}> " }; if (CommandUtilities.HasAnyPrefix(args.Message.Content, prefixes, StringComparison.OrdinalIgnoreCase, out _, out var cmd)) { var sw = Stopwatch.StartNew(); var result = await _commandService.ExecuteAsync(cmd, args.Context); sw.Stop(); if (!(result is CommandNotFoundResult)) { await OnCommandAsync(new CommandCalledEventArgs(result, args.Context, sw)); } } else { if (args.Message.Content.EqualsAnyIgnoreCase($"<@{args.Context.Client.CurrentUser.Id}>", $"<@!{args.Context.Client.CurrentUser.Id}>")) { await args.Context.CreateEmbed( $"The prefix for this guild is **{args.Data.Configuration.CommandPrefix}**; " + $"alternatively you can just mention me as a prefix, i.e. `@{args.Context.Guild.CurrentUser} help`.") .ReplyToAsync(args.Message); } else if (!await _quoteService.CheckMessageAsync(args)) { if (CommandUtilities.HasPrefix(args.Message.Content, '%', out var tagName)) { var tag = args.Context.GuildData.Extras.Tags.FirstOrDefault(t => t.Name.EqualsIgnoreCase(tagName)); if (tag is null) { return; } if (args.Context.GuildData.Configuration.EmbedTagsAndShowAuthor) { await tag.AsEmbed(args.Context).SendToAsync(args.Message.Channel); } else { await args.Message.Channel.SendMessageAsync(tag.FormatContent(args.Context)); } } } } }
private async Task HandleReceivedMessageAsync(CachedUserMessage message) { if (message.Author.IsBot) { return; } if (!(message.Channel is CachedTextChannel textChannel) || !textChannel.Guild.CurrentMember.GetPermissionsFor(textChannel).Has(Permission.SendMessages)) { return; } if (CommandUtilities.HasAnyPrefix(message.Content, Prefixes, StringComparison.CurrentCulture, out var prefix, out var output) || CommandUtilities.HasPrefix(message.Content, $"<@{Client.CurrentUser.Id}>", StringComparison.Ordinal, out output) || CommandUtilities.HasPrefix(message.Content, $"<@!{Client.CurrentUser.Id}>", StringComparison.Ordinal, out output)) { if (string.IsNullOrWhiteSpace(output)) { return; } try { if (prefix is null) { prefix = Client.CurrentUser.Mention; } var ctx = MummyContext.Create(Client, message, Services, prefix); ActiveTimings[ctx.UserId] = Stopwatch.StartNew(); var r = await Commands.ExecuteAsync(output, ctx); ActiveTimings[ctx.UserId].Stop(); ActiveTimings.Remove(ctx.UserId, out var st); if (r.IsSuccessful) { LogService.LogInformation($"command: {ctx.Command.Name} has successful finished execution in {st.ElapsedMilliseconds}ms.", LogSource.MessagesService, ctx.GuildId); } else { switch (r) { case ExecutionFailedResult executionfailed: { LogService.LogError(executionfailed.ToString(), LogSource.MessagesService, ctx.GuildId, executionfailed.Exception); break; } case ArgumentParseFailedResult parsefailed: { var eb = new LocalEmbedBuilder(); eb.WithAuthor(ctx.User); eb.WithTitle("ArmgumentParseFailure"); eb.AddField(parsefailed.Reason, parsefailed.RawArguments); await ctx.Channel.SendMessageAsync(embed : eb.Build()); break; } case ArgumentParserResult parseresult: { LogService.LogCritical("dunno argumentparse", LogSource.MessagesService, ctx.GuildId); await ctx.Channel.SendMessageAsync("a error has occoured and not been handled this error will be resolved shortly. (hopefully)"); break; } case ChecksFailedResult checksfailed: { var eb = new LocalEmbedBuilder(); eb.WithAuthor(ctx.User); eb.WithTitle($"{checksfailed.FailedChecks.Count} checks have failed"); foreach (var(Check, Result) in checksfailed.FailedChecks) { eb.AddField((Check as MummyCheckBase).Name, Result.Reason, true); } await ctx.Channel.SendMessageAsync(embed : eb.Build()); break; } case CommandDisabledResult disabled: { var eb = new LocalEmbedBuilder(); eb.WithAuthor(ctx.User); await ctx.Channel.SendMessageAsync(); eb.WithTitle($"{disabled.Command} is currently diabled"); await ctx.Channel.SendMessageAsync(embed : eb.Build()); break; } case CommandNotFoundResult notfound: { var eb = new LocalEmbedBuilder(); eb.WithAuthor(ctx.User); eb.WithTitle($"command with name {notfound.Reason}"); await ctx.Channel.SendMessageAsync(embed : eb.Build()); break; } case CommandOnCooldownResult oncooldown: { var eb = new LocalEmbedBuilder(); eb.WithAuthor(ctx.User); eb.WithTitle($"{oncooldown.Command.Name} is currently on cooldown"); foreach (var(cooldown, retryafter) in oncooldown.Cooldowns) { int index = cooldown.ToString().LastIndexOf('.'); var bucketype = (CooldownBucketType)cooldown.BucketType; eb.AddField(cooldown.ToString().Substring(index + 1), $"is only allowed to be run {cooldown.Amount} per {cooldown.Per.Humanize()} and it forced per {bucketype}, currently locked for {retryafter.TotalMinutes} Minutes", true); } await ctx.Channel.SendMessageAsync(embed : eb.Build()); break; } case OverloadsFailedResult overloadsFailed: { var eb = new LocalEmbedBuilder(); eb.WithAuthor(ctx.User); eb.WithDescription(overloadsFailed.Reason); foreach (var(command, overloadResult) in overloadsFailed.FailedOverloads) { eb.AddField($"{command.Name} {string.Join(' ', command.Parameters.Select(x => x.Name))}", overloadResult.Reason); } await ctx.Channel.SendMessageAsync(embed : eb.Build()); break; } case ParameterChecksFailedResult paramcheckfailed: { var eb = new LocalEmbedBuilder(); eb.WithAuthor(ctx.User); eb.WithTitle($"checks on {paramcheckfailed.Parameter} have failed with provided argument: {paramcheckfailed.Argument}"); foreach (var(Check, Result) in paramcheckfailed.FailedChecks) { var index = Check.ToString().LastIndexOf('.'); var name = Check.ToString().Substring(index + 1); eb.AddField(name, Result.Reason); } break; } case TypeParseFailedResult typeParseFailed: { var eb = new LocalEmbedBuilder(); eb.WithAuthor(ctx.User); eb.AddField(typeParseFailed.Parameter.Name, typeParseFailed.Reason); await ctx.Channel.SendMessageAsync(embed : eb.Build()); break; } } } } catch (Exception ex) { LogService.LogError("Issue with message service", LogSource.MessagesService, exception: ex); } } }
public async Task StartAsync() { string path = @"config.dkk"; string[] readText = File.ReadAllLines(path); string key = readText[0]; await Client.LoginAsync(TokenType.Bot, key); await Client.StartAsync(); await Client.SetGameAsync("%help"); Client.Log += x => { Console.WriteLine(x.Message); return(Task.CompletedTask); }; Commands.CommandErrored += (result, ctx, provider) => { Console.WriteLine(result.Exception.ToString()); return(Task.CompletedTask); }; Client.MessageReceived += async s => { if (!(s is SocketUserMessage msg)) { return; //Do some checks } if (!msg.Author.IsBot) { Console.WriteLine(msg.Author + " said: " + msg.Content); try { SocketGuild server = ((SocketGuildChannel)msg.Channel).Guild; using (System.IO.StreamWriter file = new System.IO.StreamWriter($"logs/{server.Name} - Log.txt", true)) { await file.WriteLineAsync(System.DateTime.Now + " | " + msg.Channel + " | " + msg.Author + " said: " + msg.Content); } } catch (Exception e) { Console.WriteLine(e.Message); } } if (msg.Author.IsBot) { return; } if (msg.Author.Id == Client.CurrentUser.Id) { return; } var context = new CommandHandlingService(msg); if (!CommandUtilities.HasAnyPrefix(msg.Content, new[] { "%" }, StringComparison.OrdinalIgnoreCase, out string usedPrefix, out string cmd) == true) { return; } var result = await Commands.ExecuteAsync(cmd, context, Provider); //Try to run Command if (result is FailedResult failResult) { await context.Channel.SendMessageAsync(failResult.Reason); } return; }; await Task.Delay(-1); //Wait forever to keep the bot running }
private async Task StartAsync() { async Task LoginRoutine() { await discordClient.LoginAsync(TokenType.Bot, _config.DiscordToken); await discordClient.StartAsync(); await Task.Delay(-1); } discordClient.Ready += async() => { if (!IsReady) { ApplicationInfo = await discordClient.GetApplicationInfoAsync(); _logger.LogInformation($"Logged into Discord as \"{discordClient.CurrentUser}\" in {discordClient.Guilds.Count} guild{(discordClient.Guilds.Count > 1 ? "s" : "")}."); LoadCommands(); var guildStorage = _serviceProvider.GetService <GuildStorage>(); var dbGuilds = await guildStorage.GetAllGuildsAsync(); foreach (var guild in dbGuilds) { var unexpiredCases = guild.Cases.Where(x => (x.GetEndingTime() > DateTimeOffset.UtcNow && x.ActionType != ActionType.Warn) || (x.ActionType == ActionType.Warn && x.GetWarnEndingTime() > DateTimeOffset.UtcNow)); int failedCaseAdds = 0; foreach (var guildCase in unexpiredCases) { if (!_caseHandlingService.TryAdd(guildCase)) { failedCaseAdds++; } } if (failedCaseAdds > 0) { _logger.LogWarning($"Failed to add {failedCaseAdds} cases to in-memory cache."); } //resolve all cases that had expired var unresolvedExpiredCases = guild.Cases.Where(x => !x.Resolved && ((x.ActionType != ActionType.Warn && x.GetEndingTime() <= DateTimeOffset.UtcNow) || (x.GetWarnEndingTime() <= DateTimeOffset.UtcNow && x.ActionType == ActionType.Warn))); foreach (var guildCase in unresolvedExpiredCases) { await _caseHandlingService.ResolveAsync(guildCase, null, null, false, false); } } IsReady = true; } }; discordClient.MessageReceived += async(m) => { if (m.Channel is IDMChannel) { return; } if (!(m is SocketUserMessage msg)) { return; } if (CommandUtilities.HasAnyPrefix(msg.Content, _prefixes, StringComparison.OrdinalIgnoreCase, out string pfx, out string output)) { var context = new QuiccbanContext(discordClient, msg, _serviceProvider); var result = await _commands.ExecuteAsync(output, context, _serviceProvider); if (result is QuiccbanSuccessResult success && !string.IsNullOrWhiteSpace(success.ReplyValue)) { await context.Channel.SendMessageAsync(success.ReplyValue); } if (result is QuiccbanFailResult inCommandFail) { await context.Channel.SendMessageAsync(inCommandFail.Reason); } if (result is ChecksFailedResult checkFail) { await context.Channel.SendMessageAsync(checkFail.FailedChecks.FirstOrDefault().Error); } if (result is ParameterChecksFailedResult paramCheckFail) { await context.Channel.SendMessageAsync(paramCheckFail.FailedChecks.FirstOrDefault().Error); } } }; discordClient.UserBanned += async(u, g) => { await Task.Delay(500); var auditLogs = await g.GetAuditLogsAsync(20).FlattenAsync(); var auditLog = auditLogs.FirstOrDefault(a => a.Data is BanAuditLogData ban && ban.Target.Id == u.Id); if (auditLog == null) { return; } if (auditLog.User.Id == discordClient.CurrentUser.Id) { return; } var data = auditLog.Data as BanAuditLogData; var dbService = _serviceProvider.GetService <DatabaseService>(); await dbService.CreateNewCaseAsync(g, auditLog.Reason, ActionType.Ban, 0, auditLog.User, data.Target); }; discordClient.UserUnbanned += async(u, g) => { await Task.Delay(500); var auditLogs = await g.GetAuditLogsAsync(20).FlattenAsync(); var auditLog = auditLogs.FirstOrDefault(a => a.Data is UnbanAuditLogData unban && unban.Target.Id == u.Id); if (auditLog == null) { return; } if (auditLog.User.Id == discordClient.CurrentUser.Id) { return; } var data = auditLog.Data as UnbanAuditLogData; var dbService = _serviceProvider.GetService <DatabaseService>(); var caseService = _serviceProvider.GetService <CaseHandlingService>(); var tempcase = caseService.GetCases().FirstOrDefault(x => x.GuildId == g.Id && x.TargetId == data.Target.Id && x.ActionType == ActionType.TempBan && !x.Resolved); if (tempcase != null) { await _caseHandlingService.ResolveAsync(tempcase, auditLog.User, auditLog.Reason, true, false); } else { await dbService.CreateNewCaseAsync(g, auditLog.Reason, ActionType.Ban, 0, auditLog.User, data.Target); } }; discordClient.UserLeft += async(u) => { await Task.Delay(500); var auditLogs = await u.Guild.GetAuditLogsAsync(20).FlattenAsync(); var auditLog = auditLogs.FirstOrDefault(a => a.Data is KickAuditLogData kick && kick.Target.Id == u.Id); if (auditLog == null) { return; } if (auditLog.User.Id == discordClient.CurrentUser.Id) { return; } var data = auditLog.Data as KickAuditLogData; var dbService = _serviceProvider.GetService <DatabaseService>(); await dbService.CreateNewCaseAsync(u.Guild, auditLog.Reason, ActionType.Kick, 0, auditLog.User, data.Target); }; discordClient.GuildMemberUpdated += async(u_before, u_after) => { await Task.Delay(500); var auditLogs = await u_after.Guild.GetAuditLogsAsync(20).FlattenAsync(); var auditLog = auditLogs.FirstOrDefault(a => a.Data is MemberRoleAuditLogData role && role.Target.Id == u_after.Id); if (auditLog == null) { return; } if (auditLog.User.Id == discordClient.CurrentUser.Id) { return; } var data = auditLog.Data as MemberRoleAuditLogData; var dbService = _serviceProvider.GetService <DatabaseService>(); var caseService = _serviceProvider.GetService <CaseHandlingService>(); var dbGuild = await dbService.GetOrCreateGuildAsync(u_after.Guild); if (data.Roles.Any(x => x.RoleId == dbGuild.MuteRoleId && x.Added)) { await dbService.CreateNewCaseAsync(u_after.Guild, auditLog.Reason, ActionType.Mute, 0, auditLog.User, data.Target); } else if (data.Roles.Any(x => x.RoleId == dbGuild.MuteRoleId && !x.Added)) { var tempcase = caseService.GetCases().FirstOrDefault(x => x.TargetId == data.Target.Id && x.ActionType == ActionType.TempMute && !x.Resolved); if (tempcase != null) { await _caseHandlingService.ResolveAsync(tempcase, auditLog.User, auditLog.Reason, true, false); } else { await dbService.CreateNewCaseAsync(u_after.Guild, auditLog.Reason, ActionType.Unmute, 0, auditLog.User, data.Target); } } }; _logger.LogInformation("Attempting to log into Discord..."); try { await LoginRoutine(); } catch { _logger.LogError("Failed to log into Discord. Attempting reconnect in 10 seconds."); await Task.Delay(10000); try { await LoginRoutine(); } catch { _logger.LogError("Reconnection failed. Exiting."); Environment.Exit(0); } } }
public bool IsCommand(SocketUserMessage message, ulong guildId) => CommandUtilities.HasAnyPrefix(message.Content, new[] { Database.GetData(guildId).Configuration.CommandPrefix, $"<@{Client.CurrentUser.Id}> ", $"<@!{Client.CurrentUser.Id}> " }, StringComparison.OrdinalIgnoreCase, out _, out _);