import path from 'node:path'; import { Reader } from '@maxmind/geoip2-node'; import config from 'config'; import runtimeId from '../../utils/runtime-id.js'; import initLogger from '../logger.js'; const logger = initLogger(); const regions = config.restrictions.regions; export default async function initRestrictionHandler() { const reader = await Reader.open('assets/GeoLite2-City.mmdb'); function getRestriction(req) { if (req.session.geo && Object.hasOwn(req.session.geo, 'country') && req.session.geo.ip === req.userIp && req.session.geo.runtimeId === runtimeId) { const { country, subdivision } = req.session.geo; if (!config.restrictions.enabled) { return { restriction: 0, country, subdivision, }; } if (Object.hasOwn(req.session.geo, 'restriction')) { return { restriction: req.session.geo.restriction, country, subdivision, }; } } const location = reader.city(req.userIp); const country = location.country.isoCode; const subdivision = location.subdivisions?.[0]?.isoCode; if (!config.restrictions.enabled) { return { restriction: 0, country, subdivision, }; } if (regions[country]?.[subdivision]) { // state or province restriction return { restriction: config.restrictions.modes[regions[country][subdivision]], country, subdivision, }; } if (regions[country]) { // country restriction return { restriction: config.restrictions.modes[regions[country]], country, subdivision, }; } return { restriction: null, country, subdivision, }; } function restrictionHandler(req, res, next) { try { const { restriction, country, subdivision, } = getRestriction(req); if (restriction === 'block' || req.path === '/sfw/') { res.render(path.join(import.meta.dirname, '../../assets/sfw.ejs'), { noVpn: config.restrictions.noVpn.includes(country), }); return; } if (req.session.geo?.restriction !== restriction) { req.session.geo = { ip: req.userIp, runtimeId, restriction, country, subdivision, }; } req.geo = { restriction, country, subdivision, }; } catch (error) { logger.error(`Failed Maxmind IP lookup for ${req.ip}: ${error.message}`); req.session.geo = { ip: req.userIp, runtimeId, restriction: 0, country: null, subdivision: null, }; req.geo = { restriction: 0, country: null, subdivision: null, }; } next(); } return restrictionHandler; }