restructure project and fix issue #12
11
.gitignore
vendored
|
@ -6,13 +6,14 @@
|
||||||
/node_modules/
|
/node_modules/
|
||||||
|
|
||||||
# Coingecko export data
|
# Coingecko export data
|
||||||
/coingecko.json
|
/storage/coingecko.json
|
||||||
/coingecko-original.json
|
/storage/coingecko-original.json
|
||||||
/coingecko-currencies.json
|
/storage/coingecko-currencies.json
|
||||||
|
/storage/cache/
|
||||||
|
|
||||||
# Secret files
|
# Secret files
|
||||||
/secrets.php
|
/secrets.php
|
||||||
|
|
||||||
# Compiled files
|
# Compiled files
|
||||||
/js/
|
/public/js/
|
||||||
/css/
|
/public/css/
|
||||||
|
|
|
@ -98,7 +98,7 @@ For an example, see [kuno.anne.media](https://kuno.anne.media/donate/onml/).
|
||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Point your web server to the repository directory.
|
4. Point your web server to the public directory inside this repository.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
class FileCache {
|
class FileCache
|
||||||
|
{
|
||||||
private $cacheDir;
|
private $cacheDir;
|
||||||
private $defaultExpiration;
|
private $defaultExpiration;
|
||||||
|
|
||||||
public function __construct($cacheDir = 'cache', $defaultExpiration = 60) {
|
public function __construct($cacheDir = '../storage/cache', $defaultExpiration = 60)
|
||||||
|
{
|
||||||
$this->cacheDir = $cacheDir;
|
$this->cacheDir = $cacheDir;
|
||||||
$this->defaultExpiration = $defaultExpiration;
|
$this->defaultExpiration = $defaultExpiration;
|
||||||
// Create the cache directory if it doesn't exist
|
// Create the cache directory if it doesn't exist
|
1160
package-lock.json
generated
|
@ -6,10 +6,11 @@ date_default_timezone_set('Europe/Berlin');
|
||||||
// Define currencies that should *not* be included in the list
|
// Define currencies that should *not* be included in the list
|
||||||
$excludedCurrencies = ['bits', 'sats'];
|
$excludedCurrencies = ['bits', 'sats'];
|
||||||
|
|
||||||
require_once __DIR__ . '/cache.php';
|
require_once '../lib/cache.php';
|
||||||
|
|
||||||
// Fetch JSON data from a file and decode it
|
// Fetch JSON data from a file and decode it
|
||||||
function fetchJson($filename) {
|
function fetchJson($filename)
|
||||||
|
{
|
||||||
return json_decode(file_get_contents($filename), true);
|
return json_decode(file_get_contents($filename), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +22,8 @@ function fetchCache(string $key, string $url, FileCache $cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make an API request and return the JSON response
|
// Make an API request and return the JSON response
|
||||||
function makeApiRequest($url) {
|
function makeApiRequest($url)
|
||||||
|
{
|
||||||
$ch = curl_init($url);
|
$ch = curl_init($url);
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
$json = curl_exec($ch);
|
$json = curl_exec($ch);
|
||||||
|
@ -36,15 +38,19 @@ function makeApiRequest($url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get CoinGecko key URL parameter
|
// Get CoinGecko key URL parameter
|
||||||
function getCoinGeckoApiUrl($path, $params = []) {
|
function getCoinGeckoApiUrl($path, $params = [])
|
||||||
$secrets = require_once 'secrets.php';
|
{
|
||||||
$key = $secrets['coingecko_api_key'];
|
$secrets = require '../secrets.php';
|
||||||
$demo = $secrets['coingecko_key_is_demo'];
|
$demo = $secrets['coingecko_key_is_demo'];
|
||||||
|
|
||||||
|
if ($secrets['use_api_key'] === true) {
|
||||||
|
$key = $secrets['coingecko_api_key'];
|
||||||
$paramName = $demo ? 'x_cg_demo_api_key' : 'x_cg_pro_api_key';
|
$paramName = $demo ? 'x_cg_demo_api_key' : 'x_cg_pro_api_key';
|
||||||
|
$params[$paramName] = $key;
|
||||||
|
}
|
||||||
|
|
||||||
$baseUrl = $demo ? "https://api.coingecko.com/api/v3/" : "https://pro-api.coingecko.com/api/v3/";
|
$baseUrl = $demo ? "https://api.coingecko.com/api/v3/" : "https://pro-api.coingecko.com/api/v3/";
|
||||||
|
|
||||||
$params[$paramName] = $key;
|
|
||||||
$url = $baseUrl . $path;
|
$url = $baseUrl . $path;
|
||||||
|
|
||||||
if (!empty($params)) {
|
if (!empty($params)) {
|
||||||
|
@ -58,8 +64,9 @@ $currentTime = time();
|
||||||
|
|
||||||
// Fetch list of available currencies from CoinGecko API
|
// Fetch list of available currencies from CoinGecko API
|
||||||
// Available currencies are cached for 24 hours
|
// Available currencies are cached for 24 hours
|
||||||
function fetchAvailableCurrencies() {
|
function fetchAvailableCurrencies()
|
||||||
$cacheFile = 'coingecko-currencies.json';
|
{
|
||||||
|
$cacheFile = dirname(__DIR__) . '/storage/coingecko-currencies.json';
|
||||||
$cacheTime = 86400;
|
$cacheTime = 86400;
|
||||||
|
|
||||||
// Return cached data if it exists and is less than 24 hours old
|
// Return cached data if it exists and is less than 24 hours old
|
||||||
|
@ -75,21 +82,23 @@ function fetchAvailableCurrencies() {
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch currency data from CoinGecko API
|
// Fetch currency data from CoinGecko API
|
||||||
function fetchCurrencyData($currencies) {
|
function fetchCurrencyData($currencies)
|
||||||
$cache = new FileCache(__DIR__ . '/cache');
|
{
|
||||||
|
$cache = new FileCache(dirname(__DIR__) . '/storage/cache');
|
||||||
$apiUrl = getCoinGeckoApiUrl('simple/price', ['ids' => 'monero', 'vs_currencies' => implode(',', array_map('strtolower', $currencies))]);
|
$apiUrl = getCoinGeckoApiUrl('simple/price', ['ids' => 'monero', 'vs_currencies' => implode(',', array_map('strtolower', $currencies))]);
|
||||||
return fetchCache('currency_data', $apiUrl, $cache);
|
return fetchCache('currency_data', $apiUrl, $cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
$currencyFile = 'coingecko.json';
|
$currencyFile = dirname(__DIR__) . '/storage/coingecko.json';
|
||||||
$originalFile = 'coingecko-original.json';
|
$originalFile = dirname(__DIR__) . '/storage/coingecko-original.json';
|
||||||
|
|
||||||
// Function to process currency data
|
// Function to process currency data
|
||||||
function processCurrencyData($availableCurrencies, $previousData, $currentTime, $excludedCurrencies) {
|
function processCurrencyData($availableCurrencies, $previousData, $currentTime, $excludedCurrencies)
|
||||||
|
{
|
||||||
// Remove excluded currencies
|
// Remove excluded currencies
|
||||||
$availableCurrencies = array_diff($availableCurrencies, $excludedCurrencies);
|
$availableCurrencies = array_diff($availableCurrencies, $excludedCurrencies);
|
||||||
$currencies = array_map('strtoupper', $availableCurrencies);
|
$currencies = array_map('strtoupper', $availableCurrencies);
|
||||||
|
@ -116,7 +125,7 @@ function processCurrencyData($availableCurrencies, $previousData, $currentTime,
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$previousData = fetchJson($currencyFile);
|
$previousData = file_exists($currencyFile) ? fetchJson($currencyFile) : ["time" => 0];
|
||||||
$output = $previousData;
|
$output = $previousData;
|
||||||
|
|
||||||
// Check if five seconds have passed since the last update
|
// Check if five seconds have passed since the last update
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 952 B After Width: | Height: | Size: 952 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 589 B After Width: | Height: | Size: 589 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 671 B After Width: | Height: | Size: 671 B |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3 KiB |
|
@ -4,23 +4,24 @@ header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
|
||||||
header("Cache-Control: post-check=0, pre-check=0", false);
|
header("Cache-Control: post-check=0, pre-check=0", false);
|
||||||
header("Pragma: no-cache");
|
header("Pragma: no-cache");
|
||||||
|
|
||||||
|
$COINGECKO_JSON_PATH = dirname(__DIR__) . '/storage/coingecko.json';
|
||||||
|
|
||||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
|
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
|
||||||
$currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
$currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
||||||
$parentUrl = dirname($currentUrl);
|
$parentUrl = dirname($currentUrl);
|
||||||
|
|
||||||
// Get currency data from JSON
|
// Get currency data from JSON
|
||||||
if (!file_exists('coingecko.json')) {
|
if (!file_exists($COINGECKO_JSON_PATH)) {
|
||||||
// Special case: First run.
|
`php coingecko.php`;
|
||||||
exec('php coingecko.php');
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$api_cg = json_decode(file_get_contents('coingecko.json'), true);
|
$api_cg = json_decode(file_get_contents($COINGECKO_JSON_PATH), true);
|
||||||
|
|
||||||
// Configuration file
|
// Configuration file
|
||||||
$config = [];
|
$config = [];
|
||||||
if (file_exists('config.php')) {
|
if (file_exists(dirname(__DIR__) . '/config.php')) {
|
||||||
$config = require_once 'config.php';
|
$config = require_once '../config.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
$display_servers_guru = isset($config['servers_guru']) && $config['servers_guru'] === true;
|
$display_servers_guru = isset($config['servers_guru']) && $config['servers_guru'] === true;
|
||||||
|
@ -71,8 +72,8 @@ $language_code = explode('-', $lang)[0];
|
||||||
$language_files = ["en", $language_code, $lang];
|
$language_files = ["en", $language_code, $lang];
|
||||||
|
|
||||||
foreach ($language_files as $language_file) {
|
foreach ($language_files as $language_file) {
|
||||||
if (file_exists('lang/' . $language_file . '.php')) {
|
if (file_exists('../lang/' . $language_file . '.php')) {
|
||||||
require_once 'lang/' . $language_file . '.php';
|
require_once '../lang/' . $language_file . '.php';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,5 +107,4 @@ foreach (array_reverse($preferred_currencies) as $currency) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output the HTML
|
// Output the HTML
|
||||||
require_once 'templates/index.php';
|
require_once '../templates/index.php';
|
||||||
?>
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'coingecko_api_key' => 'CG-xxxx',
|
'coingecko_api_key' => 'CG-xxxx',
|
||||||
'coingecko_key_is_demo' => true,
|
'coingecko_key_is_demo' => true,
|
||||||
|
'use_api_key' => false,
|
||||||
];
|
];
|
0
storage/.gitkeep
Normal file
|
@ -1,7 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="<?php echo $lang_meta; ?>" <?php if ($rtl) {
|
<html lang="<?php echo $lang_meta ?>" <?= $rtl ? 'dir="rtl"' : '' ?>>
|
||||||
echo 'dir="rtl"';
|
|
||||||
} ?>>
|
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
|
|
@ -10,7 +10,7 @@ module.exports = {
|
||||||
entry: './src/js/main.js',
|
entry: './src/js/main.js',
|
||||||
output: {
|
output: {
|
||||||
filename: 'main.js',
|
filename: 'main.js',
|
||||||
path: path.resolve(__dirname, 'js'),
|
path: path.resolve(__dirname, 'public/js'),
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
@ -29,7 +29,7 @@ module.exports = {
|
||||||
}),
|
}),
|
||||||
new PurgeCSSPlugin({
|
new PurgeCSSPlugin({
|
||||||
paths: glob.sync([
|
paths: glob.sync([
|
||||||
path.join(__dirname, 'index.php'),
|
path.join(__dirname, 'public/index.php'),
|
||||||
path.join(__dirname, 'src/js/*.js'),
|
path.join(__dirname, 'src/js/*.js'),
|
||||||
path.join(__dirname, 'templates/*.php'),
|
path.join(__dirname, 'templates/*.php'),
|
||||||
]),
|
]),
|
||||||
|
|