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); } }
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 } }
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]"); } }
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]}'"); } } }