ai generated solutions to our ai generated problems

This commit is contained in:
2026-06-19 23:36:45 +01:00
13 changed files with 3003 additions and 211 deletions
+299
View File
@@ -1,4 +1,5 @@
const fs = require('node:fs')
const { execFile } = require('node:child_process')
const crypto = require('node:crypto')
const http = require('node:http')
const https = require('node:https')
@@ -56,6 +57,28 @@ const TURNSTILE_VERIFY_TIMEOUT_MS = Number(process.env.TURNSTILE_VERIFY_TIMEOUT_
const TURNSTILE_MAX_TOKEN_LENGTH = 2048
const TURNSTILE_TOKEN_MAX_AGE_MS = 5 * 60 * 1000
const DIST_DIR = path.join(__dirname, 'dist')
const VEHICLE_ICONS_DIR = path.resolve(
__dirname,
process.env.VEHICLE_ICONS_DIR || path.join('dist', 'vehicle-icons'),
)
const BOTS_REPO_DIR = path.resolve(
expandHome(process.env.BOTS_REPO_DIR || path.join(__dirname, '..', 'BOTS')),
)
const TSSBOT_REPO_DIR = path.resolve(process.env.TSSBOT_REPO_DIR || path.join(BOTS_REPO_DIR, 'TSSBOT'))
const TSS_REPLAY_SAMPLE_DIR = path.join(TSSBOT_REPO_DIR, 'replays_sample')
const TSS_REPLAYS_DIR = path.resolve(
expandHome(
process.env.TSS_REPLAYS_DIR ||
(process.env.STORAGE_VOL_PATH
? path.join(expandHome(process.env.STORAGE_VOL_PATH), 'REPLAYS', 'TSS')
: TSS_REPLAY_SAMPLE_DIR),
),
)
const SHARED_DIR = path.resolve(process.env.SHARED_DIR || path.join(BOTS_REPO_DIR, 'SHARED'))
const TSS_REPLAY_PYTHON = path.resolve(
expandHome(process.env.TSS_REPLAY_PYTHON || path.join(SHARED_DIR, '.venv', 'bin', 'python')),
)
const TSS_REPLAY_RENDER_TIMEOUT_MS = Number(process.env.TSS_REPLAY_RENDER_TIMEOUT_MS || 30000)
const MAX_TEAM_NAME_LENGTH = 80
const MAX_CACHE_ENTRIES = 200
const MAX_RATE_LIMIT_KEYS = 1000
@@ -1591,6 +1614,15 @@ function allowedApiTarget(req) {
}
if (/^\/api\/tss\/games\/[A-Za-z0-9_-]{1,96}$/.test(pathname)) {
const keys = [...params.keys()]
const lang = params.get('lang') || 'en'
if (keys.some((key) => key !== 'lang') || !/^[A-Za-z-]{2,8}$/.test(lang)) {
return null
}
return url
}
if (/^\/api\/tss\/games\/[A-Za-z0-9_-]{1,96}\/logs$/.test(pathname)) {
if ([...params.keys()].length) return null
return url
}
@@ -2042,6 +2074,243 @@ function serveStatic(req, res) {
})
}
function serveVehicleIcon(req, res) {
let requestPath = '/'
try {
requestPath = decodeURIComponent(new URL(req.url, `http://localhost:${PORT}`).pathname)
} catch {
return send(res, 400, 'Bad request', { 'content-type': 'text/plain; charset=utf-8' })
}
const name = requestPath.slice('/vehicle-icons/'.length)
const filePath = path.resolve(VEHICLE_ICONS_DIR, `./${name}`)
const relative = path.relative(VEHICLE_ICONS_DIR, filePath)
if (relative.startsWith('..') || path.isAbsolute(relative) || path.extname(filePath) !== '.png') {
return send(res, 403, 'Forbidden', { 'content-type': 'text/plain; charset=utf-8' })
}
fs.readFile(filePath, (error, data) => {
if (error) {
return send(res, 404, 'Not found', { 'content-type': 'text/plain; charset=utf-8' })
}
send(res, 200, data, {
'content-type': 'image/png',
'cache-control': 'public, max-age=604800',
})
})
}
function safeUniquePaths(paths) {
return [...new Set(paths.filter(Boolean).map((value) => path.resolve(value)))]
}
function resolveTssReplaySessionDir(sessionId) {
const sid = String(sessionId || '').toLowerCase()
const candidates = safeUniquePaths([
path.join(TSS_REPLAYS_DIR, sid),
path.join(TSS_REPLAYS_DIR, `0${sid}`),
path.join(TSS_REPLAY_SAMPLE_DIR, sid),
path.join(TSS_REPLAY_SAMPLE_DIR, `0${sid}`),
])
for (const dir of candidates) {
try {
if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) return dir
} catch {
// Keep trying the remaining replay roots.
}
}
return path.join(TSS_REPLAYS_DIR, sid)
}
function findTssReplayDataPath(sessionDir) {
const candidates = [
path.join(sessionDir, 'replay_data.json.gz'),
path.join(sessionDir, 'replay_data.json'),
]
for (const candidate of candidates) {
try {
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) return candidate
} catch {
// Ignore unreadable candidates and let the caller return 404.
}
}
return null
}
function readFileResponse(req, res, filePath, headers = {}) {
fs.readFile(filePath, (error, data) => {
if (error) {
sendJson(res, 404, { error: 'File not found' })
return
}
send(res, 200, data, headers)
})
}
function runReplayCanvasRenderer(replayPath, jsonPath) {
const pythonBin = fs.existsSync(TSS_REPLAY_PYTHON) ? TSS_REPLAY_PYTHON : 'python3'
return new Promise((resolve, reject) => {
execFile(
pythonBin,
['-m', 'BOT.render_replay', replayPath, jsonPath],
{
cwd: TSSBOT_REPO_DIR,
timeout: TSS_REPLAY_RENDER_TIMEOUT_MS,
env: process.env,
},
(error, stdout, stderr) => {
if (error) {
reject(new Error(String(stderr || stdout || error.message || 'Replay renderer failed').trim()))
return
}
resolve()
},
)
})
}
let tssCanvasRenderCount = 0
const TSS_CANVAS_RENDER_MAX = 3
async function serveTssReplayCanvas(req, res, sessionId) {
if (!sessionId || !/^[A-Za-z0-9_-]{1,96}$/.test(sessionId)) {
sendJson(res, 400, { error: 'Invalid game ID' })
return
}
if (!isSameOriginRequest(req)) {
sendJson(res, 403, { error: 'API access is restricted to this site' })
return
}
if (isRateLimited(req)) {
sendJson(res, 429, { error: 'Too many requests' }, { 'retry-after': String(Math.ceil(API_RATE_LIMIT_WINDOW_MS / 1000)) })
return
}
const sessionDir = resolveTssReplaySessionDir(sessionId)
const replayPath = findTssReplayDataPath(sessionDir)
const jsonPath = path.join(sessionDir, 'replay_canvas.json')
if (!replayPath) {
sendJson(res, 404, { available: false, reason: 'No replay data available' })
return
}
try {
const jsonStat = fs.existsSync(jsonPath) ? fs.statSync(jsonPath) : null
const replayStat = fs.statSync(replayPath)
if (jsonStat && jsonStat.size > 0 && jsonStat.mtimeMs >= replayStat.mtimeMs) {
readFileResponse(req, res, jsonPath, {
'content-type': 'application/json; charset=utf-8',
'cache-control': 'public, max-age=86400',
})
return
}
} catch {
// Fall through and attempt regeneration.
}
if (tssCanvasRenderCount >= TSS_CANVAS_RENDER_MAX) {
sendJson(res, 503, { available: false, reason: 'Too many replays processing; try again shortly' })
return
}
tssCanvasRenderCount += 1
try {
await runReplayCanvasRenderer(replayPath, jsonPath)
if (!fs.existsSync(jsonPath)) {
sendJson(res, 500, { available: false, reason: 'Replay JSON generation produced no output' })
return
}
readFileResponse(req, res, jsonPath, {
'content-type': 'application/json; charset=utf-8',
'cache-control': 'public, max-age=86400',
})
} catch (error) {
try {
if (fs.existsSync(jsonPath)) fs.unlinkSync(jsonPath)
} catch {
// Ignore cache cleanup errors.
}
sendJson(res, 500, { available: false, reason: 'Replay JSON generation failed', detail: error.message })
} finally {
tssCanvasRenderCount -= 1
}
}
function serveReplayIcon(req, res) {
let iconName = ''
try {
const requestPath = decodeURIComponent(new URL(req.url, `http://localhost:${PORT}`).pathname)
iconName = requestPath.slice('/api/icons/type/'.length)
} catch {
sendJson(res, 400, { error: 'Bad request' })
return
}
if (!iconName || !/^[A-Za-z0-9_-]+$/.test(iconName)) {
sendJson(res, 400, { error: 'Invalid icon name' })
return
}
const iconsBase = path.join(SHARED_DIR, 'ICONS')
const candidates = [
path.join(iconsBase, `${iconName}.png`),
path.join(iconsBase, 'FALLBACKS', `${iconName}.png`),
path.join(iconsBase, 'MINIS', `${iconName}.png`),
]
for (const candidate of candidates) {
const relative = path.relative(iconsBase, candidate)
if (relative.startsWith('..') || path.isAbsolute(relative)) continue
if (fs.existsSync(candidate)) {
readFileResponse(req, res, candidate, {
'content-type': 'image/png',
'cache-control': 'public, max-age=604800',
})
return
}
}
sendJson(res, 404, { error: 'Icon not found' })
}
function serveReplayMinimap(req, res) {
let level = ''
let fullMap = false
try {
const url = new URL(req.url, `http://localhost:${PORT}`)
const requestPath = decodeURIComponent(url.pathname)
level = requestPath.slice('/api/match/minimap/'.length)
fullMap = url.searchParams.get('type') === 'full'
} catch {
sendJson(res, 400, { error: 'Bad request' })
return
}
if (!level || !/^[A-Za-z0-9_]+$/.test(level)) {
sendJson(res, 400, { error: 'Invalid level name' })
return
}
const minimapsDir = path.join(SHARED_DIR, 'MAPS', 'MINIMAPS')
const names = fullMap
? [`${level}.png`, `${level}_map.png`]
: [`${level}_tankmap.png`, `${level}.png`, `${level}_map.png`]
for (const name of [...new Set(names)]) {
const candidate = path.resolve(minimapsDir, name)
const relative = path.relative(minimapsDir, candidate)
if (relative.startsWith('..') || path.isAbsolute(relative)) continue
if (fs.existsSync(candidate)) {
readFileResponse(req, res, candidate, {
'content-type': 'image/png',
'cache-control': 'public, max-age=604800',
})
return
}
}
sendJson(res, 404, { error: 'Minimap not found' })
}
const server = http.createServer((req, res) => {
if (req.method === 'GET' && req.url === '/robots.txt') {
sendRobotsTxt(req, res)
@@ -2167,6 +2436,36 @@ const server = http.createServer((req, res) => {
return
}
if (req.method === 'GET') {
let pathname = ''
try {
pathname = new URL(req.url, `http://${req.headers.host || 'localhost'}`).pathname
} catch {
pathname = ''
}
const replayMatch = pathname.match(/^\/api\/tss\/games\/([A-Za-z0-9_-]{1,96})\/replay-canvas$/)
if (replayMatch) {
serveTssReplayCanvas(req, res, replayMatch[1])
return
}
if (pathname.startsWith('/api/icons/type/')) {
serveReplayIcon(req, res)
return
}
if (pathname.startsWith('/api/match/minimap/')) {
serveReplayMinimap(req, res)
return
}
}
if (req.method === 'GET' && req.url.startsWith('/vehicle-icons/')) {
serveVehicleIcon(req, res)
return
}
if (req.url.startsWith('/api/')) {
proxyRequest(req, res)
return