using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Discord; using Discord.Commands; using Discord.Rest; using Discord.WebSocket; using Geekbot.net.Database; using Geekbot.net.Database.Models; using Geekbot.net.Lib.Extensions; using Geekbot.net.Lib.Logger; namespace Geekbot.net.Handlers { public class CommandHandler { private readonly IDiscordClient _client; private readonly IGeekbotLogger _logger; private readonly IServiceProvider _servicesProvider; private readonly CommandService _commands; private readonly RestApplication _applicationInfo; private readonly List _ignoredServers; private readonly DatabaseContext _database; public CommandHandler(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IServiceProvider servicesProvider, CommandService commands, RestApplication applicationInfo) { _database = database; _client = client; _logger = logger; _servicesProvider = servicesProvider; _commands = commands; _applicationInfo = applicationInfo; // Some guilds only want very specific functionally without any of the commands, a quick hack that solves that "short term" // ToDo: create a clean solution for this... _ignoredServers = new List { 228623803201224704, // SwitzerLAN 169844523181015040, // EEvent 248531441548263425, // MYI 110373943822540800 // Discord Bots }; } public Task RunCommand(SocketMessage messageParam) { try { if (!(messageParam is SocketUserMessage message)) return Task.CompletedTask; if (message.Author.IsBot) return Task.CompletedTask; var guildId = ((SocketGuildChannel) message.Channel).Guild.Id; if (IsIgnoredGuild(guildId, message.Author.Id)) return Task.CompletedTask; var lowCaseMsg = message.ToString().ToLower(); if (ShouldHui(lowCaseMsg, guildId)) { message.Channel.SendMessageAsync("hui!!!"); return Task.CompletedTask; } if (ShouldPong(lowCaseMsg, guildId)) { message.Channel.SendMessageAsync("pong"); return Task.CompletedTask; } var argPos = 0; if (!IsCommand(message, ref argPos)) return Task.CompletedTask; ExecuteCommand(message, argPos); } catch (Exception e) { _logger.Error(LogSource.Geekbot, "Failed to Process Message", e); } return Task.CompletedTask; } private void ExecuteCommand(IUserMessage message, int argPos) { var context = new CommandContext(_client, message); _commands.ExecuteAsync(context, argPos, _servicesProvider); _logger.Information(LogSource.Command, context.Message.Content.Split(" ")[0].Replace("!", ""), SimpleConextConverter.ConvertContext(context)); } private bool IsIgnoredGuild(ulong guildId, ulong authorId) { if (!_ignoredServers.Contains(guildId)) return false; return authorId == _applicationInfo.Owner.Id; } private bool IsCommand(IUserMessage message, ref int argPos) { return message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos); } private bool ShouldPong(string lowerCaseMessage, ulong guildId) { if (!lowerCaseMessage.StartsWith("ping ") && !lowerCaseMessage.Equals("ping")) return false; return GetGuildSettings(guildId)?.Ping ?? false; } private bool ShouldHui(string lowerCaseMessage, ulong guildId) { if (!lowerCaseMessage.StartsWith("hui")) return false; return GetGuildSettings(guildId)?.Hui ?? false; } private GuildSettingsModel GetGuildSettings(ulong guildId) { return _database.GuildSettings.FirstOrDefault(guild => guild.GuildId.Equals(guildId.AsLong())); } } }