diff --git a/src/extractor/VidSrc.test.ts b/src/extractor/VidSrc.test.ts index 6160f5a..ae4f89e 100644 --- a/src/extractor/VidSrc.test.ts +++ b/src/extractor/VidSrc.test.ts @@ -6,21 +6,17 @@ 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`), ['xyz'])]); +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.xyz/embed/movie/tt0093058'))).toMatchSnapshot(); + 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.xyz/embed/tv/tt2085059/4/2'))).toMatchSnapshot(); - }); - - test('not found', async () => { - expect(await extractorRegistry.handle(ctx, new URL('https://vidsrc.xyz/embed/movie/tt35628853'))).toMatchSnapshot(); + 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 () => { @@ -28,15 +24,15 @@ describe('VidSrc', () => { mockAgent.disableNetConnect(); setGlobalDispatcher(mockAgent); - mockAgent.get('https://vidsrc.xyz') - .intercept({ path: '/embed/movie/tt33043892/1/1' }).reply(429); - mockAgent.get('https://vidsrc.net') - .intercept({ path: '/embed/movie/tt33043892/1/1' }).reply(429); + 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, ['net', 'xyz']); + const vidSrc = new VidSrc(fetcher, ['vidsrc-embed.ru', 'vidsrc-embed.su']); - expect(await vidSrc.extract(ctx, new URL('https://vidsrc.xyz/embed/movie/tt33043892/1/1'), {})).toMatchSnapshot(); + 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 () => { @@ -44,14 +40,14 @@ describe('VidSrc', () => { mockAgent.disableNetConnect(); setGlobalDispatcher(mockAgent); - mockAgent.get('https://vidsrc.xyz') - .intercept({ path: '/embed/movie/tt33043892/1/1' }).reply(403); - mockAgent.get('https://vidsrc.net') - .intercept({ path: '/embed/movie/tt33043892/1/1' }).reply(403); + 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, ['net', 'xyz']); + const vidSrc = new VidSrc(fetcher, ['vidsrc-embed.ru', 'vidsrc-embed.su']); - expect(await vidSrc.extract(ctx, new URL('https://vidsrc.xyz/embed/movie/tt33043892/1/1'), {})).toMatchSnapshot(); + 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 index 3a7809f..b334cc6 100644 --- a/src/extractor/VidSrc.ts +++ b/src/extractor/VidSrc.ts @@ -1,6 +1,6 @@ import * as cheerio from 'cheerio'; import slugify from 'slugify'; -import { BlockedError, NotFoundError, TooManyRequestsError } from '../error'; +import { BlockedError, TooManyRequestsError } from '../error'; import { Context, Format, Meta, NonEmptyArray, UrlResult } from '../types'; import { Fetcher, guessHeightFromPlaylist } from '../utils'; import { Extractor } from './Extractor'; @@ -12,16 +12,16 @@ export class VidSrc extends Extractor { public override readonly ttl: number = 10800000; // 3h - private readonly tlds: NonEmptyArray; + private readonly domains: NonEmptyArray; - public constructor(fetcher: Fetcher, tlds: NonEmptyArray) { + public constructor(fetcher: Fetcher, domains: NonEmptyArray) { super(fetcher); - this.tlds = tlds; + this.domains = domains; } public supports(_ctx: Context, url: URL): boolean { - return null !== url.host.match(/vidsrc/); + return null !== url.host.match(/vidsrc|vsrc/); } protected async extractInternal(ctx: Context, url: URL, meta: Meta): Promise { @@ -29,24 +29,22 @@ export class VidSrc extends Extractor { 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.extractUsingRandomTld(newCtx, url, meta, [...this.tlds]); + return this.extractUsingRandomDomain(newCtx, url, meta, [...this.domains]); }; - private async extractUsingRandomTld(ctx: Context, url: URL, meta: Meta, tlds: string[]): Promise { - const tldIndex = Math.floor(Math.random() * tlds.length); - const [tld] = tlds.splice(tldIndex, 1) as [string]; + 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); - const hostnameParts = newUrl.hostname.split('.'); - hostnameParts[hostnameParts.length - 1] = tld; - newUrl.hostname = hostnameParts.join('.'); + newUrl.hostname = domain; let html: string; try { html = await this.fetcher.text(ctx, newUrl, { queueLimit: 1 }); } catch (error) { - if (tlds.length && (error instanceof TooManyRequestsError || error instanceof BlockedError)) { - return this.extractUsingRandomTld(ctx, url, meta, tlds); + if (domains.length && (error instanceof TooManyRequestsError || error instanceof BlockedError)) { + return this.extractUsingRandomDomain(ctx, url, meta, domains); } throw error; @@ -68,11 +66,7 @@ export class VidSrc extends Extractor { 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?'(.*)'`); - if (!fileMatch) { - throw new NotFoundError(); - } - + const fileMatch = playerHtml.match(`file:\\s?'(.*)'`) as string[]; const m3u8Url = new URL(fileMatch[1] as string); return { diff --git a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-af0f048b02d186cb1fe183043113e979 b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-23fa3ba27b6d5b90a29426cfe7184dff similarity index 63% rename from src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-af0f048b02d186cb1fe183043113e979 rename to src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-23fa3ba27b6d5b90a29426cfe7184dff index b630b2c..83cb473 100644 --- a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-af0f048b02d186cb1fe183043113e979 +++ b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-23fa3ba27b6d5b90a29426cfe7184dff @@ -364,13 +364,13 @@
- +

- 5-5 = + 9-3 =

- + @@ -400,6 +400,9 @@ + + + + diff --git a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-3a02f8d98afb2b2eaf85b732c4776e35 b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-489bc0657c3df774d35190617c130a81 similarity index 64% rename from src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-3a02f8d98afb2b2eaf85b732c4776e35 rename to src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-489bc0657c3df774d35190617c130a81 index f03b3dc..fb45f8f 100644 --- a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-3a02f8d98afb2b2eaf85b732c4776e35 +++ b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-489bc0657c3df774d35190617c130a81 @@ -37,7 +37,7 @@
-
+
Full Metal Jacket (1987)
@@ -50,11 +50,11 @@ - + + - - - - - - - - - - - - - - - diff --git a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-9eecc630b5a9d2845dbdce7f20cbf283 b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-d8f58aefe7113fae6e297ef61aed6c9d similarity index 65% rename from src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-9eecc630b5a9d2845dbdce7f20cbf283 rename to src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-d8f58aefe7113fae6e297ef61aed6c9d index 8ce6d89..318e5ab 100644 --- a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-9eecc630b5a9d2845dbdce7f20cbf283 +++ b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-d8f58aefe7113fae6e297ef61aed6c9d @@ -50,11 +50,11 @@ - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-22dfb6243754ee59b8e62cb0c06ac720 b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-f0043af0e38d98b18d5d3c30f91ee037 similarity index 63% rename from src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-22dfb6243754ee59b8e62cb0c06ac720 rename to src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-f0043af0e38d98b18d5d3c30f91ee037 index a2f1bb9..f4b91b6 100644 --- a/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-22dfb6243754ee59b8e62cb0c06ac720 +++ b/src/extractor/__fixtures__/VidSrc/https:cloudnestra.com-f0043af0e38d98b18d5d3c30f91ee037 @@ -364,13 +364,13 @@
- +

- 10-9 = + 9-4 =

- +
@@ -400,6 +400,9 @@ + + + + diff --git a/src/extractor/__fixtures__/VidSrc/https:tmstr4.shadowlandschronicles.com-a246b190099b237f66484f918b0fd94d b/src/extractor/__fixtures__/VidSrc/https:tmstr4.shadowlandschronicles.com-a246b190099b237f66484f918b0fd94d deleted file mode 100644 index cbfe0eb..0000000 --- a/src/extractor/__fixtures__/VidSrc/https:tmstr4.shadowlandschronicles.com-a246b190099b237f66484f918b0fd94d +++ /dev/null @@ -1,6 +0,0 @@ -#EXTM3U -#EXT-X-INDEPENDENT-SEGMENTS -#EXT-X-STREAM-INF:BANDWIDTH=926804,CODECS="mp4a.40.2,avc1.42c01e",RESOLUTION=640x358,FRAME-RATE=24,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE -/pl/H4sIAAAAAAAAAwXB7XqCIBgA0FtCsa_97IMcFSa.gPBPwc1H0Fm5Wl79zllVS4eRdZv10uJkuarrJF7Yr8at1lWyRvZDC7cFP3IT2YU4PHAmiGKB59C1Z41bbUQ7czDQ.AgpMv6csHtqNTFGzMMGessV_bOSvRkadab4riBhWx0nxuPxDtFnXMSjqAOdM5AtK3lyjjxiyD.LYAaRbqvC8_MF_L0Bsq8GeuGHxUlLU9rSZapvkSTyUfsNkcEJi8eb9jRpRPJkMTO6H4mV33cnaCqP_LeIpw46iVlHrxDp2c6G5ILtbeoC9I42itxy_3plqev50N5FLDHfTS94T1AQKXUZrmwOA1dtVIFFOaDNP7JZ1PhBAQAA/f2a0a2e3ac935bed168e40c6c28105d7/index.m3u8 -#EXT-X-STREAM-INF:BANDWIDTH=2987782,CODECS="mp4a.40.2,avc1.42c01f",RESOLUTION=1280x714,FRAME-RATE=24,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE -/pl/H4sIAAAAAAAAAwXB7XqCIBgA0FtCsa_97IMcFSa.gPBPwc1H0Fm5Wl79zllVS4eRdZv10uJkuarrJF7Yr8at1lWyRvZDC7cFP3IT2YU4PHAmiGKB59C1Z41bbUQ7czDQ.AgpMv6csHtqNTFGzMMGessV_bOSvRkadab4riBhWx0nxuPxDtFnXMSjqAOdM5AtK3lyjjxiyD.LYAaRbqvC8_MF_L0Bsq8GeuGHxUlLU9rSZapvkSTyUfsNkcEJi8eb9jRpRPJkMTO6H4mV33cnaCqP_LeIpw46iVlHrxDp2c6G5ILtbeoC9I42itxy_3plqev50N5FLDHfTS94T1AQKXUZrmwOA1dtVIFFOaDNP7JZ1PhBAQAA/ea18a1816b821e1ba4ee5d4a76b0b7cf/index.m3u8 \ No newline at end of file diff --git a/src/extractor/__fixtures__/VidSrc/https:tmstr4.shadowlandschronicles.com-eed0f5e12e5e78051f1a0732e71d27cb b/src/extractor/__fixtures__/VidSrc/https:tmstr4.shadowlandschronicles.com-eed0f5e12e5e78051f1a0732e71d27cb new file mode 100644 index 0000000..c0fbc5c --- /dev/null +++ b/src/extractor/__fixtures__/VidSrc/https:tmstr4.shadowlandschronicles.com-eed0f5e12e5e78051f1a0732e71d27cb @@ -0,0 +1,6 @@ +#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-6e26dd536959398a2f6ade766182ee4a b/src/extractor/__fixtures__/VidSrc/https:tmstr5.shadowlandschronicles.com-6e26dd536959398a2f6ade766182ee4a deleted file mode 100644 index 56122d5..0000000 --- a/src/extractor/__fixtures__/VidSrc/https:tmstr5.shadowlandschronicles.com-6e26dd536959398a2f6ade766182ee4a +++ /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/H4sIAAAAAAAAAxXK226DIAAA0F8CrGvd27oCq1UcyP1NQdtUaozptsyvX3aez9DBQxgjgBmAPeqK_Yh2eTeG4tAPMCDwysHNaeDbevKVMM.XgMWps2XtTWGkLR8M.feQ2KroeeXG_db4vCq82.T8lkerZ0OTlLLsWuA2lnwT1FK7e6r0B5nEHL_4pNAgme2sJj28_kT0f0kuya0Sj6W6wONRnkrpAHP9vZwEzRE3T8JOohmwtwMlTimNeiw2BQWRsM4CKZ3PFuUyT1usLy6LWb3F1s3p0hPRSpqqxibcPpaG3.Mq5qS4vn4bqm.NTp8KFzOfmBykWP4AirgCPSEBAAA-/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/H4sIAAAAAAAAAxXK226DIAAA0F8CrGvd27oCq1UcyP1NQdtUaozptsyvX3aez9DBQxgjgBmAPeqK_Yh2eTeG4tAPMCDwysHNaeDbevKVMM.XgMWps2XtTWGkLR8M.feQ2KroeeXG_db4vCq82.T8lkerZ0OTlLLsWuA2lnwT1FK7e6r0B5nEHL_4pNAgme2sJj28_kT0f0kuya0Sj6W6wONRnkrpAHP9vZwEzRE3T8JOohmwtwMlTimNeiw2BQWRsM4CKZ3PFuUyT1usLy6LWb3F1s3p0hPRSpqqxibcPpaG3.Mq5qS4vn4bqm.NTp8KFzOfmBykWP4AirgCPSEBAAA-/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/H4sIAAAAAAAAAxXK226DIAAA0F8CrGvd27oCq1UcyP1NQdtUaozptsyvX3aez9DBQxgjgBmAPeqK_Yh2eTeG4tAPMCDwysHNaeDbevKVMM.XgMWps2XtTWGkLR8M.feQ2KroeeXG_db4vCq82.T8lkerZ0OTlLLsWuA2lnwT1FK7e6r0B5nEHL_4pNAgme2sJj28_kT0f0kuya0Sj6W6wONRnkrpAHP9vZwEzRE3T8JOohmwtwMlTimNeiw2BQWRsM4CKZ3PFuUyT1usLy6LWb3F1s3p0hPRSpqqxibcPpaG3.Mq5qS4vn4bqm.NTp8KFzOfmBykWP4AirgCPSEBAAA-/f4afc016a800ba375016f4bc9771890f/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 new file mode 100644 index 0000000..6283ee2 --- /dev/null +++ b/src/extractor/__fixtures__/VidSrc/https:tmstr5.shadowlandschronicles.com-cb58f88ae1bb7496b6ab3364862ddefc @@ -0,0 +1,8 @@ +#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.xyzembedmoviett0093058 b/src/extractor/__fixtures__/VidSrc/https:vidsrc-embed.ruembedmoviett0093058 similarity index 54% rename from src/extractor/__fixtures__/VidSrc/https:vidsrc.xyzembedmoviett0093058 rename to src/extractor/__fixtures__/VidSrc/https:vidsrc-embed.ruembedmoviett0093058 index 690c55b..6d816a9 100644 --- a/src/extractor/__fixtures__/VidSrc/https:vidsrc.xyzembedmoviett0093058 +++ b/src/extractor/__fixtures__/VidSrc/https:vidsrc-embed.ruembedmoviett0093058 @@ -4,6 +4,7 @@ Full Metal Jacket (1987) + - - - - -
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - diff --git a/src/extractor/__snapshots__/VidSrc.test.ts.snap b/src/extractor/__snapshots__/VidSrc.test.ts.snap index 754784f..d3d4abf 100644 --- a/src/extractor/__snapshots__/VidSrc.test.ts.snap +++ b/src/extractor/__snapshots__/VidSrc.test.ts.snap @@ -12,7 +12,7 @@ exports[`VidSrc Black Mirror 1`] = ` }, "sourceId": "vidsrc_CloudStream-Pro_", "ttl": 10800000, - "url": "https://tmstr5.shadowlandschronicles.com/pl/H4sIAAAAAAAAAxXK226DIAAA0F8CrGvd27oCq1UcyP1NQdtUaozptsyvX3aez9DBQxgjgBmAPeqK_Yh2eTeG4tAPMCDwysHNaeDbevKVMM.XgMWps2XtTWGkLR8M.feQ2KroeeXG_db4vCq82.T8lkerZ0OTlLLsWuA2lnwT1FK7e6r0B5nEHL_4pNAgme2sJj28_kT0f0kuya0Sj6W6wONRnkrpAHP9vZwEzRE3T8JOohmwtwMlTimNeiw2BQWRsM4CKZ3PFuUyT1usLy6LWb3F1s3p0hPRSpqqxibcPpaG3.Mq5qS4vn4bqm.NTp8KFzOfmBykWP4AirgCPSEBAAA-/master.m3u8", + "url": "https://tmstr5.shadowlandschronicles.com/pl/H4sIAAAAAAAAAw3N3W6DIBgA0FcC_JndpZ1oY8UK8qHcobh0ymxNFqs._Xp_kmOGD594Q2BCPxrQd9SZKDCnsPeR7bwoCD.7w155E3_VoOuSMla7.w5TgSVCa_2rkUq2R6kegQAm5MxI77Gf9rigXumZyfsZkOOAKe9S7OUeK3XiwBz9JjPr9PS3Csd4kXJlCWtzsq35.4P02bTj5QAAY.f4dkUQvF3Bas0MSfYS4kWq19aN0yZci4ZGvoaM3jp5qorMltUEuB9bIqjVGi67oUzA4R587LFo3MLV0wB1WCUTEUjuZuQU0Da1ki4mfZ5zdOIV5rHANv0Hv0Y7NiEBAAA-/master.m3u8", }, ] `; @@ -29,7 +29,7 @@ exports[`VidSrc Full Metal Jacket 1`] = ` }, "sourceId": "vidsrc_CloudStream-Pro_", "ttl": 10800000, - "url": "https://tmstr4.shadowlandschronicles.com/pl/H4sIAAAAAAAAAwXB7XqCIBgA0FtCsa_97IMcFSa.gPBPwc1H0Fm5Wl79zllVS4eRdZv10uJkuarrJF7Yr8at1lWyRvZDC7cFP3IT2YU4PHAmiGKB59C1Z41bbUQ7czDQ.AgpMv6csHtqNTFGzMMGessV_bOSvRkadab4riBhWx0nxuPxDtFnXMSjqAOdM5AtK3lyjjxiyD.LYAaRbqvC8_MF_L0Bsq8GeuGHxUlLU9rSZapvkSTyUfsNkcEJi8eb9jRpRPJkMTO6H4mV33cnaCqP_LeIpw46iVlHrxDp2c6G5ILtbeoC9I42itxy_3plqev50N5FLDHfTS94T1AQKXUZrmwOA1dtVIFFOaDNP7JZ1PhBAQAA/master.m3u8", + "url": "https://tmstr4.shadowlandschronicles.com/pl/H4sIAAAAAAAAAw3Oy3KCMBhA4VcKBqh2p0UumRJKSP4Iu1ywkYDDUKuVp6_bs_jmWBVtg.3ZvMUoDqLAxOps.jDCsVHIbPrdu5FuqQQ5UGS_dELbZh3vegVfivna5I7wqcv6nJEuYKzGaUmn71Ajv1qAR4NSX51YLjOWdN6qXsKxOxWou76cqbzzy.63Pu2fkJCjSI64kuViE3fRGZl1OjvmU8cxYOPtR7u5PYDbVg0uEANU0rPLJyofYmBcJPu_Buif5OBoOi8tBsowKRhmaSPRUw2v7n9WO76uspno3Ec8LxYeHA5dAKGU3RM2YaibGzbZ7MqxCJVkmZJutdc6qhGROgNZrqnQIxsttgVMdBEc7f4BOJFmy0EBAAA-/master.m3u8", }, ] `; @@ -43,13 +43,11 @@ exports[`VidSrc blocking issues are retried and fail if no tlds are left 1`] = ` "label": "VidSrc", "meta": {}, "sourceId": "vidsrc", - "url": "https://vidsrc.xyz/embed/movie/tt33043892/1/1", + "url": "https://vidsrc-embed.ru/embed/movie/fake2", }, ] `; -exports[`VidSrc not found 1`] = `[]`; - exports[`VidSrc rate limit issues are retried and fail if no tlds are left 1`] = ` [ { @@ -59,7 +57,7 @@ exports[`VidSrc rate limit issues are retried and fail if no tlds are left 1`] = "label": "VidSrc", "meta": {}, "sourceId": "vidsrc", - "url": "https://vidsrc.xyz/embed/movie/tt33043892/1/1", + "url": "https://vidsrc-embed.ru/embed/movie/fake1", }, ] `; diff --git a/src/extractor/index.ts b/src/extractor/index.ts index 502f1e5..36c6357 100644 --- a/src/extractor/index.ts +++ b/src/extractor/index.ts @@ -42,17 +42,13 @@ export const createExtractors = (fetcher: Fetcher): Extractor[] => { new SuperVideo(fetcher), new Uqload(fetcher), new VidSrc(fetcher, [ // https://vidsrc.domains/ - 'bz', - 'do', - 'gd', - 'in', - 'io', - // 'me', // redirects to .net - 'mn', - 'net', - 'tw', - // 'vc', // 500 internal server error - 'xyz', + 'vidsrcme.ru', + 'vidsrcme.su', + 'vidsrc-me.ru', + 'vidsrc-me.su', + 'vidsrc-embed.ru', + 'vidsrc-embed.su', + 'vsrc.su', ]), new VixSrc(fetcher), new Voe(fetcher), diff --git a/src/source/VidSrc.test.ts b/src/source/VidSrc.test.ts index ab04f34..a3440c0 100644 --- a/src/source/VidSrc.test.ts +++ b/src/source/VidSrc.test.ts @@ -1,5 +1,5 @@ import { createTestContext } from '../test'; -import { FetcherMock, ImdbId } from '../utils'; +import { ImdbId } from '../utils'; import { VidSrc } from './VidSrc'; const ctx = createTestContext(); @@ -8,7 +8,7 @@ describe('VidSrc', () => { let source: VidSrc; beforeEach(() => { - source = new VidSrc(new FetcherMock('/dev/null')); + source = new VidSrc(); }); test('handle imdb black mirror s4e2', async () => { diff --git a/src/source/VidSrc.ts b/src/source/VidSrc.ts index 0d9b4b5..a777901 100644 --- a/src/source/VidSrc.ts +++ b/src/source/VidSrc.ts @@ -1,6 +1,6 @@ import { ContentType } from 'stremio-addon-sdk'; import { Context, CountryCode } from '../types'; -import { Fetcher, getImdbId, Id } from '../utils'; +import { Id } from '../utils'; import { Source, SourceResult } from './Source'; export class VidSrc extends Source { @@ -12,22 +12,12 @@ export class VidSrc extends Source { public readonly countryCodes: CountryCode[] = [CountryCode.en]; - public readonly baseUrl = 'https://vidsrc.xyz'; + public readonly baseUrl = 'https://vidsrc-embed.ru'; - private readonly fetcher: Fetcher; - - public constructor(fetcher: Fetcher) { - super(); - - this.fetcher = fetcher; - } - - public async handleInternal(ctx: Context, _type: string, id: Id): Promise { - const imdbId = await getImdbId(ctx, this.fetcher, id); - - const url = imdbId.season - ? new URL(`/embed/tv/${imdbId.id}/${imdbId.season}/${imdbId.episode}`, this.baseUrl) - : new URL(`/embed/movie/${imdbId.id}`, this.baseUrl); + public async handleInternal(_ctx: Context, _type: string, id: Id): Promise { + const url = id.season + ? new URL(`/embed/tv/${id.id}/${id.season}-${id.episode}`, this.baseUrl) + : new URL(`/embed/movie/${id.id}`, this.baseUrl); return [{ url, meta: { countryCodes: [CountryCode.en] } }]; }; diff --git a/src/source/__snapshots__/VidSrc.test.ts.snap b/src/source/__snapshots__/VidSrc.test.ts.snap index 5f2432b..0dbd2a9 100644 --- a/src/source/__snapshots__/VidSrc.test.ts.snap +++ b/src/source/__snapshots__/VidSrc.test.ts.snap @@ -8,7 +8,7 @@ exports[`VidSrc handle imdb black mirror s4e2 1`] = ` "en", ], }, - "url": "https://vidsrc.xyz/embed/tv/tt2085059/4/2", + "url": "https://vidsrc-embed.ru/embed/tv/tt2085059/4-2", }, ] `; @@ -21,7 +21,7 @@ exports[`VidSrc handle imdb full metal jacket 1`] = ` "en", ], }, - "url": "https://vidsrc.xyz/embed/movie/tt0093058", + "url": "https://vidsrc-embed.ru/embed/movie/tt0093058", }, ] `; diff --git a/src/source/index.ts b/src/source/index.ts index b445314..cd142f9 100644 --- a/src/source/index.ts +++ b/src/source/index.ts @@ -31,7 +31,7 @@ export const createSources = (fetcher: Fetcher): Source[] => { // AL new Kokoshka(fetcher), // EN - new VidSrc(fetcher), + new VidSrc(), // ES / MX new CineHDPlus(fetcher), new Cuevana(fetcher),