v1.5.9 (Actuel)
This commit is contained in:
+113
-7
@@ -366,6 +366,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
document.querySelectorAll('input[name="trending-type"]').forEach(radio => {
|
||||
radio.addEventListener('change', renderTrending);
|
||||
});
|
||||
document.querySelectorAll('input[name="recent-type"]').forEach(radio => {
|
||||
radio.addEventListener('change', renderRecent);
|
||||
});
|
||||
|
||||
// --- HEARTBEAT : Détection source down + Refresh Tendances ---
|
||||
let wasOffline = false;
|
||||
@@ -840,6 +843,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (!movie.quality) movie.quality = qualityFromTitle;
|
||||
}
|
||||
|
||||
if (movie.year) parts.push(movie.year);
|
||||
if (movie.quality) parts.push(movie.quality);
|
||||
if (movie.lang) parts.push(movie.lang);
|
||||
subtitle = parts.join(' — ') || '';
|
||||
@@ -856,10 +860,22 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<div class="card-title">${cleanedTitle}</div>
|
||||
<div class="card-year">${typeBadge} ${subtitle}</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div class="card-year">${typeBadge} ${subtitle}</div>
|
||||
<a href="https://www.themoviedb.org/search?query=${encodeURIComponent(cleanedTitle)}" target="_blank" onclick="event.stopPropagation()" class="tmdb-link" title="Rechercher sur TMDB" style="color: var(--primary); opacity: 0.7; transition: opacity 0.2s;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M7 3v18"/><path d="M3 7.5h4"/><path d="M3 12h18"/><path d="M3 16.5h4"/><path d="M17 3v18"/><path d="M17 7.5h4"/><path d="M17 16.5h4"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
div.addEventListener('click', () => handleSelection(movie));
|
||||
|
||||
// Add hover effect for the TMDB link
|
||||
const tmdbLink = div.querySelector('.tmdb-link');
|
||||
if (tmdbLink) {
|
||||
tmdbLink.addEventListener('mouseenter', () => tmdbLink.style.opacity = '1');
|
||||
tmdbLink.addEventListener('mouseleave', () => tmdbLink.style.opacity = '0.7');
|
||||
}
|
||||
return div;
|
||||
};
|
||||
|
||||
@@ -900,12 +916,22 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const grid = dom('recent-grid');
|
||||
if (!grid) return;
|
||||
|
||||
const itemsToDisplay = state.trendingData.recent || [];
|
||||
// Get filter type from radio buttons
|
||||
const typeFilter = document.querySelector('input[name="recent-type"]:checked')?.value || 'all';
|
||||
|
||||
let itemsToDisplay = state.trendingData.recent || [];
|
||||
|
||||
// Apply filter
|
||||
if (typeFilter === 'film') {
|
||||
itemsToDisplay = itemsToDisplay.filter(m => m.type === 'movie');
|
||||
} else if (typeFilter === 'serie') {
|
||||
itemsToDisplay = itemsToDisplay.filter(m => m.type === 'series' || m.type === 'serie');
|
||||
}
|
||||
|
||||
grid.innerHTML = '';
|
||||
|
||||
if (!itemsToDisplay || !itemsToDisplay.length) {
|
||||
grid.innerHTML = '<p style="padding:1rem; opacity:0.7;">Aucun ajout récent trouvé.</p>';
|
||||
grid.innerHTML = '<p style="padding:1rem; opacity:0.7;">Aucun ajout récent trouvé pour ce filtre.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -961,6 +987,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
document.querySelectorAll('input[name="trending-type"]').forEach(radio => {
|
||||
radio.addEventListener('change', renderTrending);
|
||||
});
|
||||
|
||||
document.querySelectorAll('input[name="recent-type"]').forEach(radio => {
|
||||
radio.addEventListener('change', renderRecent);
|
||||
});
|
||||
|
||||
// --- SEARCH ---
|
||||
const searchInput = dom('search-input');
|
||||
@@ -1160,7 +1190,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const MAX_FILM_SIZE_MB = 45360;
|
||||
const MAX_FILM_SIZE_MB = 150000;
|
||||
|
||||
const enriched = data.clientOptions.map(q => {
|
||||
const lowEp = q.episode ? q.episode.toLowerCase() : '';
|
||||
@@ -1466,7 +1496,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
toggleBlockingLoader(true, "Récupération du lien...");
|
||||
try {
|
||||
const result = await apiCall('/get-link', 'POST', { chosenId: q.id, useJD });
|
||||
let result = await apiCall('/get-link', 'POST', { chosenId: q.id, useJD });
|
||||
|
||||
if (result.status === 'challenge' && result.challenge) {
|
||||
toggleBlockingLoader(false);
|
||||
const captchaData = await window.handleCaptchaChallenge(result.challenge);
|
||||
toggleBlockingLoader(true, "Vérification du captcha...");
|
||||
result = await apiCall('/get-link', 'POST', { chosenId: q.id, useJD, captchaData });
|
||||
}
|
||||
|
||||
toggleBlockingLoader(false);
|
||||
|
||||
if (useJD) {
|
||||
@@ -1555,11 +1593,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (forcedDirect) {
|
||||
useJD = false;
|
||||
}
|
||||
toggleBlockingLoader(true, "Récupération des liens...");
|
||||
try {
|
||||
const result = await apiCall('/get-links-batch', 'POST', { chosenIds: Array.from(selectedIds), useJD });
|
||||
toggleBlockingLoader(true, "Récupération des liens...");
|
||||
let result = await apiCall('/get-links-batch', 'POST', { chosenIds: Array.from(selectedIds), useJD });
|
||||
|
||||
if (result.status === 'challenge' && result.challenge) {
|
||||
toggleBlockingLoader(false);
|
||||
const captchaData = await window.handleCaptchaChallenge(result.challenge);
|
||||
toggleBlockingLoader(true, "Vérification du captcha et récupération...");
|
||||
result = await apiCall('/get-links-batch', 'POST', { chosenIds: Array.from(selectedIds), useJD, captchaData });
|
||||
}
|
||||
|
||||
toggleBlockingLoader(false);
|
||||
|
||||
if (result.errors) {
|
||||
showToast('Erreurs: ' + result.errors.join(', '));
|
||||
}
|
||||
|
||||
if (useJD) {
|
||||
showToast(result.message || 'Liens envoyés à JDownloader !');
|
||||
} else {
|
||||
@@ -1601,6 +1651,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
dom('modal-body').innerHTML = content;
|
||||
show(dom('modal-overlay'));
|
||||
};
|
||||
window.showModal = showModal;
|
||||
|
||||
const showDirectLinkModal = (title, content) => {
|
||||
const existing = document.getElementById('direct-link-modal-overlay');
|
||||
@@ -1649,6 +1700,61 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
};
|
||||
|
||||
window.handleCaptchaChallenge = function(challenge) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const existing = document.getElementById('captcha-modal-overlay');
|
||||
if (existing) existing.remove();
|
||||
|
||||
const overlay = document.createElement('div');
|
||||
overlay.id = 'captcha-modal-overlay';
|
||||
overlay.className = 'modal-overlay';
|
||||
overlay.style.zIndex = '10005';
|
||||
|
||||
if (challenge.captcha === 'turnstile') {
|
||||
overlay.innerHTML = `
|
||||
<div class="modal-content" style="max-width: 450px; text-align: center;">
|
||||
<div class="modal-header">
|
||||
<h3>Protection Cloudflare</h3>
|
||||
<button id="captcha-modal-close"><i data-lucide="x"></i></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p style="margin-bottom: 15px; color: var(--text-sec);">Ce lien est protégé par Cloudflare. Vous devez le résoudre manuellement sur le site source.</p>
|
||||
<p style="margin-bottom: 20px; color: var(--text-sec); font-size: 0.9em;">Une fois sur ${challenge.sourceName || 'le site'}, cliquez sur le lien, résolvez le captcha, puis copiez le lien 1Fichier obtenu pour l'ajouter dans l'onglet "Ajout Manuel" d'Agora.</p>
|
||||
<a href="${challenge.url}" target="_blank" class="btn-action" style="display: inline-flex; align-items: center; gap: 8px; background: var(--primary); color: var(--bg); padding: 12px 20px; border-radius: 8px; text-decoration: none; font-weight: 600;">
|
||||
<i data-lucide="external-link" style="width: 18px; height: 18px;"></i> Ouvrir ${challenge.sourceName || 'le site'}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
overlay.innerHTML = `
|
||||
<div class="modal-content" style="max-width: 400px; text-align: center;">
|
||||
<div class="modal-header">
|
||||
<h3>Vérification requise</h3>
|
||||
<button id="captcha-modal-close"><i data-lucide="x"></i></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p style="margin-bottom: 15px; color: var(--text-sec);">Captcha non supporté (${challenge.captcha}).</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
document.body.appendChild(overlay);
|
||||
lucide.createIcons({ root: overlay });
|
||||
show(overlay);
|
||||
|
||||
const closeBtn = overlay.querySelector('#captcha-modal-close');
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', () => {
|
||||
reject(new Error(challenge.captcha === 'turnstile' ? 'Redirection manuelle requise par Cloudflare.' : 'Captcha annulé.'));
|
||||
hide(overlay);
|
||||
setTimeout(() => overlay.remove(), 300);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const modalClose = dom('modal-close');
|
||||
if (modalClose) {
|
||||
modalClose.onclick = () => {
|
||||
|
||||
Reference in New Issue
Block a user