Greasy Fork is available in English.
Limpia enlaces redirigidos y elimina parámetros de seguimiento en solotodo.cl
// ==UserScript==
// @name Solotodo Limpiar Referidos Plox
// @namespace limpiotodo
// @version 0.2
// @description Limpia enlaces redirigidos y elimina parámetros de seguimiento en solotodo.cl
// @author Alplox
// @match https://*.solotodo.cl/*
// @match https://solotodo.cl/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
function safeDecode(s) {
if (!s) return s;
try { return decodeURIComponent(s); } catch (e) { return s; }
}
// Extrae URL destino caso: ad.soicos
function extractFromAdSoicos(href) {
if (!href) return null;
try {
const url = new URL(href);
if (!/(^|\.)ad\.soicos\.com$/.test(url.hostname)) return null;
const dl = url.searchParams.get('dl');
if (dl) return safeDecode(dl);
// patrón fallback: buscar primera apariencia de https%3A...
const m = href.match(/https?:%2F%2F[^"&]+/i);
if (m) return safeDecode(m[0]);
} catch (e) { return null; }
return null;
}
// Extrae URL destino caso: publicapi.solotodo.com/entities/meli_redirect/
function extractFromMeliRedirect(href) {
if (!href) return null;
try {
const url = new URL(href, location.href);
if (!url.hostname.includes('publicapi.solotodo.com')) return null;
if (!url.pathname.includes('meli_redirect')) return null;
const target = url.searchParams.get('url');
if (target) return safeDecode(target);
// patrón fallback: buscar primera apariencia de https%3A...
const m = href.match(/https?:%2F%2F[^"&]+/i);
if (m) return safeDecode(m[0]);
} catch (e) { return null; }
return null;
}
// Extrae la URL destino de redirecciones conocidas
function extractTarget(href) {
if (!href) return null;
const tryMeli = extractFromMeliRedirect(href);
if (tryMeli) return tryMeli;
const tryAd = extractFromAdSoicos(href);
if (tryAd) return tryAd;
return null;
}
function cleanUrl(u) {
if (!u) return u;
// Quitar comillas si existen
u = u.trim().replace(/^["']|["']$/g, '');
// Crear objeto URL para manipulación
try {
const url = new URL(u, location.href);
// Eliminar parámetros de seguimiento comunes
const trackingParams = [
'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',
'gclid', 'fbclid', 'ref', 'referrer', 'kid', 'aff', 'affiliate',
'tracking', 'click_id', 'source', 'cid', 'sid', 'utm_id'
];
trackingParams.forEach(param => {
url.searchParams.delete(param);
});
// Asegurar uso de HTTPS si no se especifica protocolo
if (!url.protocol) url.protocol = 'https:';
return url.toString();
} catch (e) {
// Si URL no es válida, retornar como está pero forzar HTTPS
return u.startsWith('http') ? u : 'https://' + u;
}
}
function processLink(a) {
if (!(a instanceof HTMLAnchorElement)) return;
const original = a.getAttribute('href');
if (!original) return;
// Intentar extraer URL destino si es redirección conocida
const target = extractTarget(original);
const finalUrl = target ? cleanUrl(target) : cleanUrl(original);
// Actualizar href si ha cambiado
if (finalUrl !== original) {
a.setAttribute('href', finalUrl);
}
// Eliminar atributos de seguimiento comunes
['data-tracking', 'data-ref', 'data-referrer', 'onclick', 'onmousedown', 'data-cid'].forEach(attr => {
try { a.removeAttribute(attr); } catch (e) {}
});
// Asegurar seguridad con rel="noopener"
a.setAttribute('rel', 'noopener');
}
function processAll(root = document) {
const selector = [
'a[href*="ad.soicos"]',
'a[href*="publicapi.solotodo.com"][href*="meli_redirect"]',
'a[href*="meli_redirect"]',
'a[href*="utm_"]',
'a[href*="kid="]',
'a[href*="affiliate"]'
].join(',');
const links = root.querySelectorAll(selector);
links.forEach(processLink);
}
// Configurar MutationObserver para detectar cambios dinámicos
const observer = new MutationObserver((mutations) => {
for (const m of mutations) {
if (m.addedNodes && m.addedNodes.length) {
m.addedNodes.forEach(node => {
if (node.nodeType !== 1) return;
if (node.matches && node.matches('a')) processLink(node);
if (node.querySelectorAll) processAll(node);
});
}
if (m.type === 'attributes' && m.target && m.target.matches && m.target.matches('a')) {
processLink(m.target);
}
}
});
// Procesar todos los enlaces inicialmente
processAll();
// Iniciar observador
observer.observe(document.documentElement || document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['href']
});
// Reintentos periódicos para asegurar limpieza en contenido dinámico (o por si acaso sitio carga lento)
let tries = 0;
const retry = setInterval(() => {
processAll();
if (++tries > 8) clearInterval(retry);
}, 800);
})();