mirror of
https://github.com/movie-web/providers.git
synced 2025-09-13 17:03:26 +00:00
Compare commits
2 Commits
master
...
c8b2ea3e81
Author | SHA1 | Date | |
---|---|---|---|
|
c8b2ea3e81 | ||
|
423c07cc56 |
@@ -19,6 +19,7 @@ import { kissAsianScraper } from '@/providers/sources/kissasian/index';
|
||||
import { lookmovieScraper } from '@/providers/sources/lookmovie';
|
||||
import { remotestreamScraper } from '@/providers/sources/remotestream';
|
||||
import { showboxScraper } from '@/providers/sources/showbox/index';
|
||||
import { tugaflixScraper } from '@/providers/sources/tugaflix';
|
||||
import { vidsrcScraper } from '@/providers/sources/vidsrc/index';
|
||||
import { zoechipScraper } from '@/providers/sources/zoechip';
|
||||
|
||||
@@ -66,6 +67,7 @@ export function gatherAllSources(): Array<Sourcerer> {
|
||||
warezcdnScraper,
|
||||
insertunitScraper,
|
||||
soaperTvScraper,
|
||||
tugaflixScraper,
|
||||
];
|
||||
}
|
||||
|
||||
|
21
src/providers/sources/tugaflix/common.ts
Normal file
21
src/providers/sources/tugaflix/common.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { load } from 'cheerio';
|
||||
|
||||
export const baseUrl = 'https://tugaflix.best/';
|
||||
|
||||
export function parseSearch(page: string): { title: string; year?: number; url: string }[] {
|
||||
const results: { title: string; year?: number; url: string }[] = [];
|
||||
const $ = load(page);
|
||||
|
||||
$('.items .poster').each((_, element) => {
|
||||
const $link = $(element).find('a');
|
||||
const url = $link.attr('href');
|
||||
// ex title: Home Alone (1990)
|
||||
const [, title, year] = $link.attr('title')?.match(/^(.*?)\s*(?:\((\d{4})\))?\s*$/) || [];
|
||||
if (!title || !url) return;
|
||||
|
||||
// tiles dont always have the year
|
||||
results.push({ title, year: year ? parseInt(year, 10) : undefined, url });
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
116
src/providers/sources/tugaflix/index.ts
Normal file
116
src/providers/sources/tugaflix/index.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import { load } from 'cheerio';
|
||||
|
||||
import { flags } from '@/entrypoint/utils/targets';
|
||||
import { SourcererEmbed, makeSourcerer } from '@/providers/base';
|
||||
import { compareMedia } from '@/utils/compare';
|
||||
import { NotFoundError } from '@/utils/errors';
|
||||
|
||||
import { baseUrl, parseSearch } from './common';
|
||||
|
||||
export const tugaflixScraper = makeSourcerer({
|
||||
id: 'tugaflix',
|
||||
name: 'Tugaflix',
|
||||
rank: 73,
|
||||
flags: [flags.IP_LOCKED],
|
||||
scrapeMovie: async (ctx) => {
|
||||
const searchResults = parseSearch(
|
||||
await ctx.proxiedFetcher<string>('/filmes/', {
|
||||
baseUrl,
|
||||
query: {
|
||||
s: ctx.media.title,
|
||||
},
|
||||
}),
|
||||
);
|
||||
if (searchResults.length === 0) throw new NotFoundError('No watchable item found');
|
||||
|
||||
const url = searchResults.find((x) => x && compareMedia(ctx.media, x.title, x.year))?.url;
|
||||
if (!url) throw new NotFoundError('No watchable item found');
|
||||
|
||||
const videoPage = await ctx.proxiedFetcher<string>(url, {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams({ play: '' }),
|
||||
});
|
||||
const $ = load(videoPage);
|
||||
|
||||
const embeds: SourcererEmbed[] = [];
|
||||
|
||||
for (const element of $('.play a')) {
|
||||
const embedUrl = $(element).attr('href');
|
||||
if (!embedUrl) continue;
|
||||
|
||||
const embedPage = await ctx.proxiedFetcher.full(
|
||||
embedUrl.startsWith('https://') ? embedUrl : `https://${embedUrl}`,
|
||||
);
|
||||
|
||||
const finalUrl = load(embedPage.body)('a:contains("Download Filme")').attr('href');
|
||||
if (!finalUrl) continue;
|
||||
|
||||
if (finalUrl.includes('streamtape')) {
|
||||
embeds.push({
|
||||
embedId: 'streamtape',
|
||||
url: finalUrl,
|
||||
});
|
||||
// found doodstream on a few shows, maybe movies use it too?
|
||||
// the player 2 is just streamtape in a custom player
|
||||
} else if (finalUrl.includes('dood')) {
|
||||
embeds.push({
|
||||
embedId: 'dood',
|
||||
url: finalUrl,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
embeds,
|
||||
};
|
||||
},
|
||||
scrapeShow: async (ctx) => {
|
||||
const searchResults = parseSearch(
|
||||
await ctx.proxiedFetcher<string>('/series/', {
|
||||
baseUrl,
|
||||
query: {
|
||||
s: ctx.media.title,
|
||||
},
|
||||
}),
|
||||
);
|
||||
if (searchResults.length === 0) throw new NotFoundError('No watchable item found');
|
||||
|
||||
const url = searchResults.find((x) => x && compareMedia(ctx.media, x.title, x.year))?.url;
|
||||
if (!url) throw new NotFoundError('No watchable item found');
|
||||
|
||||
const s = ctx.media.season.number < 10 ? `0${ctx.media.season.number}` : ctx.media.season.number.toString();
|
||||
const e = ctx.media.episode.number < 10 ? `0${ctx.media.episode.number}` : ctx.media.episode.number.toString();
|
||||
const videoPage = await ctx.proxiedFetcher(url, {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams({ [`S${s}E${e}`]: '' }),
|
||||
});
|
||||
|
||||
const embedUrl = load(videoPage)('iframe[name="player"]').attr('src');
|
||||
if (!embedUrl) throw new Error('Failed to find iframe');
|
||||
|
||||
const playerPage = await ctx.proxiedFetcher(embedUrl.startsWith('https:') ? embedUrl : `https:${embedUrl}`, {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams({ submit: '' }),
|
||||
});
|
||||
|
||||
const embeds: SourcererEmbed[] = [];
|
||||
|
||||
const finalUrl = load(playerPage)('a:contains("Download Episodio")').attr('href');
|
||||
|
||||
if (finalUrl?.includes('streamtape')) {
|
||||
embeds.push({
|
||||
embedId: 'streamtape',
|
||||
url: finalUrl,
|
||||
});
|
||||
} else if (finalUrl?.includes('dood')) {
|
||||
embeds.push({
|
||||
embedId: 'dood',
|
||||
url: finalUrl,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
embeds,
|
||||
};
|
||||
},
|
||||
});
|
Reference in New Issue
Block a user