mirror of
https://github.com/p-stream/providers.git
synced 2026-03-11 17:55:36 +00:00
[add] animeflv
This commit is contained in:
parent
dc7f11d489
commit
b056cade35
4 changed files with 152 additions and 33 deletions
|
|
@ -47,9 +47,14 @@ import {
|
|||
import { FedAPIPrivateScraper, FedDBScraper } from './embeds/fedapi';
|
||||
import { mp4hydraServer1Scraper, mp4hydraServer2Scraper } from './embeds/mp4hydra';
|
||||
import { ridooScraper } from './embeds/ridoo';
|
||||
import { streamtapeScraper } from './embeds/streamtape';
|
||||
import { streamtapeLatinoScraper, streamtapeScraper } from './embeds/streamtape';
|
||||
import { streamvidScraper } from './embeds/streamvid';
|
||||
import { streamwishEnglishScraper, streamwishLatinoScraper, streamwishSpanishScraper } from './embeds/streamwish';
|
||||
import {
|
||||
streamwishEnglishScraper,
|
||||
streamwishJapaneseScraper,
|
||||
streamwishLatinoScraper,
|
||||
streamwishSpanishScraper,
|
||||
} from './embeds/streamwish';
|
||||
import { vidCloudScraper } from './embeds/vidcloud';
|
||||
import {
|
||||
VidsrcsuServer10Scraper,
|
||||
|
|
@ -82,6 +87,7 @@ import {
|
|||
} from './embeds/xprime';
|
||||
import { oneServerScraper } from './sources/1server';
|
||||
import { EightStreamScraper } from './sources/8stream';
|
||||
import { animeflvScraper } from './sources/animeflv';
|
||||
import { coitusScraper } from './sources/coitus';
|
||||
import { ConsumetScraper } from './sources/consumet';
|
||||
import { cuevana3Scraper } from './sources/cuevana3';
|
||||
|
|
@ -135,6 +141,7 @@ export function gatherAllSources(): Array<Sourcerer> {
|
|||
hianimeScraper,
|
||||
oneServerScraper,
|
||||
wecimaScraper,
|
||||
animeflvScraper,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -204,8 +211,10 @@ export function gatherAllEmbeds(): Array<Embed> {
|
|||
oneServerHianimeEmbed,
|
||||
oneServerAnimepaheEmbed,
|
||||
oneServerAnizoneEmbed,
|
||||
streamwishJapaneseScraper,
|
||||
streamwishLatinoScraper,
|
||||
streamwishSpanishScraper,
|
||||
streamwishEnglishScraper,
|
||||
streamtapeLatinoScraper,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,39 +1,56 @@
|
|||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { makeEmbed } from '@/providers/base';
|
||||
|
||||
export const streamtapeScraper = makeEmbed({
|
||||
id: 'streamtape',
|
||||
name: 'Streamtape',
|
||||
rank: 160,
|
||||
async scrape(ctx) {
|
||||
const embed = await ctx.proxiedFetcher<string>(ctx.url);
|
||||
const providers = [
|
||||
{
|
||||
id: 'streamtape',
|
||||
name: 'Streamtape',
|
||||
rank: 160,
|
||||
},
|
||||
{
|
||||
id: 'streamtape-latino',
|
||||
name: 'Streamtape (Latino)',
|
||||
rank: 159,
|
||||
},
|
||||
];
|
||||
|
||||
const match = embed.match(/robotlink'\).innerHTML = (.*)'/);
|
||||
if (!match) throw new Error('No match found');
|
||||
function embed(provider: { id: string; name: string; rank: number }) {
|
||||
return makeEmbed({
|
||||
id: provider.id,
|
||||
name: provider.name,
|
||||
rank: provider.rank,
|
||||
async scrape(ctx) {
|
||||
const embedHtml = await ctx.proxiedFetcher<string>(ctx.url);
|
||||
|
||||
const [fh, sh] = match?.[1]?.split("+ ('") ?? [];
|
||||
if (!fh || !sh) throw new Error('No match found');
|
||||
const match = embedHtml.match(/robotlink'\).innerHTML = (.*)'/);
|
||||
if (!match) throw new Error('No match found');
|
||||
|
||||
const url = `https:${fh?.replace(/'/g, '').trim()}${sh?.substring(3).trim()}`;
|
||||
const [fh, sh] = match?.[1]?.split("+ ('") ?? [];
|
||||
if (!fh || !sh) throw new Error('No match found');
|
||||
|
||||
return {
|
||||
stream: [
|
||||
{
|
||||
id: 'primary',
|
||||
type: 'file',
|
||||
flags: [flags.CORS_ALLOWED, flags.IP_LOCKED],
|
||||
captions: [],
|
||||
qualities: {
|
||||
unknown: {
|
||||
type: 'mp4',
|
||||
url,
|
||||
const url = `https:${fh?.replace(/'/g, '').trim()}${sh?.substring(3).trim()}`;
|
||||
|
||||
return {
|
||||
stream: [
|
||||
{
|
||||
id: 'primary',
|
||||
type: 'file',
|
||||
flags: [flags.CORS_ALLOWED, flags.IP_LOCKED],
|
||||
captions: [],
|
||||
qualities: {
|
||||
unknown: {
|
||||
type: 'mp4',
|
||||
url,
|
||||
},
|
||||
},
|
||||
headers: {
|
||||
Referer: 'https://streamtape.com',
|
||||
},
|
||||
},
|
||||
headers: {
|
||||
Referer: 'https://streamtape.com',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
});
|
||||
],
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export const [streamtapeScraper, streamtapeLatinoScraper] = providers.map(embed);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@ import { makeEmbed } from '@/providers/base';
|
|||
import { NotFoundError } from '@/utils/errors';
|
||||
|
||||
const providers = [
|
||||
{
|
||||
id: 'streamwish-japanese',
|
||||
name: 'StreamWish (Japones Sub Español)',
|
||||
rank: 171,
|
||||
},
|
||||
{
|
||||
id: 'streamwish-latino',
|
||||
name: 'StreamWish (Latino)',
|
||||
|
|
@ -58,4 +63,5 @@ function embed(provider: { id: string; name: string; rank: number }) {
|
|||
});
|
||||
}
|
||||
|
||||
export const [streamwishLatinoScraper, streamwishSpanishScraper, streamwishEnglishScraper] = providers.map(embed);
|
||||
export const [streamwishJapaneseScraper, streamwishLatinoScraper, streamwishSpanishScraper, streamwishEnglishScraper] =
|
||||
providers.map(embed);
|
||||
|
|
|
|||
87
src/providers/sources/animeflv.ts
Normal file
87
src/providers/sources/animeflv.ts
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/* eslint-disable no-console */
|
||||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { SourcererOutput, makeSourcerer } from '@/providers/base';
|
||||
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
|
||||
const apiBase = 'https://ws-m3u8.moonpic.qzz.io:3006';
|
||||
|
||||
async function searchAnimeFlvAPI(title: string): Promise<string> {
|
||||
const res = await fetch(`${apiBase}/search?title=${encodeURIComponent(title)}`);
|
||||
if (!res.ok) throw new NotFoundError('Anime not found in API');
|
||||
const data = await res.json();
|
||||
if (!data.url) throw new NotFoundError('Anime not found in API');
|
||||
return data.url;
|
||||
}
|
||||
|
||||
async function getEpisodesAPI(animeUrl: string): Promise<{ number: number; url: string }[]> {
|
||||
const res = await fetch(`${apiBase}/episodes?url=${encodeURIComponent(animeUrl)}`);
|
||||
if (!res.ok) throw new NotFoundError('Episodes not found in API');
|
||||
const data = await res.json();
|
||||
if (!data.episodes) throw new NotFoundError('Episodes not found in API');
|
||||
return data.episodes;
|
||||
}
|
||||
|
||||
async function getEmbedsAPI(episodeUrl: string): Promise<Record<string, string>> {
|
||||
const res = await fetch(`${apiBase}/embeds?episodeUrl=${encodeURIComponent(episodeUrl)}`);
|
||||
if (!res.ok) throw new NotFoundError('No embed found for this content');
|
||||
const data = await res.json();
|
||||
return data;
|
||||
}
|
||||
|
||||
async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promise<SourcererOutput> {
|
||||
const title = ctx.media.title;
|
||||
if (!title) throw new NotFoundError('Missing title');
|
||||
|
||||
// Search anime/movie by title using the API
|
||||
const animeUrl = await searchAnimeFlvAPI(title);
|
||||
|
||||
// Get episodes using the API
|
||||
const episodes = await getEpisodesAPI(animeUrl);
|
||||
|
||||
let episodeUrl = animeUrl;
|
||||
|
||||
if (ctx.media.type === 'show') {
|
||||
const episode = ctx.media.episode?.number;
|
||||
if (!episode) throw new NotFoundError('Missing episode data');
|
||||
const ep = episodes.find((e) => e.number === episode);
|
||||
if (!ep) throw new NotFoundError('Episode not found');
|
||||
episodeUrl = ep.url;
|
||||
} else if (ctx.media.type === 'movie') {
|
||||
// For movies, use the first episode (by convention)
|
||||
const ep = episodes.find((e) => e.number === 1) || episodes[0];
|
||||
if (!ep) throw new NotFoundError('Movie episode not found');
|
||||
episodeUrl = ep.url;
|
||||
}
|
||||
|
||||
// Get all embeds using the API
|
||||
const embedsData = await getEmbedsAPI(episodeUrl);
|
||||
|
||||
const embeds = [];
|
||||
if (embedsData['streamwish-japanese']) {
|
||||
embeds.push({
|
||||
embedId: 'streamwish-japanese',
|
||||
url: embedsData['streamwish-japanese'],
|
||||
});
|
||||
}
|
||||
if (embedsData['streamtape-latino']) {
|
||||
embeds.push({
|
||||
embedId: 'streamtape-latino',
|
||||
url: embedsData['streamtape-latino'],
|
||||
});
|
||||
}
|
||||
|
||||
if (embeds.length === 0) throw new NotFoundError('No valid embed found for this content');
|
||||
|
||||
return { embeds };
|
||||
}
|
||||
|
||||
export const animeflvScraper = makeSourcerer({
|
||||
id: 'animeflv',
|
||||
name: 'AnimeFLV',
|
||||
rank: 90,
|
||||
disabled: false,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
scrapeShow: comboScraper,
|
||||
scrapeMovie: comboScraper,
|
||||
});
|
||||
Loading…
Reference in a new issue