generate-hindi-search-volumes.js
1 #!/usr/bin/env node 2 3 /** 4 * Generate search volume CSVs for Hindi keywords 5 * 6 * This script generates search volume data for Hindi keyword files: 7 * - data/in/businesses-hindi.txt → data/in/businesses-hindi-search-volume.csv 8 * - data/in/regions-hindi.txt → data/in/regions-hindi-search-volume.csv 9 * 10 * Usage: 11 * node scripts/generate-hindi-search-volumes.js [--type businesses|regions|all] 12 */ 13 14 import 'dotenv/config'; 15 import { generateSearchVolumeCSV } from '../src/utils/keyword-validator.js'; 16 import Logger from '../src/utils/logger.js'; 17 import path from 'path'; 18 import fs from 'fs'; 19 20 const logger = new Logger('HindiSearchVolumes'); 21 22 async function main() { 23 // Check DataForSEO credentials 24 if (!process.env.DATAFORSEO_LOGIN || !process.env.DATAFORSEO_PASSWORD) { 25 logger.error( 26 'DataForSEO credentials required. Add DATAFORSEO_LOGIN and DATAFORSEO_PASSWORD to .env' 27 ); 28 process.exit(1); 29 } 30 31 // Parse command line arguments 32 const args = process.argv.slice(2); 33 const typeArg = args.find(arg => arg.startsWith('--type=')); 34 const type = typeArg ? typeArg.split('=')[1] : 'all'; 35 36 if (!['businesses', 'regions', 'all'].includes(type)) { 37 logger.error('Invalid type. Use --type=businesses, --type=regions, or --type=all'); 38 process.exit(1); 39 } 40 41 const dataDir = './data/in'; 42 const tasks = []; 43 44 // Determine which files to process 45 if (type === 'businesses' || type === 'all') { 46 tasks.push({ 47 name: 'businesses', 48 inputPath: path.join(dataDir, 'businesses-hindi.txt'), 49 outputPath: path.join(dataDir, 'businesses-hindi-search-volume.csv'), 50 }); 51 } 52 53 if (type === 'regions' || type === 'all') { 54 tasks.push({ 55 name: 'regions', 56 inputPath: path.join(dataDir, 'regions-hindi.txt'), 57 outputPath: path.join(dataDir, 'regions-hindi-search-volume.csv'), 58 }); 59 } 60 61 logger.info(`Generating Hindi search volume CSVs (type: ${type})...`); 62 logger.info(`Language: Hindi (hi), Country: India (IN)`); 63 logger.info(''); 64 65 let successCount = 0; 66 let totalKeywords = 0; 67 68 for (const task of tasks) { 69 if (!fs.existsSync(task.inputPath)) { 70 logger.warn(`File not found: ${task.inputPath}`); 71 continue; 72 } 73 74 logger.info(`Processing ${task.name}...`); 75 logger.info(` Input: ${task.inputPath}`); 76 logger.info(` Output: ${task.outputPath}`); 77 78 try { 79 const stats = await generateSearchVolumeCSV( 80 task.inputPath, 81 'IN', // Country code 82 task.outputPath, 83 'hi' // Language code for Hindi 84 ); 85 86 logger.success(`✓ ${task.name}: ${stats.totalKeywords} keywords generated`); 87 logger.info(` Seeds: ${stats.seedCount}, Expanded: ${stats.expandedCount}`); 88 logger.info(''); 89 90 successCount++; 91 totalKeywords += stats.totalKeywords; 92 } catch (err) { 93 logger.error(`✗ ${task.name}: ${err.message}`); 94 logger.error(` ${err.stack}`); 95 logger.info(''); 96 97 if (err.message.includes('API') || err.message.includes('DataForSEO')) { 98 logger.warn('Stopping due to API error'); 99 break; 100 } 101 } 102 } 103 104 logger.info('='.repeat(60)); 105 logger.success(`Completed: ${successCount}/${tasks.length} tasks`); 106 logger.success(`Total keywords generated: ${totalKeywords}`); 107 } 108 109 main().catch(err => { 110 logger.error(`Fatal error: ${err.message}`); 111 console.error(err); 112 process.exit(1); 113 });