From c51ae7fa86b48ed88aae58d86cbfc213dd6d446e Mon Sep 17 00:00:00 2001 From: Pas <74743263+Pasithea0@users.noreply.github.com> Date: Sun, 23 Nov 2025 17:49:41 -0700 Subject: [PATCH] add supervideo embed --- src/providers/all.ts | 2 + src/providers/embeds/supervideo.ts | 85 ++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/providers/embeds/supervideo.ts diff --git a/src/providers/all.ts b/src/providers/all.ts index 87d6fb6..3cba6b5 100644 --- a/src/providers/all.ts +++ b/src/providers/all.ts @@ -42,6 +42,7 @@ import { streamwishLatinoScraper, streamwishSpanishScraper, } from './embeds/streamwish'; +import { supervideoScraper } from './embeds/supervideo'; import { vidCloudScraper } from './embeds/vidcloud'; import { vidhideEnglishScraper, vidhideLatinoScraper, vidhideSpanishScraper } from './embeds/vidhide'; import { vidifyEmbeds } from './embeds/vidify'; @@ -215,5 +216,6 @@ export function gatherAllEmbeds(): Array { vidhideEnglishScraper, filelionsScraper, droploadScraper, + supervideoScraper, ]; } diff --git a/src/providers/embeds/supervideo.ts b/src/providers/embeds/supervideo.ts new file mode 100644 index 0000000..4a749d5 --- /dev/null +++ b/src/providers/embeds/supervideo.ts @@ -0,0 +1,85 @@ +import { load } from 'cheerio'; +import { unpack } from 'unpacker'; + +import { flags } from '@/entrypoint/utils/targets'; +import { NotFoundError } from '@/utils/errors'; + +import { makeEmbed } from '../base'; + +function extractUrlFromPacked(html: string, patterns: RegExp[]): string { + const $ = load(html); + + // Find packed script + const packedScript = $('script') + .filter((_, el) => { + const htmlContent = $(el).html(); + return htmlContent != null && htmlContent.includes('eval(function(p,a,c,k,e,d)'); + }) + .first() + .html(); + + if (!packedScript) throw new NotFoundError('Packed script not found'); + + try { + const unpacked = unpack(packedScript); + for (const pattern of patterns) { + const match = unpacked.match(pattern); + if (match?.[1]) { + return match[1]; + } + } + } catch (error) { + // If unpacking fails, try alternative patterns or fallback + console.warn('Unpacking failed, trying fallback patterns'); + } + + throw new NotFoundError('Failed to find file URL in packed code'); +} + +export const supervideoScraper = makeEmbed({ + id: 'supervideo', + name: 'SuperVideo', + rank: 130, + scrape: async (ctx) => { + let url = ctx.url; + + // Normalize URL - replace /e/ and /k/ and /embed- with / + url = url.replace('/e/', '/').replace('/k/', '/').replace('/embed-', '/'); + + const headers = { + referer: ctx.url, + }; + + let html = await ctx.proxiedFetcher(url, { + headers, + }); + + // Check if video can only be watched as embed + if (html.includes('This video can be watched as embed only')) { + const embedUrl = url.replace(/\/([^/]*)$/, '/e$1'); + html = await ctx.proxiedFetcher(embedUrl, { + headers: { ...headers, referer: embedUrl }, + }); + } + + // Check for deleted/expired/processing videos + if (/The file was deleted|The file expired|Video is processing/.test(html)) { + throw new NotFoundError(); + } + + // Extract m3u8 URL from packed JavaScript + const m3u8Url = extractUrlFromPacked(html, [/sources:\[{file:"(.*?)"/]); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: m3u8Url, + flags: [flags.CORS_ALLOWED], + captions: [], + }, + ], + }; + }, +});