Improve and document replay search API

This commit is contained in:
Guangcong Luo 2020-04-16 03:52:33 -04:00
parent 03e88a187a
commit 34388e59f2
4 changed files with 91 additions and 13 deletions

58
WEB-API.md Normal file
View File

@ -0,0 +1,58 @@
Pokémon Showdown website APIs
=============================
Most PS APIs that you would want to access programmatically are available by adding `.json` to the URL.
Replays
-------
Getting a replay:
https://replay.pokemonshowdown.com/gen8doublesubers-1097585496.json
https://replay.pokemonshowdown.com/gen8doublesubers-1097585496.log
Replay search
-------------
List recent replays:
https://replay.pokemonshowdown.com/search.json
Search by user:
https://replay.pokemonshowdown.com/search.json?user=zarel
Search by multiple users:
https://replay.pokemonshowdown.com/search.json?user=zarel&user2=yuyuko
Search by format:
https://replay.pokemonshowdown.com/search.json?format=gen8ou
Combined searching:
https://replay.pokemonshowdown.com/search.json?user=zarel&user2=yuyuko&format=gen7randombattle
Paginate searches:
https://replay.pokemonshowdown.com/search.json?user=zarel&page=2
Searches are limited to 51 results, and pages are offset by 50 each, so the existence of a 51st result means that there's at least one more page available.
Pagination is not supported for the recent replays list, but is supported for everything else.
Users (including ladder information)
------------------------------------
https://pokemonshowdown.com/users/zarel.json
Ladders
-------
https://pokemonshowdown.com/ladder/gen8ou.json

12
replays/README.md Normal file
View File

@ -0,0 +1,12 @@
PS replays database
===================
This is the code powering https://replay.pokemonshowdown.com/
JSON API
--------
The replays database has a JSON API, documented at:
https://github.com/smogon/pokemon-showdown-client/blob/master/WEB-API.md

View File

@ -94,13 +94,14 @@ class Replays {
$isPrivate = ($args["isPrivate"] ?? null) ? 1 : 0;
$byRating = $args["byRating"] ?? null;
$format = ($args["format"] ?? null) ? $this->toId($args["format"]) : null;
if ($args["username"] ?? null) {
$order = $byRating ? "rating" : "uploadtime";
$userid = $this->toId($args["username"]);
if ($args["username2"] ?? null) {
$userid2 = $this->toId($args["username2"]);
if ($args["format"] ?? null) {
$format = $this->toId($args["format"]);
if ($format) {
$res = $this->db->prepare("(SELECT uploadtime, id, format, p1, p2, password FROM ps_replays FORCE INDEX (p1) WHERE private = ? AND p1id = ? AND p2id = ? AND format = ? ORDER BY $order DESC) UNION (SELECT uploadtime, id, format, p1, p2, password FROM ps_replays FORCE INDEX (p1) WHERE private = ? AND p1id = ? AND p2id = ? AND format = ? ORDER BY $order DESC) ORDER BY $order DESC LIMIT $limit1, 51;");
$res->execute([$isPrivate, $userid, $userid2, $format, $isPrivate, $userid2, $userid, $format]);
} else {
@ -108,9 +109,9 @@ class Replays {
$res->execute([$isPrivate, $userid, $userid2, $isPrivate, $userid2, $userid]);
}
} else {
if ($args["format"] ?? null) {
if ($format) {
$res = $this->db->prepare("(SELECT uploadtime, id, format, p1, p2, password FROM ps_replays FORCE INDEX (p1) WHERE private = ? AND p1id = ? AND format = ? ORDER BY $order DESC) UNION (SELECT uploadtime, id, format, p1, p2, password FROM ps_replays FORCE INDEX (p2) WHERE private = ? AND p2id = ? AND format = ? ORDER BY uploadtime DESC) ORDER BY $order DESC LIMIT $limit1, 51;");
$res->execute([$isPrivate, $userid, $this->toId($args["format"]), $isPrivate, $userid, $format]);
$res->execute([$isPrivate, $userid, $format, $isPrivate, $userid, $format]);
} else {
$res = $this->db->prepare("(SELECT uploadtime, id, format, p1, p2, password FROM ps_replays FORCE INDEX (p1) WHERE private = ? AND p1id = ? ORDER BY $order DESC) UNION (SELECT uploadtime, id, format, p1, p2, password FROM ps_replays FORCE INDEX (p2) WHERE private = ? AND p2id = ? ORDER BY uploadtime DESC) ORDER BY $order DESC LIMIT $limit1, 51;");
$res->execute([$isPrivate, $userid, $isPrivate, $userid]);
@ -125,7 +126,7 @@ class Replays {
} else {
$res = $this->db->prepare("SELECT uploadtime, id, format, p1, p2, password FROM ps_replays FORCE INDEX (format) WHERE private = ? AND formatid = ? ORDER BY uploadtime DESC LIMIT $limit1, 51");
}
$res->execute([$isPrivate, $this->toId($args["format"])]);
$res->execute([$isPrivate, $format]);
return $res->fetchAll();
}

View File

@ -1,7 +1,8 @@
<?php
$username = @$_REQUEST['user'];
$format = ($username ? '' : @$_REQUEST['format']);
$username2 = @$_REQUEST['user2'];
$format = @$_REQUEST['format'];
$contains = (@$_REQUEST['contains']);
$byRating = isset($_REQUEST['rating']);
$isPrivate = isset($_REQUEST['private']);
@ -14,20 +15,26 @@ include_once '../lib/ntbb-session.lib.php';
$username = $users->userid($username);
$isPrivateAllowed = ($username === $curuser['userid'] || $curuser['userid'] === 'zarel');
if ($isPrivate && !$isPrivateAllowed) {
die('"ERROR: access denied"');
}
$page = intval($_REQUEST['page'] ?? 0);
$replays = null;
if ($page > 25) {
// no
} else if ($username) {
if (!$isPrivate || $isPrivateAllowed) {
$replays = $Replays->search(["username" => $username, "isPrivate" => $isPrivate, "page" => $page]);
}
die('"ERROR: page limit is 25"');
} else if ($username || $format) {
$replays = $Replays->search([
"username" => $username,
"username2" => $username2,
"format" => $format,
"byRating" => $byRating,
"isPrivate" => $isPrivate,
"page" => $page
]);
} else if ($contains) {
$replays = $Replays->fullSearch($contains, $page);
} else if ($format) {
$replays = $Replays->search(["format" => $format, "byRating" => $byRating, "page" => $page]);
} else {
$replays = $Replays->recent();
}