ip-echo/lib/start.js

112 lines
3.5 KiB
JavaScript
Raw Permalink Normal View History

2024-11-13 05:10:54 +03:00
"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();