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, '')), 1);
return;
}
@@ -107,9 +108,10 @@ export class BattlePanel extends preact.Component<{id: string}> {
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({