diff --git a/WEB-API.md b/WEB-API.md index 0c1ebb375..64f9cd57e 100644 --- a/WEB-API.md +++ b/WEB-API.md @@ -15,6 +15,14 @@ https://replay.pokemonshowdown.com/gen8doublesubers-1097585496.json https://replay.pokemonshowdown.com/gen8doublesubers-1097585496.log +Getting a replay inputlog directly (only for formats where the team is autogenerated): + +https://replay.pokemonshowdown.com/gen8randombattle-2005209836.inputlog + +Replay logs and inputlogs are also available in the JSON, so the `.log` and `.inputlog` forms are provided only for convenience. + +Also for convenience: scrolling down in the source code for the replay page. Obviously don't _scrape_ it, but `ctrl`+`u` is way faster than futzing with URLs if you just wanted to take a look at it. + Replay search ------------- diff --git a/replay.pokemonshowdown.com/.htaccess b/replay.pokemonshowdown.com/.htaccess index 15e6b0997..c831d0abc 100644 --- a/replay.pokemonshowdown.com/.htaccess +++ b/replay.pokemonshowdown.com/.htaccess @@ -6,4 +6,5 @@ RewriteRule ^recent\.json$ /api/replays/search.json [L,QSA] RewriteRule ^([A-Za-z0-9-]+)$ index.php?name=$1 [L,QSA] RewriteRule ^([A-Za-z0-9-]+)/manage$ replay-manage.php?name=$1&manage [L,QSA] RewriteRule ^([A-Za-z0-9-]+)\.log$ replay.log.php?name=$1 [L,QSA] +RewriteRule ^([A-Za-z0-9-]+)\.inputlog$ replay.log.php?inputlog&name=$1 [L,QSA] RewriteRule ^([A-Za-z0-9-]+)\.json$ replay.log.php?json&name=$1 [L,QSA] diff --git a/replay.pokemonshowdown.com/index.template.php b/replay.pokemonshowdown.com/index.template.php index e3ed3b5df..ab8be0467 100644 --- a/replay.pokemonshowdown.com/index.template.php +++ b/replay.pokemonshowdown.com/index.template.php @@ -19,6 +19,13 @@ ini_set('display_errors', TRUE); ini_set('display_startup_errors', TRUE); $manage = false; +if (isset($_REQUEST['manage'])) { + require_once '../lib/ntbb-session.lib.php'; + if (!$users->isLeader()) die("access denied"); + $csrfOk = !!$users->csrfCheck(); + $manage = true; + header('Cache-Control: max-age=0, no-cache, no-store, must-revalidate'); +} $replay = null; $id = $_REQUEST['name'] ?? ''; @@ -262,11 +269,22 @@ https://replay.pokemonshowdown.com/gen7randomdoublesbattle-865046831.log if ($replay) { // `src/repays-battle.tsx` can also grab this data from our APIs, but // doing it here increases page load speed - echo "\n"; - echo ''."\n"; + if ($replay['safe_inputlog'] || $manage) { + if (!$replay['safe_inputlog']) echo ''."\n"; + echo ''."\n"; + } + unset($replay['log']); unset($replay['inputlog']); - echo json_encode($replay); - echo ''; + unset($replay['safe_inputlog']); + echo ''."\n"; } ?> diff --git a/replay.pokemonshowdown.com/replay.log.php b/replay.pokemonshowdown.com/replay.log.php index 9f952a292..7b515f31e 100644 --- a/replay.pokemonshowdown.com/replay.log.php +++ b/replay.pokemonshowdown.com/replay.log.php @@ -67,12 +67,16 @@ if ($replay['password'] ?? null) { } if (@$replay['inputlog']) { - if (substr($replay['formatid'], -12) === 'randombattle' || substr($replay['formatid'], -19) === 'randomdoublesbattle' || $replay['formatid'] === 'gen7challengecup' || $replay['formatid'] === 'gen7challengecup1v1' || $replay['formatid'] === 'gen7battlefactory' || $replay['formatid'] === 'gen7bssfactory' || $replay['formatid'] === 'gen7hackmonscup' || $manage) { + if ( + $replay['safe_inputlog'] || + $manage + ) { // ok } else { unset($replay['inputlog']); } } +unset($replay['safe_inputlog']); if (isset($_REQUEST['json'])) { $matchSuccess = preg_match('/\\n\\|tier\\|([^|]*)\\n/', $replay['log'], $matches); diff --git a/replay.pokemonshowdown.com/replays.lib.php b/replay.pokemonshowdown.com/replays.lib.php index c1007a509..2cdd41412 100644 --- a/replay.pokemonshowdown.com/replays.lib.php +++ b/replay.pokemonshowdown.com/replays.lib.php @@ -66,14 +66,18 @@ class Replays { if ($player[0] === '!') $player = substr($player, 1); } - // if ($replay['private'] && !($replay['password'] ?? null)) { - // $replay['password'] = $this->genPassword(); - // $res = $this->db->prepare("UPDATE ps_replays SET views = views + 1, `password` = ? WHERE id = ? LIMIT 1"); - // $res->execute([$replay['password'], $id]); - // } else { - $res = $this->db->prepare("UPDATE replays SET views = views + 1 WHERE id = ? LIMIT 1"); - $res->execute([$id]); - // } + $res = $this->db->prepare("UPDATE replays SET views = views + 1 WHERE id = ? LIMIT 1"); + $res->execute([$id]); + + $replay['safe_inputlog'] = ( + str_ends_with($replay['formatid'], 'randombattle') || + str_ends_with($replay['formatid'], 'randomdoublesbattle') || + str_ends_with($replay['formatid'], 'challengecup') || + str_ends_with($replay['formatid'], 'challengecup1v1') || + str_ends_with($replay['formatid'], 'battlefactory') || + str_ends_with($replay['formatid'], 'bssfactory') || + str_ends_with($replay['formatid'], 'hackmonscup') + ); return $replay; } diff --git a/replay.pokemonshowdown.com/src/replays-battle.tsx b/replay.pokemonshowdown.com/src/replays-battle.tsx index 8358dafbe..93fe2a45e 100644 --- a/replay.pokemonshowdown.com/src/replays-battle.tsx +++ b/replay.pokemonshowdown.com/src/replays-battle.tsx @@ -94,10 +94,11 @@ export class BattlePanel extends preact.Component<{id: string}> { this.forceUpdate(); const elem = document.getElementById(`replaydata-${id}`); + const logElem = document.getElementById(`replaylog-${id}`); if (elem) { // we actually do need to wait for that update to finish so // loadResult definitely has access to $frame and $logFrame - setTimeout(() => this.loadResult(elem.innerText, id), 1); + setTimeout(() => this.loadResult(elem.innerText, id, logElem?.innerText.replace(/<\\\//g, ' { this.loadResult(err.statusCode === 404 ? '' : String(err?.body || ''), id); }); } - loadResult(result: string, id: string) { + loadResult(result: string, id: string, log = '') { try { const replay: NonNullable = JSON.parse(result); + replay.log ||= log; this.result = replay; const $base = $(this.base!); this.battle = new Battle({