diff --git a/src/server/httpServer.ts b/src/server/httpServer.ts index 3296728..5ff9ed3 100644 --- a/src/server/httpServer.ts +++ b/src/server/httpServer.ts @@ -1,5 +1,7 @@ import express, { Express, Request, Response } from 'express'; import { Server } from 'http'; +import path from 'path'; +import fs from 'fs'; import { logger } from '../utils/logger'; import { config } from '../config'; import { runAuthTests, runSingleVariant, getVariantIds } from '../bot/authTestProcedure'; @@ -184,5 +186,61 @@ export class HttpServer { res.status(500).json({ error: (error as Error).message }); } }); + + // List screenshots for a session + // Filename format: {sessionId}-{step}-{timestamp}.png + this._app.get('/api/bot/screenshots/:sessionId', (req: Request, res: Response) => { + try { + const { sessionId } = req.params; + const screenshotDir = config.screenshotDir; + + if (!fs.existsSync(screenshotDir)) { + res.json({ screenshots: [] }); + return; + } + + const files = fs.readdirSync(screenshotDir) + .filter(f => f.startsWith(`${sessionId}-`) && f.endsWith('.png')) + .sort(); + + const screenshots = files.map(name => { + const stats = fs.statSync(path.join(screenshotDir, name)); + const withoutExt = name.replace('.png', ''); + const parts = withoutExt.split('-'); + // sessionId is a UUID (5 parts joined by -), step follows, timestamp is last + const timestamp = parseInt(parts[parts.length - 1], 10) || 0; + const step = parts.slice(5, -1).join('-'); + return { name, step, timestamp, sizeBytes: stats.size }; + }); + + res.json({ screenshots }); + } catch (error) { + logger.error('Error listing screenshots:', error); + res.status(500).json({ error: (error as Error).message }); + } + }); + + // Serve a single screenshot file + this._app.get('/api/bot/screenshots/file/:filename', (req: Request, res: Response) => { + try { + const { filename } = req.params; + + if (!filename.endsWith('.png') || filename.includes('..') || filename.includes('/') || filename.includes('\\')) { + res.status(400).json({ error: 'Invalid filename' }); + return; + } + + const filepath = path.join(config.screenshotDir, filename); + if (!fs.existsSync(filepath)) { + res.status(404).json({ error: 'Screenshot not found' }); + return; + } + + res.type('image/png').sendFile(path.resolve(filepath)); + } catch (error) { + logger.error('Error serving screenshot:', error); + res.status(500).json({ error: (error as Error).message }); + } + }); } }