Add a languageDetectionMode setting (algo | laya | laya+algo) exposed in Settings with three engine choices. When Laya is enabled, a laya service (Dockerfile.laya, optional compose profile, models stored outside the repo under ./data/models/laya) can be started, with model download and deletion from the UI via /laya routes to manage disk space. Add a channelLanguageFusion service combining Laya results with the existing algorithm, and wire detection mode through grouping, channel list and player. Cover engine selection, fusion and laya service behavior with tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
42 lines
1.8 KiB
JavaScript
42 lines
1.8 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fusion = require('../public/js/services/channelLanguageFusion.js');
|
|
|
|
const algo = {
|
|
language: { code: 'fr', label: 'French', confidence: 70, status: 'medium' },
|
|
languageScores: { fr: 70, en: 30 },
|
|
languageEvidence: [{ code: 'fr', weight: 60, type: 'name-prefix', value: 'FR' }]
|
|
};
|
|
|
|
test('Laya-only mode maps backend confidence and language', () => {
|
|
const result = fusion.applyLanguageMode(algo, { language: 'en', confidence: 0.88 }, 'laya');
|
|
assert.deepEqual(result.language, { code: 'en', label: 'English', confidence: 88, status: 'high' });
|
|
assert.equal(result.languageEvidence[0].type, 'laya');
|
|
});
|
|
|
|
test('hybrid mode combines Laya and algorithm evidence', () => {
|
|
const result = fusion.applyLanguageMode(algo, { language: 'en', confidence: 0.9 }, 'hybrid');
|
|
assert.equal(result.language.code, 'en');
|
|
assert.ok(result.languageScores.en > result.languageScores.fr);
|
|
assert.deepEqual(result.languageEvidence.map(item => item.type), ['name-prefix', 'laya']);
|
|
});
|
|
|
|
test('hybrid mode safely preserves algorithm output without Laya', () => {
|
|
assert.equal(fusion.applyLanguageMode(algo, null, 'hybrid'), algo);
|
|
});
|
|
|
|
test('batch descriptors contain only safe metadata in the backend id/text contract', () => {
|
|
const descriptor = fusion.buildLayaDescriptor({
|
|
sourceId: 4,
|
|
name: '|FR| Sports',
|
|
groupTitle: 'Sports',
|
|
sourceName: 'Provider',
|
|
tvgId: 'sports.fr',
|
|
url: 'https://user:secret@example.test/live'
|
|
}, '4:channel-1', algo);
|
|
assert.deepEqual(Object.keys(descriptor), ['id', 'text']);
|
|
assert.equal(descriptor.id, '4:channel-1');
|
|
assert.match(descriptor.text, /sourceId: 4/);
|
|
assert.doesNotMatch(descriptor.text, /secret|https:\/\//);
|
|
});
|