- 掃描 ID:
- dbedf7dd-fbe1-4b47-9e59-3a933d92f56d已完成
- 已提交的 URL:
- https://novastream.top/
- 報告完成時間:
連結 · 找到 3 個
從頁面中識別的傳出連結
連結 | Text |
---|---|
https://ko-fi.com/ambrosial | |
https://github.com/ambr0sial/nova | |
https://pastebin.com/raw/5kqU1Up8 | About |
JavaScript 變數 · 找到 5 個
在頁面的視窗物件上載入的全域 JavaScript 變數是在函數外部宣告的變數,可從目前範圍內程式碼中的任何位置存取
名稱 | 類型 |
---|---|
onbeforetoggle | object |
documentPictureInPicture | object |
onscrollend | object |
tailwind | object |
/template.html | string |
主控台記錄訊息 · 找到 1 條
記錄到 Web 主控台的訊息
類型 | 類別 | 記錄 |
---|---|---|
warning | other |
|
HTML
頁面的原始 HTML 主體
<!DOCTYPE html><html><head>
<meta charset="UTF-8">
<title>Nova</title>
<link rel="icon" type="image/x-icon" href="https://raw.githubusercontent.com/ambr0sial/nova/main/logo.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
<meta content="Nova" property="og:title">
<meta content="Click, watch, enjoy. Nova breaks down the paywall, ensuring that quality content is accessible to everyone." property="og:description">
<meta content="https://novastream.top" property="og:url">
<meta content="https://raw.githubusercontent.com/ambr0sial/nova/main/logo.png" property="og:image">
<meta content="#A17FC0" data-react-helmet="true" name="theme-color">
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
background-color: #2D132C;
background-image: linear-gradient(135deg, #2D132C 0%, #4A0D67 100%);
color: white;
font-family: 'Poppins', sans-serif;
}
#selectedMovie{
display:flex;
gap:1rem;
}
.rounded {
border-radius: 0.5rem;
}
.hover\:scale-105:hover {
transform: scale(1.05);
}
.focus\:outline-none:focus {
outline: none;
}
.focus\:ring-2:focus {
box-shadow: 0 0 0 2px rgba(139, 92, 246, 0.5);
}
#loginPage {
background-color: rgba(31, 41, 55, 0.8);
}
#searchSuggestions {
z-index: 10;
}
#githubButton, #kofiButton {
position: fixed;
top: 10px;
right: 10px;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.8);
padding: 5px;
border-radius: 50%;
}
#githubButton img, #kofiButton img {
width: 32px;
height: 32px;
border-radius: 50%;
}
#githubButton:hover, #kofiButton:hover {
background-color: rgba(0, 0, 0, 1);
}
#kofiButton {
right: 60px;
}
@media (min-width: 768px) {
#selectedMovie {
flex-direction: row;
gap: 2rem;
}
#upcomingMedia {
margin-left: 0;
}
}
.container {
max-width: 100%;
padding-left: 1rem;
padding-right: 1rem;
margin-left: auto;
margin-right: auto;
}
</style>
<style>*, ::before, ::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/* ! tailwindcss v3.4.16 | MIT License | https://tailwindcss.com */*,::after,::before{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}::after,::before{--tw-content:''}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-y-0{top:0px;bottom:0px}.bottom-0{bottom:0px}.left-0{left:0px}.right-0{right:0px}.float-right{float:right}.mx-2{margin-left:0.5rem;margin-right:0.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-4{margin-bottom:1rem}.mb-8{margin-bottom:2rem}.ml-0{margin-left:0px}.mr-1{margin-right:0.25rem}.mt-1{margin-top:0.25rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-8{height:2rem}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-8{width:2rem}.w-full{width:100%}.max-w-lg{max-width:32rem}.flex-1{flex:1 1 0%}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1, minmax(0, 1fr))}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-4{gap:1rem}.space-y-4 > :not([hidden]) ~ :not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6 > :not([hidden]) ~ :not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.rounded{border-radius:0.25rem}.rounded-lg{border-radius:0.5rem}.rounded-b-lg{border-bottom-right-radius:0.5rem;border-bottom-left-radius:0.5rem}.rounded-l{border-top-left-radius:0.25rem;border-bottom-left-radius:0.25rem}.rounded-r{border-top-right-radius:0.25rem;border-bottom-right-radius:0.25rem}.border{border-width:1px}.border-zinc-700{--tw-border-opacity:1;border-color:rgb(63 63 70 / var(--tw-border-opacity, 1))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.bg-purple-600{--tw-bg-opacity:1;background-color:rgb(147 51 234 / var(--tw-bg-opacity, 1))}.bg-zinc-700{--tw-bg-opacity:1;background-color:rgb(63 63 70 / var(--tw-bg-opacity, 1))}.bg-zinc-800{--tw-bg-opacity:1;background-color:rgb(39 39 42 / var(--tw-bg-opacity, 1))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right, var(--tw-gradient-stops))}.from-gray-800{--tw-gradient-from:#1f2937 var(--tw-gradient-from-position);--tw-gradient-to:rgb(31 41 55 / 0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from), var(--tw-gradient-to)}.to-purple-600{--tw-gradient-to:#9333ea var(--tw-gradient-to-position)}.p-3{padding:0.75rem}.p-4{padding:1rem}.p-8{padding:2rem}.px-3{padding-left:0.75rem;padding-right:0.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-2{padding-top:0.5rem;padding-bottom:0.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.text-center{text-align:center}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-sm{font-size:0.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:0.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-zinc-300{--tw-text-opacity:1;color:rgb(212 212 216 / var(--tw-text-opacity, 1))}.text-zinc-400{--tw-text-opacity:1;color:rgb(161 161 170 / var(--tw-text-opacity, 1))}.shadow-lg{--tw-shadow:0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.hover\:bg-purple-700:hover{--tw-bg-opacity:1;background-color:rgb(126 34 206 / var(--tw-bg-opacity, 1))}.hover\:bg-zinc-600:hover{--tw-bg-opacity:1;background-color:rgb(82 82 91 / var(--tw-bg-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.focus\:border-purple-500:focus{--tw-border-opacity:1;border-color:rgb(168 85 247 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)}.focus\:ring-purple-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(168 85 247 / var(--tw-ring-opacity, 1))}@media (min-width: 640px){.sm\:grid-cols-2{grid-template-columns:repeat(2, minmax(0, 1fr))}}@media (min-width: 768px){.md\:grid-cols-4{grid-template-columns:repeat(4, minmax(0, 1fr))}}@media (min-width: 1024px){.lg\:grid-cols-6{grid-template-columns:repeat(6, minmax(0, 1fr))}}</style></head>
<body class="bg-gradient-to-br from-gray-800 to-purple-600 text-white min-h-screen">
<a href="https://ko-fi.com/ambrosial" target="_blank" id="kofiButton">
<img src="https://assets-global.website-files.com/5c14e387dab576fe667689cf/64f1a9ddd0246590df69e9ef_ko-fi_logo_02-p-500.png" alt="Ko-Fi" class="w-8 h-8">
</a>
<a href="https://github.com/ambr0sial/nova" target="_blank" id="githubButton">
<img src="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" alt="GitHub" class="w-8 h-8">
</a>
<div id="loginPage" class="min-h-screen flex items-center justify-center">
<div class="w-full max-w-lg p-8 space-y-6 bg-zinc-800 rounded-lg shadow-lg">
<h1 class="text-4xl font-bold text-center">Nova</h1>
<p class="text-sm text-zinc-400 text-center">Please input your TMDB API key to access the service.</p>
<form id="apiKeyForm" class="space-y-4">
<input type="text" id="apiKeyInput" placeholder="Enter your TMDB API Key here" class="w-full p-3 rounded bg-zinc-700 text-white focus:outline-none focus:ring-2 focus:ring-purple-500">
<button type="submit" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
Submit
</button>
<div class="text-center text-sm text-zinc-400">
or
</div>
<button type="button" id="usePublicApiKey" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
Use a public API key
</button>
</form>
<p class="text-xs text-zinc-400 text-center">
Note: If the public API key doesn't work anymore, just use your own. It will rarely be updated as it's not my main priority.
</p>
</div>
</div>
<div id="homePage" class="hidden">
<div class="container mx-auto px-4 py-8">
<header class="flex justify-between items-center py-4">
<h1 class="text-3xl font-bold text-purple-400">Nova</h1>
<div class="text-center text-sm text-zinc-400 mt-4">
This website is not affiliated with novastream.to
</div>
<nav>
<a href="https://pastebin.com/raw/5kqU1Up8" class="text-zinc-300 hover:text-white px-3 py-2 rounded">About</a>
</nav>
</header>
<div class="flex gap-4 mb-8">
<div class="relative flex-1">
<input type="text" id="searchInput" placeholder="Search for something" class="w-full p-3 rounded-l bg-zinc-800 border border-zinc-700 focus:border-purple-500 focus:outline-none">
<button id="searchButton" class="absolute inset-y-0 right-0 bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded-r">
Search
</button>
<div id="searchSuggestions" class="absolute w-full bg-zinc-800 text-white rounded-b-lg mt-1 hidden"></div>
</div>
<button id="randomButton" class="bg-zinc-700 hover:bg-zinc-600 text-white font-bold py-2 px-4 rounded">
Random Movie
</button>
</div>
<h2 class="text-xl font-semibold mb-4">Upcoming Media</h2>
<div id="upcomingMedia" class="mb-8 ml-0"></div>
<h2 class="text-xl font-semibold mb-4">Popular Media</h2>
<div id="popularMovies" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4"></div>
<div id="paginationControls" class="flex justify-center items-center mt-4">
<button id="prevPage" class="bg-zinc-700 hover:bg-zinc-600 text-white font-bold py-2 px-4 rounded mx-2">Previous</button>
<span id="currentPage" class="text-white mx-2">1</span>
<button id="nextPage" class="bg-zinc-700 hover:bg-zinc-600 text-white font-bold py-2 px-4 rounded mx-2">Next</button>
</div>
<h2 class="text-xl font-semibold mt-8 mb-4">Selected Media</h2>
<div id="selectedMovie" class="bg-zinc-800 p-4 rounded-lg flex">
<div id="videoPlayer" class="w-full h-full"></div>
</div>
<footer class="text-center text-gray-400 mt-8">
Made with <span id="heartIcon" class="cursor-pointer" onmouseover="this.style.color='red'" onmouseout="this.style.color=''">♥</span> by Ambrosial. Latest version: 12/08/24
</footer>
<div class="text-center text-sm text-zinc-400 mt-4">
Nova doesn't store files, but provides links to external services. Legal issues should be discussed with file providers and hosts. The files provided by video providers are not covered by Nova.
</div>
<div id="welcomeBanner" class="fixed bottom-0 left-0 right-0 bg-gray-800 text-white p-4 text-center">
<button id="closeBanner" class="text-gray-300 hover:text-white float-right mt-1 mr-1">×</button>
<p>Welcome to Nova! Here are our only official domains:</p>
<p>novastream.top novastream.vercel.app novastream-alt.netlify.app novastream.onrender.com</p>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const loginPage = document.getElementById('loginPage');
const homePage = document.getElementById('homePage');
const apiKeyForm = document.getElementById('apiKeyForm');
const welcomeBanner = document.getElementById('welcomeBanner');
const closeBanner = document.getElementById('closeBanner');
closeBanner.addEventListener('click', () => {
welcomeBanner.style.display = 'none';
});
apiKeyForm.addEventListener('submit', async function(event) {
event.preventDefault();
const apiKey = document.getElementById('apiKeyInput').value;
const response = await fetch(`https://api.themoviedb.org/3/movie/550?api_key=${apiKey}`);
if (response.ok) {
localStorage.setItem('apiKey', apiKey);
loginPage.classList.add('hidden');
homePage.classList.remove('hidden');
fetchPopularMovies(apiKey);
} else {
alert('API Key is invalid. Please try again.');
}
});
document.getElementById('usePublicApiKey').addEventListener('click', async function() {
const publicKey = '1070730380f5fee0d87cf0382670b255';
document.getElementById('apiKeyInput').value = publicKey;
const response = await fetch(`https://api.themoviedb.org/3/movie/550?api_key=${publicKey}`);
if (response.ok) {
localStorage.setItem('apiKey', publicKey);
loginPage.classList.add('hidden');
homePage.classList.remove('hidden');
fetchPopularMovies(publicKey);
} else {
alert('Public API Key is invalid. Please try using your own key.');
}
});
const searchInput = document.getElementById('searchInput');
document.getElementById('searchButton').addEventListener('click', search);
searchInput.addEventListener('keydown', async function(event) {
if (event.key === 'Enter') {
event.preventDefault();
search();
}
});
async function search() {
const apiKey = localStorage.getItem('apiKey');
const searchInputValue = searchInput.value;
const response = await fetch(`https://api.themoviedb.org/3/search/multi?api_key=${apiKey}&query=${searchInputValue}`);
if (response.ok) {
const data = await response.json();
displaySearchResults(data.results);
searchSuggestions.classList.add('hidden');
}
}
const searchSuggestions = document.getElementById('searchSuggestions');
searchInput.addEventListener('input', async function() {
const apiKey = localStorage.getItem('apiKey');
const query = searchInput.value;
if (query.length > 2) {
const response = await fetch(`https://api.themoviedb.org/3/search/multi?api_key=${apiKey}&query=${query}`);
if (response.ok) {
const data = await response.json();
displaySearchSuggestions(data.results);
} else {
searchSuggestions.classList.add('hidden');
}
} else {
searchSuggestions.classList.add('hidden');
}
});
function displaySearchSuggestions(results) {
searchSuggestions.innerHTML = results.map(media => `
<div class="p-2 hover:bg-zinc-700 cursor-pointer" data-id="${media.id}" data-type="${media.media_type}">
<span>${media.title || media.name} (${media.media_type === 'movie' ? 'Movie' : 'TV Show'}) - ${media.vote_average}/10</span>
</div>
`).join('');
searchSuggestions.classList.remove('hidden');
searchSuggestions.querySelectorAll('div').forEach(div => {
div.addEventListener('click', function() {
const mediaId = this.getAttribute('data-id');
const mediaType = this.getAttribute('data-type');
fetchSelectedMedia(localStorage.getItem('apiKey'), mediaId, mediaType);
searchSuggestions.classList.add('hidden');
});
});
}
document.getElementById('searchButton').addEventListener('click', async function() {
const apiKey = localStorage.getItem('apiKey');
const searchInputValue = searchInput.value;
const response = await fetch(`https://api.themoviedb.org/3/search/multi?api_key=${apiKey}&query=${searchInputValue}`);
if (response.ok) {
const data = await response.json();
displaySearchResults(data.results);
}
});
document.getElementById('randomButton').addEventListener('click', async function() {
const apiKey = localStorage.getItem('apiKey');
const response = await fetch(`https://api.themoviedb.org/3/trending/all/week?api_key=${apiKey}`);
if (response.ok) {
const data = await response.json();
const randomMedia = data.results[Math.floor(Math.random() * data.results.length)];
fetchSelectedMedia(apiKey, randomMedia.id, randomMedia.media_type);
}
});
async function fetchPopularMovies(apiKey, page = 1) {
const response = await fetch(`https://api.themoviedb.org/3/trending/all/week?api_key=${apiKey}&page=${page}`);
if (response.ok) {
const data = await response.json();
displaySearchResults(data.results);
updatePaginationControls(data.page, data.total_pages);
fetchUpcomingMedia(apiKey);
} else {
console.error('Failed to fetch popular media.');
}
}
function updatePaginationControls(currentPage, totalPages) {
const prevPageButton = document.getElementById('prevPage');
const nextPageButton = document.getElementById('nextPage');
const currentPageSpan = document.getElementById('currentPage');
currentPageSpan.textContent = currentPage;
prevPageButton.disabled = currentPage === 1;
nextPageButton.disabled = currentPage === totalPages;
prevPageButton.onclick = () => changePage(currentPage - 1);
nextPageButton.onclick = () => changePage(currentPage + 1);
}
function changePage(page) {
const apiKey = localStorage.getItem('apiKey');
fetchPopularMovies(apiKey, page);
}
async function fetchSelectedMedia(apiKey, mediaId, mediaType) {
const response = await fetch(`https://api.themoviedb.org/3/${mediaType}/${mediaId}?api_key=${apiKey}`);
if (response.ok) {
const media = await response.json();
displaySelectedMedia(media, mediaType);
} else {
console.error('Failed to fetch media details.');
}
}
async function displaySelectedMedia(media, mediaType) {
const selectedMovie = document.getElementById('selectedMovie');
selectedMovie.innerHTML = `
<div class="w-1/3">
<img id="poster" src="https://image.tmdb.org/t/p/w500${media.poster_path}" alt="${media.title || media.name}" class="rounded-lg">
<div class="mt-4">
<label for="languageSelect" class="block text-sm font-medium text-zinc-300">Select Language:</label>
<select id="languageSelect" class="mt-1 block w-full bg-zinc-800 border border-zinc-700 rounded focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500">
<option value="en">English</option>
<option value="fr">French</option>
</select>
<label for="providerSelect" class="block text-sm font-medium text-zinc-300 mt-2">Select Content Provider:</label>
<select id="providerSelect" class="mt-1 block w-full bg-zinc-800 border border-zinc-700 rounded focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500">
<option value="superembed">SuperEmbed</option>
<option value="embedsoap">EmbedSoap</option>
<option value="autoembed">AutoEmbed</option>
<option value="smashystream">SmashyStream</option>
<option value="trailer">Trailer</option>
</select>
</div>
${mediaType === 'tv' ? `
<div class="mt-4">
<label for="seasonSelect" class="block text-sm font-medium text-zinc-300">Select Season:</label>
<select id="seasonSelect" class="mt-1 block w-full bg-zinc-800 border border-zinc-700 rounded focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500">
${media.seasons.map(season => `<option value="${season.season_number}">${season.name}</option>`).join('')}
</select>
<label for="episodeSelect" class="block text-sm font-medium text-zinc-300 mt-2">Select Episode:</label>
<select id="episodeSelect" class="mt-1 block w-full bg-zinc-800 border border-zinc-700 rounded focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-purple-500"></select>
</div>
` : ''}
</div>
<div id="movieInfo" class="w-2/3 pl-4">
<h2 class="text-2xl font-bold">${media.title || media.name}</h2>
<p class="text-sm text-zinc-400">${media.release_date || media.first_air_date}</p>
<p class="mt-4">${media.overview}</p>
<p class="text-sm text-zinc-400">Type: ${mediaType === 'movie' ? 'Movie' : 'TV Show'}</p>
<button id="playButton" class="mt-4 bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded">
Play
</button>
</div>
<div id="videoPlayer" class="w-full h-full rounded-lg overflow-hidden hidden"></div>
`;
const playButton = document.getElementById('playButton');
playButton.addEventListener('click', async () => {
const videoPlayer = selectedMovie.querySelector('#videoPlayer');
const movieInfo = selectedMovie.querySelector('#movieInfo');
const poster = selectedMovie.querySelector('#poster');
const languageSelect = document.getElementById('languageSelect');
const language = languageSelect.value;
const providerSelect = document.getElementById('providerSelect');
const provider = providerSelect.value;
if (!videoPlayer || !movieInfo || !poster) {
console.error("Error: videoPlayer, movieInfo, or poster elements not found.");
return;
}
let endpoint;
if (mediaType === 'tv') {
const seasonSelect = document.getElementById('seasonSelect');
const episodeSelect = document.getElementById('episodeSelect');
const seasonNumber = seasonSelect.value;
const episodeNumber = episodeSelect.value;
if (!seasonNumber || !episodeNumber) {
console.error("Error: Season number or episode number not selected.");
return;
}
if (language === 'fr') {
endpoint = `https://frembed.pro/api/serie.php?id=${media.id}&sa=${seasonNumber}&epi=${episodeNumber}`;
} else {
if (provider === 'superembed') {
endpoint = `https://multiembed.mov/?video_id=${media.id}&tmdb=1&s=${seasonNumber}&e=${episodeNumber}`;
} else if (provider === 'embedsoap') {
endpoint = `https://www.embedsoap.com/embed/tv/?id=${media.id}&s=${seasonNumber}&e=${episodeNumber}`;
} else if (provider === 'autoembed') {
endpoint = `https://autoembed.co/tv/tmdb/${media.id}-${seasonNumber}-${episodeNumber}`;
} else if (provider === 'smashystream') {
endpoint = `https://player.smashy.stream/tv/${media.id}?s=${seasonNumber}&e=${episodeNumber}`;
} else if (provider === 'trailer') {
const trailerResponse = await fetch(`https://api.themoviedb.org/3/${mediaType}/${media.id}/videos?api_key=${localStorage.getItem('apiKey')}`);
const trailerData = await trailerResponse.json();
const trailer = trailerData.results.find(video => video.type === 'Trailer' && video.site === 'YouTube');
if (trailer) {
endpoint = `https://www.youtube.com/embed/${trailer.key}`;
} else {
alert('Trailer not available.');
return;
}
}
}
} else {
if (language === 'fr') {
endpoint = `https://frembed.pro/api/film.php?id=${media.id}`;
} else {
if (provider === 'superembed') {
endpoint = `https://multiembed.mov/?video_id=${media.id}&tmdb=1`;
} else if (provider === 'embedsoap') {
endpoint = `https://www.embedsoap.com/embed/movie/${media.id}`;
} else if (provider === 'autoembed') {
endpoint = `https://autoembed.co/movie/tmdb/${media.id}`;
} else if (provider === 'smashystream') {
endpoint = `https://player.smashy.stream/movie/${media.id}`;
} else if (provider === 'trailer') {
const trailerResponse = await fetch(`https://api.themoviedb.org/3/${mediaType}/${media.id}/videos?api_key=${localStorage.getItem('apiKey')}`);
const trailerData = await trailerResponse.json();
const trailer = trailerData.results.find(video => video.type === 'Trailer' && video.site === 'YouTube');
if (trailer) {
endpoint = `https://www.youtube.com/embed/${trailer.key}`;
} else {
alert('Trailer not available.');
return;
}
}
}
}
videoPlayer.innerHTML = `<iframe src="${endpoint}" class="w-full" style="height: ${poster.offsetHeight}px;" allowfullscreen></iframe>`;
videoPlayer.classList.remove('hidden');
movieInfo.classList.add('hidden');
});
languageSelect.addEventListener('change', () => {
const providerSelect = document.getElementById('providerSelect');
if (languageSelect.value === 'fr') {
providerSelect.classList.add('hidden');
} else {
providerSelect.classList.remove('hidden');
}
playButton.click();
});
providerSelect.addEventListener('change', () => {
playButton.click();
});
if (mediaType === 'tv') {
const seasonSelect = document.getElementById('seasonSelect');
const episodeSelect = document.getElementById('episodeSelect');
async function updateEpisodes() {
const seasonNumber = seasonSelect.value;
const response = await fetch(`https://api.themoviedb.org/3/tv/${media.id}/season/${seasonNumber}?api_key=${localStorage.getItem('apiKey')}`);
if (response.ok) {
const season = await response.json();
episodeSelect.innerHTML = season.episodes.map(episode => `<option value="${episode.episode_number}">${episode.name}</option>`).join('');
} else {
console.error('Failed to fetch season details.');
}
}
seasonSelect.addEventListener('change', async () => {
await updateEpisodes();
playButton.click();
});
episodeSelect.addEventListener('change', () => {
playButton.click();
});
updateEpisodes();
}
selectedMovie.scrollIntoView({ behavior: 'smooth' });
}
function displaySearchResults(results) {
const popularMovies = document.getElementById('popularMovies');
popularMovies.innerHTML = '';
results.forEach(media => {
const mediaCard = document.createElement('div');
mediaCard.classList.add('bg-zinc-800', 'p-4', 'rounded-lg', 'cursor-pointer', 'transition', 'transform', 'hover:scale-105');
mediaCard.innerHTML = `
<img src="https://image.tmdb.org/t/p/w200${media.poster_path}" alt="${media.title || media.name}" class="rounded">
<div class="mt-2">
<h3 class="text-lg font-semibold">${media.title || media.name}</h3>
<p class="text-zinc-400">Type: ${media.media_type === 'movie' ? 'Movie' : 'TV Show'}</p>
<p class="text-sm text-zinc-400">Rating: ${media.vote_average}/10</p>
<p class="text-sm text-zinc-400">Release Date: ${media.release_date || media.first_air_date}</p>
</div>
`;
mediaCard.addEventListener('click', function() {
fetchSelectedMedia(localStorage.getItem('apiKey'), media.id, media.media_type);
});
popularMovies.appendChild(mediaCard);
});
}
async function fetchUpcomingMedia(apiKey) {
const response = await fetch(`https://api.themoviedb.org/3/movie/upcoming?api_key=${apiKey}&language=en-US&page=1`);
if (response.ok) {
const data = await response.json();
const upcomingMovies = data.results.filter(media => new Date(media.release_date) > new Date());
displayUpcomingMedia(upcomingMovies);
} else {
console.error('Failed to fetch upcoming media.');
}
}
function displayUpcomingMedia(mediaList) {
const upcomingMedia = document.getElementById('upcomingMedia');
upcomingMedia.innerHTML = '';
mediaList.forEach(media => {
const mediaItem = document.createElement('div');
mediaItem.classList.add('text-zinc-300', 'mb-2');
mediaItem.innerHTML = `<span>${media.title}:</span> <span>${media.release_date}</span>`;
upcomingMedia.appendChild(mediaItem);
});
}
});
</script>
</body></html>