contentapi.ts
Version:
Nodejs library that provides high-level APIs for obtaining information on various entertainment media such as books, movies, comic books, anime, manga, and so on.
472 lines • 25.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const cheerio_1 = require("cheerio");
const models_1 = require("../../models");
const extractors_1 = require("../../extractors");
class SFlix extends models_1.MovieParser {
constructor() {
super(...arguments);
this.name = 'SFlix';
this.baseUrl = 'https://sflix.to';
this.logo = 'https://img.sflix.to/xxrz/100x100/100/a2/33/a233d4c4a1426ca77ec1d34deec62f71/a233d4c4a1426ca77ec1d34deec62f71.png';
this.classPath = 'MOVIES.SFlix';
this.supportedTypes = new Set([models_1.TvType.MOVIE, models_1.TvType.TVSERIES]);
/**
*
* @param query search query string
* @param page page number (default 1) (optional)
*/
this.search = async (query, page = 1) => {
const searchResult = {
currentPage: page,
hasNextPage: false,
results: [],
};
try {
const { data } = await this.client.get(`${this.baseUrl}/search/${query.replace(/[\W_]+/g, '-')}?page=${page}`);
const $ = (0, cheerio_1.load)(data);
const navSelector = 'div.pre-pagination:nth-child(3) > nav:nth-child(1) > ul:nth-child(1)';
searchResult.hasNextPage =
$(navSelector).length > 0 ? !$(navSelector).children().last().hasClass('active') : false;
$('.film_list-wrap > div.flw-item').each((i, el) => {
var _a;
const releaseDate = $(el).find('div.film-detail > div.fd-infor > span:nth-child(1)').text();
searchResult.results.push({
id: (_a = $(el).find('div.film-poster > a').attr('href')) === null || _a === void 0 ? void 0 : _a.slice(1),
title: $(el).find('div.film-detail > h2 > a').attr('title'),
url: `${this.baseUrl}${$(el).find('div.film-poster > a').attr('href')}`,
image: $(el).find('div.film-poster > img').attr('data-src'),
releaseDate: isNaN(parseInt(releaseDate)) ? undefined : releaseDate,
seasons: releaseDate.includes('SS') ? parseInt(releaseDate.split('SS')[1]) : undefined,
type: $(el).find('div.film-detail > div.fd-infor > span:nth-child(2)').text() === 'Movie'
? models_1.TvType.MOVIE
: models_1.TvType.TVSERIES,
});
});
return searchResult;
}
catch (err) {
throw new Error(err.message);
}
};
/**
*
* @param mediaId media link or id
*/
this.fetchMediaInfo = async (mediaId) => {
var _a;
if (!mediaId.startsWith(this.baseUrl)) {
mediaId = `${this.baseUrl}/${mediaId}`;
}
const movieInfo = {
id: mediaId.split('to/').pop(),
title: '',
url: mediaId,
};
try {
const { data } = await this.client.get(mediaId);
const $ = (0, cheerio_1.load)(data);
const recommendationsArray = [];
$('div.container > section.block_area > div.block_area-content > div.film_list-wrap > div.flw-item').each((i, el) => {
var _a, _b, _c;
recommendationsArray.push({
id: (_a = $(el).find('div.film-poster > a').attr('href')) === null || _a === void 0 ? void 0 : _a.slice(1),
title: $(el).find('div.film-detail > h3.film-name > a').text(),
image: $(el).find('div.film-poster > img').attr('data-src'),
duration: (_b = $(el).find('div.film-detail > div.fd-infor > span.fdi-duration').text().replace('m', '')) !== null && _b !== void 0 ? _b : null,
type: $(el).find('div.film-detail > div.fd-infor > span.fdi-item').eq(1).text().trim().toLowerCase() ===
'tv'
? models_1.TvType.TVSERIES
: (_c = models_1.TvType.MOVIE) !== null && _c !== void 0 ? _c : null,
});
});
const uid = $('.detail_page-watch').attr('data-id');
movieInfo.cover = (_a = $('.cover_follow').attr('style')) === null || _a === void 0 ? void 0 : _a.slice(22).replace(')', '').replace(';', '');
movieInfo.title = $('.heading-name > a:nth-child(1)').text();
movieInfo.image = $('.dp-i-c-poster > div:nth-child(1) > img:nth-child(1)').attr('src');
movieInfo.description = $('.description')
.text()
.replace(/^Overview:\s*/i, '')
.replace(/\s+/g, ' ')
.trim();
movieInfo.type = movieInfo.id.split('/')[0] === 'tv' ? models_1.TvType.TVSERIES : models_1.TvType.MOVIE;
movieInfo.releaseDate = $('div.row > div.col-xl-5 .row-line')
.eq(0)
.text()
.replace('Released: ', '')
.trim();
movieInfo.genres = $('div.row >div.col-xl-5 .row-line')
.eq(1)
.find('a')
.map((i, el) => $(el).text().split('&'))
.get()
.map(v => v.trim());
movieInfo.casts = $('div.row > div.col-xl-5 .row-line')
.eq(2)
.find('a')
.map((i, el) => $(el).text())
.get();
movieInfo.tags = $('div.row-tags > h2')
.map((i, el) => $(el).text().replace(/\s+/g, ' ').trim())
.get();
movieInfo.production = $('div.row > div.col-xl-6 .row-line')
.eq(2)
.find('a')
.map((i, el) => $(el).text().trim())
.get()
.join(', ');
movieInfo.country = $('div.row > div.col-xl-6 .row-line').eq(1).find('a').text().trim();
movieInfo.duration = $('div.row > div.col-xl-6 .row-line')
.eq(0)
.text()
.replace('Duration: ', '')
.replace(/\s+/g, ' ')
.trim();
movieInfo.rating = parseFloat($('div.film-stats > div.fs-item > span.imdb').text().replace('IMDB: ', ''));
movieInfo.recommendations = recommendationsArray;
const ajaxReqUrl = (id, type, isSeasons = false) => `${this.baseUrl}/ajax/${type === 'movie' ? type : `v2/${type}`}/${isSeasons ? 'seasons' : 'episodes'}/${id}`;
if (movieInfo.type === models_1.TvType.TVSERIES) {
const { data } = await this.client.get(ajaxReqUrl(uid, 'tv', true));
const $$ = (0, cheerio_1.load)(data);
const seasonsIds = $$('.dropdown-menu > a')
.map((i, el) => $(el).attr('data-id'))
.get();
movieInfo.episodes = [];
let season = 1;
for (const id of seasonsIds) {
const { data } = await this.client.get(ajaxReqUrl(id, 'season'));
const $$$ = (0, cheerio_1.load)(data);
$$$('.swiper-container > .swiper-wrapper > .swiper-slide')
.map((i, el) => {
var _a;
const episode = {
id: $$$(el).find('div.flw-item').attr('id').split('-')[1],
image: $$$(el).find('div.flw-item > a > img').attr('src'),
title: $$$(el).find('div.flw-item > a > img').attr('title'),
number: parseInt($$$(el).find('div.flw-item > a > img').attr('title').split(':')[0].slice(8).trim()),
season: season,
url: `${this.baseUrl}/ajax/v2/episode/servers/${$$$(el).find('div.flw-item').attr('id').split('-')[1]}`,
};
(_a = movieInfo.episodes) === null || _a === void 0 ? void 0 : _a.push(episode);
})
.get();
season++;
}
}
else {
movieInfo.episodes = [
{
id: uid,
title: movieInfo.title,
url: `${this.baseUrl}/ajax/movie/episodes/${uid}`,
},
];
}
return movieInfo;
}
catch (err) {
console.log(err, 'err');
throw new Error(err.message);
}
};
/**
*
* @param episodeId episode id
* @param mediaId media id
* @param server server type (default `VidCloud`) (optional)
*/
this.fetchEpisodeSources = async (episodeId, mediaId, server = models_1.StreamingServers.UpCloud) => {
if (episodeId.startsWith('http')) {
const serverUrl = new URL(episodeId);
switch (server) {
case models_1.StreamingServers.Voe:
return {
headers: { Referer: serverUrl.href },
...(await new extractors_1.Voe(this.proxyConfig, this.adapter).extract(serverUrl)),
};
case models_1.StreamingServers.VidCloud:
return {
headers: { Referer: serverUrl.href },
...(await new extractors_1.VidCloud(this.proxyConfig, this.adapter).extract(serverUrl, true)),
};
case models_1.StreamingServers.UpCloud:
return {
headers: { Referer: serverUrl.href },
...(await new extractors_1.VidCloud(this.proxyConfig, this.adapter).extract(serverUrl)),
};
default:
return {
headers: { Referer: serverUrl.href },
sources: await new extractors_1.MixDrop(this.proxyConfig, this.adapter).extract(serverUrl),
};
}
}
try {
const servers = await this.fetchEpisodeServers(episodeId, mediaId);
const i = servers.findIndex(s => s.name === server);
if (i === -1) {
throw new Error(`Server ${server} not found`);
}
const { data } = await this.client.get(`${this.baseUrl}/ajax/get_link/${servers[i].url.split('.').slice(-1).shift()}`);
const serverUrl = new URL(data.link);
return await this.fetchEpisodeSources(serverUrl.href, mediaId, server);
}
catch (err) {
console.log(err, 'err');
throw new Error(err.message);
}
};
/**
*
* @param episodeId takes episode link or movie id
* @param mediaId takes movie link or id (found on movie info object)
*/
this.fetchEpisodeServers = async (episodeId, mediaId) => {
if (!episodeId.startsWith(this.baseUrl + '/ajax') && !mediaId.includes('movie'))
episodeId = `${this.baseUrl}/ajax/v2/episode/servers/${episodeId}`;
else
episodeId = `${this.baseUrl}/ajax/movie/episodes/${episodeId}`;
try {
const { data } = await this.client.get(episodeId);
const $ = (0, cheerio_1.load)(data);
const servers = $('.ulclear > li')
.map((i, el) => {
const server = {
name: mediaId.includes('movie')
? $(el).find('a').find('span').text().trim().toLowerCase()
: $(el).find('a').find('span').text().trim().toLowerCase(),
url: `${this.baseUrl}/${mediaId}.${!mediaId.includes('movie') ? $(el).find('a').attr('data-id') : $(el).find('a').attr('data-id')}`.replace(!mediaId.includes('movie') ? /\/tv\// : /\/movie\//, !mediaId.includes('movie') ? '/watch-tv/' : '/watch-movie/'),
};
return server;
})
.get();
return servers;
}
catch (err) {
throw new Error(err.message);
}
};
this.fetchRecentMovies = async () => {
try {
const { data } = await this.client.get(`${this.baseUrl}/home`);
const $ = (0, cheerio_1.load)(data);
const movies = $('section.block_area:contains("Latest Movies") > div:nth-child(2) > div:nth-child(1) > div.flw-item')
.map((i, el) => {
var _a;
const releaseDate = $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text();
const movie = {
id: (_a = $(el).find('div.film-poster > a').attr('href')) === null || _a === void 0 ? void 0 : _a.slice(1),
title: $(el).find('div.film-detail > h3.film-name > a').attr('title'),
url: `${this.baseUrl}${$(el).find('div.film-poster > a').attr('href')}`,
image: $(el).find('div.film-poster > img').attr('data-src'),
releaseDate: isNaN(parseInt(releaseDate)) ? undefined : releaseDate,
rating: $(el).find('div.film-detail > div.fd-infor > span:nth-child(1)').text() || null,
type: models_1.TvType.MOVIE,
};
return movie;
})
.get();
return movies;
}
catch (err) {
throw new Error(err.message);
}
};
this.fetchRecentTvShows = async () => {
try {
const { data } = await this.client.get(`${this.baseUrl}/home`);
const $ = (0, cheerio_1.load)(data);
const tvshows = $('section.block_area:contains("Latest TV Shows") > div:nth-child(2) > div:nth-child(1) > div.flw-item')
.map((i, el) => {
var _a;
const tvshow = {
id: (_a = $(el).find('div.film-poster > a').attr('href')) === null || _a === void 0 ? void 0 : _a.slice(1),
title: $(el).find('div.film-detail > h3.film-name > a').attr('title'),
url: `${this.baseUrl}${$(el).find('div.film-poster > a').attr('href')}`,
image: $(el).find('div.film-poster > img').attr('data-src'),
season: $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text().split(':')[0] || null,
latestEpisode: $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text().split(':')[1] || null,
type: models_1.TvType.TVSERIES,
};
return tvshow;
})
.get();
return tvshows;
}
catch (err) {
throw new Error(err.message);
}
};
this.fetchTrendingMovies = async () => {
try {
const { data } = await this.client.get(`${this.baseUrl}/home`);
const $ = (0, cheerio_1.load)(data);
const movies = $('div#trending-movies div.film_list-wrap div.flw-item')
.map((i, el) => {
var _a;
const releaseDate = $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text();
const movie = {
id: (_a = $(el).find('div.film-poster > a').attr('href')) === null || _a === void 0 ? void 0 : _a.slice(1),
title: $(el).find('div.film-detail > h3.film-name > a').attr('title'),
url: `${this.baseUrl}${$(el).find('div.film-poster > a').attr('href')}`,
image: $(el).find('div.film-poster > img').attr('data-src'),
releaseDate: isNaN(parseInt(releaseDate)) ? undefined : releaseDate,
rating: $(el).find('div.film-detail > div.fd-infor > span:nth-child(1)').text() || null,
type: models_1.TvType.MOVIE,
};
return movie;
})
.get();
return movies;
}
catch (err) {
throw new Error(err.message);
}
};
this.fetchTrendingTvShows = async () => {
try {
const { data } = await this.client.get(`${this.baseUrl}/home`);
const $ = (0, cheerio_1.load)(data);
const tvshows = $('div#trending-tv div.film_list-wrap div.flw-item')
.map((i, el) => {
var _a;
const tvshow = {
id: (_a = $(el).find('div.film-poster > a').attr('href')) === null || _a === void 0 ? void 0 : _a.slice(1),
title: $(el).find('div.film-detail > h3.film-name > a').attr('title'),
url: `${this.baseUrl}${$(el).find('div.film-poster > a').attr('href')}`,
image: $(el).find('div.film-poster > img').attr('data-src'),
season: $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text().split(':')[0] || null,
latestEpisode: $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text().split(':')[1] || null,
type: models_1.TvType.TVSERIES,
};
return tvshow;
})
.get();
return tvshows;
}
catch (err) {
throw new Error(err.message);
}
};
this.fetchByCountry = async (country, page = 1) => {
const result = {
currentPage: page,
hasNextPage: false,
results: [],
};
const navSelector = 'div.pre-pagination:nth-child(3) > nav:nth-child(1) > ul:nth-child(1)';
try {
const { data } = await this.client.get(`${this.baseUrl}/country/${country}/?page=${page}`);
const $ = (0, cheerio_1.load)(data);
result.hasNextPage =
$(navSelector).length > 0 ? !$(navSelector).children().last().hasClass('active') : false;
$('div.container > section.block_area > div.block_area-content > div.film_list-wrap > div.flw-item')
.each((i, el) => {
var _a, _b, _c, _d, _e, _f;
const resultItem = {
id: (_b = (_a = $(el).find('div.film-poster > a').attr('href')) === null || _a === void 0 ? void 0 : _a.slice(1)) !== null && _b !== void 0 ? _b : '',
title: (_c = $(el).find('div.film-detail > h2.film-name > a').attr('title')) !== null && _c !== void 0 ? _c : '',
url: `${this.baseUrl}${$(el).find('div.film-poster > a').attr('href')}`,
image: $(el).find('div.film-poster > img').attr('data-src'),
type: ((_d = $(el).find('div.film-poster > a').attr('href')) === null || _d === void 0 ? void 0 : _d.slice(1).split('/')[0].toLowerCase()) === 'movie'
? models_1.TvType.MOVIE
: models_1.TvType.TVSERIES,
};
const season = (_e = $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text().split(':')[0]) !== null && _e !== void 0 ? _e : null;
const latestEpisode = (_f = $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text().split(':')[1]) !== null && _f !== void 0 ? _f : null;
if (resultItem.type === models_1.TvType.TVSERIES) {
resultItem.season = season;
resultItem.latestEpisode = latestEpisode;
}
else {
resultItem.rating = $(el).find('div.film-detail > div.fd-infor > span:nth-child(1)').text();
resultItem.releaseDate = $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text();
}
result.results.push(resultItem);
})
.get();
return result;
}
catch (err) {
throw new Error(err.message);
}
};
this.fetchByGenre = async (genre, page = 1) => {
const result = {
currentPage: page,
hasNextPage: false,
results: [],
};
try {
const { data } = await this.client.get(`${this.baseUrl}/genre/${genre}?page=${page}`);
const $ = (0, cheerio_1.load)(data);
const navSelector = 'div.pre-pagination:nth-child(3) > nav:nth-child(1) > ul:nth-child(1)';
result.hasNextPage =
$(navSelector).length > 0 ? !$(navSelector).children().last().hasClass('active') : false;
$('.film_list-wrap > div.flw-item')
.each((i, el) => {
var _a, _b, _c, _d, _e, _f;
const resultItem = {
id: (_b = (_a = $(el).find('div.film-poster > a').attr('href')) === null || _a === void 0 ? void 0 : _a.slice(1)) !== null && _b !== void 0 ? _b : '',
title: (_c = $(el).find('div.film-detail > h2.film-name > a').attr('title')) !== null && _c !== void 0 ? _c : '',
url: `${this.baseUrl}${$(el).find('div.film-poster > a').attr('href')}`,
image: $(el).find('div.film-poster > img').attr('data-src'),
type: ((_d = $(el).find('div.film-poster > a').attr('href')) === null || _d === void 0 ? void 0 : _d.slice(1).split('/')[0].toLowerCase()) === 'movie'
? models_1.TvType.MOVIE
: models_1.TvType.TVSERIES,
};
const season = (_e = $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text().split(':')[0]) !== null && _e !== void 0 ? _e : null;
const latestEpisode = (_f = $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text().split(':')[1]) !== null && _f !== void 0 ? _f : null;
if (resultItem.type === models_1.TvType.TVSERIES) {
resultItem.season = season;
resultItem.latestEpisode = latestEpisode;
}
else {
resultItem.rating = $(el).find('div.film-detail > div.fd-infor > span:nth-child(1)').text();
resultItem.releaseDate = $(el).find('div.film-detail > div.fd-infor > span:nth-child(3)').text();
}
result.results.push(resultItem);
})
.get();
return result;
}
catch (err) {
throw new Error(err.message);
}
};
this.fetchSpotlight = async () => {
try {
const results = { results: [] };
const { data } = await this.client.get(`${this.baseUrl}/home`);
const $ = (0, cheerio_1.load)(data);
$('div.swiper-slide').each((i, el) => {
var _a, _b;
results.results.push({
id: (_a = $(el).find('a').attr('href')) === null || _a === void 0 ? void 0 : _a.slice(1),
title: $(el).find('a').attr('title'),
url: `${this.baseUrl}${$(el).find('a').attr('href')}`,
cover: $(el).find('div.slide-photo > a > img').attr('src'),
rating: $(el).find('.scd-item:nth-child(1)').text().trim(),
description: $(el).find('.sc-desc').text().trim(),
type: ((_b = $(el).find('a').attr('href')) === null || _b === void 0 ? void 0 : _b.split('/')[1]) === 'movie' ? models_1.TvType.MOVIE : models_1.TvType.TVSERIES,
});
});
return results;
}
catch (err) {
console.error(err);
throw new Error(err.message);
}
};
}
}
// (async () => {
// const movie = new SFlix();
// // const search = await movie.search('the flash');
// // const movieInfo = await movie.fetchEpisodeSources('1168337', 'tv/watch-vincenzo-67955');
// // const recentTv = await movie.fetchTrendingTvShows();
// const genre = await movie.fetchSpotlight()
// console.log(genre)
// })();
exports.default = SFlix;
//# sourceMappingURL=sflix.js.map