mirror of
https://github.com/movie-web/movie-web.git
synced 2024-12-25 08:21:52 +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 (
|
return (
|
||||||
<div className="movieRow" tabIndex={0} onKeyPress={handleKeyPress} onClick={() => props.onClick && props.onClick()}>
|
<div className="movieRow" tabIndex={0} onKeyPress={handleKeyPress} onClick={() => props.onClick && props.onClick()}>
|
||||||
|
|
||||||
{ props.source === "lookmovie" && (
|
{ (props.source === "lookmovie" || props.source === "xemovie") && (
|
||||||
<div className="subtitleIcon">
|
<div className="subtitleIcon">
|
||||||
<svg id="subtitleIcon" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<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"/>
|
<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')) {
|
if (!streamUrl.includes('.mp4')) {
|
||||||
return (
|
return (
|
||||||
<video crossOrigin="anonymous" className="videoElement" ref={videoRef} controls autoPlay onProgress={setProgress} onLoadedData={onLoad}>
|
<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={`${process.env.REACT_APP_CORS_PROXY_URL}https://lookmovie.io${sub.file}` } />) }
|
{ streamData.subtitles && streamData.subtitles.map((sub, index) => <track key={index} kind="captions" label={sub.language} src={sub.file} />) }
|
||||||
</video>
|
</video>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<video crossOrigin="anonymous" className="videoElement" ref={videoRef} controls autoPlay onProgress={setProgress} onLoadedData={onLoad}>
|
<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={`${process.env.REACT_APP_CORS_PROXY_URL}https://lookmovie.io${sub.file}` } />) }
|
{ streamData.subtitles && streamData.subtitles.map((sub, index) => <track key={index} kind="captions" label={sub.language} src={sub.file} />) }
|
||||||
<source src={streamUrl} type="video/mp4" />
|
<source src={streamUrl} type="video/mp4" />
|
||||||
</video>
|
</video>
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import lookmovie from './scraper/lookmovie';
|
import lookmovie from './scraper/lookmovie';
|
||||||
|
import xemovie from './scraper/xemovie';
|
||||||
import theflix from './scraper/theflix';
|
import theflix from './scraper/theflix';
|
||||||
import vidzstore from './scraper/vidzstore';
|
import vidzstore from './scraper/vidzstore';
|
||||||
|
|
||||||
@ -6,6 +7,7 @@ async function findContent(searchTerm, type) {
|
|||||||
const results = { options: []};
|
const results = { options: []};
|
||||||
const content = await Promise.all([
|
const content = await Promise.all([
|
||||||
// lookmovie.findContent(searchTerm, type),
|
// lookmovie.findContent(searchTerm, type),
|
||||||
|
xemovie.findContent(searchTerm, type),
|
||||||
theflix.findContent(searchTerm, type),
|
theflix.findContent(searchTerm, type),
|
||||||
vidzstore.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);
|
return await theflix.getStreamUrl(slug, type, season, episode);
|
||||||
case 'vidzstore':
|
case 'vidzstore':
|
||||||
return await vidzstore.getStreamUrl(slug);
|
return await vidzstore.getStreamUrl(slug);
|
||||||
|
case 'xemovie':
|
||||||
|
return await xemovie.getStreamUrl(slug, type, season, episode);
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -41,6 +45,8 @@ async function getEpisodes(slug, source) {
|
|||||||
return await lookmovie.getEpisodes(slug);
|
return await lookmovie.getEpisodes(slug);
|
||||||
case 'theflix':
|
case 'theflix':
|
||||||
return await theflix.getEpisodes(slug);
|
return await theflix.getEpisodes(slug);
|
||||||
|
case 'xemovie':
|
||||||
|
return await xemovie.getEpisodes(slug);
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ async function getStreamUrl(slug) {
|
|||||||
const res = await fetch(url).then(d => d.text());
|
const res = await fetch(url).then(d => d.text());
|
||||||
const DOM = new DOMParser().parseFromString(res, "text/html");
|
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 }
|
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