diff --git a/assets/css/style.css b/assets/css/style.css new file mode 100644 index 00000000..e69de29b diff --git a/assets/js/index.js b/assets/js/index.js new file mode 100644 index 00000000..8a1e751c --- /dev/null +++ b/assets/js/index.js @@ -0,0 +1,169 @@ +const cfg = { + base: "https://hidden-inlet-27205.herokuapp.com/https://lookmovie.io" +} + +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`; + } + + if (url) { + const videoOpts = await fetch(url).then((d) => d.json()); + + // Find video URL and return it (with a check for a full url if needed) + const opts = ["1080p", "1080", "720p", "720", "480p", "480", "auto"] + + let videoUrl = ""; + for (let res of opts) { + if (videoOpts[res] && !videoOpts[res].includes('dummy') && !videoOpts[res].includes('earth-1984') && !videoUrl) { + videoUrl = videoOpts[res] + } + } + + return videoUrl.startsWith("/") ? `${cfg.base}${videoUrl}` : 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`; + } + + const data = await fetch(url).then((d) => d.json()); + + const token = data?.data?.accessToken; + if (token) return token; + + return "Invalid type provided in 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()); + + let results = [ + ...movieSearchRes.result.map((v) => ({ ...v, type: "movie" })), + ...showSearchRes.result.map((v) => ({ ...v, type: "show" })), + ]; + + const fuse = new Fuse(results, { + threshold: 0.3, + distance: 200, + keys: ["title"], + }); + const matchedResults = fuse + .search(searchTerm.toString()) + .map((result) => result.item); + + let toShow; + if (matchedResults.length > 1) { + const response = window.prompt(`Pick a movie from:\n${matchedResults.map((i, v) => `${v}) ${i.title}`).join('\n')}`, 'Enter number'); + toShow = matchedResults[response]; + } else { + toShow = matchedResults[0]; + } + + if (!toShow) { + document.getElementById('error').innerHTML = 'Unable to find that, sorry!' + return; + } + + console.log(`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 pageReq = await fetch(url).then((d) => d.text()); + + // Extract and parse JSON + let scriptJson = + "{" + + pageReq + .slice(pageReq.indexOf(`${toShow.type}_storage`)) + .split("};")[0] + .split("= {")[1] + .trim() + + "}"; + + const data = JSON5.parse(scriptJson); + + // 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; + } + } + + // 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); + + 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); + } +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..a1d43324 --- /dev/null +++ b/index.html @@ -0,0 +1,23 @@ + + +
+ + + +