From 265a9eb1f70468dba1a47fa062bb254e36f66907 Mon Sep 17 00:00:00 2001 From: Pinga <121483313+getpinga@users.noreply.github.com> Date: Sat, 15 Feb 2025 18:38:26 +0200 Subject: [PATCH] Added exchange rate download script --- automation/cron.php | 1 + automation/exchange-rates.php | 106 ++++++++++++++++++++++++++++++++++ cp/routes/web.php | 16 +++++ 3 files changed, 123 insertions(+) create mode 100644 automation/exchange-rates.php diff --git a/automation/cron.php b/automation/cron.php index eee2583..cb891be 100644 --- a/automation/cron.php +++ b/automation/cron.php @@ -58,6 +58,7 @@ $scheduler->php('/opt/registry/automation/auto-approve-transfer.php')->at('*/30 $scheduler->php('/opt/registry/automation/auto-clean-unused-contact-and-host.php')->at('5 0 * * *'); $scheduler->php('/opt/registry/automation/archive-logs.php')->at('0 1 1 * *'); +$scheduler->php('/opt/registry/automation/exchange-rates.php')->at('0 1 * * *'); // Conditional Cron Jobs if ($cronJobConfig['accounting']) { diff --git a/automation/exchange-rates.php b/automation/exchange-rates.php new file mode 100644 index 0000000..78a2c74 --- /dev/null +++ b/automation/exchange-rates.php @@ -0,0 +1,106 @@ +info('job started.'); + +// Prevent concurrent execution using flock() +$lock = fopen($lockFile, "w+"); +if (!$lock) { + $log->error('Failed to open lock file.'); + exit; +} +if (!flock($lock, LOCK_EX | LOCK_NB)) { + $log->error('Script is already running. Exiting.'); + exit; +} + +// Load current rates if the file exists +$existingRates = []; +if (file_exists($outputFile)) { + $existingRates = json_decode(file_get_contents($outputFile), true); + if (!isset($existingRates['rates'])) { + $existingRates['rates'] = []; + } +} + +// Fetch exchange rates from ExchangeRate.host with API key +$apiUrl = "http://api.exchangerate.host/live?access_key={$apiKey}&format=1"; +$maxRetries = 3; +$retryDelay = 5; // seconds +$response = false; + +for ($i = 0; $i < $maxRetries; $i++) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $apiUrl); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($httpCode === 200 && $response) { + break; // Success + } + + sleep($retryDelay); +} + +if ($httpCode !== 200 || !$response) { + flock($lock, LOCK_UN); + fclose($lock); + $log->error('Failed to fetch exchange rates.'); + exit; +} + +// Decode and validate API response +$data = json_decode($response, true); +if (!isset($data['quotes'])) { + flock($lock, LOCK_UN); + fclose($lock); + $log->error('Invalid API response.'); + exit; +} + +// Filter only configured currencies, keeping old values for missing ones +$filteredRates = $existingRates['rates']; // Start with existing rates +foreach ($currencies as $currency) { + $usdKey = "USD" . $currency; + if (isset($data['quotes'][$usdKey])) { + $filteredRates[$currency] = $data['quotes'][$usdKey]; // Update with new rate + } +} + +// Prepare updated exchange rate data +$exchangeRates = [ + "base_currency" => $baseCurrency, + "rates" => $filteredRates, + "last_updated" => gmdate("Y-m-d\TH:i:s\Z") +]; + +// Save to file safely +if (file_put_contents($outputFile, json_encode($exchangeRates, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)) === false) { + flock($lock, LOCK_UN); + fclose($lock); + $log->error('Failed to save exchange rates.'); + exit; +} + +// Log success +$log->info('Exchange rates updated successfully.'); + +// Release lock and close +flock($lock, LOCK_UN); +fclose($lock); + +$log->info('job finished successfully.'); \ No newline at end of file diff --git a/cp/routes/web.php b/cp/routes/web.php index 892323e..fe3b3dc 100644 --- a/cp/routes/web.php +++ b/cp/routes/web.php @@ -1,4 +1,5 @@ any('/api[/{params:.*}]', function ( $db_username = $db['mysql']['username']; $db_password = $db['mysql']['password']; $db_database = $db['mysql']['database']; + $db_address = 'localhost'; } elseif (config('default') == 'pgsql') { $db_username = $db['pgsql']['username']; $db_password = $db['pgsql']['password']; $db_database = $db['pgsql']['database']; + $db_address = 'localhost'; + } elseif (config('default') == 'sqlite') { + $db_username = null; + $db_password = null; + $db_database = null; + $db_address = '/var/www/cp/registry.db'; } $config = new Config([ 'driver' => config('default'), 'username' => $db_username, 'password' => $db_password, 'database' => $db_database, + 'address' => $db_address, 'basePath' => '/api', 'middlewares' => 'customization,dbAuth,authorization,sanitation,multiTenancy', 'authorization.tableHandler' => function ($operation, $tableName) { @@ -308,15 +317,22 @@ $app->any('/log-api[/{params:.*}]', function ( if (config('default') == 'mysql') { $db_username = $db['mysql']['username']; $db_password = $db['mysql']['password']; + $db_address = 'localhost'; } elseif (config('default') == 'pgsql') { $db_username = $db['pgsql']['username']; $db_password = $db['pgsql']['password']; + $db_address = 'localhost'; + } elseif (config('default') == 'sqlite') { + $db_username = null; + $db_password = null; + $db_address = '/var/www/cp/registry.db'; } $config = new Config([ 'driver' => config('default'), 'username' => $db_username, 'password' => $db_password, 'database' => 'registryTransaction', + 'address' => $db_address, 'basePath' => '/log-api', 'middlewares' => 'customization,dbAuth,multiTenancy', 'customization.beforeHandler' => function ($operation, $tableName, $request, $environment) {