diff --git a/src/extractor/Streamtape.test.ts b/src/extractor/Streamtape.test.ts new file mode 100644 index 0000000..29b1969 --- /dev/null +++ b/src/extractor/Streamtape.test.ts @@ -0,0 +1,17 @@ +import winston from 'winston'; +import { FetcherMock } from '../utils'; +import { CountryCode } from '../types'; +import { ExtractorRegistry } from './ExtractorRegistry'; +import { Streamtape } from './Streamtape'; +import { createTestContext } from '../test'; + +const logger = winston.createLogger({ transports: [new winston.transports.Console({ level: 'nope' })] }); +const extractorRegistry = new ExtractorRegistry(logger, [new Streamtape(new FetcherMock(`${__dirname}/__fixtures__/Streamtape`))]); + +const ctx = createTestContext({ mediaFlowProxyUrl: 'https://mediaflow-proxy.test', mediaFlowProxyPassword: 'asdfg' }); + +describe('Streamtape', () => { + test('streamtape.com /e', async () => { + expect(await extractorRegistry.handle(ctx, new URL('https://streamtape.com/e/84Kb3mkoYAiokmW'), CountryCode.es)).toMatchSnapshot(); + }); +}); diff --git a/src/extractor/Streamtape.ts b/src/extractor/Streamtape.ts new file mode 100644 index 0000000..575457c --- /dev/null +++ b/src/extractor/Streamtape.ts @@ -0,0 +1,51 @@ +import * as cheerio from 'cheerio'; +import { Extractor } from './Extractor'; +import { + buildMediaFlowProxyExtractorRedirectUrl, + Fetcher, + guessHeightFromTitle, + supportsMediaFlowProxy, +} from '../utils'; +import { Context, CountryCode, Format, UrlResult } from '../types'; + +export class Streamtape extends Extractor { + public readonly id = 'streamtape'; + + public readonly label = 'Streamtape (via MediaFlow Proxy)'; + + public override readonly ttl = 0; + + private readonly fetcher: Fetcher; + + public constructor(fetcher: Fetcher) { + super(); + + this.fetcher = fetcher; + } + + public supports(ctx: Context, url: URL): boolean { + return null !== url.host.match(/streamtape/) && supportsMediaFlowProxy(ctx); + } + + protected async extractInternal(ctx: Context, url: URL, countryCode: CountryCode): Promise { + const html = await this.fetcher.text(ctx, url); + + const $ = cheerio.load(html); + const title = $('meta[name="og:title"]').attr('content') as string; + + return [ + { + url: buildMediaFlowProxyExtractorRedirectUrl(ctx, 'Streamtape', url), + format: Format.mp4, + label: this.label, + sourceId: `${this.id}_${countryCode}`, + ttl: this.ttl, + meta: { + countryCodes: [countryCode], + height: guessHeightFromTitle(title), + title, + }, + }, + ]; + }; +} diff --git a/src/extractor/__fixtures__/Streamtape/https:streamtape.come84Kb3mkoYAiokmW b/src/extractor/__fixtures__/Streamtape/https:streamtape.come84Kb3mkoYAiokmW new file mode 100644 index 0000000..4f9a09f --- /dev/null +++ b/src/extractor/__fixtures__/Streamtape/https:streamtape.come84Kb3mkoYAiokmW @@ -0,0 +1,261 @@ + + + + + Streamtape.com + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
ad
+ + + + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/extractor/__snapshots__/Streamtape.test.ts.snap b/src/extractor/__snapshots__/Streamtape.test.ts.snap new file mode 100644 index 0000000..8ef9280 --- /dev/null +++ b/src/extractor/__snapshots__/Streamtape.test.ts.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`Streamtape streamtape.com /e 1`] = ` +[ + { + "format": "mp4", + "label": "Streamtape (via MediaFlow Proxy)", + "meta": { + "countryCodes": [ + "es", + ], + "height": undefined, + "title": "mickey-17-2025-[latino].mp4", + }, + "sourceId": "streamtape_es", + "ttl": 0, + "url": "https://mediaflow-proxy.test/extractor/video?host=Streamtape&api_password=asdfg&d=https%3A%2F%2Fstreamtape.com%2Fe%2F84Kb3mkoYAiokmW&redirect_stream=true", + }, +] +`; diff --git a/src/extractor/index.ts b/src/extractor/index.ts index 8e806a9..ca9209b 100644 --- a/src/extractor/index.ts +++ b/src/extractor/index.ts @@ -10,6 +10,7 @@ import { SuperVideo } from './SuperVideo'; import { Uqload } from './Uqload'; import { VidSrc } from './VidSrc'; import { VixSrc } from './VixSrc'; +import { Streamtape } from './Streamtape'; export * from './Extractor'; export * from './ExtractorRegistry'; @@ -21,6 +22,7 @@ export const createExtractors = (fetcher: Fetcher): Extractor[] => [ new KinoGer(fetcher), new Mixdrop(fetcher), new Soaper(fetcher), + new Streamtape(fetcher), new Uqload(fetcher), new VidSrc(fetcher), new VixSrc(fetcher),