private async Task HandleBadRequest(DiscordMessage message, DiscordUser author, DiscordChannel channel, IEnumerable <string> commandSegments, string commandAlias, BaseDiscordCommand command, DateTimeOffset start) { LogMessage?.Invoke(this, $"[{message.Channel.Guild?.Name ?? message.Channel.Name}] {command.Name} does not take {commandSegments.Count()} arguments."); _telemetryClient?.TrackRequest(InternalTools.GetRequestTelemetry(author, channel, command, start, "400", false)); if (command.Usage != null) { await InternalTools.SendTemporaryMessage(message, author, channel, $"```\r\n{commandAlias} usage: {_config.Prefix}{commandAlias} [{command.Usage}]\r\n```"); } }
private async Task Client_GuildAvailable(GuildCreateEventArgs e) { LogMessage?.Invoke(this, $"Guild {e.Guild.Name} is now available"); _telemetryClient?.TrackEvent($"GuildAvailable", new Dictionary <string, string> { { "id", e.Guild.Id.ToString() }, { "name", e.Guild.Name } }); _config.SeenGuilds.Add(e.Guild.Id); if (_config.DisallowedGuilds.Contains(e.Guild.Id)) { DiscordChannel c = await InternalTools.GetFirstChannelAsync(e.Guild); await c.SendMessageAsync(":middle_finger:"); await e.Guild.LeaveAsync(); } }
private async Task Client_GuildCreated(GuildCreateEventArgs e) { LogMessage?.Invoke(this, $"Guild {e.Guild.Name} has been added!"); _telemetryClient?.TrackEvent($"GuildJoin", new Dictionary <string, string> { { "id", e.Guild.Id.ToString() }, { "name", e.Guild.Name } }); if (_config.DisallowedGuilds.Contains(e.Guild.Id)) { DiscordChannel c = await InternalTools.GetFirstChannelAsync(e.Guild); await c.SendMessageAsync(":middle_finger:"); await e.Guild.LeaveAsync(); } else { await InternalTools.SendWelcomeMessage(e.Guild, _config); } }
private async Task ExecuteCommandAsync(DiscordMessage message, DiscordUser author, DiscordChannel channel, IEnumerable <string> commandSegments, string commandAlias, BaseDiscordCommand command, DateTimeOffset start) { try { LogMessage?.Invoke(this, ($"[{message.Channel.Guild?.Name ?? message.Channel.Name}] Found {command.Name} command!")); _processedMessageIds.Add(message.Id); if (command.ArgumentCountPrecidate(commandSegments.Count())) { if (InternalTools.CheckPermissions(_discordClient, channel.Guild?.CurrentMember ?? _discordClient.CurrentUser, channel, command)) { if (InternalTools.CheckPermissions(_discordClient, author, channel, command)) { LogMessage?.Invoke(this, ($"[{message.Channel.Guild?.Name ?? message.Channel.Name}] Running command \"{command.Name}\" asynchronously.")); new Task(async() => await RunCommandAsync(message, author, channel, commandSegments, commandAlias, command, start)).Start(); } else { LogMessage?.Invoke(this, ($"[{message.Channel.Guild?.Name ?? message.Channel.Name}] Attempt to run command without correct user permissions.")); await InternalTools.SendTemporaryMessage(message, author, channel, $"Oi! You're not allowed to run that command! F**k off!"); _telemetryClient?.TrackRequest(InternalTools.GetRequestTelemetry(author, channel, command, start, "401", false)); } } else { LogMessage?.Invoke(this, ($"[{message.Channel.Guild?.Name ?? message.Channel.Name}] Attempt to run command without correct bot permissions.")); await InternalTools.SendTemporaryMessage(message, author, channel, $"Sorry! I don't have permission to run that command in this server! Contact an admin/mod for more info."); _telemetryClient?.TrackRequest(InternalTools.GetRequestTelemetry(author, channel, command, start, "403", false)); } } else { await HandleBadRequest(message, author, channel, commandSegments, commandAlias, command, start); } } catch (Exception ex) { Console.WriteLine(ex); } }
private async Task RunCommandAsync(DiscordMessage message, DiscordUser author, DiscordChannel channel, IEnumerable <string> commandSegments, string commandAlias, BaseDiscordCommand command, DateTimeOffset start) { bool success = true; try { await channel.TriggerTypingAsync(); command = InstantateDiscordCommand(command.GetType()); _config.Happiness.TryGetValue(author.Id, out sbyte h); CommandContext context = new CommandContext(commandSegments.ToArray(), message, _discordClient) { Happiness = h, _logger = _loggerFactory.CreateLogger("Commands") }; context.AdditionalData["botContext"] = this; string[] cmdsegarr = commandSegments.ToArray(); CommandResult result = await command.RunCommand(cmdsegarr, context); LogMessage?.Invoke(this, ($"[{message.Channel.Guild?.Name ?? message.Channel.Name}] \"{command.Name}\" returned ReturnType.{result.ReturnType}.")); if (result.ReturnType != ReturnType.None) { if (result.ReturnType == ReturnType.Text && result.ResultText.Length > 2000) { for (int i = 0; i < result.ResultText.Length; i += 1993) { string str = result.ResultText.Substring(i, Math.Min(1993, result.ResultText.Length - i)); if (result.ResultText.StartsWith("```") && !str.StartsWith("```")) { str = "```" + str; } if (result.ResultText.EndsWith("```") && !str.EndsWith("```")) { str = str + "```"; } LogMessage?.Invoke(this, ($"Chunking message to {str.Length} chars")); await channel.SendMessageAsync(str); await Task.Delay(2000); } } else { if (!string.IsNullOrWhiteSpace(result.Attachment)) { await channel.SendFileAsync(result.Attachment, result.ResultText, embed : result.ResultEmbed); } else if (result.Stream != null || result.ReturnType == ReturnType.File) { if (result.Stream.Length <= 8 * 1024 * 1024) { await channel.SendFileAsync(result.Stream, result.FileName, result.ResultText, false, result.ResultEmbed); } else { await channel.SendMessageAsync("This command has resulted in an attachment that is over 8MB in size and cannot be sent."); } } else { await channel.SendMessageAsync(result.ResultText, embed : result.ResultEmbed); } } } RequestTelemetry request = InternalTools.GetRequestTelemetry(author, channel, command, start, success ? "200" : "500", success); foreach (var pair in result.InsightsData) { request.Properties.Add(pair); } _telemetryClient?.TrackRequest(request); _config.Happiness[author.Id] = (sbyte)((int)(context.Happiness).Clamp(sbyte.MinValue, sbyte.MaxValue)); } catch (BadArgumentsException ex) { Console.WriteLine(ex); await HandleBadRequest(message, author, channel, commandSegments, commandAlias, command, start); } catch (CommandException ex) { Console.WriteLine(ex); await channel.SendMessageAsync(ex.Message); _telemetryClient?.TrackRequest(InternalTools.GetRequestTelemetry(author, channel, command, start, "400", false)); } catch (ArgumentOutOfRangeException ex) { Console.WriteLine(ex); await channel.SendMessageAsync("Hey there! That's gonna cause some issues, no thanks!!"); _telemetryClient?.TrackRequest(InternalTools.GetRequestTelemetry(author, channel, command, start, "400", false)); } catch (Exception ex) { Console.WriteLine(ex); success = false; ManageException(message, author, channel, ex, command); sbyte h = 0; _config.Happiness?.TryGetValue(author.Id, out h); _config.Happiness[author.Id] = (sbyte)((int)h - 1).Clamp(sbyte.MinValue, sbyte.MaxValue); } finally { if (command is IDisposable disp) { disp.Dispose(); } } }
private async Task ProcessMessage(DiscordMessage message, DiscordUser author, DiscordChannel channel) { try { DateTimeOffset startTime = DateTimeOffset.Now; if (!string.IsNullOrWhiteSpace(message?.Content) && !author.IsBot && !author.IsCurrent && !_processedMessageIds.Contains(message.Id)) { if (message.Content.ToLower().StartsWith(_config.Prefix.ToLower())) { LogMessage?.Invoke(this, ($"[{message.Channel.Guild?.Name ?? message.Channel.Name}] Found command prefix, parsing...")); IEnumerable <string> commandSegments = Strings.SplitCommandLine(message.Content.Substring(_config.Prefix.Length)); foreach (IParseExtension extenstion in _parseExtensions) { commandSegments = extenstion.Parse(commandSegments, channel); } if (commandSegments.Any()) { string commandAlias = commandSegments.First().ToLower(); IEnumerable <BaseDiscordCommand> foundCommands = _commands.Where(c => c?.Aliases?.Any(a => a.ToLower() == commandAlias) == true); BaseDiscordCommand commandToRun = foundCommands.FirstOrDefault(); if (commandToRun != null) { if (foundCommands.Count() == 1) { await ExecuteCommandAsync(message, author, channel, commandSegments.Skip(1), commandAlias, commandToRun, startTime); } else if (commandSegments.Count() >= 2) { foundCommands = _assemblyCommands.FirstOrDefault(c => c.Key.Name.ToLowerInvariant() == commandAlias) .Value?.Where(c => c.Aliases.Contains(commandSegments.ElementAt(1).ToLower())); if (foundCommands != null && foundCommands.Count() == 1) { await ExecuteCommandAsync(message, author, channel, commandSegments.Skip(2), commandAlias, foundCommands.First(), startTime); } else { if (commandToRun != null) { await ExecuteCommandAsync(message, author, channel, commandSegments.Skip(1), commandAlias, foundCommands.First(), startTime); } else { LogMessage?.Invoke(this, ($"[{message.Channel.Guild?.Name ?? message.Channel.Name}] Unable to find command with alias \"{commandAlias}\".")); await InternalTools.SendTemporaryMessage(message, author, channel, $"```\r\n{commandAlias}: command not found!\r\n```"); _telemetryClient?.TrackRequest(InternalTools.GetRequestTelemetry(author, channel, null, startTime, "404", false)); } } } else if (commandToRun != null) { await ExecuteCommandAsync(message, author, channel, commandSegments.Skip(1), commandAlias, foundCommands.First(), startTime); } } } } } } catch (Exception ex) { Console.WriteLine(ex); } }