Пример #1
0
        public async Task FunctionHandler(ILambdaContext context)
        {
            var sw = Stopwatch.StartNew();

            _context = context;
            _logger  = _context.Logger;
            _logger.Log($"{context?.FunctionName} => {nameof(FunctionHandler)} => Started");

            _verbose = Environment.GetEnvironmentVariable("verbose").ToBoolOrDefault(true);
            var githubToken = Environment.GetEnvironmentVariable("github_token");

            if (githubToken.IsNullOrEmpty())
            {
                throw new Exception("Environment Variable 'github-token' was not defined!");
            }

            if (Environment.GetEnvironmentVariable("test_connection").ToBoolOrDefault(false))
            {
                Log($"Your Internet Connection is {(SilyWebClientEx.CheckInternetAccess(timeout: 5000) ? "" : "NOT")} available.");
            }

            string accessToken;

            if (githubToken.IsHex())
            {
                Log($"Property 'githubToken' was determined to be a hexadecimal and will be used as accessToken");
                accessToken = githubToken;
            }
            else
            {
                Log($"Fetching github access token '{githubToken ?? "undefined"}' from secrets manager.");
                accessToken = (await _SM.GetSecret(githubToken)).JsonDeserialize <AmazonSecretsToken>()?.token;
            }

            var rateLimit = Environment.GetEnvironmentVariable("github_rate_limit").ToIntOrDefault(1000);

            _GIT = new GitHubHelper(new GITWrapper.GitHub.Models.GitHubRepoConfig(accessToken: accessToken, maxRatePerHour: rateLimit)
            {
                user       = Environment.GetEnvironmentVariable("github_user"),
                branch     = Environment.GetEnvironmentVariable("github_branch"),
                repository = Environment.GetEnvironmentVariable("github_repository"),
                userAgent  = Environment.GetEnvironmentVariable("user_agent") ?? "Asmodat Launcher Toolkit",
            });

            try
            {
                Log($"Processing...");
                await Processing();
            }
            finally
            {
                _logger.Log($"{context?.FunctionName} => {nameof(FunctionHandler)} => Stopped, Eveluated within: {sw.ElapsedMilliseconds} [ms]");
                await Task.Delay(2500);
            }
        }
Пример #2
0
        public async Task FunctionHandler(ILambdaContext context)
        {
            _sw = Stopwatch.StartNew();
            Log($"Started KIRA Address Balance Oracle v0.0.1");

            _context = context;
            _logger  = _context.Logger;
            _logger.Log($"{context?.FunctionName} => {nameof(FunctionHandler)} => Started");
            _verbose        = Environment.GetEnvironmentVariable("VERBOSE").ToBoolOrDefault(true);
            _maxParallelism = Environment.GetEnvironmentVariable("MAX_PARALLELISM").ToIntOrDefault(1);
            var maxDuration = Environment.GetEnvironmentVariable("MAX_DURATION").ToIntOrDefault(5 * 60 * 100); // 5 minutes default
            var configUrl   = Environment.GetEnvironmentVariable("CONFIG") ?? "https://raw.githubusercontent.com/KiraCore/cfg/main/EthereumOracle/env-mainnet";
            var maxCache    = Environment.GetEnvironmentVariable("MAX_CACHE").ToIntOrDefault(0);               // seconds

            _bucket    = Environment.GetEnvironmentVariable("BUCKET");
            _networks  = Environment.GetEnvironmentVariable("NETWORKS")?.Split(",");
            _addresses = Environment.GetEnvironmentVariable("ADDRESSES")?.Split(",");
            _apikey    = Environment.GetEnvironmentVariable("APIKEY");

            if (Environment.GetEnvironmentVariable("TEST_CONNECTION").ToBoolOrDefault(false))
            {
                Log($"Your Internet Connection is {(SilyWebClientEx.CheckInternetAccess(timeout: 5000) ? "" : "NOT")} available.");
            }

            if (!configUrl.IsNullOrEmpty() && (
                    _addresses.IsNullOrEmpty() ||
                    _networks.IsNullOrEmpty() ||
                    _bucket.IsNullOrEmpty() ||
                    _apikey.IsNullOrEmpty()))
            {
                var cfg = await HttpHelper.GET <Dictionary <string, string> >(configUrl, System.Net.HttpStatusCode.OK, timeoutSeconds : 10);

                _addresses = _addresses.IsNullOrEmpty() ? cfg.GetValueOrDefault("ADDRESSES", "")?.Split(",") : _addresses;
                _networks  = _networks.IsNullOrEmpty() ? cfg.GetValueOrDefault("NETWORKS", "")?.Split(",") : _networks;
                _bucket    = _bucket.IsNullOrEmpty() ? cfg.GetValueOrDefault("BUCKET", "") : _bucket;
                _apikey    = _apikey.IsNullOrEmpty() ? cfg.GetValueOrDefault("APIKEY", "") : _apikey;

                if (cfg.GetValueOrDefault("STOP", "false").ToBoolOrDefault(false))
                {
                    _logger.Log($"WARNING: Lambda will be halted, a STOP property found in the configuration file.");
                    return;
                }
            }

            while (_sw.ElapsedMilliseconds < maxDuration)
            {
#if (TEST)
                if (_addresses.IsNullOrEmpty())                                                                                      // test networks
                {
                    _addresses = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2,0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE".Split(","); // test adresses
                }
                if (_networks.IsNullOrEmpty())                                                                                       // test networks
                {
                    _networks = "mainnet,kovan".Split(",");
                }

                if (_bucket.IsNullOrEmpty())
                {
                    _bucket = "oracle-local.kiracore.com"; // test bucket
                }
                if (_apikey.IsNullOrEmpty())
                {
                    _apikey = "MAVTB6FJWAAMJZIR825QFZ3QSR27Q3349F"; // test key
                }
                _store = _store ?? new ETHOracleStore(_bucket);
                await CacheBalances(_networks, _addresses, _apikey);
#elif (PUBLISH)
                try
                {
                    _store = _store ?? new ETHOracleStore(_bucket);
                    await CacheBalances(_networks, _addresses, _apikey, maxCache);
                }
                catch (Exception ex)
                {
                    _logger.Log($"ERROR: => Message: '{ex.JsonSerializeAsPrettyException(Newtonsoft.Json.Formatting.Indented)}'");
                }
                finally
                {
                    _logger.Log($"{context?.FunctionName} => {nameof(FunctionHandler)} => Stopped, Eveluated within: {_sw.ElapsedMilliseconds} [ms]");
                }
#endif
            }
        }
Пример #3
0
        public async Task FunctionHandler(ILambdaContext context)
        {
            _sw      = Stopwatch.StartNew();
            _context = context;
            _logger  = _context.Logger;
            _logger.Log($"{context?.FunctionName} => {nameof(FunctionHandler)} => Started");
            _verbose                = Environment.GetEnvironmentVariable("verbose").ToBoolOrDefault(true);
            _masterChatId           = new ChatId(Environment.GetEnvironmentVariable("MASTER_CHAT_ID").ToLongOrDefault(-1001261081309));
            _maxParallelism         = Environment.GetEnvironmentVariable("MAX_PARALLELISM").ToIntOrDefault(0);
            _cosmosHubClientTimeout = Environment.GetEnvironmentVariable("HUB_CLIENT_TIMEOUT").ToIntOrDefault(7);
            _maxMessageAge          = Environment.GetEnvironmentVariable("MAX_MESSAGE_AGE").ToDoubleOrDefault(24 * 3600);
            _bucket     = Environment.GetEnvironmentVariable("BUCKET_NAME");
            _lambdaTime = Environment.GetEnvironmentVariable("LAMBDA_TIME").ToIntOrDefault((15 * 60 * 1000) - 5000);

            var secretName = Environment.GetEnvironmentVariable("SECRET_NAME") ?? "KiraFaucetBot";

            if (Environment.GetEnvironmentVariable("test_connection").ToBoolOrDefault(false))
            {
                Log($"Your Internet Connection is {(SilyWebClientEx.CheckInternetAccess(timeout: 5000) ? "" : "NOT")} available.");
            }

            var secret = JObject.Parse(await _SM.GetSecret(secretName));

#if (TEST)
            var accessToken = secret["test_token"]?.ToString();
            //_mnemonic = (secret["test_mnemonic"]?.ToString()).ToSecureString();
            _mnemonic = (secret["mnemonic"]?.ToString()).ToSecureString();
            _bucket   = "kira-faucet-test";
#elif (PUBLISH)
            var accessToken = secret["token"]?.ToString();
            _mnemonic = (secret["mnemonic"]?.ToString()).ToSecureString();
#endif
            _TBC = new TelegramBotClient(accessToken);
            _bot = await _TBC.GetMeAsync();

            Log($"[INFO] {_bot.FirstName} {_version} started! Bot Name: @{_bot.Username ?? "undefined"}, Bot Id: '{_bot.Id}', Master Chat: '{_masterChatId.Identifier}'");

            _TBC.OnMessage            += Tbc_OnMessage;
            _TBC.OnCallbackQuery      += _TBC_OnCallbackQuery;
            _TBC.OnInlineQuery        += _TBC_OnInlineQuery;
            _TBC.OnInlineResultChosen += _TBC_OnInlineResultChosen;
            _TBC.StartReceiving();

            try
            {
                Log($"Processing...");
                var finalize = false;
                while (true)
                {
#if (PUBLISH)
                    if (!finalize && _sw.ElapsedMilliseconds >= _lambdaTime)
                    {
                        _TBC.StopReceiving();
                        finalize = true;
                        _logger.Log($"Finalizing, elapsed {_sw.ElapsedMilliseconds} / {_lambdaTime} [ms] ...");
                    }
#endif

                    if (_messages.IsNullOrEmpty() && _callbacks.IsNullOrEmpty())
                    {
                        if (finalize)
                        {
                            _logger.Log($"Lambda was finalized gracefully within {_lambdaTime - _sw.ElapsedMilliseconds} ms.");
                            return;
                        }
                        else
                        {
                            await Task.Delay(100);

                            continue;
                        }
                    }

                    Message[] msgArr = null;
                    _ssMsgLocker.Lock(() =>
                    {
                        msgArr = _messages.ToArray().DeepCopy();
                        _messages.Clear();
                    });

                    var t0 = ParallelEx.ForEachAsync(msgArr, async msg => {
                        async Task ProcessUser(Message m)
                        {
                            var user      = m.From;
                            var replyUser = m.ReplyToMessage?.From;

                            if (user != null)
                            {
                                await UpdateUserData(user);
                            }

                            if (replyUser != null && user?.Id != replyUser.Id)
                            {
                                await UpdateUserData(replyUser);
                            }
                        }

#if (TEST)
                        await ProcessUser(msg);
#elif (PUBLISH)
                        try
                        {
                            await ProcessUser(msg);
                        }
                        catch (Exception ex)
                        {
                            _logger.Log($"[USR ERROR] => Filed ('{msg?.Chat?.Id ?? 0}') to save user status: '{ex.JsonSerializeAsPrettyException(Newtonsoft.Json.Formatting.Indented)}'");
                        }
#endif
                    });

                    var t1 = ParallelEx.ForEachAsync(msgArr, async msg =>
                    {
#if (TEST)
                        await ProcessMessage(msg);
#elif (PUBLISH)
                        try
                        {
                            await ProcessMessage(msg);
                        }
                        catch (Exception ex)
                        {
                            _logger.Log($"[MSG ERROR] => Filed ('{msg?.Chat?.Id ?? 0}') to process message ({msg?.MessageId}): '{ex.JsonSerializeAsPrettyException(Newtonsoft.Json.Formatting.Indented)}'");
                            await _TBC.SendTextMessageAsync(chatId: msg.Chat,
                                                            $"Something went wrong, visit {await GetMasterChatInviteLink()} to find help.",
                                                            replyToMessageId: msg.MessageId,
                                                            parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown);
                        }
#endif
                    }, maxDegreeOfParallelism: _maxParallelism);

                    CallbackQuery[] cbqArr = null;
                    _ssCbqLocker.Lock(() =>
                    {
                        cbqArr = _callbacks.ToArray().DeepCopy();
                        _callbacks.Clear();
                    });
                    var t2 = ParallelEx.ForEachAsync(cbqArr, async cbq =>
                    {
#if (TEST)
                        await ProcessCallbacks(cbq);
#elif (PUBLISH)
                        try
                        {
                            await ProcessCallbacks(cbq);
                        }
                        catch (Exception ex)
                        {
                            _logger.Log($"[CBQ ERROR] => Filed ('{cbq.Message?.Chat?.Id ?? 0}') to process callback ({cbq.Id}): '{ex.JsonSerializeAsPrettyException(Newtonsoft.Json.Formatting.Indented)}'");
                            await _TBC.SendTextMessageAsync(chatId: cbq.Message.Chat,
                                                            $"Something went wrong, visit {await GetMasterChatInviteLink()} to find help.",
                                                            parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown);
                        }
#endif
                    }, maxDegreeOfParallelism: _maxParallelism);

                    await Task.WhenAll(t0, t1, t2);
                }
            }
            finally
            {
                _logger.Log($"{context?.FunctionName} => {nameof(FunctionHandler)} => Stopped, Eveluated within: {_sw.ElapsedMilliseconds} [ms]");
            }
        }
Пример #4
0
        private static async Task <bool> executeScheduler(string[] args)
        {
            var nArgs = CLIHelper.GetNamedArguments(args);

            switch (args[1]?.ToLower())
            {
            case "github":
            {
                if (Environment.GetEnvironmentVariable("test_connection").ToBoolOrDefault(false))
                {
                    Console.WriteLine($"Your Internet Connection is {(SilyWebClientEx.CheckInternetAccess(timeout: 5000) ? "" : "NOT")} available.");
                }

                var userWhitelist         = nArgs.GetValueOrDefault("users")?.Split(',');
                var repositoriesWhitelist = nArgs.GetValueOrDefault("repositories")?.Split(',');

                Console.WriteLine($"Fetching scheduler info.");
                var workingDirectory = (await GetVariableByKey("working_directory", nArgs: nArgs)).ToDirectoryInfo();
                var githubSchedule   = await GetVariableByKey("github_schedule", nArgs : nArgs);

                var user = GITWrapper.GitHubHelperEx.GetUserFromUrl(githubSchedule);

                if (!userWhitelist.IsNullOrEmpty() && !userWhitelist.Any(x => x == user))
                {
                    throw new Exception($"User was specified but, user '{user ?? "undefined"}' was not present among whitelisted users: {userWhitelist.JsonSerialize()}");
                }

                var accessToken = await GetSecretHexToken("github_token", nArgs);

                var repo = GITWrapper.GitHubHelperEx.GetRepoFromUrl(githubSchedule);


                if (!repositoriesWhitelist.IsNullOrEmpty() && !repositoriesWhitelist.Any(x => x == user))
                {
                    throw new Exception($"Repository was specified but, repo '{repo ?? "undefined"}' was not present among whitelisted repositories: {repositoriesWhitelist.JsonSerialize()}");
                }

                var branch           = GITWrapper.GitHubHelperEx.GetBranchFromUrl(githubSchedule);
                var scheduleLocation = GITWrapper.GitHubHelperEx.GetFileFromUrl(githubSchedule);

                var git = new GITWrapper.GitHubHelper(new GITWrapper.Models.GitHubRepoConfig()
                    {
                        accessToken = accessToken,
                        user        = user,
                        repository  = repo,
                        branch      = branch
                    });

                var contentDirectory = PathEx.RuntimeCombine(workingDirectory.FullName, repo).ToDirectoryInfo();
                var statusDirectory  = PathEx.RuntimeCombine(workingDirectory.FullName, "status").ToDirectoryInfo();
                var logsDirectory    = PathEx.RuntimeCombine(workingDirectory.FullName, "logs").ToDirectoryInfo();
                var scheduleFileInfo = PathEx.RuntimeCombine(contentDirectory.FullName, scheduleLocation).ToFileInfo();

                contentDirectory.TryDelete(recursive: true, exception: out var contentDirectoryException);
                Console.WriteLine($"Removing git directory '{contentDirectory.FullName}' {(contentDirectory.Exists ? $"did NOT suceeded, error: {contentDirectoryException.JsonSerializeAsPrettyException()}" : "succeded")}.");

                statusDirectory.TryCreate();
                CommandOutput result;

                var pullCommand = $"git clone https://{accessToken}@github.com/{user}/{repo}.git --branch {branch}";
                result = CLIHelper.Console(pullCommand, workingDirectory: workingDirectory.FullName);
                Console.WriteLine(result.JsonSerialize());

                var gitDirectory = PathEx.RuntimeCombine(contentDirectory.FullName, ".git").ToDirectoryInfo();
                gitDirectory.TryDelete(recursive: true);
                Console.WriteLine($"Removing git directory '{gitDirectory.FullName}' {(gitDirectory.Exists ? "did NOT" : "")} succeded.");

                if (!RuntimeEx.IsWindows())
                {
                    result = CLIHelper.Console($"chmod 777 -R ./{repo}", workingDirectory: workingDirectory.FullName);
                    Console.WriteLine(result.JsonSerialize());
                }

                if (!scheduleFileInfo.Exists)
                {
                    Console.WriteLine($"FAILURE, schedule file '{scheduleFileInfo.FullName}' does not exist or was not defined.");
                    return(false);
                }

                var deploymentConfig    = scheduleFileInfo.DeserialiseJson <DeploymentConfig>();
                var deploymentConfigOld = deploymentConfig.LoadDeploymentConfig(statusDirectory);

                if (deploymentConfig?.enable != true || deploymentConfig.schedules.IsNullOrEmpty())
                {
                    Console.WriteLine($"Deployment config '{scheduleFileInfo.FullName}' was not enabled or schedules were not defined.");
                    return(false);
                }

                //Defines if schedule executuions should be triggered
                var masterTrigger = deploymentConfig.IsTriggered(deploymentConfigOld);

                var serialSchedules = deploymentConfig.schedules
                                      .Where(x => !(x?.id).IsNullOrEmpty() && x.parallelizable == false)
                                      ?.OrderBy(x => x.priority)?.DistinctBy(x => x.id)?.ToArray();

                var parallelSchedules = deploymentConfig.schedules
                                        .Where(x => !(x?.id).IsNullOrEmpty() && x.parallelizable == true)
                                        ?.OrderBy(x => x.priority)?.DistinctBy(x => x.id)?.ToArray();

                var breakAll = false;
                async Task TryCatchExecute(ExecutionSchedule s)
                {
                    var sOld = s.LoadExecutionSchedule(statusDirectory);

                    if (s == null || sOld == null)
                    {
                        Console.WriteLine($"New or old schedule could not be found.");
                        return;
                    }

                    if (!s.IsTriggered(sOld, masterTrigger))
                    {
                        Console.WriteLine($"WARNING, schedule '{s?.id ?? "undefined"}' execution was not triggered.");
                        return;
                    }


                    Console.WriteLine($"Processing executioon schedule '{s.id}', parralelized: {s.parallelizable}, cron: {s.cron ?? "null"}, trigger: {s.trigger}/{sOld.trigger}.");

                    if (s.delay > 0)
                    {
                        await Task.Delay(s.delay);
                    }

                    if (_debug)
                    {
                        Console.WriteLine($"WARNING! github schedule will be processed in DEBUG mode");
                        await ProcessSchedule(s, sOld, contentDirectory, statusDirectory, logsDirectory, masterTrigger : masterTrigger);

                        return;
                    }

                    try
                    {
                        await ProcessSchedule(s, sOld, contentDirectory, statusDirectory, logsDirectory, masterTrigger : masterTrigger);

                        breakAll = s.breakAllOnFinalize;

                        if (s.sleep > 0)
                        {
                            await Task.Delay(s.sleep);
                        }
                    }
                    catch (Exception ex)
                    {
                        try
                        {
                            if (deploymentConfig.throwOnFailure == true)
                            {
                                if (deploymentConfig.finalizeOnFailure)
                                {
                                    deploymentConfig.UpdateDeploymentConfig(statusDirectory);
                                    breakAll = s.breakAllOnFinalize;
                                }

                                throw;
                            }

                            Console.WriteLine($"FAILED! execution of schedule '{s.id}', parralelized: {s.parallelizable}, error: {ex.JsonSerializeAsPrettyException()}.");
                        }
                        finally
                        {
                            var logPath = PathEx.Combine(logsDirectory.FullName, $"{s.GetFileSafeId() ?? "tmp.log"}.log").ToFileInfo();
                            if (logPath.TryCreate())
                            {
                                logPath.AppendAllText(ex.JsonSerializeAsPrettyException());
                            }
                        }
                    }
                }

                if (deploymentConfig.delay > 0)
                {
                    await Task.Delay(deploymentConfig.delay);
                }

                var sum = 0;
                if (!serialSchedules.IsNullOrEmpty())
                {
                    sum += serialSchedules.Length;
                    foreach (var s in serialSchedules)
                    {
                        await TryCatchExecute(s);
                    }
                }

                if (!parallelSchedules.IsNullOrEmpty())
                {
                    sum += serialSchedules.Length;
                    await ParallelEx.ForEachAsync(parallelSchedules,
                                                  s => TryCatchExecute(s), maxDegreeOfParallelism : parallelSchedules.Count());
                }

                deploymentConfig.UpdateDeploymentConfig(statusDirectory);

                Console.WriteLine($"SUCCESS, {sum} github schedule/s was/were executed out of {deploymentConfig.schedules.Length}.");

                if (deploymentConfig.sleep > 0)
                {
                    await Task.Delay(deploymentConfig.sleep);
                }

                return(true);
            }

            case "help":
            case "--help":
            case "-help":
            case "-h":
            case "h":
            {
                HelpPrinter($"{args[0]}", "Command Deployment",
                            ("github", "Accepts params: working_directory, github_schedule, github_token"));
                return(true);
            }

            default:
            {
                Console.WriteLine($"Try '{args[0]} help' to find out list of available commands.");
                throw new Exception($"Unknown String command: '{args[0]} {args[1]}'");
            }
            }
        }