refactor: make resolution and size optional and extract resolution helper
This should come in handy later when adding more providers
This commit is contained in:
parent
e063d71710
commit
3a87ddb9f0
8 changed files with 67 additions and 14 deletions
|
|
@ -43,12 +43,12 @@ type RequestConfig = Record<string, boolean | string | number>;
|
|||
|
||||
const sortStreams = (streams: HandlerStream[]): void => {
|
||||
streams.sort((a, b) => {
|
||||
const resolutionComparison = parseInt(b.resolution) - parseInt(a.resolution);
|
||||
const resolutionComparison = parseInt(b.resolution ?? '0') - parseInt(a.resolution ?? '0');
|
||||
if (resolutionComparison !== 0) {
|
||||
return resolutionComparison;
|
||||
}
|
||||
|
||||
return parseFloat(b.size) - parseFloat(a.size);
|
||||
return parseFloat(b.size ?? '0') - parseFloat(a.size ?? '0');
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Stream } from 'stremio-addon-sdk';
|
||||
|
||||
export type HandlerStream = Stream & { resolution: string; size: string };
|
||||
export type HandlerStream = Stream & { resolution: string | undefined; size: string | undefined };
|
||||
|
||||
export interface Handler {
|
||||
readonly id: string;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ describe('unpackEmbedUrl', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('resolution and size return "?" if not found', async () => {
|
||||
test('resolution and size return undefined if not found', async () => {
|
||||
(unpack as jest.Mock).mockReturnValue('{sources:[{file:"https://streaming-url.mp4"}');
|
||||
(cachedFetchText as jest.Mock).mockReturnValue(
|
||||
Promise.resolve('<html><body>Something to stream<script>(eval(function(p,a,c,k,e,d){...}))</script></body></html>'),
|
||||
|
|
@ -51,8 +51,8 @@ describe('unpackEmbedUrl', () => {
|
|||
const parsePackedEmbedResult = await parsePackedEmbed('https://some-url.test');
|
||||
expect(parsePackedEmbedResult).toStrictEqual({
|
||||
url: 'https://streaming-url.mp4',
|
||||
resolution: '?',
|
||||
size: '?',
|
||||
resolution: undefined,
|
||||
size: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { unpack } from 'unpacker';
|
||||
import { cachedFetchText } from './fetch';
|
||||
import { scanFromResolution } from './resolution';
|
||||
|
||||
const LINK_REGEXPS = [
|
||||
/sources:\[{file:"(.*?)"/, // dropload, supervideo
|
||||
|
|
@ -7,20 +8,20 @@ const LINK_REGEXPS = [
|
|||
|
||||
interface ParsePackedEmbedResult {
|
||||
url: string;
|
||||
resolution: string;
|
||||
size: string;
|
||||
resolution: string | undefined;
|
||||
size: string | undefined;
|
||||
}
|
||||
|
||||
const findResolution = (html: string): string => {
|
||||
const match = html.match(/\d{3,}x(\d{3,}),/);
|
||||
const findResolution = (html: string): string | undefined => {
|
||||
const match = html.match(/(\d{3,}x\d{3,}),/);
|
||||
|
||||
return match && match[1] ? `${match[1]}p` : '?';
|
||||
return match && match[1] ? scanFromResolution(match[1]) : undefined;
|
||||
};
|
||||
|
||||
const findSize = (html: string): string => {
|
||||
const findSize = (html: string): string | undefined => {
|
||||
const sizeMatch = html.match(/([\d.]+) ?([GM]B)/);
|
||||
|
||||
return sizeMatch && sizeMatch[1] && sizeMatch[2] ? `${sizeMatch[1]} ${sizeMatch[2]}` : '?';
|
||||
return sizeMatch && sizeMatch[1] && sizeMatch[2] ? `${sizeMatch[1]} ${sizeMatch[2]}` : undefined;
|
||||
};
|
||||
|
||||
export const parsePackedEmbed = async (url: string): Promise<ParsePackedEmbedResult> => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { logError, logInfo } from './log';
|
||||
import { logError, logInfo, logWarn } from './log';
|
||||
|
||||
describe('log', () => {
|
||||
test('logError logs via console.error', () => {
|
||||
|
|
@ -10,6 +10,15 @@ describe('log', () => {
|
|||
expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('some error occurred'));
|
||||
});
|
||||
|
||||
test('logWarn logs via console.info', () => {
|
||||
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
|
||||
logWarn('something happened');
|
||||
|
||||
expect(consoleWarnSpy).toHaveBeenCalled();
|
||||
expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining('something happened'));
|
||||
});
|
||||
|
||||
test('logInfo logs via console.info', () => {
|
||||
const consoleInfoSpy = jest.spyOn(console, 'info').mockImplementation(() => undefined);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@ export const logError = (message: string) => {
|
|||
console.error(`${new Date().toISOString()}, Error: ${message}`);
|
||||
};
|
||||
|
||||
export const logWarn = (message: string) => {
|
||||
console.warn(`${new Date().toISOString()}, Warn: ${message}`);
|
||||
};
|
||||
|
||||
export const logInfo = (message: string) => {
|
||||
console.info(`${new Date().toISOString()}, Info: ${message}`);
|
||||
};
|
||||
|
|
|
|||
25
src/utils/resolution.test.ts
Normal file
25
src/utils/resolution.test.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { scanFromResolution } from './resolution';
|
||||
|
||||
describe('scanFromResolution', () => {
|
||||
test.each([
|
||||
['720p', '1280x720'],
|
||||
['720p', '1280 x 720 '],
|
||||
['240p', '352x240'],
|
||||
['240p', '352x240'],
|
||||
['480p', '720x480'],
|
||||
['1080p', '1280x1080'],
|
||||
['2160p', '3840x2160'],
|
||||
['4320p', '7680x4320'],
|
||||
])('returns %s with %s', (output, input) => {
|
||||
expect(scanFromResolution(input)).toBe(output);
|
||||
});
|
||||
|
||||
test('logs and returns undefined for invalid resolution', () => {
|
||||
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
|
||||
expect(scanFromResolution('foo')).toBe(undefined);
|
||||
|
||||
expect(consoleWarnSpy).toHaveBeenCalled();
|
||||
expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining('"foo" is not a valid resolution'));
|
||||
});
|
||||
});
|
||||
14
src/utils/resolution.ts
Normal file
14
src/utils/resolution.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { logWarn } from './log';
|
||||
|
||||
// Returns the scan from a resolution string. E.g. 720p for "1280x720"
|
||||
// See https://en.wikipedia.org/wiki/List_of_common_display_resolutions#Digital_standards
|
||||
export const scanFromResolution = (resolution: string): string | undefined => {
|
||||
const height = parseInt(resolution.split('x')[1]?.trim() || '');
|
||||
|
||||
if (isNaN(height)) {
|
||||
logWarn(`"${resolution}" is not a valid resolution`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return `${height}p`;
|
||||
};
|
||||
Loading…
Reference in a new issue