const EXCLUDED_PATHS = [ '/api/auth/oauth/vk/callback', '/api/auth/oauth/yandex/callback', '/api/webhooks/yookassa', '/api/admin/notifications/telegram/webhook', ] export function normalizeIp(ip) { if (ip && ip.startsWith('::ffff:')) { return ip.slice(7) } return ip } export function ipToInt(ip) { const parts = ip.split('.') if (parts.length !== 4) return null return parts.reduce((acc, octet) => { const num = parseInt(octet, 10) if (isNaN(num) || num < 0 || num > 255) return null return acc !== null ? (acc << 8) + num : null }, 0) } export function cidrMatch(ip, cidr) { const slashIdx = cidr.indexOf('/') if (slashIdx === -1) return false const baseIp = cidr.slice(0, slashIdx) const prefix = parseInt(cidr.slice(slashIdx + 1), 10) if (isNaN(prefix) || prefix < 0 || prefix > 32) return false const ipInt = ipToInt(normalizeIp(ip)) const baseInt = ipToInt(normalizeIp(baseIp)) if (ipInt === null || baseInt === null) return false const mask = prefix === 0 ? 0 : ~(2 ** (32 - prefix) - 1) >>> 0 return (ipInt & mask) === (baseInt & mask) } export function build403Html(ip) { const safeIp = ip || 'не определён' return `
Изделия ручной работы: вещи с характером и вниманием к деталям
Сайт находится в разработке и скоро будет доступен
Ваш IP: ${safeIp}