mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
refactor: extract CCTV media and radio directory providers
This commit is contained in:
1 parent
fada0c661f
commit
79b4929b88
17 files changed
+1977
-1831
No files matched your search
@@ -0,0 +1,119 @@
|
||||
import { RADIO_UUID_RE } from './constants.js';
|
||||
import { normalizeRadioCountryInput } from '../../../src/data/radioCountry.js';
|
||||
export function cleanRadioText(value, maxLength) {
|
||||
return String(value ?? '').replace(/[\u0000-\u001f\u007f]/g, ' ').replace(/\s+/g, ' ').trim().slice(0, maxLength).trim();
|
||||
}
|
||||
|
||||
export function isNonGlobalIpv4(hostname) {
|
||||
const pieces = hostname.split('.');
|
||||
if (pieces.length !== 4 || pieces.some((piece) => !/^\d{1,3}$/.test(piece))) return false;
|
||||
const values = pieces.map(Number);
|
||||
if (values.some((value) => value > 255)) return true;
|
||||
const [a, b, c] = values;
|
||||
return a === 0 || a === 10 || a === 127 || a >= 224
|
||||
|| (a === 100 && b >= 64 && b <= 127)
|
||||
|| (a === 169 && b === 254)
|
||||
|| (a === 172 && b >= 16 && b <= 31)
|
||||
|| (a === 192 && b === 0)
|
||||
|| (a === 192 && b === 88 && c === 99)
|
||||
|| (a === 192 && b === 168)
|
||||
|| (a === 198 && (b === 18 || b === 19))
|
||||
|| (a === 198 && b === 51 && c === 100)
|
||||
|| (a === 203 && b === 0 && c === 113);
|
||||
}
|
||||
|
||||
/** Return a normalized public HTTPS URL, or null for local/private targets. */
|
||||
export function publicRadioHttpsUrl(value) {
|
||||
try {
|
||||
const url = new URL(String(value ?? ''));
|
||||
const hostname = url.hostname.toLowerCase().replace(/^\[|\]$/g, '').replace(/\.$/, '');
|
||||
if (url.protocol !== 'https:' || url.username || url.password || !hostname) return null;
|
||||
if (
|
||||
hostname === 'localhost'
|
||||
|| hostname.endsWith('.localhost')
|
||||
|| hostname.endsWith('.local')
|
||||
|| isNonGlobalIpv4(hostname)
|
||||
|| hostname.includes(':')
|
||||
) return null;
|
||||
url.hash = '';
|
||||
return url.href;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Normalize one Radio Browser station and omit favicons and unsafe streams. */
|
||||
export function normalizeRadioBrowserStation(raw) {
|
||||
const id = cleanRadioText(raw?.stationuuid, 40).toLowerCase();
|
||||
const lat = raw?.geo_lat === null || raw?.geo_lat === '' ? null : Number(raw?.geo_lat);
|
||||
const lon = raw?.geo_long === null || raw?.geo_long === '' ? null : Number(raw?.geo_long);
|
||||
const codec = cleanRadioText(raw?.codec, 16).toUpperCase();
|
||||
const streamUrl = publicRadioHttpsUrl(raw?.url_resolved || raw?.url);
|
||||
if (
|
||||
!RADIO_UUID_RE.test(id)
|
||||
|| Number(raw?.lastcheckok) !== 1
|
||||
|| Number(raw?.hls) === 1
|
||||
|| !Number.isFinite(lat) || lat < -90 || lat > 90
|
||||
|| !Number.isFinite(lon) || lon < -180 || lon > 180
|
||||
|| !/^(?:MP3|AAC(?:\+|-LC|-HE)?|HE-AAC)$/i.test(codec)
|
||||
|| !streamUrl
|
||||
) return null;
|
||||
|
||||
const name = cleanRadioText(raw?.name, 140);
|
||||
if (!name) return null;
|
||||
const tags = String(raw?.tags ?? '')
|
||||
.split(',')
|
||||
.map((tag) => cleanRadioText(tag, 80).toLocaleLowerCase().replace(/[_-]+/g, ' ').replace(/\s+/g, ' ').trim())
|
||||
.filter(Boolean)
|
||||
.filter((tag, index, all) => all.indexOf(tag) === index)
|
||||
.slice(0, 24);
|
||||
const languages = String(raw?.language ?? '')
|
||||
.split(',')
|
||||
.map((language) => cleanRadioText(language, 40))
|
||||
.filter(Boolean)
|
||||
.slice(0, 8);
|
||||
const rawCountryCode = cleanRadioText(raw?.countrycode, 2).toUpperCase();
|
||||
const normalizedCode = normalizeRadioCountryInput(rawCountryCode);
|
||||
const normalizedCountry = normalizedCode.valid && !normalizedCode.empty
|
||||
? normalizedCode
|
||||
: normalizeRadioCountryInput(cleanRadioText(raw?.country, 80));
|
||||
const bitrate = Number(raw?.bitrate);
|
||||
return {
|
||||
id,
|
||||
name,
|
||||
lat,
|
||||
lon,
|
||||
streamUrl,
|
||||
homepage: publicRadioHttpsUrl(raw?.homepage),
|
||||
tags,
|
||||
languages,
|
||||
state: cleanRadioText(raw?.state, 80),
|
||||
country: normalizedCountry.valid && !normalizedCountry.empty
|
||||
? normalizedCountry.name
|
||||
: cleanRadioText(raw?.country, 80),
|
||||
countryCode: normalizedCountry.valid ? normalizedCountry.code : '',
|
||||
metadataTrust: 'untrusted-community',
|
||||
codec,
|
||||
bitrate: Number.isInteger(bitrate) && bitrate >= 8 && bitrate <= 1024 ? bitrate : null,
|
||||
clickCount: Math.max(0, Math.min(10_000_000, Number(raw?.clickcount) || 0)),
|
||||
};
|
||||
}
|
||||
|
||||
export function publicRadioStation(station) {
|
||||
return {
|
||||
id: station.id,
|
||||
name: station.name,
|
||||
lat: station.lat,
|
||||
lon: station.lon,
|
||||
streamUrl: station.streamUrl,
|
||||
homepage: station.homepage,
|
||||
tags: station.tags,
|
||||
languages: station.languages,
|
||||
state: station.state,
|
||||
country: station.country,
|
||||
countryCode: station.countryCode,
|
||||
metadataTrust: station.metadataTrust,
|
||||
codec: station.codec,
|
||||
bitrate: station.bitrate,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user