cinestream / index.html
docto41's picture
Add 2 files
4a90a5d verified
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CineStream - Films avec streaming automatique</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#6d28d9',
secondary: '#8b5cf6',
dark: '#1e1b4b',
light: '#f5f3ff',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
}
}
}
</script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Inter', sans-serif;
background-color: #0f172a;
color: white;
}
.movie-card {
transition: all 0.3s ease;
}
.movie-card:hover {
transform: translateY(-10px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.movie-poster {
height: 450px;
object-fit: cover;
}
.loading-spinner {
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.gradient-text {
background: linear-gradient(90deg, #8b5cf6, #ec4899);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.search-input:focus {
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.5);
}
.error-message {
background-color: rgba(239, 68, 68, 0.2);
border-left: 4px solid #ef4444;
}
.placeholder-poster {
background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
display: flex;
align-items: center;
justify-content: center;
}
/* Style pour le lecteur vidéo */
.video-container {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
height: 0;
overflow: hidden;
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: none;
}
/* Style pour les boutons de streaming */
.stream-btn {
transition: all 0.2s ease;
}
.stream-btn:hover {
transform: scale(1.05);
}
/* Style pour la fenêtre de streaming */
.streaming-window {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.9);
z-index: 1000;
display: flex;
flex-direction: column;
}
.streaming-header {
padding: 15px;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: space-between;
align-items: center;
}
.streaming-content {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.streaming-controls {
padding: 15px;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: space-between;
align-items: center;
}
/* Style pour la sélection de serveur */
.server-list {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.server-btn {
padding: 8px 12px;
border-radius: 20px;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
}
.server-btn.active {
background-color: #6d28d9;
color: white;
}
.server-btn.inactive {
background-color: #334155;
color: #94a3b8;
}
/* Animation de chargement du streaming */
.stream-loading {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20px;
}
.stream-loading-spinner {
width: 50px;
height: 50px;
border: 5px solid rgba(255, 255, 255, 0.1);
border-radius: 50%;
border-top-color: #6d28d9;
animation: spin 1s linear infinite;
}
</style>
</head>
<body class="min-h-screen">
<!-- Navigation -->
<nav class="bg-gray-900 bg-opacity-90 backdrop-blur-md fixed w-full z-50 shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<div class="flex items-center">
<div class="flex-shrink-0">
<span class="text-2xl font-bold gradient-text">CineStream</span>
</div>
<div class="hidden md:block ml-10">
<div class="flex space-x-4">
<a href="#" class="text-white px-3 py-2 rounded-md text-sm font-medium bg-primary">Accueil</a>
<a href="#" class="text-gray-300 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Films</a>
<a href="#" class="text-gray-300 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Séries</a>
<a href="#" class="text-gray-300 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Tendances</a>
</div>
</div>
</div>
<div class="hidden md:block">
<div class="ml-4 flex items-center md:ml-6">
<div class="relative mx-4">
<input type="text" id="search-input" placeholder="Rechercher un film..."
class="search-input bg-gray-800 text-white px-4 py-2 rounded-full w-64 focus:outline-none focus:ring-2 focus:ring-purple-500 transition duration-200">
<button onclick="searchMovies()" class="absolute right-3 top-2 text-gray-400 hover:text-white">
<i class="fas fa-search"></i>
</button>
</div>
<button class="p-1 rounded-full text-gray-400 hover:text-white focus:outline-none">
<i class="fas fa-user-circle text-xl"></i>
</button>
</div>
</div>
<div class="-mr-2 flex md:hidden">
<button class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none">
<i class="fas fa-bars"></i>
</button>
</div>
</div>
</div>
</nav>
<!-- Main Content -->
<main class="pt-24 pb-12">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<!-- Featured Section -->
<section class="mb-12">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-bold text-white">Films populaires</h2>
<div class="flex space-x-2">
<button onclick="filterMovies('popular')" class="px-4 py-1 rounded-full text-sm bg-primary text-white">Populaires</button>
<button onclick="filterMovies('top_rated')" class="px-4 py-1 rounded-full text-sm bg-gray-700 text-white">Mieux notés</button>
<button onclick="filterMovies('upcoming')" class="px-4 py-1 rounded-full text-sm bg-gray-700 text-white">Prochainement</button>
</div>
</div>
<div id="movies-container" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
<!-- Movies will be loaded here -->
<div class="flex justify-center items-center py-12 col-span-full">
<div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-primary loading-spinner"></div>
</div>
</div>
<div id="load-more-container" class="mt-8 flex justify-center">
<button onclick="loadMoreMovies()" class="px-6 py-2 bg-primary text-white rounded-full hover:bg-secondary transition flex items-center">
<span>Voir plus</span>
<i class="fas fa-chevron-down ml-2"></i>
</button>
</div>
</section>
<!-- Genres Section -->
<section class="mb-12">
<h2 class="text-2xl font-bold text-white mb-6">Par genres</h2>
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4">
<button onclick="filterByGenre(28)" class="genre-btn px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-full text-sm">Action</button>
<button onclick="filterByGenre(12)" class="genre-btn px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-full text-sm">Aventure</button>
<button onclick="filterByGenre(16)" class="genre-btn px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded-full text-sm">Animation</button>
<button onclick="filterByGenre(35)" class="genre-btn px-4 py-2 bg-yellow-600 hover:bg-yellow-700 text-white rounded-full text-sm">Comédie</button>
<button onclick="filterByGenre(80)" class="genre-btn px-4 py-2 bg-gray-600 hover:bg-gray-700 text-white rounded-full text-sm">Crime</button>
<button onclick="filterByGenre(18)" class="genre-btn px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-full text-sm">Drame</button>
</div>
</section>
</div>
</main>
<!-- Footer -->
<footer class="bg-gray-900 text-gray-400 py-8">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
<div>
<h3 class="text-white text-lg font-semibold mb-4">CineStream</h3>
<p class="text-sm">La meilleure plateforme pour regarder des films avec streaming automatique.</p>
</div>
<div>
<h3 class="text-white text-lg font-semibold mb-4">Navigation</h3>
<ul class="space-y-2 text-sm">
<li><a href="#" class="hover:text-white">Accueil</a></li>
<li><a href="#" class="hover:text-white">Films</a></li>
<li><a href="#" class="hover:text-white">Séries</a></li>
<li><a href="#" class="hover:text-white">Nouveautés</a></li>
</ul>
</div>
<div>
<h3 class="text-white text-lg font-semibold mb-4">Légal</h3>
<ul class="space-y-2 text-sm">
<li><a href="#" class="hover:text-white">Conditions d'utilisation</a></li>
<li><a href="#" class="hover:text-white">Politique de confidentialité</a></li>
<li><a href="#" class="hover:text-white">DMCA</a></li>
</ul>
</div>
<div>
<h3 class="text-white text-lg font-semibold mb-4">Contact</h3>
<div class="flex space-x-4">
<a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-facebook-f"></i></a>
<a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-twitter"></i></a>
<a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-instagram"></i></a>
<a href="#" class="text-gray-400 hover:text-white"><i class="fab fa-discord"></i></a>
</div>
</div>
</div>
<div class="border-t border-gray-800 mt-8 pt-8 text-sm text-center">
<p>© 2023 CineStream. Tous droits réservés.</p>
</div>
</div>
</footer>
<!-- Movie Details Modal -->
<div id="movie-modal" class="fixed inset-0 z-50 hidden overflow-y-auto">
<div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-900 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div class="inline-block align-bottom bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-4xl sm:w-full">
<div class="px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div id="modal-poster" class="flex-shrink-0 w-full sm:w-1/3 mb-4 sm:mb-0 sm:mr-6">
<img class="w-full rounded-lg shadow-lg" src="" alt="Movie Poster">
</div>
<div class="mt-3 text-center sm:mt-0 sm:text-left w-full sm:w-2/3">
<h3 id="modal-title" class="text-2xl leading-6 font-bold text-white mb-2"></h3>
<div class="flex items-center mb-4">
<span id="modal-rating" class="bg-yellow-500 text-white text-xs font-semibold px-2 py-1 rounded mr-3"></span>
<span id="modal-year" class="text-gray-300 text-sm"></span>
<span id="modal-runtime" class="ml-3 text-gray-300 text-sm"></span>
</div>
<p id="modal-overview" class="text-gray-300 mb-4"></p>
<div id="modal-genres" class="flex flex-wrap gap-2 mb-4"></div>
<!-- Serveurs de streaming -->
<div class="mb-4">
<h4 class="text-sm font-semibold text-gray-400 mb-2">CHOISIR UN SERVEUR :</h4>
<div class="server-list">
<button onclick="selectServer('hdvip')" class="server-btn active" data-server="hdvip">
<i class="fas fa-crown mr-1"></i> HD VIP
</button>
<button onclick="selectServer('streamlare')" class="server-btn inactive" data-server="streamlare">
<i class="fas fa-play-circle mr-1"></i> Streamlare
</button>
<button onclick="selectServer('streamtape')" class="server-btn inactive" data-server="streamtape">
<i class="fas fa-tape mr-1"></i> Streamtape
</button>
<button onclick="selectServer('younetu')" class="server-btn inactive" data-server="younetu">
<i class="fas fa-film mr-1"></i> Younetu
</button>
<button onclick="selectServer('uptostream')" class="server-btn inactive" data-server="uptostream">
<i class="fas fa-cloud mr-1"></i> Uptostream
</button>
<button onclick="selectServer('vidsrc')" class="server-btn inactive" data-server="vidsrc">
<i class="fas fa-server mr-1"></i> VidSrc
</button>
</div>
</div>
<div class="mt-4">
<button type="button" onclick="closeModal()" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-primary text-base font-medium text-white hover:bg-secondary focus:outline-none sm:ml-3 sm:w-auto sm:text-sm">
Fermer
</button>
<button id="watch-now-btn" onclick="startStreaming()" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-600 text-base font-medium text-white hover:bg-green-700 focus:outline-none sm:ml-3 sm:w-auto sm:text-sm">
<i class="fas fa-play mr-2"></i> Lecture auto
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Streaming Window (hidden by default) -->
<div id="streaming-window" class="streaming-window hidden">
<div class="streaming-header">
<h3 id="streaming-title" class="text-xl font-bold text-white"></h3>
<button onclick="closeStreamingWindow()" class="text-gray-400 hover:text-white">
<i class="fas fa-times text-xl"></i>
</button>
</div>
<div class="streaming-content">
<div id="streaming-player-container" class="w-full h-full" style="max-width: 1200px;">
<!-- Contenu du lecteur sera chargé ici -->
<div id="stream-loading" class="stream-loading w-full h-full">
<div class="stream-loading-spinner"></div>
<p class="text-gray-300">Chargement du flux vidéo...</p>
</div>
</div>
</div>
<div class="streaming-controls">
<div class="flex space-x-2">
<button onclick="changeQuality('720p')" class="stream-btn px-3 py-1 bg-gray-700 hover:bg-gray-600 text-white rounded-full text-sm">720p</button>
<button onclick="changeQuality('1080p')" class="stream-btn px-3 py-1 bg-gray-700 hover:bg-gray-600 text-white rounded-full text-sm">1080p</button>
<button onclick="changeQuality('4k')" class="stream-btn px-3 py-1 bg-gray-700 hover:bg-gray-600 text-white rounded-full text-sm">4K</button>
</div>
<div>
<button onclick="toggleFullscreen()" class="stream-btn px-3 py-1 bg-gray-700 hover:bg-gray-600 text-white rounded-full text-sm">
<i class="fas fa-expand mr-1"></i> Plein écran
</button>
</div>
</div>
</div>
<script>
// Configuration
const API_KEY = 'c45a857c193f6302f2b5061c3b85e743'; // Clé API TMDB valide
const BASE_URL = 'https://api.themoviedb.org/3';
// Serveurs de streaming avec URLs de base fonctionnelles
const STREAMING_SERVERS = {
hdvip: {
name: 'Lecteur HD VIP',
url: 'https://database.gdriveplayer.us/player.php?tmdb=',
autoPlay: true,
requiresTMDB: true,
requiresIMDB: false
},
streamlare: {
name: 'Streamlare',
url: 'https://streamlare.com/e/',
autoPlay: true,
requiresTMDB: false,
requiresIMDB: true
},
streamtape: {
name: 'Streamtape',
url: 'https://streamtape.com/e/',
autoPlay: true,
requiresTMDB: false,
requiresIMDB: true
},
younetu: {
name: 'Younetu',
url: 'https://younetu.com/embed/',
autoPlay: true,
requiresTMDB: false,
requiresIMDB: true
},
uptostream: {
name: 'Uptostream',
url: 'https://uptostream.com/iframe/',
autoPlay: true,
requiresTMDB: false,
requiresIMDB: true
},
vidsrc: {
name: 'VidSrc',
url: 'https://vidsrc.to/embed/movie/',
autoPlay: true,
requiresTMDB: true,
requiresIMDB: false
}
};
let currentPage = 1;
let currentFilter = 'popular';
let currentGenre = null;
let currentSearch = '';
let totalPages = 1;
let isLoading = false;
let currentMovieId = null;
let currentIMDBId = null;
let selectedServer = 'hdvip';
// Fonction utilitaire pour faire les requêtes API
async function fetchAPI(endpoint, params = {}) {
const url = new URL(`${BASE_URL}${endpoint}`);
// Ajouter les paramètres par défaut
const defaultParams = {
language: 'fr-FR',
page: currentPage,
api_key: API_KEY
};
// Fusionner les paramètres
const queryParams = {...defaultParams, ...params};
// Ajouter les paramètres à l'URL
Object.keys(queryParams).forEach(key => {
if (queryParams[key] !== undefined && queryParams[key] !== null) {
url.searchParams.append(key, queryParams[key]);
}
});
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Erreur HTTP: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Erreur API:', error);
throw error;
}
}
// Charger les films au démarrage
document.addEventListener('DOMContentLoaded', function() {
loadMovies();
// Écouter la touche Entrée dans la recherche
document.getElementById('search-input').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
searchMovies();
}
});
});
// Charger les films
async function loadMovies() {
if (isLoading) return;
isLoading = true;
showLoadingState();
try {
let data;
if (currentSearch) {
data = await fetchAPI('/search/movie', {
query: currentSearch,
include_adult: false,
page: currentPage
});
} else if (currentGenre) {
data = await fetchAPI('/discover/movie', {
include_adult: false,
include_video: false,
sort_by: 'popularity.desc',
with_genres: currentGenre,
page: currentPage
});
} else {
data = await fetchAPI(`/movie/${currentFilter}`, {
page: currentPage
});
}
totalPages = data.total_pages || 1;
if (currentPage === 1) {
document.getElementById('movies-container').innerHTML = '';
}
if (data.results && data.results.length > 0) {
displayMovies(data.results);
updateLoadMoreButton();
} else {
showNoResults();
}
} catch (error) {
console.error('Error fetching movies:', error);
showErrorState(error.message);
} finally {
isLoading = false;
}
}
// Afficher l'état de chargement
function showLoadingState() {
const container = document.getElementById('movies-container');
container.innerHTML = `
<div class="flex justify-center items-center py-12 col-span-full">
<div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-primary loading-spinner"></div>
</div>
`;
}
// Afficher les films avec boutons de streaming
function displayMovies(movies) {
const container = document.getElementById('movies-container');
movies.forEach(movie => {
const movieCard = document.createElement('div');
movieCard.className = 'movie-card bg-gray-800 rounded-lg overflow-hidden shadow-lg hover:shadow-xl transition-all duration-300';
// Utiliser l'image originale en haute qualité si disponible
const posterPath = movie.poster_path
? `https://image.tmdb.org/t/p/w500${movie.poster_path}`
: 'https://via.placeholder.com/500x750?text=Affiche+non+disponible';
movieCard.innerHTML = `
<div>
<div class="movie-poster w-full rounded-t-lg overflow-hidden ${!movie.poster_path ? 'placeholder-poster' : ''}">
<img src="${posterPath}"
alt="${movie.title || 'Titre inconnu'}"
class="w-full h-full object-cover"
onerror="this.src='https://via.placeholder.com/500x750?text=Image+non+chargée'; this.classList.add('placeholder-poster')">
</div>
<div class="p-4">
<h3 class="text-lg font-semibold text-white truncate">${movie.title || 'Titre inconnu'}</h3>
<div class="flex items-center mt-2">
<span class="text-yellow-400 text-sm">
<i class="fas fa-star"></i> ${movie.vote_average ? movie.vote_average.toFixed(1) : 'N/A'}
</span>
<span class="text-gray-400 text-sm ml-auto">${movie.release_date ? movie.release_date.substring(0, 4) : 'N/A'}</span>
</div>
<div class="mt-3">
<button onclick="startAutoStreaming(${movie.id}, '${movie.title || 'Film'}')" class="w-full stream-btn px-3 py-2 bg-green-600 hover:bg-green-700 text-white rounded text-sm">
<i class="fas fa-play-circle mr-1"></i> Lecture auto
</button>
<button onclick="showMovieDetails(${movie.id})" class="w-full mt-2 px-3 py-2 bg-gray-700 hover:bg-gray-600 text-white rounded text-sm">
<i class="fas fa-info-circle mr-1"></i> Détails
</button>
</div>
</div>
</div>
`;
container.appendChild(movieCard);
});
}
// Afficher un message d'erreur
function showErrorState(errorMessage) {
const container = document.getElementById('movies-container');
container.innerHTML = `
<div class="col-span-full py-6 px-4 error-message rounded-lg">
<div class="flex items-center">
<i class="fas fa-exclamation-triangle text-red-500 text-xl mr-3"></i>
<div>
<h3 class="text-lg font-medium text-white">Erreur lors du chargement des films</h3>
<p class="text-gray-300 mt-1">${errorMessage || 'Veuillez réessayer plus tard'}</p>
<button onclick="retryLoading()" class="mt-3 px-4 py-2 bg-primary text-white rounded-full hover:bg-secondary transition text-sm">
<i class="fas fa-sync-alt mr-2"></i> Réessayer
</button>
</div>
</div>
</div>
`;
document.getElementById('load-more-container').classList.add('hidden');
}
// Afficher un message quand aucun résultat n'est trouvé
function showNoResults() {
const container = document.getElementById('movies-container');
container.innerHTML = `
<div class="col-span-full text-center py-12">
<i class="fas fa-film text-4xl text-gray-500 mb-4"></i>
<h3 class="text-xl text-white">Aucun film trouvé</h3>
<p class="text-gray-400 mt-2">Essayez avec d'autres critères de recherche</p>
</div>
`;
document.getElementById('load-more-container').classList.add('hidden');
}
// Réessayer le chargement
function retryLoading() {
currentPage = 1;
loadMovies();
}
// Mettre à jour le bouton "Voir plus"
function updateLoadMoreButton() {
const loadMoreContainer = document.getElementById('load-more-container');
if (currentPage >= totalPages) {
loadMoreContainer.innerHTML = `
<p class="text-gray-400">Vous avez atteint la fin des résultats</p>
`;
} else {
loadMoreContainer.classList.remove('hidden');
}
}
// Filtrer les films
function filterMovies(filter) {
currentFilter = filter;
currentGenre = null;
currentSearch = '';
currentPage = 1;
document.getElementById('search-input').value = '';
loadMovies();
// Mettre à jour les boutons actifs
document.querySelectorAll('button').forEach(btn => {
if (btn.textContent.toLowerCase().includes(filter.replace('_', ' '))) {
btn.classList.remove('bg-gray-700');
btn.classList.add('bg-primary');
} else {
btn.classList.remove('bg-primary');
btn.classList.add('bg-gray-700');
}
});
}
// Filtrer par genre
function filterByGenre(genreId) {
currentGenre = genreId;
currentSearch = '';
currentPage = 1;
document.getElementById('search-input').value = '';
loadMovies();
// Mettre à jour les boutons actifs
document.querySelectorAll('.genre-btn').forEach(btn => {
btn.classList.remove('bg-primary');
if (btn.onclick.toString().includes(genreId.toString())) {
btn.classList.add('bg-primary');
}
});
}
// Rechercher des films
function searchMovies() {
const query = document.getElementById('search-input').value.trim();
if (query) {
currentSearch = query;
currentGenre = null;
currentPage = 1;
loadMovies();
}
}
// Charger plus de films
function loadMoreMovies() {
if (currentPage < totalPages) {
currentPage++;
loadMovies();
}
}
// Afficher les détails du film
async function showMovieDetails(movieId) {
try {
const movie = await fetchAPI(`/movie/${movieId}`);
currentMovieId = movieId;
// Récupérer l'ID IMDB si disponible
if (movie.imdb_id) {
currentIMDBId = movie.imdb_id;
} else {
// Si l'ID IMDB n'est pas disponible, essayer de le récupérer via l'API
const externalIds = await fetchAPI(`/movie/${movieId}/external_ids`);
currentIMDBId = externalIds.imdb_id || null;
}
// Remplir la modal
const modalPoster = document.querySelector('#modal-poster img');
modalPoster.src = movie.poster_path
? `https://image.tmdb.org/t/p/w500${movie.poster_path}`
: 'https://via.placeholder.com/500x750?text=Affiche+non+disponible';
modalPoster.onerror = function() {
this.src = 'https://via.placeholder.com/500x750?text=Image+non+chargée';
};
document.getElementById('modal-title').textContent = movie.title || 'Titre inconnu';
document.getElementById('modal-rating').textContent = `${movie.vote_average ? movie.vote_average.toFixed(1) : 'N/A'}/10`;
document.getElementById('modal-year').textContent = movie.release_date ? movie.release_date.substring(0, 4) : 'N/A';
document.getElementById('modal-runtime').textContent = movie.runtime ? `${movie.runtime} min` : '';
document.getElementById('modal-overview').textContent = movie.overview || 'Aucun synopsis disponible.';
// Afficher les genres
const genresContainer = document.getElementById('modal-genres');
genresContainer.innerHTML = '';
if (movie.genres && movie.genres.length > 0) {
movie.genres.forEach(genre => {
const genreBadge = document.createElement('span');
genreBadge.className = 'bg-gray-700 text-white text-xs px-2 py-1 rounded';
genreBadge.textContent = genre.name;
genresContainer.appendChild(genreBadge);
});
} else {
genresContainer.innerHTML = '<span class="text-gray-400 text-sm">Aucun genre spécifié</span>';
}
// Afficher la modal
document.getElementById('movie-modal').classList.remove('hidden');
} catch (error) {
console.error('Error fetching movie details:', error);
alert('Erreur lors du chargement des détails du film: ' + (error.message || 'Veuillez réessayer'));
}
}
// Fermer la modal de détails
function closeModal() {
document.getElementById('movie-modal').classList.add('hidden');
}
// Sélectionner un serveur de streaming
function selectServer(serverId) {
selectedServer = serverId;
// Mettre à jour l'état des boutons
document.querySelectorAll('.server-btn').forEach(btn => {
if (btn.dataset.server === serverId) {
btn.classList.remove('inactive');
btn.classList.add('active');
} else {
btn.classList.remove('active');
btn.classList.add('inactive');
}
});
}
// Démarrer le streaming depuis la modal
function startStreaming() {
if (currentMovieId) {
const movieTitle = document.getElementById('modal-title').textContent;
startAutoStreaming(currentMovieId, movieTitle);
closeModal();
}
}
// Démarrer le streaming automatique dans une nouvelle fenêtre
async function startAutoStreaming(movieId, movieTitle) {
currentMovieId = movieId;
// Afficher la fenêtre de streaming
const streamingWindow = document.getElementById('streaming-window');
document.getElementById('streaming-title').textContent = movieTitle;
// Afficher l'état de chargement
const playerContainer = document.getElementById('streaming-player-container');
playerContainer.innerHTML = `
<div id="stream-loading" class="stream-loading w-full h-full">
<div class="stream-loading-spinner"></div>
<p class="text-gray-300">Chargement du flux vidéo...</p>
</div>
`;
// Afficher la fenêtre de streaming
streamingWindow.classList.remove('hidden');
// Récupérer les informations du film pour l'ID IMDB si nécessaire
let imdbId = currentIMDBId;
if (!imdbId && STREAMING_SERVERS[selectedServer].requiresIMDB) {
try {
const externalIds = await fetchAPI(`/movie/${movieId}/external_ids`);
imdbId = externalIds.imdb_id;
if (!imdbId) {
throw new Error("ID IMDB non disponible");
}
} catch (error) {
console.error("Erreur lors de la récupération de l'ID IMDB:", error);
playerContainer.innerHTML = `
<div class="flex flex-col items-center justify-center h-full text-red-400">
<i class="fas fa-exclamation-triangle text-4xl mb-4"></i>
<p class="text-lg">Impossible de trouver l'ID IMDB pour ce film</p>
<p class="text-sm text-gray-400 mt-2">Essayez avec un autre serveur</p>
</div>
`;
return;
}
}
// Construire l'URL de streaming en fonction du serveur sélectionné
let streamingUrl;
const serverConfig = STREAMING_SERVERS[selectedServer];
if (serverConfig.requiresTMDB) {
streamingUrl = serverConfig.url + movieId;
} else if (serverConfig.requiresIMDB && imdbId) {
streamingUrl = serverConfig.url + imdbId;
} else {
// Si aucun ID n'est disponible, utiliser TMDB par défaut
streamingUrl = serverConfig.url + movieId;
}
// Ajouter le paramètre de lecture automatique si pris en charge
if (serverConfig.autoPlay) {
streamingUrl += '/auto';
}
// Créer l'iframe pour le lecteur vidéo
const iframe = document.createElement('iframe');
iframe.id = 'streaming-player';
iframe.src = streamingUrl;
iframe.setAttribute('allowfullscreen', '');
iframe.setAttribute('scrolling', 'no');
iframe.setAttribute('frameborder', '0');
iframe.setAttribute('marginwidth', '0');
iframe.setAttribute('marginheight', '0');
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.border = 'none';
// Gestion des erreurs de chargement
iframe.onerror = function() {
playerContainer.innerHTML = `
<div class="flex flex-col items-center justify-center h-full text-red-400">
<i class="fas fa-exclamation-triangle text-4xl mb-4"></i>
<p class="text-lg">Erreur lors du chargement du flux vidéo</p>
<p class="text-sm text-gray-400 mt-2">Le serveur peut être temporairement indisponible</p>
<button onclick="tryAlternativeServer()" class="mt-4 px-4 py-2 bg-primary text-white rounded hover:bg-secondary transition">
<i class="fas fa-sync-alt mr-2"></i> Essayer un autre serveur
</button>
</div>
`;
};
// Remplacer le chargement par le lecteur
playerContainer.innerHTML = '';
playerContainer.appendChild(iframe);
// Mettre le focus sur la fenêtre de streaming
streamingWindow.focus();
// Tentative de lecture automatique (peut être bloquée par le navigateur)
setTimeout(() => {
try {
iframe.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
} catch (e) {
console.log("Auto-play blocked by browser");
}
}, 2000);
}
// Essayer un autre serveur en cas d'erreur
function tryAlternativeServer() {
const servers = Object.keys(STREAMING_SERVERS);
const currentIndex = servers.indexOf(selectedServer);
const nextIndex = (currentIndex + 1) % servers.length;
selectedServer = servers[nextIndex];
startAutoStreaming(currentMovieId, document.getElementById('streaming-title').textContent);
}
// Fermer la fenêtre de streaming
function closeStreamingWindow() {
const playerContainer = document.getElementById('streaming-player-container');
playerContainer.innerHTML = '';
document.getElementById('streaming-window').classList.add('hidden');
}
// Changer la qualité de streaming (simulé)
function changeQuality(quality) {
alert(`Qualité changée en ${quality}. Note: Ceci est une démonstration.`);
// En réalité, vous devriez mettre à jour la source du lecteur vidéo
}
// Basculer en plein écran
function toggleFullscreen() {
const playerContainer = document.getElementById('streaming-player-container');
if (playerContainer.requestFullscreen) {
playerContainer.requestFullscreen();
} else if (playerContainer.webkitRequestFullscreen) {
playerContainer.webkitRequestFullscreen();
} else if (playerContainer.msRequestFullscreen) {
playerContainer.msRequestFullscreen();
}
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=docto41/cinestream" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>