diff --git a/ToDo.txt b/ToDo.txt index 5dd139e..174fc3a 100644 --- a/ToDo.txt +++ b/ToDo.txt @@ -1,12 +1,13 @@ Have command to alter the command character [NOT POSSIBLE!] !Check all command names -Add wikis for each command on GitHub !Uniform all error messages with Embeds (use Duck code) !Have all messages and commands to disappear after a while (configurable) if not needed to stay -Have a cmd to configure how long messages should stay !Add TryCatch to all code and commands -Add "keep" option to reformat -Extend the reputation by checking "tanks and thank you" in messages and add to mentioned mebers or author of referenced message +!Extend the reputation by checking "tanks and thank you" in messages and add to mentioned mebers or author of referenced message +Have a cmd to configure how long messages should stay +!Add "delete" option to reformat +Add wikis for each command on GitHub +Check if a message to reformat has something after the ```, consider the ``` the end of the block to reformat Errors DelAnsw EmbedRes TryCatch Log@Begin UseSQL MemberTracking | | | | X | | | diff --git a/UPBot Code/Actions/AppreciationTracking.cs b/UPBot Code/Actions/AppreciationTracking.cs index d105d1f..dac45f3 100644 --- a/UPBot Code/Actions/AppreciationTracking.cs +++ b/UPBot Code/Actions/AppreciationTracking.cs @@ -75,21 +75,32 @@ public async Task ShowAppreciationCommand(CommandContext ctx) { internal static Task ThanksAdded(DiscordClient sender, MessageCreateEventArgs args) { try { - if (args.Message.Reference == null && (args.Message.MentionedUsers == null || args.Message.MentionedUsers.Count == 0)) return Task.FromResult(0); - string msg = args.Message.Content.ToLowerInvariant(); if (thanks.IsMatch(msg) || thankyou.IsMatch(msg) || thank2you.IsMatch(msg)) { // Add thanks if (thank4n.IsMatch(msg)) return Task.FromResult(0); if (GetTracking()) return Task.FromResult(0); - IReadOnlyList mentions = args.Message.MentionedUsers; - ulong authorId = args.Message.Author.Id; - ulong refAuthorId = args.Message.Reference != null ? args.Message.Reference.Message.Author.Id : 0; + DiscordMessage theMsg = args.Message; + ulong authorId = theMsg.Author.Id; + if (theMsg.Reference == null && (theMsg.MentionedUsers == null || theMsg.MentionedUsers.Count == 0)) { + // Unrelated thank you, get the previous message and check + IReadOnlyList msgs = theMsg.Channel.GetMessagesBeforeAsync(theMsg.Id, 2).Result; + theMsg = null; + foreach (DiscordMessage m in msgs) + if (m.Author.Id != authorId) { + theMsg = m; + break; + } + if (theMsg == null) return Task.FromResult(0); + } + + IReadOnlyList mentions = theMsg.MentionedUsers; + ulong refAuthorId = theMsg.Reference != null ? theMsg.Reference.Message.Author.Id : 0; if (mentions != null) foreach (DiscordUser u in mentions) if (u.Id != authorId && u.Id != refAuthorId) tracking.AlterThankYou(u.Id); - if (args.Message.Reference != null) - if (args.Message.Reference.Message.Author.Id != authorId) tracking.AlterThankYou(args.Message.Reference.Message.Author.Id); + if (theMsg.Reference != null) + if (theMsg.Reference.Message.Author.Id != authorId) tracking.AlterThankYou(theMsg.Reference.Message.Author.Id); } return Task.FromResult(0); diff --git a/UPBot Code/Actions/MembersTracking.cs b/UPBot Code/Actions/MembersTracking.cs index 0149868..02a3918 100644 --- a/UPBot Code/Actions/MembersTracking.cs +++ b/UPBot Code/Actions/MembersTracking.cs @@ -9,22 +9,22 @@ public class MembersTracking { static DiscordChannel trackChannel = null; public static async Task DiscordMemberRemoved(DiscordClient client, DSharpPlus.EventArgs.GuildMemberRemoveEventArgs args) { - try{ - if (tracking == null) tracking = new Dictionary(); - if (trackChannel == null) trackChannel = args.Guild.GetChannel(831186370445443104ul); + try { + if (tracking == null) tracking = new Dictionary(); + if (trackChannel == null) trackChannel = args.Guild.GetChannel(831186370445443104ul); - if (tracking.ContainsKey(args.Member.Id)) { - tracking.Remove(args.Member.Id); - string msg = "User " + args.Member.DisplayName + " did a kiss and go."; - await trackChannel.SendMessageAsync(msg); - Utils.Log(msg); - } - else { - string msgC = Utils.GetEmojiSnowflakeID(EmojiEnum.KO) + " User " + args.Member.Mention + " left on " + DateTime.Now.ToString("yyyyMMdd HH:mm:ss") + " (" + args.Guild.MemberCount + " memebrs total)"; - string msgL = "- User " + args.Member.DisplayName + " left on " + DateTime.Now.ToString("yyyyMMdd HH:mm:ss") + " (" + args.Guild.MemberCount + " memebrs total)"; - await trackChannel.SendMessageAsync(msgC); - Utils.Log(msgL); - } + if (tracking.ContainsKey(args.Member.Id)) { + tracking.Remove(args.Member.Id); + string msg = "User " + args.Member.DisplayName + " did a kiss and go."; + await trackChannel.SendMessageAsync(msg); + Utils.Log(msg); + } + else { + string msgC = Utils.GetEmojiSnowflakeID(EmojiEnum.KO) + " User " + args.Member.Mention + " (" + args.Member.DisplayName + ") left on " + DateTime.Now.ToString("yyyyMMdd HH:mm:ss") + " (" + args.Guild.MemberCount + " memebrs total)"; + string msgL = "- User " + args.Member.DisplayName + " left on " + DateTime.Now.ToString("yyyyMMdd HH:mm:ss") + " (" + args.Guild.MemberCount + " memebrs total)"; + await trackChannel.SendMessageAsync(msgC); + Utils.Log(msgL); + } } catch (Exception ex) { Utils.Log("Error in DiscordMemberRemoved: " + ex.Message); } diff --git a/UPBot Code/Commands/Refactor.cs b/UPBot Code/Commands/Refactor.cs index 86d9e12..1ff098d 100644 --- a/UPBot Code/Commands/Refactor.cs +++ b/UPBot Code/Commands/Refactor.cs @@ -12,113 +12,187 @@ /// public class Refactor : BaseCommandModule { + enum Action { + Analyze, + Replace, + Keep + } + + enum Langs { + NONE, cs, js, cpp, java, python + } + + /* + /refactor + /refactor lng + /refactor lng replace + /refactor keep lng + /refactor best + /refactor keep + + /refactor + /refactor lng + /refactor lng replace + /refactor keep lng + /refactor best + /refactor keep + + normal users can reformat their own posts + admins can reformat messages from other users + + */ + + [Command("checklanguage")] [Description("Checks what language is in the post you replied to, or the last post of a specified user or just the last post.")] public async Task CheckLanguage(CommandContext ctx) { // Refactors the previous post, if it is code - await RefactorCode(ctx, null, "best"); + await RefactorCode(ctx, null, Action.Analyze, Langs.NONE); } [Command("checklanguage")] [Description("Checks what language is in the post you replied to, or the last post of a specified user or just the last post.")] - public async Task CheckLanguage(CommandContext ctx, [Description("The user the posted the message to check")] DiscordMember member) { // Refactors the previous post, if it is code - await RefactorCode(ctx, member, "best"); + public async Task CheckLanguage(CommandContext ctx, [Description("The user that posted the message to check")] DiscordMember member) { // Refactors the previous post, if it is code + await RefactorCode(ctx, member, Action.Analyze, Langs.NONE); } [Command("reformat")] [Description("Replace a specified post with a reformatted code block using the specified language or the best language")] - [RequirePermissions(Permissions.ManageMessages)] // Restrict this command to users/roles who have the "Manage Messages" permission - [RequireRoles(RoleCheckMode.Any, "Helper", "Mod", "Owner")] // Restrict this command to "Helper", "Mod" and "Owner" roles only public async Task RefactorCommand(CommandContext ctx) { // Refactors the previous post, if it is code - await RefactorCode(ctx, null, null); + await RefactorCode(ctx, null, Action.Keep, Langs.NONE); + } + + [Command("reformat")] + [Description("Replace the last post of the specified user or the post you replied to with a formatted code block")] + public async Task ReformatCommand(CommandContext ctx, [Description("Analyze the language with **Best** or **Analyze**, use **Replace** to replace the refactored post (only your own posts or if you are an admin), specify a **language** if you want to force one.")] string what) { // Refactors the previous post, if it is code + if (IsBest(what)) await RefactorCode(ctx, null, Action.Analyze, Langs.NONE); + else if (IsReplace(what)) await RefactorCode(ctx, null, Action.Replace, Langs.NONE); + else await RefactorCode(ctx, null, Action.Keep, NormalizeLanguage(what)); } [Command("reformat")] [Description("Replace the last post of the specified user or the post you replied to with a formatted code block")] - [RequirePermissions(Permissions.ManageMessages)] // Restrict this command to users/roles who have the "Manage Messages" permission - [RequireRoles(RoleCheckMode.Any, "Helper", "Mod", "Owner")] // Restrict this command to "Helper", "Mod" and "Owner" roles only - public async Task ReformatCommand(CommandContext ctx, [Description("Force the Language to use. Use **Best** or **Analyze** to find the best language.")] string language) { // Refactors the previous post, if it is code - await RefactorCode(ctx, null, language); + public async Task ReformatCommand(CommandContext ctx, [Description("Use **Replace** to replace the refactored post (only your own posts or if you are an admin), or specify a **language** if you want to force one.")] string cmd1, [Description("Use **Replace** to replace the refactored post (only your own posts or if you are an admin), or sa **language** if you want to force one.")] string cmd2) { // Refactors the previous post, if it is code + if (IsBest(cmd1) || IsBest(cmd2)) await RefactorCode(ctx, null, Action.Analyze, Langs.NONE); + else if (IsReplace(cmd1)) await RefactorCode(ctx, null, Action.Replace, NormalizeLanguage(cmd2)); + else if (IsReplace(cmd2)) await RefactorCode(ctx, null, Action.Replace, NormalizeLanguage(cmd1)); + else { + Langs l = NormalizeLanguage(cmd1); + if (l == Langs.NONE) l = NormalizeLanguage(cmd2); + await RefactorCode(ctx, null, Action.Keep, l); + } } [Command("reformat")] - [RequirePermissions(Permissions.ManageMessages)] // Restrict this command to users/roles who have the "Manage Messages" permission - [RequireRoles(RoleCheckMode.Any, "Helper", "Mod", "Owner")] // Restrict this command to "Helper", "Mod" and "Owner" roles only - public async Task ReformatCommand(CommandContext ctx, [Description("The user the posted the message to refactor")] DiscordMember member) { // Refactor the last post of the specified user in the channel - await RefactorCode(ctx, member, null); + public async Task ReformatCommand(CommandContext ctx, [Description("The user that posted the message to refactor")] DiscordMember member) { // Refactor the last post of the specified user in the channel + await RefactorCode(ctx, member, Action.Keep, Langs.NONE); } [Command("reformat")] - [RequirePermissions(Permissions.ManageMessages)] // Restrict this command to users/roles who have the "Manage Messages" permission - [RequireRoles(RoleCheckMode.Any, "Helper", "Mod", "Owner")] // Restrict this command to "Helper", "Mod" and "Owner" roles only - public async Task RefacReformatCommandtorCommand(CommandContext ctx, [Description("The user the posted the message to refactor")] DiscordMember member, [Description("Force the Language to use. Use 'best' or 'Analyze' to find the best language.")] string language) { // Refactor the last post of the specified user in the channel - await RefactorCode(ctx, member, language); + public async Task RefacReformatCommandtorCommand(CommandContext ctx, [Description("The user that posted the message to refactor")] DiscordMember member, [Description("Analyze the language with **Best** or **Analyze**, use **Replace** to replace the refactored post, specify a **language** if you want to force one.")] string what) { // Refactor the last post of the specified user in the channel + if (IsBest(what)) await RefactorCode(ctx, member, Action.Analyze, Langs.NONE); + else if (IsReplace(what)) await RefactorCode(ctx, member, Action.Replace, Langs.NONE); + else await RefactorCode(ctx, member, Action.Keep, NormalizeLanguage(what)); + } + + [Command("reformat")] + public async Task RefacReformatCommandtorCommand(CommandContext ctx, [Description("The user that posted the message to refactor")] DiscordMember member, [Description("Use **Replace** to replace the refactored post (only your own posts or if you are an admin), or specify a **language** if you want to force one.")] string cmd1, [Description("Use **Replace** to replace the refactored post (only your own posts or if you are an admin), or sa **language** if you want to force one.")] string cmd2) { // Refactors the previous post, if it is code + if (IsBest(cmd1) || IsBest(cmd2)) await RefactorCode(ctx, member, Action.Analyze, Langs.NONE); + else if (IsReplace(cmd1)) await RefactorCode(ctx, member, Action.Replace, NormalizeLanguage(cmd2)); + else if (IsReplace(cmd2)) await RefactorCode(ctx, member, Action.Replace, NormalizeLanguage(cmd1)); + else { + Langs l = NormalizeLanguage(cmd1); + if (l == Langs.NONE) l = NormalizeLanguage(cmd2); + await RefactorCode(ctx, member, Action.Keep, l); + } } - private async Task> RefactorCode(CommandContext ctx, DiscordMember m, string language) { + private async Task> RefactorCode(CommandContext ctx, DiscordMember m, Action action, Langs lang) { Utils.LogUserCommand(ctx); + try { - DiscordChannel c = ctx.Channel; + // Find the message DiscordMessage toRefactor = null; + Langs msgLang = Langs.NONE; if (ctx.Message.Reference != null) toRefactor = ctx.Message.Reference.Message; - else { - IReadOnlyList msgs = await c.GetMessagesAsync(50); - if (m == null) toRefactor = msgs[1]; - else { - for (int i = 1; i < msgs.Count; i++) { - if (msgs[i].Author.Id.Equals(m.Id)) { - toRefactor = msgs[i]; - break; - } + else if (m != null) { // Get last post of the specified member + IReadOnlyList msgs = await ctx.Channel.GetMessagesAsync(50); + for (int i = 1; i < msgs.Count; i++) { + if (msgs[i].Author.Id.Equals(m.Id)) { + toRefactor = msgs[i]; + break; + } + } + } + else { // Get last post that looks like code + IReadOnlyList msgs = await ctx.Channel.GetMessagesAsync(50); + for (int i = 1; i < msgs.Count; i++) { + string content = msgs[i].Content; + msgLang = GetBestMatch(content); + if (msgLang != Langs.NONE) { + toRefactor = msgs[i]; + break; } } - if (toRefactor == null) return ctx.RespondAsync("Nothing to refactor found"); } - // Is the message some code? + if (toRefactor == null) return ctx.RespondAsync("Nothing to refactor found"); + // FIXME If we are not an admin, and the message is not from ourselves, do not accept the replace option. + if (action == Action.Replace && !Utils.IsAdmin(ctx.Member) && toRefactor.Author.Id != ctx.Member.Id) action = Action.Keep; + + // Is the message some code, or at least somethign we recognize? string code = toRefactor.Content; - int weightCs = 0, weightCp = 0, weightJv = 0, weightJs = 0, weightPy = 0; - foreach (LangKWord k in keywords) { - if (k.regexp.IsMatch(code)) { - weightCs += k.wCs; - weightCp += k.wCp; - weightJv += k.wJv; - weightJs += k.wJs; - weightPy += k.wPy; + if (msgLang==Langs.NONE) + msgLang = GetBestMatch(code); + + if (action == Action.Analyze) { + int weightCs = 0, weightCp = 0, weightJv = 0, weightJs = 0, weightPy = 0; + foreach (LangKWord k in keywords) { + if (k.regexp.IsMatch(code)) { + weightCs += k.wCs; + weightCp += k.wCp; + weightJv += k.wJv; + weightJs += k.wJs; + weightPy += k.wPy; + } + } + string guessed = "no one"; + switch (msgLang) { + case Langs.cs: guessed = "<:csharp:831465428214743060> C#"; break; + case Langs.js: guessed = "<:Javascript:876103767068647435> Javascript"; break; + case Langs.cpp: guessed = "<:cpp:831465408874676273> C++"; break; + case Langs.java: guessed = "<:java:875852276017815634> Java"; break; + case Langs.python: guessed = "<:python:831465381016895500> Python"; break; } + return ctx.RespondAsync("Best guess for the language is: " + guessed + "\nC# = " + weightCs + " C++ = " + weightCp + " Java = " + weightJv + " Javascript = " + weightJs + " Python = " + weightPy); } - string guessed = "no one"; - string best = ""; - EmojiEnum langEmoji = EmojiEnum.None; - int w = 0; - if (weightCs > w) { guessed = "<:csharp:831465428214743060> C#"; w = weightCs; best = "cs"; langEmoji = EmojiEnum.CSharp; } - if (weightCp > w) { guessed = "<:cpp:831465408874676273> C++"; w = weightCp; best = "cpp"; langEmoji = EmojiEnum.Cpp; } - if (weightJs > w) { guessed = "<:Javascript:876103767068647435> Javascript"; w = weightJs; best = "js"; langEmoji = EmojiEnum.Javascript; } - if (weightJv > w) { guessed = "<:java:875852276017815634> Java"; w = weightJv; best = "java"; langEmoji = EmojiEnum.Java; } - if (weightPy > w) { guessed = "<:python:831465381016895500> Python"; w = weightPy; best = "python"; langEmoji = EmojiEnum.Python; } - if (w == 0 && language == null) return ctx.RespondAsync("Nothing to reformat"); - - language = NormalizeLanguage(language, best); - if (language == null) - return ctx.RespondAsync("Best guess for the language is: " + guessed + "\nC# = " + weightCs + " C++ = " + weightCp + " Java = " + weightJv + " Javascript = " + weightJs + " Python = " + weightPy); // Remove the ``` at begin and end, if any. And the code name after initial ``` - bool deleteOrig = true; + bool deleteOrig = action == Action.Replace; Match codeMatch = codeBlock.Match(code); if (codeMatch.Success) { - code = codeMatch.Groups[5].Value; - deleteOrig = string.IsNullOrWhiteSpace(codeMatch.Groups[1].Value); + if (codeMatch.Groups[3].Value.IndexOf(';') != -1) + code = codeMatch.Groups[3].Value.Substring(3) + codeMatch.Groups[6].Value; + else + code = codeMatch.Groups[6].Value; } code = code.Trim(' ', '\t', '\r', '\n'); code = emptyLines.Replace(code, "\n"); - if (langEmoji == EmojiEnum.CSharp || langEmoji == EmojiEnum.Cpp || langEmoji == EmojiEnum.Java || langEmoji == EmojiEnum.Javascript) code = FixIndentation(code); + if (lang != Langs.NONE) msgLang = lang; + EmojiEnum langEmoji = EmojiEnum.None; + string lmd = ""; + switch (msgLang) { + case Langs.cs: langEmoji = EmojiEnum.CSharp; lmd = "cs"; break; + case Langs.js: langEmoji = EmojiEnum.Javascript; lmd = "js"; break; + case Langs.cpp: langEmoji = EmojiEnum.Cpp; lmd = "cpp"; break; + case Langs.java: langEmoji = EmojiEnum.Java; lmd = "java"; break; + case Langs.python: langEmoji = EmojiEnum.Python; lmd = "python"; break; + } - code = "Reformatted " + toRefactor.Author.Mention + " code\n" + "```" + language + "\n" + code + "\n```"; + if ( langEmoji != EmojiEnum.None && langEmoji != EmojiEnum.Python) code = FixIndentation(code); - if (guessed == "no one" && language != null) { - langEmoji = GetLanguageEmoji(language); - } + code = "Reformatted " + toRefactor.Author.Mention + " code\n" + "```" + lmd + "\n" + code + "\n```"; DiscordMessage replacement = await ctx.Channel.SendMessageAsync(code); DiscordEmoji autoRefactored = Utils.GetEmoji(EmojiEnum.AutoRefactored); @@ -201,50 +275,74 @@ private string FixIndentation(string code) { return res; } - private string NormalizeLanguage(string language, string best) { - if (language == null) return best; - language = language.ToLowerInvariant(); - if (language == "best") return null; - if (language == "what") return null; - if (language == "whatis") return null; - if (language == "analyze") return null; - if (language == "analysis") return null; - if (language == "c#") return "cs"; - if (language == "cs") return "cs"; - if (language == "csharp") return "cs"; - if (language == "cpp") return "cpp"; - if (language == "c++") return "cpp"; - if (language == "java") return "java"; - if (language == "javascript") return "js"; - if (language == "jscript") return "js"; - if (language == "js") return "js"; - if (language == "json") return "js"; - if (language == "typescript") return "js"; - if (language == "phyton") return "python"; - if (language == "python") return "python"; - if (language == "py") return "python"; - return ""; + private Langs GetBestMatch(string code) { + int weightCs = 0, weightCp = 0, weightJv = 0, weightJs = 0, weightPy = 0; + foreach (LangKWord k in keywords) { + if (k.regexp.IsMatch(code)) { + weightCs += k.wCs; + weightCp += k.wCp; + weightJv += k.wJv; + weightJs += k.wJs; + weightPy += k.wPy; + } + } + int w = 0; + Langs res = Langs.NONE; + if (weightCs > w) { w = weightCs; res = Langs.cs; } + if (weightCp > w) { w = weightCp; res = Langs.cpp; } + if (weightJs > w) { w = weightJs; res = Langs.js; } + if (weightJv > w) { w = weightJv; res = Langs.java; } + if (weightPy > w) { w = weightPy; res = Langs.python; } + return res; } - private EmojiEnum GetLanguageEmoji(string language) { + + private bool IsBest(string what) { + if (what == null) return false; + what = what.ToLowerInvariant(); + if (what == "best") return true; + if (what == "what") return true; + if (what == "whatis") return true; + if (what == "analyze") return true; + if (what == "analysis") return true; + return false; + } + + private bool IsReplace(string what) { + if (what == null) return false; + what = what.ToLowerInvariant(); + if (what == "rep") return true; + if (what == "repl") return true; + if (what == "replace") return true; + if (what == "remove") return true; + if (what == "change") return true; + if (what == "substitute") return true; + if (what == "destroy") return true; + if (what == "delete") return true; + return false; + } + + private Langs NormalizeLanguage(string language) { + if (language == null) return Langs.NONE; language = language.ToLowerInvariant(); - if (language == "c#") return EmojiEnum.CSharp; - if (language == "cs") return EmojiEnum.CSharp; - if (language == "csharp") return EmojiEnum.CSharp; - if (language == "cpp") return EmojiEnum.Cpp; - if (language == "c++") return EmojiEnum.Cpp; - if (language == "java") return EmojiEnum.Java; - if (language == "javascript") return EmojiEnum.Javascript; - if (language == "jscript") return EmojiEnum.Javascript; - if (language == "js") return EmojiEnum.Javascript; - if (language == "typescript") return EmojiEnum.Javascript; - if (language == "json") return EmojiEnum.Javascript; - if (language == "phyton") return EmojiEnum.Python; - if (language == "python") return EmojiEnum.Python; - if (language == "py") return EmojiEnum.Python; - return EmojiEnum.None; + if (language == "c#") return Langs.cs; + if (language == "cs") return Langs.cs; + if (language == "csharp") return Langs.cs; + if (language == "cpp") return Langs.cpp; + if (language == "c++") return Langs.cpp; + if (language == "c") return Langs.cpp; + if (language == "java") return Langs.java; + if (language == "javascript") return Langs.js; + if (language == "jscript") return Langs.js; + if (language == "js") return Langs.js; + if (language == "json") return Langs.js; + if (language == "typescript") return Langs.js; + if (language == "phyton") return Langs.python; + if (language == "python") return Langs.python; + if (language == "py") return Langs.python; + return Langs.NONE; } - readonly Regex codeBlock = new Regex("(.*)(\\n|\\r|\\r\\n)?(```[a-z]*(\\n|\\r|\\r\\n))(.*)(```[a-z]*(\\n|\\r|\\r\\n)?)", RegexOptions.Singleline, TimeSpan.FromSeconds(1)); + readonly Regex codeBlock = new Regex("(.*)(\\n|\\r|\\r\\n)?(```[a-z]*(\\n|\\r|\\r\\n)|```[^;]*;(\\n|\\r|\\r\\n))(.*)(```[a-z]*(\\n|\\r|\\r\\n)?)", RegexOptions.Singleline, TimeSpan.FromSeconds(1)); readonly Regex emptyLines = new Regex("(\\r?\\n\\s*){1,}(\\r?\\n)", RegexOptions.Singleline, TimeSpan.FromSeconds(1)); readonly LangKWord[] keywords = { diff --git a/UPBot Code/Commands/WhoIs.cs b/UPBot Code/Commands/WhoIs.cs index 4e238e2..ec72c59 100644 --- a/UPBot Code/Commands/WhoIs.cs +++ b/UPBot Code/Commands/WhoIs.cs @@ -76,7 +76,7 @@ private Task GenerateWhoIs(CommandContext ctx, DiscordMember m) { } if (num == 1) embed.AddField("Role", roles, false); - else + else if (num != 0) embed.AddField(num + " Roles", roles, false); string perms = ""; // Not all permissions are shown diff --git a/UPBot Code/DataClasses/CustomCommand.cs b/UPBot Code/DataClasses/CustomCommand.cs index 15f7406..edee929 100644 --- a/UPBot Code/DataClasses/CustomCommand.cs +++ b/UPBot Code/DataClasses/CustomCommand.cs @@ -45,7 +45,11 @@ internal void EditCommand(string[] newNames) { } internal bool Contains(string name) { - return (Name.Equals(name) || Alias0.Equals(name) || Alias1.Equals(name) || Alias2.Equals(name) || Alias3.Equals(name)); + return ((Name != null && Name.Equals(name)) || + (Alias0 != null && Alias0.Equals(name)) || + (Alias1 != null && Alias1.Equals(name)) || + (Alias2 != null && Alias2.Equals(name)) || + (Alias3 != null && Alias3.Equals(name))); } internal string GetNames() { diff --git a/UPBot Code/Database.cs b/UPBot Code/Database.cs index 7431387..75ea0ae 100644 --- a/UPBot Code/Database.cs +++ b/UPBot Code/Database.cs @@ -167,14 +167,8 @@ public static void AddTable() { update += field.Name + "=@p" + field.Name; } ed.insert = insert + insertpost + ");"; - ed.update = update; + ed.update = update + " WHERE " + theKey + "=@param1"; entities.Add(t, ed); - - /* - * FIXME add indexes if we will need them - */ - - } public static int Count() { @@ -195,13 +189,15 @@ public static void Add(T val) { EntityDef ed = entities[t]; // Get the values with this key from the db SQLiteCommand cmd = new SQLiteCommand(ed.count, connection); - cmd.Parameters.Add(new SQLiteParameter("@param1", (val as Entity).GetKey().GetValue(val))); + object key = (val as Entity).GetKey().GetValue(val); + cmd.Parameters.Add(new SQLiteParameter("@param1", key)); // Do we have our value? if (Convert.ToInt32(cmd.ExecuteScalar()) > 0) { // Yes -> Update SQLiteCommand update = new SQLiteCommand(ed.update, connection); foreach (FieldInfo field in t.GetFields()) { update.Parameters.Add(new SQLiteParameter("@p" + field.Name, field.GetValue(val))); } + update.Parameters.Add(new SQLiteParameter("@param1", key)); update.ExecuteNonQuery(); } else { // No - Insert @@ -226,11 +222,11 @@ public static void Delete(T val) { Utils.Log("Error in Deleting data for " + val.GetType() + ": " + ex.Message); } } - public static void DeleteByKey(object key) { + public static void DeleteByKey(object keyvalue) { try { EntityDef ed = entities[typeof(T)]; SQLiteCommand cmd = new SQLiteCommand(ed.delete, connection); - cmd.Parameters.Add(new SQLiteParameter("@param1", key)); + cmd.Parameters.Add(new SQLiteParameter("@param1", keyvalue)); cmd.ExecuteNonQuery(); } catch (Exception ex) { Utils.Log("Error in Deleting data for " + typeof(T) + ": " + ex.Message); @@ -248,6 +244,7 @@ public static T Get(object keyvalue) { T res = (T)Activator.CreateInstance(t); int num = 0; foreach (FieldInfo field in t.GetFields()) { + if (reader.IsDBNull(num)) continue; FieldType ft = ed.fields[field.Name]; switch (ft) { case FieldType.Bool: field.SetValue(res, reader.GetByte(num) != 0); break; @@ -286,6 +283,7 @@ public static List GetAll() { int num = 0; foreach (FieldInfo field in t.GetFields()) { FieldType ft = ed.fields[field.Name]; + if (reader.IsDBNull(num)) continue; switch (ft) { case FieldType.Bool: field.SetValue(val, reader.GetByte(num) != 0); break; case FieldType.Byte: field.SetValue(val, reader.GetByte(num)); break; @@ -308,7 +306,7 @@ public static List GetAll() { } return res; } catch (Exception ex) { - Utils.Log("Error in Reading data for " + typeof(T) + ": " + ex.Message); + Utils.Log(" " + typeof(T) + ": " + ex.Message); } return null; } diff --git a/UPBot Code/Utils.cs b/UPBot Code/Utils.cs index 89ae0ba..42c9439 100644 --- a/UPBot Code/Utils.cs +++ b/UPBot Code/Utils.cs @@ -31,7 +31,7 @@ public static class Utils private static DiscordGuild guild; public static string GetVersion() { - return vmajor + "." + vminor + "." + vbuild + " dev - 2021/08/19"; + return vmajor + "." + vminor + "." + vbuild + " - 2021/08/26"; } /// @@ -328,6 +328,13 @@ static void DelayAfterAWhile(DiscordMessage msg, int delay) { } catch (Exception) { } } + public static bool IsAdmin(DiscordMember m) { + if (m.Permissions.HasFlag(Permissions.Administrator)) return true; + if (m.Permissions.HasFlag(Permissions.ManageMessages)) return true; + foreach (DiscordRole r in m.Roles) + if (r.Id == 830901562960117780ul /* Owner */ || r.Id == 830901743624650783ul /* Mod */ || r.Id == 831050318171078718ul /* Helper */) return true; + return false; + } }