← back to Nineoh Guide
scripts/seed-recurring-cast.mjs
72 lines
// Promote recurring guest actors (>= MIN_EPS episodes) into cast_people +
// characters + credits(credit_type='recurring'), so the Cast tab lists them
// alongside the 14 mains. Bios are ORIGINAL and grounded only in our own
// episode-count data (no fabricated external facts). Idempotent by name.
//
// node scripts/seed-recurring-cast.mjs
//
import { readFileSync } from "node:fs";
import { Pool } from "pg";
const MIN_EPS = 4;
const env = readFileSync(new URL("../apps/web/.env.local", import.meta.url), "utf8");
const DB = env.match(/^DATABASE_URL=(.+)$/m)?.[1]?.replace(/^["']|["']$/g, "");
if (!DB) throw new Error("DATABASE_URL not found in apps/web/.env.local");
const pool = new Pool({ connectionString: DB, max: 4 });
// show_id (all characters/credits hang off it)
const { rows: showRows } = await pool.query(`select id from shows limit 1`);
const showId = showRows[0].id;
const { rows: people } = await pool.query(
`select person_name,
(array_agg(character_name order by ord))[1] as character,
count(distinct episode_id) as eps
from episode_guest_cast
where person_name not in (select name from cast_people)
group by person_name
having count(distinct episode_id) >= $1
order by eps desc`,
[MIN_EPS]
);
console.log(`recurring actors to add (>= ${MIN_EPS} eps): ${people.length}`);
let added = 0;
for (const p of people) {
const bio = `Recurring guest star who appears as ${p.character ?? "a recurring character"} in ${p.eps} episodes of the reboot. Part of the extended 90210 ensemble beyond the core cast.`;
// cast_people (skip if somehow already there)
const cp = await pool.query(
`insert into cast_people (name, biography_original, bio_status, publicity_risk_level)
values ($1,$2,'ai-draft','editorial-only')
on conflict do nothing
returning id`,
[p.person_name, bio]
);
let personId = cp.rows[0]?.id;
if (!personId) {
const ex = await pool.query(`select id from cast_people where name=$1`, [p.person_name]);
personId = ex.rows[0].id;
}
// character
let charId = null;
if (p.character) {
const ch = await pool.query(
`insert into characters (name, show_id) values ($1,$2) returning id`,
[p.character, showId]
);
charId = ch.rows[0].id;
}
// recurring credit — billing_order negative-eps so higher counts sort first
await pool.query(
`insert into credits (person_id, character_id, credit_type, billing_order)
values ($1,$2,'recurring',$3)`,
[personId, charId, -p.eps]
);
added++;
}
console.log(`added ${added} recurring cast members`);
await pool.end();