MovixOpenSource/API/Mainapi/services/kisskh/__tests__/config.test.js
Movix eae5a24c51 feat: ajoute KissKH et fiabilise les sources, les sous-titres et le Cast — Android 2.5.8
- 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>
2026-08-03 21:37:41 +02:00

109 lines
4.9 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const path = require('node:path');
const CANONICAL_HOSTS = 'auto.cdnvideo11.shop,sub.cdnvideo11.shop';
function enabledEnv(overrides = {}) {
return {
KISSKH_ENABLED: 'true',
KISSKH_BROWSER_FALLBACK_ENABLED: 'true',
KISSKH_SUBTITLE_ALLOWED_HOSTS: CANONICAL_HOSTS,
KISSKH_SUBTITLE_MAX_BYTES: '2097152',
...overrides,
};
}
test('canonical fallback policy has the exact strict shape', () => {
const { loadFallbackPolicy } = require('../config');
const policy = loadFallbackPolicy();
assert.deepEqual(Object.keys(policy), ['version', 'subtitleHosts', 'maxSubtitleBytes']);
assert.equal(policy.version, 1);
assert.deepEqual(policy.subtitleHosts, ['auto.cdnvideo11.shop', 'sub.cdnvideo11.shop']);
assert.equal(policy.maxSubtitleBytes, 2097152);
});
test('runtime configuration starts without a deployed monorepo policy file', () => {
const fs = require('node:fs');
const originalReadFileSync = fs.readFileSync;
fs.readFileSync = (filename, ...args) => {
if (String(filename).endsWith('kisskhFallbackPolicy.json')) {
const error = new Error('simulated container policy absence');
error.code = 'ENOENT';
throw error;
}
return originalReadFileSync(filename, ...args);
};
try {
const { fromEnv } = require('../config');
const config = fromEnv(enabledEnv());
assert.equal(config.subtitleMaxBytes, 2097152);
} finally {
fs.readFileSync = originalReadFileSync;
}
});
test('config ignores removed browser fallback and subtitle byte environment settings', () => {
const { fromEnv } = require('../config');
for (const value of ['0', '-1', '1.5', '1e3', ' 2097152', '2097152 ', '9007199254740992']) {
const config = fromEnv(enabledEnv({
KISSKH_BROWSER_FALLBACK_ENABLED: 'true',
KISSKH_SUBTITLE_MAX_BYTES: value,
}));
assert.equal(config.browserFallbackEnabled, false);
assert.equal(config.subtitleMaxBytes, 2097152);
}
for (const name of ['KISSKH_BUNDLE_CHECK_TTL_SECONDS', 'KISSKH_BUNDLE_STALE_MAX_SECONDS']) {
assert.throws(() => fromEnv(enabledEnv({ [name]: '1.5' })), new RegExp(name));
}
});
test('enabled KissKH does not require or expose an internal secret', () => {
const { fromEnv } = require('../config');
const config = fromEnv(enabledEnv({ KISSKH_INTERNAL_SECRET: '' }));
assert.equal(Object.hasOwn(config, 'internalSecret'), false);
});
test('config rejects a missing or invalid canonical policy', () => {
const { loadFallbackPolicy, validateFallbackPolicy } = require('../config');
assert.throws(() => loadFallbackPolicy(path.join(__dirname, 'fixtures', 'missing-policy.json')), /policy/i);
assert.throws(() => validateFallbackPolicy({ version: 1, subtitleHosts: [], maxSubtitleBytes: 2097152 }), /policy/i);
assert.throws(() => validateFallbackPolicy({ version: 1, subtitleHosts: ['*.cdnvideo11.shop'], maxSubtitleBytes: 2097152 }), /policy/i);
assert.throws(() => validateFallbackPolicy({ version: 1, subtitleHosts: ['placeholder.example.com'], maxSubtitleBytes: 2097152 }), /policy/i);
assert.throws(() => validateFallbackPolicy({ version: 1, subtitleHosts: ['sub.cdnvideo11.shop', 'auto.cdnvideo11.shop'], maxSubtitleBytes: 2097152 }), /policy/i);
assert.throws(() => validateFallbackPolicy({ version: 1, subtitleHosts: ['auto.cdnvideo11.shop'], maxSubtitleBytes: 1000 }), /policy/i);
assert.throws(() => validateFallbackPolicy({ version: 1, subtitleHosts: ['auto.cdnvideo11.shop'], maxSubtitleBytes: 2097152, extra: true }), /policy/i);
});
test('enabled KissKH keeps browser fallback disabled and canonical byte limit', () => {
const { fromEnv } = require('../config');
const config = fromEnv(enabledEnv());
assert.equal(config.enabled, true);
assert.equal(config.browserFallbackEnabled, false);
assert.deepEqual(config.subtitleAllowedHosts, ['auto.cdnvideo11.shop', 'sub.cdnvideo11.shop']);
assert.equal(config.subtitleMaxBytes, 2097152);
assert.equal(config.bundleCheckTtlSeconds, 900);
assert.equal(config.bundleStaleMaxSeconds, 86400);
});
test('enabled browser fallback accepts host drift separately', () => {
const { fromEnv } = require('../config');
const config = fromEnv(enabledEnv({ KISSKH_SUBTITLE_ALLOWED_HOSTS: 'sub.cdnvideo11.shop' }));
assert.deepEqual(config.subtitleAllowedHosts, ['sub.cdnvideo11.shop']);
});
test('enabled KissKH ignores byte-limit drift', () => {
const { fromEnv } = require('../config');
const config = fromEnv(enabledEnv({ KISSKH_SUBTITLE_MAX_BYTES: '1048576' }));
assert.equal(config.subtitleMaxBytes, 2097152);
});
test('disabled KissKH uses safe defaults without requiring a secret', () => {
const { fromEnv } = require('../config');
const config = fromEnv({});
assert.equal(config.enabled, false);
assert.equal(config.browserFallbackEnabled, false);
assert.equal(Object.hasOwn(config, 'internalSecret'), false);
assert.deepEqual(config.subtitleAllowedHosts, []);
assert.equal(config.subtitleMaxBytes, 2097152);
});