mirror of
https://github.com/movixcorp/MovixOpenSource.git
synced 2026-08-09 12:57:38 +00:00
- corrige l’extraction Fsvid/Vidzy dans proxiesembed, les extensions et le userscript avec un décodage XOR/P.A.C.K.E.R plus robuste - rejette les URL « troll » et supprime les résultats Fsvid/Vidzy contaminés des caches - ajoute KissKH pour les films et séries avec matching TMDB, catalogue, cache distribué, verrouillage, rotation des proxys et fallback sécurisé - ajoute le relais KissKH HLS/MP4 dans proxiesembed, avec retry SOCKS5 sur les erreurs 403 et streaming des segments BYTERANGE - prend en charge les sous-titres KissKH SRT/TXT/TXT2, leur déchiffrement AES et leur conversion en WebVTT - intègre KissKH au lecteur, aux priorités de sources, aux extensions Chrome/Firefox et au userscript - améliore la sélection, le formatage sécurisé, la traduction et l’affichage Picture-in-Picture des sous-titres - corrige le Cast web et Android pour transmettre les sous-titres internes, externes, KissKH et traduits - ajoute le support des pistes WebVTT inline via le relais LAN Android et améliore le suivi des sessions Cast - protège les liens jouables des caches Cpasmal et Coflix contre les rafraîchissements vides ou concurrents - fiabilise la sélection des saisons FStream et améliore le matching DarkiWorld par TMDB, titre et année - simplifie les nouvelles URL TMDB tout en conservant le décodage des anciens identifiants encodés - corrige l’opacité des icônes SVG dans toute l’interface en séparant la couleur de leur niveau d’opacité - met à jour le Dockerfile vers Node.js 22 et installe uniquement les dépendances runtime du workspace Hono - ajoute le workspace server avec ses dépendances dédiées et un arrêt gracieux sur SIGTERM/SIGINT - accélère le healthcheck Docker et évite de recopier tous les node_modules du builder dans l’image finale - retire les migrations et créations de tables automatiques au démarrage de la Main API au profit de db:init - attribue un port CycleTLS distinct à chaque worker pour éviter les conflits en mode cluster - ajoute des tests de non-régression pour KissKH, les caches de sources, CycleTLS et le Cast Android - publie Android 2.5.8 build 17 avec le nouvel APK - met à jour les extensions Chrome 1.3.13 et Firefox 1.5.10 Co-authored-by: GPT-5.6 Sol <noreply@openai.com>
97 lines
4 KiB
JavaScript
97 lines
4 KiB
JavaScript
const fs = require('node:fs');
|
|
|
|
const POLICY_KEYS = ['version', 'subtitleHosts', 'maxSubtitleBytes'];
|
|
const CANONICAL_SUBTITLE_BYTES = 2 * 1024 * 1024;
|
|
const RUNTIME_POLICY = Object.freeze({
|
|
version: 1,
|
|
subtitleHosts: Object.freeze(['auto.cdnvideo11.shop', 'sub.cdnvideo11.shop']),
|
|
maxSubtitleBytes: CANONICAL_SUBTITLE_BYTES,
|
|
});
|
|
const PLACEHOLDER_LABELS = new Set(['example', 'invalid', 'localhost', 'placeholder', 'test']);
|
|
|
|
function invalidPolicy() {
|
|
return new TypeError('policy KissKH invalide');
|
|
}
|
|
|
|
function isValidHostname(hostname) {
|
|
if (typeof hostname !== 'string' || hostname !== hostname.toLowerCase() || hostname.length > 253) return false;
|
|
if (!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/.test(hostname)) return false;
|
|
return !hostname.split('.').some((label) => PLACEHOLDER_LABELS.has(label));
|
|
}
|
|
|
|
function validateFallbackPolicy(value) {
|
|
if (!value || typeof value !== 'object' || Array.isArray(value)) throw invalidPolicy();
|
|
if (JSON.stringify(Object.keys(value)) !== JSON.stringify(POLICY_KEYS)) throw invalidPolicy();
|
|
if (value.version !== 1 || value.maxSubtitleBytes !== CANONICAL_SUBTITLE_BYTES) throw invalidPolicy();
|
|
if (!Array.isArray(value.subtitleHosts) || !value.subtitleHosts.length) throw invalidPolicy();
|
|
if (value.subtitleHosts.some((host) => !isValidHostname(host))) throw invalidPolicy();
|
|
const canonical = [...new Set(value.subtitleHosts)].sort();
|
|
if (canonical.length !== value.subtitleHosts.length
|
|
|| JSON.stringify(canonical) !== JSON.stringify(value.subtitleHosts)) throw invalidPolicy();
|
|
return Object.freeze({
|
|
version: 1,
|
|
subtitleHosts: Object.freeze([...value.subtitleHosts]),
|
|
maxSubtitleBytes: CANONICAL_SUBTITLE_BYTES,
|
|
});
|
|
}
|
|
|
|
function loadFallbackPolicy(policyPath) {
|
|
if (policyPath === undefined) return RUNTIME_POLICY;
|
|
let parsed;
|
|
try {
|
|
parsed = JSON.parse(fs.readFileSync(policyPath, 'utf8'));
|
|
} catch (cause) {
|
|
const error = invalidPolicy();
|
|
error.cause = cause;
|
|
throw error;
|
|
}
|
|
return validateFallbackPolicy(parsed);
|
|
}
|
|
|
|
function parseBoolean(environ, name, fallback = false) {
|
|
const raw = environ[name];
|
|
if (raw === undefined || raw === '') return fallback;
|
|
if (raw === 'true') return true;
|
|
if (raw === 'false') return false;
|
|
throw new TypeError(`${name} doit valoir true ou false`);
|
|
}
|
|
|
|
function parsePositiveInteger(environ, name, fallback) {
|
|
const raw = environ[name];
|
|
if (raw === undefined || raw === '') return fallback;
|
|
if (typeof raw !== 'string' || !/^[1-9]\d*$/.test(raw)) throw new TypeError(`${name} invalide`);
|
|
const value = Number(raw);
|
|
if (!Number.isSafeInteger(value)) throw new TypeError(`${name} invalide`);
|
|
return value;
|
|
}
|
|
|
|
function parseHostList(raw) {
|
|
if (raw === undefined || raw === '') return [];
|
|
if (typeof raw !== 'string') throw new TypeError('KISSKH_SUBTITLE_ALLOWED_HOSTS invalide');
|
|
const hosts = raw.split(',');
|
|
if (!hosts.length || hosts.some((host) => host !== host.trim() || !isValidHostname(host))) {
|
|
throw new TypeError('KISSKH_SUBTITLE_ALLOWED_HOSTS invalide');
|
|
}
|
|
const unique = [...new Set(hosts)].sort();
|
|
if (unique.length !== hosts.length) throw new TypeError('KISSKH_SUBTITLE_ALLOWED_HOSTS invalide');
|
|
return unique;
|
|
}
|
|
|
|
function fromEnv(environ) {
|
|
if (!environ || typeof environ !== 'object') throw new TypeError('environnement KissKH invalide');
|
|
const policy = loadFallbackPolicy();
|
|
const enabled = parseBoolean(environ, 'KISSKH_ENABLED');
|
|
const subtitleAllowedHosts = parseHostList(environ.KISSKH_SUBTITLE_ALLOWED_HOSTS);
|
|
const bundleCheckTtlSeconds = parsePositiveInteger(environ, 'KISSKH_BUNDLE_CHECK_TTL_SECONDS', 900);
|
|
const bundleStaleMaxSeconds = parsePositiveInteger(environ, 'KISSKH_BUNDLE_STALE_MAX_SECONDS', 86_400);
|
|
return Object.freeze({
|
|
enabled,
|
|
browserFallbackEnabled: false,
|
|
subtitleAllowedHosts: Object.freeze(subtitleAllowedHosts),
|
|
subtitleMaxBytes: policy.maxSubtitleBytes,
|
|
bundleCheckTtlSeconds,
|
|
bundleStaleMaxSeconds,
|
|
});
|
|
}
|
|
|
|
module.exports = { fromEnv, loadFallbackPolicy, validateFallbackPolicy };
|