public async Task MainAsync()
        {
            services = new ServiceCollection().BuildServiceProvider();

            await rABotLog(LogSeverity.Info, "Reading configuration files.");

            #region Process configurations
            string _Result = ProcessConfig();
            if (!String.IsNullOrEmpty(_Result))
            {
                await rABotLog(LogSeverity.Critical, "Configuration file " + _Result + " is missing."); // ERROR_OPEN_FAILED

                Environment.Exit(1);
            }
            #endregion
            else
            {
                await rABotLog(LogSeverity.Info, "Done reading configuration files.");

                Console.Title = Config.ConsoleTitle;

                DpService = new DivinePrideService
                {
                    BaseUrl = Config.DivinePrideBaseUrl,
                    ApiKey  = Config.DivinePrideApiKey
                };

                discord      = new DiscordSocketClient();
                discord.Log += Log;

                #region Restrict bot to rAthena server
                discord.JoinedGuild += async(server) =>
                {
                    if (server.Id != Config.ServerId)
                    {
                        await server.LeaveAsync();
                    }
                    else
                    {
                        foreach (var chanStr in Config.Channels)
                        {
                            var channel = server.TextChannels.FirstOrDefault((e) => e.Name.Equals(chanStr.Value));
                            if (channel == null)
                            {
                                await rABotLog(LogSeverity.Critical, chanStr.Value + " channel doesn't exists. Exiting...");

                                Environment.Exit(1);
                            }
                        }

                        await Channels["General"].SendMessageAsync("Test message please ignore. Testing CygnusBot for .NET Core");
                    }
                };
                #endregion

                #region Discord Events - UserJoined
                discord.UserJoined += async(user) =>
                {
                    await Channels["General"].SendMessageAsync("Hello " + user.Mention + ", welcome to rAthena Discord." + Environment.NewLine +
                                                               "Kindly read the " + Channels["Rules"].Mention + " before you start posting. Thank you.");
                };
                #endregion

                #region Register Commands
                commands = new CommandService();
                discord.MessageReceived += HandleCommand;
                discord.MessageReceived += HandleVoldemulator;
                await commands.AddModulesAsync(Assembly.GetEntryAssembly());

                #endregion

                await ScriptHelpCommand.RefreshScriptCommandsTxt();

                if (!(await ScriptHelpCommand.ProcessScriptCommands()))
                {
                    await Log(new LogMessage(LogSeverity.Warning, "rAthenaBot", "Script command process failed. Script command help will not be available!"));
                }

                #region RSS Timer

                /*TimerRSS.Interval = RSSConfig.RefreshInterval;
                 * TimerRSS.AutoReset = RSSConfig.AutoReset;
                 * TimerRSS.Enabled = RSSConfig.Enabled;
                 * TimerRSS.Elapsed += new ElapsedEventHandler(OnCheckRSSFeed);
                 * TimerRSS.Start();*/
                #endregion

                instance = this;
                await discord.LoginAsync(TokenType.Bot, Config.DiscordToken);

                await discord.StartAsync();

                await discord.SetGameAsync(Config.PrefixChar + "help", "https://www.rAthena.org", StreamType.NotStreaming);

                await discord.SetStatusAsync(UserStatus.Online);

                await Task.Delay(-1);
            }
        }
        public rAthenaBot()
        {
            Console.WriteLine("Reading configuration files.");
            #region Process configurations
            string _Result = ProcessConfig();
            if (!String.IsNullOrEmpty(_Result))
            {
                FatalError("Configuration file " + _Result + " is missing.", 0x6E); // ERROR_OPEN_FAILED
            }
            #endregion
            else
            {
                Console.WriteLine("Done reading configuration files.");
                Console.Title = Config.ConsoleTitle;

                DpService = new DivinePrideService {
                    BaseUrl = Config.DivinePrideBaseUrl,
                    ApiKey  = Config.DivinePrideApiKey
                };

                discord = new DiscordClient(x =>
                {
                    x.LogLevel   = LogSeverity.Info;
                    x.LogHandler = Log;
                });

                #region Discord Events - UserJoined
                discord.UserJoined += async(s, e) =>
                {
                    if (e.Server.Name.Equals(Config.ServerName))
                    {
                        Channel channel = e.Server.FindChannels(Config.Channels["General"]).FirstOrDefault();
                        if (channel != null)
                        {
                            await channel.SendMessage("Hello " + e.User.Mention + ", welcome to " + Config.ServerName + " Discord." + Environment.NewLine +
                                                      "Kindly read the " + e.Server.FindChannels(Config.Channels["Rules"], ChannelType.Text).FirstOrDefault().Mention + " before you start posting. Thank you.");
                        }
                    }
                };
                #endregion

                #region Register Commands
                discord.UsingCommands(x =>
                {
                    x.PrefixChar         = Config.PrefixChar.ElementAt(0);
                    x.HelpMode           = HelpMode.Public;
                    x.AllowMentionPrefix = Config.AllowMentionPrefix;
                });

                commands = discord.GetService <CommandService>();
                #endregion

                #region List of Commands

                #region Command - stats
                commands.CreateCommand("stats")
                .Description("This command will return the stats of rAthena Discord. ```Usage: /stats```")
                .Alias(new string[] { "stat", "status" })
                .Parameter("args", ParameterType.Unparsed)
                .Do(async(e) =>
                {
                    string msg = "**rAthena Discord Stat**:" + System.Environment.NewLine
                                 + "```"
                                 + "Region - " + e.Server.Region.Name + System.Environment.NewLine
                                 + System.Environment.NewLine
                                 + "Total Users - " + e.Channel.Server.Users.Where(x => x.IsBot == false).Count() + System.Environment.NewLine
                                 + System.Environment.NewLine
                                 + "Total Bots - " + e.Channel.Server.Users.Where(x => x.IsBot == true).Count() + System.Environment.NewLine
                                 + "Total Online Bots - " + e.Channel.Server.Users.Where(x => x.IsBot == true && x.Status != UserStatus.Offline).Count() + System.Environment.NewLine
                                 + "Total Offline Bots - " + e.Channel.Server.Users.Where(x => x.IsBot == true && x.Status == UserStatus.Offline).Count() + System.Environment.NewLine
                                 + System.Environment.NewLine
                                 + "Total Channels - " + e.Server.ChannelCount + System.Environment.NewLine
                                 + "Total Text Channels - " + e.Server.TextChannels.Count() + System.Environment.NewLine
                                 + "Total Voice Channels - " + e.Server.VoiceChannels.Count() + System.Environment.NewLine
                                 + "```";
                    await e.Channel.SendMessage(msg);
                });
                #endregion

                #region Command - Search
                commands.CreateCommand("search")
                .Description("This command will search for contents at rAthena forum. ```Usage: /search <content>```")
                .Alias(new string[] { "find", "google" })
                .Parameter("args", ParameterType.Multiple)
                .Do(async(e) =>
                {
                    if (e.Args.Length <= 0)
                    {
                        await e.Channel.SendMessage(e.Command.Description);
                    }
                    else
                    {
                        string query = String.Join("%20", e.Args.ToList());
                        string url   = "https://rathena.org/board/search/?&q=" + query;
                        await e.Channel.SendMessage("Search result: `" + String.Join(" ", e.Args.ToList()) + "`" + System.Environment.NewLine + url);
                    }
                });
                #endregion

                #region Command - Purge
                commands.CreateCommand("purge")
                .Hide()
                .Description("This command will remove some Chat Log. ```Usage: /purge <amount> <@mention>```")
                .Alias(new string[] { "remove", "clean", "delete" })
                .Parameter("arg", ParameterType.Multiple)
                .Do(async(e) =>
                {
                    if (e.User.Roles.Any(x => x.Permissions.ManageMessages == true))
                    {
                        if (e.Args.Length < 1)
                        {
                            await e.Channel.SendMessage(e.Command.Description);
                        }
                        else
                        {
                            int amount    = Convert.ToInt16(e.Args[0]) + 1;
                            string author = string.Empty;
                            if (e.Args.Length > 1)
                            {
                                author = String.Join(" ", e.Args.Skip(1).ToList());
                            }
                            if (amount > 0)
                            {
                                Message[] msg;
                                msg = await e.Channel.DownloadMessages(amount);
                                if (!String.IsNullOrEmpty(author))
                                {
                                    msg = msg.Where(x => x.User.Mention.Equals(author)).ToArray();
                                }
                                await e.Channel.DeleteMessages(msg);
                            }
                        }
                    }
                    else
                    {
                        await e.Channel.SendIsTyping();
                        await e.Channel.SendMessage("Invalid Command");
                    }
                });
                #endregion

                #region Command - WhoIs
                commands.CreateCommand("whois")
                .Description("This command will return information of user. ```Usage: /whois <@mention>```")
                .Alias(new string[] { "who", "profile", "check" })
                .Parameter("arg", ParameterType.Multiple)
                .Do(async(e) =>
                {
                    string username = String.Empty;
                    User user       = null;
                    if (e.Args.Length == 0)
                    {
                        user = e.Channel.FindUsers(e.User.Name, true).FirstOrDefault();
                    }
                    else
                    {
                        username = String.Join(" ", e.Args).Trim();
                        if (username.Contains("@"))
                        {
                            user = e.Channel.Users.FirstOrDefault(x => x.Mention == username);
                        }
                        else
                        {
                            user = e.Channel.FindUsers(username).FirstOrDefault();
                        }
                    }

                    await e.Channel.SendIsTyping();
                    if (user == null)
                    {
                        await e.Channel.SendMessage("User : '******' not found.");
                    }
                    else
                    {
                        string msg = "```"
                                     + "Name: " + user.Name + " (" + user.ToString() + ")" + System.Environment.NewLine
                                     + "Role: " + String.Join(",", user.Roles.Select(x => x.Name)) + System.Environment.NewLine
                                     + "Joined Since: " + user.JoinedAt + System.Environment.NewLine
                                     + "Last Activity: " + user.LastActivityAt + System.Environment.NewLine
                                     + "Last Online At: " + user.LastOnlineAt + System.Environment.NewLine
                                     //+ "Status: " + user.Status + System.Environment.NewLine
                                     + "```";
                        await e.Channel.SendMessage(msg);
                    }
                });
                #endregion

                #region Command - Divine-Pride to rAthena Monster DB
                #region ramob
                commands.CreateCommand("ramob")
                .Description("This command will return information of a monster in rAthena's mob_db.txt format. ```Usage: /ramob <MonsterID>```")
                .Parameter("arg", ParameterType.Required)
                .Do(async(e) =>
                {
                    int id = Convert.ToInt32(e.Args[0]);
                    await e.Channel.SendIsTyping();
                    if (id <= 0)
                    {
                        await e.Channel.SendMessage(e.Command.Description);
                    }
                    else
                    {
                        Monster mob = DpService.GetMonster(id);
                        if (mob == null)
                        {
                            await e.Channel.SendMessage("Can't retrieve monster info from divine-pride. Either mob-id doesn't exist or divine-pride is down.");
                        }
                        else
                        {
                            await e.Channel.SendMessage("`" + mob.ToString() + "`");
                        }
                    }
                });
                #endregion

                #region Command - mobinfo
                commands.CreateCommand("mobinfo")
                .Description("This command will return information of a monster. ```Usage: /mobinfo <MonsterID>```")
                .Alias(new string[] { "mi", "mobdb", "mobinfo" })
                .Parameter("arg", ParameterType.Required)
                .Do(async(e) =>
                {
                    int id = Convert.ToInt32(e.Args[0]);
                    await e.Channel.SendIsTyping();
                    if (id <= 0)
                    {
                        await e.Channel.SendMessage(e.Command.Description);
                    }
                    else
                    {
                        Monster mob = DpService.GetMonster(id);
                        if (mob == null)
                        {
                            await e.Channel.SendMessage("Can't retrieve monster info from divine-pride. Either mob-id doesn't exist or divine-pride is down.");
                        }
                        else
                        {
                            string template = "Monster info for monster **{0} ({1})** :" + Environment.NewLine +
                                              "Stats: Lv:{2} HP:{3} SP:{4} STR:{5} AGI:{6} VIT:{7} INT:{8} DEX:{9} LUK:{10}" + Environment.NewLine +
                                              "Attack: {11}-{12} Def:{13} Mdef:{14} Exp:{15} JobExp:{16} Hit:{17} Flee:{18}" + Environment.NewLine +
                                              "Race:{19} Size:{20} Element:{21} MVP:{22}" + Environment.NewLine +
                                              "**Drops**: WIP";
                            await e.Channel.SendMessage(string.Format(template, mob.name, mob.kROName, mob.stats.level, mob.stats.health, mob.stats.sp,
                                                                      mob.stats.str, mob.stats.agi, mob.stats.vit, mob.stats.Int, mob.stats.dex, mob.stats.luk, mob.stats.attack["minimum"], mob.stats.attack["maximum"],
                                                                      mob.stats.defense, mob.stats.magicDefense, mob.stats.baseExperience, mob.stats.jobExperience, mob.stats.hit, mob.stats.flee, Monster.Idx2Race(mob.stats.race), Monster.Idx2Size(mob.stats.scale),
                                                                      "WIP", mob.stats.mvp == 1 ? "Yes" : "No")); // TODO : Implement Element
                        }
                    }
                });
                #endregion
                #endregion

                #region Command - Divine-Pride to rAthena Item DB
                commands.CreateCommand("raitem")
                .Alias(new string[] { "ii", "itemdb" })
                .Description("This command will return information of an item in rAthena's item_db.txt format. ```Usage: /raitem <Item ID>```")
                .Parameter("arg", ParameterType.Required)
                .Do(async(e) =>
                {
                    int nameid = Convert.ToInt32(e.Args[0]);
                    await e.Channel.SendIsTyping();
                    if (nameid <= 0)
                    {
                        await e.Channel.SendMessage(e.Command.Description);
                    }
                    else
                    {
                        Item item = DpService.GetItem(nameid);
                        if (item == null)
                        {
                            await e.Channel.SendMessage("Can't retrieve item info from divine-pride. Either item-id doesn't exist or divine-pride is down.");
                        }
                        else
                        {
                            await e.Channel.SendMessage("`" + item.ToString() + "`");
                        }
                    }
                });
                #endregion

                #region Command - Member
                commands.CreateCommand("emistry")
                .Do(async(e) =>
                {
                    await e.Channel.SendMessage("ZzzzZzzZzzZZZzzzzZZzzzzz...");
                    await e.Channel.SendFile(@"img\emistry.gif");
                });
                commands.CreateCommand("aleos")
                .Do(async(e) =>
                {
                    await e.Channel.SendFile(@"img\aleos.gif");
                });
                commands.CreateCommand("akkarin")
                .Do(async(e) =>
                {
                    await e.Channel.SendFile(@"img\akkarin.gif");
                });
                #endregion

                #region Command - Script command documentation
                if (ProcessScriptCommands())
                {
                    commands.CreateCommand("script")
                    .Description("View rAthena script command documentation.")
                    .Parameter("name", ParameterType.Required)
                    .Do(async(e) =>
                    {
                        ScriptCommand cmd = scriptCommands.FirstOrDefault(x => x.Name.Equals(e.Args[0], StringComparison.CurrentCultureIgnoreCase));
                        if (cmd == null)
                        {
                            await e.Channel.SendMessage("Command not found.");
                        }
                        else
                        {
                            string desc = "```";
                            foreach (string x in cmd.Descriptions)
                            {
                                desc += x + Environment.NewLine;
                            }
                            await e.Channel.SendMessage(desc + "```");
                        }
                    });
                }
                #endregion
                #endregion

                #region RSS Timer
                TimerRSS.Interval  = RSSConfig.RefreshInterval;
                TimerRSS.AutoReset = RSSConfig.AutoReset;
                TimerRSS.Enabled   = RSSConfig.Enabled;
                TimerRSS.Elapsed  += new ElapsedEventHandler(OnCheckRSSFeed);
                TimerRSS.Start();
                #endregion

                instance = this;
                discord.ExecuteAndWait(async() =>
                {
                    try
                    {
                        await discord.Connect(Config.DiscordToken, TokenType.Bot);
                        discord.SetGame("rAthena", GameType.Default, "www.rAthena.org");
                        discord.SetStatus(UserStatus.Online);
                    }
                    catch (HttpException e)
                    {
                        FatalError("HTTP Error : " + e.Message);
                    }
                });
            }
        }