Spaces:
Running
Running
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>NexusFlix - Serveurs Automatiques</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 src="https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js"></script> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Rajdhani:wght@300;500;700&display=swap'); | |
| :root { | |
| --primary: #00f0ff; | |
| --secondary: #ff00e6; | |
| --dark: #0a0a1a; | |
| --darker: #050510; | |
| } | |
| body { | |
| font-family: 'Rajdhani', sans-serif; | |
| background-color: var(--darker); | |
| color: white; | |
| overflow-x: hidden; | |
| } | |
| h1, h2, h3, .font-futurist { | |
| font-family: 'Orbitron', sans-serif; | |
| } | |
| .glow { | |
| text-shadow: 0 0 10px var(--primary), 0 0 20px var(--primary); | |
| } | |
| .glow-secondary { | |
| text-shadow: 0 0 10px var(--secondary), 0 0 20px var(--secondary); | |
| } | |
| .neon-border { | |
| border: 1px solid var(--primary); | |
| box-shadow: 0 0 10px var(--primary), inset 0 0 10px var(--primary); | |
| } | |
| .holographic-card { | |
| background: rgba(10, 10, 30, 0.7); | |
| backdrop-filter: blur(10px); | |
| border-radius: 10px; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .holographic-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: -50%; | |
| left: -50%; | |
| width: 200%; | |
| height: 200%; | |
| background: linear-gradient( | |
| 45deg, | |
| transparent 0%, | |
| rgba(0, 240, 255, 0.1) 50%, | |
| transparent 100% | |
| ); | |
| transform: rotate(45deg); | |
| animation: shine 3s infinite; | |
| } | |
| @keyframes shine { | |
| 0% { transform: rotate(45deg) translateX(-100%); } | |
| 100% { transform: rotate(45deg) translateX(100%); } | |
| } | |
| .scanline { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .scanline::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient( | |
| to bottom, | |
| transparent 0%, | |
| rgba(0, 240, 255, 0.05) 50%, | |
| transparent 100% | |
| ); | |
| animation: scan 8s linear infinite; | |
| } | |
| @keyframes scan { | |
| 0% { top: -100%; } | |
| 100% { top: 100%; } | |
| } | |
| .player-container { | |
| aspect-ratio: 16/9; | |
| background: black; | |
| position: relative; | |
| } | |
| .quality-badge { | |
| position: absolute; | |
| top: 10px; | |
| right: 10px; | |
| background: rgba(0,0,0,0.7); | |
| padding: 3px 8px; | |
| border-radius: 3px; | |
| font-size: 12px; | |
| font-weight: bold; | |
| } | |
| .PM4 { color: #4CAF50; } | |
| .EMB { color: #FFC107; } | |
| .HD { color: #2196F3; } | |
| .UHD { color: #9C27B0; } | |
| .loading-pulse { | |
| animation: pulse 1.5s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { opacity: 0.5; } | |
| 50% { opacity: 1; } | |
| 100% { opacity: 0.5; } | |
| } | |
| #particles-js { | |
| position: fixed; | |
| width: 100%; | |
| height: 100%; | |
| z-index: -1; | |
| top: 0; | |
| left: 0; | |
| } | |
| .cyber-input { | |
| background: rgba(10, 20, 30, 0.7); | |
| border: 1px solid var(--primary); | |
| color: white; | |
| padding: 10px 15px; | |
| border-radius: 5px; | |
| transition: all 0.3s; | |
| } | |
| .cyber-input:focus { | |
| outline: none; | |
| box-shadow: 0 0 10px var(--primary); | |
| border-color: var(--secondary); | |
| } | |
| .cyber-button { | |
| background: linear-gradient(45deg, var(--primary), var(--secondary)); | |
| border: none; | |
| color: black; | |
| font-weight: bold; | |
| padding: 10px 20px; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| text-transform: uppercase; | |
| } | |
| .cyber-button:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 5px 15px rgba(0, 240, 255, 0.4); | |
| } | |
| .flicker { | |
| animation: flicker 0.01s infinite alternate; | |
| } | |
| @keyframes flicker { | |
| 0% { opacity: 0.95; } | |
| 100% { opacity: 1; } | |
| } | |
| .server-link { | |
| display: inline-block; | |
| margin: 5px; | |
| padding: 5px 10px; | |
| background: rgba(0, 240, 255, 0.1); | |
| border: 1px solid var(--primary); | |
| border-radius: 4px; | |
| font-size: 12px; | |
| transition: all 0.3s; | |
| } | |
| .server-link:hover { | |
| background: rgba(0, 240, 255, 0.3); | |
| transform: translateY(-2px); | |
| } | |
| .server-link.PM4 { border-color: #4CAF50; } | |
| .server-link.EMB { border-color: #FFC107; } | |
| .server-link.HD { border-color: #2196F3; } | |
| .server-link.UHD { border-color: #9C27B0; } | |
| .server-status { | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 50%; | |
| display: inline-block; | |
| margin-right: 5px; | |
| } | |
| .online { background-color: #4CAF50; } | |
| .offline { background-color: #F44336; } | |
| .loading { background-color: #FFC107; } | |
| .server-card { | |
| transition: all 0.3s; | |
| border-left: 3px solid; | |
| } | |
| .server-card:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 5px 15px rgba(0, 240, 255, 0.2); | |
| } | |
| .server-card.FR { border-left-color: #0055A4; } | |
| .server-card.US { border-left-color: #3C3B6E; } | |
| .server-card.DE { border-left-color: #000000; } | |
| .server-card.UK { border-left-color: #012169; } | |
| .server-card.JP { border-left-color: #BC002D; } | |
| .server-card.CA { border-left-color: #D52B1E; } | |
| .watch-button { | |
| background: linear-gradient(45deg, #00c6ff, #0072ff); | |
| border: none; | |
| color: white; | |
| font-weight: bold; | |
| padding: 8px 16px; | |
| border-radius: 20px; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| } | |
| .watch-button:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15); | |
| background: linear-gradient(45deg, #00b4e6, #0066cc); | |
| } | |
| .watch-button i { | |
| margin-right: 8px; | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen"> | |
| <div id="particles-js"></div> | |
| <!-- Header --> | |
| <header class="py-4 px-6 border-b border-gray-800 flex justify-between items-center"> | |
| <div class="flex items-center space-x-4"> | |
| <div class="w-12 h-12 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full flex items-center justify-center"> | |
| <i class="fas fa-play text-xl"></i> | |
| </div> | |
| <h1 class="text-3xl font-futurist glow">NEXUS<span class="glow-secondary">FLIX</span></h1> | |
| </div> | |
| <div class="flex items-center space-x-6"> | |
| <div class="relative"> | |
| <input type="text" id="searchInput" placeholder="Recherche quantique..." class="cyber-input w-64"> | |
| <button class="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400"> | |
| <i class="fas fa-search"></i> | |
| </button> | |
| </div> | |
| <div class="flex items-center space-x-2"> | |
| <div class="w-10 h-10 rounded-full bg-gradient-to-br from-blue-400 to-purple-500 flex items-center justify-center"> | |
| <i class="fas fa-user"></i> | |
| </div> | |
| <span class="font-bold">Admin</span> | |
| </div> | |
| </div> | |
| </header> | |
| <div class="flex"> | |
| <!-- Sidebar --> | |
| <aside class="w-64 min-h-screen bg-gray-900 bg-opacity-70 border-r border-gray-800 p-4"> | |
| <nav class="space-y-6"> | |
| <div> | |
| <h3 class="text-xs uppercase tracking-wider text-gray-400 mb-3 font-futurist">Navigation</h3> | |
| <ul class="space-y-2"> | |
| <li> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 rounded-lg bg-blue-900 bg-opacity-30 text-blue-300"> | |
| <i class="fas fa-home"></i> | |
| <span>Tableau de bord</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 rounded-lg hover:bg-gray-800 hover:text-white"> | |
| <i class="fas fa-film"></i> | |
| <span>Bibliothèque</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 rounded-lg hover:bg-gray-800 hover:text-white"> | |
| <i class="fas fa-tv"></i> | |
| <span>Streams</span> | |
| </a> | |
| </li> | |
| <li> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 rounded-lg hover:bg-gray-800 hover:text-white"> | |
| <i class="fas fa-robot"></i> | |
| <span>Serveurs Robots</span> | |
| </a> | |
| </li> | |
| </ul> | |
| </div> | |
| <div> | |
| <h3 class="text-xs uppercase tracking-wider text-gray-400 mb-3 font-futurist">Filtres</h3> | |
| <div class="space-y-3"> | |
| <div> | |
| <label class="block text-sm text-gray-300 mb-1">Qualité</label> | |
| <select id="qualityFilter" class="cyber-input w-full"> | |
| <option value="all">Toutes</option> | |
| <option value="PM4" class="PM4">PM4</option> | |
| <option value="EMB" class="EMB">EMB</option> | |
| <option value="HD" class="HD">HD</option> | |
| <option value="UHD" class="UHD">UHD</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm text-gray-300 mb-1">Langue</label> | |
| <select id="languageFilter" class="cyber-input w-full"> | |
| <option value="all">Toutes</option> | |
| <option value="FR">Français</option> | |
| <option value="EN">Anglais</option> | |
| <option value="DE">Allemand</option> | |
| <option value="ES">Espagnol</option> | |
| <option value="JP">Japonais</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm text-gray-300 mb-1">Année</label> | |
| <div class="flex items-center space-x-2"> | |
| <input type="number" id="yearFrom" min="1900" max="2023" placeholder="De" class="cyber-input w-1/2"> | |
| <input type="number" id="yearTo" min="1900" max="2023" placeholder="À" class="cyber-input w-1/2"> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="pt-4 border-t border-gray-800"> | |
| <h3 class="text-xs uppercase tracking-wider text-gray-400 mb-3 font-futurist">Statistiques</h3> | |
| <div class="space-y-2"> | |
| <div class="flex justify-between text-sm"> | |
| <span>Films:</span> | |
| <span id="totalMovies" class="font-bold">Chargement...</span> | |
| </div> | |
| <div class="flex justify-between text-sm"> | |
| <span>Serveurs actifs:</span> | |
| <span id="activeServers" class="font-bold">12/12</span> | |
| </div> | |
| <div class="flex justify-between text-sm"> | |
| <span>Liens trouvés:</span> | |
| <span id="totalLinks" class="font-bold">0</span> | |
| </div> | |
| </div> | |
| </div> | |
| </nav> | |
| </aside> | |
| <!-- Main Content --> | |
| <main class="flex-1 p-6"> | |
| <div class="mb-8"> | |
| <h2 class="text-2xl font-futurist glow mb-4">Lecteur Holographique Nexus</h2> | |
| <div class="player-container neon-border rounded-lg overflow-hidden scanline" id="mainPlayer"> | |
| <div class="absolute inset-0 flex items-center justify-center bg-black"> | |
| <div class="text-center"> | |
| <div class="w-16 h-16 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-4"></div> | |
| <p class="text-xl font-futurist">Sélectionnez un film pour commencer</p> | |
| <p class="text-sm text-gray-400 mt-2">Le lecteur quantique est prêt</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mt-4 hidden" id="playerInfo"> | |
| <div class="flex items-center justify-between"> | |
| <div> | |
| <h3 class="text-xl font-bold" id="currentMovieTitle">Titre du film</h3> | |
| <div class="flex items-center space-x-4 text-sm text-gray-400 mt-1"> | |
| <span id="currentMovieYear">2023</span> | |
| <span id="currentMovieRating">PG-13</span> | |
| <span id="currentMovieDuration">2h 00min</span> | |
| <span class="flex items-center"> | |
| <i class="fas fa-star text-yellow-400 mr-1"></i> | |
| <span id="currentMovieScore">0.0</span>/10 | |
| </span> | |
| </div> | |
| </div> | |
| <div class="flex space-x-3"> | |
| <button class="cyber-button px-4 py-2 text-sm" id="downloadBtn"> | |
| <i class="fas fa-download mr-2"></i> Télécharger | |
| </button> | |
| <button class="cyber-button px-4 py-2 text-sm bg-gradient-to-br from-purple-500 to-pink-500" id="alternateLinksBtn"> | |
| <i class="fas fa-link mr-2"></i> Liens Alternatifs | |
| </button> | |
| </div> | |
| </div> | |
| <div class="mt-4" id="serverLinksContainer"> | |
| <h4 class="text-sm font-bold mb-2">Serveurs disponibles:</h4> | |
| <div id="serverLinks" class="flex flex-wrap"> | |
| <!-- Server links will be added here by JavaScript --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mb-8"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h2 class="text-xl font-futurist glow">Serveurs Automatiques</h2> | |
| <div class="flex items-center space-x-2"> | |
| <span class="text-xs bg-green-500 px-2 py-1 rounded-full flex items-center"> | |
| <i class="fas fa-circle text-xs mr-1"></i> <span id="onlineCount">12</span> EN LIGNE | |
| </span> | |
| <button id="refreshServersBtn" class="text-xs bg-blue-600 hover:bg-blue-700 px-3 py-1 rounded"> | |
| <i class="fas fa-sync-alt mr-1"></i> Actualiser | |
| </button> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" id="serversGrid"> | |
| <!-- Server cards will be loaded here --> | |
| <div class="server-card FR bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur FR-1</span> | |
| <span class="ml-2 text-xs bg-blue-600 px-2 py-1 rounded">FR</span> | |
| </h3> | |
| <span class="text-xs PM4">UHD</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Paris, France</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">28ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card FR bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur FR-2</span> | |
| <span class="ml-2 text-xs bg-blue-600 px-2 py-1 rounded">FR</span> | |
| </h3> | |
| <span class="text-xs HD">HD</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Lyon, France</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">35ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card US bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur US-1</span> | |
| <span class="ml-2 text-xs bg-red-600 px-2 py-1 rounded">US</span> | |
| </h3> | |
| <span class="text-xs UHD">UHD</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">New York, USA</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">98ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card US bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur US-2</span> | |
| <span class="ml-2 text-xs bg-red-600 px-2 py-1 rounded">US</span> | |
| </h3> | |
| <span class="text-xs HD">HD</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Los Angeles, USA</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">112ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card UK bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur UK-1</span> | |
| <span class="ml-2 text-xs bg-purple-600 px-2 py-1 rounded">UK</span> | |
| </h3> | |
| <span class="text-xs UHD">UHD</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Londres, UK</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">45ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card DE bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur DE-1</span> | |
| <span class="ml-2 text-xs bg-yellow-500 px-2 py-1 rounded">DE</span> | |
| </h3> | |
| <span class="text-xs HD">HD</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Berlin, Allemagne</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">52ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card JP bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur JP-1</span> | |
| <span class="ml-2 text-xs bg-red-500 px-2 py-1 rounded">JP</span> | |
| </h3> | |
| <span class="text-xs UHD">UHD</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Tokyo, Japon</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">210ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card CA bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur CA-1</span> | |
| <span class="ml-2 text-xs bg-green-600 px-2 py-1 rounded">CA</span> | |
| </h3> | |
| <span class="text-xs HD">HD</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Montréal, Canada</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">85ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card FR bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur FR-3</span> | |
| <span class="ml-2 text-xs bg-blue-600 px-2 py-1 rounded">FR</span> | |
| </h3> | |
| <span class="text-xs EMB">EMB</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Marseille, France</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">42ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card US bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur US-3</span> | |
| <span class="ml-2 text-xs bg-red-600 px-2 py-1 rounded">US</span> | |
| </h3> | |
| <span class="text-xs PM4">PM4</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Chicago, USA</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">105ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card UK bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur UK-2</span> | |
| <span class="ml-2 text-xs bg-purple-600 px-2 py-1 rounded">UK</span> | |
| </h3> | |
| <span class="text-xs HD">HD</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Manchester, UK</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">48ms</span></span> | |
| </div> | |
| </div> | |
| <div class="server-card DE bg-gray-800 bg-opacity-70 rounded p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <h3 class="font-bold flex items-center"> | |
| <span class="server-status online"></span> | |
| <span>Serveur DE-2</span> | |
| <span class="ml-2 text-xs bg-yellow-500 px-2 py-1 rounded">DE</span> | |
| </h3> | |
| <span class="text-xs UHD">UHD</span> | |
| </div> | |
| <p class="text-xs text-gray-400 mb-3">Munich, Allemagne</p> | |
| <div class="flex justify-between text-xs"> | |
| <span>Liens trouvés: <span class="font-bold">0</span></span> | |
| <span>Latence: <span class="font-bold">55ms</span></span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Nouvelle section pour les films de votre liste --> | |
| <div class="mb-8"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h2 class="text-xl font-futurist glow">Collection Premium</h2> | |
| <div class="flex items-center space-x-2"> | |
| <button id="refreshPremiumBtn" class="text-xs bg-blue-600 hover:bg-blue-700 px-3 py-1 rounded"> | |
| <i class="fas fa-sync-alt mr-1"></i> Actualiser | |
| </button> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-6" id="premiumMoviesGrid"> | |
| <!-- Films premium seront chargés ici --> | |
| </div> | |
| </div> | |
| <div class="mb-8"> | |
| <div class="flex items-center justify-between mb-4"> | |
| <h2 class="text-xl font-futurist glow">Bibliothèque Cinématique</h2> | |
| <div class="flex items-center space-x-2"> | |
| <button id="refreshMoviesBtn" class="text-xs bg-blue-600 hover:bg-blue-700 px-3 py-1 rounded"> | |
| <i class="fas fa-sync-alt mr-1"></i> Actualiser | |
| </button> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-6" id="moviesGrid"> | |
| <!-- Movies will be loaded here by JavaScript --> | |
| <div class="col-span-full text-center py-10"> | |
| <div class="w-16 h-16 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-4"></div> | |
| <p class="text-xl font-futurist">Chargement de la bibliothèque...</p> | |
| <p class="text-sm text-gray-400 mt-2">Connexion aux serveurs multidimensionnels</p> | |
| </div> | |
| </div> | |
| <div class="mt-6 flex justify-center"> | |
| <button id="loadMoreBtn" class="cyber-button px-6 py-2 hidden"> | |
| <i class="fas fa-plus mr-2"></i> Charger plus | |
| </button> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <footer class="bg-gray-900 bg-opacity-70 border-t border-gray-800 p-4 text-center text-sm text-gray-400 font-futurist"> | |
| <p>NEXUSFLIX SYSTEM v4.2 - © 2023 Tous droits réservés - Accès API: <span id="totalMoviesFooter">0</span> films multidimensionnels</p> | |
| </footer> | |
| <!-- Movie Details Modal --> | |
| <div id="movieModal" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden"> | |
| <div class="holographic-card w-11/12 max-w-4xl max-h-screen overflow-y-auto"> | |
| <div class="p-6"> | |
| <div class="flex justify-between items-start mb-4"> | |
| <div> | |
| <h2 class="text-2xl font-bold" id="modalMovieTitle">Titre du film</h2> | |
| <div class="flex items-center space-x-4 text-sm text-gray-400 mt-1"> | |
| <span id="modalMovieYear">2023</span> | |
| <span id="modalMovieRating">PG-13</span> | |
| <span id="modalMovieDuration">2h 00min</span> | |
| <span class="flex items-center"> | |
| <i class="fas fa-star text-yellow-400 mr-1"></i> | |
| <span id="modalMovieScore">0.0</span>/10 | |
| </span> | |
| </div> | |
| </div> | |
| <button id="closeModal" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-times text-xl"></i> | |
| </button> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
| <div class="md:col-span-1"> | |
| <img id="modalMoviePoster" src="" alt="Poster" class="w-full rounded-lg"> | |
| </div> | |
| <div class="md:col-span-2"> | |
| <h3 class="font-bold mb-2">Synopsis</h3> | |
| <p id="modalMovieOverview" class="text-gray-300 mb-4">Chargement...</p> | |
| <h3 class="font-bold mb-2">Genres</h3> | |
| <div id="modalMovieGenres" class="flex flex-wrap gap-2 mb-4"> | |
| <!-- Genres will be added here --> | |
| </div> | |
| <h3 class="font-bold mb-2">Serveurs disponibles</h3> | |
| <div id="modalServerLinks" class="flex flex-wrap gap-2"> | |
| <!-- Server links will be added here --> | |
| </div> | |
| <!-- Bouton "Regarder maintenant" --> | |
| <button id="watchNowBtn" class="watch-button mt-6"> | |
| <i class="fas fa-play"></i> Regarder maintenant | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // API Configuration | |
| const API_KEY = 'fb437b10727a5a4eb8d9134e29c82ae0'; | |
| const BASE_URL = 'https://api.themoviedb.org/3'; | |
| const IMAGE_URL = 'https://image.tmdb.org/t/p/w500'; | |
| // Server Configuration | |
| const SERVERS = [ | |
| { id: 'FR-1', name: 'Serveur FR-1', location: 'Paris, France', country: 'FR', quality: 'UHD', latency: 28, status: 'online' }, | |
| { id: 'FR-2', name: 'Serveur FR-2', location: 'Lyon, France', country: 'FR', quality: 'HD', latency: 35, status: 'online' }, | |
| { id: 'FR-3', name: 'Serveur FR-3', location: 'Marseille, France', country: 'FR', quality: 'EMB', latency: 42, status: 'online' }, | |
| { id: 'US-1', name: 'Serveur US-1', location: 'New York, USA', country: 'US', quality: 'UHD', latency: 98, status: 'online' }, | |
| { id: 'US-2', name: 'Serveur US-2', location: 'Los Angeles, USA', country: 'US', quality: 'HD', latency: 112, status: 'online' }, | |
| { id: 'US-3', name: 'Serveur US-3', location: 'Chicago, USA', country: 'US', quality: 'PM4', latency: 105, status: 'online' }, | |
| { id: 'UK-1', name: 'Serveur UK-1', location: 'Londres, UK', country: 'UK', quality: 'UHD', latency: 45, status: 'online' }, | |
| { id: 'UK-2', name: 'Serveur UK-2', location: 'Manchester, UK', country: 'UK', quality: 'HD', latency: 48, status: 'online' }, | |
| { id: 'DE-1', name: 'Serveur DE-1', location: 'Berlin, Allemagne', country: 'DE', quality: 'HD', latency: 52, status: 'online' }, | |
| { id: 'DE-2', name: 'Serveur DE-2', location: 'Munich, Allemagne', country: 'DE', quality: 'UHD', latency: 55, status: 'online' }, | |
| { id: 'JP-1', name: 'Serveur JP-1', location: 'Tokyo, Japon', country: 'JP', quality: 'UHD', latency: 210, status: 'online' }, | |
| { id: 'CA-1', name: 'Serveur CA-1', location: 'Montréal, Canada', country: 'CA', quality: 'HD', latency: 85, status: 'online' } | |
| ]; | |
| // Votre liste de films | |
| const PREMIUM_MOVIES = { | |
| "page": 1, | |
| "results": [ | |
| { | |
| "imageurl": ["https://m.media-amazon.com/images/M/MV5BNzY3YTUwYTQtNjkwNy00OTAyLWE0OWEtYmE3MGIyOWZkODY1XkEyXkFqcGdeQXVyMjkyNzYwMTc@._V1_UX182_CR0,0,182,268_AL_.jpg"], | |
| "genre": ["Action", "Adventure", "Animation"], | |
| "imdbid": "tt9580138", | |
| "title": "Mortal Kombat Legends: Scorpion's Revenge", | |
| "imdbrating": 7.4, | |
| "released": 2020, | |
| "synopsis": "Hanzo Hasashi loses his clan, family, and his life during an attack by a rival ninja clan. He is given the chance to compete in an interdimensional tournament to save his loved ones.", | |
| "type": "movie" | |
| }, | |
| { | |
| "imageurl": ["https://m.media-amazon.com/images/M/MV5BMmUyYTU5MjItMGNhOC00ZGFhLTkwYjctMjBmNTlkOTIzYmM1XkEyXkFqcGdeQXVyOTUyOTM3MDc@._V1_UY268_CR110,0,182,268_AL_.jpg"], | |
| "genre": ["Action", "Adventure", "Drama"], | |
| "imdbid": "tt9286908", | |
| "title": "High Ground", | |
| "imdbrating": 6.5, | |
| "released": 2020, | |
| "synopsis": "In a bid to save the last of his family, Gutjuk, a young Aboriginal man, teams up with ex-soldier Travis to track down Baywara, the most dangerous warrior in the Territory, his uncle.", | |
| "type": "movie" | |
| }, | |
| { | |
| "imageurl": ["https://m.media-amazon.com/images/M/MV5BMDJiNzUwYzEtNmQ2Yy00NWE4LWEwNzctM2M0MjE0OGUxZTA3XkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_UX182_CR0,0,182,268_AL_.jpg"], | |
| "genre": ["Action", "Thriller"], | |
| "imdbid": "tt8936646", | |
| "title": "Extraction", | |
| "imdbrating": 6.7, | |
| "released": 2020, | |
| "synopsis": "Tyler Rake, a fearless black market mercenary, embarks on the most deadly extraction of his career when he's enlisted to rescue the kidnapped son of an imprisoned international crime lord.", | |
| "type": "movie" | |
| }, | |
| { | |
| "imageurl": ["https://m.media-amazon.com/images/M/MV5BNzU1ZTE4YzAtOWNkYi00YWE4LThmY2YtMDNlYzU2ZTgxYTc2XkEyXkFqcGdeQXVyODQzNTE3ODc@._V1_UX182_CR0,0,182,268_AL_.jpg"], | |
| "genre": ["Action", "Comedy", "Crime"], | |
| "imdbid": "tt8851668", | |
| "title": "The Lovebirds", | |
| "imdbrating": 6, | |
| "released": 2020, | |
| "type": "movie", | |
| "synopsis": "A couple (Issa Rae and Kumail Nanjiani) experiences a defining moment in their relationship when they are unintentionally embroiled in a murder mystery." | |
| }, | |
| { | |
| "imageurl": ["https://m.media-amazon.com/images/M/MV5BNDJiZDliZDAtMjc5Yy00MzVhLThkY2MtNDYwNTQ2ZTM5MDcxXkEyXkFqcGdeQXVyMDA4NzMyOA@@._V1_UX182_CR0,0,182,268_AL_.jpg"], | |
| "genre": ["Action", "Adventure", "Fantasy"], | |
| "imdbid": "tt7556122", | |
| "title": "The Old Guard", | |
| "imdbrating": 6.6, | |
| "released": 2020, | |
| "type": "movie", | |
| "synopsis": "A covert team of immortal mercenaries are suddenly exposed and must now fight to keep their identity a secret just as an unexpected new member is discovered." | |
| }, | |
| { | |
| "imageurl": ["https://m.media-amazon.com/images/M/MV5BYjE2MjIwMmYtM2ZiMy00MzdmLTkyNTYtNmFiNjM5MDJhMGVmXkEyXkFqcGdeQXVyODk4OTc3MTY@._V1_UX182_CR0,0,182,268_AL_.jpg"], | |
| "genre": ["Action", "Crime", "Mystery"], | |
| "imdbid": "tt7149730", | |
| "title": "The Silencing", | |
| "imdbrating": 6.2, | |
| "released": 2020, | |
| "type": "movie", | |
| "synopsis": "A reformed hunter living in isolation on a wildlife sanctuary becomes involved in a deadly game of cat and mouse when he and the local Sheriff set out to track a vicious killer who may have kidnapped his daughter years ago." | |
| }, | |
| { | |
| "imageurl": ["https://m.media-amazon.com/images/M/MV5BOGJlMTc5YmYtYjFlNi00ZDJiLWFhNWMtMjc0NDBjOWNkNjA1XkEyXkFqcGdeQXVyMTA5NzExNzM1._V1_UY268_CR110,0,182,268_AL_.jpg"], | |
| "genre": ["Action", "Crime", "Drama"], | |
| "imdbid": "tt1838556", | |
| "title": "Honest Thief", | |
| "imdbrating": 6, | |
| "released": 2020, | |
| "type": "movie", | |
| "synopsis": "A bank robber tries to turn himself in because he's falling in love and wants to live an honest life...but when he realizes the Feds are more corrupt than him, he must fight back to clear his name." | |
| }, | |
| { | |
| "imageurl": ["https://m.media-amazon.com/images/M/MV5BMWU0MGYwZWQtMzcwYS00NWVhLTlkZTAtYWVjOTYwZTBhZTBiXkEyXkFqcGdeQXVyMTkxNjUyNQ@@._V1_UX182_CR0,0,182,268_AL_.jpg"], | |
| "genre": ["Action", "Comedy", "Crime"], | |
| "imdbid": "tt1502397", | |
| "title": "Bad Boys for Life", | |
| "imdbrating": 6.5, | |
| "released": 2020, | |
| "synopsis": "Miami detectives Mike Lowrey and Marcus Burnett must face off against a mother-and-son pair of drug lords who wreak vengeful havoc on their city.", | |
| "type": "movie" | |
| } | |
| ] | |
| }; | |
| // State | |
| let currentPage = 1; | |
| let totalPages = 1; | |
| let currentMovies = []; | |
| let genres = []; | |
| let activeStreams = {}; | |
| let currentModalMovie = null; | |
| // DOM Elements | |
| const moviesGrid = document.getElementById('moviesGrid'); | |
| const premiumMoviesGrid = document.getElementById('premiumMoviesGrid'); | |
| const loadMoreBtn = document.getElementById('loadMoreBtn'); | |
| const searchInput = document.getElementById('searchInput'); | |
| const qualityFilter = document.getElementById('qualityFilter'); | |
| const languageFilter = document.getElementById('languageFilter'); | |
| const yearFrom = document.getElementById('yearFrom'); | |
| const yearTo = document.getElementById('yearTo'); | |
| const refreshMoviesBtn = document.getElementById('refreshMoviesBtn'); | |
| const refreshPremiumBtn = document.getElementById('refreshPremiumBtn'); | |
| const refreshServersBtn = document.getElementById('refreshServersBtn'); | |
| const totalMoviesFooter = document.getElementById('totalMoviesFooter'); | |
| const totalMoviesEl = document.getElementById('totalMovies'); | |
| const onlineCount = document.getElementById('onlineCount'); | |
| const mainPlayer = document.getElementById('mainPlayer'); | |
| const playerInfo = document.getElementById('playerInfo'); | |
| const currentMovieTitle = document.getElementById('currentMovieTitle'); | |
| const currentMovieYear = document.getElementById('currentMovieYear'); | |
| const currentMovieRating = document.getElementById('currentMovieRating'); | |
| const currentMovieDuration = document.getElementById('currentMovieDuration'); | |
| const currentMovieScore = document.getElementById('currentMovieScore'); | |
| const serverLinks = document.getElementById('serverLinks'); | |
| const downloadBtn = document.getElementById('downloadBtn'); | |
| const alternateLinksBtn = document.getElementById('alternateLinksBtn'); | |
| const movieModal = document.getElementById('movieModal'); | |
| const modalMovieTitle = document.getElementById('modalMovieTitle'); | |
| const modalMovieYear = document.getElementById('modalMovieYear'); | |
| const modalMovieRating = document.getElementById('modalMovieRating'); | |
| const modalMovieDuration = document.getElementById('modalMovieDuration'); | |
| const modalMovieScore = document.getElementById('modalMovieScore'); | |
| const modalMoviePoster = document.getElementById('modalMoviePoster'); | |
| const modalMovieOverview = document.getElementById('modalMovieOverview'); | |
| const modalMovieGenres = document.getElementById('modalMovieGenres'); | |
| const modalServerLinks = document.getElementById('modalServerLinks'); | |
| const closeModal = document.getElementById('closeModal'); | |
| const watchNowBtn = document.getElementById('watchNowBtn'); | |
| const serversGrid = document.getElementById('serversGrid'); | |
| const totalLinks = document.getElementById('totalLinks'); | |
| // Initialize | |
| document.addEventListener('DOMContentLoaded', function() { | |
| initParticles(); | |
| loadGenres(); | |
| loadMovies(); | |
| loadPremiumMovies(); | |
| updateServerStatus(); | |
| // Event listeners | |
| loadMoreBtn.addEventListener('click', loadMoreMovies); | |
| refreshMoviesBtn.addEventListener('click', refreshMovies); | |
| refreshPremiumBtn.addEventListener('click', loadPremiumMovies); | |
| refreshServersBtn.addEventListener('click', refreshServers); | |
| searchInput.addEventListener('keyup', function(e) { | |
| if (e.key === 'Enter') { | |
| currentPage = 1; | |
| loadMovies(); | |
| } | |
| }); | |
| qualityFilter.addEventListener('change', function() { | |
| currentPage = 1; | |
| loadMovies(); | |
| }); | |
| languageFilter.addEventListener('change', function() { | |
| currentPage = 1; | |
| loadMovies(); | |
| }); | |
| yearFrom.addEventListener('change', function() { | |
| currentPage = 1; | |
| loadMovies(); | |
| }); | |
| yearTo.addEventListener('change', function() { | |
| currentPage = 1; | |
| loadMovies(); | |
| }); | |
| closeModal.addEventListener('click', function() { | |
| movieModal.classList.add('hidden'); | |
| }); | |
| watchNowBtn.addEventListener('click', function() { | |
| if (currentModalMovie) { | |
| playMovie(currentModalMovie.id, currentModalMovie.title, currentModalMovie.vote_average, | |
| currentModalMovie.release_date ? currentModalMovie.release_date.substring(0, 4) : 'N/A'); | |
| movieModal.classList.add('hidden'); | |
| } | |
| }); | |
| // Simulate finding links periodically | |
| setInterval(simulateFindingLinks, 5000); | |
| }); | |
| // Initialize particles.js | |
| function initParticles() { | |
| particlesJS('particles-js', { | |
| "particles": { | |
| "number": { | |
| "value": 80, | |
| "density": { | |
| "enable": true, | |
| "value_area": 800 | |
| } | |
| }, | |
| "color": { | |
| "value": "#00f0ff" | |
| }, | |
| "shape": { | |
| "type": "circle", | |
| "stroke": { | |
| "width": 0, | |
| "color": "#000000" | |
| }, | |
| "polygon": { | |
| "nb_sides": 5 | |
| } | |
| }, | |
| "opacity": { | |
| "value": 0.5, | |
| "random": false, | |
| "anim": { | |
| "enable": false, | |
| "speed": 1, | |
| "opacity_min": 0.1, | |
| "sync": false | |
| } | |
| }, | |
| "size": { | |
| "value": 3, | |
| "random": true, | |
| "anim": { | |
| "enable": false, | |
| "speed": 40, | |
| "size_min": 0.1, | |
| "sync": false | |
| } | |
| }, | |
| "line_linked": { | |
| "enable": true, | |
| "distance": 150, | |
| "color": "#00f0ff", | |
| "opacity": 0.2, | |
| "width": 1 | |
| }, | |
| "move": { | |
| "enable": true, | |
| "speed": 2, | |
| "direction": "none", | |
| "random": false, | |
| "straight": false, | |
| "out_mode": "out", | |
| bounce: false, | |
| "attract": { | |
| "enable": false, | |
| "rotateX": 600, | |
| "rotateY": 1200 | |
| } | |
| } | |
| }, | |
| "interactivity": { | |
| "detect_on": "canvas", | |
| "events": { | |
| "onhover": { | |
| "enable": true, | |
| "mode": "grab" | |
| }, | |
| "onclick": { | |
| "enable": true, | |
| "mode": "push" | |
| }, | |
| "resize": true | |
| }, | |
| "modes": { | |
| "grab": { | |
| "distance": 140, | |
| "line_linked": { | |
| "opacity": 1 | |
| } | |
| }, | |
| "bubble": { | |
| "distance": 400, | |
| "size": 40, | |
| "duration": 2, | |
| "opacity": 8, | |
| "speed": 3 | |
| }, | |
| "repulse": { | |
| "distance": 200, | |
| "duration": 0.4 | |
| }, | |
| "push": { | |
| "particles_nb": 4 | |
| }, | |
| "remove": { | |
| "particles_nb": 2 | |
| } | |
| } | |
| }, | |
| "retina_detect": true | |
| }); | |
| } | |
| // Load movie genres from TMDb | |
| function loadGenres() { | |
| fetch(`${BASE_URL}/genre/movie/list?api_key=${API_KEY}&language=fr-FR`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| genres = data.genres; | |
| populateGenreFilter(); | |
| }) | |
| .catch(error => { | |
| console.error('Error loading genres:', error); | |
| }); | |
| } | |
| // Load movies from TMDb | |
| function loadMovies() { | |
| const searchQuery = searchInput.value.trim(); | |
| const quality = qualityFilter.value; | |
| const language = languageFilter.value; | |
| const fromYear = yearFrom.value; | |
| const toYear = yearTo.value; | |
| let url; | |
| if (searchQuery) { | |
| url = `${BASE_URL}/search/movie?api_key=${API_KEY}&query=${encodeURIComponent(searchQuery)}&page=${currentPage}&language=fr-FR`; | |
| } else { | |
| url = `${BASE_URL}/discover/movie?api_key=${API_KEY}&page=${currentPage}&language=fr-FR&sort_by=popularity.desc`; | |
| if (language !== 'all') { | |
| url += `&with_original_language=${language.toLowerCase()}`; | |
| } | |
| if (fromYear) { | |
| url += `&primary_release_date.gte=${fromYear}-01-01`; | |
| } | |
| if (toYear) { | |
| url += `&primary_release_date.lte=${toYear}-12-31`; | |
| } | |
| } | |
| moviesGrid.innerHTML = ` | |
| <div class="col-span-full text-center py-10"> | |
| <div class="w-16 h-16 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-4"></div> | |
| <p class="text-xl font-futurist">Chargement des films...</p> | |
| <p class="text-sm text-gray-400 mt-2">Connexion aux serveurs multidimensionnels</p> | |
| </div> | |
| `; | |
| fetch(url) | |
| .then(response => response.json()) | |
| .then(data => { | |
| totalPages = data.total_pages; | |
| currentMovies = data.results; | |
| if (currentPage === 1) { | |
| moviesGrid.innerHTML = ''; | |
| totalMoviesFooter.textContent = data.total_results.toLocaleString(); | |
| totalMoviesEl.textContent = data.total_results.toLocaleString(); | |
| } | |
| displayMovies(currentMovies); | |
| if (currentPage < totalPages) { | |
| loadMoreBtn.classList.remove('hidden'); | |
| } else { | |
| loadMoreBtn.classList.add('hidden'); | |
| } | |
| }) | |
| .catch(error => { | |
| console.error('Error loading movies:', error); | |
| moviesGrid.innerHTML = ` | |
| <div class="col-span-full text-center py-10"> | |
| <i class="fas fa-exclamation-triangle text-red-500 text-4xl mb-4"></i> | |
| <p class="text-xl font-futurist">Erreur de chargement</p> | |
| <p class="text-sm text-gray-400 mt-2">Impossible de se connecter aux serveurs</p> | |
| </div> | |
| `; | |
| }); | |
| } | |
| // Load premium movies from your list | |
| function loadPremiumMovies() { | |
| premiumMoviesGrid.innerHTML = ''; | |
| PREMIUM_MOVIES.results.forEach(movie => { | |
| const movieCard = document.createElement('div'); | |
| movieCard.className = 'holographic-card rounded-lg overflow-hidden transition-transform hover:scale-105 hover:z-10 flicker'; | |
| const posterUrl = movie.imageurl && movie.imageurl.length > 0 ? movie.imageurl[0] : ''; | |
| movieCard.innerHTML = ` | |
| <div class="relative"> | |
| ${posterUrl ? | |
| `<img src="${posterUrl}" alt="${movie.title}" class="w-full h-64 object-cover cursor-pointer" onclick="showPremiumMovieDetails('${movie.imdbid}')">` : | |
| `<div class="w-full h-64 bg-gray-800 flex items-center justify-center cursor-pointer" onclick="showPremiumMovieDetails('${movie.imdbid}')"> | |
| <i class="fas fa-film text-4xl text-gray-600"></i> | |
| </div>` | |
| } | |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black to-transparent p-2"> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-xs ${getRandomQualityClass()} px-2 py-1 rounded">${getRandomQuality()}</span> | |
| <span class="text-xs bg-yellow-600 px-2 py-1 rounded flex items-center"> | |
| <i class="fas fa-star text-xs mr-1"></i> ${movie.imdbrating.toFixed(1)} | |
| </span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-3"> | |
| <h3 class="font-bold truncate">${movie.title}</h3> | |
| <p class="text-xs text-gray-400">${movie.released} • ${movie.genre.slice(0, 2).join(', ')}</p> | |
| <div class="mt-4 flex justify-between items-center"> | |
| <button class="watch-button" onclick="playPremiumMovie('${movie.imdbid}', '${movie.title}', ${movie.imdbrating}, ${movie.released})"> | |
| <i class="fas fa-play"></i> Regarder | |
| </button> | |
| <div class="flex space-x-1"> | |
| <button class="text-xs bg-gray-700 hover:bg-gray-600 w-6 h-6 rounded-full flex items-center justify-center" onclick="event.stopPropagation(); addToFavorites('${movie.imdbid}')"> | |
| <i class="fas fa-plus text-xs"></i> | |
| </button> | |
| <button class="text-xs bg-gray-700 hover:bg-gray-600 w-6 h-6 rounded-full flex items-center justify-center" onclick="event.stopPropagation(); showDownloadOptions('${movie.imdbid}')"> | |
| <i class="fas fa-download text-xs"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| premiumMoviesGrid.appendChild(movieCard); | |
| }); | |
| } | |
| // Display movies in the grid | |
| function displayMovies(movies) { | |
| movies.forEach(movie => { | |
| const movieCard = document.createElement('div'); | |
| movieCard.className = 'holographic-card rounded-lg overflow-hidden transition-transform hover:scale-105 hover:z-10 flicker'; | |
| movieCard.innerHTML = ` | |
| <div class="relative"> | |
| ${movie.poster_path ? | |
| `<img src="${IMAGE_URL}${movie.poster_path}" alt="${movie.title}" class="w-full h-64 object-cover cursor-pointer" onclick="showMovieDetails(${movie.id})">` : | |
| `<div class="w-full h-64 bg-gray-800 flex items-center justify-center cursor-pointer" onclick="showMovieDetails(${movie.id})"> | |
| <i class="fas fa-film text-4xl text-gray-600"></i> | |
| </div>` | |
| } | |
| <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black to-transparent p-2"> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-xs ${getRandomQualityClass()} px-2 py-1 rounded">${getRandomQuality()}</span> | |
| <span class="text-xs bg-yellow-600 px-2 py-1 rounded flex items-center"> | |
| <i class="fas fa-star text-xs mr-1"></i> ${movie.vote_average.toFixed(1)} | |
| </span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="p-3"> | |
| <h3 class="font-bold truncate">${movie.title}</h3> | |
| <p class="text-xs text-gray-400">${movie.release_date ? movie.release_date.substring(0, 4) : 'N/A'} • ${getMovieGenres(movie.genre_ids)}</p> | |
| <div class="mt-4 flex justify-between items-center"> | |
| <button class="watch-button" onclick="playMovie(${movie.id}, '${movie.title}', ${movie.vote_average}, '${movie.release_date ? movie.release_date.substring(0, 4) : 'N/A'}')"> | |
| <i class="fas fa-play"></i> Regarder | |
| </button> | |
| <div class="flex space-x-1"> | |
| <button class="text-xs bg-gray-700 hover:bg-gray-600 w-6 h-6 rounded-full flex items-center justify-center" onclick="event.stopPropagation(); addToFavorites(${movie.id})"> | |
| <i class="fas fa-plus text-xs"></i> | |
| </button> | |
| <button class="text-xs bg-gray-700 hover:bg-gray-600 w-6 h-6 rounded-full flex items-center justify-center" onclick="event.stopPropagation(); showDownloadOptions(${movie.id})"> | |
| <i class="fas fa-download text-xs"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| moviesGrid.appendChild(movieCard); | |
| }); | |
| } | |
| // Get random quality for demo purposes | |
| function getRandomQuality() { | |
| const qualities = ['PM4', 'EMB', 'HD', 'UHD']; | |
| return qualities[Math.floor(Math.random() * qualities.length)]; | |
| } | |
| // Get random quality class for demo purposes | |
| function getRandomQualityClass() { | |
| const qualityClasses = ['PM4', 'EMB', 'HD', 'UHD']; | |
| return qualityClasses[Math.floor(Math.random() * qualityClasses.length)]; | |
| } | |
| // Get movie genres as string | |
| function getMovieGenres(genreIds) { | |
| if (!genreIds || !genres.length) return 'N/A'; | |
| const movieGenres = genres.filter(genre => genreIds.includes(genre.id)); | |
| return movieGenres.slice(0, 2).map(genre => genre.name).join(', '); | |
| } | |
| // Load more movies | |
| function loadMoreMovies() { | |
| currentPage++; | |
| loadMovies(); | |
| } | |
| // Refresh movies | |
| function refreshMovies() { | |
| currentPage = 1; | |
| loadMovies(); | |
| } | |
| // Refresh servers | |
| function refreshServers() { | |
| // Simulate refreshing servers | |
| document.querySelectorAll('.server-status').forEach(status => { | |
| status.classList.remove('online', 'offline', 'loading'); | |
| status.classList.add('loading'); | |
| }); | |
| setTimeout(() => { | |
| updateServerStatus(); | |
| }, 1500); | |
| } | |
| // Update server status | |
| function updateServerStatus() { | |
| let onlineCount = 0; | |
| SERVERS.forEach(server => { | |
| // Randomly set status (90% chance online) | |
| server.status = Math.random() > 0.1 ? 'online' : 'offline'; | |
| if (server.status === 'online') onlineCount++; | |
| // Update latency slightly | |
| server.latency = Math.max(10, server.latency + Math.floor(Math.random() * 20) - 10); | |
| // Find server card and update | |
| const serverCard = document.querySelector(`.server-card.${server.id}`); | |
| if (serverCard) { | |
| const statusElement = serverCard.querySelector('.server-status'); | |
| const latencyElement = serverCard.querySelector('span.font-bold:last-child'); | |
| if (statusElement) { | |
| statusElement.classList.remove('online', 'offline', 'loading'); | |
| statusElement.classList.add(server.status); | |
| } | |
| if (latencyElement) { | |
| latencyElement.textContent = `${server.latency}ms`; | |
| } | |
| } | |
| }); | |
| document.getElementById('onlineCount').textContent = onlineCount; | |
| } | |
| // Simulate finding links periodically | |
| function simulateFindingLinks() { | |
| let totalLinksFound = 0; | |
| SERVERS.forEach(server => { | |
| if (server.status === 'online') { | |
| // Randomly find 0-5 links per server | |
| const linksFound = Math.floor(Math.random() * 6); | |
| totalLinksFound += linksFound; | |
| // Update server card | |
| const serverCard = document.querySelector(`.server-card.${server.id}`); | |
| if (serverCard) { | |
| const linksElement = serverCard.querySelector('span.font-bold:first-child'); | |
| if (linksElement) { | |
| linksElement.textContent = linksFound; | |
| } | |
| } | |
| } | |
| }); | |
| document.getElementById('totalLinks').textContent = totalLinksFound; | |
| } | |
| // Show premium movie details in modal | |
| function showPremiumMovieDetails(imdbId) { | |
| const movie = PREMIUM_MOVIES.results.find(m => m.imdbid === imdbId); | |
| if (!movie) return; | |
| currentModalMovie = { | |
| id: movie.imdbid, | |
| title: movie.title, | |
| vote_average: movie.imdbrating, | |
| release_date: movie.released.toString(), | |
| overview: movie.synopsis || 'Aucune description disponible.', | |
| genres: movie.genre.map(name => ({ name })), | |
| poster_path: movie.imageurl && movie.imageurl.length > 0 ? movie.imageurl[0] : null | |
| }; | |
| modalMovieTitle.textContent = movie.title; | |
| modalMovieYear.textContent = movie.released; | |
| modalMovieRating.textContent = 'PG-13'; // Default rating | |
| modalMovieDuration.textContent = 'N/A'; // Default duration | |
| modalMovieScore.textContent = movie.imdbrating.toFixed(1); | |
| modalMovieOverview.textContent = movie.synopsis || 'Aucune description disponible.'; | |
| if (movie.imageurl && movie.imageurl.length > 0) { | |
| modalMoviePoster.src = movie.imageurl[0]; | |
| modalMoviePoster.alt = movie.title; | |
| } else { | |
| modalMoviePoster.src = ''; | |
| modalMoviePoster.alt = 'Poster non disponible'; | |
| } | |
| // Display genres | |
| modalMovieGenres.innerHTML = ''; | |
| if (movie.genre && movie.genre.length) { | |
| movie.genre.slice(0, 3).forEach(genre => { | |
| const genreBadge = document.createElement('span'); | |
| genreBadge.className = 'text-xs bg-gray-700 px-2 py-1 rounded'; | |
| genreBadge.textContent = genre; | |
| modalMovieGenres.appendChild(genreBadge); | |
| }); | |
| } | |
| // Display server links | |
| modalServerLinks.innerHTML = ''; | |
| SERVERS.forEach(server => { | |
| if (server.status === 'online') { | |
| const serverLink = document.createElement('a'); | |
| serverLink.className = `server-link ${server.quality}`; | |
| serverLink.href = '#'; | |
| serverLink.onclick = function(e) { | |
| e.preventDefault(); | |
| playPremiumMovie(movie.imdbid, movie.title, movie.imdbrating, movie.released); | |
| }; | |
| serverLink.innerHTML = ` | |
| <i class="fas fa-server mr-1"></i> ${server.name} <span class="${server.quality}">${server.quality}</span> | |
| <span class="text-xs ml-2">${server.latency}ms</span> | |
| `; | |
| modalServerLinks.appendChild(serverLink); | |
| } | |
| }); | |
| movieModal.classList.remove('hidden'); | |
| } | |
| // Play premium movie in main player | |
| function playPremiumMovie(imdbId, title, rating, year) { | |
| const movie = PREMIUM_MOVIES.results.find(m => m.imdbid === imdbId); | |
| if (!movie) return; | |
| currentMovieTitle.textContent = title; | |
| currentMovieYear.textContent = year; | |
| currentMovieRating.textContent = 'PG-13'; | |
| currentMovieDuration.textContent = 'N/A'; | |
| currentMovieScore.textContent = rating.toFixed(1); | |
| // Find best server (lowest latency, highest quality) | |
| const bestServer = SERVERS | |
| .filter(s => s.status === 'online') | |
| .sort((a, b) => { | |
| // Prioritize UHD, then HD, etc. | |
| const qualityOrder = { 'UHD': 4, 'HD': 3, 'EMB': 2, 'PM4': 1 }; | |
| const aQuality = qualityOrder[a.quality] || 0; | |
| const bQuality = qualityOrder[b.quality] || 0; | |
| if (aQuality !== bQuality) return bQuality - aQuality; | |
| return a.latency - b.latency; | |
| })[0]; | |
| // Simulate loading player | |
| mainPlayer.innerHTML = ` | |
| <div class="absolute inset-0 flex items-center justify-center bg-black"> | |
| <div class="text-center"> | |
| <div class="w-16 h-16 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-4"></div> | |
| <p class="text-xl font-futurist">Connexion au serveur ${bestServer.name}</p> | |
| <p class="text-sm text-gray-400 mt-2">Qualité: ${bestServer.quality} • Latence: ${bestServer.latency}ms</p> | |
| </div> | |
| </div> | |
| <div class="quality-badge ${bestServer.quality}">${bestServer.quality}</div> | |
| `; | |
| // Simulate player ready after delay | |
| setTimeout(() => { | |
| startPlayerStream({ | |
| id: imdbId, | |
| title: title, | |
| vote_average: rating, | |
| release_date: year.toString() | |
| }, bestServer); | |
| }, 2000); | |
| playerInfo.classList.remove('hidden'); | |
| } | |
| // Show movie details in modal | |
| function showMovieDetails(movieId) { | |
| fetch(`${BASE_URL}/movie/${movieId}?api_key=${API_KEY}&language=fr-FR`) | |
| .then(response => response.json()) | |
| .then(movie => { | |
| currentModalMovie = movie; | |
| modalMovieTitle.textContent = movie.title; | |
| modalMovieYear.textContent = movie.release_date ? movie.release_date.substring(0, 4) : 'N/A'; | |
| modalMovieRating.textContent = movie.adult ? 'R' : 'PG-13'; | |
| modalMovieDuration.textContent = movie.runtime ? `${Math.floor(movie.runtime / 60)}h ${movie.runtime % 60}min` : 'N/A'; | |
| modalMovieScore.textContent = movie.vote_average.toFixed(1); | |
| modalMovieOverview.textContent = movie.overview || 'Aucune description disponible.'; | |
| if (movie.poster_path) { | |
| modalMoviePoster.src = IMAGE_URL + movie.poster_path; | |
| modalMoviePoster.alt = movie.title; | |
| } else { | |
| modalMoviePoster.src = ''; | |
| modalMoviePoster.alt = 'Poster non disponible'; | |
| } | |
| // Display genres | |
| modalMovieGenres.innerHTML = ''; | |
| if (movie.genres && movie.genres.length) { | |
| movie.genres.forEach(genre => { | |
| const genreBadge = document.createElement('span'); | |
| genreBadge.className = 'text-xs bg-gray-700 px-2 py-1 rounded'; | |
| genreBadge.textContent = genre.name; | |
| modalMovieGenres.appendChild(genreBadge); | |
| }); | |
| } | |
| // Display server links | |
| modalServerLinks.innerHTML = ''; | |
| SERVERS.forEach(server => { | |
| if (server.status === 'online') { | |
| const serverLink = document.createElement('a'); | |
| serverLink.className = `server-link ${server.quality}`; | |
| serverLink.href = '#'; | |
| serverLink.onclick = function(e) { | |
| e.preventDefault(); | |
| playOnServer(server, movie); | |
| }; | |
| serverLink.innerHTML = ` | |
| <i class="fas fa-server mr-1"></i> ${server.name} <span class="${server.quality}">${server.quality}</span | |
| </html> |