Implement crypto currency rates feature and enhance API responses

- Added a new job to fetch crypto currency rates from an external source and store them in a JSON file.
- Updated the CurrencyController to include methods for retrieving current crypto currency rates and rates by name.
- Enhanced the API to return detailed metadata for crypto currency rates, including timestamps and update information.
- Updated the API routes to support new endpoints for crypto currency rates.
- Modified the merged rates JSON to include crypto currency data alongside existing currency and gold rates.
- Improved the welcome view to display additional crypto currency information, enhancing user experience.

These changes collectively expand the functionality of the Truncgil Finance application, providing users with comprehensive access to crypto currency data.
This commit is contained in:
Ümit Tunç
2025-01-21 19:27:03 +03:00
parent 30dd0c5b8d
commit 09e981f94b
9 changed files with 362 additions and 30 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6
View File
@@ -6,6 +6,7 @@ use Illuminate\Console\Command;
use App\Jobs\FetchCurrencyRates;
use App\Jobs\FetchGoldRates;
use App\Jobs\MergeCurrencyAndGoldRates;
use App\Jobs\FetchCryptoCurrencyRates;
class RunAllFetchs extends Command
{
@@ -37,6 +38,11 @@ class RunAllFetchs extends Command
$duration = microtime(true) - $start;
$results[] = ['FetchCurrencyRates', number_format($duration, 2)];
$start = microtime(true);
FetchCryptoCurrencyRates::dispatchSync();
$duration = microtime(true) - $start;
$results[] = ['FetchCryptoCurrencyRates', number_format($duration, 2)];
$start = microtime(true);
FetchGoldRates::dispatchSync();
$duration = microtime(true) - $start;
+64 -9
View File
@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
use App\Jobs\FetchCurrencyRates;
use App\Jobs\FetchGoldRates;
use App\Jobs\MergeCurrencyAndGoldRates;
use App\Jobs\FetchCryptoCurrencyRates;
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\Controller;
@@ -27,6 +28,7 @@ class CurrencyController extends Controller
public function runAllFetchs()
{
try {
FetchCryptoCurrencyRates::dispatchSync();
FetchCurrencyRates::dispatchSync();
FetchGoldRates::dispatchSync();
MergeCurrencyAndGoldRates::dispatchSync();
@@ -50,29 +52,29 @@ class CurrencyController extends Controller
*/
public function getAllRates()
{
// JSON dosyasından oku
$jsonFile = 'merged/rates.json';
if (Storage::exists($jsonFile)) {
$data = json_decode(Storage::get($jsonFile), true);
$currentDate = now(); // Şu anki tarih
$currentDate = now();
$updateDate = isset($data['Update_Date']) ? \Carbon\Carbon::parse($data['Update_Date']) : null;
if ($updateDate) {
$minutesAgo = round($currentDate->diffInMinutes($updateDate), 2); // Kaç dakika önce alındığı
$metaData = [ // Tarih bilgileri için alt dizi
$minutesAgo = round($currentDate->diffInMinutes($updateDate), 2);
$metaData = [
'Minutes_Ago' => $minutesAgo,
'Current_Date' => $currentDate->toDateTimeString(),
'Update_Date' => $updateDate->toDateTimeString(), // Update_Date burada kalacak
'Update_Date' => $updateDate->toDateTimeString(),
];
unset($data['Update_Date']); // Rates içerisindeki Update_Date elemanını kaldır
unset($data['Update_Date']);
$data = [
'Meta_Data' => $metaData, // Tarih bilgileri alt dizisi
'Rates' => $data, // Kur bilgileri alt dizisi
'Meta_Data' => $metaData,
'Rates' => $data
];
}
return response()->json($data);
}
}
return response()->json(['error' => 'Veri bulunamadı'], 404);
}
@@ -145,6 +147,39 @@ class CurrencyController extends Controller
return response()->json(['error' => 'Veri bulunamadı'], 404);
}
/**
* Retrieves the current crypto currency rates
*
* @return \Illuminate\Http\JsonResponse
*/
public function getCryptoCurrencyRates()
{
$jsonFile = 'crypto/today.json';
if (Storage::exists($jsonFile)) {
$data = json_decode(Storage::get($jsonFile), true);
$currentDate = now();
$updateDate = isset($data['Update_Date']) ? \Carbon\Carbon::parse($data['Update_Date']) : null;
if ($updateDate) {
$minutesAgo = round($currentDate->diffInMinutes($updateDate), 2);
$metaData = [
'Minutes_Ago' => $minutesAgo,
'Current_Date' => $currentDate->toDateTimeString(),
'Update_Date' => $updateDate->toDateTimeString(),
];
unset($data['Update_Date']);
$data = [
'Meta_Data' => $metaData,
'Rates' => $data,
];
}
return response()->json($data);
}
return response()->json(['error' => 'Veri bulunamadı'], 404);
}
/**
* 🟰 💵 Retrieves the currency rate by its name
*
@@ -186,4 +221,24 @@ class CurrencyController extends Controller
return response()->json(['error' => 'Data not found'], 404);
}
/**
* 🟰 Retrieves the crypto currency rate by its name
*
* @param string $cryptoCurrencyName
* @return \Illuminate\Http\JsonResponse
*/
public function getCryptoCurrencyRateByName($cryptoCurrencyName)
{
$jsonFile = 'crypto/today.json';
if (Storage::exists($jsonFile)) {
$data = json_decode(Storage::get($jsonFile), true);
if (isset($data[$cryptoCurrencyName])) {
return response()->json([$cryptoCurrencyName => $data[$cryptoCurrencyName]]);
}
return response()->json(['error' => 'Kripto para birimi bulunamadı'], 404);
}
return response()->json(['error' => 'Veri bulunamadı'], 404);
}
}
+82
View File
@@ -0,0 +1,82 @@
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use App\Helpers\NumberFormatter;
class FetchCryptoCurrencyRates implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function handle()
{
$data = [];
$data['Update_Date'] = now()->format('Y-m-d H:i:s');
// Kripto para kurları
$response = $this->fetchData('https://www.doviz.com/kripto-paralar');
// DOM işlemleri için veri çekme
$dom = new \DOMDocument();
@$dom->loadHTML($response->body());
$xpath = new \DOMXPath($dom);
// Kripto para verilerini içeren tabloyu ID'ye göre bul
$rows = $xpath->query("//table[@id='coins']/tbody/tr");
foreach ($rows as $row) {
$symbol = trim($xpath->evaluate("string(.//td[1]//text()[last()])", $row));
// Semboldeki boşlukları temizle ve sadece kripto para sembolünü al
$symbol = preg_replace('/^.*\s(\w+)\s*$/', '$1', $symbol);
// Kripto para ismini al
$name = $xpath->evaluate("string(.//td[1]//div[@class='cname'])", $row);
if (strlen($symbol) > 0) {
$priceUSD = $xpath->evaluate("string(.//td[2])", $row);
$priceTRY = $xpath->evaluate("string(.//td[3])", $row);
$change = $xpath->evaluate("string(.//td[6])", $row);
// Fiyat verilerini temizle (örn: $3.310,57 -> 3310.57)
$priceUSD = str_replace('$', '', $priceUSD);
$priceUSD = str_replace('.', '', $priceUSD);
$priceUSD = str_replace(',', '.', $priceUSD);
$priceTRY = str_replace('₺', '', $priceTRY);
$priceTRY = str_replace('.', '', $priceTRY);
$priceTRY = str_replace(',', '.', $priceTRY);
$change = str_replace('%', '', $change);
$change = str_replace('.', '', $change);
$change = str_replace(',', '.', $change);
$data[$symbol] = [
'Name' => trim($name),
'USD_Price' => (float)$priceUSD,
'TRY_Price' => (float)$priceTRY,
'Selling' => (float)$priceTRY,
'Change' => (float)$change,
'Type' => 'CryptoCurrency'
];
}
}
// JSON dosyasını kaydet
Storage::put('crypto/today.json', json_encode($data, JSON_UNESCAPED_UNICODE));
return $data;
}
private function fetchData($url)
{
return Http::withHeaders([
'User-Agent' => 'Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10',
'Accept-Language' => 'en'
])->get($url);
}
}
+7
View File
@@ -38,9 +38,16 @@ class FetchCurrencyRates implements ShouldQueue
if (trim($name) !== '') {
if ($name == "JPY") $value = $value / 100;
if (strlen($name) === 3) {
// Para birimi ismini bul
$nameElement = $xpath->query(".//div[@class='cname']", $element->parentNode);
if ($nameElement->length > 0) {
$data[$name]['Name'] = trim($nameElement->item(0)->nodeValue);
}
if ($type == "bid") $data[$name]['Buying'] = (float)$value;
if ($type == "ask") $data[$name]['Selling'] = (float)$value;
if ($type == "c") $data[$name]['Change'] = round((float)$value, 2);
$data[$name]['Type'] = "Currency";
}
}
+2 -1
View File
@@ -17,9 +17,10 @@ class MergeCurrencyAndGoldRates implements ShouldQueue
{
$currencyData = $this->getData('currency/today.json');
$goldData = $this->getData('gold/today.json');
$cryptoCurrencyData = $this->getData('crypto/today.json');
// Verileri birleştir
$mergedData = array_merge($currencyData, $goldData);
$mergedData = array_merge($currencyData, $goldData, $cryptoCurrencyData);
// Birleştirilmiş veriyi dışarıya aktar
Storage::put('merged/rates.json', json_encode($mergedData, JSON_UNESCAPED_UNICODE));
+2 -2
View File
@@ -130,7 +130,7 @@
@php
$response = file_get_contents('https://finance.truncgil.com/api/today.json');
$data = json_decode($response, true);
$currencies = ['USD', 'EUR', 'GBP', 'GRA'];
$currencies = ['USD', 'EUR', 'GBP', 'GRA', 'BTC', 'ETH', 'XRP', 'LTC'];
$rates = [];
foreach ($currencies as $currency) {
@@ -178,7 +178,7 @@
</main>
<footer class="py-16 text-center text-sm text-black dark:text-white/70">
Truncgil Finance v{{ app()->version() }} (PHP v{{ PHP_VERSION }})
Truncgil Finance v5.0.3
</footer>
</div>
</div>
+3
View File
@@ -20,6 +20,9 @@ Route::get('/currency-rates/{currencyName}', [CurrencyController::class, 'getCur
Route::get('/gold-rates', [CurrencyController::class, 'getGoldRates']);
Route::get('/gold-rates/{goldName}', [CurrencyController::class, 'getGoldRateByName']);
Route::get('/crypto-currency-rates', [CurrencyController::class, 'getCryptoCurrencyRates']);
Route::get('/crypto-currency-rates/{cryptoCurrencyName}', [CurrencyController::class, 'getCryptoCurrencyRateByName']);
Route::get('/server-time', [TimeDateController::class, 'getServerTime']);
Route::get('/server-date', [TimeDateController::class, 'getServerDate']);