chore: sync with Gitea master and restore local-only files
Reset local main to gitea/master (new source of truth) and restored local-only files: web scrapers, admin dashboard, ChromaDB integration, debug scripts, and utility libraries that aren't tracked in Gitea. Gitea master adds: discovermass, buscarmisas-network, hk-parishes, bohosluzby, kerknet, gottesdienstzeiten, miserend importers, ClaimRequest model, forward geocoding, heartbeat healthcheck. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
134
scripts/debug/list-church-websites.ts
Normal file
134
scripts/debug/list-church-websites.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import { config } from 'dotenv';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { Pool } from 'pg';
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
|
||||
// Load .env.local first, then .env
|
||||
config({ path: '.env.local' });
|
||||
config({ path: '.env' });
|
||||
|
||||
const connectionString = process.env.DATABASE_URL;
|
||||
|
||||
if (!connectionString) {
|
||||
throw new Error('DATABASE_URL environment variable is not set');
|
||||
}
|
||||
|
||||
const pool = new Pool({ connectionString });
|
||||
const adapter = new PrismaPg(pool);
|
||||
const prisma = new PrismaClient({ adapter });
|
||||
|
||||
async function listChurchWebsites() {
|
||||
try {
|
||||
console.log('Fetching churches from database...\n');
|
||||
|
||||
const churches = await prisma.church.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
city: true,
|
||||
state: true,
|
||||
country: true,
|
||||
website: true,
|
||||
googlePlaceId: true,
|
||||
},
|
||||
orderBy: [
|
||||
{ country: 'asc' },
|
||||
{ state: 'asc' },
|
||||
{ city: 'asc' },
|
||||
],
|
||||
});
|
||||
|
||||
console.log(`Total churches: ${churches.length}`);
|
||||
|
||||
const withWebsite = churches.filter(c => c.website);
|
||||
const withGoogle = churches.filter(c => c.googlePlaceId);
|
||||
const withoutWebsite = churches.filter(c => !c.website);
|
||||
|
||||
console.log(`Churches with website: ${withWebsite.length}`);
|
||||
console.log(`Churches with Google Place ID: ${withGoogle.length}`);
|
||||
console.log(`Churches without website: ${withoutWebsite.length}\n`);
|
||||
|
||||
// Group by country
|
||||
const byCountry = churches.reduce((acc, church) => {
|
||||
const country = church.country || 'Unknown';
|
||||
if (!acc[country]) {
|
||||
acc[country] = [];
|
||||
}
|
||||
acc[country].push(church);
|
||||
return acc;
|
||||
}, {} as Record<string, typeof churches>);
|
||||
|
||||
// Write to file
|
||||
let output = '# Church Websites\n\n';
|
||||
output += `Generated: ${new Date().toISOString()}\n\n`;
|
||||
output += `## Summary\n`;
|
||||
output += `- Total churches: ${churches.length}\n`;
|
||||
output += `- With website: ${withWebsite.length} (${((withWebsite.length / churches.length) * 100).toFixed(1)}%)\n`;
|
||||
output += `- With Google Place ID: ${withGoogle.length} (${((withGoogle.length / churches.length) * 100).toFixed(1)}%)\n`;
|
||||
output += `- Without website: ${withoutWebsite.length} (${((withoutWebsite.length / churches.length) * 100).toFixed(1)}%)\n\n`;
|
||||
|
||||
// Add country breakdown
|
||||
output += `## By Country\n\n`;
|
||||
Object.entries(byCountry)
|
||||
.sort(([, a], [, b]) => b.length - a.length)
|
||||
.forEach(([country, countryChurches]) => {
|
||||
const withSite = countryChurches.filter(c => c.website).length;
|
||||
const withGoogle = countryChurches.filter(c => c.googlePlaceId).length;
|
||||
output += `### ${country} (${countryChurches.length} churches)\n`;
|
||||
output += `- With website: ${withSite} (${((withSite / countryChurches.length) * 100).toFixed(1)}%)\n`;
|
||||
output += `- With Google Place ID: ${withGoogle} (${((withGoogle / countryChurches.length) * 100).toFixed(1)}%)\n\n`;
|
||||
});
|
||||
|
||||
// List all websites
|
||||
output += `## All Websites\n\n`;
|
||||
Object.entries(byCountry)
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
.forEach(([country, countryChurches]) => {
|
||||
output += `### ${country}\n\n`;
|
||||
countryChurches.forEach(church => {
|
||||
const location = [church.city, church.state, church.country].filter(Boolean).join(', ');
|
||||
if (church.website) {
|
||||
output += `- **${church.name}** (${location})\n`;
|
||||
output += ` - Website: ${church.website}\n`;
|
||||
if (church.googlePlaceId) {
|
||||
output += ` - Google Place ID: ${church.googlePlaceId}\n`;
|
||||
}
|
||||
output += ` - DB ID: ${church.id}\n\n`;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// List churches without websites
|
||||
output += `## Churches Without Websites\n\n`;
|
||||
Object.entries(byCountry)
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
.forEach(([country, countryChurches]) => {
|
||||
const without = countryChurches.filter(c => !c.website);
|
||||
if (without.length > 0) {
|
||||
output += `### ${country}\n\n`;
|
||||
without.forEach(church => {
|
||||
const location = [church.city, church.state, church.country].filter(Boolean).join(', ');
|
||||
output += `- **${church.name}** (${location})\n`;
|
||||
if (church.googlePlaceId) {
|
||||
output += ` - Google Place ID: ${church.googlePlaceId}\n`;
|
||||
}
|
||||
output += ` - DB ID: ${church.id}\n\n`;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Write to file
|
||||
const fs = await import('fs/promises');
|
||||
await fs.writeFile('church-websites.md', output);
|
||||
console.log('✓ Written to church-websites.md');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
listChurchWebsites();
|
||||
Reference in New Issue
Block a user