#!/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 { 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); });