mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-08 10:23:29 +00:00
@@ -1,6 +1,11 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { DownloadItem } from '../bindings/DownloadItem';
|
||||
import { redactDownloadForPersistence, resolveDownloadConnections } from './downloads';
|
||||
import {
|
||||
downloadFileNamesMatch,
|
||||
downloadMediaKindsMatch,
|
||||
redactDownloadForPersistence,
|
||||
resolveDownloadConnections
|
||||
} from './downloads';
|
||||
|
||||
const item = (status: DownloadItem['status']): DownloadItem => ({
|
||||
id: 'download-1',
|
||||
@@ -56,3 +61,28 @@ describe('download connection resolution', () => {
|
||||
expect(resolveDownloadConnections(Number.NaN, 8)).toBe(8);
|
||||
});
|
||||
});
|
||||
|
||||
describe('download filename matching', () => {
|
||||
it('matches case and path spelling while preserving the actual filename', () => {
|
||||
expect(downloadFileNamesMatch(
|
||||
'Media\\Example.Show.S01E01.MKV',
|
||||
'example.show.s01e01.mkv'
|
||||
)).toBe(true);
|
||||
});
|
||||
|
||||
it('does not collapse distinct extensions or names', () => {
|
||||
expect(downloadFileNamesMatch('example.zip', 'example.tar')).toBe(false);
|
||||
expect(downloadFileNamesMatch('example-1.zip', 'example.zip')).toBe(false);
|
||||
});
|
||||
|
||||
it('does not auto-match weak metadata fallback names', () => {
|
||||
expect(downloadFileNamesMatch('download', 'download')).toBe(false);
|
||||
expect(downloadFileNamesMatch('identifier', 'IDENTIFIER')).toBe(false);
|
||||
expect(downloadFileNamesMatch('real-file.bin', 'real-file.bin')).toBe(true);
|
||||
});
|
||||
|
||||
it('treats omitted media flags as ordinary downloads', () => {
|
||||
expect(downloadMediaKindsMatch(undefined, false)).toBe(true);
|
||||
expect(downloadMediaKindsMatch(undefined, true)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -132,6 +132,29 @@ export const canonicalizeDownloadFileName = (fileName: string): string => {
|
||||
return sanitized && sanitized !== '.' && sanitized !== '..' ? sanitized : 'download';
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare metadata-derived names without allowing path spelling or case to
|
||||
* turn the same download into a second queue entry. Keep the extension and
|
||||
* the rest of the name intact: URL query strings are not part of this value.
|
||||
*/
|
||||
export const normalizeDownloadFileNameForMatch = (fileName: string): string =>
|
||||
canonicalizeDownloadFileName(fileName).normalize('NFKC').toLowerCase();
|
||||
|
||||
export const downloadMediaKindsMatch = (
|
||||
left: boolean | undefined,
|
||||
right: boolean | undefined
|
||||
): boolean => Boolean(left) === Boolean(right);
|
||||
|
||||
const WEAK_DOWNLOAD_FILE_NAMES = new Set(['download', 'identifier', 'view', 'uc']);
|
||||
|
||||
export const downloadFileNamesMatch = (left: string, right: string): boolean => {
|
||||
const normalizedLeft = normalizeDownloadFileNameForMatch(left);
|
||||
const normalizedRight = normalizeDownloadFileNameForMatch(right);
|
||||
return !WEAK_DOWNLOAD_FILE_NAMES.has(normalizedLeft)
|
||||
&& !WEAK_DOWNLOAD_FILE_NAMES.has(normalizedRight)
|
||||
&& normalizedLeft === normalizedRight;
|
||||
};
|
||||
|
||||
export const isMediaUrl = (rawUrl: string): boolean => {
|
||||
try {
|
||||
const url = new URL(rawUrl);
|
||||
|
||||
Reference in New Issue
Block a user