112 lines
3.5 KiB
JavaScript
Vendored
112 lines
3.5 KiB
JavaScript
Vendored
"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();
|