Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151#!/usr/bin/env node
/** * Re-bake Tapes * * Re-triggers oven MP4 conversion for tapes that were never processed. * Sends each tape to the oven /bake endpoint with the correct ZIP URL. * * Usage: * node rebake-tapes.mjs [options] * * Options: * --dry-run Show what would be sent without triggering * --limit N Only process N tapes * --code CODE Re-bake a specific tape by code * --delay MS Delay between requests (default: 2000) */
import { connect } from "../../../system/backend/database.mjs";import { config } from "dotenv";
config({ path: "../../../system/.env" });
const args = process.argv.slice(2);const dryRun = args.includes("--dry-run");const limitIndex = args.indexOf("--limit");const limit = limitIndex !== -1 ? parseInt(args[limitIndex + 1]) : null;const codeIndex = args.indexOf("--code");const targetCode = codeIndex !== -1 ? args[codeIndex + 1] : null;const delayIndex = args.indexOf("--delay");const delay = delayIndex !== -1 ? parseInt(args[delayIndex + 1]) : 2000;
const OVEN_URL = process.env.OVEN_URL || "https://oven.aesthetic.computer";const CALLBACK_URL = process.env.URL ? `${process.env.URL}/api/oven-complete` : "https://aesthetic.computer/api/oven-complete";const CALLBACK_SECRET = process.env.OVEN_CALLBACK_SECRET;
async function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms));}
async function rebakeTapes() { console.log("๐ฅ Re-bake Unprocessed Tapes\n"); console.log(`Mode: ${dryRun ? "๐ DRY RUN" : "๐ฅ LIVE"}`); console.log(`Oven: ${OVEN_URL}`); console.log(`Callback: ${CALLBACK_URL}`); console.log(`Secret: ${CALLBACK_SECRET ? "โ
set" : "โ missing"}`); if (targetCode) console.log(`Code: ${targetCode}`); console.log();
if (!CALLBACK_SECRET && !dryRun) { console.error("โ OVEN_CALLBACK_SECRET is required. Set it in system/.env"); process.exit(1); }
const database = await connect(); const tapes = database.db.collection("tapes"); const handles = database.db.collection("@handles");
const query = { $or: [{ mp4Url: { $exists: false } }, { mp4Url: null }], };
if (targetCode) { query.code = targetCode; }
const cursor = tapes.find(query).sort({ when: -1 }); if (limit) cursor.limit(limit);
const allTapes = await cursor.toArray(); console.log(`Found ${allTapes.length} tapes needing MP4 conversion\n`);
if (allTapes.length === 0) { console.log("โจ All tapes already have MP4s!"); await database.disconnect(); return; }
let sent = 0, skipped = 0, failed = 0;
for (let i = 0; i < allTapes.length; i++) { const tape = allTapes[i]; const handle = await handles.findOne({ _id: tape.user }); const h = handle?.handle || (tape.user ? "unknown" : "guest");
const bucket = tape.bucket || (tape.user ? "user-aesthetic-computer" : "art-aesthetic-computer"); const key = tape.user ? `${tape.user}/${tape.slug}.zip` : `${tape.slug}.zip`; const zipUrl = `https://${bucket}.sfo3.digitaloceanspaces.com/${key}`;
console.log( ` [${i + 1}/${allTapes.length}] @${h} code:${tape.code} โ ${zipUrl.split("/").pop()}`, );
if (dryRun) { sent++; continue; }
const payload = { mongoId: tape._id.toString(), slug: tape.slug, code: tape.code, zipUrl, callbackUrl: CALLBACK_URL, callbackSecret: CALLBACK_SECRET, };
try { const res = await fetch(`${OVEN_URL}/bake`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), });
if (res.ok) { const data = await res.json(); console.log(` โ
Accepted: ${data.message || "ok"}`); sent++; } else { const text = await res.text(); console.log(` โ ${res.status}: ${text}`); failed++; } } catch (err) { console.log(` โ ${err.message}`); failed++; }
if (i < allTapes.length - 1) { await sleep(delay); } }
console.log("\n" + "โ".repeat(50)); console.log(`๐ฅ Sent: ${sent}`); console.log(`โญ๏ธ Skipped: ${skipped}`); console.log(`โ Failed: ${failed}`); console.log(`๐ Total: ${allTapes.length}\n`);
await database.disconnect();}
rebakeTapes().catch((err) => { console.error("Fatal:", err); process.exit(1);});