import { writeFile } from 'node:fs/promises';
import { existsSync } from 'node:fs';
import Influship from 'influship';
const query = process.argv.slice(2).join(' ').trim();
if (query.length < 3 || query.length > 500) {
throw new Error('Supply a campaign brief between 3 and 500 characters.');
}
function cell(value: string | number | null): string {
let text = value === null ? '' : String(value);
// Prevent creator data from becoming a spreadsheet formula.
if (/^\s*[=+\-@]/.test(text)) text = `'${text}`;
return `"${text.replaceAll('"', '""')}"`;
}
if (existsSync('creator-shortlist.csv')) {
throw new Error('Move the existing creator-shortlist.csv before another search.');
}
const client = new Influship({ maxRetries: 0 });
const { data: search, response } = await client.search.create({
query, platforms: ['instagram'], limit: 5,
}).withResponse();
const header = ['Name', 'Handle', 'Followers', 'Engagement %', 'Score',
'Ranking source', 'Location unverified', 'Low confidence', 'Reasons'];
const rows = search.data.map((item) => {
const profile = item.relevant_profile ?? item.primary_profile;
return [item.creator.name, profile?.username ?? null,
profile?.followers ?? null, profile?.engagement_rate ?? null,
item.match.score, item.match.ranking_source ?? 'reranked',
String(item.location_unverified), String(item.match.low_confidence),
item.match.reasons.join('; ')];
});
const csv = [header, ...rows].map((row) => row.map(cell).join(',')).join('\r\n');
await writeFile('creator-shortlist.csv', csv, { flag: 'wx' });
console.log(`Saved ${rows.length} creators to creator-shortlist.csv`);
console.log('Credits charged:', response.headers.get('x-credits-charged'));