Files
olliewazza_larry/scripts/competitor-research.js

88 lines
3.2 KiB
JavaScript

#!/usr/bin/env node
/**
* Competitor Research — Save & Query Findings
*
* The actual research is done by the agent using the browser.
* This script manages the competitor-research.json file.
*
* Usage:
* node competitor-research.js --dir tiktok-marketing/ --summary
* node competitor-research.js --dir tiktok-marketing/ --add-competitor '{"name":"AppX","tiktokHandle":"@appx",...}'
* node competitor-research.js --dir tiktok-marketing/ --gaps
*/
const fs = require('fs');
const path = require('path');
const args = process.argv.slice(2);
const dir = args.includes('--dir') ? args[args.indexOf('--dir') + 1] : 'tiktok-marketing';
const filePath = path.join(dir, 'competitor-research.json');
function loadData() {
if (!fs.existsSync(filePath)) {
return {
researchDate: '',
competitors: [],
nicheInsights: { trendingSounds: [], commonFormats: [], gapOpportunities: '', avoidPatterns: '' }
};
}
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
}
function saveData(data) {
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
}
if (args.includes('--summary')) {
const data = loadData();
if (data.competitors.length === 0) {
console.log('No competitor research yet. Use the browser to research competitors first.');
process.exit(0);
}
console.log(`📊 Competitor Research (${data.researchDate})\n`);
console.log(`Found ${data.competitors.length} competitors:\n`);
data.competitors.forEach(c => {
console.log(` ${c.name} (${c.tiktokHandle || 'no handle'})`);
console.log(` Followers: ${c.followers || '?'} | Avg views: ${c.avgViews || '?'}`);
if (c.bestVideo) console.log(` Best: ${c.bestVideo.views} views — "${c.bestVideo.hook}"`);
if (c.strengths) console.log(` Strengths: ${c.strengths}`);
if (c.weaknesses) console.log(` Weaknesses: ${c.weaknesses}`);
console.log('');
});
if (data.nicheInsights?.gapOpportunities) {
console.log(`💡 Gap opportunities: ${data.nicheInsights.gapOpportunities}`);
}
if (data.nicheInsights?.avoidPatterns) {
console.log(`⚠️ Avoid: ${data.nicheInsights.avoidPatterns}`);
}
}
if (args.includes('--add-competitor')) {
const idx = args.indexOf('--add-competitor');
const json = args[idx + 1];
try {
const competitor = JSON.parse(json);
const data = loadData();
data.competitors.push(competitor);
data.researchDate = new Date().toISOString().split('T')[0];
saveData(data);
console.log(`✅ Added competitor: ${competitor.name}`);
} catch (e) {
console.error('Invalid JSON for competitor:', e.message);
process.exit(1);
}
}
if (args.includes('--gaps')) {
const data = loadData();
if (!data.nicheInsights) {
console.log('No niche insights yet.');
process.exit(0);
}
console.log('Gap Analysis:\n');
console.log(` Opportunities: ${data.nicheInsights.gapOpportunities || 'None recorded'}`);
console.log(` Avoid: ${data.nicheInsights.avoidPatterns || 'None recorded'}`);
console.log(` Common formats: ${(data.nicheInsights.commonFormats || []).join(', ') || 'None recorded'}`);
console.log(` Trending sounds: ${(data.nicheInsights.trendingSounds || []).join(', ') || 'None recorded'}`);
}