← back to Prestige Car Wash

scripts/ig-pull.js

43 lines

#!/usr/bin/env node
'use strict';
/**
 * ig-pull.js — pull public media for the services gallery from Instagram @prestigecwash.
 *
 * Reality check: Instagram blocks unauthenticated scraping; a reliable pull needs the
 * business-owner Graph API token (deferred — Steve doesn't have logins wired yet).
 * This script attempts the public oEmbed/profile path best-effort and, on failure,
 * leaves the service `ig_photo` fields empty so the site falls back to generated media.
 *
 * Usage: node scripts/ig-pull.js  [postUrl1 postUrl2 ...]
 *   With explicit public post URLs it uses IG oEmbed (most reliable public route).
 */
const handle = process.env.IG_HANDLE || 'prestigecwash';
const postUrls = process.argv.slice(2);

async function oembed(url) {
  try {
    const r = await fetch(`https://api.instagram.com/oembed/?url=${encodeURIComponent(url)}`);
    if (!r.ok) return null;
    const j = await r.json();
    return { url, thumbnail: j.thumbnail_url, title: j.title };
  } catch { return null; }
}

async function main() {
  console.log(`📸 IG pull for @${handle}`);
  if (!postUrls.length) {
    console.log('  No post URLs given. Owner Graph API token is needed for a full profile pull.');
    console.log('  Once the owner token is available, wire the Graph media endpoint here.');
    console.log('  For now, service cards use Nano Banana / SeeDance generated media.');
    return;
  }
  const results = [];
  for (const u of postUrls) {
    const o = await oembed(u);
    console.log(o ? `  ✔ ${u} -> ${o.thumbnail}` : `  ✖ ${u} (blocked / private)`);
    if (o) results.push(o);
  }
  console.log(`  pulled ${results.length}/${postUrls.length}`);
}
main().catch(e => { console.error(e); process.exit(1); });