1 Commits
Author SHA1 Message Date
Worph 0ac862c681 improve search and fix languages
Build and Push Docker Image / build (push) Failing after 15s
2026-09-14 22:29:50 +02:00
2 changed files with 30 additions and 4 deletions
+21 -2
View File
@@ -242,9 +242,22 @@ export async function midhashOverWebDAV(client: WebDAVClient, filePath: string,
// Record keys // Record keys
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/**
* Keys on the video record for one linked subtitle (METADATA_KEYS.md §8, §9).
*
* The language lands in `subtitleLanguages/<lang3>` **and** in the
* `languages/<lang3>` union — §9 rule #7: "a union field is written, never
* computed". Nothing reconciles them afterwards, and `languages` is the only
* field a query filters on, so a subtitle language recorded in the split alone
* is invisible to every language filter on every peer. This mirrors
* subtitle-extractor's `videoSubtitleKeys`, which has always written both.
*/
export function videoSubtitleKeys(subCid: string, lang3: string): Record<string, string> { export function videoSubtitleKeys(subCid: string, lang3: string): Record<string, string> {
const keys: Record<string, string> = { [`subtitles/${lang3}/${subCid}`]: 'true' }; const keys: Record<string, string> = { [`subtitles/${lang3}/${subCid}`]: 'true' };
if (lang3 !== 'und') keys[`subtitleLanguages/${lang3}`] = 'true'; if (lang3 !== 'und') {
keys[`subtitleLanguages/${lang3}`] = 'true';
keys[`languages/${lang3}`] = 'true';
}
return keys; return keys;
} }
@@ -299,7 +312,13 @@ async function writeVideoLinks(
deletes.push('subtitleLanguages'); deletes.push('subtitleLanguages');
for (const code of legacyLangs) { for (const code of legacyLangs) {
const l = languageToken(code); const l = languageToken(code);
if (l && l !== 'und') sets[`subtitleLanguages/${l}`] = 'true'; if (l && l !== 'und') {
sets[`subtitleLanguages/${l}`] = 'true';
// The legacy csv never had a union member to migrate, so the
// migration is also the only chance to satisfy §9 rule #7 for
// these records.
sets[`languages/${l}`] = 'true';
}
} }
} }
for (const { subCid, lang3 } of links) deletes.push(...staleLanguageLeaves(flat, 'subtitles', subCid, lang3)); for (const { subCid, lang3 } of links) deletes.push(...staleLanguageLeaves(flat, 'subtitles', subCid, lang3));
+9 -2
View File
@@ -220,8 +220,15 @@ describe('midhash256', () => {
}); });
describe('record keys (METADATA_KEYS.md §8)', () => { describe('record keys (METADATA_KEYS.md §8)', () => {
it('video: language-nested leaf, plus the facet for a known language', () => { it('video: language-nested leaf, plus the facet AND the union for a known language', () => {
expect(videoSubtitleKeys('bagsub', 'fre')).toEqual({ 'subtitles/fre/bagsub': 'true', 'subtitleLanguages/fre': 'true' }); // §9 rule #7 — the split never travels without the union, because
// `languages` is the only field a query filters on.
expect(videoSubtitleKeys('bagsub', 'fre')).toEqual({
'subtitles/fre/bagsub': 'true',
'subtitleLanguages/fre': 'true',
'languages/fre': 'true',
});
// `und` is never a member of either set (§9).
expect(videoSubtitleKeys('bagsub', 'und')).toEqual({ 'subtitles/und/bagsub': 'true' }); expect(videoSubtitleKeys('bagsub', 'und')).toEqual({ 'subtitles/und/bagsub': 'true' });
}); });