trip) adding support for lodgings
This commit is contained in:
90
scripts/download-airline-logos.ts
Normal file
90
scripts/download-airline-logos.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env bun
|
||||
/**
|
||||
* Download airline logo SVGs from airlinelogos.aero into static/airline-logos/
|
||||
* Run with: bun run scripts/download-airline-logos.ts
|
||||
*/
|
||||
|
||||
import { Database } from 'bun:sqlite';
|
||||
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
||||
import { join, dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const ROOT = join(__dirname, '..');
|
||||
const DB_PATH = process.env.DATABASE_URL?.replace('file:', '') ?? join(ROOT, 'trips.db');
|
||||
const OUTPUT_DIR = join(ROOT, 'static', 'airline-logos');
|
||||
|
||||
const DELAY_MS = 50;
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function main() {
|
||||
if (!existsSync(OUTPUT_DIR)) {
|
||||
mkdirSync(OUTPUT_DIR, { recursive: true });
|
||||
console.log(`Created ${OUTPUT_DIR}`);
|
||||
}
|
||||
|
||||
const db = new Database(DB_PATH, { readonly: true });
|
||||
|
||||
const rows = db
|
||||
.query<
|
||||
{ iata_code: string },
|
||||
[]
|
||||
>(`SELECT DISTINCT iata_code FROM airlines WHERE iata_code IS NOT NULL AND iata_code != '' ORDER BY iata_code`)
|
||||
.all();
|
||||
|
||||
db.close();
|
||||
|
||||
console.log(`Found ${rows.length} distinct IATA codes`);
|
||||
|
||||
let downloaded = 0;
|
||||
let skipped = 0;
|
||||
let failed = 0;
|
||||
|
||||
for (const { iata_code } of rows) {
|
||||
const outPath = join(OUTPUT_DIR, `${iata_code}.svg`);
|
||||
|
||||
if (existsSync(outPath)) {
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const url = `https://airlinelogos.aero/logos/${iata_code}.svg`;
|
||||
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
headers: { 'User-Agent': 'trips-app/1.0 (logo downloader)' }
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
const contentType = res.headers.get('content-type') ?? '';
|
||||
if (contentType.includes('svg') || contentType.includes('xml')) {
|
||||
const text = await res.text();
|
||||
writeFileSync(outPath, text, 'utf-8');
|
||||
console.log(` ✓ ${iata_code}`);
|
||||
downloaded++;
|
||||
} else {
|
||||
console.log(` - ${iata_code} (not SVG: ${contentType})`);
|
||||
failed++;
|
||||
}
|
||||
} else {
|
||||
console.log(` - ${iata_code} (HTTP ${res.status})`);
|
||||
failed++;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(` ! ${iata_code} (${err instanceof Error ? err.message : err})`);
|
||||
failed++;
|
||||
}
|
||||
|
||||
await sleep(DELAY_MS);
|
||||
}
|
||||
|
||||
console.log(`\nDone: ${downloaded} downloaded, ${skipped} skipped, ${failed} not found`);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user