Bloque des utilisateurs sur Chatlet et gère les pseudos longs.
// ==UserScript==
// @name Chatlet Blocker Message (Version FINAL)
// @namespace http://tampermonkey.net/
// @version 1.3
// @description Bloque des utilisateurs sur Chatlet et gère les pseudos longs.
// @author VotrePseudo & Manus
// @match https://chatlet.com/*
// @match https://chatlet.com/*
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(function ( ) {
'use strict';
// --- Stockage persistant ---
// On charge les pseudos bloqués depuis la mémoire de Tampermonkey
const BLOCKED = new Set(GM_getValue('blockedUsers', []));
// Fonction pour sauvegarder
function saveBlockedUsers() {
GM_setValue('blockedUsers', Array.from(BLOCKED));
}
const users = {};
// --- Création de l'interface ---
const panel = document.createElement('div');
panel.style.cssText = `
position: fixed; bottom: 20px; right: 20px; z-index: 99999;
background: #1e1e1e; border: 1px solid #333; border-radius: 10px;
width: 250px; font-family: sans-serif; font-size: 13px; color: #eee;
box-shadow: 0 4px 20px rgba(0,0,0,0.5);
resize: both; overflow: hidden; min-width: 180px; min-height: 80px;
`;
const header = document.createElement('div');
header.style.cssText = `
padding: 8px 12px; border-bottom: 1px solid #333;
display: flex; justify-content: space-between; align-items: center;
cursor: move; user-select: none;
`;
header.innerHTML = `
<span style="font-weight:600;">Blocker</span>
<div style="display:flex;align-items:center;gap:8px;">
<span id="bl-count" style="font-size:11px;color:#888;">0 en ligne</span>
<button id="bl-toggle" style="background:none; border:1px solid #444; border-radius:4px; color:#aaa; cursor:pointer; font-size:12px; padding:1px 7px; line-height:1.4;">−</button>
</div>
`;
const list = document.createElement('div');
list.style.cssText = `height: 200px; overflow-y: auto; padding: 4px 0; scrollbar-width: thin; scrollbar-color: #444 #1e1e1e;`;
const resizeHandle = document.createElement('div');
resizeHandle.style.cssText = `position: absolute; bottom: 0; right: 0; width: 16px; height: 16px; cursor: se-resize; display: flex; align-items: flex-end; justify-content: flex-end; padding: 2px;`;
resizeHandle.innerHTML = `<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 9L9 2M5 9L9 5M8 9L9 8" stroke="#555" stroke-width="1.5" stroke-linecap="round"/></svg>`;
panel.appendChild(header);
panel.appendChild(list);
panel.appendChild(resizeHandle);
document.body.appendChild(panel);
// --- Logique de l'interface (drag, resize, minimize) ---
let resizing = false, rsx, rsy, rsw, rsh;
resizeHandle.addEventListener('mousedown', e => { resizing = true; rsx = e.clientX; rsy = e.clientY; rsw = panel.offsetWidth; rsh = panel.offsetHeight; e.preventDefault(); e.stopPropagation(); });
document.addEventListener('mousemove', e => { if (!resizing) return; const newW = Math.max(180, rsw + (e.clientX - rsx)); const newH = Math.max(80, rsh + (e.clientY - rsy)); panel.style.width = newW + 'px'; list.style.height = Math.max(40, newH - header.offsetHeight - 20) + 'px'; panel.style.height = newH + 'px'; });
document.addEventListener('mouseup', () => resizing = false);
let minimized = false;
header.querySelector('#bl-toggle').addEventListener('click', () => { minimized = !minimized; list.style.display = minimized ? 'none' : 'block'; resizeHandle.style.display = minimized ? 'none' : 'flex'; panel.style.width = minimized ? 'auto' : '250px'; panel.style.height = minimized ? 'auto' : panel.style.height; header.querySelector('#bl-toggle').textContent = minimized ? '+' : '−'; header.querySelector('#bl-count').style.display = minimized ? 'none' : 'inline'; });
let ox, oy, dragging = false;
header.addEventListener('mousedown', e => { if (e.target.id === 'bl-toggle') return; dragging = true; ox = e.clientX - panel.offsetLeft; oy = e.clientY - panel.offsetTop; });
document.addEventListener('mousemove', e => { if (!dragging) return; panel.style.left = (e.clientX - ox) + 'px'; panel.style.top = (e.clientY - oy) + 'px'; panel.style.right = 'auto'; panel.style.bottom = 'auto'; });
document.addEventListener('mouseup', () => dragging = false);
// --- Rendu de la liste ---
function renderList() {
const online = Object.values(users).filter(u => u.status === 'online').length;
document.getElementById('bl-count').textContent = online + ' en ligne';
list.innerHTML = '';
const sorted = Object.entries(users).sort((a, b) => { if (a[1].status === b[1].status) return a[0].localeCompare(b[0]); return a[1].status === 'online' ? -1 : 1; });
if (sorted.length === 0) {
list.innerHTML = `<div style="padding:10px 12px;color:#666;font-size:12px;">Aucun utilisateur détecté</div>`;
return;
}
sorted.forEach(([pseudo, data]) => {
const row = document.createElement('div');
const isBlocked = BLOCKED.has(pseudo);
const isOnline = data.status === 'online';
row.style.cssText = `display: flex; align-items: center; gap: 8px; padding: 5px 12px; background: ${isBlocked ? '#2a1515' : 'transparent'};`;
const cb = document.createElement('input');
cb.type = 'checkbox';
cb.checked = isBlocked;
cb.style.cssText = 'margin:0; cursor:pointer; accent-color: #e55;';
cb.addEventListener('change', () => {
if (cb.checked) BLOCKED.add(pseudo);
else BLOCKED.delete(pseudo);
saveBlockedUsers(); // On sauvegarde la modification
renderList();
});
const label = document.createElement('span');
label.textContent = pseudo;
label.title = pseudo; // AFFICHE LE PSEUDO COMPLET AU SURVOL
label.style.cssText = `
flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
color: ${isBlocked ? '#e55' : isOnline ? '#eee' : '#666'};
text-decoration: ${isBlocked ? 'line-through' : 'none'};
font-size: 12px; cursor: default;
`;
const badge = document.createElement('span');
badge.textContent = isBlocked ? 'bloqué' : isOnline ? 'en ligne' : 'parti';
badge.style.cssText = `font-size: 10px; padding: 2px 6px; border-radius: 99px; background: ${isBlocked ? '#5a1a1a' : isOnline ? '#1a3a1a' : '#2a2a2a'}; color: ${isBlocked ? '#e55' : isOnline ? '#5e5' : '#666'};`;
row.appendChild(cb);
row.appendChild(label);
row.appendChild(badge);
list.appendChild(row);
});
}
// --- Interception et blocage ---
const origLog = console.log;
console.log = function (...args) {
try {
const msg = args.join(' ');
const matchIn = msg.match(/peer connection [a-f0-9]+.*?displayName":"([^"]+)"/);
if (matchIn) {
const pseudo = matchIn[2];
if (!users[pseudo] || users[pseudo].status !== 'online') {
users[pseudo] = { status: 'online' };
renderList();
}
}
} catch (e) { /* Ignore les erreurs du script */ }
return origLog.apply(this, args);
};
new MutationObserver(mutations => {
for (const m of mutations) {
for (const node of m.addedNodes) {
if (node.nodeType !== 1) continue;
const senderNode = node.querySelector?.('.sender');
if (senderNode) {
const sender = senderNode.textContent?.replace(': ', '').trim();
if (sender && (!users[sender] || users[sender].status !== 'online')) {
users[sender] = { status: 'online' };
renderList();
}
if (sender && BLOCKED.has(sender)) {
node.remove();
}
}
}
}
}).observe(document.body, { childList: true, subtree: true });
renderList();
console.info('✅ Chatlet Blocker (v1.3) actif');
})();