mirror of
https://github.com/p-stream/providers.git
synced 2026-04-20 20:32:07 +00:00
add embed.su
This commit is contained in:
parent
79be492355
commit
ad3a9198dc
3 changed files with 111 additions and 0 deletions
|
|
@ -74,12 +74,14 @@ import {
|
|||
VidsrcsuServer8Scraper,
|
||||
VidsrcsuServer9Scraper,
|
||||
} from './embeds/vidsrcsu';
|
||||
import { viperScraper } from './embeds/viper';
|
||||
import { voeScraper } from './embeds/voe';
|
||||
import { warezcdnembedHlsScraper } from './embeds/warezcdn/hls';
|
||||
import { warezcdnembedMp4Scraper } from './embeds/warezcdn/mp4';
|
||||
import { warezPlayerScraper } from './embeds/warezcdn/warezplayer';
|
||||
import { webtor1080Scraper, webtor480Scraper, webtor4kScraper, webtor720Scraper } from './embeds/webtor';
|
||||
import { wootlyScraper } from './embeds/wootly';
|
||||
import { embedsuScraper } from './sources/embedsu';
|
||||
import { goojaraScraper } from './sources/goojara';
|
||||
import { hdRezkaScraper } from './sources/hdrezka';
|
||||
import { m4uScraper } from './sources/m4ufree';
|
||||
|
|
@ -129,6 +131,7 @@ export function gatherAllSources(): Array<Sourcerer> {
|
|||
TASFScraper,
|
||||
mp4hydraScraper,
|
||||
webtorScraper,
|
||||
embedsuScraper,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -197,5 +200,6 @@ export function gatherAllEmbeds(): Array<Embed> {
|
|||
webtor1080Scraper,
|
||||
webtor720Scraper,
|
||||
webtor480Scraper,
|
||||
viperScraper,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
36
src/providers/embeds/viper.ts
Normal file
36
src/providers/embeds/viper.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { makeEmbed } from '@/providers/base';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
|
||||
export const viperScraper = makeEmbed({
|
||||
id: 'viper',
|
||||
name: 'Viper',
|
||||
rank: 182,
|
||||
async scrape(ctx) {
|
||||
const apiResponse = await ctx.proxiedFetcher.full<{
|
||||
source: string;
|
||||
}>(ctx.url, {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Referer: 'https://embed.su/',
|
||||
},
|
||||
});
|
||||
|
||||
if (!apiResponse.body.source) {
|
||||
throw new NotFoundError('No source found');
|
||||
}
|
||||
const playlistUrl = apiResponse.body.source.replace(/^.*\/viper\//, 'https://');
|
||||
|
||||
return {
|
||||
stream: [
|
||||
{
|
||||
type: 'hls',
|
||||
id: 'primary',
|
||||
playlist: playlistUrl,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
});
|
||||
71
src/providers/sources/embedsu.ts
Normal file
71
src/providers/sources/embedsu.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { SourcererEmbed, SourcererOutput, makeSourcerer } from '@/providers/base';
|
||||
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
|
||||
// custom atob 💀
|
||||
async function stringAtob(input: string): Promise<string> {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
const str = input.replace(/=+$/, '');
|
||||
let output = '';
|
||||
if (str.length % 4 === 1) {
|
||||
throw new Error('The string to be decoded is not correctly encoded.');
|
||||
}
|
||||
for (let bc = 0, bs = 0, i = 0; i < str.length; i++) {
|
||||
const buffer = str.charAt(i);
|
||||
const charIndex = chars.indexOf(buffer);
|
||||
if (charIndex === -1) continue;
|
||||
bs = bc % 4 ? bs * 64 + charIndex : charIndex;
|
||||
if (bc++ % 4) {
|
||||
output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)));
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promise<SourcererOutput> {
|
||||
const embedUrl = `https://embed.su/embed/${ctx.media.type === 'movie' ? `movie/${ctx.media.tmdbId}` : `tv/${ctx.media.tmdbId}/${ctx.media.season.number}/${ctx.media.episode.number}`}`;
|
||||
|
||||
const embedPage = await ctx.proxiedFetcher<string>(embedUrl, {
|
||||
headers: {
|
||||
Referer: 'https://embed.su/',
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
|
||||
},
|
||||
});
|
||||
|
||||
const vConfigMatch = embedPage.match(/window\.vConfig\s*=\s*JSON\.parse\(atob\(`([^`]+)/i);
|
||||
const encodedConfig = vConfigMatch?.[1];
|
||||
if (!encodedConfig) throw new NotFoundError('No encoded config found');
|
||||
|
||||
const decodedConfig = JSON.parse(await stringAtob(encodedConfig));
|
||||
if (!decodedConfig?.hash) throw new NotFoundError('No stream hash found');
|
||||
|
||||
const firstDecode = (await stringAtob(decodedConfig.hash))
|
||||
.split('.')
|
||||
.map((item) => item.split('').reverse().join(''));
|
||||
|
||||
const secondDecode = JSON.parse(await stringAtob(firstDecode.join('').split('').reverse().join(''))) as Array<{
|
||||
name: string;
|
||||
hash: string;
|
||||
}>;
|
||||
|
||||
if (!secondDecode?.length) throw new NotFoundError('No servers found');
|
||||
ctx.progress(50);
|
||||
|
||||
const embeds: SourcererEmbed[] = secondDecode.map((server) => ({
|
||||
embedId: 'viper',
|
||||
url: `https://embed.su/api/e/${server.hash}`,
|
||||
}));
|
||||
ctx.progress(90);
|
||||
|
||||
return { embeds };
|
||||
}
|
||||
|
||||
export const embedsuScraper = makeSourcerer({
|
||||
id: 'embedsu',
|
||||
name: 'embed.su',
|
||||
rank: 229,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
scrapeMovie: comboScraper,
|
||||
scrapeShow: comboScraper,
|
||||
});
|
||||
Loading…
Reference in a new issue