From 447ffe4a69bca8969aceaa54b46de8852bb58325 Mon Sep 17 00:00:00 2001
From: James Hawkins <jhawki2005@gmail.com>
Date: Thu, 30 Dec 2021 19:23:15 +0000
Subject: [PATCH] Add new source!

---
 .env                                          |   2 +-
 src/components/VideoElement.js                |   4 +-
 src/lib/index.js                              |  85 +++++++-------
 src/lib/scraper/gdriveplayer.js.disabled      | 111 ++++++++++++++++++
 .../{gomostream.js => gomostream.js.disabled} |   2 +
 src/lib/scraper/theflix.js                    |  70 +++++++++++
 src/lib/scraper/vmovee.js.disabled            |  84 +++++++++++++
 7 files changed, 312 insertions(+), 46 deletions(-)
 create mode 100644 src/lib/scraper/gdriveplayer.js.disabled
 rename src/lib/scraper/{gomostream.js => gomostream.js.disabled} (96%)
 create mode 100644 src/lib/scraper/theflix.js
 create mode 100644 src/lib/scraper/vmovee.js.disabled

diff --git a/.env b/.env
index 73026647..c4a4738f 100644
--- a/.env
+++ b/.env
@@ -1 +1 @@
-REACT_APP_CORS_PROXY_URL=https://proxy-1.movie-web.workers.dev?destination=
+REACT_APP_CORS_PROXY_URL=https://proxy-1.movie-web.workers.dev/?destination=
diff --git a/src/components/VideoElement.js b/src/components/VideoElement.js
index da4dc0e8..4a08fbe6 100644
--- a/src/components/VideoElement.js
+++ b/src/components/VideoElement.js
@@ -18,7 +18,7 @@ export function VideoElement({ streamUrl, loading, setProgress, videoRef, startT
     }
 
     React.useEffect(() => {
-        if (!streamUrl.endsWith('.mp4')) {
+        if (!streamUrl.includes('.mp4')) {
             setError(false)
             if (!videoRef || !videoRef.current || !streamUrl || streamUrl.length === 0 || loading) return;
             
@@ -46,7 +46,7 @@ export function VideoElement({ streamUrl, loading, setProgress, videoRef, startT
     if (!streamUrl || streamUrl.length === 0)
         return <VideoPlaceholder>No video selected</VideoPlaceholder>
 
-    if (!streamUrl.endsWith('.mp4')) {
+    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}` } />) }
diff --git a/src/lib/index.js b/src/lib/index.js
index 3174c2bd..f9adfc4d 100644
--- a/src/lib/index.js
+++ b/src/lib/index.js
@@ -1,44 +1,43 @@
-import lookMovie from './scraper/lookmovie';
-import gomostream from './scraper/gomostream';
-
-async function findContent(searchTerm, type) {
-    const results = { options: []};
-    const content = await Promise.all([
-        lookMovie.findContent(searchTerm, type),
-        gomostream.findContent(searchTerm, type)
-    ]);
-
-    content.forEach((o) => {
-        if (!o || !o.options) return;
-
-        o.options.forEach((i) => {
-            if (!i) return;
-            results.options.push(i)
-        })
-    });
-
-    return results;
-}
-
-async function getStreamUrl(slug, type, source, season, episode) {
-    switch (source) {
-        case 'lookmovie':
-            return await lookMovie.getStreamUrl(slug, type, season, episode);
-        case 'gomostream':
-            return await gomostream.getStreamUrl(slug, type, season, episode);
-        default:
-            return;
-    }
-}
-
-async function getEpisodes(slug, source) {
-    switch (source) {
-        case 'lookmovie':
-            return await lookMovie.getEpisodes(slug);
-        case 'gomostream':
-        default:
-            return;
-    }
-}
-
+import lookmovie from './scraper/lookmovie';
+import theflix from './scraper/theflix';
+
+async function findContent(searchTerm, type) {
+    const results = { options: []};
+    const content = await Promise.all([
+        lookmovie.findContent(searchTerm, type),
+        theflix.findContent(searchTerm, type)
+    ]);
+
+    content.forEach((o) => {
+        if (!o || !o.options) return;
+
+        o.options.forEach((i) => {
+            if (!i) return;
+            results.options.push(i)
+        })
+    });
+
+    return results;
+}
+
+async function getStreamUrl(slug, type, source, season, episode) {
+    switch (source) {
+        case 'lookmovie':
+            return await lookmovie.getStreamUrl(slug, type, season, episode);
+        case 'theflix':
+            return await theflix.getStreamUrl(slug, type, season, episode);
+        default:
+            return;
+    }
+}
+
+async function getEpisodes(slug, source) {
+    switch (source) {
+        case 'lookmovie':
+            return await lookmovie.getEpisodes(slug);
+        default:
+            return;
+    }
+}
+
 export { findContent, getStreamUrl, getEpisodes }
\ No newline at end of file
diff --git a/src/lib/scraper/gdriveplayer.js.disabled b/src/lib/scraper/gdriveplayer.js.disabled
new file mode 100644
index 00000000..0c206844
--- /dev/null
+++ b/src/lib/scraper/gdriveplayer.js.disabled
@@ -0,0 +1,111 @@
+// THIS SCRAPER DOES NOT CURRENTLY WORK AND IS NOT IN USE
+
+const BASE_URL = `${process.env.REACT_APP_CORS_PROXY_URL}https://database.gdriveplayer.us`;
+const MOVIE_URL = `${process.env.REACT_APP_CORS_PROXY_URL}https://database.gdriveplayer.us/player.php`;
+const SHOW_URL = `${process.env.REACT_APP_CORS_PROXY_URL}https://series.databasegdriveplayer.co/player.php`;
+
+async function findContent(searchTerm, type) {
+    try {
+        if (type !== 'movie') return;
+
+        const term = searchTerm.toLowerCase()
+        const tmdbRes = await fetch(`${process.env.REACT_APP_CORS_PROXY_URL}https://www.themoviedb.org/search?query=${term}`).then(d => d.text());
+
+        const doc = new DOMParser().parseFromString(tmdbRes, 'text/html');
+        const nodes = Array.from(doc.querySelectorAll('div.results > div > div.wrapper'));
+        const results = nodes.slice(0, 10).map((node) => {
+            let type = node.querySelector('div.details > div.wrapper > div.title > div > a').getAttribute('data-media-type');
+            switch (type) {
+                case 'movie':
+                    type = 'movie';
+                    break;
+                case 'tv':
+                    type = 'show';
+                    // eslint-disable-next-line array-callback-return
+                    return;
+                case 'collection':
+                    // eslint-disable-next-line array-callback-return
+                    return;
+                default:
+                    break;
+            }
+
+            return {
+                type: type,
+                title: node.querySelector('div.details > div.wrapper > div.title > div > a').textContent,
+                year: node.querySelector('div.details > div.wrapper > div.title > span').textContent.trim().split(' ')[2],
+                slug: node.querySelector('div.details > div.wrapper > div.title > div > a').href.split('/')[4],
+                source: 'gdriveplayer'
+            }
+        });
+
+        if (results.length > 1) {
+            return { options: results };
+        } else {
+            return { options: [ results[0] ] }
+        }
+    } catch (err) {
+        console.error(err);
+        throw new Error(err)
+    }
+}
+
+async function getStreamUrl(slug, type, season, episode) {
+    if (type !== 'movie') return;
+
+    // const tmdbRes = await fetch(`${process.env.REACT_APP_CORS_PROXY_URL}https://www.themoviedb.org/search?query=${term}`).then(d => d.text());
+
+    console.log(`${MOVIE_URL}?tmdb=${slug}`)
+    const res = await fetch(`${MOVIE_URL}?tmdb=${slug}`).then(d => d.text());
+
+    const embed = Array.from(new DOMParser().parseFromString(res, 'text/html').querySelectorAll('.list-server-items a'))
+        .find((e) => e.textContent.includes("Mirror"))
+
+    if (embed && embed.getAttribute('href')) {
+        let href = embed.getAttribute('href');
+        if (href.startsWith('//')) href = `https:${href}`;
+
+        const res1 = await fetch(`${process.env.REACT_APP_CORS_PROXY_URL}${href}`.replace('streaming.php', 'download')).then(d => d.text());
+        const sb = Array.from(new DOMParser().parseFromString(res1, 'text/html').querySelectorAll('a'))
+            .find((a) => a.textContent.includes("StreamSB"));
+
+        console.log(sb);
+
+        if (sb && sb.getAttribute('href')) {
+            console.log(sb.getAttribute('href'))
+            const src = await sbPlayGetLink(sb.getAttribute('href'));
+            if (src) return { url: src };
+        }
+    }
+
+    return { url: '' }
+}
+
+async function sbPlayGetLink(href) {
+    if (href.startsWith("//")) href = `https:${href}`;
+
+    const res = await fetch(`${process.env.REACT_APP_CORS_PROXY_URL}${href}`).then(d => d.text());
+    const a = new DOMParser().parseFromString(res, 'text/html').querySelector('table tbody tr a');
+
+    if (a && a.getAttribute('onclick')) {
+        let match = a.getAttribute("onclick").match(/'([^']+)'/gm);
+        console.log(a.getAttribute("onclick"));
+
+        if (match) {
+            let [code, mode, hash] = match;
+
+            const url = `https://sbplay2.com/dl?op=download_orig&id=${code.replace(/'/gm, "")}&mode=${mode.replace(/'/gm, "")}&hash=${hash.replace(/'/gm, "")}`;
+            
+            // https://sbplay2.com/dl?op=download_orig&id=glr78kyk21kd&mode=n&hash=1890245-0-0-1640889479-95e144cdfdbe0e9104a67b8e3eee0c2d
+            // https://sbplay2.com/dl?op=download_orig&id=0hh6mxf5qqn0&mode=h&hash=2473604-78-149-1640889782-797bc207a16b2934c21ea6fdb1e97352
+            // https://proxy-1.movie-web.workers.dev/?destination=https://sbplay2.com/dl?op=download_orig&id=glr78kyk21kd&mode=n&hash=1890245-0-0-1640889479-95e144cdfdbe0e9104a67b8e3eee0c2d
+
+            const text = await fetch(url).then((e) => e.text());
+            const a = new DOMParser().parseFromString(text, 'text/html').querySelector(".contentbox span a");
+            if (a && a.getAttribute("href")) return a.getAttribute("href");
+        }
+    }
+}
+
+const gdriveplayer = { findContent, getStreamUrl }
+export default gdriveplayer;
\ No newline at end of file
diff --git a/src/lib/scraper/gomostream.js b/src/lib/scraper/gomostream.js.disabled
similarity index 96%
rename from src/lib/scraper/gomostream.js
rename to src/lib/scraper/gomostream.js.disabled
index f93eb171..6be4ec04 100644
--- a/src/lib/scraper/gomostream.js
+++ b/src/lib/scraper/gomostream.js.disabled
@@ -1,3 +1,5 @@
+// THIS SCRAPER DOES NOT CURRENTLY WORK AND IS NOT IN USE
+
 import { unpack } from '../util/unpacker';
 
 const BASE_URL = `${process.env.REACT_APP_CORS_PROXY_URL}https://gomo.to`;
diff --git a/src/lib/scraper/theflix.js b/src/lib/scraper/theflix.js
new file mode 100644
index 00000000..a27dc05c
--- /dev/null
+++ b/src/lib/scraper/theflix.js
@@ -0,0 +1,70 @@
+const BASE_URL = `${process.env.REACT_APP_CORS_PROXY_URL}https://www.theflix.to`;
+
+async function findContent(searchTerm, type) {
+    try {
+        if (type !== 'movie') return;
+
+        const term = searchTerm.toLowerCase()
+        const tmdbRes = await fetch(`${process.env.REACT_APP_CORS_PROXY_URL}https://www.themoviedb.org/search?query=${term}`).then(d => d.text());
+
+        const doc = new DOMParser().parseFromString(tmdbRes, 'text/html');
+        const nodes = Array.from(doc.querySelectorAll('div.results > div > div.wrapper'));
+        const results = nodes.slice(0, 10).map((node) => {
+            let type = node.querySelector('div.details > div.wrapper > div.title > div > a').getAttribute('data-media-type');
+            switch (type) {
+                case 'movie':
+                    type = 'movie';
+                    break;
+                case 'tv':
+                    type = 'show';
+                    // eslint-disable-next-line array-callback-return
+                    return;
+                case 'collection':
+                    // eslint-disable-next-line array-callback-return
+                    return;
+                default:
+                    break;
+            }
+
+            const title = node.querySelector('div.details > div.wrapper > div.title > div > a').textContent;
+            const year = node.querySelector('div.details > div.wrapper > div.title > span').textContent.trim().split(' ')[2];
+            const slug = node.querySelector('div.details > div.wrapper > div.title > div > a').getAttribute('href').split('/')[2];
+
+            return {
+                type: type,
+                title: title,
+                year: year,
+                slug: slug + '-' + title.replace(/[^a-z0-9]+|\s+/gmi, " ").replace(/\s+/g, '-').toLowerCase(),
+                source: 'theflix'
+            }
+        });
+
+        if (results.length > 1) {
+            return { options: results };
+        } else {
+            return { options: [ results[0] ] }
+        }
+    } catch (err) {
+        console.error(err);
+        throw new Error(err)
+    }
+}
+
+async function getStreamUrl(slug, type, season, episode) {
+    if (type !== 'movie') return;
+
+    const res = await fetch(`${BASE_URL}/${type}/${slug}?movieInfo=${slug}`).then(d => d.text());
+
+    const scripts = Array.from(new DOMParser().parseFromString(res, "text/html").querySelectorAll('script'));
+    const prop = scripts.find((e) => e.textContent.includes("theflixvd.b-cdn"));
+
+    if (prop) {
+        const data = JSON.parse(prop.textContent);
+        return { url: data.props.pageProps.videoUrl };
+    }
+
+    return { url: '' }
+}
+
+const theflix = { findContent, getStreamUrl }
+export default theflix;
\ No newline at end of file
diff --git a/src/lib/scraper/vmovee.js.disabled b/src/lib/scraper/vmovee.js.disabled
new file mode 100644
index 00000000..41039ea6
--- /dev/null
+++ b/src/lib/scraper/vmovee.js.disabled
@@ -0,0 +1,84 @@
+// THIS SCRAPER DOES NOT CURRENTLY WORK AND IS NOT IN USE
+
+import { unpack } from '../util/unpacker';
+
+const BASE_URL = `https://www.vmovee.watch`;
+const CORS_URL = `${process.env.REACT_APP_CORS_PROXY_URL}${BASE_URL}`;
+const SHOW_URL = `${CORS_URL}/series`
+const MOVIE_URL = `${CORS_URL}/movies`
+const MOVIE_URL_NO_CORS = `${BASE_URL}/movies`
+
+async function findContent(searchTerm, type) {
+    try {
+        if (type !== 'movie') return;
+
+        const searchUrl = `${CORS_URL}/?s=${encodeURIComponent(searchTerm)}`;
+        const searchRes = await fetch(searchUrl).then((d) => d.text());
+
+        const parser = new DOMParser();
+        const doc = parser.parseFromString(searchRes, "text/html");
+        const nodes = Array.from(doc.querySelectorAll('div.search-page > div.result-item > article'));
+        const results = nodes.map(node => {
+            const imgHolder = node.querySelector('div.image > div.thumbnail > a');
+            const titleHolder = node.querySelector('div.title > a');
+
+            return {
+                type: imgHolder.querySelector('span').textContent === 'TV' ? 'show' : 'movie',
+                title: titleHolder.textContent,
+                year: node.querySelector('div.details > div.meta > span.year').textContent,
+                slug: titleHolder.href.split('/')[4],
+                source: 'vmovee'
+            }
+        });
+
+        if (results.length > 1) {
+            return { options: results };
+        } else {
+            return { options: [ results[0] ] }
+        }
+    } catch (err) {
+        throw new Error(err)
+    }
+}
+
+async function getStreamUrl(slug, type, season, episode) {
+    let url = '';
+
+    if (type === 'movie') {
+        url = `${MOVIE_URL}/${slug}`;
+    } else if (type === 'show') {
+        url = `${SHOW_URL}/${slug}`;
+    }
+
+    const res1 = await fetch(url, { headers: new Headers().append('referer', `${BASE_URL}/dashboard/admin-ajax.php`) });
+    const id = res1.headers.get('link').split('>')[0].split('?p=')[1];
+
+    const res2Headers = new Headers().append('referer', `${BASE_URL}/dashboard/admin-ajax.php`);
+    const form = new FormData();
+    form.append('action', 'doo_player_ajax')
+    form.append('post', id)
+    form.append('nume', '2')
+    form.append('type', type)
+
+    const res2 = await fetch(`${CORS_URL}/dashboard/admin-ajax.php`, {
+        method: 'POST',
+        headers: res2Headers,
+        body: form
+    }).then((res) => res.json());
+    let realUrl = res2.embed_url;
+
+    console.log(res2)
+
+    if (realUrl.startsWith('//')) {
+        realUrl = `https:${realUrl}`;
+    }
+
+    const res3 = await fetch(`${process.env.REACT_APP_CORS_PROXY_URL}${realUrl}`);
+    res3.headers.forEach(console.log)
+
+    return { url: '' }
+
+}
+
+const vmovee = { findContent, getStreamUrl }
+export default vmovee;
\ No newline at end of file