import re with open('server.mjs', 'r', encoding='utf-8') as f: code = f.read() # 1. Replace startup cleanup with loadHistory, cleanupOldRenders, saveHistory, activeSessions definition startup_cleanup_regex = re.compile(r"// Cleanup on startup / rebuild[\s\S]*?\} catch \(err\) \{[\s\S]*?console\.error\('.*?', err\.message\);\n\}") replacement_1 = """// Active export sessions and History Persistence const HISTORY_FILE = path.join(DATA_DIR, 'history.json'); const activeSessions = new Map(); function saveHistory() { try { const historyData = {}; for (const [id, sess] of activeSessions.entries()) { const { ffmpegProc, ...sessData } = sess; historyData[id] = sessData; } fs.writeFileSync(HISTORY_FILE, JSON.stringify(historyData)); } catch (err) { console.error('⚠️ Failed to save history:', err.message); } } function loadHistory() { try { if (fs.existsSync(HISTORY_FILE)) { const data = JSON.parse(fs.readFileSync(HISTORY_FILE, 'utf-8')); for (const [id, sess] of Object.entries(data)) { if (!sess.done) { sess.error = 'Abgebrochen durch Server-Neustart'; sess.done = true; sess.currentStatus = 'Fehler'; } activeSessions.set(id, sess); } console.log(✅ Loaded past sessions from history.json); } } catch (err) { console.error('⚠️ Failed to load history:', err.message); } } function cleanupOldRenders() { console.log('🧹 Running 7-day retention cleanup...'); const MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000; const now = Date.now(); let deletedCount = 0; for (const [id, sess] of activeSessions.entries()) { if (now - sess.createdAt > MAX_AGE_MS) { if (sess.formats) { for (const fmt of Object.values(sess.formats)) { if (fmt.path && fs.existsSync(fmt.path)) { try { fs.unlinkSync(fmt.path); } catch (e) {} } } } activeSessions.delete(id); deletedCount++; } } if (deletedCount > 0) { console.log(🗑️ Deleted old sessions.); saveHistory(); } // Cleanup orphan files in TEMP_DIR and UPLOADS_DIR older than 7 days [TEMP_DIR, UPLOADS_DIR].forEach(dir => { if (fs.existsSync(dir)) { const files = fs.readdirSync(dir); for (const file of files) { const curPath = path.join(dir, file); try { const stats = fs.statSync(curPath); if (now - stats.mtimeMs > MAX_AGE_MS) { if (stats.isDirectory()) { fs.rmSync(curPath, { recursive: true, force: true }); } else { fs.unlinkSync(curPath); } } } catch (e) {} } } }); } loadHistory(); cleanupOldRenders(); setInterval(cleanupOldRenders, 60 * 60 * 1000); """ code = startup_cleanup_regex.sub(replacement_1, code) # 2. Remove the old const activeSessions = new Map(); code = re.sub(r"// Active export sessions\nconst activeSessions = new Map\(\);\n", "", code) # 3. Add saveHistory() to all places where state updates code = code.replace("activeSessions.set(sessionId, session);", "activeSessions.set(sessionId, session);\n saveHistory();") code = code.replace("session.done = true;", "session.done = true;\n saveHistory();") code = code.replace("session.currentStatus = Rendere /: ...;", "session.currentStatus = Rendere /: ...;\n saveHistory();") code = code.replace("session.currentStatus = 'Fertig';\n session.done = true;", "session.currentStatus = 'Fertig';\n session.done = true;\n saveHistory();") code = code.replace("session.formats[formatId].ready = true;", "session.formats[formatId].ready = true;\n saveHistory();") code = code.replace("session.formats.prores.ready = true;", "session.formats.prores.ready = true;\n saveHistory();") with open('server.mjs', 'w', encoding='utf-8') as f: f.write(code)