import config from 'config'; import path from 'path'; import { Reader } from '@maxmind/geoip2-node'; 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 (Object.hasOwn(req.session, 'restriction') && Object.hasOwn(req.session, 'country') && req.session.restrictionIp === req.userIp) { return { restriction: req.session.restriction, country: req.session.country, }; } const location = reader.city(req.userIp); const country = location.country.isoCode; const subdivision = location.subdivisions?.[0]?.isoCode; if (regions[country]?.[subdivision]) { // state or province restriction return { restriction: config.restrictions.modes[regions[country][subdivision]], country, }; } if (regions[country]) { // country restriction return { restriction: config.restrictions.modes[regions[country]], country, }; } return { restriction: null, country, }; } function restrictionHandler(req, res, next) { if (!config.restrictions.enabled) { next(); return; } try { const { restriction, country } = 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.restriction !== restriction) { req.session.restrictionIp = req.userIp; req.session.restriction = restriction; req.session.country = country; } req.restriction = restriction; req.country = country; } catch (error) { logger.error(`Failed Maxmind IP lookup for ${req.ip}: ${error.message}`); req.session.restrictionIp = req.userIp; req.session.restriction = 0; req.session.country = null; } next(); } return restrictionHandler; }