commit
bc34b95647
|
@ -1,3 +1,4 @@
|
|||
import { load } from 'cheerio';
|
||||
import { unpack } from 'unpacker';
|
||||
|
||||
import { flags } from '@/entrypoint/utils/targets';
|
||||
|
@ -19,7 +20,8 @@ export const fileMoonScraper = makeEmbed({
|
|||
referer: ctx.url,
|
||||
},
|
||||
});
|
||||
const evalCode = embedRes.match(evalCodeRegex);
|
||||
const embedHtml = load(embedRes);
|
||||
const evalCode = embedHtml('script').text().match(evalCodeRegex);
|
||||
if (!evalCode) throw new Error('Failed to find eval code');
|
||||
const unpacked = unpack(evalCode[1]);
|
||||
const file = fileRegex.exec(unpacked);
|
||||
|
|
|
@ -2,6 +2,7 @@ import * as unpacker from 'unpacker';
|
|||
|
||||
import { makeEmbed } from '@/providers/base';
|
||||
|
||||
const mixdropBase = 'https://mixdrop.ag';
|
||||
const packedRegex = /(eval\(function\(p,a,c,k,e,d\){.*{}\)\))/;
|
||||
const linkRegex = /MDCore\.wurl="(.*?)";/;
|
||||
|
||||
|
@ -12,7 +13,16 @@ export const mixdropScraper = makeEmbed({
|
|||
async scrape(ctx) {
|
||||
// Example url: https://mixdrop.co/e/pkwrgp0pizgod0
|
||||
// Example url: https://mixdrop.vc/e/pkwrgp0pizgod0
|
||||
const streamRes = await ctx.proxiedFetcher<string>(ctx.url);
|
||||
let embedUrl = ctx.url;
|
||||
if (ctx.url.includes('primewire')) embedUrl = (await ctx.fetcher.full(ctx.url)).finalUrl;
|
||||
const embedId = new URL(embedUrl).pathname.split('/')[2];
|
||||
// constructing the url because many times mixdrop.co is returned which does not work
|
||||
// this also handels the case where preview page urls are returned
|
||||
// Example: https://mixdrop.vc/f/pkwrgp0pizgod0
|
||||
// these don't have the packed code
|
||||
const streamRes = await ctx.proxiedFetcher<string>(`/e/${embedId}`, {
|
||||
baseUrl: mixdropBase,
|
||||
});
|
||||
const packed = streamRes.match(packedRegex);
|
||||
|
||||
// MixDrop uses a queue system for embeds
|
||||
|
@ -45,7 +55,7 @@ export const mixdropScraper = makeEmbed({
|
|||
url: url.startsWith('http') ? url : `https:${url}`, // URLs don't always start with the protocol
|
||||
headers: {
|
||||
// MixDrop requires this header on all streams
|
||||
Referer: 'https://mixdrop.co/',
|
||||
Referer: mixdropBase,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -60,6 +60,7 @@ export const upcloudScraper = makeEmbed({
|
|||
id: 'upcloud',
|
||||
name: 'UpCloud',
|
||||
rank: 200,
|
||||
disabled: true,
|
||||
async scrape(ctx) {
|
||||
// Example url: https://dokicloud.one/embed-4/{id}?z=
|
||||
const parsedUrl = new URL(ctx.url.replace('embed-5', 'embed-4'));
|
||||
|
|
|
@ -6,6 +6,7 @@ export const vidCloudScraper = makeEmbed({
|
|||
id: 'vidcloud',
|
||||
name: 'VidCloud',
|
||||
rank: 201,
|
||||
disabled: true,
|
||||
async scrape(ctx) {
|
||||
// Both vidcloud and upcloud have the same embed domain (rabbitstream.net)
|
||||
const result = await upcloudScraper.scrape(ctx);
|
||||
|
|
|
@ -3,7 +3,7 @@ import { makeEmbed } from '@/providers/base';
|
|||
import { Caption, getCaptionTypeFromUrl, labelToLanguageCode } from '@/providers/captions';
|
||||
|
||||
import { getFileUrl } from './common';
|
||||
import { SubtitleResult, VidplaySourceResponse } from './types';
|
||||
import { SubtitleResult, ThumbnailTrack, VidplaySourceResponse } from './types';
|
||||
|
||||
export const vidplayScraper = makeEmbed({
|
||||
id: 'vidplay',
|
||||
|
@ -18,6 +18,15 @@ export const vidplayScraper = makeEmbed({
|
|||
});
|
||||
if (typeof fileUrlRes.result === 'number') throw new Error('File not found');
|
||||
const source = fileUrlRes.result.sources[0].file;
|
||||
const thumbnailSource = fileUrlRes.result.tracks.find((track) => track.kind === 'thumbnails');
|
||||
|
||||
let thumbnailTrack: ThumbnailTrack | undefined;
|
||||
if (thumbnailSource) {
|
||||
thumbnailTrack = {
|
||||
type: 'vtt',
|
||||
url: thumbnailSource.file,
|
||||
};
|
||||
}
|
||||
|
||||
const url = new URL(ctx.url);
|
||||
const subtitlesLink = url.searchParams.get('sub.info');
|
||||
|
@ -47,6 +56,7 @@ export const vidplayScraper = makeEmbed({
|
|||
playlist: source,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
captions,
|
||||
thumbnailTrack,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -3,10 +3,10 @@ export type VidplaySourceResponse = {
|
|||
| {
|
||||
sources: {
|
||||
file: string;
|
||||
tracks: {
|
||||
file: string;
|
||||
kind: string;
|
||||
}[];
|
||||
}[];
|
||||
tracks: {
|
||||
file: string;
|
||||
kind: string;
|
||||
}[];
|
||||
}
|
||||
| number;
|
||||
|
@ -17,3 +17,8 @@ export type SubtitleResult = {
|
|||
label: string;
|
||||
kind: string;
|
||||
}[];
|
||||
|
||||
export type ThumbnailTrack = {
|
||||
type: 'vtt';
|
||||
url: string;
|
||||
};
|
||||
|
|
|
@ -2,7 +2,12 @@ import { load } from 'cheerio';
|
|||
|
||||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { makeSourcerer } from '@/providers/base';
|
||||
import { doodScraper } from '@/providers/embeds/dood';
|
||||
import { mixdropScraper } from '@/providers/embeds/mixdrop';
|
||||
import { upcloudScraper } from '@/providers/embeds/upcloud';
|
||||
import { upstreamScraper } from '@/providers/embeds/upstream';
|
||||
import { vidCloudScraper } from '@/providers/embeds/vidcloud';
|
||||
import { voeScraper } from '@/providers/embeds/voe';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
|
||||
import { getSource } from './source';
|
||||
|
@ -13,12 +18,11 @@ export const goMoviesScraper = makeSourcerer({
|
|||
id: 'gomovies',
|
||||
name: 'GOmovies',
|
||||
rank: 60,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
disabled: true,
|
||||
flags: [flags.CORS_ALLOWED],
|
||||
async scrapeShow(ctx) {
|
||||
const search = await ctx.proxiedFetcher<string>(`/ajax/search`, {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams({ keyword: ctx.media.title }),
|
||||
const search = await ctx.proxiedFetcher(`/search/${ctx.media.title.replaceAll(/[^a-z0-9A-Z]/g, '-')}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
},
|
||||
|
@ -26,12 +30,12 @@ export const goMoviesScraper = makeSourcerer({
|
|||
});
|
||||
|
||||
const searchPage = load(search);
|
||||
const mediaElements = searchPage('a.nav-item');
|
||||
const mediaElements = searchPage('div.film-detail');
|
||||
|
||||
const mediaData = mediaElements.toArray().map((movieEl) => {
|
||||
const name = searchPage(movieEl).find('h3.film-name')?.text();
|
||||
const year = searchPage(movieEl).find('div.film-infor span:first-of-type')?.text();
|
||||
const path = searchPage(movieEl).attr('href');
|
||||
const name = searchPage(movieEl).find('h2.film-name a')?.text();
|
||||
const year = searchPage(movieEl).find('span.fdi-item:first')?.text();
|
||||
const path = searchPage(movieEl).find('h2.film-name a').attr('href');
|
||||
return { name, year, path };
|
||||
});
|
||||
|
||||
|
@ -89,21 +93,56 @@ export const goMoviesScraper = makeSourcerer({
|
|||
},
|
||||
});
|
||||
|
||||
const upcloudSource = await getSource(ctx, sources);
|
||||
const upcloudSource = await getSource(ctx, sources, 'upcloud');
|
||||
const vidcloudSource = await getSource(ctx, sources, 'vidcloud');
|
||||
const voeSource = await getSource(ctx, sources, 'voe');
|
||||
const doodSource = await getSource(ctx, sources, 'doodstream');
|
||||
const upstreamSource = await getSource(ctx, sources, 'upstream');
|
||||
const mixdropSource = await getSource(ctx, sources, 'mixdrop');
|
||||
|
||||
const embeds = [
|
||||
{
|
||||
embedId: upcloudScraper.id,
|
||||
url: upcloudSource?.link,
|
||||
},
|
||||
{
|
||||
embedId: vidCloudScraper.id,
|
||||
url: vidcloudSource?.link,
|
||||
},
|
||||
{
|
||||
embedId: voeScraper.id,
|
||||
url: voeSource?.link,
|
||||
},
|
||||
{
|
||||
embedId: doodScraper.id,
|
||||
url: doodSource?.link,
|
||||
},
|
||||
{
|
||||
embedId: upstreamScraper.id,
|
||||
url: upstreamSource?.link,
|
||||
},
|
||||
{
|
||||
embedId: mixdropScraper.id,
|
||||
url: mixdropSource?.link,
|
||||
},
|
||||
];
|
||||
|
||||
const filteredEmbeds = embeds
|
||||
.filter((embed) => embed.url)
|
||||
.map((embed) => ({
|
||||
embedId: embed.embedId,
|
||||
url: embed.url as string,
|
||||
}));
|
||||
|
||||
if (filteredEmbeds.length === 0) throw new Error('No valid embeds found.');
|
||||
|
||||
return {
|
||||
embeds: [
|
||||
{
|
||||
embedId: upcloudScraper.id,
|
||||
url: upcloudSource.link,
|
||||
},
|
||||
],
|
||||
embeds: filteredEmbeds,
|
||||
};
|
||||
},
|
||||
async scrapeMovie(ctx) {
|
||||
const search = await ctx.proxiedFetcher<string>(`ajax/search`, {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams({ keyword: ctx.media.title }),
|
||||
const search = await ctx.proxiedFetcher(`/search/${ctx.media.title.replaceAll(/[^a-z0-9A-Z]/g, '-')}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
},
|
||||
|
@ -111,12 +150,12 @@ export const goMoviesScraper = makeSourcerer({
|
|||
});
|
||||
|
||||
const searchPage = load(search);
|
||||
const mediaElements = searchPage('a.nav-item');
|
||||
const mediaElements = searchPage('div.film-detail');
|
||||
|
||||
const mediaData = mediaElements.toArray().map((movieEl) => {
|
||||
const name = searchPage(movieEl).find('h3.film-name')?.text();
|
||||
const year = searchPage(movieEl).find('div.film-infor span:first-of-type')?.text();
|
||||
const path = searchPage(movieEl).attr('href');
|
||||
const name = searchPage(movieEl).find('h2.film-name a')?.text();
|
||||
const year = searchPage(movieEl).find('span.fdi-item:first')?.text();
|
||||
const path = searchPage(movieEl).find('h2.film-name a').attr('href');
|
||||
return { name, year, path };
|
||||
});
|
||||
|
||||
|
@ -136,15 +175,51 @@ export const goMoviesScraper = makeSourcerer({
|
|||
baseUrl: gomoviesBase,
|
||||
});
|
||||
|
||||
const upcloudSource = await getSource(ctx, sources);
|
||||
const upcloudSource = await getSource(ctx, sources, 'upcloud');
|
||||
const vidcloudSource = await getSource(ctx, sources, 'vidcloud');
|
||||
const voeSource = await getSource(ctx, sources, 'voe');
|
||||
const doodSource = await getSource(ctx, sources, 'doodstream');
|
||||
const upstreamSource = await getSource(ctx, sources, 'upstream');
|
||||
const mixdropSource = await getSource(ctx, sources, 'mixdrop');
|
||||
|
||||
const embeds = [
|
||||
{
|
||||
embedId: upcloudScraper.id,
|
||||
url: upcloudSource?.link,
|
||||
},
|
||||
{
|
||||
embedId: vidCloudScraper.id,
|
||||
url: vidcloudSource?.link,
|
||||
},
|
||||
{
|
||||
embedId: voeScraper.id,
|
||||
url: voeSource?.link,
|
||||
},
|
||||
{
|
||||
embedId: doodScraper.id,
|
||||
url: doodSource?.link,
|
||||
},
|
||||
{
|
||||
embedId: upstreamScraper.id,
|
||||
url: upstreamSource?.link,
|
||||
},
|
||||
{
|
||||
embedId: mixdropScraper.id,
|
||||
url: mixdropSource?.link,
|
||||
},
|
||||
];
|
||||
|
||||
const filteredEmbeds = embeds
|
||||
.filter((embed) => embed.url)
|
||||
.map((embed) => ({
|
||||
embedId: embed.embedId,
|
||||
url: embed.url as string,
|
||||
}));
|
||||
|
||||
if (filteredEmbeds.length === 0) throw new Error('No valid embeds found.');
|
||||
|
||||
return {
|
||||
embeds: [
|
||||
{
|
||||
embedId: upcloudScraper.id,
|
||||
url: upcloudSource.link,
|
||||
},
|
||||
],
|
||||
embeds: filteredEmbeds,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
import { load } from 'cheerio';
|
||||
|
||||
import { ScrapeContext } from '@/utils/context';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
|
||||
import { gomoviesBase } from '.';
|
||||
|
||||
export async function getSource(ctx: ScrapeContext, sources: any) {
|
||||
const upcloud = load(sources)('a[title*="upcloud" i]');
|
||||
export async function getSource(ctx: ScrapeContext, sources: any, title: string) {
|
||||
const source = load(sources)(`a[title*=${title} i]`);
|
||||
|
||||
const upcloudDataId = upcloud?.attr('data-id') ?? upcloud?.attr('data-linkid');
|
||||
const sourceDataId = source?.attr('data-id') ?? source?.attr('data-linkid');
|
||||
|
||||
if (!upcloudDataId) throw new NotFoundError('Upcloud source not available');
|
||||
if (!sourceDataId) return undefined;
|
||||
|
||||
const upcloudSource = await ctx.proxiedFetcher<{
|
||||
const sourceData = await ctx.proxiedFetcher<{
|
||||
type: 'iframe' | string;
|
||||
link: string;
|
||||
sources: [];
|
||||
title: string;
|
||||
tracks: [];
|
||||
}>(`/ajax/sources/${upcloudDataId}`, {
|
||||
}>(`/ajax/sources/${sourceDataId}`, {
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
},
|
||||
baseUrl: gomoviesBase,
|
||||
});
|
||||
|
||||
if (!upcloudSource.link || upcloudSource.type !== 'iframe') throw new NotFoundError('No upcloud stream found');
|
||||
if (!sourceData.link || sourceData.type !== 'iframe') return undefined;
|
||||
|
||||
return upcloudSource;
|
||||
return sourceData;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue