From db25f98251257133ead68187e3aa97333cbab302 Mon Sep 17 00:00:00 2001 From: webstreamr <210764791+webstreamr@users.noreply.github.com> Date: Fri, 31 Oct 2025 23:14:48 +0100 Subject: [PATCH] feat(extractor): add Vidora extractor (#466) --- src/extractor/Vidora.test.ts | 20 + src/extractor/Vidora.ts | 46 ++ ...srvmaxcdnandi0.3andsp5000andfr5iz6c1elaqgq | 6 + .../Vidora/https:vidora.stream5iz6c1elaqgq | 605 ++++++++++++++++++ .../__snapshots__/Vidora.test.ts.snap | 41 ++ 5 files changed, 718 insertions(+) create mode 100644 src/extractor/Vidora.test.ts create mode 100644 src/extractor/Vidora.ts create mode 100644 src/extractor/__fixtures__/Vidora/https:cdn.dmovies.tophls203000005iz6c1elaqgq_hx.urlsetmaster.m3u8t59WQnICkdOsWf2RrsiNPQmXTU1CUk7gGqBgLvh-MaIUands1761923136ande43200andv22226828andsrvmaxcdnandi0.3andsp5000andfr5iz6c1elaqgq create mode 100644 src/extractor/__fixtures__/Vidora/https:vidora.stream5iz6c1elaqgq create mode 100644 src/extractor/__snapshots__/Vidora.test.ts.snap diff --git a/src/extractor/Vidora.test.ts b/src/extractor/Vidora.test.ts new file mode 100644 index 0000000..6634ff5 --- /dev/null +++ b/src/extractor/Vidora.test.ts @@ -0,0 +1,20 @@ +import winston from 'winston'; +import { createTestContext } from '../test'; +import { FetcherMock } from '../utils'; +import { ExtractorRegistry } from './ExtractorRegistry'; +import { Vidora } from './Vidora'; + +const logger = winston.createLogger({ transports: [new winston.transports.Console({ level: 'nope' })] }); +const extractorRegistry = new ExtractorRegistry(logger, [new Vidora(new FetcherMock(`${__dirname}/__fixtures__/Vidora`))]); + +const ctx = createTestContext(); + +describe('Vidora', () => { + test('vidora.stream', async () => { + expect(await extractorRegistry.handle(ctx, new URL('https://vidora.stream/5iz6c1elaqgq'))).toMatchSnapshot(); + }); + + test('vidora.stream /embed/', async () => { + expect(await extractorRegistry.handle(ctx, new URL('https://vidora.stream/embed/5iz6c1elaqgq'))).toMatchSnapshot(); + }); +}); diff --git a/src/extractor/Vidora.ts b/src/extractor/Vidora.ts new file mode 100644 index 0000000..ffdf7b7 --- /dev/null +++ b/src/extractor/Vidora.ts @@ -0,0 +1,46 @@ +import * as cheerio from 'cheerio'; +import { Context, Format, Meta, UrlResult } from '../types'; +import { extractUrlFromPacked, guessHeightFromPlaylist } from '../utils'; +import { Extractor } from './Extractor'; + +export class Vidora extends Extractor { + public readonly id = 'vidora'; + + public readonly label = 'Vidora'; + + public override readonly ttl: number = 43200000; // 12h + + public supports(_ctx: Context, url: URL): boolean { + return null !== url.host.match(/vidora/); + } + + public override normalize(url: URL): URL { + return new URL(url.href.replace('/embed/', '/')); + } + + protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { + const html = await this.fetcher.text(ctx, url); + + const $ = cheerio.load(html); + const title = $('title').text().trim().replace(/^Watch /, '').trim(); + + const m3u8Url = extractUrlFromPacked(html, [/file: ?"(.*?)"/]); + const headers = { Origin: url.origin }; + + return [ + { + url: m3u8Url, + format: Format.hls, + label: this.label, + sourceId: `${this.id}_${meta.countryCodes?.join('_')}`, + ttl: this.ttl, + meta: { + ...meta, + height: await guessHeightFromPlaylist(ctx, this.fetcher, m3u8Url, url, { headers }), + title, + }, + requestHeaders: headers, + }, + ]; + }; +} diff --git a/src/extractor/__fixtures__/Vidora/https:cdn.dmovies.tophls203000005iz6c1elaqgq_hx.urlsetmaster.m3u8t59WQnICkdOsWf2RrsiNPQmXTU1CUk7gGqBgLvh-MaIUands1761923136ande43200andv22226828andsrvmaxcdnandi0.3andsp5000andfr5iz6c1elaqgq b/src/extractor/__fixtures__/Vidora/https:cdn.dmovies.tophls203000005iz6c1elaqgq_hx.urlsetmaster.m3u8t59WQnICkdOsWf2RrsiNPQmXTU1CUk7gGqBgLvh-MaIUands1761923136ande43200andv22226828andsrvmaxcdnandi0.3andsp5000andfr5iz6c1elaqgq new file mode 100644 index 0000000..7f3eb4f --- /dev/null +++ b/src/extractor/__fixtures__/Vidora/https:cdn.dmovies.tophls203000005iz6c1elaqgq_hx.urlsetmaster.m3u8t59WQnICkdOsWf2RrsiNPQmXTU1CUk7gGqBgLvh-MaIUands1761923136ande43200andv22226828andsrvmaxcdnandi0.3andsp5000andfr5iz6c1elaqgq @@ -0,0 +1,6 @@ +#EXTM3U +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1484443,RESOLUTION=1720x720,FRAME-RATE=60.000,CODECS="avc1.64002a,mp4a.40.2",VIDEO-RANGE=SDR +https://cdn.dmovies.top/hls2/03/00000/5iz6c1elaqgq_h/index-v1-a1.m3u8?t=59WQnICkdOsWf2RrsiNPQmXTU1CUk7gGqBgLvh-MaIU&s=1761923136&e=43200&v=22226828&srv=maxcdn&i=0.3&sp=5000&fr=5iz6c1elaqgq +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2615495,RESOLUTION=1912x800,FRAME-RATE=60.000,CODECS="avc1.64002a,mp4a.40.2",VIDEO-RANGE=SDR +https://cdn.dmovies.top/hls2/03/00000/5iz6c1elaqgq_x/index-v1-a1.m3u8?t=59WQnICkdOsWf2RrsiNPQmXTU1CUk7gGqBgLvh-MaIU&s=1761923136&e=43200&v=22226828&srv=maxcdn&i=0.3&sp=5000&fr=5iz6c1elaqgq + diff --git a/src/extractor/__fixtures__/Vidora/https:vidora.stream5iz6c1elaqgq b/src/extractor/__fixtures__/Vidora/https:vidora.stream5iz6c1elaqgq new file mode 100644 index 0000000..d2966fa --- /dev/null +++ b/src/extractor/__fixtures__/Vidora/https:vidora.stream5iz6c1elaqgq @@ -0,0 +1,605 @@ + + + + + Watch Highest Lowest 2025 1080p ATVP WEB DDP5 Atmos 264 BYNDR + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+ + +
+ + Sign Up +
+
+ +
+ + +
+
+
+ + + + +
+ + +
+
+ + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + + + +
+ + + +
+
+ + + + + + + +
+
+
+ + +
+
+
+

+ Highest 2 Lowest 2025 1080p ATVP WEB-DL DDP5 1 Atmos H 264-BYNDR + +

+
+
+ on Sep 5, 2025 admin +
+
0 views
+ + + +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ + +
+
+
+
+ + +
+
+ +
+
+ + + + + + + +
+ + +
+ + + + + + +
+ +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+
+ + +
+ + + + + + + + diff --git a/src/extractor/__snapshots__/Vidora.test.ts.snap b/src/extractor/__snapshots__/Vidora.test.ts.snap new file mode 100644 index 0000000..e2b6d6b --- /dev/null +++ b/src/extractor/__snapshots__/Vidora.test.ts.snap @@ -0,0 +1,41 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`Vidora vidora.stream /embed/ 1`] = ` +[ + { + "format": "hls", + "label": "Vidora", + "meta": { + "countryCodes": [], + "height": 800, + "title": "Highest Lowest 2025 1080p ATVP WEB DDP5 Atmos 264 BYNDR", + }, + "requestHeaders": { + "Origin": "https://vidora.stream", + }, + "sourceId": "vidora_", + "ttl": 43200000, + "url": "https://cdn.dmovies.top/hls2/03/00000/5iz6c1elaqgq_,h,x,.urlset/master.m3u8?t=59WQnICkdOsWf2RrsiNPQmXTU1CUk7gGqBgLvh-MaIU&s=1761923136&e=43200&v=22226828&srv=maxcdn&i=0.3&sp=5000&fr=5iz6c1elaqgq", + }, +] +`; + +exports[`Vidora vidora.stream 1`] = ` +[ + { + "format": "hls", + "label": "Vidora", + "meta": { + "countryCodes": [], + "height": 800, + "title": "Highest Lowest 2025 1080p ATVP WEB DDP5 Atmos 264 BYNDR", + }, + "requestHeaders": { + "Origin": "https://vidora.stream", + }, + "sourceId": "vidora_", + "ttl": 43200000, + "url": "https://cdn.dmovies.top/hls2/03/00000/5iz6c1elaqgq_,h,x,.urlset/master.m3u8?t=59WQnICkdOsWf2RrsiNPQmXTU1CUk7gGqBgLvh-MaIU&s=1761923136&e=43200&v=22226828&srv=maxcdn&i=0.3&sp=5000&fr=5iz6c1elaqgq", + }, +] +`;