From d0959aecdc8631d88a6b8505ec050a7f3a9546cb Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Mon, 30 Jul 2018 22:44:45 +0200 Subject: [PATCH] System for custom tags --- DeukBot4/Database/DatabaseInitializer.cs | 9 + .../CommandHandler/Commands/TagCommands.cs | 48 ++++ .../CommandHandler/TagStorage.cs | 218 ++++++++++++++++++ DeukBot4/Program.cs | 8 +- 4 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 DeukBot4/MessageHandlers/CommandHandler/Commands/TagCommands.cs create mode 100644 DeukBot4/MessageHandlers/CommandHandler/TagStorage.cs diff --git a/DeukBot4/Database/DatabaseInitializer.cs b/DeukBot4/Database/DatabaseInitializer.cs index 546fb1b..482cb3d 100644 --- a/DeukBot4/Database/DatabaseInitializer.cs +++ b/DeukBot4/Database/DatabaseInitializer.cs @@ -18,12 +18,21 @@ namespace DeukBot4.Database "PRIMARY KEY(server_id, role_id)" + ")"; cmd.ExecuteNonQuery(); + cmd.CommandText = "CREATE TABLE IF NOT EXISTS server_settings (" + "server_id bigint NOT NULL," + "muted_role bigint NOT NULL," + "PRIMARY KEY(server_id)" + ")"; cmd.ExecuteNonQuery(); + + cmd.CommandText = "CREATE TABLE IF NOT EXISTS tags (" + + "server_id bigint NOT NULL," + + "key varchar(25) NOT NULL," + + "value varchar(255) NOT NULL," + + "PRIMARY KEY(key)" + + ")"; + cmd.ExecuteNonQuery(); } } } diff --git a/DeukBot4/MessageHandlers/CommandHandler/Commands/TagCommands.cs b/DeukBot4/MessageHandlers/CommandHandler/Commands/TagCommands.cs new file mode 100644 index 0000000..cfdbbf7 --- /dev/null +++ b/DeukBot4/MessageHandlers/CommandHandler/Commands/TagCommands.cs @@ -0,0 +1,48 @@ +using System.Threading.Tasks; +using DeukBot4.MessageHandlers.CommandHandler.RequestStructure; +using DeukBot4.MessageHandlers.Permissions; + +namespace DeukBot4.MessageHandlers.CommandHandler +{ + public class TagCommands : CommandContainerBase + { + public override string Name => "Tags"; + + [Command("createtag", PermissionLevel.Helper)] + [CommandParameters(ParameterMatcher.ParameterType.Word, ParameterMatcher.ParameterType.Remainder)] + [CommandHelp("Creates a tag", "Creates a tag\nRequires at least two words")] + [BlockUsageInPm, RequireParameterMatch] + public async Task CreateTag(CommandRequest request) + { + TagStorage.AddTag(request); + } + + [Command("removetag", PermissionLevel.Helper)] + [CommandParameters(ParameterMatcher.ParameterType.Word)] + [CommandHelp("Removes a tag", "Removes a a tag\nRequires the key to be given")] + [BlockUsageInPm, RequireParameterMatch] + public async Task RemoveTag(CommandRequest request) + { + TagStorage.RemoveTag(request); + } + + [Command("tag", PermissionLevel.Everyone)] + [CommandParameters(ParameterMatcher.ParameterType.Word)] + [CommandHelp("Gets a tag", "Gets a tag earlier set by a moderator.")] + + [BlockUsageInPm, RequireParameterMatch] + public async Task GetTag(CommandRequest request) + { + TagStorage.GetTag(request); + } + + [Command("tags", PermissionLevel.Everyone)] + [CommandHelp("List tags in the server", "List tags in the server set by a moderator.")] + [BlockUsageInPm] + public async Task GetTags(CommandRequest request) + { + TagStorage.GetTags(request); + } + + } +} \ No newline at end of file diff --git a/DeukBot4/MessageHandlers/CommandHandler/TagStorage.cs b/DeukBot4/MessageHandlers/CommandHandler/TagStorage.cs new file mode 100644 index 0000000..4e8b0f9 --- /dev/null +++ b/DeukBot4/MessageHandlers/CommandHandler/TagStorage.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using DeukBot4.Database; +using DeukBot4.MessageHandlers.CommandHandler.RequestStructure; +using DeukBot4.Utilities; +using Discord; +using Npgsql; + +namespace DeukBot4.MessageHandlers.CommandHandler +{ + public static class TagStorage + { + public class ServerTags + { + private readonly Dictionary Tags = new Dictionary(); + private ulong ServerId { get; set; } + + public ServerTags(ulong serverId) + { + ServerId = serverId; + } + + public ServerTags(ulong serverId, Dictionary tags) + { + Tags = tags; + } + + private static string CleanKey(string key) + { + return key.ToLowerInvariant(); + } + + public (bool success, string result) AddTag(string key, string value) + { + var parsedTag = CleanKey(key); + if (Tags.ContainsKey(parsedTag)) + { + return (false, "A tag with that name already exists"); + } + Tags.Add(parsedTag, value); + using (var db = new DatabaseConnection()) + { + using (var command = new NpgsqlCommand()) + { + command.Connection = db; + command.CommandText = "INSERT INTO tags (server_id, key, value) VALUES (@id, @key, @value)"; + command.Parameters.AddWithValue("@id", ServerId.ToLong()); + command.Parameters.AddWithValue("@key", parsedTag); + command.Parameters.AddWithValue("@value", value); + command.ExecuteNonQuery(); + } + } + return (true, ""); + } + + public (bool success, string result) RemoveTag(string key) + { + var parsedTag = CleanKey(key); + if (!Tags.ContainsKey(parsedTag)) + { + return (false, "No tag with that name exists"); + } + Tags.Remove(parsedTag); + using (var db = new DatabaseConnection()) + { + using (var command = new NpgsqlCommand()) + { + command.Connection = db; + command.CommandText = "DELETE FROM tags WHERE server_id = @id AND key = @key"; + command.Parameters.AddWithValue("@id", ServerId.ToLong()); + command.Parameters.AddWithValue("@key", parsedTag); + var res = command.ExecuteNonQuery(); + } + } + + return (true, ""); + } + + public string GetTag(string key) + { + var parsedTag = CleanKey(key); + if (!Tags.TryGetValue(parsedTag, out var value)) + { + return "No tag by that name exists"; + } + + return value; + } + + public List TagList() + { + return Tags.Keys.OrderBy(x => x).ToList(); + } + } + + private static readonly Dictionary ServerCache = new Dictionary(); + + public static void BuildTags() + { + using (var conn = new DatabaseConnection()) + { + using (var command = new NpgsqlCommand()) + { + command.Connection = conn; + command.CommandText = "SELECT server_id, key, value FROM tags"; + var reader = command.ExecuteReader(); + var res = new Dictionary>(); + while (reader.Read()) + { + var id = reader.GetInt64(0).ToUlong(); + var key = reader.GetString(1); + var value = reader.GetString(2); + if (!res.TryGetValue(id, out var dic)) + { + dic = new Dictionary(); + res.Add(id, dic); + } + dic.Add(key, value); + } + + foreach (var dic in res) + { + ServerCache.Add(dic.Key, new ServerTags(dic.Key, dic.Value)); + } + } + } + } + + public static async Task AddTag(CommandRequest cmd) + { + var channel = cmd.OriginalMessage.Channel as IGuildChannel; + if (channel == null) + return; + var serverId = channel.GuildId; + if (!ServerCache.TryGetValue(serverId, out var serverTags)) + { + serverTags = new ServerTags(serverId); + ServerCache.Add(serverId, serverTags); + } + + var key = cmd.Parameters[0].AsString(); + var value = cmd.Parameters[1].AsString(); + var result = serverTags.AddTag(key, value); + if (!result.success) + { + cmd.SendMessageAsync("Something went wrong: " + result.result); + } + else + { + cmd.SendMessageAsync("Success! Added tag with key: " + key); + } + } + + public static async Task RemoveTag(CommandRequest cmd) + { + var channel = cmd.OriginalMessage.Channel as IGuildChannel; + if (channel == null) + return; + var serverId = channel.GuildId; + if (!ServerCache.TryGetValue(serverId, out var serverTags)) + { + serverTags = new ServerTags(serverId); + ServerCache.Add(serverId, serverTags); + } + + var key = cmd.Parameters[0].AsString(); + var result = serverTags.RemoveTag(key); + if (!result.success) + { + cmd.SendMessageAsync("Something went wrong: " + result.result); + } + else + { + cmd.SendMessageAsync("Success! Removed tag with key: " + key); + } + + } + + public static async Task GetTag(CommandRequest cmd) + { + var channel = cmd.OriginalMessage.Channel as IGuildChannel; + if (channel == null) + return; + var serverId = channel.GuildId; + if (!ServerCache.TryGetValue(serverId, out var serverTags)) + { + serverTags = new ServerTags(serverId); + ServerCache.Add(serverId, serverTags); + } + + var key = cmd.Parameters[0].AsString(); + cmd.SendMessageAsync(serverTags.GetTag(key)); + } + + public static async Task GetTags(CommandRequest cmd) + { + var channel = cmd.OriginalMessage.Channel as IGuildChannel; + if (channel == null) + return; + var serverId = channel.GuildId; + if (!ServerCache.TryGetValue(serverId, out var serverTags)) + { + return; + } + var tags = serverTags.TagList(); + var eb = new EmbedBuilder + { + Title = "This Server Has The Following Tags:", + Description = tags.Join("\n"), + Color = Color.Gold, + }; + cmd.OriginalMessage.Channel.SendMessageAsync("", embed: eb.Build()); + } + + } +} \ No newline at end of file diff --git a/DeukBot4/Program.cs b/DeukBot4/Program.cs index 4f471f6..af3be50 100644 --- a/DeukBot4/Program.cs +++ b/DeukBot4/Program.cs @@ -28,6 +28,7 @@ namespace DeukBot4 DatabaseInitializer.Initialize(); ServerSettingHandler.OnBotStartUp(); + TagStorage.BuildTags(); CommandHandler.Build(); ImageBackupHandler.SetBackupChannels(Settings.BackupChannels); ImageBackupHandler.Settings = Settings.NextcloudSettings; @@ -48,11 +49,16 @@ namespace DeukBot4 private static async Task OnReady() { - await Client.CurrentUser.ModifyAsync(properties => + Client.CurrentUser.ModifyAsync(properties => { properties.Username = Settings.Username; properties.Avatar = new Image("avatar.png"); }); + Console.WriteLine(("Joined Guilds: ")); + foreach (var clientGuild in Client.Guilds) + { + Console.WriteLine($"- {clientGuild.Id}: {clientGuild.Name}"); + } BotId = Client.CurrentUser.Id; } }