Initial commit with translated description
This commit is contained in:
87
scripts/competitor-research.js
Normal file
87
scripts/competitor-research.js
Normal file
@@ -0,0 +1,87 @@
|
||||
#!/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'}`);
|
||||
}
|
||||
Reference in New Issue
Block a user