// ==UserScript== // @name Telegram Web Sort by Reactions (Auto-Clear & Jump) // @name:zh-CN Telegram Web 按回应排序 (自动清空 & 精准跳转) // @namespace https://gist.github.com/panwanke/c30874ba5a0996be2fff5bcf609efd6f // @version 1.0.1 // @description Find messages with the most reactions. Compact view, precise jump, and auto-clear on chat switch. // @description:zh-CN 帮助您查找 Telegram 中回应最多的消息。支持简约面板预览、精准跳转以及切换频道自动清空。 // @author epool // @license MIT // @match https://web.telegram.org/* // @icon https://www.google.com/s2/favicons?sz=64&domain=telegram.org // @require http://code.jquery.com/jquery-3.3.1.min.js // @grant none // @run-at document-end // @downloadURL none // ==/UserScript== (function() { 'use strict'; // ========================================== // 1. 注入 UI 样式 (极致去图纯文本模式 + 新按钮) // ========================================== let style = ` #sBtn { position: fixed; top: 73px; right: 16px; width: 45px; height: 45px; padding: 5px; border-radius: 10px; z-index: 9999; opacity: 0.8; background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAtGVYSWZJSSoACAAAAAYAEgEDAAEAAAABAAAAGgEFAAEAAABWAAAAGwEFAAEAAABeAAAAKAEDAAEAAAACAAAAEwIDAAEAAAABAAAAaYcEAAEAAABmAAAAAAAAAEgAAAABAAAASAAAAAEAAAAGAACQBwAEAAAAMDIxMAGRBwAEAAAAAQIDAACgBwAEAAAAMDEwMAGgAwABAAAA//8AAAKgBAABAAAAQAAAAAOgBAABAAAAQAAAAAAAAABuEYT5AAABkklEQVR4nO2bPU7EMBBGX74OcQIKjgFnYMVPh1YcZ7kMFQeh4g4sghtQYhSJaoWCHduJZ8dPcud8sZ3VTPZJgU6n05nmGngHwsHYA5uCeaXyi7OfWORb4bwS+UkMEXNCgYyUvNz8JIRzhHOEc7TCPccOkFIwVyf8M1LZRHaCsQNccYRdoCmEc4RzhHOEc4RzhHOEc7TCPWN9QDO+IBR+E0zxAdV9wWDAB1DzTVQ4RzhHOEeN+4AmfEFYyQcs4guGiDndBxwzwjnCOcI5wjnCOcI5MuwDFvMFoWEfkO0LhsgDyM1IySvN5PqEc4RzhHNk3Acs4gtCoz6gmC+4Az4qLGDMvMUAHxWfwpI/99k1YKiYb8IW3QPfFZ7+mLnFCLsKB/CIIQbgqeDmny2+Y5wALwU2/wqcYpSzzB79CZxjnAvga8bmx2suG/IBWb5gm9gZxrkPDfqALF+wq1TxQ2MjuzOkVnwzBxDTGeZUfFMHMNUZ5lZ8cwfwV2eIrfimi+AhN78X7DP/5i7lA5r4HqHT6dA0P32R2X1NXS7nAAAAAElFTkSuQmCC") no-repeat center center; background-size: 32px; background-color: #fff; cursor: pointer; box-shadow: 0 2px 5px rgba(0,0,0,0.2); transition: all 0.2s; } #sBtn:hover { opacity: 1; transform: scale(1.05); } .theme-dark #sBtn { background-color: #2c2c2c; } #tg-sort-panel { position: fixed; top: 0; right: -420px; width: 350px; height: 100vh; background: #ffffff; z-index: 10000; box-shadow: -5px 0 15px rgba(0,0,0,0.1); transition: right 0.3s ease; display: flex; flex-direction: column; } #tg-sort-panel.open { right: 0; } .theme-dark #tg-sort-panel { background: #212121; color: #fff; border-left: 1px solid #333; } .tg-panel-header { padding: 15px 20px; background: #3390ec; color: white; font-weight: bold; display: flex; justify-content: space-between; align-items: center; font-size: 16px; } .tg-panel-actions span { cursor: pointer; font-size: 18px; margin-left: 12px; opacity: 0.8; transition: opacity 0.2s; } .tg-panel-actions span:hover { opacity: 1; } .tg-panel-content { flex: 1; overflow-y: auto; padding: 15px 10px; background: #f4f4f5; } .theme-dark .tg-panel-content { background: #0f0f0f; } .tg-sorted-msg-wrap { margin-bottom: 12px; background: #fff; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); padding: 10px; position: relative; cursor: pointer; transition: background 0.2s ease; border: 1px solid transparent; overflow: hidden; } .theme-dark .tg-sorted-msg-wrap { background: #181818; } .tg-sorted-msg-wrap:hover { background: #f0f8ff; border-color: #3390ec; } .theme-dark .tg-sorted-msg-wrap:hover { background: #2c3e50; } .tg-rank-badge { display: inline-block; background: #ff4500; color: #fff; font-size: 12px; font-weight: bold; padding: 2px 6px; border-radius: 6px; margin-bottom: 4px; } /* 暴力隐藏多媒体及干扰项 */ .tg-sorted-msg-wrap .attachment, .tg-sorted-msg-wrap .album-item, .tg-sorted-msg-wrap .media-container, .tg-sorted-msg-wrap img:not(.media-sticker), .tg-sorted-msg-wrap video, .tg-sorted-msg-wrap .media-wrap, .tg-sorted-msg-wrap .message-media, .tg-sorted-msg-wrap .ReplyInfo, .tg-sorted-msg-wrap .stacked-avatars, .tg-sorted-msg-wrap .bubble-beside-button, .tg-sorted-msg-wrap .bubble-tail { display: none !important; } /* 文字折叠 */ .tg-sorted-msg-wrap .message, .tg-sorted-msg-wrap .text-content, .tg-sorted-msg-wrap .MessageText, .tg-sorted-msg-wrap .translatable-message { display: -webkit-box !important; -webkit-line-clamp: 2 !important; -webkit-box-orient: vertical !important; overflow: hidden !important; font-size: 13px !important; color: #555; line-height: 1.4; white-space: normal !important; margin-top: 2px; } .theme-dark .tg-sorted-msg-wrap .message, .theme-dark .tg-sorted-msg-wrap .text-content, .theme-dark .tg-sorted-msg-wrap .MessageText, .theme-dark .tg-sorted-msg-wrap .translatable-message { color: #aaa; } /* 反应按钮缩放 */ .tg-sorted-msg-wrap reaction-element, .tg-sorted-msg-wrap .reaction { transform: scale(0.85); transform-origin: left top; margin-top: 5px; } /* 闪烁高亮动画 */ @keyframes tg-flash { 0% { background-color: rgba(51, 144, 236, 0.4); } 100% { background-color: transparent; } } .tg-highlight-msg { animation: tg-flash 2s ease-out; } `; $('body').prepend(''); // ========================================== // 2. 构建 UI DOM (新增清空按钮) // ========================================== $('body').append("
"); $('body').append(`
🏆 Top Reactions
🗑️
暂无数据。请点击左侧按钮进行扫描。
`); // 绑定关闭按钮 $('.tg-panel-close').click(() => $('#tg-sort-panel').removeClass('open')); // 绑定手动清空按钮 $('.tg-panel-clear').click(function() { $('.tg-panel-content').html('
已清空。请点击左侧按钮重新扫描当前频道。
'); }); // ========================================== // 3. 智能检测频道切换 (Auto-clear on chat switch) // ========================================== let currentChatUrl = window.location.href; setInterval(() => { if (window.location.href !== currentChatUrl) { currentChatUrl = window.location.href; // 当网址发生变化(切换了频道/群组),自动收起面板并清空数据 if ($('#tg-sort-panel').hasClass('open')) { $('#tg-sort-panel').removeClass('open'); } $('.tg-panel-content').html('
检测到频道切换,数据已自动重置。请重新扫描。
'); } }, 1000); // 每秒轻量级检测一次网址 // ========================================== // 4. 数字转换函数 // ========================================== $.fn.text2qty = function () { let counterSpan = $(this).find('.reaction-counter'); let textToParse = counterSpan.length > 0 ? counterSpan.text() : $(this).text(); if (!textToParse) return 0; let qty = parseFloat(textToParse.replace(/[^0-9.,]/g, '').replace(/[,]/g, '.')) || 0; if (textToParse.match(/K$/i)) qty *= 1000; if (textToParse.match(/M$/i)) qty *= 1000000; if (qty > 0) return qty; return 0; }; // ========================================== // 5. 扫描、提取与跳转逻辑 // ========================================== $('#sBtn').click(function() { let msgArray = []; let messages = $('.bubble, .message-list-item, .Message'); messages.each(function() { let item = $(this); let reactSum = 0; if (item.hasClass('bubble') && item.find('.bubble-content').length === 0) return; let possibleId1 = item.attr('id'); let possibleId2 = item.attr('data-message-id'); let possibleId3 = item.attr('data-mid'); item.find('reaction-element, .reaction, .Reactions .Button').each(function() { reactSum += $(this).text2qty(); }); if (reactSum > 0) { let cloneNode = item.clone().removeAttr('id'); cloneNode.find('reaction-element, .reaction, .Reactions .Button, .replies').css('pointer-events', 'none'); msgArray.push({ score: reactSum, id1: possibleId1, id2: possibleId2, id3: possibleId3, dom: cloneNode }); } }); // 降序排序 msgArray.sort((a, b) => b.score - a.score); let contentContainer = $('.tg-panel-content'); contentContainer.empty(); if (msgArray.length === 0) { contentContainer.append('
当前可视区域未扫描到包含互动的消息。

💡 提示:请先在聊天窗口往上滚动一段距离加载历史记录,然后再点击扫描。
'); } else { msgArray.forEach((msgObj, index) => { let wrapper = $('
'); let badge = $(`
#${index + 1} (♥ ${msgObj.score})
`); wrapper.append(badge); wrapper.append(msgObj.dom); wrapper.click(function() { let targetElement = null; if (msgObj.id3) targetElement = $(`[data-mid="${msgObj.id3}"]`); if (!targetElement || !targetElement.length) { if (msgObj.id1) targetElement = $('#' + $.escapeSelector(msgObj.id1)); } if (!targetElement || !targetElement.length) { if (msgObj.id2) targetElement = $(`[data-message-id="${msgObj.id2}"]`); } if (targetElement && targetElement.length > 0) { try { targetElement.get(0).scrollIntoView({ behavior: 'smooth', block: 'center' }); targetElement.removeClass('tg-highlight-msg'); setTimeout(() => { targetElement.addClass('tg-highlight-msg'); }, 10); } catch(e) { console.error("Jump failed:", e); } } else { alert('⚠️ 消息已被内存清理,请在聊天窗口向上滚动一段距离后重试。'); } }); contentContainer.append(wrapper); }); } $('#tg-sort-panel').addClass('open'); }); })();