diff --git a/assets/css/style.css b/assets/css/style.css index e69de29b..7801a75c 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -0,0 +1,59 @@ +@font-face { + font-family: 'JetBrainsMono'; + src: url(../fonts/JetBrainsMono-Regular.woff2); + font-weight: 400; + font-style: normal; +} + +html, body { + height: 1vh; +} + +body { + margin: 0; + color: #95979F; + background-color: #0c0e14; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%23586ca8' fill-opacity='0.12'%3E%3Cpath d='M0 38.59l2.83-2.83 1.41 1.41L1.41 40H0v-1.41zM0 1.4l2.83 2.83 1.41-1.41L1.41 0H0v1.41zM38.59 40l-2.83-2.83 1.41-1.41L40 38.59V40h-1.41zM40 1.41l-2.83 2.83-1.41-1.41L38.59 0H40v1.41zM20 18.6l2.83-2.83 1.41 1.41L21.41 20l2.83 2.83-1.41 1.41L20 21.41l-2.83 2.83-1.41-1.41L18.59 20l-2.83-2.83 1.41-1.41L20 18.59z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); + font-family: 'JetBrainsMono'; +} + +.messages { + background-color: #2D313D; + border-radius: 10px; + width: 80%; + padding-left: 10px; +} + +.error { + color: #f3565d; +} + +.info { + color: #2e5bbd; +} + +.content { + padding: 1rem; + border-radius: 10px; + background-color: #2D313D; + width: 80%; +} + +.video { + width: 100%; +} + +form { + background-color: #2D313D; + padding: 5px; + width: 300px; + text-align: center; +} + +input[type="submit"] { + width: 20%; +} + +input[type="text"] { + width: 70%; +} \ No newline at end of file diff --git a/assets/fonts/JetBrainsMono-Regular.woff2 b/assets/fonts/JetBrainsMono-Regular.woff2 new file mode 100644 index 00000000..80c62dd1 Binary files /dev/null and b/assets/fonts/JetBrainsMono-Regular.woff2 differ diff --git a/assets/js/index.js b/assets/js/index.js index 8a1e751c..b6431901 100644 --- a/assets/js/index.js +++ b/assets/js/index.js @@ -1,18 +1,12 @@ -const cfg = { - base: "https://hidden-inlet-27205.herokuapp.com/https://lookmovie.io" +function getCorsUrl(url) { + return `https://hidden-inlet-27205.herokuapp.com/${url}`; } async function getVideoUrl(config) { const accessToken = await getAccessToken(config); const now = Math.floor(Date.now() / 1e3); - let url = null; - - if (config.type === "tv") { - url = `${cfg.base}/manifests/shows/json/${accessToken}/${now}/${config.episodeId}/master.m3u8`; - } else if (config.type === "movie") { - url = `${cfg.base}/manifests/movies/json/${config.movieId}/${now}/${accessToken}/master.m3u8`; - } + let url = getCorsUrl(`https://lookmovie.io/manifests/movies/json/${config.movieId}/${now}/${accessToken}/master.m3u8`); if (url) { const videoOpts = await fetch(url).then((d) => d.json()); @@ -27,22 +21,14 @@ async function getVideoUrl(config) { } } - return videoUrl.startsWith("/") ? `${cfg.base}${videoUrl}` : videoUrl; + return videoUrl.startsWith("/") ? getCorsUrl(`https://lookmovie.io/${videoUrl}`) : getCorsUrl(videoUrl); } return "Invalid type."; } async function getAccessToken(config) { - let url = ""; - - if (config.type === "tv") { - // 'mbQFYTR499c9vfDmAwOFrg' // Retrieved from: https://lookmovie.io/api/v1/security/show-access?slug=1839578-person-of-interest-2011&token=&step=2 - url = `${cfg.base}/api/v1/security/show-access?slug=${config.slug}&token=&step=2`; - } else if (config.type === "movie") { - // https://lookmovie.io/api/v1/security/movie-access?id_movie=14358&token=1&sk=&step=1 - url = `${cfg.base}/api/v1/security/movie-access?id_movie=${config.movieId}&token=1&sk=&step=1`; - } + let url = getCorsUrl(`https://lookmovie.io/api/v1/security/movie-access?id_movie=${config.movieId}&token=1&sk=&step=1`); const data = await fetch(url).then((d) => d.json()); @@ -55,27 +41,13 @@ async function getAccessToken(config) { async function findMovie() { const searchTerm = document.getElementById('search').value; - const movieSearchRes = await fetch( - `https://hidden-inlet-27205.herokuapp.com/https://lookmovie.io/api/v1/movies/search/?q=${encodeURIComponent( - searchTerm - )}` - ).then((d) => d.json()); - const showSearchRes = await fetch( - `https://hidden-inlet-27205.herokuapp.com/https://lookmovie.io/api/v1/shows/search/?q=${encodeURIComponent( - searchTerm - )}` - ).then((d) => d.json()); + sendMessage('info', `Searching for "${searchTerm}"`) - let results = [ - ...movieSearchRes.result.map((v) => ({ ...v, type: "movie" })), - ...showSearchRes.result.map((v) => ({ ...v, type: "show" })), - ]; + const searchUrl = getCorsUrl(`https://lookmovie.io/api/v1/movies/search/?q=${encodeURIComponent(searchTerm)}`); + const searchRes = await fetch(searchUrl).then((d) => d.json()); + let results = [ ...searchRes.result.map((v) => ({ ...v, type: "movie" })) ]; - const fuse = new Fuse(results, { - threshold: 0.3, - distance: 200, - keys: ["title"], - }); + const fuse = new Fuse(results, { threshold: 0.3, distance: 200, keys: ["title"] }); const matchedResults = fuse .search(searchTerm.toString()) .map((result) => result.item); @@ -89,81 +61,46 @@ async function findMovie() { } if (!toShow) { - document.getElementById('error').innerHTML = 'Unable to find that, sorry!' + sendMessage('error', 'Unable to find that, sorry!') return; } - console.log(`Scraping the ${toShow.type} "${toShow.title}"`); + sendMessage('info', `Scraping the ${toShow.type} "${toShow.title}"`) - // ! Now we get the ID and stuff we need - const url = `https://hidden-inlet-27205.herokuapp.com/https://lookmovie.io/${toShow.type}s/view/${toShow.slug}`; + const url = getCorsUrl(`https://lookmovie.io/${toShow.type}s/view/${toShow.slug}`); const pageReq = await fetch(url).then((d) => d.text()); - // Extract and parse JSON - let scriptJson = - "{" + + const data = JSON5.parse("{" + pageReq .slice(pageReq.indexOf(`${toShow.type}_storage`)) .split("};")[0] .split("= {")[1] .trim() + - "}"; + "}" + ); - const data = JSON5.parse(scriptJson); + const videoUrl = await getVideoUrl({ + slug: toShow.slug, + movieId: data.id_movie, + type: "movie", + }); - // Find the relevant id - let id = null; - let relevantEpisode; - if (toShow.type === "movie") { - id = data.id_movie; - } else if (toShow.type === "show") { - const episodeObj = data.seasons.find((v) => { - return v.season == season && v.episode == episode; - }); - if (episodeObj) { - console.log( - `Finding streams for ${toShow.title} ${season}x${episode}: ${episodeObj.title}` - ); - id = episodeObj.id_episode; - relevantEpisode = episodeObj; - } - } + sendMessage('info', `Streaming "${toShow.title}"`) + streamVideo(videoUrl) +} - // Check ID - if (id === null) { - console.error(`Not found: S${season} E${episode}`); - return; - } - - // Generate object to send over to scraper - let reqObj = null; - if (toShow.type === "show") { - reqObj = { - slug: toShow.slug, - episodeId: id, - type: "tv", - }; - } else if (toShow.type === "movie") { - reqObj = { - slug: toShow.slug, - movieId: id, - type: "movie", - }; - } - - if (!reqObj) { - document.getElementById('error').innerHTML = 'Invalid type!' - return; - } - - const videoUrl = await getVideoUrl(reqObj); +function sendMessage(type, message) { + if (!['info', 'error'].includes(type)) return; + document.getElementById(type).innerHTML += `${message}
`; +} +function streamVideo(url) { var video = document.getElementById('video'); - var videoSrc = `https://hidden-inlet-27205.herokuapp.com/${videoUrl}`; + if (Hls.isSupported()) { var video = document.getElementById('video'); var hls = new Hls(); hls.attachMedia(video); - hls.loadSource(videoSrc); + hls.loadSource(url); } } \ No newline at end of file diff --git a/index.html b/index.html index a1d43324..9ec86391 100644 --- a/index.html +++ b/index.html @@ -5,19 +5,30 @@ movie-web + + + + -
-

+
+ +
+ +
+
- - - +
+ +

+

+
+
\ No newline at end of file