diff --git a/src/components/TypeSelector.js b/src/components/TypeSelector.js index 05f545e3..2af819f4 100644 --- a/src/components/TypeSelector.js +++ b/src/components/TypeSelector.js @@ -1,5 +1,4 @@ import React from 'react'; -// import { Arrow } from './Arrow'; import './TypeSelector.css' // setType: (txt: string) => void diff --git a/src/lib/gomostream.js b/src/lib/gomostream.js index fc88e899..9c81036f 100644 --- a/src/lib/gomostream.js +++ b/src/lib/gomostream.js @@ -1,11 +1,11 @@ -import { unpacker } from './unpacker'; +import { unpack } from './unpacker'; const CORS_URL = 'https://hidden-inlet-27205.herokuapp.com/'; const BASE_URL = `${CORS_URL}https://gomo.to`; const MOVIE_URL = `${BASE_URL}/movie` const DECODING_URL = `${BASE_URL}/decoding_v3.php` -async function findContentGomo(searchTerm, type) { +async function findContent(searchTerm, type) { try { if (type !== 'movie') return; @@ -29,17 +29,13 @@ async function findContentGomo(searchTerm, type) { } else { return { options: [results[0]] } } - - // const movieId = imdbRes.d[0]?.id - // if (!movieId) return; - } catch (err) { console.log(err); throw new Error(err) } } -async function getStreamUrlGomo(slug, type, season, episode) { +async function getStreamUrl(slug, type, season, episode) { if (type !== 'movie') return; // Get stream to go with IMDB ID @@ -67,7 +63,7 @@ async function getStreamUrlGomo(slug, type, season, episode) { const site2Dom = parser.parseFromString(site2, "text/html"); const script = site2Dom.querySelectorAll("script")[8].innerHTML; - let unpacked = unpacker.unpack(script).split(''); + let unpacked = unpack(script).split(''); unpacked.splice(0, 43); let index = unpacked.findIndex((e) => e === '"'); const url = unpacked.slice(0, index).join(''); @@ -75,4 +71,4 @@ async function getStreamUrlGomo(slug, type, season, episode) { return { url } } -export { findContentGomo, getStreamUrlGomo } \ No newline at end of file +export { findContent, getStreamUrl } \ No newline at end of file diff --git a/src/lib/index.js b/src/lib/index.js new file mode 100644 index 00000000..7e1ccfc9 --- /dev/null +++ b/src/lib/index.js @@ -0,0 +1,16 @@ +import lookMovie from './lookMovie'; +// import gomostream from './gomostream'; + +async function findContent(searchTerm, type) { + return await lookMovie.findContent(searchTerm, type); +} + +async function getStreamUrl(slug, type, season, episode) { + return await lookMovie.getStreamUrl(slug, type, season, episode); +} + +async function getEpisodes(slug) { + return await lookMovie.getEpisodes(slug); +} + +export { findContent, getStreamUrl, getEpisodes } \ No newline at end of file diff --git a/src/lib/lookMovie.js b/src/lib/lookMovie.js index 55047c33..7bd0c8fb 100644 --- a/src/lib/lookMovie.js +++ b/src/lib/lookMovie.js @@ -66,12 +66,12 @@ async function getEpisodes(slug) { "}" ); - let seasons, episodes = []; - - data.forEach((e) => { + let seasons = []; + let episodes = []; + data.seasons.forEach((e) => { if (!seasons.includes(e.season)) seasons.push(e.season); - + if (!episodes[e.season]) episodes[e.season] = [] episodes[e.season].push(e.episode) @@ -96,14 +96,14 @@ async function getStreamUrl(slug, type, season, episode) { let id = ''; if (type === "movie") { - id = data.id_movie; - } else if (type === "show") { - const episodeObj = data.seasons.find((v) => { return v.season === season && v.episode === episode; }); + id = data.id_movie; + } else if (type === "show") { + const episodeObj = data.seasons.find((v) => { return v.season === season && v.episode === episode; }); if (episodeObj) { - id = episodeObj.id_episode; - } - } + id = episodeObj.id_episode; + } + } if (id === '') { return { url: '' } @@ -118,11 +118,10 @@ async function getStreamUrl(slug, type, season, episode) { return { url: videoUrl } } -async function findContent(searchTerm, type) { - // const searchUrl = getCorsUrl(`https://lookmovie.io/api/v1/${type}s/search/?q=${encodeURIComponent(searchTerm)}`); +async function findContent(searchTerm, type) { const searchUrl = getCorsUrl(`https://lookmovie.io/${type}s/search/?q=${encodeURIComponent(searchTerm)}`); const searchRes = await fetch(searchUrl).then((d) => d.text()); - + // Parse DOM to find search results on full search page const parser = new DOMParser(); const doc = parser.parseFromString(searchRes, "text/html"); @@ -147,7 +146,7 @@ async function findContent(searchTerm, type) { if (matchedResults.length > 1) { const res = { options: [] }; - + matchedResults.forEach((r) => res.options.push({ title: r.title, slug: r.slug, @@ -158,11 +157,12 @@ async function findContent(searchTerm, type) { return res; } else { const { title, slug, type, year } = matchedResults[0]; - + return { options: [{ title, slug, type, year }] } } } -export { findContent, getStreamUrl, getEpisodes }; \ No newline at end of file +const lookMovie = { findContent, getStreamUrl, getEpisodes }; +export default lookMovie; \ No newline at end of file diff --git a/src/lib/unpacker.js b/src/lib/unpacker.js index 7031bb4b..da7e1e51 100644 --- a/src/lib/unpacker.js +++ b/src/lib/unpacker.js @@ -1,46 +1,53 @@ -/* port of https://github.com/beautify-web/js-beautify/blob/master/python/jsbeautifier/unpackers/packer.py (MIT) */ -const unpacker = { - unpack: function (str) { - var params = unpacker.filterargs(str); - var payload = params[0], symtab = params[1], radix = params[2], count = params[3]; - if (count !== symtab.length) { - throw new Error("Malformed p.a.c.k.e.r. symtab. (" + count + " != " + symtab.length + ")"); - } - var unbase = unpacker.unbaser(radix); - var lookup = (word) => symtab[unbase(word)] || word; - var source = payload.replace(/\b\w+\b/g, lookup); - return source; - }, - filterargs: function(str) { - /* [\s\S] insteadof . because javascript has no dotall modifier */ - var juicers = [ - /}\('([\s\S]*)', *(\d+), *(\d+), *'([\s\S]*)'\.split\('\|'\), *(\d+), *([\s\S]*)\)\)/, - /}\('([\s\S]*)', *(\d+), *(\d+), *'([\s\S]*)'\.split\('\|'\)/ - ]; - for (var c = 0; c < juicers.length; ++c) { - var m, juicer = juicers[c]; - // eslint-disable-next-line no-cond-assign - if (m = juicer.exec(str)) { - return [m[1], m[4].split('|'), parseInt(m[2]), parseInt(m[3])]; - } - } - throw new Error("Could not make sense of p.a.c.k.e.r data (unexpected code structure)"); - }, - alphabet: { - 62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", - 95: '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~' - }, - unbaser: function(base) - { - if (2 <= base <= 36) return (str) => parseInt(str, base); - var dictionary = {}; - var alphabet = unpacker.alphabet[base]; - if (!alphabet) throw new Error("Unsupported encoding"); - for (var c = 0; c < alphabet.length; ++alphabet) { - dictionary[alphabet[c]] = c; - } - return (str) => str.split("").reverse().reduce((cipher, ind) => Math.pow(base, ind) * dictionary[cipher]); - } +const alphabet = { + 62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + 95: '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~' }; -export { unpacker }; \ No newline at end of file +function _filterargs(str) { + var juicers = [ + /}\('([\s\S]*)', *(\d+), *(\d+), *'([\s\S]*)'\.split\('\|'\), *(\d+), *([\s\S]*)\)\)/, + /}\('([\s\S]*)', *(\d+), *(\d+), *'([\s\S]*)'\.split\('\|'\)/ + ]; + + for (var c = 0; c < juicers.length; ++c) { + var m, juicer = juicers[c]; + + // eslint-disable-next-line no-cond-assign + if (m = juicer.exec(str)) { + return [m[1], m[4].split('|'), parseInt(m[2]), parseInt(m[3])]; + } + } + + throw new Error("Could not make sense of p.a.c.k.e.r data (unexpected code structure)"); +} + +function _unbaser(base) { + if (2 <= base <= 36) return (str) => parseInt(str, base); + + const dictionary = {}; + var alpha = alphabet[base]; + if (!alpha) throw new Error("Unsupported encoding"); + + for (let c = 0; c < alpha.length; ++alpha) { + dictionary[alpha[c]] = c; + } + + return (str) => str.split("").reverse().reduce((cipher, ind) => Math.pow(base, ind) * dictionary[cipher]); +} + +function unpack(str) { + var params = _filterargs(str); + var payload = params[0], symtab = params[1], radix = params[2], count = params[3]; + + if (count !== symtab.length) { + throw new Error("Malformed p.a.c.k.e.r. symtab. (" + count + " != " + symtab.length + ")"); + } + + var unbase = _unbaser(radix); + var lookup = (word) => symtab[unbase(word)] || word; + var source = payload.replace(/\b\w+\b/g, lookup); + + return source; +} + +export { unpack }; \ No newline at end of file diff --git a/src/views/Movie.js b/src/views/Movie.js index ac8db275..7e7d9c74 100644 --- a/src/views/Movie.js +++ b/src/views/Movie.js @@ -4,8 +4,9 @@ import { Card } from '../components/Card' import { useMovie } from '../hooks/useMovie' import { VideoElement } from '../components/VideoElement' import { EpisodeSelector } from '../components/EpisodeSelector' +import { getStreamUrl } from '../lib/index' + import './Movie.css' -import { getStreamUrl } from '../lib/lookMovie' export function MovieView(props) { const { streamUrl, streamData, setStreamUrl } = useMovie(); diff --git a/src/views/Search.js b/src/views/Search.js index 75104a0e..2dd5aedb 100644 --- a/src/views/Search.js +++ b/src/views/Search.js @@ -1,17 +1,16 @@ import React from 'react'; -import { InputBox } from '../components/InputBox' -import { Title } from '../components/Title' -import { Card } from '../components/Card' -import { ErrorBanner } from '../components/ErrorBanner' -import { MovieRow } from '../components/MovieRow' -import { Arrow } from '../components/Arrow' -import { Progress } from '../components/Progress' -import { findContent, getStreamUrl, getEpisodes } from '../lib/lookMovie' -// import { findContentGomo, getStreamUrlGomo } from '../lib/gomostream'; +import { InputBox } from '../components/InputBox'; +import { Title } from '../components/Title'; +import { Card } from '../components/Card'; +import { ErrorBanner } from '../components/ErrorBanner'; +import { MovieRow } from '../components/MovieRow'; +import { Arrow } from '../components/Arrow'; +import { Progress } from '../components/Progress'; +import { findContent, getStreamUrl, getEpisodes } from '../lib/index'; import { useMovie } from '../hooks/useMovie'; -import { TypeSelector } from '../components/TypeSelector' +import { TypeSelector } from '../components/TypeSelector'; -import './Search.css' +import './Search.css'; export function SearchView() { const { navigate, setStreamUrl, setStreamData } = useMovie(); @@ -68,6 +67,7 @@ export function SearchView() { setText(`Streaming...`) navigate("movie") } catch (err) { + console.error(err); fail("Failed to get stream") } }