Example #1
0
        public static async Task MainAsync(string[] args)
        {
            try
            {
                Log("==> Running pre-start operations...");
                // hook global errors (final failsafe)
                AppDomain.CurrentDomain.UnhandledException += GlobalErrorHandler;
                Log("Global error handler is armed and ready!");
                // process commandlines
                await CmdLineProcess.RunCommand(Environment.CommandLine).ConfigureAwait(false);

                // everything (exits and/or errors) are handled above, please do not process.
                // detect environment variables
                // including: $pmcenter_conf, $pmcenter_lang
                try
                {
                    var ConfByEnviVar = Environment.GetEnvironmentVariable("pmcenter_conf");
                    var LangByEnviVar = Environment.GetEnvironmentVariable("pmcenter_lang");
                    if (ConfByEnviVar != null)
                    {
                        if (File.Exists(ConfByEnviVar))
                        {
                            Vars.ConfFile = ConfByEnviVar;
                        }
                        else
                        {
                            Log($"==> The following file was not found: {ConfByEnviVar}", "CORE", LogLevel.INFO);
                        }
                    }
                    if (LangByEnviVar != null)
                    {
                        if (File.Exists(LangByEnviVar))
                        {
                            Vars.LangFile = LangByEnviVar;
                        }
                        else
                        {
                            Log($"==> The following file was not found: {LangByEnviVar}", "CORE", LogLevel.INFO);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log($"Failed to read environment variables: {ex.ToString()}", "CORE", LogLevel.WARN);
                }

                Log($"==> Using configurations file: {Vars.ConfFile}");
                Log($"==> Using language file: {Vars.LangFile}");

                Log("==> Running start operations...");
                Log("==> Initializing module - CONF"); // BY DEFAULT CONF & LANG ARE NULL! PROCEED BEFORE DOING ANYTHING. <- well anyway we have default values
                await InitConf().ConfigureAwait(false);

                _ = await ReadConf().ConfigureAwait(false);
                await InitLang().ConfigureAwait(false);

                _ = await ReadLang().ConfigureAwait(false);

                if (Vars.CurrentLang == null)
                {
                    throw new InvalidOperationException("Language file is empty.");
                }

                if (Vars.RestartRequired)
                {
                    Log("This may be the first time that you use the pmcenter bot.", "CORE");
                    Log("Configuration guide could be found at https://see.wtf/feEJJ", "CORE");
                    Log("Received restart requirement from settings system. Exiting...", "CORE", LogLevel.ERROR);
                    Log("You may need to check your settings and try again.", "CORE", LogLevel.INFO);
                    Environment.Exit(1);
                }

                Log("==> Initializing module - THREADS");
                Log("Starting RateLimiter...");
                Vars.RateLimiter = new Thread(() => ThrRateLimiter());
                Vars.RateLimiter.Start();
                Log("Waiting...");
                while (!Vars.RateLimiter.IsAlive)
                {
                    Thread.Sleep(100);
                }
                Log("Starting UpdateChecker...");
                if (Vars.CurrentConf.EnableAutoUpdateCheck)
                {
                    Vars.UpdateChecker = new Thread(() => ThrUpdateChecker());
                    Vars.UpdateChecker.Start();
                    Log("Waiting...");
                    while (!Vars.UpdateChecker.IsAlive)
                    {
                        Thread.Sleep(100);
                    }
                }
                else
                {
                    Vars.UpdateCheckerStatus = ThreadStatus.Stopped;
                    Log("Skipped.");
                }
                Log("Starting SyncConf...");
                Vars.SyncConf = new Thread(() => ThrSyncConf());
                Vars.SyncConf.Start();
                Log("Waiting...");
                while (!Vars.SyncConf.IsAlive)
                {
                    Thread.Sleep(100);
                }

                Log("==> Initializing module - BOT");
                Log("Initializing bot instance...");
                if (Vars.CurrentConf.UseProxy)
                {
                    Log("Activating SOCKS5 proxy...");
                    List <ProxyInfo> ProxyInfoList = new List <ProxyInfo>();
                    foreach (Socks5Proxy Info in Vars.CurrentConf.Socks5Proxies)
                    {
                        ProxyInfo ProxyInfo = new ProxyInfo(Info.ServerName,
                                                            Info.ServerPort,
                                                            Info.Username,
                                                            Info.ProxyPass);
                        ProxyInfoList.Add(ProxyInfo);
                    }
                    HttpToSocks5Proxy Proxy = new HttpToSocks5Proxy(ProxyInfoList.ToArray())
                    {
                        ResolveHostnamesLocally = Vars.CurrentConf.ResolveHostnamesLocally
                    };
                    Log("SOCKS5 proxy is enabled.");
                    Vars.Bot = new TelegramBotClient(Vars.CurrentConf.APIKey, Proxy);
                }
                else
                {
                    Vars.Bot = new TelegramBotClient(Vars.CurrentConf.APIKey);
                }
                _ = await Vars.Bot.TestApiAsync().ConfigureAwait(false);

                Log("Hooking event processors...");
                Vars.Bot.OnUpdate += BotProcess.OnUpdate;
                Log("Starting receiving...");
                Vars.Bot.StartReceiving(new[] { UpdateType.Message });
                Log("==> Startup complete!");
                Log("==> Running post-start operations...");
                try
                {
                    if (!Vars.CurrentConf.NoStartupMessage)
                    {
                        _ = await Vars.Bot.SendTextMessageAsync(Vars.CurrentConf.OwnerUID,
                                                                Vars.CurrentLang.Message_BotStarted
                                                                .Replace("$1", Math.Round(Vars.StartSW.Elapsed.TotalSeconds, 2) + "s"),
                                                                ParseMode.Markdown,
                                                                false,
                                                                false).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    Log($"Failed to send startup message to owner.\nDid you set the \"OwnerID\" key correctly? Otherwise pmcenter could not work properly.\nYou can try to use setup wizard to update/get your OwnerID automatically, just run \"dotnet pmcenter.dll --setup\".\n\nError details: {ex.ToString()}", "BOT", LogLevel.ERROR);
                }
                if (Vars.CurrentLang.TargetVersion != Vars.AppVer.ToString())
                {
                    Log("Language version mismatch detected.", "CORE", LogLevel.WARN);
                    _ = await Vars.Bot.SendTextMessageAsync(Vars.CurrentConf.OwnerUID,
                                                            Vars.CurrentLang.Message_LangVerMismatch
                                                            .Replace("$1", Vars.CurrentLang.TargetVersion)
                                                            .Replace("$2", Vars.AppVer.ToString()),
                                                            ParseMode.Markdown,
                                                            false,
                                                            false).ConfigureAwait(false);
                }
                Log("==> All finished!");
                while (true)
                {
                    Thread.Sleep(60000);
                }
            }
            catch (Exception ex)
            {
                CheckOpenSSLComp(ex);
                Log($"Unexpected error during startup: {ex.ToString()}", "CORE", LogLevel.ERROR);
                Environment.Exit(1);
            }
        }
Example #2
0
        public static async Task MainAsync(string[] args)
        {
            try
            {
                Check("Initial checkpoint"); // mark initial checkpoint
                Log("==> Running pre-start operations...");
                // hook global errors (final failsafe)
                AppDomain.CurrentDomain.UnhandledException += GlobalErrorHandler;
                Log("Global error handler is armed and ready!");
                // hook ctrl-c events
                Console.CancelKeyPress += CtrlCHandler;
                Check("Event handlers armed");
                // process commandlines
                await CmdLineProcess.RunCommand(Environment.CommandLine).ConfigureAwait(false);

                Check("Command line arguments processed");
                // everything (exits and/or errors) are handled above, please do not process.
                // detect environment variables
                // including:
                // $pmcenter_conf
                // $pmcenter_lang
                try
                {
                    var confByEnvironmentVar = Environment.GetEnvironmentVariable("pmcenter_conf");
                    var langByEnvironmentVar = Environment.GetEnvironmentVariable("pmcenter_lang");
                    if (confByEnvironmentVar != null)
                    {
                        if (File.Exists(confByEnvironmentVar))
                        {
                            Vars.ConfFile = confByEnvironmentVar;
                        }
                        else
                        {
                            Log($"==> The following file was not found: {confByEnvironmentVar}", "CORE", LogLevel.Info);
                        }
                    }
                    if (langByEnvironmentVar != null)
                    {
                        if (File.Exists(langByEnvironmentVar))
                        {
                            Vars.LangFile = langByEnvironmentVar;
                        }
                        else
                        {
                            Log($"==> The following file was not found: {langByEnvironmentVar}", "CORE", LogLevel.Info);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log($"Failed to read environment variables: {ex}", "CORE", LogLevel.Warning);
                }
                Check("Environment variables processed");

                Log($"==> Using configurations file: {Vars.ConfFile}");
                Log($"==> Using language file: {Vars.LangFile}");

                Log("==> Running start operations...");
                Log("==> Initializing module - CONF"); // BY DEFAULT CONF & LANG ARE NULL! PROCEED BEFORE DOING ANYTHING. <- well anyway we have default values
                await InitConf().ConfigureAwait(false);

                _ = await ReadConf().ConfigureAwait(false);

                Check("Configurations loaded");
                await InitLang().ConfigureAwait(false);

                _ = await ReadLang().ConfigureAwait(false);

                Check("Custom locale loaded");

                if (Vars.CurrentLang == null)
                {
                    throw new InvalidOperationException("Language file is empty.");
                }

                if (Vars.RestartRequired)
                {
                    Log("This may be the first time that you use the pmcenter bot.", "CORE");
                    Log("Configuration guide could be found at https://see.wtf/feEJJ", "CORE");
                    Log("Received restart requirement from settings system. Exiting...", "CORE", LogLevel.Error);
                    Log("You may need to check your settings and try again.", "CORE", LogLevel.Info);
                    Environment.Exit(1);
                }

                // check if logs are being omitted
                if (Vars.CurrentConf.IgnoredLogModules.Count > 0)
                {
                    var tmp = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("!!!!!!!!!! SOME LOG ENTRIES ARE HIDDEN ACCORDING TO CURRENT SETTINGS !!!!!!!!!!");
                    Console.WriteLine("To revert this, clear the \"IgnoredLogModules\" field in pmcenter.json.");
                    Console.WriteLine("To disable all log output, turn on \"LowPerformanceMode\".");
                    Console.WriteLine("This warning will appear every time pmcenter starts up with \"IgnoredLogModules\" set.");
                    Console.ForegroundColor = tmp;
                }
                Check("Warnings displayed");

                Log("==> Initializing module - THREADS");
                Log("Starting RateLimiter...");
                Vars.RateLimiter = new Thread(() => ThrRateLimiter());
                Vars.RateLimiter.Start();
                Log("Waiting...");
                while (!Vars.RateLimiter.IsAlive)
                {
                    Thread.Sleep(100);
                }
                Check("Rate limiter online");

                Log("Starting UpdateChecker...");
                if (Vars.CurrentConf.EnableAutoUpdateCheck)
                {
                    Vars.UpdateChecker = new Thread(() => ThrUpdateChecker());
                    Vars.UpdateChecker.Start();
                    Log("Waiting...");
                    while (!Vars.UpdateChecker.IsAlive)
                    {
                        Thread.Sleep(100);
                    }
                }
                else
                {
                    Vars.UpdateCheckerStatus = ThreadStatus.Stopped;
                    Log("Skipped.");
                }
                Check("Update checker ready");

                Log("Starting SyncConf...");
                Vars.SyncConf = new Thread(() => ThrSyncConf());
                Vars.SyncConf.Start();
                Log("Waiting...");
                while (!Vars.SyncConf.IsAlive)
                {
                    Thread.Sleep(100);
                }
                Check("Configurations autosaver online");

                Log("==> Initializing module - BOT");
                Log("Initializing bot instance...");
                if (Vars.CurrentConf.UseProxy)
                {
                    Log("Activating SOCKS5 proxy...");
                    List <ProxyInfo> proxyInfoList = new List <ProxyInfo>();
                    foreach (var proxyInfo in Vars.CurrentConf.Socks5Proxies)
                    {
                        var newProxyInfo = new ProxyInfo(proxyInfo.ServerName,
                                                         proxyInfo.ServerPort,
                                                         proxyInfo.Username,
                                                         proxyInfo.ProxyPass);
                        proxyInfoList.Add(newProxyInfo);
                    }
                    var proxy = new HttpToSocks5Proxy(proxyInfoList.ToArray())
                    {
                        ResolveHostnamesLocally = Vars.CurrentConf.ResolveHostnamesLocally
                    };
                    Log("SOCKS5 proxy is enabled.");
                    Vars.Bot = new TelegramBotClient(Vars.CurrentConf.APIKey, proxy);
                }
                else
                {
                    Vars.Bot = new TelegramBotClient(Vars.CurrentConf.APIKey);
                }
                Check("Bot initialized");

                Log("Validating API Key...");
                if (Vars.CurrentConf.SkipAPIKeyVerification)
                {
                    Log("API Key validation skipped", LogLevel.Warning);
                }
                else
                {
                    _ = await Vars.Bot.TestApiAsync().ConfigureAwait(false);
                }
                Check("API Key test passed");

                Log("Hooking message processors...");
                Vars.Bot.OnUpdate += BotProcess.OnUpdate;
                Log("Starting receiving...");
                Vars.Bot.StartReceiving(new[]
                {
                    UpdateType.Message,
                    UpdateType.CallbackQuery
                });
                Check("Update receiving started");

                Log("==> Startup complete!");
                Log("==> Running post-start operations...");
                try
                {
                    // prompt startup success
                    if (!Vars.CurrentConf.NoStartupMessage)
                    {
                        _ = await Vars.Bot.SendTextMessageAsync(Vars.CurrentConf.OwnerUID,
                                                                Vars.CurrentLang.Message_BotStarted
                                                                .Replace("$1", $"{Math.Round(Vars.StartSW.Elapsed.TotalSeconds, 2)}s"),
                                                                ParseMode.Markdown,
                                                                false,
                                                                false).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    Log($"Failed to send startup message to owner.\nDid you set the \"OwnerID\" key correctly? Otherwise pmcenter could not work properly.\nYou can try to use setup wizard to update/get your OwnerID automatically, just run \"dotnet pmcenter.dll --setup\".\n\nError details: {ex}", "BOT", LogLevel.Warning);
                }
                Check("Startup message sent");

                try
                {
                    // check .net core runtime version
                    var netCoreVersion = GetNetCoreVersion();
                    if (!CheckNetCoreVersion(netCoreVersion) && !Vars.CurrentConf.DisableNetCore3Check)
                    {
                        _ = await Vars.Bot.SendTextMessageAsync(Vars.CurrentConf.OwnerUID,
                                                                Vars.CurrentLang.Message_NetCore31Required
                                                                .Replace("$1", netCoreVersion.ToString()),
                                                                ParseMode.Markdown,
                                                                false,
                                                                false).ConfigureAwait(false);

                        Vars.CurrentConf.DisableNetCore3Check = true;
                        _ = await SaveConf(false, true);
                    }
                }
                catch (Exception ex)
                {
                    Log($".NET Core runtime version warning wasn't delivered to the owner: {ex.Message}, did you set the \"OwnerID\" key correctly?", "BOT", LogLevel.Warning);
                }
                Check(".NET Core runtime version check complete");

                // check language mismatch
                if (Vars.CurrentLang.TargetVersion != Vars.AppVer.ToString())
                {
                    Log("Language version mismatch detected", "CORE", LogLevel.Warning);
                    if (Vars.CurrentConf.CheckLangVersionMismatch)
                    {
                        _ = await Vars.Bot.SendTextMessageAsync(Vars.CurrentConf.OwnerUID,
                                                                Vars.CurrentLang.Message_LangVerMismatch
                                                                .Replace("$1", Vars.CurrentLang.TargetVersion)
                                                                .Replace("$2", Vars.AppVer.ToString()),
                                                                ParseMode.Markdown,
                                                                false,
                                                                false).ConfigureAwait(false);
                    }
                }
                Check("Language version mismatch checked");
                Check("Complete");
                if (Vars.CurrentConf.AnalyzeStartupTime)
                {
                    Log("Advanced startup time analysis is on, printing startup checkpoints...");
                    PrintCheckPoints();
                    _checkPoints.Clear();
                }

                Log("==> All finished!");
                if (Vars.ServiceMode)
                {
                    while (true)
                    {
                        Thread.Sleep(int.MaxValue);
                    }
                }
                else
                {
                    while (true)
                    {
                        Console.ReadKey(true);
                    }
                }
            }
            catch (Exception ex)
            {
                CheckOpenSSLComp(ex);
                Log($"Unexpected error during startup: {ex}", "CORE", LogLevel.Error);
                Environment.Exit(1);
            }
        }