Files
Torn-Vault-Tracker/functions.php
T

199 lines
6.0 KiB
PHP

<?php
/**
* Functions for the Torn Vault Tracker application.
*
* PHP version 8.1+
*
* @category Functions
* @package TornVaultTracker
* @author Keith Solomon <ksolomon@gmail.com>
* @license Unlicense https://unlicense.org/
* @link https://github.com/ksolomon/TornVaultTracker
*/
// Include settings from configuration file
require_once __DIR__ . '/config.php';
// Include utility functions
require_once 'includes/exceptions.php';
require_once 'includes/utilities.php';
/**
* Returns a PDO connection to the database
* This function creates the database connection and creates the database
* file if it doesn't exist, and the vault table if it doesn't exist.
*
* @return PDO
*/
function getDatabaseConnection() {
static $pdo = null;
// SQL to create the vault table if it doesn't exist
$createTableSQL = "CREATE TABLE IF NOT EXISTS vault (
id TEXT PRIMARY KEY,
user TEXT NOT NULL,
timestamp INTEGER NOT NULL,
description TEXT NOT NULL,
amount REAL NOT NULL,
running_balance INTEGER
);";
if ($pdo === null) {
try {
$pdo = new PDO(DB_DSN, DB_USER, DB_PASSWORD);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec($createTableSQL);
// Add the running_balance column for databases created before the
// column was added. Idempotent: skip if it already exists.
$columns = $pdo->query("PRAGMA table_info(vault)")->fetchAll(PDO::FETCH_COLUMN, 1);
if (!in_array('running_balance', $columns, true)) {
$pdo->exec('ALTER TABLE vault ADD COLUMN running_balance INTEGER');
}
} catch (PDOException $e) {
die("Database connection failed: " . $e->getMessage());
}
}
return $pdo;
}
/**
* Pulls and stores the full vault transaction log history for a user.
*
* Pages through the v2 Torn API using `_metadata.links.next` until the
* API reports no further pages. Intended for first-run use when the
* local database is empty. Idempotent: re-running on a partially
* populated database inserts only new entries (ON CONFLICT DO NOTHING).
*
* @param string $user The user whose logs should be fetched.
*
* @return void
*/
function backfillUserLogs($user) {
$url = 'https://api.torn.com/v2/user?selections=log&log=5850,5851';
$pdo = getDatabaseConnection();
do {
$next = fetchAndStoreLogPage($pdo, $user, $url);
$url = $next;
} while ($next !== null);
refetchRunningBalances($pdo, $user);
}
/**
* Synchronizes recent vault transactions for a user.
*
* On a non-empty database, fetches only entries newer than the user's
* most recent row. Falls back to full backfill when the database is
* empty.
*
* @param string $user The user whose logs should be synced.
*
* @return void
*/
function syncUserLogs($user) {
if (dbNew()) {
backfillUserLogs($user);
return;
}
$pdo = getDatabaseConnection();
$stmt = $pdo->prepare('SELECT MAX(timestamp) AS max_ts FROM vault WHERE user = :user');
$stmt->bindValue(':user', $user);
$stmt->execute();
$lastTs = (int)$stmt->fetch(PDO::FETCH_ASSOC)['max_ts'];
$url = "https://api.torn.com/v2/user?selections=log&log=5850,5851&from=" . ($lastTs + 1);
do {
$next = fetchAndStoreLogPage($pdo, $user, $url);
$url = $next;
} while ($next !== null);
refetchRunningBalances($pdo, $user);
}
/**
* Generate the current balance for a user or all users
*
* @param string $name (optional) The user to get the balance for. If not provided, all users' balances will be added.
*
* @return string The balance as a formatted string
*/
function generateBalance($name=null) {
$balance = vaultLoop($name);
return number_format($balance, 0); // Format the balance as an integer
}
/**
* Calculate the available vault space for a user or all users.
*
* This function calculates the remaining space in the vault based on the
* transactions for a specific user or all users. If a user is specified,
* the available space is calculated against a limit of 500,000,000.
* If no user is specified, the available space is calculated against a
* total vault limit of 1,000,000,000.
*
* @param string|null $name (optional) The user to calculate the vault space for.
* If not provided, calculates for all users.
*
* @return string The available vault space as a formatted string.
*/
function getSpace($name=null) {
$space = vaultLoop($name);
if ($name === null) {
$space = 1000000000 - $space;
} else {
$space = 500000000 - $space;
}
return number_format($space, 0); // Format the balance as an integer
}
/**
* Builds an HTML table of all transactions in the vault
*
* Loops over all records in the vault and builds a table of the user, timestamp,
* description and amount of each transaction. Amounts are formatted as integers.
*
* @return void
*/
function buildTable () {
$records = fetchVaultRecords();
foreach ($records as $entry) {
$user = $entry['user'];
$timestamp = $entry['timestamp'];
$description = $entry['description'];
$amount = $entry['amount'];
$sign = getSign($amount);
if ($description == 'Vault withdraw') {
$class = 'debit';
$amount = substr($amount, 1); // Remove the negative sign
} else {
$class = 'credit';
}
$amount = number_format($amount, 0); // Format the amount as an integer
$runningBalance = isset($entry['running_balance']) && $entry['running_balance'] !== null
? '$' . number_format((int)$entry['running_balance'], 0)
: '—';
echo '<tr class="'.$class.'">';
echo '<td>'.$user.'</td>';
echo '<td>'.date("F j, Y / H:i", $timestamp).'</td>';
echo '<td>'.$description.'</td>';
echo '<td>'.$sign.$amount.'</td>';
echo '<td>'.$runningBalance.'</td>';
echo '</tr>';
}
}