add consumet

add other emebeds

remove headers

update

dont proxy and just use useragent

revert no user agent
This commit is contained in:
Pas 2025-04-19 17:02:05 -06:00
parent c8cffb6111
commit 4a28b23121
5 changed files with 282 additions and 0 deletions

View file

@ -35,6 +35,12 @@ import {
autoembedTeluguScraper,
} from './embeds/autoembed';
import { closeLoadScraper } from './embeds/closeload';
import {
ConsumetStreamSBScraper,
ConsumetStreamTapeScraper,
ConsumetVidCloudScraper,
ConsumetVidStreamingScraper,
} from './embeds/consumet';
import { FedAPIPrivateScraper, FedDBScraper } from './embeds/fedapi';
import { mp4hydraServer1Scraper, mp4hydraServer2Scraper } from './embeds/mp4hydra';
import { ridooScraper } from './embeds/ridoo';
@ -64,6 +70,7 @@ import { webtor1080Scraper, webtor480Scraper, webtor4kScraper, webtor720Scraper
import { xprimeApolloEmbed, xprimeFoxEmbed, xprimeStreamboxEmbed } from './embeds/xprime';
import { EightStreamScraper } from './sources/8stream';
import { coitusScraper } from './sources/coitus';
import { ConsumetScraper } from './sources/consumet';
import { embedsuScraper } from './sources/embedsu';
import { FedAPIScraper } from './sources/fedapi';
import { hdRezkaScraper } from './sources/hdrezka';
@ -109,6 +116,7 @@ export function gatherAllSources(): Array<Sourcerer> {
riveScraper,
EightStreamScraper,
xprimeScraper,
ConsumetScraper,
];
}
@ -169,5 +177,9 @@ export function gatherAllEmbeds(): Array<Embed> {
xprimeFoxEmbed,
xprimeApolloEmbed,
xprimeStreamboxEmbed,
ConsumetVidCloudScraper,
ConsumetStreamSBScraper,
ConsumetVidStreamingScraper,
ConsumetStreamTapeScraper,
];
}

View file

@ -0,0 +1,152 @@
/* eslint-disable no-console */
import { flags } from '@/entrypoint/utils/targets';
import { EmbedOutput, makeEmbed } from '@/providers/base';
import { NotFoundError } from '@/utils/errors';
import { Caption } from '../captions';
interface StreamData {
headers: {
Referer: string;
Origin?: string;
};
intro: {
start: number;
end: number;
};
outro: {
start: number;
end: number;
};
sources: Array<{
url: string;
isM3U8: boolean;
type: string;
}>;
subtitles: Array<{
url: string;
lang: string;
}>;
}
const providers = [
{
id: 'consumet-vidcloud',
rank: 405,
name: 'VidCloud',
server: 'vidcloud',
},
{
id: 'consumet-streamsb',
rank: 404,
name: 'StreamSB',
server: 'streamsb',
disabled: true,
},
{
id: 'consumet-vidstreaming',
rank: 403,
name: 'VidStreaming',
server: 'vidstreaming',
disabled: true,
},
{
id: 'consumet-streamtape',
rank: 402,
name: 'StreamTape',
server: 'streamtape',
disabled: true,
},
];
const languageMap: Record<string, string> = {
English: 'en',
Spanish: 'es',
French: 'fr',
German: 'de',
Italian: 'it',
Portuguese: 'pt',
Arabic: 'ar',
Russian: 'ru',
Japanese: 'ja',
Korean: 'ko',
Chinese: 'zh',
Hindi: 'hi',
Turkish: 'tr',
Dutch: 'nl',
Polish: 'pl',
Swedish: 'sv',
Indonesian: 'id',
Thai: 'th',
Vietnamese: 'vi',
};
function embed(provider: { id: string; rank: number; name: string; server: string; disabled?: boolean }) {
return makeEmbed({
id: provider.id,
name: provider.name,
rank: provider.rank,
disabled: provider.disabled,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
const apiUrl = `https://consumet.pstream.org/anime/zoro/watch?episodeId=${query.episodeId}&server=${provider.server}`;
const data = await ctx.fetcher<StreamData>(apiUrl);
if (!data?.sources?.length) {
throw new NotFoundError('No stream found');
}
ctx.progress(50);
const captions: Caption[] = data.subtitles
.filter((sub) => sub.lang !== 'thumbnails')
.map((sub) => ({
type: 'vtt',
id: sub.url,
url: sub.url,
language: languageMap[sub.lang] || 'unknown',
hasCorsRestrictions: false,
}));
const streams = data.sources.reduce(
(acc, source) => {
if (source.isM3U8) {
acc.unknown = source.url;
}
return acc;
},
{} as Record<string, string>,
);
const thumbnailTrack = data.subtitles.find((sub) => sub.lang === 'thumbnails');
ctx.progress(90);
return {
stream: [
{
id: 'primary',
captions,
playlist: `https://proxy.fifthwit.net/m3u8-proxy?url=${encodeURIComponent(streams.unknown)}&headers=${encodeURIComponent(JSON.stringify({ ...(data.headers.Referer && { referer: data.headers.Referer }), ...(data.headers.Origin && { origin: data.headers.Origin }) }))}`,
type: 'hls',
flags: [flags.CORS_ALLOWED],
...(thumbnailTrack && {
thumbnailTrack: {
type: 'vtt',
url: thumbnailTrack.url,
},
}),
},
],
};
},
});
}
export const [
ConsumetVidCloudScraper,
ConsumetStreamSBScraper,
ConsumetVidStreamingScraper,
ConsumetStreamTapeScraper,
] = providers.map(embed);

View file

@ -0,0 +1,72 @@
import { flags } from '@/entrypoint/utils/targets';
import { SourcererOutput, makeSourcerer } from '@/providers/base';
import { ShowScrapeContext } from '@/utils/context';
import { InfoResponse, SearchResponse } from './types';
async function consumetScraper(ctx: ShowScrapeContext): Promise<SourcererOutput> {
// Search
const searchQuery = ctx.media.title;
const page = 1;
const searchUrl = `https://consumet.pstream.org/anime/zoro/${encodeURIComponent(searchQuery)}?page=${page}`;
const searchResponse = await ctx.fetcher<SearchResponse>(searchUrl);
if (!searchResponse?.results?.length) {
throw new Error('No results found');
}
const bestMatch =
searchResponse.results.find((result) => result.title.toLowerCase() === ctx.media.title.toLowerCase()) ||
searchResponse.results[0];
// Get episode list
const infoUrl = `https://consumet.pstream.org/anime/zoro/info?id=${bestMatch.id}`;
const infoResponse = await ctx.fetcher<InfoResponse>(infoUrl);
if (!infoResponse?.episodes?.length) {
throw new Error('No episodes found');
}
const targetEpisode = infoResponse.episodes.find((ep) => ep.number === ctx.media.episode.number);
if (!targetEpisode) {
throw new Error('Episode not found');
}
// Parse embeds
const query = {
episodeId: `${bestMatch.id}$${ctx.media.season.number}$${targetEpisode.id}$both`,
};
const embeds = [
{
embedId: 'consumet-vidcloud',
url: JSON.stringify({ ...query, server: 'vidcloud' }),
},
{
embedId: 'consumet-streamsb',
url: JSON.stringify({ ...query, server: 'streamsb' }),
},
{
embedId: 'consumet-vidstreaming',
url: JSON.stringify({ ...query, server: 'vidstreaming' }),
},
{
embedId: 'consumet-streamtape',
url: JSON.stringify({ ...query, server: 'streamtape' }),
},
];
return {
embeds,
};
}
export const ConsumetScraper = makeSourcerer({
id: 'consumet',
name: 'Zoro (Anime)',
rank: 4,
flags: [flags.CORS_ALLOWED],
scrapeShow: consumetScraper,
});

View file

@ -0,0 +1,36 @@
export interface SearchResult {
id: string;
title: string;
image: string;
releaseDate: string | null;
subOrDub: 'sub' | 'dub';
}
export interface SearchResponse {
totalPages: number;
currentPage: number;
hasNextPage: boolean;
results: SearchResult[];
}
export interface Episode {
id: string;
number: number;
url: string;
}
export interface InfoResponse {
id: string;
title: string;
url: string;
image: string;
releaseDate: string | null;
description: string | null;
genres: string[];
subOrDub: 'sub' | 'dub';
type: string | null;
status: string;
otherName: string | null;
totalEpisodes: number;
episodes: Episode[];
}

View file

@ -1,5 +1,11 @@
// import { alphaScraper, deltaScraper } from '@/providers/embeds/nsbx';
// import { astraScraper, novaScraper, orionScraper } from '@/providers/embeds/whvx';
import {
ConsumetStreamSBScraper,
ConsumetStreamTapeScraper,
ConsumetVidCloudScraper,
ConsumetVidStreamingScraper,
} from '@/providers/embeds/consumet';
import { FedAPIPrivateScraper, FedDBScraper } from '@/providers/embeds/fedapi';
import { warezcdnembedMp4Scraper } from '@/providers/embeds/warezcdn/mp4';
import { xprimeApolloEmbed, xprimeFoxEmbed, xprimeStreamboxEmbed } from '@/providers/embeds/xprime';
@ -23,6 +29,10 @@ const SKIP_VALIDATION_CHECK_IDS = [
xprimeFoxEmbed.id,
xprimeApolloEmbed.id,
xprimeStreamboxEmbed.id,
ConsumetVidCloudScraper.id,
ConsumetStreamSBScraper.id,
ConsumetVidStreamingScraper.id,
ConsumetStreamTapeScraper.id,
];
export function isValidStream(stream: Stream | undefined): boolean {