From fb61d3922566b9fbcdeb295dc30c041c356586fc Mon Sep 17 00:00:00 2001 From: WebStreamr <210764791+webstreamr@users.noreply.github.com> Date: Sun, 18 May 2025 21:20:48 +0200 Subject: [PATCH] feat(extractor): implement UQLoad --- src/extractor/ExtractorRegistry.ts | 2 + src/extractor/UQLoad.ts | 37 +++ src/handler/Frembed.test.ts | 18 ++ ...apiseriesid42009andsa7andepi1andidTypetmdb | 1 + .../https:uqload.netembed-zbcuhvyfh3ni.html | 262 ++++++++++++++++++ 5 files changed, 320 insertions(+) create mode 100644 src/extractor/UQLoad.ts create mode 100644 src/utils/__fixtures__/Fetcher/https:frembed.clubapiseriesid42009andsa7andepi1andidTypetmdb create mode 100644 src/utils/__fixtures__/Fetcher/https:uqload.netembed-zbcuhvyfh3ni.html diff --git a/src/extractor/ExtractorRegistry.ts b/src/extractor/ExtractorRegistry.ts index a8d8ac6..a2aac6f 100644 --- a/src/extractor/ExtractorRegistry.ts +++ b/src/extractor/ExtractorRegistry.ts @@ -6,6 +6,7 @@ import { Fetcher } from '../utils'; import { DoodStream } from './DoodStream'; import { Dropload } from './Dropload'; import { SuperVideo } from './SuperVideo'; +import { UQLoad } from './UQLoad'; export class ExtractorRegistry { private readonly logger: winston.Logger; @@ -18,6 +19,7 @@ export class ExtractorRegistry { new DoodStream(fetcher), new Dropload(fetcher), new SuperVideo(fetcher), + new UQLoad(fetcher), ]; this.urlResultCache = new TTLCache({ max: 1024 }); } diff --git a/src/extractor/UQLoad.ts b/src/extractor/UQLoad.ts new file mode 100644 index 0000000..34ee5c0 --- /dev/null +++ b/src/extractor/UQLoad.ts @@ -0,0 +1,37 @@ +import { Extractor } from './types'; +import { Fetcher } from '../utils'; +import { Context } from '../types'; + +export class UQLoad implements Extractor { + readonly id = 'uqload'; + + readonly label = 'UQLoad'; + + readonly ttl = 900000; // 15m + + private readonly fetcher: Fetcher; + + constructor(fetcher: Fetcher) { + this.fetcher = fetcher; + } + + readonly supports = (url: URL): boolean => null !== url.host.match(/uqload/); + + readonly extract = async (ctx: Context, url: URL, countryCode: string) => { + const html = await this.fetcher.text(ctx, url); + + const sourceMatch = html.match(/sources: ?\[["'](.*?)["']/) as string[]; + + return { + url: new URL(sourceMatch[1] as string), + label: this.label, + sourceId: `${this.id}_${countryCode.toLowerCase()}`, + height: 0, + bytes: 0, + countryCode, + requestHeaders: { + Referer: `${url.protocol}//${url.host.split('.').slice().slice(-2).join('.')}`, + }, + }; + }; +} diff --git a/src/handler/Frembed.test.ts b/src/handler/Frembed.test.ts index ce3c8ca..1ea4ab8 100644 --- a/src/handler/Frembed.test.ts +++ b/src/handler/Frembed.test.ts @@ -41,4 +41,22 @@ describe('Frembed', () => { }); expect(streams[0]?.url.href).toMatch(/^https:\/\/.*?token.*?expiry/); }); + + test('handle imdb black mirror s7e1', async () => { + const streams = (await handler.handle(ctx, 'series', 'tt2085059:7:1')).filter(stream => stream !== undefined); + + expect(streams).toHaveLength(1); + expect(streams[0]).toStrictEqual({ + url: expect.any(URL), + label: 'UQLoad', + sourceId: 'uqload_fr', + height: 0, + bytes: 0, + countryCode: 'fr', + requestHeaders: { + Referer: 'https://uqload.net', + }, + }); + expect(streams[0]?.url.href).toMatch(/^https:\/\/.*?uqload\.net\/.*?\.mp4/); + }); }); diff --git a/src/utils/__fixtures__/Fetcher/https:frembed.clubapiseriesid42009andsa7andepi1andidTypetmdb b/src/utils/__fixtures__/Fetcher/https:frembed.clubapiseriesid42009andsa7andepi1andidTypetmdb new file mode 100644 index 0000000..eee8670 --- /dev/null +++ b/src/utils/__fixtures__/Fetcher/https:frembed.clubapiseriesid42009andsa7andepi1andidTypetmdb @@ -0,0 +1 @@ +{"id":96183,"tmdb":"42009","title":"Black Mirror","sa":7,"epi":1,"link":null,"imdb":"","year":2025,"version":"VF","link_vostfr":null,"link1":null,"link2":"https://netu.frembed.art/f/hF3h2vKWJHkJ","link3":"https://johnalwayssame.com/e/5uxuyrmybm4w","link4":"https://uqload.net/embed-zbcuhvyfh3ni.html","link5":null,"link6":null,"link7":null,"link1vostfr":null,"link2vostfr":null,"link3vostfr":null,"link4vostfr":null,"link5vostfr":null,"link6vostfr":null,"link7vostfr":null,"link1vo":null,"link2vo":null,"link3vo":null,"link4vo":null,"link5vo":null,"link6vo":null,"link7vo":null,"date_creation":"2025-04-11T23:32:58.000Z","update_date":"2025-04-25T22:27:04.000Z","views":11,"tatavid":"https://tatavid.com/embed-2aq5umwg3n7r.html","backdropImage":"/dg3OindVAGZBjlT3xYKqIAdukPL.jpg","posterImage":"/seN6rRfN0I6n8iDXjlSMk1QjNcq.jpg","prevEpisode":{"sa":6,"epi":5,"url":"/series?id=42009&sa=6&epi=5"},"nextEpisode":{"sa":7,"epi":2,"url":"/series?id=42009&sa=7&epi=2"}} \ No newline at end of file diff --git a/src/utils/__fixtures__/Fetcher/https:uqload.netembed-zbcuhvyfh3ni.html b/src/utils/__fixtures__/Fetcher/https:uqload.netembed-zbcuhvyfh3ni.html new file mode 100644 index 0000000..8342bd1 --- /dev/null +++ b/src/utils/__fixtures__/Fetcher/https:uqload.netembed-zbcuhvyfh3ni.html @@ -0,0 +1,262 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + +