← 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); });