← back to Norma

agents/instagram-agent/backfill-all.js

44 lines

/**
 * backfill-all.js — one-off: paginate the FULL post history of every IG account into its
 * per-account cache (data/live-media[-<id>].json). Read-only Graph /media sweep, $0.
 * Sequential with a delay between accounts to stay under Meta's rate limit. Accounts that
 * are already `complete` are skipped (DW is already fully backfilled). Continues on error
 * and prints a per-account summary; re-run to retry any failures.
 */
require('dotenv').config();
const fs = require('fs');
const path = require('path');
const { listAccounts, refreshLiveMedia } = require('./live-media');

const DATA = path.join(__dirname, 'data');
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const cachePath = (id) => id === process.env.IG_USER_ID
  ? path.join(DATA, 'live-media.json') : path.join(DATA, `live-media-${id}.json`);
const isComplete = (id) => { try { return !!JSON.parse(fs.readFileSync(cachePath(id), 'utf8')).complete; } catch { return false; } };

(async () => {
  const accts = listAccounts();
  const todo = accts.filter((a) => !isComplete(a.ig_user_id));
  console.log(`[backfill-all] ${accts.length} accounts · ${accts.length - todo.length} already complete · ${todo.length} to backfill`);
  const results = [];
  let i = 0;
  for (const a of todo) {
    i++;
    process.stdout.write(`[${i}/${todo.length}] @${a.handle} … `);
    try {
      const r = await refreshLiveMedia({ igUserId: a.ig_user_id, full: true });
      console.log(`+${r.added} (${r.scanned} scanned, ${r.pages}p)${r.complete ? ' ✓complete' : ' (capped)'}`);
      results.push({ handle: a.handle, added: r.added, scanned: r.scanned, complete: r.complete, ok: true });
    } catch (e) {
      console.log(`ERROR: ${e.message}`);
      results.push({ handle: a.handle, error: e.message, ok: false });
    }
    await sleep(1500); // be gentle on the Graph rate limit
  }
  const ok = results.filter((r) => r.ok);
  const tot = ok.reduce((n, r) => n + (r.added || 0), 0);
  console.log(`\n[backfill-all] DONE: ${ok.length}/${results.length} ok · +${tot.toLocaleString()} posts cached`);
  const fails = results.filter((r) => !r.ok);
  if (fails.length) console.log('[backfill-all] FAILURES (re-run to retry): ' + fails.map((f) => `@${f.handle}: ${f.error}`).join(' · '));
})();