mirror of
https://github.com/movie-web/movie-web.git
synced 2024-12-24 19:11:49 +01:00
✨ feat: added xemovie as a scraper
breaking changes for lookmovie, cannot fix however due to lookmovie captcha
This commit is contained in:
parent
116a679736
commit
4c4719628c
@ -28,7 +28,7 @@ export function MovieRow(props) {
|
||||
return (
|
||||
<div className="movieRow" tabIndex={0} onKeyPress={handleKeyPress} onClick={() => props.onClick && props.onClick()}>
|
||||
|
||||
{ props.source === "lookmovie" && (
|
||||
{ (props.source === "lookmovie" || props.source === "xemovie") && (
|
||||
<div className="subtitleIcon">
|
||||
<svg id="subtitleIcon" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20 4H4C2.897 4 2 4.897 2 6V18C2 19.103 2.897 20 4 20H20C21.103 20 22 19.103 22 18V6C22 4.897 21.103 4 20 4ZM11 10H8V14H11V16H8C6.897 16 6 15.103 6 14V10C6 8.897 6.897 8 8 8H11V10ZM18 10H15V14H18V16H15C13.897 16 13 15.103 13 14V10C13 8.897 13.897 8 15 8H18V10Z" fill="#EEEEEE"/>
|
||||
|
@ -48,14 +48,14 @@ export function VideoElement({ streamUrl, loading, setProgress, videoRef, startT
|
||||
|
||||
if (!streamUrl.includes('.mp4')) {
|
||||
return (
|
||||
<video crossOrigin="anonymous" className="videoElement" ref={videoRef} controls autoPlay onProgress={setProgress} onLoadedData={onLoad}>
|
||||
{ streamData.subtitles && streamData.subtitles.map((sub, index) => <track key={index} kind="captions" label={sub.language} src={`${process.env.REACT_APP_CORS_PROXY_URL}https://lookmovie.io${sub.file}` } />) }
|
||||
<video className="videoElement" ref={videoRef} controls autoPlay onProgress={setProgress} onLoadedData={onLoad}>
|
||||
{ streamData.subtitles && streamData.subtitles.map((sub, index) => <track key={index} kind="captions" label={sub.language} src={sub.file} />) }
|
||||
</video>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<video crossOrigin="anonymous" className="videoElement" ref={videoRef} controls autoPlay onProgress={setProgress} onLoadedData={onLoad}>
|
||||
{ streamData.subtitles && streamData.subtitles.map((sub, index) => <track key={index} kind="captions" label={sub.language} src={`${process.env.REACT_APP_CORS_PROXY_URL}https://lookmovie.io${sub.file}` } />) }
|
||||
<video className="videoElement" ref={videoRef} controls autoPlay onProgress={setProgress} onLoadedData={onLoad}>
|
||||
{ streamData.subtitles && streamData.subtitles.map((sub, index) => <track key={index} kind="captions" label={sub.language} src={sub.file} />) }
|
||||
<source src={streamUrl} type="video/mp4" />
|
||||
</video>
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
import lookmovie from './scraper/lookmovie';
|
||||
import xemovie from './scraper/xemovie';
|
||||
import theflix from './scraper/theflix';
|
||||
import vidzstore from './scraper/vidzstore';
|
||||
|
||||
@ -6,6 +7,7 @@ async function findContent(searchTerm, type) {
|
||||
const results = { options: []};
|
||||
const content = await Promise.all([
|
||||
// lookmovie.findContent(searchTerm, type),
|
||||
xemovie.findContent(searchTerm, type),
|
||||
theflix.findContent(searchTerm, type),
|
||||
vidzstore.findContent(searchTerm, type)
|
||||
]);
|
||||
@ -30,6 +32,8 @@ async function getStreamUrl(slug, type, source, season, episode) {
|
||||
return await theflix.getStreamUrl(slug, type, season, episode);
|
||||
case 'vidzstore':
|
||||
return await vidzstore.getStreamUrl(slug);
|
||||
case 'xemovie':
|
||||
return await xemovie.getStreamUrl(slug, type, season, episode);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@ -41,6 +45,8 @@ async function getEpisodes(slug, source) {
|
||||
return await lookmovie.getEpisodes(slug);
|
||||
case 'theflix':
|
||||
return await theflix.getEpisodes(slug);
|
||||
case 'xemovie':
|
||||
return await xemovie.getEpisodes(slug);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ async function getStreamUrl(slug) {
|
||||
const res = await fetch(url).then(d => d.text());
|
||||
const DOM = new DOMParser().parseFromString(res, "text/html");
|
||||
|
||||
return { url: `${process.env.REACT_APP_CORS_PROXY_URL}${DOM.querySelector("source").src}` };
|
||||
return { url: DOM.querySelector("source").src };
|
||||
}
|
||||
|
||||
const vidzstore = { findContent, getStreamUrl }
|
||||
|
92
src/lib/scraper/xemovie.js
Normal file
92
src/lib/scraper/xemovie.js
Normal file
@ -0,0 +1,92 @@
|
||||
const BASE_URL = `${process.env.REACT_APP_CORS_PROXY_URL}https://xemovie.co`;
|
||||
|
||||
async function findContent(searchTerm, type) {
|
||||
try {
|
||||
let results;
|
||||
|
||||
const searchUrl = `${BASE_URL}/search?q=${encodeURIComponent(searchTerm)}`;
|
||||
const searchRes = await fetch(searchUrl).then((d) => d.text());
|
||||
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(searchRes, "text/html");
|
||||
switch (type) {
|
||||
case 'show':
|
||||
// const showContainer = doc.querySelectorAll(".py-10")[1].querySelector(".grid");
|
||||
// const showNodes = [...showContainer.querySelectorAll("a")].filter(link => !link.className);
|
||||
// results = showNodes.map(node => {
|
||||
// node = node.parentElement
|
||||
// return {
|
||||
// type,
|
||||
// title: [...new Set(node.innerText.split("\n"))][1].split("(")[0].trim(),
|
||||
// year: [...new Set(node.innerText.split("\n"))][3],
|
||||
// slug: node.querySelector("a").href.split('/').pop(),
|
||||
// source: "xemovie"
|
||||
// }
|
||||
// })
|
||||
// break;
|
||||
return { options: [] };
|
||||
case 'movie':
|
||||
const movieContainer = doc.querySelectorAll(".py-10")[0].querySelector(".grid");
|
||||
const movieNodes = [...movieContainer.querySelectorAll("a")].filter(link => !link.className);
|
||||
results = movieNodes.map(node => {
|
||||
node = node.parentElement
|
||||
return {
|
||||
type,
|
||||
title: [...new Set(node.innerText.split("\n"))][1].split("(")[0].trim(),
|
||||
year: [...new Set(node.innerText.split("\n"))][3],
|
||||
slug: node.querySelector("a").href.split('/').pop(),
|
||||
source: "xemovie"
|
||||
}
|
||||
})
|
||||
break;
|
||||
default:
|
||||
results = [];
|
||||
break;
|
||||
}
|
||||
|
||||
return { options: results };
|
||||
} catch {
|
||||
return { options: [] };
|
||||
}
|
||||
}
|
||||
|
||||
async function getStreamUrl(slug, type, season, episode) {
|
||||
let url;
|
||||
|
||||
if (type === "show") {
|
||||
|
||||
} else {
|
||||
url = `${BASE_URL}/movies/${slug}/watch`;
|
||||
}
|
||||
|
||||
let mediaUrl = "";
|
||||
let subtitles = [];
|
||||
|
||||
const res = await fetch(url).then(d => d.text());
|
||||
const DOM = new DOMParser().parseFromString(res, "text/html");
|
||||
|
||||
for (const script of DOM.scripts) {
|
||||
if (script.textContent.match(/https:\/\/s[0-9]\.xemovie\.com/)) {
|
||||
// eslint-disable-next-line
|
||||
let data = JSON.parse(JSON.stringify(eval(`(${script.textContent.replace("const data = ", "").split("};")[0]}})`)));
|
||||
// eslint-disable-next-line
|
||||
mediaUrl = data.playlist[0].file;
|
||||
// eslint-disable-next-line
|
||||
for (const subtitleTrack of data.playlist[0].tracks) {
|
||||
const subtitleBlob = URL.createObjectURL(await fetch(`${process.env.REACT_APP_CORS_PROXY_URL}${subtitleTrack.file}`).then(res => res.blob())); // do this so no need for CORS errors
|
||||
subtitles.push({
|
||||
file: subtitleBlob,
|
||||
language: subtitleTrack.label
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return { url: mediaUrl, subtitles: subtitles }
|
||||
}
|
||||
|
||||
async function getEpisodes(slug) {
|
||||
|
||||
}
|
||||
|
||||
const xemovie = { findContent, getStreamUrl, getEpisodes }
|
||||
export default xemovie;
|
Loading…
Reference in New Issue
Block a user