*/ // Return source code if(isset($_GET['source'])) { header("Content-Type: text/plain"); die(file_get_contents(basename($_SERVER['PHP_SELF']))); } header("Content-Type: application/json"); /* vars.php should contain the following, but with your variables as needed: * * // Database constants for PostgreSQL database * $DB_HOST = 'localhost'; * $DB_NAME = ''; * $DB_USER = ''; * $DB_PASSWORD = ''; * * You also need to run the following SQL: * * CREATE TABLE words ( * id INT PRIMARY KEY, * solution VARCHAR(5) NOT NULL, * print_date VARCHAR(10) NOT NULL, * days_since_launch INT, * editor VARCHAR(64), * access_count INT DEFAULT 0 * ); * * CREATE TABLE update ( * time TIMESTAMPTZ NOT NULL DEFAULT NOW(), * lock BOOL PRIMARY KEY DEFAULT TRUE, * CONSTRAINT lock_unique CHECK(lock) * ); * * INSERT INTO update VALUES (NOW()); */ require_once('vars.php'); //// Functions: //// function get_words($date, $limit, $include) { $query = "SELECT $include FROM words WHERE print_date>=$1 ORDER BY print_date ASC LIMIT $2"; $res = pg_query_params($query, [$date, $limit]) or die('Query failed: ' . pg_last_error()); if(pg_num_rows($res) == 0) { return [ 'status' => 'ERROR', 'message' => 'Already up to date' ]; } while($row = pg_fetch_array($res, null, PGSQL_ASSOC)) { $toint = ['id', 'days_since_launch', 'access_count']; foreach($toint as $key) { if(array_key_exists($key, $row)) $row[$key] = intval($row[$key]); } $words[] = $row; } $query = 'UPDATE words SET access_count=access_count+1 WHERE print_date>=$1'; pg_query_params($query, [$date]) or die('Query failed ' . pg_last_error()); // If just one column, do a straight array if(!str_contains($include, ',')) $words = array_column($words, $include); return $words; } function add_words($datestamp) { $ret = false; while(true) { $date = date('Y-m-d', $datestamp); $query = 'SELECT FROM words WHERE print_date=$1'; $res = pg_query_params($query, [$date]) or die('Query failed: ' . pg_last_error()); if(pg_num_rows($res) == 0) { $content = file_get_contents("https://www.nytimes.com/svc/wordle/v2/$date.json"); if(!$content) break; $word = json_decode($content, true); // The Times' IDs for guess list answers don't seem to have any // relation to the sorted list, so we're doing our own which is: // The index in the guess list array, but 1 indexed and negative require_once('word_lists.php'); if($word['id'] > count(CHOICES)) { $word['id'] = -(array_search(strtoupper($word['solution']), GUESSES) + 1); } // Add word to database $query = 'INSERT INTO words (id, solution, print_date, days_since_launch, editor) ' . 'VALUES ($1, UPPER($2), $3, $4, $5)'; $params = [ $word['id'], $word['solution'], $word['print_date'], $word['days_since_launch'], $word['editor'] ]; pg_query_params($query, $params) or die('Query failed: ' . pg_last_error()); $ret = true; // (at least one) word added } $datestamp += 60 * 60 * 24; } return $ret; } //// Code start: //// // Connect to the database $dbc = pg_connect("host=$DB_HOST dbname=$DB_NAME user=$DB_USER password=$DB_PASSWORD") or die('Could not connect: ' . pg_last_error()); // Check for words once a day $res = pg_query('SELECT EXTRACT(EPOCH FROM time) AS time FROM update') or die('Query failed: ' . pg_last_error()); $cur_time = time(); $last_time = pg_fetch_array($res)['time']; if($cur_time > $last_time + (60 * 60 * 24)) { add_words($cur_time); $query = 'UPDATE update SET time=TO_TIMESTAMP($1)'; pg_query_params($query, [$cur_time]) or die('Query failed: ' . pg_last_error()); } // Get words if($_GET['mode'] == 'mod.json') { header('Content-Disposition: attachment; filename="mod.json"'); echo json_encode([ 'words' => [ 'order' => get_words('2021-06-19', 100000, 'id') ] ]); } else { // Check get vars $date = $_GET['date']; $limit = isset($_GET['limit']) ? intval($_GET['limit']) : 100; $include = isset($_GET['include']) ? $_GET['include'] : 'id,solution,print_date,days_since_launch,editor'; if(!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) { die(json_encode([ 'status' => 'ERROR', 'message' => 'Invalid date format (YYYY-MM-DD)' ])); } else if($date < '2021-06-19') { die(json_encode([ 'status' => 'ERROR', 'message' => 'Date too early' ])); } else if($limit <= 0) { die(json_encode([ 'status' => 'ERROR', 'message' => 'Invalid limit' ])); } else if(!preg_match('/^[a-z,_]+$/', $include)) { die(json_encode([ 'status' => 'ERROR', 'message' => 'Invalid include' ])); } echo json_encode(get_words($date, $limit, $include)); } pg_close($dbc);