fix(geo): распознать CDN-локации и добавить иконки сервисов
Docker / build (push) Failing after 22s

CDN-значения вида SE (ARN) больше не помечаются как ошибка. У каждого GeoIP-сервиса — бренд-иконка, как в разделе блокировок.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-08-25 15:54:04 +07:00
co-authored by Cursor
parent 235ae03489
commit 7480b9dc11
10 changed files with 328 additions and 30 deletions
+39 -10
View File
@@ -131,19 +131,48 @@ export function emptyIpregionSummary(): IpregionSummary {
}
const ISO_RE = /^[A-Z]{2}$/
const ISO_IATA_RE = /^([A-Z]{2})\s*\(([A-Z]{3})\)$/
const IATA_RE = /^[A-Z]{3}$/
/** ISO `RU` → ok; иначе статусы ipregion (`N/A`, `Denied`, `Rate-limit`, `Server error`). */
export type CanonicalCountry = {
status: IpregionStatus
country: string | null
iata: string | null
}
/** ISO `RU` / CDN `SE (ARN)` → ok; иначе статусы ipregion (`N/A`, `Denied`, `Rate-limit`, `Server error`). */
export function canonicalizeCountryValue(
raw: string | null | undefined,
): { status: IpregionStatus; country: string | null } {
): CanonicalCountry {
const value = raw?.replace(/\s+/g, ' ').trim() ?? ''
if (!value || value === 'null' || /^n\/a$/i.test(value)) {
return { status: 'na', country: null }
if (!value || /^null$/i.test(value) || /^n\/a$/i.test(value)) {
return { status: 'na', country: null, iata: null }
}
if (/^denied$/i.test(value)) return { status: 'denied', country: null }
if (/^rate[- ]?limit$/i.test(value)) return { status: 'rate_limit', country: null }
if (/^server error$/i.test(value)) return { status: 'server_error', country: null }
const iso = value.toUpperCase()
if (ISO_RE.test(iso)) return { status: 'ok', country: iso }
return { status: 'server_error', country: null }
if (/^denied$/i.test(value)) return { status: 'denied', country: null, iata: null }
if (/^rate[- ]?limit$/i.test(value)) return { status: 'rate_limit', country: null, iata: null }
if (/^server error$/i.test(value)) return { status: 'server_error', country: null, iata: null }
const upper = value.toUpperCase()
const withIata = upper.match(ISO_IATA_RE)
if (withIata) {
return { status: 'ok', country: withIata[1]!, iata: withIata[2]! }
}
if (ISO_RE.test(upper)) {
return { status: 'ok', country: upper, iata: null }
}
const iataOnly = upper.match(/^\(([A-Z]{3})\)$/)
if (iataOnly) {
return { status: 'ok', country: null, iata: iataOnly[1]! }
}
if (IATA_RE.test(upper)) {
return { status: 'ok', country: null, iata: upper }
}
return { status: 'server_error', country: null, iata: null }
}
export function formatCanonicalCountry(parsed: CanonicalCountry): string | null {
if (parsed.country && parsed.iata) return `${parsed.country} (${parsed.iata})`
if (parsed.country) return parsed.country
if (parsed.iata) return parsed.iata
return null
}