add hianime

enable cors for all

Update hianime.ts

Update valid.ts
This commit is contained in:
Pas 2025-04-21 19:28:53 -06:00
parent 4a28b23121
commit f64582f5b6
4 changed files with 313 additions and 0 deletions

View file

@ -1,5 +1,11 @@
import { Embed, Sourcerer } from '@/providers/base';
import { doodScraper } from '@/providers/embeds/dood';
import {
hianimeHd1DubEmbed,
hianimeHd1SubEmbed,
hianimeHd2DubEmbed,
hianimeHd2SubEmbed,
} from '@/providers/embeds/hianime';
import { mixdropScraper } from '@/providers/embeds/mixdrop';
import {
riveAsiacloudScraper,
@ -21,6 +27,7 @@ import { autoembedScraper } from '@/providers/sources/autoembed';
import { catflixScraper } from '@/providers/sources/catflix';
import { ee3Scraper } from '@/providers/sources/ee3';
import { fsharetvScraper } from '@/providers/sources/fsharetv';
import { hianimeScraper } from '@/providers/sources/hianime';
import { insertunitScraper } from '@/providers/sources/insertunit';
import { mp4hydraScraper } from '@/providers/sources/mp4hydra';
import { riveScraper } from '@/providers/sources/rive';
@ -117,6 +124,7 @@ export function gatherAllSources(): Array<Sourcerer> {
EightStreamScraper,
xprimeScraper,
ConsumetScraper,
hianimeScraper,
];
}
@ -181,5 +189,9 @@ export function gatherAllEmbeds(): Array<Embed> {
ConsumetStreamSBScraper,
ConsumetVidStreamingScraper,
ConsumetStreamTapeScraper,
hianimeHd1DubEmbed,
hianimeHd2DubEmbed,
hianimeHd1SubEmbed,
hianimeHd2SubEmbed,
];
}

View file

@ -0,0 +1,199 @@
import { flags } from '@/entrypoint/utils/targets';
import { EmbedOutput, makeEmbed } from '@/providers/base';
import { NotFoundError } from '@/utils/errors';
export const hianimeHd1DubEmbed = makeEmbed({
id: 'hianime-hd1-dub',
name: 'Hianime HD-1 (Dub)',
disabled: true,
rank: 250,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
const url = `https://hianime.pstream.org/api/v2/hianime/episode/sources?animeEpisodeId=${query.episodeId}&server=hd-1&category=dub`;
const data = await ctx.fetcher(url);
if (!data) throw new NotFoundError('No response received');
if (!data.data?.sources?.[0]?.url) throw new NotFoundError('No stream URL found in response');
const thumbnailTrack = data.data.tracks?.find((track: { kind: string }) => track.kind === 'thumbnails')?.file;
return {
stream: [
{
type: 'hls',
id: 'primary',
playlist: data.data.sources[0].url,
flags: [flags.CORS_ALLOWED],
captions: [],
...(thumbnailTrack
? {
thumbnailTrack: {
type: 'vtt',
url: thumbnailTrack,
},
}
: {}),
headers: data.data.headers,
},
],
};
},
});
export const hianimeHd2DubEmbed = makeEmbed({
id: 'hianime-hd2-dub',
name: 'Hianime HD-2 (Dub)',
rank: 251,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
const url = `https://hianime.pstream.org/api/v2/hianime/episode/sources?animeEpisodeId=${query.episodeId}&server=hd-2&category=dub`;
const data = await ctx.fetcher(url);
if (!data) throw new NotFoundError('No response received');
if (!data.data?.sources?.[0]?.url) throw new NotFoundError('No stream URL found in response');
const thumbnailTrack = data.data.tracks?.find((track: { kind: string }) => track.kind === 'thumbnails')?.file;
return {
// stream: [
// {
// type: 'hls',
// id: 'primary',
// playlist: data.data.sources[0].url,
// flags: [flags.CORS_ALLOWED],
// captions: [],
// ...(thumbnailTrack
// ? {
// thumbnailTrack: {
// type: 'vtt',
// url: thumbnailTrack,
// },
// }
// : {}),
// 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)',
disabled: true,
rank: 252,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
const url = `https://hianime.pstream.org/api/v2/hianime/episode/sources?animeEpisodeId=${query.episodeId}&server=hd-1&category=sub`;
const data = await ctx.fetcher(url);
if (!data) throw new NotFoundError('No response received');
if (!data.data?.sources?.[0]?.url) throw new NotFoundError('No stream URL found in response');
const thumbnailTrack = data.data.tracks?.find((track: { kind: string }) => track.kind === 'thumbnails')?.file;
return {
stream: [
{
type: 'hls',
id: 'primary',
playlist: data.data.sources[0].url,
flags: [flags.CORS_ALLOWED],
captions: [],
...(thumbnailTrack
? {
thumbnailTrack: {
type: 'vtt',
url: thumbnailTrack,
},
}
: {}),
headers: data.data.headers,
},
],
};
},
});
export const hianimeHd2SubEmbed = makeEmbed({
id: 'hianime-hd2-sub',
name: 'Hianime HD-2 (Sub)',
rank: 253,
async scrape(ctx): Promise<EmbedOutput> {
const query = JSON.parse(ctx.url);
const url = `https://hianime.pstream.org/api/v2/hianime/episode/sources?animeEpisodeId=${query.episodeId}&server=hd-2&category=sub`;
const data = await ctx.fetcher(url);
if (!data) throw new NotFoundError('No response received');
if (!data.data?.sources?.[0]?.url) throw new NotFoundError('No stream URL found in response');
const thumbnailTrack = data.data.tracks?.find((track: { kind: string }) => track.kind === 'thumbnails')?.file;
return {
// stream: [
// {
// type: 'hls',
// id: 'primary',
// playlist: data.data.sources[0].url,
// flags: [flags.CORS_ALLOWED],
// captions: [],
// ...(thumbnailTrack
// ? {
// thumbnailTrack: {
// type: 'vtt',
// url: thumbnailTrack,
// },
// }
// : {}),
// 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

@ -0,0 +1,92 @@
import { flags } from '@/entrypoint/utils/targets';
import { SourcererOutput, makeSourcerer } from '@/providers/base';
import { ShowScrapeContext } from '@/utils/context';
interface HianimeSearchResult {
success: boolean;
data: {
animes: Array<{
id: string;
name: string;
}>;
};
}
interface HianimeEpisodeResult {
success: boolean;
data: {
episodes: Array<{
number: number;
title: string;
episodeId: string;
}>;
};
}
async function searchAnime(title: string): Promise<string> {
const response = await fetch(`https://hianime.pstream.org/api/v2/hianime/search?q=${encodeURIComponent(title)}`);
if (!response.ok) throw new Error('Failed to search anime');
const data: HianimeSearchResult = await response.json();
if (!data.success || !data.data.animes.length) {
throw new Error('Anime not found');
}
// Return the ID of the first matching anime
return data.data.animes[0].id;
}
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');
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);
// 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');
const embeds = [
{
embedId: 'hianime-hd1-dub',
url: JSON.stringify({
episodeId: episode.episodeId,
}),
},
{
embedId: 'hianime-hd2-dub',
url: JSON.stringify({
episodeId: episode.episodeId,
}),
},
{
embedId: 'hianime-hd1-sub',
url: JSON.stringify({
episodeId: episode.episodeId,
}),
},
{
embedId: 'hianime-hd2-sub',
url: JSON.stringify({
episodeId: episode.episodeId,
}),
},
];
return { embeds };
}
export const hianimeScraper = makeSourcerer({
id: 'hianime',
name: 'Hianime',
rank: 7,
disabled: false,
flags: [flags.CORS_ALLOWED],
scrapeShow: comboScraper,
});

View file

@ -7,6 +7,12 @@ import {
ConsumetVidStreamingScraper,
} from '@/providers/embeds/consumet';
import { FedAPIPrivateScraper, FedDBScraper } from '@/providers/embeds/fedapi';
import {
hianimeHd1DubEmbed,
hianimeHd1SubEmbed,
hianimeHd2DubEmbed,
hianimeHd2SubEmbed,
} from '@/providers/embeds/hianime';
import { warezcdnembedMp4Scraper } from '@/providers/embeds/warezcdn/mp4';
import { xprimeApolloEmbed, xprimeFoxEmbed, xprimeStreamboxEmbed } from '@/providers/embeds/xprime';
import { embedsuScraper } from '@/providers/sources/embedsu';
@ -33,6 +39,10 @@ const SKIP_VALIDATION_CHECK_IDS = [
ConsumetStreamSBScraper.id,
ConsumetVidStreamingScraper.id,
ConsumetStreamTapeScraper.id,
hianimeHd1DubEmbed.id,
hianimeHd1SubEmbed.id,
hianimeHd2DubEmbed.id,
hianimeHd2SubEmbed.id,
];
export function isValidStream(stream: Stream | undefined): boolean {