// ==UserScript== // @name WebSocket 拦截器库 // @namespace http://tampermonkey.net/ // @version 1.0.0 // @description WebSocket 消息拦截和解压缩工具库 // @author ruby // @require https://cdnjs.cloudflare.com/ajax/libs/pako/2.1.0/pako.min.js // @grant none // ==/UserScript== (function () { 'use strict'; // 默认配置 const config = { // 调试模式开关 debugMode: false, // 消息过滤器(排除包含这些关键字的消息) excludeFilters: ["PING", "PONG:", /"source":.*,"target":.*/], // 包含过滤器(只打印包含这些关键字的消息) includeFilters: [], }; // 消息处理回调队列 const messageCallbacks = []; // 检查消息是否应该被排除(基于排除过滤器) function shouldExcludeMessage(message) { if (typeof message !== 'string') { return false; } return config.excludeFilters.some(filter => { if (filter instanceof RegExp) { return filter.test(message); } if (typeof filter === 'string' && filter.startsWith('/') && filter.endsWith('/')) { try { const regexPattern = filter.slice(1, -1); const regex = new RegExp(regexPattern, 'i'); return regex.test(message); } catch (e) { console.error('[WebSocket拦截器] 无效的正则表达式:', filter); return false; } } if (typeof filter === 'string') { return message.toLowerCase().includes(filter.toLowerCase()); } return false; }); } // 检查消息是否应该被包含(基于包含过滤器) function shouldIncludeMessage(message) { if (typeof message !== 'string') { return false; } if (config.includeFilters.length === 0) { return true; } return config.includeFilters.some(filter => message.toLowerCase().includes(filter.toLowerCase()) ); } // 检查消息是否应该被打印 function shouldPrintMessage(message) { if (config.includeFilters.length > 0) { return shouldIncludeMessage(message); } return !shouldExcludeMessage(message); } // 打印消息的函数 function logMessage(direction, message, isCompressed = false, parsedMessage = null) { const messageToCheck = parsedMessage !== null ? JSON.stringify(parsedMessage) : message; if (!shouldPrintMessage(message)) { return; } const color = direction === '发送' ? '#03A9F4' : '#4CAF50'; if (isCompressed) { console.log(`%c[WebSocket ${direction}]`, `color: ${color}; font-weight: bold;`, `(已压缩)`, parsedMessage); } else { console.log(`%c[WebSocket ${direction}]`, `color: ${color}; font-weight: bold;`, message); } } // 检测数据压缩格式 function detectCompression(buf) { const b = new Uint8Array(buf); if (b.length < 2) return 'deflate'; if (b[0] === 0x1f && b[1] === 0x8b) return 'gzip'; if (b[0] === 0x78 && (((b[0] << 8) | b[1]) % 31) === 0) return 'zlib'; return 'deflate'; } // 触发所有注册的回调 function triggerCallbacks(parsedMessage, rawMessage, event) { messageCallbacks.forEach(callback => { try { callback(parsedMessage, rawMessage, event); } catch (error) { console.error('[WebSocket拦截器] 回调执行错误:', error); } }); } // WebSocket拦截核心功能 function initWebSocketInterceptor() { const OriginalWebSocket = window.WebSocket; const originalSend = OriginalWebSocket.prototype.send; const originalAddEventListener = OriginalWebSocket.prototype.addEventListener; // 重写send方法 OriginalWebSocket.prototype.send = function (data) { if (config.debugMode) { logMessage('发送', data); } return originalSend.apply(this, arguments); }; // 重写addEventListener方法 OriginalWebSocket.prototype.addEventListener = function (type, listener, options) { if (type === 'message') { const wrappedListener = function (event) { processMessageEvent(event, listener, this); }; return originalAddEventListener.call(this, type, wrappedListener, options); } return originalAddEventListener.call(this, type, listener, options); }; // 拦截onmessage属性 const originalOnMessageDescriptor = Object.getOwnPropertyDescriptor(OriginalWebSocket.prototype, 'onmessage'); Object.defineProperty(OriginalWebSocket.prototype, 'onmessage', { get: function () { return originalOnMessageDescriptor && originalOnMessageDescriptor.get ? originalOnMessageDescriptor.get.call(this) : this._onmessage; }, set: function (handler) { const self = this; const wrappedHandler = function (event) { processMessageEvent(event, handler, self); }; if (originalOnMessageDescriptor && originalOnMessageDescriptor.set) { originalOnMessageDescriptor.set.call(this, wrappedHandler); } else { this._onmessage = wrappedHandler; } } }); // 处理消息事件 function processMessageEvent(event, handler, context) { let parsed = null; let rawText = null; // 检查是否为二进制消息(压缩数据) if (event.data instanceof ArrayBuffer) { try { const format = detectCompression(event.data); const text = pako.inflate(new Uint8Array(event.data), {to: 'string'}); rawText = text; try { parsed = JSON.parse(text); } catch { parsed = text; } if (config.debugMode) { logMessage('接收', text, true, parsed); } } catch (err) { if (config.debugMode) { console.error('%c[WebSocket错误]', 'color: #f44336;', '消息解压失败:', err); } } } else { // 文本消息 rawText = event.data; if (config.debugMode) { logMessage('接收', event.data); } try { parsed = JSON.parse(event.data); } catch { parsed = event.data; } } // 触发所有注册的回调 if (parsed) { triggerCallbacks(parsed, rawText, event); } // 调用原始处理函数 if (typeof handler === 'function') { handler.call(context, event); } } } // 创建全局 API const WebSocketInterceptor = { // 初始化拦截器 init: function() { initWebSocketInterceptor(); console.log('[WebSocket拦截器] 已启动'); }, // 注册消息回调 onMessage: function(callback) { if (typeof callback === 'function') { messageCallbacks.push(callback); console.log('[WebSocket拦截器] 已注册消息回调'); } }, // 移除消息回调 offMessage: function(callback) { const index = messageCallbacks.indexOf(callback); if (index > -1) { messageCallbacks.splice(index, 1); console.log('[WebSocket拦截器] 已移除消息回调'); } }, // 添加排除过滤器 addExcludeFilter: function (filter) { if (!config.excludeFilters.includes(filter)) { config.excludeFilters.push(filter); console.log(`[WebSocket拦截器] 已添加排除过滤器: ${filter}`); } }, // 移除排除过滤器 removeExcludeFilter: function (filter) { const index = config.excludeFilters.indexOf(filter); if (index > -1) { config.excludeFilters.splice(index, 1); console.log(`[WebSocket拦截器] 已移除排除过滤器: ${filter}`); } }, // 获取当前排除过滤器列表 getExcludeFilters: function () { return [...config.excludeFilters]; }, // 清空排除过滤器列表 clearExcludeFilters: function () { config.excludeFilters = []; console.log('[WebSocket拦截器] 已清空所有排除过滤器'); }, // 添加包含过滤器 addIncludeFilter: function (filter) { if (!config.includeFilters.includes(filter)) { config.includeFilters.push(filter); console.log(`[WebSocket拦截器] 已添加包含过滤器: ${filter}`); } }, // 移除包含过滤器 removeIncludeFilter: function (filter) { const index = config.includeFilters.indexOf(filter); if (index > -1) { config.includeFilters.splice(index, 1); console.log(`[WebSocket拦截器] 已移除包含过滤器: ${filter}`); } }, // 获取当前包含过滤器列表 getIncludeFilters: function () { return [...config.includeFilters]; }, // 清空包含过滤器列表 clearIncludeFilters: function () { config.includeFilters = []; console.log('[WebSocket拦截器] 已清空所有包含过滤器'); }, // 启用/禁用调试模式 setDebugMode: function (enabled) { config.debugMode = enabled; console.log(`[WebSocket拦截器] 调试模式已${enabled ? '启用' : '禁用'}`); } }; // 暴露到全局 window.WebSocketInterceptor = WebSocketInterceptor; // 兼容旧的全局变量名 window.wsInterceptor = WebSocketInterceptor; })();