diff --git a/mode_affiches.js b/mode_affiches.js new file mode 100644 index 0000000..fe0dc59 --- /dev/null +++ b/mode_affiches.js @@ -0,0 +1,495 @@ +// ==UserScript== +// @name UseNet Enhanced +// @version 6.28 +// @date 12.07.25 +// @description Userscript pour transformer la liste de releases sur un indexeur privé en galerie d'affiches responsive +// @author Aerya | https://upandclear.org +// @match https://unfr.pw/* +// @updateURL https://raw.githubusercontent.com/Aerya/Mode-Affiches/main/mode_affiches.js +// @downloadURL https://raw.githubusercontent.com/Aerya/Mode-Affiches/main/mode_affiches.js +// @grant none +// ==/UserScript== + + +(function () { + 'use strict'; + + const TMDB_API_KEY = '1234'; // Mettez votre clé ici ! + const TMDB_CACHE_TTL = 24 * 60 * 60 * 1000; // 1 jour + + const CATEGORIES = [ + { key: 'HOME', label: 'Accueil' }, + { key: 'MOVIE', label: 'Films' }, + { key: 'TV', label: 'Séries' } + ]; + + const STORAGE_KEY = 'afficheModeSections'; + const STORAGE_MINWIDTH_KEY = 'afficheMinWidth'; + const STORAGE_FONT_SIZE_KEY = 'afficheRlzFontSize'; + const STORAGE_SHOW_TMDB_KEY = 'afficheShowTmdb'; + const TMDB_CACHE_KEY = 'afficheTmdbCache'; + + function getStoredConfig() { + try { return JSON.parse(localStorage.getItem(STORAGE_KEY)) || []; } catch (e) { return []; } + } + function saveConfig(arr) { localStorage.setItem(STORAGE_KEY, JSON.stringify(arr)); } + function getMinWidth() { return parseInt(localStorage.getItem(STORAGE_MINWIDTH_KEY) || '260'); } + function setMinWidth(val) { localStorage.setItem(STORAGE_MINWIDTH_KEY, val); } + function getFontSize() { return parseInt(localStorage.getItem(STORAGE_FONT_SIZE_KEY) || '22'); } + function setFontSize(val) { localStorage.setItem(STORAGE_FONT_SIZE_KEY, val); } + function getShowTmdb() { return localStorage.getItem(STORAGE_SHOW_TMDB_KEY) !== '0'; } + function setShowTmdb(val) { localStorage.setItem(STORAGE_SHOW_TMDB_KEY, val ? '1' : '0'); } + function getTmdbCache() { + try { return JSON.parse(localStorage.getItem(TMDB_CACHE_KEY)) || {}; } catch (e) { return {}; } + } + function saveTmdbCache(cache) { localStorage.setItem(TMDB_CACHE_KEY, JSON.stringify(cache)); } + + function fetchTmdb(type, tmdbId) { + if (!TMDB_API_KEY || !tmdbId) return Promise.resolve(null); + const cache = getTmdbCache(); + const key = `${type}_${tmdbId}`; + const now = Date.now(); + if (cache[key] && now - cache[key].fetched < TMDB_CACHE_TTL) { + return Promise.resolve(cache[key].data); + } + let url = ''; + if (type === 'movie') url = `https://api.themoviedb.org/3/movie/${tmdbId}?api_key=${TMDB_API_KEY}&language=fr-FR`; + else if (type === 'tv') url = `https://api.themoviedb.org/3/tv/${tmdbId}?api_key=${TMDB_API_KEY}&language=fr-FR`; + return fetch(url) + .then(r => r.json()) + .then(data => { + cache[key] = { data, fetched: now }; + saveTmdbCache(cache); + return data; + }).catch(() => null); + } + + function extractDateAndSize(card) { + let date = '', size = ''; + card.querySelectorAll('.badge').forEach(badge => { + const txt = badge.textContent.trim(); + if (!size && /([0-9]+(\.[0-9]+)?)( ?(GB|MB|G|M|Go|Mo))$/i.test(txt)) size = txt; + if (!date && /\d{2}\/\d{2}\/\d{2}/.test(txt)) date = txt.match(/\d{2}\/\d{2}\/\d{2}/)?.[0] || ''; + }); + return { date, size }; + } + + function getSection() { + const url = new URL(window.location.href); + const section = url.searchParams.get('section'); + const vm = url.searchParams.get('vm'); + if (!section && (vm === '1' || !vm)) return 'HOME'; + return section?.toUpperCase() || ''; + } + + function transformAffiches() { + const section = getSection(); + const config = getStoredConfig(); + const minwidth = getMinWidth(); + const rlzFontSize = getFontSize(); + const showTmdb = getShowTmdb(); + const show = config.includes(section); + if (!CATEGORIES.some(c => c.key === section)) return; + if (!show) return; + + const cards = Array.from(document.querySelectorAll('.containert.article .card.affichet')); + const containers = document.querySelectorAll('.containert.article'); + if (!cards.length || !containers.length) return; + + // Group releases par film/série via TMDB ID + const grouped = new Map(); + cards.forEach(card => { + const link = card.querySelector('a[href*="?d=fiche"]'); + const href = link?.getAttribute('href') || ''; + let tmdbId = ''; + let movieType = 'movie'; + let match = href.match(/movieid=(\d+)/i); + if (match) { + tmdbId = match[1]; + movieType = 'movie'; + } else { + match = href.match(/tvid=(\d+)/i); + if (match) { + tmdbId = match[1]; + movieType = 'tv'; + } + } + if (!tmdbId) { + const inp = card.querySelector('input#tmdb_id'); + if (inp) tmdbId = inp.value; + } + const idKey = movieType + '_' + tmdbId; + if (!tmdbId) return; + if (!grouped.has(idKey)) grouped.set(idKey, { cards: [], tmdbId, movieType }); + grouped.get(idKey).cards.push(card); + }); + + // Création galerie + const gallery = document.createElement('div'); + gallery.className = 'd-flex flex-wrap'; + gallery.style.justifyContent = 'center'; + gallery.style.marginTop = '20px'; + gallery.style.gap = '8px'; + gallery.style.padding = '0 12px'; + gallery.style.width = '100%'; + gallery.style.marginLeft = 'auto'; + gallery.style.marginRight = 'auto'; + + grouped.forEach((group, groupKey) => { + const card = group.cards[0]; + const img = card.querySelector('img.card-img-top'); + const minHeight = img?.height || 330; + if (!img) return; + + // Affiche = vignette + const containerCard = document.createElement('div'); + containerCard.style.flex = `0 0 ${minwidth}px`; + containerCard.style.maxWidth = `${minwidth}px`; + containerCard.style.position = 'relative'; + containerCard.style.display = 'block'; + + // Badge note TMDB (optionnel) + if (showTmdb) { + fetchTmdb(group.movieType, group.tmdbId).then(data => { + if (!data) return; + const vote = data.vote_average ? Number(data.vote_average).toFixed(1) : '?'; + const votes = data.vote_count ? ` (${data.vote_count})` : ''; + const tmdbSvg = ``; + + // Détermine le lien TMDB (film ou série) + let tmdbUrl = ''; + if (group.movieType === 'movie') tmdbUrl = `https://www.themoviedb.org/movie/${group.tmdbId}`; + else if (group.movieType === 'tv') tmdbUrl = `https://www.themoviedb.org/tv/${group.tmdbId}`; + + const badge = document.createElement('a'); + badge.href = tmdbUrl; + badge.target = '_blank'; + badge.rel = 'noopener noreferrer'; + badge.title = "Voir sur TMDB"; + badge.style.position = 'absolute'; + badge.style.top = '7px'; + badge.style.left = '8px'; + badge.style.background = '#032541de'; + badge.style.color = '#ffd04e'; + badge.style.fontWeight = 'bold'; + badge.style.borderRadius = '8px'; + badge.style.padding = '2px 11px 2px 3px'; + badge.style.fontSize = '18px'; + badge.style.boxShadow = '0 2px 8px #222c'; + badge.style.zIndex = 15; + badge.style.display = 'flex'; + badge.style.alignItems = 'center'; + badge.style.textDecoration = 'none'; + + badge.innerHTML = `${tmdbSvg}${vote}${votes}`; + + containerCard.appendChild(badge); + }); + + } + + // Clone affiche + const cloneImg = img.cloneNode(true); + cloneImg.style.width = `${minwidth}px`; + cloneImg.style.cursor = 'pointer'; + containerCard.appendChild(cloneImg); + + // Overlay + const tooltip = document.createElement('div'); + tooltip.className = 'affiche-tooltip'; + tooltip.style.position = 'absolute'; + tooltip.style.top = '0'; + tooltip.style.left = '0'; + tooltip.style.background = 'rgba(10,10,10,0.98)'; + tooltip.style.color = '#fff'; + tooltip.style.padding = '22px 36px 26px 36px'; + tooltip.style.borderRadius = '10px'; + tooltip.style.fontSize = rlzFontSize + 'px'; + tooltip.style.fontWeight = '400'; + tooltip.style.width = Math.min(window.innerWidth - 40, 1150) + 'px'; + tooltip.style.maxWidth = '99vw'; + tooltip.style.minHeight = `${minHeight}px`; + tooltip.style.zIndex = '1010'; + tooltip.style.boxShadow = '0 0 14px 6px rgba(0,0,0,0.7)'; + tooltip.style.whiteSpace = 'normal'; + tooltip.style.display = 'none'; + tooltip.style.pointerEvents = 'auto'; + + // Responsive : recalcule la largeur à l’ouverture si resize + function adjustOverlayWidth() { + tooltip.style.width = Math.min(window.innerWidth - 40, 1150) + 'px'; + } + window.addEventListener('resize', adjustOverlayWidth); + + // Header overlay + let typeLabel = 'film', typeGender = 'le'; + if (group.movieType === 'tv') { typeLabel = 'série'; typeGender = 'la'; } + tooltip.innerHTML = ` +