← back to Beverlyhillsvideos

social/poster/token-health.mjs

37 lines

#!/usr/bin/env node
// token-health.mjs — READ-ONLY check that the BHV Graph API token is alive + not near
// expiry. The 6-hour poster fails SILENTLY if the token dies (launchd doesn't alert),
// so this is the missing watchdog (Cody FIX-FIRST #2). Exit 0 healthy, 1 dead/expiring.
// Wire to a launchd job + George email on non-zero (gated install — see pending-approval).
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';

const env = fs.readFileSync(path.join(os.homedir(), 'Projects/secrets-manager/.env'), 'utf8');
const g = (k) => { let v = null; for (const l of env.split('\n')) { const m = l.match(/^([A-Z0-9_]+)=(.*)$/); if (m && m[1] === k) v = m[2]; } return v; };
const tok = g('BHV_IG_ACCESS_TOKEN'), ig = g('BHV_IG_USER_ID'), ver = g('BHV_IG_GRAPH_VERSION') || 'v21.0';

const WARN_DAYS = 10; // warn if expiry within this window

(async () => {
  if (!tok || !ig) { console.log('DEAD: missing BHV_IG token/user id'); process.exit(1); }
  try {
    // 1) can the token still read the IG account?
    const r = await fetch(`https://graph.facebook.com/${ver}/${ig}?fields=username&access_token=${tok}`);
    const j = await r.json();
    if (j.error) { console.log(`DEAD: ${JSON.stringify(j.error).slice(0, 160)}`); process.exit(1); }
    // 2) how long until it expires?
    const d = await (await fetch(`https://graph.facebook.com/${ver}/debug_token?input_token=${tok}&access_token=${tok}`)).json();
    const exp = d?.data?.expires_at;
    if (exp && exp > 0) {
      const days = Math.round((exp * 1000 - Date.now()) / 864e5);
      if (days <= 0) { console.log('DEAD: token expired'); process.exit(1); }
      if (days <= WARN_DAYS) { console.log(`EXPIRING: @${j.username} token expires in ${days}d`); process.exit(1); }
      console.log(`HEALTHY: @${j.username} token OK, expires in ${days}d`);
    } else {
      console.log(`HEALTHY: @${j.username} token OK (no expiry / long-lived)`);
    }
    process.exit(0);
  } catch (e) { console.log(`DEAD: ${e.message}`); process.exit(1); }
})();