"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const promises_1 = require("fs/promises"); const fastify_1 = require("fastify"); const cors_1 = require("@fastify/cors"); const mmdb_lib_1 = require("mmdb-lib"); async function existsAsync(fileOrDir) { try { await (0, promises_1.stat)(fileOrDir); return true; } catch { return false; } } const DB_FILE = './data/GeoLite2-Country.mmdb'; let tag = ''; async function download() { if (!(await existsAsync('./data'))) { await (0, promises_1.mkdir)('./data', { recursive: true }); } const apiUrl = 'https://api.github.com/repos/P3TERX/GeoLite.mmdb/releases/latest'; const apiJson = (await (await fetch(apiUrl, { signal: AbortSignal.timeout(60000) })).json()); const tag_name = apiJson?.tag_name; if (tag === tag_name) { return; } const downloadUrl = apiJson?.assets?.find((a) => a.name === 'GeoLite2-Country.mmdb')?.browser_download_url; if (!downloadUrl) { throw new Error('Cound not find latest Geolite DB!'); } console.log(`Downloading ${downloadUrl}`); const resp = await fetch(downloadUrl, { signal: AbortSignal.timeout(60000), redirect: 'follow', }); if (!resp.ok) { throw new Error(await resp.text()); } const data = Buffer.from(await resp.arrayBuffer()); await (0, promises_1.writeFile)(DB_FILE, data); console.log(`Saved latest IP Country DB ${tag_name} to ${DB_FILE}`); tag = tag_name; return data; } async function torlist() { try { const exitlist = await (await fetch('https://check.torproject.org/torbulkexitlist', { signal: AbortSignal.timeout(60000), })).text(); const exitnodes = new Set(exitlist .match(/[^\r\n]+/g) ?.filter((r) => r) .sort((a, b) => a.localeCompare(b)) || []); console.log(`Fetched ${exitnodes.size} tor exit nodes`); return exitnodes; } catch { return new Set(); } } async function start() { let reader = new mmdb_lib_1.Reader((await download())); let torSet = await torlist(); const app = (0, fastify_1.fastify)({ trustProxy: 1, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any app.register(cors_1.fastifyCors, () => (req, callback) => { callback(null, { origin: req.headers.origin || '*', credentials: true, methods: ['GET, POST, OPTIONS'], headers: [ 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type', ], maxAge: 1728000, }); }); app.get('/', (req, reply) => { const { ip } = req; const iso = reader.get(ip)?.country?.iso_code; const tor = torSet.has(ip); reply.send({ ip, iso, tor, }); }); app.listen({ port: 3500, host: '127.0.0.1' }, (err, address) => { if (err) { console.log(err); throw err; } else { console.log(`IP Echo listening on ${address}`); } }); setInterval(async () => { try { const newDB = await download(); if (newDB) { reader = new mmdb_lib_1.Reader(newDB); } torSet = await torlist(); // eslint-disable-next-line no-empty } catch { } }, 86_400_000); } start();