diff --git a/src/extractor/Soaper.ts b/src/extractor/Soaper.ts index cc05928..06d2d17 100644 --- a/src/extractor/Soaper.ts +++ b/src/extractor/Soaper.ts @@ -1,5 +1,5 @@ import { Extractor } from './types'; -import { Fetcher } from '../utils'; +import { Fetcher, guessFromPlaylist } from '../utils'; import { Context, Meta, UrlResult } from '../types'; interface SoaperInfoResponsePartial { @@ -47,18 +47,17 @@ export class Soaper implements Extractor { const jsonResponse = JSON.parse(response) as SoaperInfoResponsePartial; const m3u8Url = new URL(jsonResponse['val'], url.origin); - const m3u8Data = await this.fetcher.text(ctx, m3u8Url); - const height = m3u8Data.match(/\d+x(\d+)|(\d+)p/) as string[]; + const height = await guessFromPlaylist(ctx, this.fetcher, m3u8Url); return [ { - url: new URL(jsonResponse['val'], url.origin), + url: m3u8Url, label: this.label, sourceId: `${this.id}_${meta.countryCode.toLowerCase()}`, ttl: this.ttl, meta: { ...meta, - ...(height && { height: parseInt(height[1] ?? height[2] as string) }), + ...(height && { height }), }, }, ]; diff --git a/src/utils/height.ts b/src/utils/height.ts index 23ea291..86ecf7c 100644 --- a/src/utils/height.ts +++ b/src/utils/height.ts @@ -1,3 +1,6 @@ +import { Fetcher } from './Fetcher'; +import { Context } from '../types'; + export const guessFromTitle = (title: string): number | undefined => { const heightMatch = title.match(/([0-9]+)p/); if (heightMatch && heightMatch[1]) { @@ -6,3 +9,14 @@ export const guessFromTitle = (title: string): number | undefined => { return undefined; }; + +export const guessFromPlaylist = async (ctx: Context, fetcher: Fetcher, url: URL): Promise => { + const m3u8Data = await fetcher.text(ctx, url); + + const heights = Array.from(m3u8Data.matchAll(/\d+x(\d+)|(\d+)p/g)) + .map(heightMatch => heightMatch[1] ?? heightMatch[2]) + .filter(height => height !== undefined) + .map(height => parseInt(height)); + + return Math.max(...heights); +};