3 changed files with 192 additions and 0 deletions
@ -0,0 +1,169 @@
@@ -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); |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
<title>movie-web</title> |
||||
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script> |
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@6.4.6"></script> |
||||
<script src="https://unpkg.com/json5@^2.0.0/dist/index.min.js"></script> |
||||
<script src="assets/js/index.js"></script> |
||||
</head> |
||||
<body> |
||||
<div id='errorContainer'> |
||||
<h2 id='error'></h2> |
||||
</div> |
||||
|
||||
<input id="search" placeholder="Find movie..."><!-- |
||||
--><button onclick=findMovie()>find movie</button> |
||||
|
||||
<video id="video" controls autoplay style="width: 80%"></video> |
||||
</body> |
||||
</html> |
Loading…
Reference in new issue