* @license Unlicense https://unlicense.org/ * @link https://github.com/ksolomon/Torn-Vault-Tracker */ /** * Checks if the database is new and empty. * * This function checks if the 'vault' table in the database has any entries. * If it does not, it returns true, indicating that the database is new and * empty. Otherwise, it returns false. * * @return boolean True if the database is new and empty, false otherwise. */ function dbNew() { $pdo = getDatabaseConnection(); $stmt = $pdo->query("SELECT COUNT(*) FROM vault"); return $stmt->fetchColumn() == 0; } /** * Ensures that a user has an API key configured. * * @param string $user The user to check the API key for * * @return void * * @throws Exception If the user does not have an API key configured */ function ensureUserHasApiKey($user) { if (!array_key_exists($user, USER_KEYS)) { throw new ApiKeyMissingException("User does not have an API key configured."); } } /** * Executes a GET request to the given API endpoint and returns the JSON response as an associative array. * * Uses the v2 Torn API authentication scheme by sending the API key in an * `Authorization: ApiKey ` header. The key is never transmitted as a * query parameter. * * @param string $apiEndpoint The URL of the API endpoint to call * @param string $apiKey The v2 API key to authenticate with * * @throws ApiKeyMissingException If the API key is empty * @throws CurlErrorException If the cURL call fails * @throws JsonDataException If the response body cannot be decoded as JSON * * @return array The JSON response from the API */ function executeApiCall($apiEndpoint, $apiKey) { if (empty($apiKey)) { throw new ApiKeyMissingException('API key is required for executeApiCall.'); } $headers = ["Authorization: ApiKey $apiKey"]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $apiEndpoint); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $response = curl_exec($ch); if (curl_errno($ch)) { throw new CurlErrorException("cURL error: " . curl_error($ch)); } curl_close($ch); $responseData = json_decode($response, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new JsonDataException("Failed to decode JSON response: " . json_last_error_msg()); } return $responseData; } /** * Validates the API response data for the presence of a log array. * * @param array $responseData The API response data to validate. * * @return void * * @throws Exception If the log data is missing or not an array. */ function validateApiResponse($responseData) { if (!isset($responseData['log']) || !is_array($responseData['log'])) { throw new ApiValidationException('Invalid log data received from the API.'); } } /** * Prepare a PDO statement for checking if a given vault transaction already exists in the database. * * @param PDO $pdo The PDO instance to prepare the statement with * * @return PDOStatement The prepared statement */ function prepareCheckStatement($pdo) { $checkQuery = "SELECT COUNT(*) FROM vault WHERE user = :user AND timestamp = :timestamp AND amount = :amount"; return $pdo->prepare($checkQuery); } /** * Prepare a PDO statement for inserting a new vault transaction into the database. * * @param PDO $pdo The PDO instance to prepare the statement with * * @return PDOStatement The prepared statement */ function prepareInsertStatement($pdo) { $insertQuery = "INSERT INTO vault (ID, user, timestamp, description, amount) VALUES (:id, :user, :timestamp, :description, :amount)"; return $pdo->prepare($insertQuery); } /** * Process an array of log entries retrieved from the Torn API. * * Goes through each log entry and checks if it's a vault deposit or withdrawal. * If it is, it checks if the entry already exists in the database. If it * doesn't, it inserts the entry into the database. * * @param array $logEntries The array of log entries to process * @param string $user The user whose log entries are being processed * @param PDOStatement $checkStmt A prepared statement to check if an entry * already exists in the database * @param PDOStatement $insertStmt A prepared statement to insert a new entry * into the database * @param boolean $debug Whether to output debug information (default: false) * * @return void */ function processLogEntries($logEntries, $user, $checkStmt, $insertStmt, $debug) { foreach ($logEntries as $key =>$entry) { if ($debug) { $logMessage = "Raw entry:\n" . print_r($entry, true); file_put_contents(__DIR__ . '/debug.log', $logMessage, FILE_APPEND); } $timestamp = $entry['timestamp']; $description = $entry['title']; $amount = $entry['log'] === 5850 ? $entry['data']['deposited'] : -$entry['data']['withdrawn']; if ($debug) { $logMessage = "Vault entry:\n\tUser: $user,\n\tTimestamp: $timestamp,\n\tDescription: $description,\n\tAmount: $amount\n"; file_put_contents(__DIR__ . '/debug.log', $logMessage, FILE_APPEND); } $checkStmt->execute( [ ':user' => $user, ':timestamp' => $timestamp, ':amount' => $amount ] ); if ($checkStmt->fetchColumn() == 0) { $insertStmt->execute( [ ':id' => $key, ':user' => $user, ':timestamp' => $timestamp, ':description' => $description, ':amount' => $amount ] ); } } } /** * Fetch vault records from the database * If a user is provided, only that user's records * are returned. Otherwise, all records are returned. * * @param string $user (optional) The user to filter by * * @return array An array of records, or an empty array on error */ function fetchVaultRecords($user = null) { $pdo = getDatabaseConnection(); if ($user) { $query = "SELECT * FROM vault WHERE user = :user ORDER BY timestamp DESC"; $params = [':user' => $user]; } else { $query = "SELECT * FROM vault ORDER BY timestamp DESC"; $params = []; } try { $stmt = $pdo->prepare($query); $stmt->execute($params); return $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { echo "Error fetching records: " . $e->getMessage(); return []; } } /** * Iterate over all vault records for the given user (or all users if no user is given), * * @param string|null $name (optional) The user to loop over records for. * If not provided, all users' records will be looped over. * * @return int The total balance of the given user (or all users if no user is given). */ function vaultLoop ($name=null) { $vault = fetchVaultRecords($name); $balance = 0; foreach ($vault as $entry) { $balance += $entry['amount']; } return $balance; } /** * Returns a string indicating the sign of a number, with a dollar symbol. * * @param int|float $number The number to check. * * @return string A string containing a dollar sign and a negative sign if the * number is negative. */ function getSign($number) { if (substr($number, 0, 1) == '-') { return '-$'; } return '$'; }