import https from 'https'; import fs from 'fs'; const EN_KEYWORDS = [ 'receipt scanner to excel', 'receipt to excel', 'receipt scanner', 'expense tracker', 'tax receipt organizer', 'receipt keeper', 'invoice scanner', 'bookkeeping scanner', 'ocr receipt scanner', 'extract receipt to csv' ]; const DE_KEYWORDS = [ 'beleg scanner', 'belege digitalisieren', 'kassenbon scanner', 'quittung scanner', 'spesen app', 'rechnung scanner', 'receipt to excel', 'datev scanner', 'belegmanager', 'ausgaben tracker' ]; const STOREFRONTS = [ { id: 'US', country: 'us', name: 'USA', lang: 'en' }, { id: 'GB', country: 'gb', name: 'UK', lang: 'en' }, { id: 'CA', country: 'ca', name: 'Kanada', lang: 'en' }, { id: 'AU', country: 'au', name: 'Australien', lang: 'en' }, { id: 'DE', country: 'de', name: 'Deutschland', lang: 'de' }, { id: 'AT', country: 'at', name: 'Österreich', lang: 'de' }, { id: 'CH', country: 'ch', name: 'Schweiz', lang: 'de' } ]; function fetchStoreData(term, country) { return new Promise((resolve) => { const url = `https://itunes.apple.com/search?term=${encodeURIComponent(term)}&country=${country}&entity=software&limit=10`; https.get(url, { headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)' } }, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const json = JSON.parse(data); resolve(json.results || []); } catch { resolve([]); } }); }).on('error', () => resolve([])); }); } function calculateDifficulty(apps, term) { if (!apps || apps.length === 0) return { score: 10, tier: 'Sehr gering' }; const top5 = apps.slice(0, 5); const totalReviews = top5.reduce((sum, a) => sum + (a.userRatingCount || 0), 0); const avgReviews = totalReviews / top5.length; const titleMatches = top5.filter(a => (a.trackName || '').toLowerCase().includes(term.toLowerCase())).length; // Logarithmic scale for reviews let reviewScore = 0; if (avgReviews > 500000) reviewScore = 95; else if (avgReviews > 100000) reviewScore = 85; else if (avgReviews > 20000) reviewScore = 70; else if (avgReviews > 5000) reviewScore = 55; else if (avgReviews > 1000) reviewScore = 40; else if (avgReviews > 100) reviewScore = 25; else reviewScore = 15; const matchScore = titleMatches * 5; const finalScore = Math.min(99, Math.max(10, Math.round((reviewScore * 0.8) + (matchScore * 0.2)))); return { score: finalScore, avgReviews: Math.round(avgReviews), top1: top5[0] ? `${top5[0].trackName} (${top5[0].userRatingCount || 0} rev, ★${top5[0].averageUserRating?.toFixed(1) || '0'})` : 'Keine', resultCount: apps.length }; } async function run() { console.log("Starte Live-Abfrage der Apple Storefront API..."); const report = {}; for (const sf of STOREFRONTS) { console.log(`\nPrüfe Storefront: ${sf.name} (${sf.id})...`); report[sf.id] = { name: sf.name, data: [] }; const keywords = sf.lang === 'de' ? DE_KEYWORDS : EN_KEYWORDS; for (const kw of keywords) { const apps = await fetchStoreData(kw, sf.country); const diff = calculateDifficulty(apps, kw); report[sf.id].data.push({ keyword: kw, ...diff }); await new Promise(r => setTimeout(r, 200)); } } fs.writeFileSync('scripts/live_api_results.json', JSON.stringify(report, null, 2)); console.log("\nLive-Ergebnisse erfolgreich in scripts/live_api_results.json gespeichert!"); } run();