// Cloudflare Worker + D1 (M&M Games Enhanced Edition - Fixed) let ready = false; const J = (o, c = 200) => new Response(JSON.stringify(o), { status: c, headers: { 'Content-Type': 'application/json' } }); export default { async fetch(req, env) { const url = new URL(req.url); const m = url.pathname.match(/^\/api\/([a-z0-9]{3,16})$/i); // Serve HTML if (!m) { return new Response(getHTML(), { headers: { 'Content-Type': 'text/html; charset=utf-8' } }); } if (!env.DB) return J({ error: 'D1 binding named DB is missing' }, 500); if (!ready) { await env.DB.exec('CREATE TABLE IF NOT EXISTS rooms (id TEXT PRIMARY KEY, data TEXT, t INTEGER)'); ready = true; } const id = m[1].toLowerCase(); if (req.method === 'GET') { const r = await env.DB.prepare('SELECT data FROM rooms WHERE id=?').bind(id).first(); return new Response(r ? r.data : '{}', { headers: { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' } }); } if (req.method === 'POST') { let b; try { const text = await req.text(); if (text.length > 25000) throw 0; b = JSON.parse(text); if (!b.data || typeof b.data !== 'object') throw 0; } catch { return J({ error: 'bad request' }, 400); } const data = JSON.stringify(b.data); const t = Date.now(); const q = b.op === 'set' ? 'INSERT OR REPLACE INTO rooms (id,data,t) VALUES (?,?,?)' : 'INSERT INTO rooms (id,data,t) VALUES (?,?,?) ON CONFLICT(id) DO UPDATE SET data=json_patch(data,excluded.data), t=excluded.t'; await env.DB.prepare(q).bind(id, data, t).run(); if (Math.random() < 0.05) { await env.DB.prepare('DELETE FROM rooms WHERE t').bind(t - 24 * 3600e3).run(); } return J({ ok: 1 }); } return J({ error: 'not found' }, 404); }, }; function getHTML() { return `