rmsoft1 icon

CoreModule.cs

rmsoft1 | PRO | 04/29/18 11:03:29 PM UTC | 0 ⭐ | 210 👁️ | Never ⏰ | []
C# |

27.46 KB

|

None

|

0 👍

/

0 👎

using Discord;
using Discord.Commands;
using Discord.WebSocket;
using RMSoftware.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using System.Net.Http;
namespace RMSoftware.ModularBot
{
    
    public class CoreModule : ModuleBase
    {
 
         DiscordSocketClient Client { get; set; }
 
         CommandService cmdsvr { get; set; }
        public CoreModule(DiscordSocketClient client, CommandService cmdservice)
        {
            Client = client;
            cmdsvr = cmdservice;
        }
        [Command("about"), Summary("Display information about the bot")]
        public async Task ShowAbout()
        {
            EmbedBuilder builder = new EmbedBuilder();
            builder.Title = "About";
            builder.WithAuthor(Context.Client.CurrentUser);
            builder.Color = Color.Blue;
            builder.Description = "A Multi-purpose, multi-module bot designed for discord. Tailor it for your specific server, create your own modules and plug-ins. Includes a core module for custom text-based commands & EXEC functionality";
            builder.AddField("Copyright", "Copyright © 2017 RMSoftware Development");
            builder.AddField("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(3));
            builder.WithFooter("RMSoftware.ModularBot, created by rmsoft1");
            await Retry.Do(async () => await Context.Channel.SendMessageAsync("", false, builder.Build()), TimeSpan.FromMilliseconds(140));
        }
 
        [Command("uptime"),Summary("Displays how long the bot has been connected")]
        public async Task ShowUptime([Remainder]string args=null)
        {
            var delta = DateTime.Now - Program.StartTime;
 
            string format = string.Format("I've been alive and well for **{0}** hours, **{1}** minutes, and **{2}** seconds!", Math.Floor(delta.TotalHours).ToString("n0"), delta.Minutes, delta.Seconds);
            await Retry.Do(async () => await Context.Channel.SendMessageAsync(format + " " + args), TimeSpan.FromMilliseconds(140));
 
        }
 
        [Command("status"), Summary("Set the bot's 'Playing' status"), Remarks("[CMDMgmt]")]
        public async Task setStatus([Remainder]string args = null)
        {
           await Client.SetGameAsync(args);
        }
 
        [Command("streamstatus"), Summary("Set the bot's status to streaming on twitch, with twitch url and custom text."), Remarks("[CMDMgmt]")]
        public async Task setStatus(string streamurl, [Remainder]string args)
        {
            
            await Client.SetGameAsync(args, streamurl, StreamType.Twitch);
        }
 
        [Command("STOPBOT",RunMode=RunMode.Async), Summary("Shutdown the bot"), RequireOwner, Remarks("[CMDMgmt]")]
        public async Task StopBot()
        {
            if (Program.LOG_ONLY_MODE)
            {
                await Context.Channel.SendMessageAsync("Unable to run command. Origin instance started with `-log_only` parameter. Stop it from console or UI Host instead.");
                return;
            }
            await Context.Channel.SendMessageAsync("**[BotMaster]** called ***StopBot***... *Ending Session*");
                DiscordSocketClient c = (DiscordSocketClient)Context.Client;
                Program.BCMDStarted = false;
                await c.SetGameAsync("");
                await Task.Delay(1000);
                await c.SetStatusAsync(UserStatus.Invisible);
                await Task.Delay(1000);
                Program.BCMDStarted = false;
                await c.StopAsync();
                await Task.Delay(3000);//Allow the bot to shut down fully before telling Main() to scream at user to finger the keyboard to close the console.
                Program.discon = true;
        }
 
#if DEBUG
        [Command("Session", RunMode = RunMode.Async), Summary("Shutdown the bot with a session error."), RequireOwner, Remarks("[CMDMgmt]")]
        public async Task InvalidateSession()
        {
            if (Program.LOG_ONLY_MODE)
            {
                await Context.Channel.SendMessageAsync("Unable to run command. Origin instance started with `-log_only` parameter. Stop it from console or UI Host instead.");
                return;
            }
            await Context.Channel.SendMessageAsync("`CRITICAL: Instance owner triggered a session invalidation. Immediately terminating session and calling for restart.`");
            await Task.Delay(200);
            await Context.Channel.SendMessageAsync("`CRITICAL: If restart fails, please verify the install & ensure you can properly contact discord API.`");
            await Task.Delay(400);
            await Context.Channel.SendMessageAsync("`CRITICAL: This command is for DEBUG builds only!`");
            DiscordSocketClient c = (DiscordSocketClient)Context.Client;
            Program.BCMDStarted = false;
            await c.SetGameAsync("");
            await Task.Delay(1000);
            await c.SetStatusAsync(UserStatus.Invisible);
            await Task.Delay(1000);
            Program.BCMDStarted = false;
            await c.StopAsync();
            await Task.Delay(3000);//Allow the bot to shut down fully before telling Main() to scream at user to finger the keyboard to close the console.
            Program.discon = true;
            Program.CriticalError = true;
            Program.crashException = new Discord.Net.WebSocketClosedException(4007, "Forced invalidate session.");
        }
 
        [Command("Throw", RunMode = RunMode.Async), Summary("Shutdown the bot with a session error."), RequireOwner, Remarks("[CMDMgmt]")]
        public async Task crash()
        {
            if (Program.LOG_ONLY_MODE)
            {
                await Context.Channel.SendMessageAsync("Unable to run command. Origin instance started with `-log_only` parameter. Stop it from console or UI Host instead.");
                return;
            }
            await Context.Channel.SendMessageAsync("`CRITICAL: Instance owner triggered a manual crash!`");
            await Task.Delay(200);
            await Context.Channel.SendMessageAsync("`CRITICAL: If restart fails, please verify the install & ensure you can properly contact discord API.`");
            await Task.Delay(400);
            await Context.Channel.SendMessageAsync("`CRITICAL: This command is for DEBUG builds only!`");
            DiscordSocketClient c = (DiscordSocketClient)Context.Client;
            Program.BCMDStarted = false;
            await c.SetGameAsync("");
            await Task.Delay(1000);
            await c.SetStatusAsync(UserStatus.Invisible);
            await Task.Delay(1000);
            Program.BCMDStarted = false;
            await c.StopAsync();
            await Task.Delay(3000);//Allow the bot to shut down fully before telling Main() to scream at user to finger the keyboard to close the console.
            Program.discon = true;
            Program.CriticalError = true;
            Program.crashException = new Exception("THIS IS A MANUAL DEBUG CRASH!");
            throw (Program.crashException);
        }
#endif
        [Command("RESTARTBOT", RunMode = RunMode.Async), Summary("Restart the bot"), RequireOwner, Remarks("[CMDMgmt]")]
        public async Task RestartBot()
        {
            if(Program.LOG_ONLY_MODE)
            {
                await Context.Channel.SendMessageAsync("Unable to run command. Origin instance started with `-log_only` parameter. Restart it from console or UI Host instead.");
                return;
            }
                await Context.Channel.SendMessageAsync("**[BotMaster]** called ***RestartBot***... *Ending Session, then restarting the program...*");
                DiscordSocketClient c = (DiscordSocketClient)Context.Client;
                Program.BCMDStarted = false;
                await c.SetGameAsync("");
                await Task.Delay(1000);
                await c.SetStatusAsync(UserStatus.Invisible);
                await Task.Delay(1000);
                Program.BCMDStarted = false;
                await c.StopAsync();
                await Task.Delay(3000);//Allow the bot to shut down fully before telling Main() to scream at user to finger the keyboard to close the console.
                Program.RestartRequested = true;
                Program.discon = true;
            
 
        }
 
        [Command("addcmd"), Summary("Add a custom command to the bot"),RequireContext(ContextType.Guild), Remarks("[CMDMgmt]")]
        public async Task AddCmd(string cmdTag, bool DevCmdOnly, bool lockToGuild, [Remainder]string action)
        {
            SocketGuildUser user = ((SocketGuildUser)Context.Message.Author);
            SocketMessage arg = Context.Message as SocketMessage;
 
            if (Program.rolemgt.CheckUserRole(user))//If user has a role that is in the database, it is good.
            {
                try
                {
                    Program.LogToConsole(new LogMessage(LogSeverity.Info,"CmdMgmt","User has a role in cmdMgrDB"));
 
                    string tosend = "";
                    if (action.StartsWith(Program.CommandPrefix.ToString()))
                    {
                        tosend = "Haha, you're funny. This bot will not run commands with nested commands. *That's dumb*.";
 
                        await Retry.Do(async () => await Context.Channel.SendMessageAsync(tosend), TimeSpan.FromMilliseconds(140));
                        return;
                    }
                    if (!lockToGuild)
                    {
                        tosend = Program.ccmg.AddCommand(cmdTag, action, DevCmdOnly);
                    }
                    if (lockToGuild)
                    {
                        tosend = Program.ccmg.AddCommand(cmdTag, action, DevCmdOnly, Context.Guild.Id);
                    }
 
                    IUserMessage a = await Retry.Do(async () => await Context.Channel.SendMessageAsync(tosend), TimeSpan.FromMilliseconds(140));//This is something to try, if it works, then boom!
                    return;
                }
                catch (System.Net.Http.HttpRequestException ex)
                {
 
                    await arg.Channel.SendMessageAsync("The request failed due to an API related http error that I can't sort out right now... please forgive me... (The command was most likely added anyway~)");
 
                    Program.LogToConsole(new LogMessage(LogSeverity.Error,"CritERR",ex.Message,ex));
                }
                catch (Exception ex)
                {
                    Program.LogToConsole(new LogMessage(LogSeverity.Error, "CritERR", ex.Message, ex));
                    ConsoleColor Last = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Gray;
                    
                    Console.ForegroundColor = Last;
                }
                return;
            }
            await Retry.Do(async () => await Context.Channel.SendMessageAsync("HEY! You don't have permission to do that!"), TimeSpan.FromMilliseconds(140));
            return;
        }
 
        [Command("addcmds"), Summary("Add a series of commands from attached file."), RequireContext(ContextType.Guild), Remarks("[CMDMgmt]")]
        public async Task AddCmds()
        {
            SocketGuildUser user = ((SocketGuildUser)Context.Message.Author);
            SocketMessage arg = Context.Message as SocketMessage;
            
            if (Program.rolemgt.CheckUserRole(user))//If user has a role that is in the database, it is good.
            {
                if (Context.Message.Attachments.Count < 1)
                {
                    await Retry.Do(async () => await Context.Channel.SendMessageAsync("You must attach a file."), TimeSpan.FromMilliseconds(140));
                    return;
                }
 
                var a = Context.Message.Attachments.First();
                //TODO: Download, process and merge into command database.
                return;
            }
            await Retry.Do(async () => await Context.Channel.SendMessageAsync("HEY! You don't have permission to do that!"), TimeSpan.FromMilliseconds(140));
            return;
        }
 
        [Command("editcmd"), Summary("edit an existing custom command"), RequireContext(ContextType.Guild), Remarks("[CMDMgmt]")]
        public async Task editcmd(string cmdTag, bool newDevCmdOnly, [Remainder]string newaction)
        {
            SocketGuildUser user = ((SocketGuildUser)Context.Message.Author);
            SocketMessage arg = Context.Message as SocketMessage;
 
            if (Program.rolemgt.CheckUserRole(user))
            {
                try
                {
                    Program.LogToConsole(new LogMessage(LogSeverity.Info,"CmdMgmt","User has required permission."));
 
                    string tosend = "";
 
                    if (newaction.StartsWith(Program.CommandPrefix.ToString()))
                    {
                        tosend = "Haha, you're funny. This bot will not run commands with nested commands. *That's dumb*.";
 
                        await Retry.Do(async () => await Context.Channel.SendMessageAsync(tosend), TimeSpan.FromMilliseconds(140));
                        return;
                    }
                    tosend = Program.ccmg.EditCommand(cmdTag, newaction, newDevCmdOnly);
 
                    RequestOptions op = new RequestOptions();
                    op.Timeout = 256;
                    op.RetryMode = RetryMode.AlwaysRetry;
                    IUserMessage a = await Retry.Do(async () => await Context.Channel.SendMessageAsync(tosend), TimeSpan.FromMilliseconds(140));
                    return;
                }
                catch (AggregateException ex)
                {
 
                    await arg.Channel.SendMessageAsync("The request failed (MANY TIMES) due to an API related http error that I can't sort out right now... please forgive me... (The command was most likely changed anyway~)");
 
                    Program.LogToConsole(new LogMessage(LogSeverity.Error,"CritERR",ex.Message,ex));
                    ConsoleColor Last = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Gray;
                    Console.ForegroundColor = Last;
                }
                catch (Exception ex)
                {
                    Program.LogToConsole(new LogMessage(LogSeverity.Error, "CritERR", ex.Message, ex));
                    ConsoleColor Last = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Gray;
                    Console.ForegroundColor = Last;
                }
                return;
            }
            await Retry.Do(async () => await Context.Channel.SendMessageAsync("Hey " + arg.Author.Mention + ", You don't have permission to use this command!"), TimeSpan.FromMilliseconds(140));
            
            return;
        }
 
        [Command("delcmd"), Summary("Remove specified custom command."), RequireContext(ContextType.Guild), Remarks("[CMDMgmt]")]
        public async Task delcmd(string cmdTag)
        {
            SocketGuildUser user = ((SocketGuildUser)Context.Message.Author);
            SocketMessage arg = Context.Message as SocketMessage;
 
            if (Program.rolemgt.CheckUserRole(user))
            {
                try
                {
 
                    Program.ccmg.DeleteCommand(cmdTag);
                    RequestOptions op = new RequestOptions();
                    op.Timeout = 256;
                    op.RetryMode = RetryMode.AlwaysRetry;
                    await Retry.Do(async () => await Context.Channel.SendMessageAsync("Command removed!make sure to save."), TimeSpan.FromMilliseconds(140));
                }
                catch (AggregateException ex)
                {
 
                    await arg.Channel.SendMessageAsync("The request failed (MANY TIMES) due to an API related http error that I can't sort out right now... please forgive me... (The command probably still got removed though)");
 
                    Program.LogToConsole(new LogMessage(LogSeverity.Error, "CritERR", ex.Message, ex));
                    ConsoleColor Last = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Gray;
                    Console.ForegroundColor = Last;
                }
                catch (Exception ex)
                {
                    await arg.Channel.SendMessageAsync("Command is probably removed, but I threw some kind of error... My master will look into it...");
                    Program.LogToConsole(new LogMessage(LogSeverity.Error, "CritERR", ex.Message, ex));
                    ConsoleColor Last = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Gray;
                    Console.ForegroundColor = Last;
                }
            }
 
            return;
        }
 
        //TODO: remove the attachment property! -- STREAM IT
        [Command("listcmd"), Summary("Shows a list of available commands."), RequireContext(ContextType.Guild)]
        public async Task listCmds()
        {
            CommandList commandList = new CommandList(Client.CurrentUser.Username);
            INICategory[] cmdcats = Program.ccmg.GetAllCommand();
            
#region CORE
            foreach (CommandInfo item in cmdsvr.Commands)
            {
                string group = item.Module.Aliases[0] + " ";
                string sum = item.Summary;
                if (string.IsNullOrWhiteSpace(group))
                {
                    group = "";//Command's groupAttribute?
                }
 
                if (item.Module.Name == "CoreModule")
                {
                    
                    if (string.IsNullOrEmpty(sum))
                    {
                        sum = "No summary was provided.";
                    }
                    
                }
                string usage = Program.CommandPrefix + group + item.Name + " ";
                foreach (var param in item.Parameters)
                {
                    if (param.IsOptional)
                    {
                        usage += $"[{param.Type.Name} {param.Name}] ";
                    }
                    if (!param.IsOptional)
                    {
                        usage += $"<{param.Type.Name} {param.Name}> ";
                    }
                }
                commandList.AddCommand(Program.CommandPrefix + group + item.Name, item.Remarks == "[CMDMgmt]", item.Module.Name == "CoreModule", sum, usage);
            }
#endregion
 
#region Custom Commands
            foreach (INICategory item in cmdcats)
            {
                if (item.CheckForEntry("guildID"))
                {
                    if (item.GetEntryByName("guildID").GetAsUlong() != Context.Guild.Id)
                    {
                        continue;//if the entry exists, and it doesn't match the guild listcmd was called in, don't add it to the list.
                    }
 
                }
                string commandSummary = "";
                string usage = "";
                if (item.CheckForEntry("summary"))
                {
                    commandSummary = item.GetEntryByName("summary").GetAsString();
 
                }
                if (item.CheckForEntry("usage"))
                {
                    usage = item.GetEntryByName("usage").GetAsString();
 
                }
                commandList.AddCommand(Program.CommandPrefix + item.Name, item.GetEntryByName("restricted").GetAsBool(), false, commandSummary, usage);
 
            }
#endregion
 
            try
            {
 
                using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                {
                    using (System.IO.StreamWriter sw = new System.IO.StreamWriter(ms))
                    {
 
                        sw.WriteLine(commandList.GetFullHTML());
                        sw.Flush();
                        ms.Position = 0;
                        await Context.Channel.SendMessageAsync("**See the attached web document for a full list of commands.**", false);
                        
                        await Context.Channel.SendFileAsync(ms, $"{Context.Guild.Name}_{Context.Client.CurrentUser.Username}_AllCommands.html");
 
                    }
                }
 
 
 
 
            }
            catch (AggregateException ex)
            {
 
                await Context.Channel.SendMessageAsync("Tried to do this THREE different times, and Quite honestly, I just could not do it... I'm sorry...");
                Program.LogToConsole(new LogMessage(LogSeverity.Error, "CritERR", ex.Message, ex));
            }
            return;
 
        }
 
        [Command("save"), Summary("Save the command database."), RequireContext(ContextType.Guild), Remarks("[CMDMgmt]")]
        public async Task SaveCmd()
        {
 
 
            SocketMessage arg = Context.Message as SocketMessage;
            SocketGuildUser user = ((SocketGuildUser)arg.Author);
 
            if (Program.rolemgt.CheckUserRole(user))
            {
 
                Program.LogToConsole(new LogMessage(LogSeverity.Info, "CmdEXEC","User has required permission"));
                await arg.Channel.SendMessageAsync("Command DB saved.");
                Program.ccmg.Save();
                
            }
 
            return;
        }
 
        [Command("changes"), Summary("Shows what changed in this version")]
        public async Task ShowChanges()
        {
            EmbedBuilder eb = new EmbedBuilder();
 
            eb.WithAuthor("What's New", Client.CurrentUser.GetAvatarUrl(), "");
            eb.AddField($"v{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)} (Beta release)", "• Adjusting logging feature... Making logging a globally-accessible system.\r\n• Fixed ERRORS.LOG. It will actually be created again.\r\n Re-worded save prompts.");
            eb.WithFooter("RMSoftware.ModularBOT");
            eb.Color = Color.DarkBlue;
            RequestOptions op = new RequestOptions();
            op.RetryMode = RetryMode.AlwaysRetry;
            await Context.Channel.SendMessageAsync("**Full version history/change log: http://rms0.org?a=mbChanges**", false, eb.Build(), op);
        }
 
        [Command("shadowban"), RequireContext(ContextType.Guild), RequireOwner, Remarks("[CMDMgmt]")]
        public async Task IgnoreUser(params IUser[] users)
        {
            int count = 0;
            foreach (var item in users)
            {
                if (Program.rolemgt.AddUserToBlacklist(item as SocketUser))
                {
                    count++;
                }
            }
            await Context.Channel.SendMessageAsync($"Added `{count}` user(s) to the blacklist. they can no longer access my commands.");
        }
 
        [Command("shadowunban"), RequireContext(ContextType.Guild), RequireOwner, Remarks("[CMDMgmt]")]
        public async Task UnIgnoreUser(params IUser[] users)
        {
            int count = 0;
            foreach (var item in users)
            {
                if (Program.rolemgt.DeleteUserFromBlacklist(item as SocketUser))
                {
                    count++;
                }
            }
            await Context.Channel.SendMessageAsync($"Removed `{count}` user(s) from the blacklist. they can now access my commands.");
        }
 
        [Command("addmgrole"), Summary("add a role to CommandMGMT database"), RequireContext(ContextType.Guild),RequireOwner, Remarks("[CMDMgmt]")]
        public async Task AddRoletoDB(params IRole[] roles)
        {
            foreach (var item in roles)
            {
                Program.rolemgt.AddCommandManagerRole(item as SocketRole);
            }
            await Context.Channel.SendMessageAsync($"Successfully added `{roles.Length}` role(s) to the CommandMGMT database for guild: `{Context.Guild.Name}`.");
        }
        [Command("delmgrole"), Summary("Delete a role from CommandMGMT database"), RequireContext(ContextType.Guild), RequireOwner, Remarks("[CMDMgmt]")]
        public async Task DelRoleFromDB(params IRole[] roles)
        {
            foreach (var item in roles)
            {
                Program.rolemgt.DeleteCommandManager(item as SocketRole);
            }
            await Context.Channel.SendMessageAsync($"Successfully removed `{roles.Length}` role(s) from the CommandMGMT database for guild: `{Context.Guild.Name}`.");
        }
        [Command("listmgrole",RunMode=RunMode.Async), Summary("lists the authorized management roles for the guild where the command was called."), RequireContext(ContextType.Guild), RequireOwner, Remarks("[CMDMgmt]")]
        public async Task listmgroledbguild()
        {
            await Context.Channel.SendMessageAsync($"This could take a while...");
            await Task.Delay(500);
            using (Context.Channel.EnterTypingState())
            {
                SocketRole[] items = Program.rolemgt.GetRolesForGuild(Context.Guild as SocketGuild);
                string roles = "";
                foreach (var item in items)
                {
                    roles += $"{item.Id} - {item.Name}{Environment.NewLine}";
                }
                await Context.Channel.SendMessageAsync($"All authorized management roles for `{Context.Guild.Name}`:\r\n```\r\n{roles}\r\n```");
            }
                
        }
 
        [Command("listallmgroles", RunMode = RunMode.Async), Summary("lists the authorized management roles for all guilds"), RequireContext(ContextType.Guild), RequireOwner, Remarks("[CMDMgmt]")]
        public async Task listmgroledball()
        {
            int zint = 0;
            await Context.Channel.SendMessageAsync($"This could take a while...");
            await Task.Delay(500);
            using (Context.Channel.EnterTypingState())
            {
                
                SocketRole[] items = Program.rolemgt.GetAllRoles();
                List<string> book = new List<string>();
                string roles = "";
                foreach (var item in items)
                {
                    string toAddTo = $"{item.Id} - {item.Name}{Environment.NewLine}";
                    int len = roles.Length + toAddTo.Length;
 
                    if(len >600)
                    {
                        len = 0;
                        book.Add(new String(roles.ToCharArray()));//This is probably super dumb, but I want to add the string to the list and change the roles string without affecting the entry in the list. Im doing this to be safe.
                        roles = "";
 
                    }
                    roles += $"{item.Guild.Name} - {item.Id} - {item.Name}{Environment.NewLine}";
                }
                book.Add(roles);
                foreach (string item in book)
                {
                    if(zint <1)
                    {
                        await Context.Channel.SendMessageAsync($"All authorized management roles in the database:\r\n```\r\n{item}\r\n```");
                    }
                    if (zint >= 1)
                    {
                        await Context.Channel.SendMessageAsync($"```\r\n{item}\r\n```");
                    }
                    zint++;
 
                    SocketGuildUser r = Context.User as SocketGuildUser;
 
                    string display = r.Nickname ?? r.Username;
                }
            }
 
        }
 
    }
 
  
}

Comments