rmsoft1

Program.cs

Apr 29th, 2018
327
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 58.01 KB | None | 0 0
  1. //https://github.com/RMSoftware-Development Commit soon.
  2.  
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. using System.IO;
  8. using Discord;
  9. using Discord.WebSocket;
  10. using System.Reflection;
  11. using Discord.Commands;
  12. using System.Threading;
  13. using Microsoft.Extensions.DependencyInjection;
  14. using RMSoftware.IO;
  15. using System.Diagnostics;
  16. using Newtonsoft.Json;
  17. using System.Runtime.ExceptionServices;
  18.  
  19. namespace RMSoftware.ModularBot
  20. {
  21.     class Program
  22.     {
  23.         #region STATIC fields & properties
  24.         public static DateTime StartTime;
  25.         public static bool BCMDStarted = false;
  26.         public static bool WizardDebug = false;
  27.         public static bool discon = false;
  28.         public static bool CriticalError = false;
  29.         public static bool RestartRequested = false;
  30.         public static Exception crashException = null;
  31.         static string auth = "";
  32.         static bool CRASH = false;
  33.         public static string[] ARGS = null;
  34.         public static CustomCommandManager ccmg { get; private set; }
  35.         public static CmdRoleManager rolemgt { get; private set; }
  36.         public static char CommandPrefix { get; private set; }
  37.         public static DiscordSocketClient _client;
  38.         static List<SocketMessage> messageQueue = new List<SocketMessage>();
  39.         public static bool LOG_ONLY_MODE = false;//Set by args on start. if true, console header and resets are ignored. Should only be done if hosting the process in a UI.
  40.         public static bool MessagesDisabled = false;
  41.         public static ConsoleLogWriter writer = new ConsoleLogWriter();
  42.         /// <summary>
  43.         /// Application's main configuration file
  44.         /// </summary>
  45.         public static INIFile MainCFG { get; private set;}
  46.         #endregion
  47.  
  48.         #region Instance fields & properties
  49.         public IServiceCollection serviceCollection;
  50.         public IServiceProvider services;
  51.         public CommandService cmdsvr = new Discord.Commands.CommandService();
  52.         #endregion
  53.  
  54.         #region STATIC methods
  55.  
  56.         public static int Main(string[] args)
  57.         {
  58.             ARGS = args;
  59.             try
  60.             {
  61.                 foreach (string item in args)
  62.                 {
  63.                     if (item.ToLower() == "-log_only")
  64.                     {
  65.                         LOG_ONLY_MODE = true;
  66.                     }
  67.                     if (item.ToLower() == "-crashed")
  68.                     {
  69.                         CRASH = true;
  70.                     }
  71.                     if (item.StartsWith("-auth"))
  72.                     {
  73.                         auth = item.Split(' ')[1];
  74.                     }
  75.                 }
  76.                 BCMDStarted = false;
  77.                 ConsoleGUIReset(ConsoleColor.Green, ConsoleColor.Black, "Welcome", 79, 45);
  78.                 Console.Title = "RMSoftware.ModularBOT";
  79.                 Console.WriteLine("Oh, Hello! Greetings! Salutations! Stuff is about to happen... Please wait...");
  80.                 System.Threading.Thread.Sleep(800);
  81.                 ConsoleWriteImage(Prog.res1.Resource1.RMSoftwareICO);
  82.                 System.Threading.Thread.Sleep(3000);
  83.                 ConsoleGUIReset(ConsoleColor.Cyan, ConsoleColor.Black, "Program Starting");
  84.                 ccmg = new CustomCommandManager();
  85.                 rolemgt = new CmdRoleManager();
  86.  
  87.                 AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
  88.                 //AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
  89.  
  90.  
  91.  
  92.                 SetupWizard();
  93.  
  94.                 if (auth.Length == 0)
  95.                 {
  96.                     ConsoleGUIReset(ConsoleColor.White, ConsoleColor.DarkBlue, "Initializing");
  97.                     Console.WriteLine("You didn't specify an authorization token as parameter....");
  98.                     Console.WriteLine("usage: RMSoftwareModularBot.exe <authToken>");
  99.                     Console.WriteLine("No big deal though, Will use configuration instead");
  100.                     auth = Program.MainCFG.GetCategoryByName("Application").GetEntryByName("botToken").GetAsString();
  101.                 }
  102.  
  103.                 //set command prefix
  104.  
  105.                 CommandPrefix = Convert.ToChar(MainCFG.GetCategoryByName("Application").GetEntryByName("cmdPrefix").GetAsInteger());
  106.                 Program.LogToConsole(new LogMessage(LogSeverity.Info, "Initialize", $"Using the command prefix: {(char)CommandPrefix}"));
  107.                 var prg = new Program();
  108.                 prg.MainAsync(auth).GetAwaiter().GetResult();
  109.                 Task.Run(new Action(ReadConsole));
  110.                 Task.Run(new Action(writer.ProcessStack().GetAwaiter().GetResult));
  111.                 SpinWait.SpinUntil(BotShutdown);//Wait until shutdown;
  112.                 BCMDStarted = false;
  113.                 ConsoleGUIReset(ConsoleColor.White, ConsoleColor.DarkRed, "Disconnected");
  114.                 if (CriticalError)
  115.                 {
  116.                     Program.LogToConsole(new LogMessage(LogSeverity.Critical, "Session", "Failed to resume previous session.",crashException));
  117.                     using (FileStream fs = File.Create("CRASH.LOG"))
  118.                     {
  119.                         using (StreamWriter sw = new StreamWriter(fs))
  120.                         {
  121.                             LogMessage m = new LogMessage(LogSeverity.Critical, "Session", crashException.Message, crashException);
  122.                             sw.WriteLine(m.ToString());
  123.                             List<string> restart_args = new List<string>();
  124.                             restart_args.AddRange(ARGS);
  125.                             if (!restart_args.Contains("-crashed"))
  126.                             {
  127.                                 restart_args.Add("-crashed");
  128.                             }
  129.                             ARGS = restart_args.ToArray();
  130.                             sw.Flush();
  131.  
  132.                         }
  133.                     }
  134.                     if (!LOG_ONLY_MODE)
  135.                     {
  136.                         Program.LogToConsole(new LogMessage(LogSeverity.Warning, "Application", "Restarting in 4 seconds..."));
  137.                         Thread.Sleep(1000);
  138.                     }
  139.  
  140.                     RestartRequested = true;
  141.                     _client = null;
  142.                 }
  143.             }
  144.             catch (Exception ex)
  145.             {
  146.                 crashException = ex;
  147.                 ConsoleGUIReset(ConsoleColor.White,ConsoleColor.DarkRed,"Critical Application Error.");
  148.                 Program.LogToConsole(new LogMessage(LogSeverity.Critical, "Exception", ex.Message, ex));
  149.                 CriticalError = true;
  150.                 RestartRequested = true;
  151.                 using (FileStream fs = File.Create("CRASH.LOG"))
  152.                 {
  153.                     using (StreamWriter sw = new StreamWriter(fs))
  154.                     {
  155.                         LogMessage m = new LogMessage(LogSeverity.Critical, "Session", ex.Message, ex);
  156.                         sw.WriteLine(m.ToString());
  157.                         List<string> restart_args = new List<string>();
  158.                         restart_args.AddRange(ARGS);
  159.                         if (!restart_args.Contains("-crashed"))
  160.                         {
  161.                             restart_args.Add("-crashed");
  162.                         }
  163.                         ARGS = restart_args.ToArray();
  164.                         sw.Flush();
  165.  
  166.                     }
  167.                 }
  168.                 using (FileStream fs = new FileStream("ERRORS.LOG", FileMode.Append))
  169.                 {
  170.                     using (StreamWriter sw = new StreamWriter(fs))
  171.                     {
  172.  
  173.                         sw.WriteLine(DateTime.Today.ToString("MM/dd/yyyy") + "   " + ex.ToString());
  174.                         sw.Flush();
  175.  
  176.                     }
  177.                 }
  178.             }
  179.             if (RestartRequested)
  180.             {
  181.                 Process p = new Process();
  182.                 string flattened = "";
  183.                 foreach (string item in ARGS)
  184.                 {
  185.                     flattened += item + " ";
  186.                 }
  187.                 p.StartInfo = new ProcessStartInfo(Process.GetCurrentProcess().MainModule.FileName, flattened);
  188.                 ConsoleGUIReset(ConsoleColor.White, ConsoleColor.DarkRed, "Disconnected");
  189.                 writer.WriteEntry(new LogMessage(LogSeverity.Warning, "Program", "Restarting in 3...")).GetAwaiter().GetResult();//using direct writer to try and prevent blanks.
  190.                 Thread.Sleep(1000);
  191.                 ConsoleGUIReset(ConsoleColor.White, ConsoleColor.DarkRed, "Disconnected");
  192.                 writer.WriteEntry(new LogMessage(LogSeverity.Warning, "Program", "Restarting in 2...")).GetAwaiter().GetResult();
  193.  
  194.                 Thread.Sleep(1000);
  195.                 ConsoleGUIReset(ConsoleColor.White, ConsoleColor.DarkRed, "Disconnected");
  196.                 writer.WriteEntry(new LogMessage(LogSeverity.Warning, "Program", "Restarting in 1...")).GetAwaiter().GetResult();
  197.  
  198.                 Thread.Sleep(1000);
  199.                 p.Start();
  200.                 return 0x00000c4;
  201.             }
  202.             writer.WriteEntry(new LogMessage(LogSeverity.Warning, "Program", "Termination.")).GetAwaiter().GetResult();
  203.  
  204.             if (!CriticalError)
  205.             {
  206.  
  207.                 return 4007;//NOT OKAY
  208.             }
  209.             else
  210.             {
  211.  
  212.                 return 200;//OK status
  213.             }
  214.         }
  215.  
  216.         private static void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
  217.         {
  218.             writer.push(new LogMessage(LogSeverity.Critical, "FirstERR", e.Exception.ToString()));
  219.         }
  220.  
  221.         static void ReadConsole()
  222.         {
  223.             ulong chID = 0;
  224.             while (true)
  225.             {
  226.                 if (discon)
  227.                 {
  228.                     break;
  229.                 }
  230.                
  231.                 string input = Console.ReadLine();
  232.                 if (discon)
  233.                 {
  234.                     if(string.IsNullOrWhiteSpace(input))
  235.                     {
  236.                         return;
  237.                     }
  238.                 }
  239.                 if (input.ToLower() == "bot.stopbot")
  240.                 {
  241.                     _client.SetGameAsync("");
  242.                     System.Threading.Thread.Sleep(2000);
  243.                     _client.SetStatusAsync(UserStatus.Invisible);
  244.                     System.Threading.Thread.Sleep(2000);
  245.                     Program.BCMDStarted = false;
  246.                     _client.StopAsync();
  247.                     System.Threading.Thread.Sleep(3000);//Allow the bot to shut down fully before telling Main() to scream at user to finger the keyboard to close the console.
  248.                     Program.discon = true;
  249.                     break;
  250.                 }
  251.                 if (input.ToLower() == "cn_term")
  252.                 {
  253.                     Console.WriteLine("Termination");
  254.                     break;
  255.                 }
  256.                 if (input.ToLower() == "bot.disablecmd")
  257.                 {
  258.                     Program.LogToConsole(new LogMessage(LogSeverity.Warning, "Console", "Command processing disabled!"));
  259.  
  260.                     _client.SetStatusAsync(UserStatus.DoNotDisturb);
  261.                     _client.SetGameAsync("");
  262.                     MessagesDisabled = true;
  263.                 }
  264.                 if (input.ToLower() == "bot.enablecmd")
  265.                 {
  266.                     Program.LogToConsole(new LogMessage(LogSeverity.Info, "Console", "Command processing enabled."));
  267.  
  268.                     _client.SetStatusAsync(UserStatus.Online);
  269.                     _client.SetGameAsync("READY!");
  270.                     MessagesDisabled = false;
  271.                 }
  272.                 if (input.ToLower().StartsWith("bot.status"))
  273.                 {
  274.                     string status = input.Remove(0, 10).Trim();
  275.                     Program.LogToConsole(new LogMessage(LogSeverity.Warning, "Client", "client status changed."));
  276.  
  277.                     _client.SetGameAsync(status);
  278.                 }
  279.                 if (input.StartsWith("setgch"))
  280.                 {
  281.                     input = input.Remove(0, 6).Trim();
  282.                     if (!ulong.TryParse(input, out chID))
  283.                     {
  284.                         Program.LogToConsole(new LogMessage(LogSeverity.Error, "Console", "Invalid ULONG."));
  285.  
  286.                         continue;
  287.                     }
  288.                 }
  289.                 if (input.StartsWith("conmsg"))
  290.                 {
  291.                     input = input.Remove(0, 6).Trim();
  292.                     SocketTextChannel Channel = _client.GetChannel(chID) as SocketTextChannel;
  293.                     if (Channel == null)
  294.                     {
  295.                         Program.LogToConsole(new LogMessage(LogSeverity.Warning, "Console", "Invalid channel."));
  296.  
  297.                         continue;
  298.                     }
  299.                     Channel.SendMessageAsync(input);
  300.                 }
  301.                
  302.             }
  303.         }
  304.  
  305.         private static void SetupWizard()
  306.         {
  307.             if (InitializeConfig())//If true, do setup.
  308.             {
  309.                 #region Page 1
  310.                 ConsoleGUIReset(ConsoleColor.Cyan, ConsoleColor.Black, "Welcome");
  311.                 Console.WriteLine("Welcome to the initial setup wizard for your new modular discord bot...\r\n Some things to note before we get started:");
  312.                 Console.WriteLine("\t- This bot requires a token. If you don't know what that is," +
  313.                     " please visit this site first!");
  314.                 Console.WriteLine("\t- https://discordapp.com/developers/docs/intro");
  315.  
  316.                 Console.WriteLine("\t- Privacy notice: This application will output any message that mentions the bot, or messages that start with ! to the console.\r\n\t" +
  317.                     " THEY DO NOT GET SAVED OR POSTED ANYWHERE ELSE... That would be creepy and probably illegal...");
  318.  
  319.                 Console.WriteLine("\r\nPress ENTER to continue...");
  320.                 Console.ReadLine();
  321.                 #endregion
  322.  
  323.                 #region Page 2
  324.                 ConsoleGUIReset(ConsoleColor.Green, ConsoleColor.Black, "Step 1: Token Configuration");
  325.  
  326.                 Console.WriteLine("As mentioned before, this bot requires a token. It can be added in one of two ways.");
  327.                 Console.WriteLine("\t- METHOD 1: Program arguments. Simply launch the program from a batch file,\r\n\t- USAGE: RMSoftwareModularBot.exe <put token here>");
  328.                 Console.WriteLine("\t- METHOD 2: Configure it. Actually, let's do that now.");
  329.                 Console.WriteLine("Go ahead and find your token and copy/paste* it here, then press enter.");
  330.                 Console.WriteLine("*Only if your CMD console will let you... If not, that sucks... You can painfully type it in also...");
  331.                 Console.Write("> ");
  332.                 string conf_Token = Console.ReadLine();
  333.                
  334.                 if (!WizardDebug)
  335.                 {
  336.                     MainCFG.CreateCategory("Application");
  337.                     MainCFG.CreateEntry("Application", "botToken", conf_Token);
  338.                 }
  339.  
  340.                 Console.WriteLine("Okay! Please remember, You can also start the program with a token as an argument.");
  341.                 Console.WriteLine("Be advised, the token in the configuration is ignored when using the program parameter.");
  342.  
  343.                 Console.WriteLine("\r\nPress ENTER to continue...");
  344.                 Console.ReadLine();
  345.                 #endregion
  346.  
  347.                 #region Page 3
  348.                 ConsoleGUIReset(ConsoleColor.Green, ConsoleColor.Black, "Step 2: Control Channel & Command prefix");
  349.  
  350.                 Console.WriteLine("Ah, yes... The Control channel...");
  351.                 Console.WriteLine("\t- Whenever you start your bot, it will execute AutoStart.bcmd, a script full of commands to prepare for that bot life...");
  352.                 Console.WriteLine("\t- However, in order to do this, the bot needs to know where to send these messages and commands...");
  353.                 Console.WriteLine("\t- Not doing this now would result in a crashing bot that doesn't know what to do with its life.");
  354.                 Console.WriteLine("\t- All I need is the ID of that channel to put into the configuration.");
  355.                 Console.WriteLine("\t- If you need a refresher on how to find a channel ID: https://goo.gl/nqAbhw \r\n\t" +
  356.                     "(It goes to the discord's official docs)");
  357.                 Console.WriteLine("copy/paste or painfully type in your Initialization Channel's id and press enter");
  358.                 Console.Write("> ");
  359.                 string conf_BotChannel = Console.ReadLine();
  360.                 if (!WizardDebug)
  361.                 {
  362.                     Program.MainCFG.CreateEntry("Application", "botChannel", conf_BotChannel);
  363.                 }
  364.                 Console.WriteLine("Great! Now that channel will be the bot's main log channel...");
  365.                 Console.WriteLine();
  366.                 Console.WriteLine("Now... The Command Prefix: Please enter a single character (Recommended: A symbol of some kind), to use as the bot's command prefix");
  367.                 Console.Write("> ");
  368.                 int conf_cmdPrefix = Console.Read();
  369.                 if (!WizardDebug)
  370.                 {
  371.                     Program.MainCFG.CreateEntry("Application", "cmdPrefix", conf_cmdPrefix);
  372.                     Program.MainCFG.SaveConfiguration();//save
  373.                 }
  374.                 Console.WriteLine("Great! Your bot will use '" + Convert.ToChar(conf_cmdPrefix) + "' [without quotes] as a prefix for it's commands!");
  375.                 Console.WriteLine("\r\nPress ENTER to continue...");
  376.                 Console.ReadLine();
  377.  
  378.                 #endregion
  379.  
  380.                 #region Page 4
  381.                 ConsoleGUIReset(ConsoleColor.Cyan, ConsoleColor.Black, "Step 3: Final Notes & ProTips");
  382.                 Console.WriteLine("That is all the configuration for right now! Here are a few more things to know:");
  383.                 Console.WriteLine("\t- If you want to re-run this configuration wizard, delete the 'rmsftModBot.ini' file in the program directory.");
  384.                 Console.WriteLine("\t- The source code for this bot is available on http://rmsoftware.org");
  385.                 Console.WriteLine("\r\nCORE Command usage (in discord):");
  386.                 Console.WriteLine("\t- use <prefix>addmgrole [@roles] to add roles to the command user database.");
  387.                 Console.WriteLine("\t- usage: <prefix>addcmd <command name> <CmdMgmtOnly[true/false]> <LockToGuild[true/false]> <action>");
  388.                 Console.WriteLine("\t- Actions: Any text/emotes with optional formatting.");
  389.                 Console.WriteLine("\t- <prefix>addcmd sample1SplitParam false false splitparam 3|" +
  390.                     " This is a sample of splitparam. Var1: {0} var2: {1} and var3: {2} all walked into a bar");
  391.                 Console.WriteLine("\t- <prefix>addcmd hug false false You hug {params} for a long time");
  392.                 Console.WriteLine("\t- More Action parameters: EXEC and CLI_EXEC ");
  393.                 Console.WriteLine("\t- <prefix>addcmd exectest falase false EXEC modname.dll ModNameSpace.ModClass StaticMethod {params}");
  394.                 Console.WriteLine("\t- <prefix>addcmd exectest falase false CLI_EXEC modname.dll ModNameSpace.ModClass StaticMethod {params}");
  395.                 Console.WriteLine("\t  - NOTE: splitparam is not supported for EXEC or CLI_EXEC");
  396.                 Console.WriteLine("\t  - NOTE: EXEC: Allows you to execute a class method for a more advanced command");
  397.                 Console.WriteLine("\t  - NOTE: CLI_EXEC is the same thing, but it gives the class access to the bot directly...");
  398.                 Console.WriteLine("Extra Configuration Options:");
  399.                 Console.WriteLine("\t  - Adding the line DisableCore=True to the [Application] section of the config file, will disable all core commands.");
  400.                 Console.WriteLine("\t     - Remember this will disable the ability to manage commands. putting the bot in a sort of 'read-only' state.");
  401.            
  402.                 Console.WriteLine("Override core: ");
  403.                 Console.WriteLine("\t  - You can create custom commands that use the same name as core commands. This is useful for overriding core commands for even more customization...");
  404.                 Console.WriteLine("\r\nPlease visit http://rmsoftware.org/rmsoftwareModularBot for more information and documentation.");
  405.                 Console.WriteLine("\r\nPress ENTER to launch the bot!");
  406.                 Console.ReadLine();
  407.                 #endregion
  408.             }
  409.         }
  410.  
  411.  
  412.         private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
  413.         {
  414.             //Exception ex = e.ExceptionObject as Exception;
  415.             //LogToConsole("CritERR", ex.Message);
  416.             //ConsoleColor Last = Console.ForegroundColor;
  417.             //Console.ForegroundColor = ConsoleColor.Gray;
  418.             //LogToConsole("ExStack\r\n\r\n", ex.StackTrace);
  419.             //Console.ForegroundColor = Last;
  420.             CriticalError = true;
  421.             RestartRequested = true;
  422.             crashException = (Exception)e.ExceptionObject;
  423.             using (FileStream fs = File.Create("CRASH.LOG"))
  424.             {
  425.                 using (StreamWriter sw = new StreamWriter(fs))
  426.                 {
  427.                     LogMessage m = new LogMessage(LogSeverity.Critical, "Session", crashException.Message, crashException);
  428.                     sw.WriteLine(m.ToString());
  429.                     List<string> restart_args = new List<string>();
  430.                     restart_args.AddRange(ARGS);
  431.                     if (!restart_args.Contains("-crashed"))
  432.                     {
  433.                         restart_args.Add("-crashed");
  434.                     }
  435.                     ARGS = restart_args.ToArray();
  436.                     sw.Flush();
  437.  
  438.                 }
  439.             }
  440.             using (FileStream fs = new FileStream("ERRORS.LOG", FileMode.Append))
  441.             {
  442.                 using (StreamWriter sw = new StreamWriter(fs))
  443.                 {
  444.  
  445.                     sw.WriteLine(DateTime.Today.ToString("MM/dd/yyyy") + "   " + ((Exception)e.ExceptionObject).ToString());
  446.                     sw.Flush();
  447.  
  448.                 }
  449.             }
  450.         }
  451.         static Func<bool> BotShutdown = delegate ()
  452.         {
  453.             return discon;
  454.         };
  455.  
  456.         /// <summary>
  457.         /// Reset the console layout using specified values
  458.         /// </summary>
  459.         /// <param name="fore">Text color</param>
  460.         /// <param name="back">Background color</param>
  461.         /// <param name="title">Console's header title (not window title)</param>
  462.         public static void ConsoleGUIReset(ConsoleColor fore, ConsoleColor back, string title)
  463.         {
  464.             if(LOG_ONLY_MODE)
  465.             {
  466.                 return;
  467.             }
  468.             Console.Clear();
  469.             Console.SetWindowSize(144, 32);
  470.             Console.SetBufferSize(144, 256);
  471.             Console.BackgroundColor = back;
  472.             Console.ForegroundColor = fore;
  473.             Console.Clear();
  474.            
  475.             Console.BackgroundColor = ConsoleColor.Black;
  476.             Console.ForegroundColor = ConsoleColor.White;
  477.             DecorateTop();
  478.             string WTitle = (""+DateTime.Now.ToString("HH:mm:ss") + " " + title + " - RMSoftwareModularBot v" + Assembly.GetExecutingAssembly().GetName().Version.ToString(4));
  479.             string pTitle = WTitle.PadLeft(71+WTitle.Length/2);
  480.             pTitle += "".PadRight(71-WTitle.Length/2);
  481.             Console.Write("\u2551{0}\u2551", pTitle);
  482.             DecorateBottom();
  483.             Console.BackgroundColor = back;
  484.             Console.ForegroundColor = fore;
  485.         }
  486.  
  487.         /// <summary>
  488.         /// Reset the console layout using specified values
  489.         /// </summary>
  490.         /// <param name="fore">Text color</param>
  491.         /// <param name="back">Background color</param>
  492.         /// <param name="title">Console's header title (not window title)</param>
  493.         /// <param name="w">Console window & buffer width</param>
  494.         /// <param name="h">Console window & buffer height</param>
  495.         public static void ConsoleGUIReset(ConsoleColor fore, ConsoleColor back, string title,short w, short h)
  496.         {
  497.             if (LOG_ONLY_MODE)
  498.             {
  499.                 return;
  500.             }
  501.             Console.Clear();
  502.             Console.SetWindowSize(w, h);
  503.             Console.SetBufferSize(w, h);
  504.             Console.BackgroundColor = back;
  505.             Console.ForegroundColor = fore;
  506.             Console.Clear();
  507.  
  508.             Console.BackgroundColor = ConsoleColor.Black;
  509.             Console.ForegroundColor = ConsoleColor.White;
  510.             DecorateTop();
  511.             string WTitle = ("" + DateTime.Now.ToString("HH:mm:ss") + " " + title + " - RMSoftwareModularBot v" + Assembly.GetExecutingAssembly().GetName().Version.ToString(4));
  512.             string pTitle = WTitle.PadLeft(((w/2)+2) + WTitle.Length / 2);
  513.             pTitle += "".PadRight(((w / 2)-3) - WTitle.Length / 2);
  514.             Console.Write("\u2551{0}\u2551", pTitle);
  515.  
  516.  
  517.             DecorateBottom();
  518.             Console.BackgroundColor = back;
  519.             Console.ForegroundColor = fore;
  520.         }
  521.  
  522.         private static void DecorateTop()
  523.         {
  524.             for (int i = 0; i < Console.WindowWidth; i++)
  525.             {
  526.                 if(i==0)
  527.                 {
  528.                     Console.Write("\u2554");
  529.                     continue;
  530.                 }
  531.                
  532.                 if (i == Console.WindowWidth-1)
  533.                 {
  534.                     Console.Write("\u2557");
  535.                     break;
  536.                 }
  537.                 Console.Write("\u2550");
  538.             }
  539.         }
  540.  
  541.         private static void DecorateBottom()
  542.         {
  543.             for (int i = 0; i < Console.WindowWidth; i++)
  544.             {
  545.                 if (i == 0)
  546.                 {
  547.                     Console.Write("\u255A");
  548.                     continue;
  549.                 }
  550.  
  551.                 if (i == Console.WindowWidth - 1)
  552.                 {
  553.                     Console.Write("\u255D");
  554.                     break;
  555.                 }
  556.                 Console.Write("\u2550");
  557.             }
  558.         }
  559.  
  560.         public static void LogToConsole(LogMessage msg)
  561.         {
  562.             if(!LOG_ONLY_MODE)
  563.             {
  564.                
  565.                 //Console.WriteLine(l.ToString());
  566.                 writer.push(msg);
  567.             }
  568.             else
  569.             {
  570.                 Console.WriteLine(JsonConvert.SerializeObject(msg));
  571.             }
  572.             if (msg.Exception != null)
  573.             {
  574.                 using (FileStream fs = new FileStream("ERRORS.LOG", FileMode.Append))
  575.                 {
  576.                     using (StreamWriter sw = new StreamWriter(fs))
  577.                     {
  578.  
  579.                         sw.WriteLine(DateTime.Today.ToString("MM/dd/yyyy") + "   " + msg.ToString());
  580.                         sw.Flush();
  581.  
  582.                     }
  583.                 }
  584.             }
  585.         }
  586.  
  587.  
  588.         /// <summary>
  589.         /// Initialize configuration.
  590.         /// </summary>
  591.         /// <returns>True if it generated a new file, or has zero categories in said file.</returns>
  592.         private static bool InitializeConfig()
  593.         {
  594.             ConsoleGUIReset(ConsoleColor.Cyan, ConsoleColor.Black, "Initializing Configuration");
  595.             Program.MainCFG = new INIFile("rmsftModBot.ini");
  596.  
  597.             if (Program.MainCFG.Categories.Count == 0)
  598.             {
  599.                 return true;
  600.             }
  601.             else
  602.             {
  603.                 if (Program.MainCFG.CheckForCategory("Application"))
  604.                 {
  605.                     if (Program.MainCFG.GetCategoryByName("Application").CheckForEntry("Dev-ShowWizard"))
  606.                     {
  607.                         WizardDebug = true;
  608.                         return Program.MainCFG.GetCategoryByName("Application").GetEntryByName("Dev-ShowWizard").GetAsBool();
  609.                     }
  610.  
  611.                     //REQUIRED entries.
  612.                     if (!Program.MainCFG.GetCategoryByName("Application").CheckForEntry("botToken") ||
  613.                         !Program.MainCFG.GetCategoryByName("Application").CheckForEntry("botChannel") ||
  614.                         !Program.MainCFG.GetCategoryByName("Application").CheckForEntry("cmdPrefix"))
  615.                     {
  616.                         Program.LogToConsole(new LogMessage(LogSeverity.Warning, "Warning", "Invalid or missing config. Reset all settings."));
  617.  
  618.                         File.Delete("rmsftModBot.ini");
  619.                         Program.MainCFG = new INIFile("rmsftModBot.ini");//Re-write from scratch.
  620.                         return true;
  621.                     }
  622.                 }
  623.             }
  624.             return false;//basically the file is found and nothing broke.
  625.  
  626.         }
  627.  
  628.  
  629.         #region Console pixel art - Courtesy of Stackoverflow.com
  630.         static int[] cColors = { 0x000000, 0x000080, 0x008000, 0x008080, 0x800000, 0x800080, 0x808000, 0xC0C0C0, 0x808080, 0x0000FF, 0x00FF00, 0x00FFFF, 0xFF0000, 0xFF00FF, 0xFFFF00, 0xFFFFFF };
  631.         private static bool term;
  632.  
  633.         public static void ConsoleWritePixel(System.Drawing.Color cValue)
  634.         {
  635.             System.Drawing.Color[] cTable = cColors.Select(x => System.Drawing.Color.FromArgb(x)).ToArray();
  636.             char[] rList = new char[] { (char)9617, (char)9618, (char)9619, (char)9608 }; // 1/4, 2/4, 3/4, 4/4
  637.             int[] bestHit = new int[] { 0, 0, 4, int.MaxValue }; //ForeColor, BackColor, Symbol, Score
  638.  
  639.             for (int rChar = rList.Length; rChar > 0; rChar--)
  640.             {
  641.                 for (int cFore = 0; cFore < cTable.Length; cFore++)
  642.                 {
  643.                     for (int cBack = 0; cBack < cTable.Length; cBack++)
  644.                     {
  645.                         int R = (cTable[cFore].R * rChar + cTable[cBack].R * (rList.Length - rChar)) / rList.Length;
  646.                         int G = (cTable[cFore].G * rChar + cTable[cBack].G * (rList.Length - rChar)) / rList.Length;
  647.                         int B = (cTable[cFore].B * rChar + cTable[cBack].B * (rList.Length - rChar)) / rList.Length;
  648.                         int iScore = (cValue.R - R) * (cValue.R - R) + (cValue.G - G) * (cValue.G - G) + (cValue.B - B) * (cValue.B - B);
  649.                         if (!(rChar > 1 && rChar < 4 && iScore > 50000)) // rule out too weird combinations
  650.                         {
  651.                             if (iScore < bestHit[3])
  652.                             {
  653.                                 bestHit[3] = iScore; //Score
  654.                                 bestHit[0] = cFore;  //ForeColor
  655.                                 bestHit[1] = cBack;  //BackColor
  656.                                 bestHit[2] = rChar;  //Symbol
  657.                             }
  658.                         }
  659.                     }
  660.                 }
  661.             }
  662.             Console.ForegroundColor = (ConsoleColor)bestHit[0];
  663.             Console.BackgroundColor = (ConsoleColor)bestHit[1];
  664.             Console.Write(rList[bestHit[2] - 1]);
  665.         }
  666.  
  667.         public static void ConsoleWriteImage(System.Drawing.Bitmap source)
  668.         {
  669.             if (LOG_ONLY_MODE)
  670.             {
  671.                 return;
  672.             }
  673.             int sMax = 39;
  674.             decimal percent = Math.Min(decimal.Divide(sMax, source.Width), decimal.Divide(sMax, source.Height));
  675.             System.Drawing.Size dSize = new System.Drawing.Size((int)(source.Width * percent), (int)(source.Height * percent));
  676.             System.Drawing.Bitmap bmpMax = new System.Drawing.Bitmap(source, dSize.Width * 2, dSize.Height);
  677.             for (int i = 0; i < dSize.Height; i++)
  678.             {
  679.                 for (int j = 0; j < dSize.Width; j++)
  680.                 {
  681.                     ConsoleWritePixel(bmpMax.GetPixel(j * 2, i));
  682.                     ConsoleWritePixel(bmpMax.GetPixel(j * 2 + 1, i));
  683.                 }
  684.                 System.Console.WriteLine();
  685.             }
  686.             Console.ResetColor();
  687.         }
  688.         #endregion
  689.  
  690.         #endregion
  691.  
  692.         #region Async tasks
  693.         public async Task LoadModules()
  694.         {
  695.             cmdsvr = new CommandService();
  696.             serviceCollection = serviceCollection.AddSingleton(_client);
  697.             serviceCollection = serviceCollection.AddSingleton(cmdsvr);
  698.  
  699.             foreach (string item in Directory.EnumerateFiles("CMDModules","*.dll",SearchOption.TopDirectoryOnly))
  700.             {
  701.                 LogToConsole(new LogMessage(LogSeverity.Info,"Modules", $"Adding commands from module library: {item}"));
  702.                 try
  703.                 {
  704.                     Assembly asmb = Assembly.LoadFile(Path.GetFullPath(item));
  705.                     string serviceFilename = $"CMDModules\\services.{Path.GetFileNameWithoutExtension(item)}.ini";
  706.                     string servicefilePath = Path.GetFullPath(serviceFilename);
  707.                     if(File.Exists(servicefilePath))
  708.                     {
  709.                         INIFile serviceFile = new INIFile(servicefilePath);
  710.                         foreach (INIEntry entryitem in serviceFile.GetCategoryByName("Services").Entries)
  711.                         {
  712.                             string typename = entryitem.GetAsString();
  713.                             LogToConsole(new LogMessage(LogSeverity.Info,"Modules", $"Injecting service: {typename} from {asmb.GetName().Name}"));
  714.                             serviceCollection = serviceCollection.AddSingleton(asmb.GetType(typename));
  715.                         }
  716.                     }
  717.                     await cmdsvr.AddModulesAsync(asmb);//ADD EXTERNAL.
  718.                 }
  719.                 catch (Exception ex)
  720.                 {
  721.                     Program.LogToConsole(new LogMessage(LogSeverity.Error, "CritERR",ex.Message,ex));
  722.  
  723.                     using (FileStream fs = new FileStream("ERRORS.LOG", FileMode.Append))
  724.                     {
  725.                         using (StreamWriter sw = new StreamWriter(fs))
  726.                         {
  727.  
  728.                             sw.WriteLine(DateTime.Today.ToString("MM/dd/yyyy") + "   " + ex.ToString());
  729.                             sw.Flush();
  730.  
  731.                         }
  732.                     }
  733.                 }
  734.             }
  735.             services = serviceCollection.BuildServiceProvider();
  736.             //check cfg for disabled core.
  737.             if(MainCFG.GetCategoryByName("Application").CheckForEntry("disableCore"))
  738.             {
  739.                 if(MainCFG.GetCategoryByName("Application").GetEntryByName("disableCore").GetAsBool())
  740.                 {
  741.                     LogToConsole(new LogMessage(LogSeverity.Warning,"Program", "RMSoftware.ModularBOT CORE was disabled in the configuration."));
  742.                     LogToConsole(new LogMessage(LogSeverity.Warning,"Program", "You will not be able to manage existing commands, nor add new ones, via discord."));
  743.                     return;//DO NOT LOAD CORE IF THIS IS TRUE.
  744.                 }
  745.             }
  746.             await cmdsvr.AddModulesAsync(Assembly.GetEntryAssembly());//ADD CORE.
  747.         }
  748.  
  749.         public async Task MainAsync(string token)
  750.         {
  751.             try
  752.             {
  753.                 ConsoleGUIReset(ConsoleColor.White, ConsoleColor.DarkBlue, "Application Running");
  754.  
  755.                 _client = new DiscordSocketClient();
  756.                 _client.Log += Log;
  757.                 serviceCollection = new ServiceCollection();
  758.  
  759.                 _client.Ready += _ClientReady;
  760.                 _client.Connected += _client_Connected;
  761.                 _client.MessageReceived += _client_MessageReceived;
  762.                 _client.Disconnected += _client_Disconnected;
  763.  
  764.                 await LoadModules();//ADD CORE AND EXTERNAL MODULES
  765.                 await _client.LoginAsync(TokenType.Bot, token);
  766.                 await _client.StartAsync();
  767.             }
  768.             catch (Exception ex)
  769.             {
  770.                 CriticalError = true;
  771.                 RestartRequested = true;
  772.                 crashException = ex;
  773.                 using (FileStream fs = File.Create("CRASH.LOG"))
  774.                 {
  775.                     using (StreamWriter sw = new StreamWriter(fs))
  776.                     {
  777.                         LogMessage m = new LogMessage(LogSeverity.Critical, "Exception", crashException.Message, crashException);
  778.                         sw.WriteLine(m.ToString());
  779.                         List<string> restart_args = new List<string>();
  780.                         restart_args.AddRange(ARGS);
  781.                         if (!restart_args.Contains("-crashed"))
  782.                         {
  783.                             restart_args.Add("-crashed");
  784.                         }
  785.                         ARGS = restart_args.ToArray();
  786.                         sw.Flush();
  787.                     }
  788.                 }
  789.                 using (FileStream fs = new FileStream("ERRORS.LOG", FileMode.Append))
  790.                 {
  791.                     using (StreamWriter sw = new StreamWriter(fs))
  792.                     {
  793.  
  794.                         sw.WriteLine(DateTime.Today.ToString("MM/dd/yyyy") + "   " + ex.ToString());
  795.                         sw.Flush();
  796.  
  797.                     }
  798.                 }
  799.             }
  800.                    
  801.         }
  802.  
  803.         private Task _client_Connected()
  804.         {
  805.             StartTime = DateTime.Now;
  806.             LogToConsole(new LogMessage(LogSeverity.Info,"Uptime", "Reset uptime to ALL zero."));
  807.             Console.Title = "RMSoftware.ModularBOT -> " + _client.CurrentUser.Username + " | Connected to " + _client.Guilds.Count + " guilds.";
  808.             return Task.Delay(1);
  809.         }
  810.  
  811.         private Task _client_Disconnected(Exception arg)
  812.         {
  813.             LogToConsole(new LogMessage(LogSeverity.Warning,"Session", "Disconnected: "+ arg.Message,arg));
  814.             Console.Title = "RMSoftware.ModularBot - Disconnected";
  815.             LogToConsole(new LogMessage(LogSeverity.Info,"Uptime", "The client is disconnected."));
  816.            
  817.             return Task.Delay(3);
  818.         }
  819.  
  820.         private async Task _ClientReady()
  821.         {
  822.             await Log(new LogMessage(LogSeverity.Info, "TaskMgr", "Running Onstart.bcmd - task"));
  823.             await Task.Run(new Action(OffloadReady));
  824.             Console.Title = "RMSoftware.ModularBOT -> " + _client.CurrentUser.Username + " | Connected to " + _client.Guilds.Count + " guilds.";
  825.          
  826.         }
  827.  
  828.         private async void OffloadReady()
  829.         {
  830.             try
  831.             {
  832.                 if (!BCMDStarted)
  833.                 {
  834.                     await _client.SetStatusAsync(UserStatus.DoNotDisturb);
  835.                     //PROCESS THE AutoEXEC file
  836.                     ulong id = MainCFG.GetCategoryByName("Application").GetEntryByName("botChannel").GetAsUlong();
  837.                     using (StreamReader fs = File.OpenText("OnStart.bcmd"))
  838.                     {
  839.                         while (!fs.EndOfStream)
  840.                         {
  841.                             string line = await fs.ReadLineAsync();
  842.                             if (!string.IsNullOrWhiteSpace(line))
  843.                             {
  844.                                 if (!line.StartsWith(@"\\"))
  845.                                 {
  846.                                     IGuildChannel ch = _client.GetChannel(id) as IGuildChannel;
  847.                                     //line = line.Replace("%p_", CommandPrefix.ToString());
  848.                                     if (CRASH)
  849.                                     {
  850.                                         ConsoleColor last = Console.BackgroundColor;
  851.                                         Console.BackgroundColor = ConsoleColor.DarkRed;
  852.                                         LogToConsole(new LogMessage(LogSeverity.Warning,"Program", "The program was auto-restarted due to a crash. Please see CRASH.LOG for details on what happened."));
  853.                                         Console.BackgroundColor = last;
  854.                                         await ((IMessageChannel)ch).SendMessageAsync("**WARNING:** `The bot was auto-restarted due to a crash. Please see CRASH.LOG for details on what happened.`");
  855.                                         CRASH = false;//don't make it happen more than once pls.
  856.                                     }
  857.                                     if (!line.StartsWith("%p_"))
  858.                                     {
  859.  
  860.                                         await ((IMessageChannel)ch).SendMessageAsync(line);
  861.                                     }
  862.                                     else
  863.                                     {
  864.  
  865.  
  866.                                         line = line.Replace("%p_", CommandPrefix.ToString());
  867.                                         if (await ccmg.Process(new PsuedoMessage(line, _client.CurrentUser, ch, MessageSource.User)))
  868.                                         {
  869.                                             LogToConsole(new LogMessage(LogSeverity.Info,"OnStart", line));
  870.                                             LogToConsole(new LogMessage(LogSeverity.Info, "OnStart", "CustomCMD Success..."));
  871.                                             continue;
  872.                                         }
  873.                                         //Damn, I can't be sassy here... If it was a command, but not a ccmg command, then try the context for modules. If THAT didn't work
  874.                                         //Then it will output the result of the context.
  875.                                         var context = new CommandContext(_client, new PsuedoMessage(line,_client.CurrentUser,ch,MessageSource.User));
  876.                                         // Execute the command. (result does not indicate a return value,
  877.                                         // rather an object stating if the command executed successfully)
  878.                                         var result = await cmdsvr.ExecuteAsync(context, 1, services);
  879.                                         LogToConsole(new LogMessage(LogSeverity.Info,"OnStart", line));
  880.                                         LogToConsole(new LogMessage(LogSeverity.Info,"OnStart", result.ToString()));
  881.                                     }
  882.                                     await Task.Delay(250);
  883.                                 }
  884.                             }
  885.                         }
  886.                     }
  887.                     BCMDStarted = true;
  888.                     await _client.SetGameAsync("READY!");
  889.                     LogToConsole(new LogMessage(LogSeverity.Info,"TaskMgr", "Task is complete."));
  890.                     await _client.SetStatusAsync(UserStatus.Online);
  891.                     LogToConsole(new LogMessage(LogSeverity.Info,"TaskMgr", "Running Message Queue - task"));
  892.                     foreach (var item in messageQueue)
  893.                     {
  894.                        
  895.                         await _client_MessageReceived(item);
  896.                         await Task.Delay(500);
  897.                     }
  898.                     LogToConsole(new LogMessage(LogSeverity.Info,"TaskMgr", "Task is complete"));
  899.                 }
  900.             }
  901.             catch (Exception ex)
  902.             {
  903.                 BCMDStarted = false;
  904.                 LogToConsole(new LogMessage(LogSeverity.Error,"CritERR", ex.Message,ex));
  905.  
  906.             }
  907.         }
  908.  
  909.         private async Task _client_MessageReceived(SocketMessage arg)
  910.         {
  911.             if(MessagesDisabled)
  912.             {
  913.                 return;
  914.             }
  915.             if(rolemgt.UserBlacklisted(arg.Author))
  916.             {
  917.                 return;
  918.             }
  919.             #region Console Output debug
  920.             //DEBUG: Output the bot-mentioned chat message to the console
  921.             foreach (SocketUser item in arg.MentionedUsers)
  922.             {
  923.                 if (item.Mention == _client.CurrentUser.Mention)
  924.                 {
  925.                     LogToConsole(new LogMessage(LogSeverity.Info,"Mention", "<[" + arg.Channel.Name + "] " + arg.Author.Username + " >: " + arg.Content));
  926.                 }
  927.             }
  928.             //DEBUG: output ! prefixed messages to console.
  929.             if (arg.Content.StartsWith(CommandPrefix.ToString()))
  930.             {
  931.                 LogToConsole(new LogMessage(LogSeverity.Info,"Command", "<[" + arg.Channel.Name + "] " + arg.Author.Username + " >: " + arg.Content));
  932.  
  933.             }
  934.  
  935.             #endregion
  936.  
  937.             // Don't process the command if it was a System Message
  938.             var message = arg as SocketUserMessage;
  939.             if (message == null) return;
  940.             // Create a number to track where the prefix ends and the command begins
  941.             int argPos = 0;
  942.             // Determine if the message is a command, based on if it starts with 'commandprefix' or a mention prefix. if not, ignore it.
  943.             if (!(message.HasCharPrefix(CommandPrefix, ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos))) return;
  944.             if (!arg.Author.IsBot && !BCMDStarted)
  945.             {
  946.                 messageQueue.Add(arg);  //queue it up. The bcmdStarted check should
  947.                                         //provide PLENTY (if not an excessive amount) of time for modules,and extra commands
  948.                                         //to be fully loaded by the time it is set to true. Preemptively solving the "hey, you just ignored my commands completely"
  949.                                         //when the bot starts and doesn't respond to a command at first
  950.                 return;
  951.             }
  952.             // Create a Command Context for command modules
  953.             //Process CoreCustom commands
  954.             if (await ccmg.Process(arg))
  955.             {
  956.                 return;//If the message contained a custom command from config, No need to continue.
  957.             };
  958.             var context = new CommandContext(_client, message);
  959.             // Execute the command. (result does not indicate a return value,
  960.             // rather an object stating if the command executed successfully)
  961.             var result = await cmdsvr.ExecuteAsync(context, argPos, services);
  962.             //If the result is unsuccessful AND not unknown command, send the error details.
  963.             if (result.Error.HasValue)
  964.             {
  965.                 if (!result.Error.Value.HasFlag(CommandError.UnknownCommand) && !result.IsSuccess)
  966.                 {
  967.                     await arg.Channel.SendMessageAsync(result.ErrorReason);
  968.                 }
  969.                 if (result.Error.Value.HasFlag(CommandError.BadArgCount))
  970.                 {
  971.                     await arg.Channel.SendMessageAsync(result.ErrorReason);
  972.                 }
  973.             }
  974.  
  975.  
  976.         }
  977.  
  978.         private Task Log(LogMessage msg)
  979.         {
  980.             if(!LOG_ONLY_MODE)
  981.             {
  982.                 LogToConsole(msg);
  983.             }
  984.             else
  985.             {
  986.                 Console.WriteLine(JsonConvert.SerializeObject(msg));
  987.             }
  988.             if (msg.Message == "Failed to resume previous session")
  989.             {
  990.                 _client.StopAsync();
  991.                 _client = null;
  992.                 crashException = new Exception("Failed to resume previous session. See ERRORS.LOG for any additional information.");
  993.                 CriticalError = true;
  994.                 discon = true;
  995.                 Thread.Sleep(3000);
  996.             }
  997.             if(msg.Exception != null)
  998.             {
  999.                 using (FileStream fs = new FileStream("ERRORS.LOG",FileMode.Append))
  1000.                 {
  1001.                     using (StreamWriter sw = new StreamWriter(fs))
  1002.                     {
  1003.                        
  1004.                         sw.WriteLine(DateTime.Today.ToString("MM/dd/yyyy")+"   "+msg.ToString());
  1005.                         sw.Flush();
  1006.  
  1007.                     }
  1008.                 }
  1009.             }
  1010.             return Task.Delay(0);
  1011.         }
  1012.  
  1013.  
  1014.         #endregion
  1015.     }
  1016.    
  1017.     #region Retry clause - API error workaround [possibly obsolete] [Stackoverflow.com]
  1018.     public static class Retry
  1019.     {
  1020.         public static void Do(
  1021.             Action action,
  1022.             TimeSpan retryInterval,
  1023.             int maxAttemptCount = 3)
  1024.         {
  1025.             Do<object>(() =>
  1026.             {
  1027.                  action();
  1028.                 return null;
  1029.             }, retryInterval, maxAttemptCount);
  1030.         }
  1031.  
  1032.         public static T Do<T>(
  1033.             Func<T> action,
  1034.             TimeSpan retryInterval,
  1035.             int maxAttemptCount = 3)
  1036.         {
  1037.             var exceptions = new List<Exception>();
  1038.  
  1039.             for (int attempted = 0; attempted < maxAttemptCount; attempted++)
  1040.             {
  1041.                 try
  1042.                 {
  1043.                     if (attempted > 0)
  1044.                     {
  1045.                         Thread.Sleep(retryInterval);
  1046.                     }
  1047.                     return action();
  1048.                 }
  1049.                 catch (Exception ex)
  1050.                 {
  1051.                     exceptions.Add(ex);
  1052.                     Program.LogToConsole(new LogMessage(LogSeverity.Warning,"API_RETRY", ex.Message,ex));
  1053.                     Program.LogToConsole(new LogMessage(LogSeverity.Warning,"API_RETRY", "Retrying " + (maxAttemptCount-attempted) + " more time(s)"));
  1054.                 }
  1055.             }
  1056.             throw new AggregateException(exceptions);
  1057.         }
  1058.     }
  1059.  
  1060.     #endregion
  1061.  
  1062.     #region Advanced Command Processing
  1063.     public class CmdRoleManager
  1064.     {
  1065.         INIFile mgmt;
  1066.         INIFile userBlackList;
  1067.         public CmdRoleManager()
  1068.         {
  1069.             mgmt = new INIFile("cmdMgr.ini");
  1070.             userBlackList = new INIFile("blacklist.ini");
  1071.             if(!userBlackList.CheckForCategory("Blacklist"))
  1072.             {
  1073.                 userBlackList.CreateCategory("Blacklist");
  1074.                 userBlackList.SaveConfiguration();
  1075.             }
  1076.         }
  1077.  
  1078.         public bool AddUserToBlacklist(SocketUser user)
  1079.         {
  1080.             string guildCat = "Blacklist";
  1081.             bool check = userBlackList.GetCategoryByName(guildCat).CheckForEntry(user.Id.ToString());
  1082.             if(!check)
  1083.             {
  1084.                 userBlackList.CreateEntry(guildCat, user.Id.ToString(), user.Username.Replace("=", "_"));
  1085.             }
  1086.             userBlackList.SaveConfiguration();
  1087.             return !check;
  1088.         }
  1089.  
  1090.         public bool DeleteUserFromBlacklist(SocketUser user)
  1091.         {
  1092.             string guildCat = "Blacklist";
  1093.             bool check = userBlackList.GetCategoryByName(guildCat).CheckForEntry(user.Id.ToString());
  1094.             if (check)
  1095.             {
  1096.                 userBlackList.DeleteEntry(guildCat, user.Id.ToString());
  1097.             }
  1098.             userBlackList.SaveConfiguration();
  1099.             return check;
  1100.         }
  1101.  
  1102.         public void AddCommandManagerRole(SocketRole role)
  1103.         {
  1104.             string guildCat = role.Guild.Id.ToString();
  1105.             bool check = mgmt.CheckForCategory(guildCat);
  1106.             int indx = -1;
  1107.             if(check)
  1108.             {
  1109.                 indx = mgmt.GetCategoryByName(guildCat).Entries.Count-1;
  1110.                 mgmt.CreateEntry(guildCat, "role" + (indx + 1), role.Id);
  1111.             }
  1112.             else
  1113.             {
  1114.                 mgmt.CreateCategory(guildCat);
  1115.                 indx = mgmt.GetCategoryByName(guildCat).Entries.Count - 1;
  1116.                 mgmt.CreateEntry(guildCat, "role" + (indx + 1), role.Id);
  1117.             }
  1118.             mgmt.SaveConfiguration();
  1119.         }
  1120.  
  1121.         public bool UserBlacklisted(SocketUser user)
  1122.         {
  1123.             return userBlackList.GetCategoryByName("Blacklist").CheckForEntry(user.Id.ToString());
  1124.         }
  1125.  
  1126.         public string DeleteCommandManager(SocketRole role)
  1127.         {
  1128.             string guildCat = role.Guild.Id.ToString();
  1129.             bool check = mgmt.CheckForCategory(guildCat);
  1130.             int indx = -1;
  1131.             if (check)
  1132.             {
  1133.                 indx = mgmt.GetCategoryByName(guildCat).Entries.Count - 1;
  1134.                 try
  1135.                 {
  1136.                     mgmt.DeleteEntry(guildCat, mgmt.GetCategoryByName(guildCat).Entries.Find(x => x.GetAsUlong() == role.Id).Name);
  1137.                     //Then get all entries and rename them.
  1138.  
  1139.                     for (int i = 0; i < mgmt.GetCategoryByName(guildCat).Entries.Count; i++)
  1140.                     {
  1141.                         mgmt.GetCategoryByName(guildCat).Entries[i].Name = $"role{i}";
  1142.                     }
  1143.                 }
  1144.                 catch (Exception ex)
  1145.                 {
  1146.  
  1147.                     return ex.Message;
  1148.                 }
  1149.                
  1150.             }
  1151.             else
  1152.             {
  1153.                 return "No results. The guild ID didn't exist in the database.";
  1154.             }
  1155.             mgmt.SaveConfiguration();
  1156.             return "Command Manager database updated.";
  1157.         }
  1158.  
  1159.         public bool CheckUserRole(SocketGuildUser user)
  1160.         {
  1161.             string guildcat = user.Guild.Id.ToString();//if the category does not exist, return false... can't have that;
  1162.             if(!mgmt.CheckForCategory(guildcat))
  1163.             {
  1164.                 return false;
  1165.             }
  1166.             foreach (var role in user.Roles)
  1167.             {
  1168.                 ulong id = role.Id;
  1169.                 if (mgmt.GetCategoryByName(guildcat).Entries.Exists(x => x.GetAsUlong() == id))
  1170.                 {
  1171.                     return true;//keep doing it until it returns true.
  1172.                 }
  1173.             }
  1174.             return false;//default;
  1175.         }
  1176.  
  1177.         public SocketRole[] GetRolesForGuild(SocketGuild guild)
  1178.         {
  1179.             List<SocketRole> items = new List<SocketRole>();
  1180.             string guildcat = guild.Id.ToString();
  1181.             if (!mgmt.CheckForCategory(guildcat))
  1182.             {
  1183.                 return null;
  1184.             }
  1185.             foreach (var item in mgmt.GetCategoryByName(guildcat).Entries)
  1186.             {
  1187.                 items.Add(guild.GetRole(item.GetAsUlong()));
  1188.             }
  1189.             return items.ToArray();
  1190.         }
  1191.  
  1192.         public SocketRole[] GetAllRoles()
  1193.         {
  1194.             List<SocketRole> items = new List<SocketRole>();
  1195.             foreach (var itemc in mgmt.Categories)
  1196.             {
  1197.                 foreach (var item in itemc.Entries)
  1198.                 {
  1199.                     items.Add(Program._client.GetGuild(Convert.ToUInt64(itemc.Name)).GetRole(item.GetAsUlong()));
  1200.                 }
  1201.             }
  1202.             return items.ToArray();
  1203.         }
  1204.     }
  1205.     public class PsuedoMessage : IMessage, IUserMessage
  1206.     {
  1207.         string _content = "";
  1208.         SocketUser _author;
  1209.         IGuildChannel _c;
  1210.         MessageSource _source;
  1211.         MessageType _type;
  1212.         public PsuedoMessage(string content,SocketUser author,IGuildChannel ch ,MessageSource source)
  1213.         {
  1214.             _content = content;
  1215.             _author = author;
  1216.             _c = ch;
  1217.             _source = source;
  1218.             _type = MessageType.Default;
  1219.         }
  1220.  
  1221.  
  1222.         IReadOnlyCollection<IAttachment> IMessage.Attachments
  1223.         {
  1224.             get;
  1225.         }
  1226.  
  1227.         IUser IMessage.Author
  1228.         {
  1229.             get { return _author; }
  1230.         }
  1231.  
  1232.         IMessageChannel IMessage.Channel
  1233.         {
  1234.             get { return _c as IMessageChannel; }
  1235.         }
  1236.  
  1237.         string IMessage.Content
  1238.         {
  1239.             get { return _content; }
  1240.         }
  1241.  
  1242.         DateTimeOffset ISnowflakeEntity.CreatedAt
  1243.         {
  1244.             get;
  1245.         }
  1246.  
  1247.         DateTimeOffset? IMessage.EditedTimestamp
  1248.         {
  1249.             get;
  1250.         }
  1251.  
  1252.         IReadOnlyCollection<IEmbed> IMessage.Embeds
  1253.         {
  1254.             get;
  1255.         }
  1256.  
  1257.         ulong IEntity<ulong>.Id
  1258.         {
  1259.             get { return (ulong)new Random().Next(0,int.MaxValue); }
  1260.         }
  1261.  
  1262.         bool IMessage.IsPinned
  1263.         {
  1264.             get { return false; }
  1265.         }
  1266.  
  1267.         bool IMessage.IsTTS
  1268.         {
  1269.             get { return false; }
  1270.         }
  1271.  
  1272.         IReadOnlyCollection<ulong> IMessage.MentionedChannelIds
  1273.         {
  1274.             get;
  1275.         }
  1276.  
  1277.         IReadOnlyCollection<ulong> IMessage.MentionedRoleIds
  1278.         {
  1279.             get;
  1280.         }
  1281.  
  1282.         IReadOnlyCollection<ulong> IMessage.MentionedUserIds
  1283.         {
  1284.             get;
  1285.         }
  1286.  
  1287.         MessageSource IMessage.Source
  1288.         {
  1289.             get { return _source; }
  1290.         }
  1291.  
  1292.         IReadOnlyCollection<ITag> IMessage.Tags
  1293.         {
  1294.             get;
  1295.         }
  1296.  
  1297.         DateTimeOffset IMessage.Timestamp
  1298.         {
  1299.             get;
  1300.         }
  1301.  
  1302.         MessageType IMessage.Type
  1303.         {
  1304.             get { return _type; }
  1305.         }
  1306.  
  1307.         public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions
  1308.         {
  1309.             get
  1310.             {
  1311.                 throw new NotImplementedException();
  1312.             }
  1313.         }
  1314.  
  1315.         Task IDeletable.DeleteAsync(RequestOptions options)
  1316.         {
  1317.             return Task.Delay(0);
  1318.         }
  1319.  
  1320.         public Task ModifyAsync(Action<MessageProperties> func, RequestOptions options = null)
  1321.         {
  1322.             throw new NotImplementedException();
  1323.         }
  1324.  
  1325.         public Task PinAsync(RequestOptions options = null)
  1326.         {
  1327.             throw new NotImplementedException();
  1328.         }
  1329.  
  1330.         public Task UnpinAsync(RequestOptions options = null)
  1331.         {
  1332.             throw new NotImplementedException();
  1333.         }
  1334.  
  1335.         public Task AddReactionAsync(IEmote emote, RequestOptions options = null)
  1336.         {
  1337.             throw new NotImplementedException();
  1338.         }
  1339.  
  1340.         public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null)
  1341.         {
  1342.             throw new NotImplementedException();
  1343.         }
  1344.  
  1345.         public Task RemoveAllReactionsAsync(RequestOptions options = null)
  1346.         {
  1347.             throw new NotImplementedException();
  1348.         }
  1349.  
  1350.         public Task<IReadOnlyCollection<IUser>> GetReactionUsersAsync(string emoji, int limit = 100, ulong? afterUserId = default(ulong?), RequestOptions options = null)
  1351.         {
  1352.             throw new NotImplementedException();
  1353.         }
  1354.  
  1355.         public string Resolve(TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name, TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name)
  1356.         {
  1357.             throw new NotImplementedException();
  1358.         }
  1359.     }
  1360.  
  1361.     #endregion
  1362. }
Advertisement
Add Comment
Please, Sign In to add comment