update zoro and consumet

This commit is contained in:
Pas 2025-04-23 10:21:20 -06:00
parent 640c82ba52
commit 4487e9e818
3 changed files with 100 additions and 64 deletions

View file

@ -4,7 +4,7 @@ import { NotFoundError } from '@/utils/errors';
export const hianimeHd1DubEmbed = makeEmbed({
id: 'hianime-hd1-dub',
name: 'Hianime HD-1 (Dub)',
name: 'HD-1 (Dub)',
disabled: true,
rank: 250,
async scrape(ctx): Promise<EmbedOutput> {
@ -42,7 +42,7 @@ export const hianimeHd1DubEmbed = makeEmbed({
export const hianimeHd2DubEmbed = makeEmbed({
id: 'hianime-hd2-dub',
name: 'Hianime HD-2 (Dub)',
name: 'HD-2 (Dub)',
rank: 251,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
@ -55,11 +55,34 @@ export const hianimeHd2DubEmbed = makeEmbed({
const thumbnailTrack = data.data.tracks?.find((track: { kind: string }) => track.kind === 'thumbnails')?.file;
return {
stream: [
{
type: 'hls',
id: 'primary',
playlist: `https://proxy-m3u8.uira.live/m3u8-proxy?url=${data.data.sources[0].url}&headers=${encodeURIComponent(JSON.stringify(data.data.headers))}`,
flags: [flags.CORS_ALLOWED],
captions: [],
...(thumbnailTrack
? {
thumbnailTrack: {
type: 'vtt',
url: thumbnailTrack,
},
}
: {}),
// headers: data.data.headers,
},
],
// stream: [
// {
// type: 'hls',
// type: 'file',
// id: 'primary',
// playlist: data.data.sources[0].url,
// qualities: {
// unknown: {
// type: 'mp4',
// url: data.data.sources[0].url,
// },
// },
// flags: [flags.CORS_ALLOWED],
// captions: [],
// ...(thumbnailTrack
@ -73,36 +96,13 @@ export const hianimeHd2DubEmbed = makeEmbed({
// headers: data.data.headers,
// },
// ],
stream: [
{
type: 'file',
id: 'primary',
qualities: {
unknown: {
type: 'mp4',
url: data.data.sources[0].url,
},
},
flags: [flags.CORS_ALLOWED],
captions: [],
...(thumbnailTrack
? {
thumbnailTrack: {
type: 'vtt',
url: thumbnailTrack,
},
}
: {}),
headers: data.data.headers,
},
],
};
},
});
export const hianimeHd1SubEmbed = makeEmbed({
id: 'hianime-hd1-sub',
name: 'Hianime HD-1 (Sub)',
name: 'HD-1 (Sub)',
disabled: true,
rank: 252,
async scrape(ctx): Promise<EmbedOutput> {
@ -140,7 +140,7 @@ export const hianimeHd1SubEmbed = makeEmbed({
export const hianimeHd2SubEmbed = makeEmbed({
id: 'hianime-hd2-sub',
name: 'Hianime HD-2 (Sub)',
name: 'HD-2 (Sub)',
rank: 253,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
@ -153,11 +153,34 @@ export const hianimeHd2SubEmbed = makeEmbed({
const thumbnailTrack = data.data.tracks?.find((track: { kind: string }) => track.kind === 'thumbnails')?.file;
return {
stream: [
{
type: 'hls',
id: 'primary',
playlist: `https://proxy-m3u8.uira.live/m3u8-proxy?url=${data.data.sources[0].url}&headers=${encodeURIComponent(JSON.stringify(data.data.headers))}`,
flags: [flags.CORS_ALLOWED],
captions: [],
...(thumbnailTrack
? {
thumbnailTrack: {
type: 'vtt',
url: thumbnailTrack,
},
}
: {}),
// headers: data.data.headers,
},
],
// stream: [
// {
// type: 'hls',
// type: 'file',
// id: 'primary',
// playlist: data.data.sources[0].url,
// qualities: {
// unknown: {
// type: 'mp4',
// url: data.data.sources[0].url,
// },
// },
// flags: [flags.CORS_ALLOWED],
// captions: [],
// ...(thumbnailTrack
@ -171,29 +194,6 @@ export const hianimeHd2SubEmbed = makeEmbed({
// headers: data.data.headers,
// },
// ],
stream: [
{
type: 'file',
id: 'primary',
qualities: {
unknown: {
type: 'mp4',
url: data.data.sources[0].url,
},
},
flags: [flags.CORS_ALLOWED],
captions: [],
...(thumbnailTrack
? {
thumbnailTrack: {
type: 'vtt',
url: thumbnailTrack,
},
}
: {}),
headers: data.data.headers,
},
],
};
},
});

View file

@ -65,7 +65,7 @@ async function consumetScraper(ctx: ShowScrapeContext): Promise<SourcererOutput>
export const ConsumetScraper = makeSourcerer({
id: 'consumet',
name: 'Zoro (Anime)',
name: 'Consumet (Anime)',
rank: 4,
flags: [flags.CORS_ALLOWED],
scrapeShow: consumetScraper,

View file

@ -1,6 +1,8 @@
/* eslint-disable no-console */
import { flags } from '@/entrypoint/utils/targets';
import { SourcererOutput, makeSourcerer } from '@/providers/base';
import { ShowScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';
interface HianimeSearchResult {
success: boolean;
@ -32,25 +34,59 @@ async function searchAnime(title: string): Promise<string> {
throw new Error('Anime not found');
}
// Return the ID of the first matching anime
return data.data.animes[0].id;
// Try to find exact match (case-insensitive)
const match = data.data.animes.find((anime) => anime.name.toLowerCase() === title.toLowerCase());
// Return the matched ID or fallback to the first result
return match?.id ?? data.data.animes[0].id;
}
async function fetchTmdbSeasonEpisodes(tmdbShowId: string, seasonNumber: number): Promise<any[]> {
const apiKey = '5b9790d9305dca8713b9a0afad42ea8d'; // plz dont abuse
const response = await fetch(
`https://api.themoviedb.org/3/tv/${tmdbShowId}/season/${seasonNumber}?api_key=${apiKey}`,
);
if (!response.ok) throw new NotFoundError('Failed to fetch season data from TMDB');
const data = await response.json();
return data.episodes; // each item has 'episode_number' and 'season_number'
}
async function calculateAbsoluteEpisodeNumber(
tmdbShowId: string,
seasonNumber: number,
episodeNumber: number,
): Promise<number> {
const previousSeasons = await Promise.all(
Array.from({ length: seasonNumber - 1 }, (_, i) => fetchTmdbSeasonEpisodes(tmdbShowId, i + 1)),
);
const episodesBefore = previousSeasons.reduce((sum, seasonEpisodes) => sum + seasonEpisodes.length, 0);
return episodesBefore + episodeNumber;
}
async function fetchEpisodeData(animeId: string): Promise<HianimeEpisodeResult> {
const response = await fetch(`https://hianime.pstream.org/api/v2/hianime/anime/${animeId}/episodes`);
if (!response.ok) throw new Error('Failed to fetch episode data');
if (!response.ok) throw new NotFoundError('Failed to fetch episode data');
return response.json();
}
async function comboScraper(ctx: ShowScrapeContext): Promise<SourcererOutput> {
// First, search for the anime to get its Hianime ID
const animeId = await searchAnime(ctx.media.title);
// console.log(animeId);
const absoluteEp = await calculateAbsoluteEpisodeNumber(
ctx.media.tmdbId,
ctx.media.season.number,
ctx.media.episode.number,
);
// console.log(absoluteEp);
// Then, get the episode data
const episodeData = await fetchEpisodeData(animeId);
const episode = episodeData.data.episodes.find((ep) => ep.number === ctx.media.episode.number);
if (!episode) throw new Error('Episode not found');
// console.log(episodeData);
const episode = episodeData.data.episodes.find((ep) => ep.number === absoluteEp);
if (!episode) throw new NotFoundError('Episode not found');
const embeds = [
{
@ -84,7 +120,7 @@ async function comboScraper(ctx: ShowScrapeContext): Promise<SourcererOutput> {
export const hianimeScraper = makeSourcerer({
id: 'hianime',
name: 'Hianime',
name: 'Zoro (Anime)',
rank: 7,
disabled: false,
flags: [flags.CORS_ALLOWED],