From 02c9ae3b1b7b384a4c3a98861b4a26e32b40ed5e Mon Sep 17 00:00:00 2001 From: WebStreamr <210764791+webstreamr@users.noreply.github.com> Date: Mon, 12 May 2025 14:12:05 +0000 Subject: [PATCH] feat(handler): add MostraGuarda --- src/handler/MostraGuarda.test.ts | 48 ++ src/handler/MostraGuarda.ts | 41 ++ src/handler/index.ts | 1 + src/index.ts | 3 +- .../https:dropload.ioxsr90y2ltdyx.html | 502 ++++++++++++++++++ .../https:mostraguarda.streammoviett12345678 | 1 + .../https:mostraguarda.streammoviett29141112 | 109 ++++ .../Fetcher/https:supervideo.cc6vri8jyhla3n | 401 ++++++++++++++ 8 files changed, 1105 insertions(+), 1 deletion(-) create mode 100644 src/handler/MostraGuarda.test.ts create mode 100644 src/handler/MostraGuarda.ts create mode 100644 src/utils/__fixtures__/Fetcher/https:dropload.ioxsr90y2ltdyx.html create mode 100644 src/utils/__fixtures__/Fetcher/https:mostraguarda.streammoviett12345678 create mode 100644 src/utils/__fixtures__/Fetcher/https:mostraguarda.streammoviett29141112 create mode 100644 src/utils/__fixtures__/Fetcher/https:supervideo.cc6vri8jyhla3n diff --git a/src/handler/MostraGuarda.test.ts b/src/handler/MostraGuarda.test.ts new file mode 100644 index 0000000..3d1a95a --- /dev/null +++ b/src/handler/MostraGuarda.test.ts @@ -0,0 +1,48 @@ +import { MostraGuarda } from './MostraGuarda'; +import { Fetcher } from '../utils'; +import { Dropload, EmbedExtractors, SuperVideo } from '../embed-extractor'; +import { Context } from '../types'; +jest.mock('../utils/Fetcher'); + +// @ts-expect-error No constructor args needed +const fetcher = new Fetcher(); +const mostraguarda = new MostraGuarda(fetcher, new EmbedExtractors([new Dropload(fetcher), new SuperVideo(fetcher)])); +const ctx: Context = { ip: '127.0.0.1' }; + +describe('FrenchCloud', () => { + test('does not handle non imdb movies', async () => { + const streams = await mostraguarda.handle(ctx, 'kitsu:123'); + + expect(streams).toHaveLength(0); + }); + + test('handles non-existent movies gracefully', async () => { + const streams = await mostraguarda.handle(ctx, 'tt12345678'); + + expect(streams).toHaveLength(0); + }); + + test('handle imdb the devil\'s bath', async () => { + const streams = await mostraguarda.handle(ctx, 'tt29141112'); + + expect(streams).toHaveLength(2); + expect(streams[0]).toStrictEqual({ + url: expect.any(URL), + label: 'SuperVideo', + sourceId: 'supervideo', + height: 720, + bytes: 1181116006, + language: 'it', + }); + expect(streams[0]?.url.href).toMatch(/^https:\/\/.*?.m3u8/); + expect(streams[1]).toStrictEqual({ + url: expect.any(URL), + label: 'Dropload', + sourceId: 'dropload', + height: 720, + bytes: 1181116006, + language: 'it', + }); + expect(streams[1]?.url.href).toMatch(/^https:\/\/.*?.m3u8/); + }); +}); diff --git a/src/handler/MostraGuarda.ts b/src/handler/MostraGuarda.ts new file mode 100644 index 0000000..e2f6017 --- /dev/null +++ b/src/handler/MostraGuarda.ts @@ -0,0 +1,41 @@ +import * as cheerio from 'cheerio'; +import { Handler } from './types'; +import { Fetcher, parseImdbId } from '../utils'; +import { EmbedExtractors } from '../embed-extractor'; +import { Context } from '../types'; + +export class MostraGuarda implements Handler { + readonly id = 'mostraguarda'; + + readonly label = 'MostraGuarda'; + + readonly contentTypes = ['movie']; + + readonly languages = ['it']; + + private readonly fetcher: Fetcher; + private readonly embedExtractors: EmbedExtractors; + + constructor(fetcher: Fetcher, embedExtractors: EmbedExtractors) { + this.fetcher = fetcher; + this.embedExtractors = embedExtractors; + } + + readonly handle = async (ctx: Context, id: string) => { + if (!id.startsWith('tt')) { + return []; + } + + const html = await this.fetcher.text(ctx, new URL(`https://mostraguarda.stream/movie/${parseImdbId(id).id}`)); + + const $ = cheerio.load(html); + + return Promise.all( + $('[data-link!=""]') + .map((_i, el) => new URL(($(el).attr('data-link') as string).replace(/^(https:)?\/\//, 'https://'))) + .toArray() + .filter(embedUrl => embedUrl.host.match(/(dropload|supervideo)/)) + .map(embedUrl => this.embedExtractors.handle(ctx, embedUrl, 'it')), + ); + }; +} diff --git a/src/handler/index.ts b/src/handler/index.ts index 192f38f..0176e9a 100644 --- a/src/handler/index.ts +++ b/src/handler/index.ts @@ -1,4 +1,5 @@ export * from './FrenchCloud'; export * from './KinoKiste'; export * from './MeineCloud'; +export * from './MostraGuarda'; export * from './types'; diff --git a/src/index.ts b/src/index.ts index b856c7e..e7ffdca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ import makeFetchHappen from 'make-fetch-happen'; import { flag } from 'country-emoji'; import winston from 'winston'; import { landingTemplate } from './landingTemplate'; -import { FrenchCloud, Handler, KinoKiste, MeineCloud } from './handler'; +import { FrenchCloud, Handler, KinoKiste, MeineCloud, MostraGuarda } from './handler'; import { Dropload, EmbedExtractors, SuperVideo } from './embed-extractor'; import { buildManifest, Fetcher } from './utils'; import { Config, UrlResult } from './types'; @@ -43,6 +43,7 @@ const handlers: Handler[] = [ new FrenchCloud(fetcher, embedExtractors), new KinoKiste(fetcher, embedExtractors), new MeineCloud(fetcher, embedExtractors), + new MostraGuarda(fetcher, embedExtractors), ]; addon.use((_req: Request, res: Response, next: NextFunction) => { diff --git a/src/utils/__fixtures__/Fetcher/https:dropload.ioxsr90y2ltdyx.html b/src/utils/__fixtures__/Fetcher/https:dropload.ioxsr90y2ltdyx.html new file mode 100644 index 0000000..e2dec65 --- /dev/null +++ b/src/utils/__fixtures__/Fetcher/https:dropload.ioxsr90y2ltdyx.html @@ -0,0 +1,502 @@ + + + +
+ +
+
+
+