add TSS API endpoints + web proxy (#1234)
Adds /api/tss/teams/* and /api/tss/leaderboard/teams to SREBOT/server.js, reading tss_battles.db and tss_teams.db with queries adapted to the team_id / team_name / teams_data schema. Mirrors the existing /api/squadrons/* endpoints. SREBOT/web/server.js gains matching proxy routes so the frontend can reach them via the website host. TSSBOT/BOT/storage.py picks up the columns and table the endpoints need to return meaningful data: teams_data.clanrating, team_members.points, and a new teams_points history table. All idempotent under the existing init_tss_dbs() call. Co-authored-by: Heidi <clippii@protonmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2181,6 +2181,98 @@ app.get('/api/squadrons/:name/games', cors(apiCorsOptions), async (req, res) =>
|
||||
}
|
||||
});
|
||||
|
||||
// ── TSS proxy routes ───────────────────────────────────────────────────────
|
||||
// Mirrors the /api/squadrons/* proxy block above but targets the upstream
|
||||
// /api/tss/* endpoints (defined in SREBOT/server.js) which read tss_battles.db
|
||||
// and tss_teams.db. Both /api/tss/teams/* and /api/tss/squadrons/* are
|
||||
// supported upstream — we proxy the canonical /teams/* path here.
|
||||
const TSS_BACKEND = () => process.env.EXTERNAL_API_URL || 'http://127.0.0.1:6000';
|
||||
|
||||
function _forwardDateParams(req) {
|
||||
const qp = new URLSearchParams();
|
||||
if (req.query.start_date) qp.append('start_date', req.query.start_date);
|
||||
if (req.query.end_date) qp.append('end_date', req.query.end_date);
|
||||
if (req.query.season) qp.append('season', req.query.season);
|
||||
if (req.query.week) qp.append('week', req.query.week);
|
||||
return qp;
|
||||
}
|
||||
|
||||
app.get('/api/tss/teams/resolve', cors(apiCorsOptions), async (req, res) => {
|
||||
try {
|
||||
const name = req.query.name || req.query.q || req.query.team || '';
|
||||
const apiUrl = `${TSS_BACKEND()}/api/tss/teams/resolve?name=${encodeURIComponent(name)}`;
|
||||
const response = await fetch(apiUrl);
|
||||
if (!response.ok) return res.status(response.status).json({ error: 'Failed to resolve TSS team' });
|
||||
res.json(await response.json());
|
||||
} catch (err) {
|
||||
log.error('Error resolving TSS team', err);
|
||||
res.status(500).json({ error: 'Failed to resolve TSS team' });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/tss/leaderboard/teams', cors(apiCorsOptions), async (req, res) => {
|
||||
try {
|
||||
const qp = _forwardDateParams(req);
|
||||
if (req.query.limit) qp.append('limit', req.query.limit);
|
||||
const qs = qp.toString();
|
||||
const apiUrl = `${TSS_BACKEND()}/api/tss/leaderboard/teams${qs ? '?' + qs : ''}`;
|
||||
const response = await fetch(apiUrl);
|
||||
if (!response.ok) return res.status(response.status).json({ error: 'Failed to fetch TSS leaderboard', teams: [], total_teams: 0 });
|
||||
res.json(await response.json());
|
||||
} catch (err) {
|
||||
log.error('Error in TSS leaderboard proxy', err);
|
||||
res.status(500).json({ error: 'Failed to fetch TSS leaderboard', teams: [], total_teams: 0 });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/tss/teams/:name', cors(apiCorsOptions), async (req, res) => {
|
||||
try {
|
||||
const qs = _forwardDateParams(req).toString();
|
||||
const apiUrl = `${TSS_BACKEND()}/api/tss/teams/${encodeURIComponent(req.params.name)}${qs ? '?' + qs : ''}`;
|
||||
const response = await fetch(apiUrl);
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
return res.status(404).json({ error: 'TSS team not found', players: [] });
|
||||
}
|
||||
return res.status(response.status).json({ error: 'Failed to fetch TSS team details' });
|
||||
}
|
||||
res.json(await response.json());
|
||||
} catch (err) {
|
||||
log.error('Error fetching TSS team details', err);
|
||||
res.status(500).json({ error: 'Failed to fetch TSS team details' });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/tss/teams/:name/history', cors(apiCorsOptions), async (req, res) => {
|
||||
try {
|
||||
const apiUrl = `${TSS_BACKEND()}/api/tss/teams/${encodeURIComponent(req.params.name)}/history`;
|
||||
const response = await fetch(apiUrl);
|
||||
if (!response.ok) return res.status(response.status).json({ error: 'Failed to fetch TSS team history' });
|
||||
res.json(await response.json());
|
||||
} catch (err) {
|
||||
log.error('Error fetching TSS team history', err);
|
||||
res.status(500).json({ error: 'Failed to fetch TSS team history' });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/tss/teams/:name/games', cors(apiCorsOptions), async (req, res) => {
|
||||
try {
|
||||
const qs = _forwardDateParams(req).toString();
|
||||
const apiUrl = `${TSS_BACKEND()}/api/tss/teams/${encodeURIComponent(req.params.name)}/games${qs ? '?' + qs : ''}`;
|
||||
const response = await fetch(apiUrl);
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
return res.status(404).json({ games: [], total_games_returned: 0, error: 'TSS team not found' });
|
||||
}
|
||||
return res.status(response.status).json({ error: 'Failed to fetch TSS team games' });
|
||||
}
|
||||
res.json(await response.json());
|
||||
} catch (err) {
|
||||
log.error('Error fetching TSS team games', err);
|
||||
res.status(500).json({ error: 'Failed to fetch TSS team games', games: [], total_games_returned: 0 });
|
||||
}
|
||||
});
|
||||
|
||||
// API Routes with better error handling
|
||||
let statsCache = null;
|
||||
let statsCacheTime = 0;
|
||||
|
||||
Reference in New Issue
Block a user