#!/usr/bin/env bun /** * 给存量 LobeChat 用户补建沙箱容器(幂等,已存在就跳过)。 * * 用法(在 VPS 上跑): * export DATABASE_URL=postgresql://... * export SANDBOX_BACKEND_URL=http://127.0.0.1:8700 * export SANDBOX_BACKEND_SECRET= * bun run scripts/backfill-users.ts */ import postgres from 'postgres'; const DATABASE_URL = process.env.DATABASE_URL; const BACKEND_URL = process.env.SANDBOX_BACKEND_URL ?? 'http://127.0.0.1:8700'; const SECRET = process.env.SANDBOX_BACKEND_SECRET; if (!DATABASE_URL) throw new Error('DATABASE_URL required'); if (!SECRET) throw new Error('SANDBOX_BACKEND_SECRET required'); const sql = postgres(DATABASE_URL, { max: 1 }); const users: { id: string; email: string | null }[] = await sql` SELECT id, email FROM users ORDER BY created_at ASC `; console.log(`[backfill] ${users.length} users to check`); let ok = 0, skip = 0, fail = 0; for (const u of users) { try { const res = await fetch(`${BACKEND_URL}/api/v1/users`, { body: JSON.stringify({ userId: u.id }), headers: { 'Content-Type': 'application/json', 'X-Sandbox-Secret': SECRET }, method: 'POST', }); const text = await res.text(); if (res.ok) { if (text.includes('"success":true')) { ok++; console.log(`[backfill] ✓ ${u.id} (${u.email ?? '-'})`); } else { skip++; console.log(`[backfill] ~ ${u.id}: ${text.slice(0, 100)}`); } } else { fail++; console.error(`[backfill] ✗ ${u.id}: HTTP ${res.status} ${text.slice(0, 100)}`); } } catch (e) { fail++; console.error(`[backfill] ✗ ${u.id}:`, (e as Error).message); } } console.log(`[backfill] done: ok=${ok} skip=${skip} fail=${fail}`); await sql.end();