You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.4 KiB
119 lines
3.4 KiB
import { |
|
MWMediaProvider, |
|
MWMediaType, |
|
MWPortableMedia, |
|
MWMediaStream, |
|
MWQuery, |
|
MWMediaSeasons, |
|
MWProviderMediaResult, |
|
} from "@/providers/types"; |
|
|
|
import { |
|
searchTheFlix, |
|
getDataFromSearch, |
|
turnDataIntoMedia, |
|
} from "@/providers/list/theflix/search"; |
|
|
|
import { getDataFromPortableSearch } from "@/providers/list/theflix/portableToMedia"; |
|
import { conf } from "@/config"; |
|
|
|
export const theFlixScraper: MWMediaProvider = { |
|
id: "theflix", |
|
enabled: false, |
|
type: [MWMediaType.MOVIE, MWMediaType.SERIES], |
|
displayName: "theflix", |
|
|
|
async getMediaFromPortable( |
|
media: MWPortableMedia |
|
): Promise<MWProviderMediaResult> { |
|
const data: any = await getDataFromPortableSearch(media); |
|
|
|
return { |
|
...media, |
|
year: new Date(data.releaseDate).getFullYear().toString(), |
|
title: data.name, |
|
}; |
|
}, |
|
|
|
async searchForMedia(query: MWQuery): Promise<MWProviderMediaResult[]> { |
|
const searchRes = await searchTheFlix(query); |
|
const searchData = await getDataFromSearch(searchRes, 10); |
|
|
|
const results: MWProviderMediaResult[] = []; |
|
for (const item of searchData) { |
|
results.push(turnDataIntoMedia(item)); |
|
} |
|
|
|
return results; |
|
}, |
|
|
|
async getStream(media: MWPortableMedia): Promise<MWMediaStream> { |
|
let url = ""; |
|
|
|
if (media.mediaType === MWMediaType.MOVIE) { |
|
url = `${conf().CORS_PROXY_URL}https://theflix.to/movie/${ |
|
media.mediaId |
|
}?movieInfo=${media.mediaId}`; |
|
} else if (media.mediaType === MWMediaType.SERIES) { |
|
url = `${conf().CORS_PROXY_URL}https://theflix.to/tv-show/${ |
|
media.mediaId |
|
}/season-${media.seasonId}/episode-${media.episodeId}`; |
|
} |
|
|
|
const res = await fetch(url).then((d) => d.text()); |
|
|
|
const prop: HTMLElement | undefined = Array.from( |
|
new DOMParser() |
|
.parseFromString(res, "text/html") |
|
.querySelectorAll("script") |
|
).find((e) => e.textContent?.includes("theflixvd.b-cdn")); |
|
|
|
if (!prop || !prop.textContent) { |
|
throw new Error("Could not find stream"); |
|
} |
|
|
|
const data = JSON.parse(prop.textContent); |
|
|
|
return { url: data.props.pageProps.videoUrl, type: "mp4", captions: [] }; |
|
}, |
|
|
|
async getSeasonDataFromMedia( |
|
media: MWPortableMedia |
|
): Promise<MWMediaSeasons> { |
|
const url = `${conf().CORS_PROXY_URL}https://theflix.to/tv-show/${ |
|
media.mediaId |
|
}/season-${media.seasonId}/episode-${media.episodeId}`; |
|
const res = await fetch(url).then((d) => d.text()); |
|
|
|
const node: Element = Array.from( |
|
new DOMParser() |
|
.parseFromString(res, "text/html") |
|
.querySelectorAll(`script[id="__NEXT_DATA__"]`) |
|
)[0]; |
|
|
|
let data = JSON.parse(node.innerHTML).props.pageProps.selectedTv.seasons; |
|
|
|
data = data.filter((season: any) => season.releaseDate != null); |
|
data = data.map((season: any) => { |
|
const episodes = season.episodes.filter( |
|
(episode: any) => episode.releaseDate != null |
|
); |
|
return { ...season, episodes }; |
|
}); |
|
|
|
return { |
|
seasons: data.map((d: any) => ({ |
|
sort: d.seasonNumber === 0 ? 999 : d.seasonNumber, |
|
id: d.seasonNumber.toString(), |
|
type: d.seasonNumber === 0 ? "special" : "season", |
|
title: d.name, |
|
episodes: d.episodes.map((e: any) => ({ |
|
title: e.name, |
|
sort: e.episodeNumber, |
|
id: e.episodeNumber.toString(), |
|
episodeNumber: e.episodeNumber, |
|
})), |
|
})), |
|
}; |
|
}, |
|
};
|
|
|