Add kissasian scraper

This commit is contained in:
2023-09-15 15:09:00 -05:00
parent 2d6a603b2b
commit a0637cc046
7 changed files with 163 additions and 2 deletions

View File

@@ -18,7 +18,7 @@ providers need to be ported to the new provider repo:
* [ ] superstream
* [x] flixhq
* [ ] gomovies
* [ ] kissasian
* [x] kissasian
* [x] remotestream
embeds:

View File

@@ -3,11 +3,12 @@ import { mp4uploadScraper } from '@/providers/embeds/mp4upload';
import { streamsbScraper } from '@/providers/embeds/streamsb';
import { upcloudScraper } from '@/providers/embeds/upcloud';
import { flixhqScraper } from '@/providers/sources/flixhq/index';
import { kissAsianScraper } from '@/providers/sources/kissasian/index';
import { remotestreamScraper } from '@/providers/sources/remotestream';
export function gatherAllSources(): Array<Sourcerer> {
// all sources are gathered here
return [flixhqScraper, remotestreamScraper];
return [flixhqScraper, remotestreamScraper, kissAsianScraper];
}
export function gatherAllEmbeds(): Array<Embed> {

View File

@@ -0,0 +1,15 @@
import { mp4uploadScraper } from '@/providers/embeds/mp4upload';
import { streamsbScraper } from '@/providers/embeds/streamsb';
export const kissasianBase = 'https://kissasian.li';
export const embedProviders = [
{
type: mp4uploadScraper.id,
id: 'mp',
},
{
type: streamsbScraper.id,
id: 'sb',
},
];

View File

@@ -0,0 +1,34 @@
import { load } from 'cheerio';
import { ScrapeContext } from '@/utils/context';
import { embedProviders, kissasianBase } from './common';
export async function getEmbeds(
ctx: ScrapeContext,
targetEpisode: {
number: string;
url?: string;
},
) {
let embeds = await Promise.all(
embedProviders.map(async (provider) => {
const watch = await ctx.fetcher<any>(`${kissasianBase}/${targetEpisode.url}&s=${provider.id}`);
const watchPage = load(watch);
const embedUrl = watchPage('iframe[id=my_video_1]').attr('src');
if (!embedUrl) throw new Error('Embed not found');
return {
embedId: provider.id,
url: embedUrl,
};
}),
);
embeds = embeds.filter((e) => !!e.url);
return embeds;
}

View File

@@ -0,0 +1,14 @@
import { CheerioAPI } from 'cheerio';
export async function getEpisodes(dramaPage: CheerioAPI) {
const episodesEl = dramaPage('tbody tr:not(:first-child)');
return episodesEl
.toArray()
.map((ep) => {
const number = dramaPage(ep).find('td.episodeSub a').text().split('Episode')[1]?.trim();
const url = dramaPage(ep).find('td.episodeSub a').attr('href');
return { number, url };
})
.filter((e) => !!e.url);
}

View File

@@ -0,0 +1,70 @@
import { load } from 'cheerio';
import { flags } from '@/main/targets';
import { makeSourcerer } from '@/providers/base';
import { NotFoundError } from '@/utils/errors';
import { getEmbeds } from './getEmbeds';
import { getEpisodes } from './getEpisodes';
import { search } from './search';
export const kissAsianScraper = makeSourcerer({
id: 'kissasian',
name: 'KissAsian',
rank: 130,
flags: [flags.NO_CORS],
async scrapeShow(ctx) {
const seasonNumber = ctx.media.season.number;
const episodeNumber = ctx.media.episode.number;
const dramas = await search(ctx, ctx.media.title, seasonNumber);
const targetDrama = dramas.find((d) => d.name?.toLowerCase() === ctx.media.title.toLowerCase()) ?? dramas[0];
if (!targetDrama) throw new Error('Drama not found');
ctx.progress(30);
const drama = await ctx.fetcher<any>(targetDrama.url);
const dramaPage = load(drama);
const episodes = await getEpisodes(dramaPage);
const targetEpisode = episodes.find((e) => e.number === `${episodeNumber}`);
if (!targetEpisode?.url) throw new NotFoundError('Episode not found');
ctx.progress(70);
const embeds = await getEmbeds(ctx, targetEpisode);
return {
embeds,
};
},
async scrapeMovie(ctx) {
const dramas = await search(ctx, ctx.media.title, undefined);
const targetDrama = dramas.find((d) => d.name?.toLowerCase() === ctx.media.title.toLowerCase()) ?? dramas[0];
if (!targetDrama) throw new Error('Drama not found');
ctx.progress(30);
const drama = await ctx.fetcher<any>(targetDrama.url);
const dramaPage = load(drama);
const episodes = await getEpisodes(dramaPage);
const targetEpisode = episodes[0];
if (!targetEpisode?.url) throw new NotFoundError('Episode not found');
ctx.progress(70);
const embeds = await getEmbeds(ctx, targetEpisode);
return {
embeds,
};
},
});

View File

@@ -0,0 +1,27 @@
import { load } from 'cheerio';
import FormData from 'form-data';
import { ScrapeContext } from '@/utils/context';
import { kissasianBase } from './common';
export async function search(ctx: ScrapeContext, title: string, seasonNumber?: number) {
const searchForm = new FormData();
searchForm.append('keyword', `${title} ${seasonNumber ?? ''}`.trim());
searchForm.append('type', 'Drama');
const searchResults = await ctx.fetcher<any>('/Search/SearchSuggest', {
baseUrl: kissasianBase,
method: 'POST',
body: searchForm,
});
const searchPage = load(searchResults);
return Array.from(searchPage('a')).map((drama) => {
return {
name: searchPage(drama).text(),
url: drama.attribs.href,
};
});
}