mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-26 00:55:16 -07:00
212 lines
6.5 KiB
TypeScript
212 lines
6.5 KiB
TypeScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import * as fs from 'fs';
|
|
import * as os from 'os';
|
|
import * as path from 'path';
|
|
|
|
import {
|
|
buildCharacterDictionarySeriesKey,
|
|
createCharacterDictionaryManualSelectionStore,
|
|
} from './manual-selection';
|
|
|
|
const REZERO_EP1 =
|
|
'/anime/ReZERO/Season 1/Re - ZERO, Starting Life in Another World (2016) - S01E01 - - The End of the Beginning and the Beginning of the End [v2 Bluray-1080p Proper][10bit][x265][FLAC 2.0][EN+JA]-SCY.mkv';
|
|
const REZERO_EP2 =
|
|
'/anime/ReZERO/Season 1/Re - ZERO, Starting Life in Another World (2016) - S01E02 - Reunion with the Witch [Bluray-1080p][x265][JA]-SCY.mkv';
|
|
const REZERO_S2_EP1 =
|
|
'/anime/ReZERO/Season 2/Re - ZERO, Starting Life in Another World (2016) - S02E01 - Each Ones Promise [Bluray-1080p][x265][JA]-SCY.mkv';
|
|
|
|
function makeTempDir(): string {
|
|
return fs.mkdtempSync(path.join(os.tmpdir(), 'subminer-manual-selection-'));
|
|
}
|
|
|
|
test('buildCharacterDictionarySeriesKey scopes guessit title and year by media directory', () => {
|
|
const key = buildCharacterDictionarySeriesKey({
|
|
mediaPath: REZERO_EP1,
|
|
mediaTitle: null,
|
|
guess: {
|
|
title: 'Re ZERO, Starting Life in Another World',
|
|
alternativeTitle: 'ZERO, Starting Life in Another World',
|
|
year: 2016,
|
|
season: 1,
|
|
episode: 1,
|
|
source: 'guessit',
|
|
},
|
|
});
|
|
|
|
assert.equal(key, 'anime-rezero-season-1--re-zero-starting-life-in-another-world-2016');
|
|
});
|
|
|
|
test('manual selection store persists overrides and matches later episodes in the same directory', async () => {
|
|
const userDataPath = makeTempDir();
|
|
const store = createCharacterDictionaryManualSelectionStore({ userDataPath });
|
|
const firstKey = buildCharacterDictionarySeriesKey({
|
|
mediaPath: REZERO_EP1,
|
|
mediaTitle: null,
|
|
guess: {
|
|
title: 'Re ZERO, Starting Life in Another World',
|
|
alternativeTitle: 'ZERO, Starting Life in Another World',
|
|
year: 2016,
|
|
season: 1,
|
|
episode: 1,
|
|
source: 'guessit',
|
|
},
|
|
});
|
|
await store.setOverride({
|
|
seriesKey: firstKey,
|
|
mediaId: 21355,
|
|
mediaTitle: 'Re:ZERO -Starting Life in Another World-',
|
|
staleMediaIds: [10607],
|
|
});
|
|
|
|
const reloaded = createCharacterDictionaryManualSelectionStore({ userDataPath });
|
|
const secondKey = buildCharacterDictionarySeriesKey({
|
|
mediaPath: REZERO_EP2,
|
|
mediaTitle: null,
|
|
guess: {
|
|
title: 'Re ZERO, Starting Life in Another World',
|
|
alternativeTitle: 'ZERO, Starting Life in Another World',
|
|
year: 2016,
|
|
season: 1,
|
|
episode: 2,
|
|
source: 'guessit',
|
|
},
|
|
});
|
|
|
|
assert.equal(secondKey, firstKey);
|
|
assert.deepEqual(await reloaded.getOverride(secondKey), {
|
|
seriesKey: firstKey,
|
|
mediaId: 21355,
|
|
mediaTitle: 'Re:ZERO -Starting Life in Another World-',
|
|
staleMediaIds: [10607],
|
|
});
|
|
});
|
|
|
|
test('manual selection store resolves legacy unscoped override keys', async () => {
|
|
const userDataPath = makeTempDir();
|
|
const overrideDir = path.join(userDataPath, 'character-dictionaries');
|
|
fs.mkdirSync(overrideDir, { recursive: true });
|
|
fs.writeFileSync(
|
|
path.join(overrideDir, 'anilist-overrides.json'),
|
|
JSON.stringify({
|
|
overrides: [
|
|
{
|
|
seriesKey: 're-zero-starting-life-in-another-world-2016',
|
|
mediaId: 21355,
|
|
mediaTitle: 'Re:ZERO -Starting Life in Another World-',
|
|
staleMediaIds: [10607],
|
|
},
|
|
],
|
|
}),
|
|
'utf8',
|
|
);
|
|
|
|
const scopedKey = buildCharacterDictionarySeriesKey({
|
|
mediaPath: REZERO_EP1,
|
|
mediaTitle: null,
|
|
guess: {
|
|
title: 'Re ZERO, Starting Life in Another World',
|
|
alternativeTitle: 'ZERO, Starting Life in Another World',
|
|
year: 2016,
|
|
season: 1,
|
|
episode: 1,
|
|
source: 'guessit',
|
|
},
|
|
});
|
|
|
|
const store = createCharacterDictionaryManualSelectionStore({ userDataPath });
|
|
|
|
assert.deepEqual(await store.getOverride(scopedKey), {
|
|
seriesKey: 're-zero-starting-life-in-another-world-2016',
|
|
mediaId: 21355,
|
|
mediaTitle: 'Re:ZERO -Starting Life in Another World-',
|
|
staleMediaIds: [10607],
|
|
});
|
|
});
|
|
|
|
test('manual selection store prefers exact scoped override over legacy fallback', async () => {
|
|
const userDataPath = makeTempDir();
|
|
const overrideDir = path.join(userDataPath, 'character-dictionaries');
|
|
fs.mkdirSync(overrideDir, { recursive: true });
|
|
const scopedKey = buildCharacterDictionarySeriesKey({
|
|
mediaPath: REZERO_EP1,
|
|
mediaTitle: null,
|
|
guess: {
|
|
title: 'Re ZERO, Starting Life in Another World',
|
|
alternativeTitle: 'ZERO, Starting Life in Another World',
|
|
year: 2016,
|
|
season: 1,
|
|
episode: 1,
|
|
source: 'guessit',
|
|
},
|
|
});
|
|
fs.writeFileSync(
|
|
path.join(overrideDir, 'anilist-overrides.json'),
|
|
JSON.stringify({
|
|
overrides: [
|
|
{
|
|
seriesKey: 're-zero-starting-life-in-another-world-2016',
|
|
mediaId: 10607,
|
|
mediaTitle: 'Legacy Re:ZERO',
|
|
staleMediaIds: [],
|
|
},
|
|
{
|
|
seriesKey: scopedKey,
|
|
mediaId: 21355,
|
|
mediaTitle: 'Re:ZERO -Starting Life in Another World-',
|
|
staleMediaIds: [10607],
|
|
},
|
|
],
|
|
}),
|
|
'utf8',
|
|
);
|
|
|
|
const store = createCharacterDictionaryManualSelectionStore({ userDataPath });
|
|
|
|
assert.deepEqual(await store.getOverride(scopedKey), {
|
|
seriesKey: scopedKey,
|
|
mediaId: 21355,
|
|
mediaTitle: 'Re:ZERO -Starting Life in Another World-',
|
|
staleMediaIds: [10607],
|
|
});
|
|
});
|
|
|
|
test('manual selection store keeps overrides separate for different season directories', async () => {
|
|
const userDataPath = makeTempDir();
|
|
const store = createCharacterDictionaryManualSelectionStore({ userDataPath });
|
|
const firstSeasonKey = buildCharacterDictionarySeriesKey({
|
|
mediaPath: REZERO_EP1,
|
|
mediaTitle: null,
|
|
guess: {
|
|
title: 'Re ZERO, Starting Life in Another World',
|
|
alternativeTitle: 'ZERO, Starting Life in Another World',
|
|
year: 2016,
|
|
season: 1,
|
|
episode: 1,
|
|
source: 'guessit',
|
|
},
|
|
});
|
|
await store.setOverride({
|
|
seriesKey: firstSeasonKey,
|
|
mediaId: 21355,
|
|
mediaTitle: 'Re:ZERO -Starting Life in Another World-',
|
|
staleMediaIds: [],
|
|
});
|
|
|
|
const secondSeasonKey = buildCharacterDictionarySeriesKey({
|
|
mediaPath: REZERO_S2_EP1,
|
|
mediaTitle: null,
|
|
guess: {
|
|
title: 'Re ZERO, Starting Life in Another World',
|
|
alternativeTitle: 'ZERO, Starting Life in Another World',
|
|
year: 2016,
|
|
season: 2,
|
|
episode: 1,
|
|
source: 'guessit',
|
|
},
|
|
});
|
|
|
|
assert.notEqual(secondSeasonKey, firstSeasonKey);
|
|
assert.equal(await store.getOverride(secondSeasonKey), null);
|
|
});
|