← back to Ventura Corridor

src/jobs/auto_publish_top.ts

40 lines

/**
 * Nightly auto-publish: take the top-N most-viewed drafts/reviewed features and
 * flip them to status='published'. Keeps the public /issue growing without
 * Steve having to manually curate every feature.
 *
 *   $ npx tsx src/jobs/auto_publish_top.ts        # default top 10
 *   $ npx tsx src/jobs/auto_publish_top.ts 25     # top 25
 */
import 'dotenv/config';
import { pool, query } from '../../db/pool.ts';

const N = parseInt(process.argv.find(a => /^\d+$/.test(a)) || '10', 10);
const MIN_LEN = parseInt(process.env.MIN_LEN || '160', 10);

async function main() {
  // Pick: status NOT yet published, editorial decent length, sort by views desc + recency
  const r = await query(
    `WITH picks AS (
       SELECT mf.id
       FROM magazine_features mf
       WHERE mf.status IN ('draft', 'reviewed')
         AND length(mf.editorial) >= $2
       ORDER BY mf.views DESC, mf.generated_at DESC
       LIMIT $1
     )
     UPDATE magazine_features
     SET status = 'published', published_at = NOW(), reviewed_at = COALESCE(reviewed_at, NOW())
     WHERE id IN (SELECT id FROM picks)
     RETURNING id, headline`,
    [N, MIN_LEN]
  );
  console.log(`[auto_publish_top] published ${r.rowCount} features (top ${N} by views, min editorial ${MIN_LEN} chars)`);
  for (const row of r.rows) {
    console.log(`  ★ ${row.id} ${(row.headline || '').slice(0, 60)}`);
  }
  await pool.end();
}

main().catch(e => { console.error(e); process.exit(1); });