internal static void Main(string[] args)
        {
            var a = Assembly.GetExecutingAssembly();
            var l = a.Location;

            Location   = Path.GetDirectoryName(l);
            Assemblies = new Dictionary <string, Assembly>();

            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

            l = Path.Combine(Location, "v2_lib");
            if (Directory.Exists(l))
            {
                var ls = Directory.GetFiles(l, "*.dll", SearchOption.TopDirectoryOnly);
                foreach (var xl in ls)
                {
                    try
                    {
                        var xa = Assembly.Load(File.ReadAllBytes(xl));
                        Assemblies.Add(xa.FullName, xa);
                    }
                    catch (Exception ex) { Console.WriteLine("CRITICAL: Could not load {0}: {2}/{1}", xl, ex.Message, ex.GetType().ToString()); }
                }
            }
            else
            {
                Console.WriteLine("CRITICAL: v2_lib does not exist");
            }

            L.D(Debugger.IsAttached);
            L.R(Console.Out);
            L.W("ACB v2", "Initializing");
            L.W("ACB v2", "Running from \"{0}\"", Location);

            L.W("ACB v2", "Parsing commandline");
            var cmdl = ParseCommandline(args);

            L.W("ACB v2", "Options:");
            L.W("ACB v2", "  Override: {0}", cmdl.Target);
            L.W("ACB v2", "  Single: {0}", cmdl.SingleId);

            L.W("STOA Lib", "Initializing STO Academy tools");
            var tools = new StoAcademyTools();

            tools.Initialize();

            L.W("ACB-HTTP", "Initializing HTTP component");
            var http = new HttpRequestBuilder();

            http.UserAgent = "linux:stoap:2 (by /u/eMZi0767)";

            L.W("ACB-REDDIT", "Initializing Reddit component");
            var reddit = new RedditApi(http);

            reddit.Initialize();

            L.W("ACB-REDDIT", "Querying STOBuilds");
            var posts    = reddit.QueryPosts();
            var comments = reddit.QueryComments();

            L.W("ACB v2", "Checking posts");
            foreach (var post in posts)
            {
                try
                {
                    if (!post.Convert)
                    {
                        continue;
                    }

                    L.W("ACB-STOA", "Post {0} requires conversion", post.Fullname);

                    L.W("ACB-STOA", "Loading build");
                    var xbld = tools.GetBuild(post.BuildId);

                    L.W("ACB-BLDW", "Writing markdown");
                    var xbsb = new StringBuilder();
                    using (var sw = new StringWriter(xbsb))
                        using (var md = new MarkdownWriter(sw))
                            using (var bw = new BuildWriter(md))
                                bw.WriteBuild(xbld, tools);

                    L.W("ACB-MD", "Making comments");
                    var xblc = xbsb.ToString().Replace(Environment.NewLine, "\n");
                    var xbps = new List <string>();
                    if (xblc.Length > 10000)
                    {
                        L.W("ACB-MD", "Comment too long, splitting");

                        var xscs = xblc.Split(new string[] { "\n\n---\n\n" }, StringSplitOptions.None);
                        var xcpr = "";
                        foreach (var xsec in xscs)
                        {
                            if (xsec.Length > 10000)
                            {
                                throw new Exception("Section too long");
                            }

                            if (xcpr.Length + xsec.Length + 7 < 10000)
                            {
                                if (!string.IsNullOrWhiteSpace(xcpr))
                                {
                                    xcpr += "\n\n---\n\n" + xsec;
                                }
                                else
                                {
                                    xcpr += xsec;
                                }
                            }
                            else
                            {
                                xbps.Add(xcpr);
                                xcpr = xsec;
                            }
                        }
                        xbps.Add(xcpr);
                    }
                    else
                    {
                        xbps.Add(xblc);
                    }

                    var xcpn = string.IsNullOrWhiteSpace(cmdl.Target) ? post.Fullname : cmdl.Target;
                    foreach (var xbpt in xbps)
                    {
                        L.W("ACB-REDDIT", "Writing comment");
                        xcpn = reddit.Comment(xbpt, xcpn);
                    }
                }
                catch (Exception ex)
                {
                    L.X("ACB v2 ERR", ex);
                    reddit.UnregisterThing(post.Fullname);
                }
            }

            L.W("ACB v2", "Checking comments");
            foreach (var comment in comments)
            {
                try
                {
                    if (!comment.Convert)
                    {
                        continue;
                    }

                    L.W("ACB-STOA", "Comment {0} requires conversion", comment.Fullname);

                    L.W("ACB-STOA", "Loading build");
                    var xbld = tools.GetBuild(comment.BuildId);

                    L.W("ACB-BLDW", "Writing markdown");
                    var xbsb = new StringBuilder();
                    using (var sw = new StringWriter(xbsb))
                        using (var md = new MarkdownWriter(sw))
                            using (var bw = new BuildWriter(md))
                                bw.WriteBuild(xbld, tools);

                    L.W("ACB-MD", "Making comments");
                    var xblc = xbsb.ToString().Replace(Environment.NewLine, "\n");
                    var xbps = new List <string>();
                    if (xblc.Length > 10000)
                    {
                        L.W("ACB-MD", "Comment too long, splitting");

                        var xscs = xblc.Split(new string[] { "\n\n---\n\n" }, StringSplitOptions.None);
                        var xcpr = "";
                        foreach (var xsec in xscs)
                        {
                            if (xsec.Length > 10000)
                            {
                                throw new Exception("Section too long");
                            }

                            if (xcpr.Length + xsec.Length + 7 < 10000)
                            {
                                if (!string.IsNullOrWhiteSpace(xcpr))
                                {
                                    xcpr += "\n\n---\n\n" + xsec;
                                }
                                else
                                {
                                    xcpr += xsec;
                                }
                            }
                            else
                            {
                                xbps.Add(xcpr);
                                xcpr = xsec;
                            }
                        }
                        xbps.Add(xcpr);
                    }
                    else
                    {
                        xbps.Add(xblc);
                    }

                    var xcpn = string.IsNullOrWhiteSpace(cmdl.Target) ? comment.Fullname : cmdl.Target;
                    foreach (var xbpt in xbps)
                    {
                        L.W("ACB-REDDIT", "Writing comment");
                        xcpn = reddit.Comment(xbpt, xcpn);
                    }
                }
                catch (Exception ex)
                {
                    L.X("ACB v2 ERR", ex);
                    reddit.UnregisterMiniThing(comment.Fullname);
                }
            }

            L.W("ACB v2", "Writing settings");
            reddit.WriteLast();

            L.W("ACB v2", "All operations completed");
            L.Q();
        }
        private void BwOperation_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                throw e.Error;
            }

            var saveto = new bool[]
            {
                cbClipboard.Checked, // [0]: Cliboard
                cbFile.Checked,      // [1]: File
            };

            var sb = new StringBuilder();

            using (var sw = new StringWriter(sb))
                using (var mdw = new MarkdownWriter(sw))
                    using (var bw = new BuildWriter(mdw))
                    {
                        bw.WriteBuild((StoAcademyBuild)e.Result, stoat, rSpace.Checked ? BuildType.Space : BuildType.Ground);
                    }
            var build = sb.ToString();

            // save to clipboard
            if (saveto[0] && MessageBox.Show(this, "Are you sure you want to replace the contents of the clipboard with your build?", "Save to clipboard", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                Clipboard.SetText(build);
            }

            // save to file
            if (saveto[1])
            {
                sfdMarkdown.FileName = string.Concat("build_", ((StoAcademyBuild)e.Result).ID, ".txt");
                if (sfdMarkdown.ShowDialog() == DialogResult.OK)
                {
                    var fi = new FileInfo(sfdMarkdown.FileName);
                    using (var fs = fi.Create())
                        using (var sw = new StreamWriter(fs, new UTF8Encoding(false)))
                        {
                            sw.Write(build);
                        }
                }
            }

            var msg = "Build conversion completed. Put the contents of ";

            if (saveto[1])
            {
                msg = string.Concat(msg, "the saved file");
            }
            if (saveto[1] && saveto[0])
            {
                msg = string.Concat(msg, " or ");
            }
            if (saveto[0])
            {
                msg = string.Concat(msg, "your clipboard");
            }
            msg = string.Concat(msg, " in your /r/stobuilds post.");
            MessageBox.Show(this, msg, "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);

            btGo.Enabled        = true;
            cbClipboard.Enabled = true;
            cbFile.Enabled      = true;
            rSpace.Enabled      = true;
            rGround.Enabled     = true;
            tbURL.Enabled       = true;
        }
        public static void RunBot(string[] args)
        {
            LoadConf();

            L.D(Debugger.IsAttached);
            L.R(Console.Out);

            // this is for discord logger
            if (UseDiscordLog)
            {
                var dsb = new StringBuilder();
                var dsw = new StringWriter(dsb);
                L.R(dsw);
                DiscordLog = dsb;
            }

            L.W("ACB v2", "Initializing");
            L.W("ACB v2", "Running from \"{0}\"", Location);
            L.W("ACB v2", "Bot Version: {0}", LibBotVersion);
            L.W("ACB v2", "LibStoa Version: {0}", LibAcademyVersion);

            L.W("ACB v2", "Parsing commandline");
            var cmdl = ParseCommandline(args);

            L.W("ACB v2", "Options:");
            L.W("ACB v2", "  Override: {0}", cmdl.Target);
            L.W("ACB v2", "  Single: {0}", cmdl.SingleId);

            L.W("STOA Lib", "Initializing STO Academy tools");
            var tools = new StoAcademyInterface();

            tools.Initialize();

            L.W("ACB-HTTP", "Initializing HTTP component");
            var http = new HttpRequestBuilder();

            http.UserAgent = "linux:stoap:2 (by /u/eMZi0767)";

            L.W("ACB-REDDIT", "Initializing Reddit component");
            var reddit = new RedditApi(http);

            reddit.Initialize();

            L.W("ACB-REDDIT", "Querying STOBuilds");
            var posts    = reddit.QueryPosts();
            var comments = reddit.QueryComments();

            L.W("ACB v2", "Checking posts");
            foreach (var post in posts)
            {
                try
                {
                    if (!post.Convert)
                    {
                        continue;
                    }

                    L.W("ACB-STOA", "Post {0} requires conversion", post.Fullname);

                    L.W("ACB-STOA", "Loading build");
                    var xbld = tools.GetBuild(post.BuildId);

                    L.W("ACB-BLDW", "Writing markdown");
                    var xbsb = new StringBuilder();
                    using (var sw = new StringWriter(xbsb))
                        using (var md = new MarkdownWriter(sw))
                            using (var bw = new BuildWriter(md))
                                bw.WriteBuild(xbld, tools);

                    L.W("ACB-MD", "Making comments");
                    var xblc = xbsb.ToString().Replace(Environment.NewLine, "\n");
                    var xbps = new List <string>();
                    if (xblc.Length > 10000)
                    {
                        L.W("ACB-MD", "Comment too long, splitting");

                        var xscs = xblc.Split(new string[] { "\n\n---\n\n" }, StringSplitOptions.None);
                        var xcpr = "";
                        foreach (var xsec in xscs)
                        {
                            if (xsec.Length > 10000)
                            {
                                throw new Exception("Section too long");
                            }

                            if (xcpr.Length + xsec.Length + 7 < 10000)
                            {
                                if (!string.IsNullOrWhiteSpace(xcpr))
                                {
                                    xcpr += "\n\n---\n\n" + xsec;
                                }
                                else
                                {
                                    xcpr += xsec;
                                }
                            }
                            else
                            {
                                xbps.Add(xcpr);
                                xcpr = xsec;
                            }
                        }
                        xbps.Add(xcpr);
                    }
                    else
                    {
                        xbps.Add(xblc);
                    }

                    var xcpn = string.IsNullOrWhiteSpace(cmdl.Target) ? post.Fullname : cmdl.Target;
                    foreach (var xbpt in xbps)
                    {
                        L.W("ACB-REDDIT", "Writing comment");
                        xcpn = reddit.Comment(xbpt, xcpn);
                    }
                }
                catch (Exception ex)
                {
                    L.X("ACB v2 ERR", ex);
                    reddit.UnregisterThing(post.Fullname);
                }
            }

            L.W("ACB v2", "Checking comments");
            foreach (var comment in comments)
            {
                try
                {
                    if (!comment.Convert)
                    {
                        continue;
                    }

                    L.W("ACB-STOA", "Comment {0} requires conversion", comment.Fullname);

                    L.W("ACB-STOA", "Loading build");
                    var xbld = tools.GetBuild(comment.BuildId);

                    L.W("ACB-BLDW", "Writing markdown");
                    var xbsb = new StringBuilder();
                    using (var sw = new StringWriter(xbsb))
                        using (var md = new MarkdownWriter(sw))
                            using (var bw = new BuildWriter(md))
                                bw.WriteBuild(xbld, tools);

                    L.W("ACB-MD", "Making comments");
                    var xblc = xbsb.ToString().Replace(Environment.NewLine, "\n");
                    var xbps = new List <string>();
                    if (xblc.Length > 10000)
                    {
                        L.W("ACB-MD", "Comment too long, splitting");

                        var xscs = xblc.Split(new string[] { "\n\n---\n\n" }, StringSplitOptions.None);
                        var xcpr = "";
                        foreach (var xsec in xscs)
                        {
                            if (xsec.Length > 10000)
                            {
                                throw new Exception("Section too long");
                            }

                            if (xcpr.Length + xsec.Length + 7 < 10000)
                            {
                                if (!string.IsNullOrWhiteSpace(xcpr))
                                {
                                    xcpr += "\n\n---\n\n" + xsec;
                                }
                                else
                                {
                                    xcpr += xsec;
                                }
                            }
                            else
                            {
                                xbps.Add(xcpr);
                                xcpr = xsec;
                            }
                        }
                        xbps.Add(xcpr);
                    }
                    else
                    {
                        xbps.Add(xblc);
                    }

                    var xcpn = string.IsNullOrWhiteSpace(cmdl.Target) ? comment.Fullname : cmdl.Target;
                    foreach (var xbpt in xbps)
                    {
                        L.W("ACB-REDDIT", "Writing comment");
                        xcpn = reddit.Comment(xbpt, xcpn);
                    }
                }
                catch (Exception ex)
                {
                    L.X("ACB v2 ERR", ex);
                    reddit.UnregisterMiniThing(comment.Fullname);
                }
            }

            L.W("ACB v2", "Writing settings");
            reddit.WriteLast();

            L.W("ACB v2", "All operations completed");
            L.Q();

            // write the discord log
            if (UseDiscordLog)
            {
                var sender = new Socket(DiscordLogEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                sender.Connect(DiscordLogEndpoint);
                var msgd = new UTF8Encoding(false).GetBytes(DiscordLog.ToString());
                var msgl = BitConverter.GetBytes((ulong)msgd.Length);
                var msg  = new byte[msgd.Length + msgl.Length];
                Array.Copy(msgl, 0, msg, 0, msgl.Length);
                Array.Copy(msgd, 0, msg, msgl.Length, msgd.Length);
                sender.Send(msg);
                sender.Close();
            }
        }