diff --git a/src/extractor/VidSrc.test.ts b/src/extractor/VidSrc.test.ts deleted file mode 100644 index ae4f89e..0000000 --- a/src/extractor/VidSrc.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { MockAgent, setGlobalDispatcher } from 'undici'; -import winston from 'winston'; -import { createTestContext } from '../test'; -import { Fetcher, FetcherMock } from '../utils'; -import { ExtractorRegistry } from './ExtractorRegistry'; -import { VidSrc } from './VidSrc'; - -const logger = winston.createLogger({ transports: [new winston.transports.Console({ level: 'nope' })] }); -const extractorRegistry = new ExtractorRegistry(logger, [new VidSrc(new FetcherMock(`${__dirname}/__fixtures__/VidSrc`), ['vidsrc-embed.ru'])]); - -const ctx = createTestContext(); - -describe('VidSrc', () => { - test('Full Metal Jacket', async () => { - expect(await extractorRegistry.handle(ctx, new URL('https://vidsrc-embed.ru/embed/movie/tt0093058'))).toMatchSnapshot(); - }); - - test('Black Mirror', async () => { - expect(await extractorRegistry.handle(ctx, new URL('https://vidsrc-embed.ru/embed/tv/tt2085059/4-2'))).toMatchSnapshot(); - }); - - test('rate limit issues are retried and fail if no tlds are left', async () => { - const mockAgent = new MockAgent({ enableCallHistory: true }); - mockAgent.disableNetConnect(); - setGlobalDispatcher(mockAgent); - - mockAgent.get('https://vidsrc-embed.ru') - .intercept({ path: '/embed/movie/fake1' }).reply(429); - mockAgent.get('https://vidsrc-embed.su') - .intercept({ path: '/embed/movie/fake1' }).reply(429); - - const fetcher = new Fetcher(winston.createLogger({ transports: [new winston.transports.Console({ level: 'nope' })] })); - const vidSrc = new VidSrc(fetcher, ['vidsrc-embed.ru', 'vidsrc-embed.su']); - - expect(await vidSrc.extract(ctx, new URL('https://vidsrc-embed.ru/embed/movie/fake1'), {})).toMatchSnapshot(); - }); - - test('blocking issues are retried and fail if no tlds are left', async () => { - const mockAgent = new MockAgent({ enableCallHistory: true }); - mockAgent.disableNetConnect(); - setGlobalDispatcher(mockAgent); - - mockAgent.get('https://vidsrc-embed.ru') - .intercept({ path: '/embed/movie/fake2' }).reply(403); - mockAgent.get('https://vidsrc-embed.su') - .intercept({ path: '/embed/movie/fake2' }).reply(403); - - const fetcher = new Fetcher(winston.createLogger({ transports: [new winston.transports.Console({ level: 'nope' })] })); - const vidSrc = new VidSrc(fetcher, ['vidsrc-embed.ru', 'vidsrc-embed.su']); - - expect(await vidSrc.extract(ctx, new URL('https://vidsrc-embed.ru/embed/movie/fake2'), {})).toMatchSnapshot(); - }); -}); diff --git a/src/extractor/VidSrc.ts b/src/extractor/VidSrc.ts deleted file mode 100644 index c6a7258..0000000 --- a/src/extractor/VidSrc.ts +++ /dev/null @@ -1,87 +0,0 @@ -import * as cheerio from 'cheerio'; -import slugify from 'slugify'; -import { BlockedError, TooManyRequestsError } from '../error'; -import { Context, Format, Meta, NonEmptyArray, UrlResult } from '../types'; -import { Fetcher, guessHeightFromPlaylist } from '../utils'; -import { Extractor } from './Extractor'; - -export class VidSrc extends Extractor { - public readonly id = 'vidsrc'; - - public readonly label = 'VidSrc'; - - public override readonly ttl: number = 10800000; // 3h - - private readonly domains: NonEmptyArray; - - public constructor(fetcher: Fetcher, domains: NonEmptyArray) { - super(fetcher); - - this.domains = domains; - } - - public supports(_ctx: Context, url: URL): boolean { - return null !== url.host.match(/vidsrc|vsrc/); - } - - protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { - // While this is a crappy thing to do, they seem to be blocking overly strict IMO - const randomIp = `${Math.floor(Math.random() * 223) + 1}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}.${Math.floor(Math.random() * 256)}`; - const newCtx = { ...ctx, ip: randomIp }; - - return this.extractUsingRandomDomain(newCtx, url, meta, [...this.domains]); - }; - - private async extractUsingRandomDomain(ctx: Context, url: URL, meta: Meta, domains: string[]): Promise { - const domainIndex = Math.floor(Math.random() * domains.length); - const [domain] = domains.splice(domainIndex, 1) as [string]; - - const newUrl = new URL(url); - newUrl.hostname = domain; - - let html: string; - try { - html = await this.fetcher.text(ctx, newUrl, { queueLimit: 1 }); - } catch (error) { - if (domains.length && (error instanceof TooManyRequestsError || error instanceof BlockedError)) { - return this.extractUsingRandomDomain(ctx, url, meta, domains); - } - - throw error; - } - - const $ = cheerio.load(html); - - const iframeUrl = new URL(($('#player_iframe').attr('src') as string).replace(/^\/\//, 'https://')); - const title = $('title').text().trim(); - - return Promise.all( - $('.server') - .map((_i, el) => ({ serverName: $(el).text(), dataHash: $(el).data('hash') })) - .toArray() - .filter(({ serverName }) => serverName === 'CloudStream Pro') - .map(async ({ serverName, dataHash }) => { - const rcpUrl = new URL(`/rcp/${dataHash}`, iframeUrl.origin); - const iframeHtml = await this.fetcher.text(ctx, rcpUrl, { headers: { Referer: newUrl.origin } }); - const srcMatch = iframeHtml.match(`src:\\s?'(.*)'`) as string[]; - - const playerHtml = await this.fetcher.text(ctx, new URL(srcMatch[1] as string, iframeUrl.origin), { headers: { Referer: rcpUrl.href } }); - const fileMatch = playerHtml.match(`file:\\s?'(.*)'`) as string[]; - const m3u8Url = new URL(fileMatch[1] as string); - - return { - url: m3u8Url, - format: Format.hls, - label: serverName, - sourceId: `${this.id}_${slugify(serverName)}_${meta.countryCodes?.join('_')}`, - ttl: this.ttl, - meta: { - ...meta, - height: await guessHeightFromPlaylist(ctx, this.fetcher, m3u8Url, url, { headers: { Referer: iframeUrl.href } }), - title, - }, - }; - }), - ); - } -} diff --git a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-23fa3ba27b6d5b90a29426cfe7184dff b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-23fa3ba27b6d5b90a29426cfe7184dff deleted file mode 100644 index 83cb473..0000000 --- a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-23fa3ba27b6d5b90a29426cfe7184dff +++ /dev/null @@ -1,751 +0,0 @@ - - - -Black Mirror (2011) S04E02 - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-489bc0657c3df774d35190617c130a81 b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-489bc0657c3df774d35190617c130a81 deleted file mode 100644 index fb45f8f..0000000 --- a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-489bc0657c3df774d35190617c130a81 +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - - - - - - - -
-
-
- Full Metal Jacket (1987)
- -
-
- -
- - - - - - - - - - - - - - - - - - diff --git a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-d8f58aefe7113fae6e297ef61aed6c9d b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-d8f58aefe7113fae6e297ef61aed6c9d deleted file mode 100644 index 318e5ab..0000000 --- a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-d8f58aefe7113fae6e297ef61aed6c9d +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - - - - - - - -
-
-
- Black Mirror (2011) S04E02
- -
-
- -
- - - - - - - - - - - - - - - - - - diff --git a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-f0043af0e38d98b18d5d3c30f91ee037 b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-f0043af0e38d98b18d5d3c30f91ee037 deleted file mode 100644 index f4b91b6..0000000 --- a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-f0043af0e38d98b18d5d3c30f91ee037 +++ /dev/null @@ -1,751 +0,0 @@ - - - -Full Metal Jacket (1987) - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/extractor/__fixtures__/VidSrc/https:tmstr4.shadowlandschronicles.com-eed0f5e12e5e78051f1a0732e71d27cb b/src/extractor/__fixtures__/VidSrc/https:tmstr4.shadowlandschronicles.com-eed0f5e12e5e78051f1a0732e71d27cb deleted file mode 100644 index c0fbc5c..0000000 --- a/src/extractor/__fixtures__/VidSrc/https:tmstr4.shadowlandschronicles.com-eed0f5e12e5e78051f1a0732e71d27cb +++ /dev/null @@ -1,6 +0,0 @@ -#EXTM3U -#EXT-X-INDEPENDENT-SEGMENTS -#EXT-X-STREAM-INF:BANDWIDTH=833322,CODECS="mp4a.40.2,avc1.42c01e",RESOLUTION=640x358,FRAME-RATE=24,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE -/pl/H4sIAAAAAAAAAw3Oy3KCMBhA4VcKBqh2p0UumRJKSP4Iu1ywkYDDUKuVp6_bs_jmWBVtg.3ZvMUoDqLAxOps.jDCsVHIbPrdu5FuqQQ5UGS_dELbZh3vegVfivna5I7wqcv6nJEuYKzGaUmn71Ajv1qAR4NSX51YLjOWdN6qXsKxOxWou76cqbzzy.63Pu2fkJCjSI64kuViE3fRGZl1OjvmU8cxYOPtR7u5PYDbVg0uEANU0rPLJyofYmBcJPu_Buif5OBoOi8tBsowKRhmaSPRUw2v7n9WO76uspno3Ec8LxYeHA5dAKGU3RM2YaibGzbZ7MqxCJVkmZJutdc6qhGROgNZrqnQIxsttgVMdBEc7f4BOJFmy0EBAAA-/f2a0a2e3ac935bed168e40c6c28105d7/index.m3u8 -#EXT-X-STREAM-INF:BANDWIDTH=2728709,CODECS="mp4a.40.2,avc1.64001f",RESOLUTION=1280x714,FRAME-RATE=24,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE -/pl/H4sIAAAAAAAAAw3Oy3KCMBhA4VcKBqh2p0UumRJKSP4Iu1ywkYDDUKuVp6_bs_jmWBVtg.3ZvMUoDqLAxOps.jDCsVHIbPrdu5FuqQQ5UGS_dELbZh3vegVfivna5I7wqcv6nJEuYKzGaUmn71Ajv1qAR4NSX51YLjOWdN6qXsKxOxWou76cqbzzy.63Pu2fkJCjSI64kuViE3fRGZl1OjvmU8cxYOPtR7u5PYDbVg0uEANU0rPLJyofYmBcJPu_Buif5OBoOi8tBsowKRhmaSPRUw2v7n9WO76uspno3Ec8LxYeHA5dAKGU3RM2YaibGzbZ7MqxCJVkmZJutdc6qhGROgNZrqnQIxsttgVMdBEc7f4BOJFmy0EBAAA-/ea18a1816b821e1ba4ee5d4a76b0b7cf/index.m3u8 \ No newline at end of file diff --git a/src/extractor/__fixtures__/VidSrc/https:tmstr5.shadowlandschronicles.com-cb58f88ae1bb7496b6ab3364862ddefc b/src/extractor/__fixtures__/VidSrc/https:tmstr5.shadowlandschronicles.com-cb58f88ae1bb7496b6ab3364862ddefc deleted file mode 100644 index 6283ee2..0000000 --- a/src/extractor/__fixtures__/VidSrc/https:tmstr5.shadowlandschronicles.com-cb58f88ae1bb7496b6ab3364862ddefc +++ /dev/null @@ -1,8 +0,0 @@ -#EXTM3U -#EXT-X-INDEPENDENT-SEGMENTS -#EXT-X-STREAM-INF:BANDWIDTH=884887,CODECS="mp4a.40.2,avc1.42c01e",RESOLUTION=640x346,FRAME-RATE=25,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE -/pl/H4sIAAAAAAAAAw3N3W6DIBgA0FcC_JndpZ1oY8UK8qHcobh0ymxNFqs._Xp_kmOGD594Q2BCPxrQd9SZKDCnsPeR7bwoCD.7w155E3_VoOuSMla7.w5TgSVCa_2rkUq2R6kegQAm5MxI77Gf9rigXumZyfsZkOOAKe9S7OUeK3XiwBz9JjPr9PS3Csd4kXJlCWtzsq35.4P02bTj5QAAY.f4dkUQvF3Bas0MSfYS4kWq19aN0yZci4ZGvoaM3jp5qorMltUEuB9bIqjVGi67oUzA4R587LFo3MLV0wB1WCUTEUjuZuQU0Da1ki4mfZ5zdOIV5rHANv0Hv0Y7NiEBAAA-/e2f2579229bebcfbb0eafde12cbc1bf9/index.m3u8 -#EXT-X-STREAM-INF:BANDWIDTH=2911865,CODECS="mp4a.40.2,avc1.42c01f",RESOLUTION=1280x694,FRAME-RATE=25,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE -/pl/H4sIAAAAAAAAAw3N3W6DIBgA0FcC_JndpZ1oY8UK8qHcobh0ymxNFqs._Xp_kmOGD594Q2BCPxrQd9SZKDCnsPeR7bwoCD.7w155E3_VoOuSMla7.w5TgSVCa_2rkUq2R6kegQAm5MxI77Gf9rigXumZyfsZkOOAKe9S7OUeK3XiwBz9JjPr9PS3Csd4kXJlCWtzsq35.4P02bTj5QAAY.f4dkUQvF3Bas0MSfYS4kWq19aN0yZci4ZGvoaM3jp5qorMltUEuB9bIqjVGi67oUzA4R587LFo3MLV0wB1WCUTEUjuZuQU0Da1ki4mfZ5zdOIV5rHANv0Hv0Y7NiEBAAA-/0e258eeccefba231686dc455bae2c1be/index.m3u8 -#EXT-X-STREAM-INF:BANDWIDTH=5301648,CODECS="mp4a.40.2,avc1.42c028",RESOLUTION=1920x1040,FRAME-RATE=25,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE -/pl/H4sIAAAAAAAAAw3N3W6DIBgA0FcC_JndpZ1oY8UK8qHcobh0ymxNFqs._Xp_kmOGD594Q2BCPxrQd9SZKDCnsPeR7bwoCD.7w155E3_VoOuSMla7.w5TgSVCa_2rkUq2R6kegQAm5MxI77Gf9rigXumZyfsZkOOAKe9S7OUeK3XiwBz9JjPr9PS3Csd4kXJlCWtzsq35.4P02bTj5QAAY.f4dkUQvF3Bas0MSfYS4kWq19aN0yZci4ZGvoaM3jp5qorMltUEuB9bIqjVGi67oUzA4R587LFo3MLV0wB1WCUTEUjuZuQU0Da1ki4mfZ5zdOIV5rHANv0Hv0Y7NiEBAAA-/f4afc016a800ba375016f4bc9771890f/index.m3u8 \ No newline at end of file diff --git a/src/extractor/__fixtures__/VidSrc/https:vidsrc-embed.ruembedmoviett0093058 b/src/extractor/__fixtures__/VidSrc/https:vidsrc-embed.ruembedmoviett0093058 deleted file mode 100644 index 6d816a9..0000000 --- a/src/extractor/__fixtures__/VidSrc/https:vidsrc-embed.ruembedmoviett0093058 +++ /dev/null @@ -1,276 +0,0 @@ - - - -Full Metal Jacket (1987) - - - - - - - - - - -
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - diff --git a/src/extractor/__fixtures__/VidSrc/https:vidsrc-embed.ruembedtvtt20850594-2 b/src/extractor/__fixtures__/VidSrc/https:vidsrc-embed.ruembedtvtt20850594-2 deleted file mode 100644 index 5997b4e..0000000 --- a/src/extractor/__fixtures__/VidSrc/https:vidsrc-embed.ruembedtvtt20850594-2 +++ /dev/null @@ -1,276 +0,0 @@ - - - -Black Mirror (2011) S04E02 - - - - - - - - - - -
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - diff --git a/src/extractor/__snapshots__/VidSrc.test.ts.snap b/src/extractor/__snapshots__/VidSrc.test.ts.snap deleted file mode 100644 index d3d4abf..0000000 --- a/src/extractor/__snapshots__/VidSrc.test.ts.snap +++ /dev/null @@ -1,63 +0,0 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing - -exports[`VidSrc Black Mirror 1`] = ` -[ - { - "format": "hls", - "label": "CloudStream Pro", - "meta": { - "countryCodes": [], - "height": 1040, - "title": "Black Mirror (2011) S04E02", - }, - "sourceId": "vidsrc_CloudStream-Pro_", - "ttl": 10800000, - "url": "https://tmstr5.shadowlandschronicles.com/pl/H4sIAAAAAAAAAw3N3W6DIBgA0FcC_JndpZ1oY8UK8qHcobh0ymxNFqs._Xp_kmOGD594Q2BCPxrQd9SZKDCnsPeR7bwoCD.7w155E3_VoOuSMla7.w5TgSVCa_2rkUq2R6kegQAm5MxI77Gf9rigXumZyfsZkOOAKe9S7OUeK3XiwBz9JjPr9PS3Csd4kXJlCWtzsq35.4P02bTj5QAAY.f4dkUQvF3Bas0MSfYS4kWq19aN0yZci4ZGvoaM3jp5qorMltUEuB9bIqjVGi67oUzA4R587LFo3MLV0wB1WCUTEUjuZuQU0Da1ki4mfZ5zdOIV5rHANv0Hv0Y7NiEBAAA-/master.m3u8", - }, -] -`; - -exports[`VidSrc Full Metal Jacket 1`] = ` -[ - { - "format": "hls", - "label": "CloudStream Pro", - "meta": { - "countryCodes": [], - "height": 714, - "title": "Full Metal Jacket (1987)", - }, - "sourceId": "vidsrc_CloudStream-Pro_", - "ttl": 10800000, - "url": "https://tmstr4.shadowlandschronicles.com/pl/H4sIAAAAAAAAAw3Oy3KCMBhA4VcKBqh2p0UumRJKSP4Iu1ywkYDDUKuVp6_bs_jmWBVtg.3ZvMUoDqLAxOps.jDCsVHIbPrdu5FuqQQ5UGS_dELbZh3vegVfivna5I7wqcv6nJEuYKzGaUmn71Ajv1qAR4NSX51YLjOWdN6qXsKxOxWou76cqbzzy.63Pu2fkJCjSI64kuViE3fRGZl1OjvmU8cxYOPtR7u5PYDbVg0uEANU0rPLJyofYmBcJPu_Buif5OBoOi8tBsowKRhmaSPRUw2v7n9WO76uspno3Ec8LxYeHA5dAKGU3RM2YaibGzbZ7MqxCJVkmZJutdc6qhGROgNZrqnQIxsttgVMdBEc7f4BOJFmy0EBAAA-/master.m3u8", - }, -] -`; - -exports[`VidSrc blocking issues are retried and fail if no tlds are left 1`] = ` -[ - { - "error": [Error], - "format": "unknown", - "isExternal": true, - "label": "VidSrc", - "meta": {}, - "sourceId": "vidsrc", - "url": "https://vidsrc-embed.ru/embed/movie/fake2", - }, -] -`; - -exports[`VidSrc rate limit issues are retried and fail if no tlds are left 1`] = ` -[ - { - "error": [Error], - "format": "unknown", - "isExternal": true, - "label": "VidSrc", - "meta": {}, - "sourceId": "vidsrc", - "url": "https://vidsrc-embed.ru/embed/movie/fake1", - }, -] -`; diff --git a/src/extractor/index.ts b/src/extractor/index.ts index 6ab5bdd..0e9bb29 100644 --- a/src/extractor/index.ts +++ b/src/extractor/index.ts @@ -16,7 +16,6 @@ import { Streamtape } from './Streamtape'; import { SuperVideo } from './SuperVideo'; import { Uqload } from './Uqload'; import { Vidora } from './Vidora'; -import { VidSrc } from './VidSrc'; import { VixSrc } from './VixSrc'; import { Voe } from './Voe'; import { YouTube } from './YouTube'; @@ -43,15 +42,6 @@ export const createExtractors = (fetcher: Fetcher): Extractor[] => { new SuperVideo(fetcher), new Uqload(fetcher), new Vidora(fetcher), - new VidSrc(fetcher, [ // https://vidsrc.domains/ - 'vidsrcme.ru', - 'vidsrcme.su', - 'vidsrc-me.ru', - 'vidsrc-me.su', - 'vidsrc-embed.ru', - 'vidsrc-embed.su', - 'vsrc.su', - ]), new VixSrc(fetcher), new Voe(fetcher), new YouTube(fetcher),