Add full application: receipt scanning, auth, billing, and account deletion
Brings the working codebase (Next.js app, auth system, Stripe billing, Docker/deploy config, tests, docs) into version control on top of the placeholder initial commit, and adds account self-deletion (Danger Zone in Settings, password + typed-email confirmation, cascading DB cleanup, Stripe cancellation) per GDPR right-to-erasure. Excludes local build caches, node_modules, and internal agent scratch files; .gitignore hardened to keep those out going forward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
90
scripts/multi_country_aso.mjs
Normal file
90
scripts/multi_country_aso.mjs
Normal file
@@ -0,0 +1,90 @@
|
||||
import https from 'https';
|
||||
|
||||
const EN_KEYWORDS = [
|
||||
'receipt scanner',
|
||||
'receipt to excel',
|
||||
'receipt scanner to excel',
|
||||
'expense tracker',
|
||||
'receipt keeper',
|
||||
'invoice scanner',
|
||||
'tax receipts',
|
||||
'ocr receipt scanner',
|
||||
'smart receipts',
|
||||
'mileage and receipts',
|
||||
'receipt organizer',
|
||||
'bookkeeping scanner',
|
||||
'scan receipts for taxes',
|
||||
'extract receipt to csv',
|
||||
'business expense tracker'
|
||||
];
|
||||
|
||||
const DE_KEYWORDS = [
|
||||
'beleg scanner',
|
||||
'belege digitalisieren',
|
||||
'rechnung scanner',
|
||||
'kassenbon scanner',
|
||||
'quittung scanner',
|
||||
'spesen app',
|
||||
'buchhaltung scanner',
|
||||
'datev scanner',
|
||||
'receipt to excel',
|
||||
'haushaltsbuch',
|
||||
'ausgaben tracker',
|
||||
'steuer belege',
|
||||
'belegmanager'
|
||||
];
|
||||
|
||||
const COUNTRIES = {
|
||||
US: 'us',
|
||||
GB: 'gb',
|
||||
CA: 'ca',
|
||||
AU: 'au',
|
||||
DE: 'de'
|
||||
};
|
||||
|
||||
function fetchSearch(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' } }, (res) => {
|
||||
let data = '';
|
||||
res.on('data', chunk => data += chunk);
|
||||
res.on('end', () => {
|
||||
try {
|
||||
resolve(JSON.parse(data));
|
||||
} catch {
|
||||
resolve({ results: [] });
|
||||
}
|
||||
});
|
||||
}).on('error', () => resolve({ results: [] }));
|
||||
});
|
||||
}
|
||||
|
||||
async function analyze() {
|
||||
console.log("Analyzing Multi-Country App Store data...");
|
||||
const countryResults = {};
|
||||
|
||||
for (const [cName, cCode] of Object.entries(COUNTRIES)) {
|
||||
countryResults[cName] = {};
|
||||
const kws = cName === 'DE' ? DE_KEYWORDS : EN_KEYWORDS;
|
||||
for (const kw of kws) {
|
||||
const data = await fetchSearch(kw, cCode);
|
||||
const apps = data.results || [];
|
||||
const top5 = apps.slice(0, 5);
|
||||
const top5Reviews = top5.reduce((sum, a) => sum + (a.userRatingCount || 0), 0);
|
||||
const avgTop5Reviews = Math.round(top5Reviews / (top5.length || 1));
|
||||
const top1 = top5[0] || {};
|
||||
|
||||
countryResults[cName][kw] = {
|
||||
resultCount: data.resultCount,
|
||||
top1Name: top1.trackName || 'N/A',
|
||||
top1Reviews: top1.userRatingCount || 0,
|
||||
avgTop5Reviews,
|
||||
};
|
||||
await new Promise(r => setTimeout(r, 100));
|
||||
}
|
||||
}
|
||||
|
||||
console.log(JSON.stringify(countryResults, null, 2));
|
||||
}
|
||||
|
||||
analyze();
|
||||
Reference in New Issue
Block a user