add 8stream

This commit is contained in:
Pas 2025-04-06 23:13:13 -06:00
parent cf7c449d54
commit 995bbfde5c
5 changed files with 263 additions and 0 deletions

View file

@ -61,6 +61,7 @@ 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 { EightStreamScraper } from './sources/8stream';
import { coitusScraper } from './sources/coitus';
import { embedsuScraper } from './sources/embedsu';
import { FedAPIScraper } from './sources/fedapi';
@ -104,6 +105,7 @@ export function gatherAllSources(): Array<Sourcerer> {
streamboxScraper,
nunflixScraper,
riveScraper,
EightStreamScraper,
];
}

View file

@ -0,0 +1,85 @@
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';
import getInfo from './getInfo';
import getStream from './getStream';
export async function getMovie(ctx: ShowScrapeContext | MovieScrapeContext, id: string, lang: string = 'English') {
try {
const mediaInfo = await getInfo(ctx, id);
if (mediaInfo?.success) {
const playlist = mediaInfo?.data?.playlist;
if (!playlist || !Array.isArray(playlist)) {
throw new NotFoundError('Playlist not found or invalid');
}
let file = playlist.find((item: any) => item?.title === lang);
if (!file) {
file = playlist?.[0];
}
if (!file) {
throw new NotFoundError('No file found');
}
const availableLang = playlist.map((item: any) => item?.title);
const key = mediaInfo?.data?.key;
ctx.progress(70);
const streamUrl = await getStream(ctx, file?.file, key);
if (streamUrl?.success) {
return { success: true, data: streamUrl?.data, availableLang };
}
throw new NotFoundError('No stream url found');
}
throw new NotFoundError('No media info found');
} catch (error) {
if (error instanceof NotFoundError) throw error;
throw new NotFoundError('Failed to fetch movie data');
}
}
export async function getTV(
ctx: ShowScrapeContext | MovieScrapeContext,
id: string,
season: number,
episode: number,
lang: string,
) {
try {
const mediaInfo = await getInfo(ctx, id);
if (!mediaInfo?.success) {
throw new NotFoundError('No media info found');
}
const playlist = mediaInfo?.data?.playlist;
const getSeason = playlist.find((item: any) => item?.id === season.toString());
if (!getSeason) {
throw new NotFoundError('No season found');
}
const getEpisode = getSeason?.folder.find((item: any) => item?.episode === episode.toString());
if (!getEpisode) {
throw new NotFoundError('No episode found');
}
let file = getEpisode?.folder.find((item: any) => item?.title === lang);
if (!file) {
file = getEpisode?.folder?.[0];
}
if (!file) {
throw new NotFoundError('No file found');
}
const availableLang = getEpisode?.folder.map((item: any) => {
return item?.title;
});
const filterLang = availableLang.filter((item: any) => item?.length > 0);
const key = mediaInfo?.data?.key;
ctx.progress(70);
const streamUrl = await getStream(ctx, file?.file, key);
if (streamUrl?.success) {
return {
success: true,
data: streamUrl?.data,
availableLang: filterLang,
};
}
throw new NotFoundError('No stream url found');
} catch (error) {
if (error instanceof NotFoundError) throw error;
throw new NotFoundError('Failed to fetch TV data');
}
}

View file

@ -0,0 +1,63 @@
import * as cheerio from 'cheerio';
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';
export default async function getStream(ctx: ShowScrapeContext | MovieScrapeContext, id: string): Promise<any> {
try {
const baseUrl = 'https://ftmoh345xme.com';
const headers = {
Origin: 'https://friness-cherlormur-i-275.site',
Referer: 'https://google.com/',
Dnt: '1',
};
const url = `${baseUrl}/play/${id}`;
const result = await ctx.proxiedFetcher(url, {
headers: {
...headers,
},
method: 'GET',
});
const $ = cheerio.load(result);
const script = $('script').last().html()!;
if (!script) {
throw new NotFoundError('Failed to extract script data');
}
const content = script.match(/(\{[^;]+});/)?.[1] || script.match(/\((\{.*\})\)/)?.[1];
if (!content) {
throw new NotFoundError('Media not found');
}
const data = JSON.parse(content);
let file = data.file;
if (!file) {
throw new NotFoundError('File not found');
}
if (file.startsWith('/')) {
file = baseUrl + file;
}
const key = data.key;
const headers2 = {
Origin: 'https://friness-cherlormur-i-275.site',
Referer: 'https://google.com/',
Dnt: '1',
'X-Csrf-Token': key,
};
const PlayListRes = await ctx.proxiedFetcher(file, {
headers: {
...headers2,
},
method: 'GET',
});
const playlist = PlayListRes;
return {
success: true,
data: {
playlist,
key,
},
};
} catch (error) {
if (error instanceof NotFoundError) throw error;
throw new NotFoundError('Failed to fetch media info');
}
}

View file

@ -0,0 +1,36 @@
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';
export default async function getStream(
ctx: ShowScrapeContext | MovieScrapeContext,
file: string,
key: string,
): Promise<any> {
const f = file as string;
const path = `${f.slice(1)}.txt`;
try {
const baseUrl = 'https://ftmoh345xme.com';
const headers = {
Origin: 'https://friness-cherlormur-i-275.site',
Referer: 'https://google.com/',
Dnt: '1',
'X-Csrf-Token': key,
};
const url = `${baseUrl}/playlist/${path}`;
const result = await ctx.proxiedFetcher(url, {
headers: {
...headers,
},
method: 'GET',
});
return {
success: true,
data: {
link: result,
},
};
} catch (error) {
throw new NotFoundError('Failed to fetch stream data');
}
}

View file

@ -0,0 +1,77 @@
import { flags } from '@/entrypoint/utils/targets';
import { SourcererOutput, makeSourcerer } from '@/providers/base';
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';
import { getMovie, getTV } from './8Stream';
async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promise<SourcererOutput> {
const query = {
title: ctx.media.title,
releaseYear: ctx.media.releaseYear,
tmdbId: ctx.media.tmdbId,
imdbId: ctx.media.imdbId,
type: ctx.media.type,
season: '',
episode: '',
};
if (ctx.media.type === 'show') {
query.season = ctx.media.season.number.toString();
query.episode = ctx.media.episode.number.toString();
}
if (ctx.media.type === 'movie') {
ctx.progress(40);
const res = await getMovie(ctx, ctx.media.imdbId as string);
if (res?.success) {
ctx.progress(90);
return {
embeds: [],
stream: [
{
id: 'primary',
captions: [],
playlist: res.data.link,
type: 'hls',
flags: [flags.CORS_ALLOWED],
},
],
};
}
throw new NotFoundError('No providers available');
}
if (ctx.media.type === 'show') {
ctx.progress(40);
const lang = 'English';
const res = await getTV(ctx, ctx.media.imdbId as string, ctx.media.season.number, ctx.media.episode.number, lang);
if (res?.success) {
ctx.progress(90);
return {
embeds: [],
stream: [
{
id: 'primary',
captions: [],
playlist: res.data.link,
type: 'hls',
flags: [flags.CORS_ALLOWED],
},
],
};
}
throw new NotFoundError('No providers available');
}
throw new NotFoundError('No providers available');
}
export const EightStreamScraper = makeSourcerer({
id: '8stream',
name: '8stream',
rank: 111,
flags: [],
disabled: false,
scrapeMovie: comboScraper,
scrapeShow: comboScraper,
});