Modo catálogo en elamigos.site con portadas limpias y títulos ordenados
目前為
// ==UserScript==
// @name ElAmigos modo catálogo
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Modo catálogo en elamigos.site con portadas limpias y títulos ordenados
// @author Shu2Ouma
// @match https://elamigos.site/*
// @grant GM_xmlhttpRequest
// @connect elamigos.site
// @run-at document-idle
// @icon https://elamigos.site/favicon.ico
// @license MIT
// ==/UserScript==
(function() {
'use strict';
function convertYouTubeLinks(doc, contenedorFlex = null) {
const parrafos = doc.querySelectorAll('p');
parrafos.forEach(p => {
const walker = document.createTreeWalker(p, NodeFilter.SHOW_TEXT, null, false);
let node;
while (node = walker.nextNode()) {
const ytRegex = /(https?:\/\/(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+))/g;
if (ytRegex.test(node.textContent)) {
const frag = document.createDocumentFragment();
let lastIndex = 0;
node.textContent.replace(ytRegex, (match, url, videoId, offset) => {
if (offset > lastIndex) frag.appendChild(document.createTextNode(node.textContent.slice(lastIndex, offset)));
const iframe = document.createElement('iframe');
iframe.width = 560;
iframe.height = 315;
iframe.src = `https://www.youtube-nocookie.com/embed/${videoId}`;
iframe.frameBorder = 0;
iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture';
iframe.allowFullscreen = true;
if (contenedorFlex) contenedorFlex.appendChild(iframe);
else frag.appendChild(iframe);
lastIndex = offset + match.length;
});
if (lastIndex < node.textContent.length)
frag.appendChild(document.createTextNode(node.textContent.slice(lastIndex)));
node.parentNode.replaceChild(frag, node);
}
}
});
}
if(location.href.includes('/data/')){
const primeraImg = document.querySelector('img');
if(primeraImg){
const iframeHeight = 315;
primeraImg.style.height = iframeHeight + 'px';
primeraImg.style.width = 'auto';
primeraImg.style.objectFit = 'cover';
const contenedor = document.createElement('div');
contenedor.style.display = 'flex';
contenedor.style.alignItems = 'flex-start';
contenedor.style.gap = '20px';
primeraImg.parentNode.insertBefore(contenedor, primeraImg);
contenedor.appendChild(primeraImg);
convertYouTubeLinks(document, contenedor);
}
return;
}
if(document.getElementById('catalogo-elamigos')) return;
function limpiarNombre(nombre) {
return nombre
.replace(/\bEl\s*-?\s*Amigos\b/gi, '')
.replace(/\bElAmigos\b/gi, '')
.replace(/[\[\(\{]\s*El\s*-?\s*Amigos\s*[\]\)\}]/gi, '')
.replace(/\bAmigos\b/gi, '')
.replace(/\s{2,}/g, ' ')
.replace(/\r?\n/g, '')
.replace(/\s*\+\s*(?=\[)/g, '')
.replace(/(?=\[)/g, '<br>')
.trim();
}
// --- Estilos ---
const style = document.createElement('style');
style.textContent = `
#catalogo-elamigos {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
gap: 16px;
margin: 20px 0;
}
#catalogo-elamigos .card {
text-align: center;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
#catalogo-elamigos .card:hover {
transform: translateY(-5px) scale(1.05);
box-shadow: 0 8px 20px rgba(0,0,0,0.3);
}
#catalogo-elamigos img {
width: 150px;
height: 225px;
object-fit: cover;
display: block;
margin: 0 auto 8px auto;
border-radius: 8px;
transition: transform 0.3s ease;
}
#catalogo-elamigos .card:hover img {
transform: scale(1.08);
}
#catalogo-elamigos .title {
width: 150px;
font-size: 12px;
font-weight: bold;
text-align: center;
word-wrap: break-word;
margin: 0 auto;
transition: color 0.3s ease;
line-height: 1.2em;
}
#catalogo-elamigos .card:hover .title {
color: #007bff !important;
}
#catalogo-elamigos .placeholder {
width: 150px;
height: 225px;
background: #eee;
border-radius: 8px;
margin: 0 auto 8px auto;
}
#catalogo-elamigos .title br {
line-height: 1.2em;
}
nav.fixed-nav-bar {
display: flex;
justify-content: space-between;
align-items: center;
}
#letter-filter-container {
margin-right: 25%;
}
#letter-filter-container label {
color: #fff;
font-weight: bold;
font-size: 16px;
margin-right: 10px;
}
#letter-filter-container select {
padding: 6px 8px;
font-size: 16px;
border-radius: 4px;
border: none;
background: #222;
color: #fff;
font-weight: bold;
cursor: pointer;
transition: background 0.3s ease;
margin-right: 20px;
}
#letter-filter-container select:hover {
background: #007bff;
color: #fff;
}
`;
document.head.appendChild(style);
const grid = document.createElement('div');
grid.id = 'catalogo-elamigos';
const observer = new IntersectionObserver((entries)=>{
entries.forEach(entry=>{
if(!entry.isIntersecting) return;
const card = entry.target;
const link = card.dataset.link;
const tituloTexto = card.dataset.title;
if(card.dataset.loaded) return;
GM_xmlhttpRequest({
method:'GET',
url: link,
onload:function(response){
try{
const parser = new DOMParser();
const doc = parser.parseFromString(response.responseText,'text/html');
convertYouTubeLinks(doc);
const imgElem = doc.querySelector('img');
if(imgElem){
const imgSrc = new URL(imgElem.src, link).href;
const enlace = document.createElement('a');
enlace.href = link;
enlace.target = '_blank';
enlace.rel = 'noopener noreferrer';
enlace.style.textDecoration = 'none';
const portada = document.createElement('img');
portada.src = imgSrc;
portada.alt = tituloTexto;
portada.width = 150;
portada.height = 225;
portada.style.objectFit = 'cover';
enlace.appendChild(portada);
const placeholder = card.querySelector('.placeholder');
if(placeholder) card.replaceChild(enlace, placeholder);
else card.insertBefore(enlace, card.firstChild);
}
const titulo = document.createElement('div');
titulo.className = 'title';
titulo.innerHTML = tituloTexto;
titulo.style.color = window.getComputedStyle(card).color;
card.appendChild(titulo);
card.dataset.loaded = "true";
}catch(err){
console.error('Error cargando portada:', link, err);
}
},
onerror:function(err){
console.warn('GM_xmlhttpRequest ->', err);
}
});
observer.unobserve(card);
});
},{rootMargin:'200px'});
function findFirstFecha(){
return Array.from(document.querySelectorAll('h1')).find(h1 =>
/^\d{2}\.\d{2}\.\d{4}$/.test(h1.textContent.trim())
) || null;
}
function processFrom(reference){
if(!reference) return;
reference.parentNode.insertBefore(grid, reference.nextSibling);
let nodo = reference.nextElementSibling;
while(nodo){
const nextNodo = nodo.nextElementSibling;
const textoNodo = nodo.textContent.trim();
const esFecha = /^\d{2}\.\d{2}\.\d{4}$/.test(textoNodo);
const esOtroSeparador = /Full log of updates|Otro Separador/i.test(textoNodo);
if(esFecha || esOtroSeparador){
const brBefore = document.createElement('br');
const brAfter = document.createElement('br');
nodo.parentNode.insertBefore(brBefore, nodo);
nodo.parentNode.insertBefore(brAfter, nodo.nextSibling);
}
else if(['H3','H4','H5'].includes(nodo.tagName)){
const a = nodo.querySelector('a[href]');
if(a){
const link = a.href;
let tituloTexto = nodo.textContent.replace(/DOWNLOAD/gi,'').trim();
tituloTexto = limpiarNombre(tituloTexto);
const card = document.createElement('div');
card.className = 'card';
card.dataset.link = link;
card.dataset.title = tituloTexto;
const placeholder = document.createElement('div');
placeholder.className = 'placeholder';
card.appendChild(placeholder);
grid.appendChild(card);
observer.observe(card);
try{ nodo.style.display = 'none'; }catch(e){}
}
}
nodo = nextNodo;
}
const nav = document.querySelector('nav.fixed-nav-bar');
if(nav){
const container = document.createElement('div');
container.id = 'letter-filter-container';
const label = document.createElement('label');
label.textContent = 'Filtrar por letra: ';
const select = document.createElement('select');
const letras = ['Todos','#',...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'];
letras.forEach(letra=>{
const option = document.createElement('option');
option.value = letra;
option.textContent = letra;
select.appendChild(option);
});
label.appendChild(select);
container.appendChild(label);
nav.appendChild(container);
select.addEventListener('change',()=>{
const valor = select.value;
const cards = document.querySelectorAll('#catalogo-elamigos .card');
cards.forEach(card=>{
const titulo = card.dataset.title || '';
if(valor==='Todos') card.style.display='block';
else if(valor==='#') card.style.display=/^[^A-Z]/i.test(titulo)?'block':'none';
else card.style.display=titulo.toUpperCase().startsWith(valor)?'block':'none';
});
});
}
}
const firstFecha = findFirstFecha();
if(firstFecha) processFrom(firstFecha);
else{
const mo = new MutationObserver((mutations, observerMut)=>{
const fecha = findFirstFecha();
if(fecha){
observerMut.disconnect();
processFrom(fecha);
}
});
mo.observe(document.documentElement||document.body,{childList:true, subtree:true});
setTimeout(()=>{
const fecha2 = findFirstFecha();
if(fecha2) processFrom(fecha2);
},3000);
}
})();