您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
鼠标🖱放到用户ID(.e.g @author)上时显示用户的注册(不可用)时间 - 显示更多信息以便识别网络水军
// ==UserScript== // @name 推特工具箱 | twitter toolkit // @namespace https://twitter.com // @icon http://pic.baike.soso.com/ugc/baikepic2/26526/cut-20190524093048-1039431188_jpg_686_550_12779.jpg/300 // @version 1.1.0 // @description 鼠标🖱放到用户ID(.e.g @author)上时显示用户的注册(不可用)时间 - 显示更多信息以便识别网络水军 // @author Sven // @license MIT // @note v1.1.0 修复因 ajax-hook 升级导致的报错; 参照 change list 修改引用方式 // @match https://twitter.com/* // @require https://unpkg.com/ajax-hook/dist/ajaxhook.min.js // @run-at document-start // @grant none // ==/UserScript== ; (() => { class ToolkitModule { constructor() { } isActive = true } /** * Breaking Ajax */ class BreakingModule extends ToolkitModule { constructor() { super() } init(ctx) { // 添加 mouseover 事件, 在鼠标悬浮在用户头像上时显示注册(不可用)时间 document.addEventListener('mouseover', evt => { if (evt.target.tagName !== 'SPAN' || evt.target.parentNode.tagName !== 'DIV' || (evt.target.nextElementSibling && evt.target.nextElementSibling.classList.contains('twitter-toolkit-user-created-at'))) return for (const id in window._$TwitterToolkit.users) { const userName = window._$TwitterToolkit.users[id].screen_name if (evt.target.innerText === '@' + userName) { ctx.log('监测到鼠标悬浮在用户头像上, 用户信息: ', window._$TwitterToolkit.users[id]) // 账号注册(不可用)时间 const createdAtDom = document.createElement('div') const { created_at } = window._$TwitterToolkit.users[id] const createdAtDate = new Date(created_at) createdAtDom.innerText = 'created at ' + createdAtDate.toLocaleDateString() createdAtDom.style.fontSize = '12px' createdAtDom.style.color = 'rgb(27, 149, 224)' createdAtDom.classList.add('twitter-toolkit-user-created-at') evt.target.parentNode.appendChild(createdAtDom) break } } }) ah.hook({ //拦截回调 onreadystatechange: (xhr) => { const responseStr = (xhr.response instanceof ArrayBuffer ? String.fromCharCode.apply(null, Uint16Array) : xhr.response) || '' if (responseStr.indexOf('"users":{') === -1) return let users = null try { const res = JSON.parse(responseStr) users = (res.globalObjects && res.globalObjects.users) } catch (err) { } if (users === null) return // ctx.log('users: ', users) for (const id in users) { if (ctx.users[id]) { Object.assign(ctx.users[id], users[id]) } else { ctx.users[id] = users[id] } } setTimeout(this._showUserInfo, 500) }, // onload: function (xhr) { // console.log("onload called: %O", xhr) // }, //拦截方法 // open: function (arg, xhr) { // xhr._$request = { url: arg[1], method: arg[0] } // } }) } _showUserInfo() { console.log(window._$TwitterToolkit.users) } onload(ctx) { ctx.log('onload') } } /** * 工具类 */ class Toolkit { debug = true options = {} users = {} constructor(options = {}) { Object.assign(this.options, options) this.emitHook('init') } /** * 工具集 */ static modules = [] /** * 注册(不可用)工具模块 */ static use(moduleItem) { // 禁用未激活的模块 if (!moduleItem.isActive) return Array.isArray(moduleItem) ? moduleItem.map(item => Toolkit.use(item)) : Toolkit.modules.push(moduleItem) } /** * 触发钩子函数 * @param {string}} hook 钩子函数名 */ emitHook(hook) { this.log('触发钩子函数: ' + hook, Toolkit.modules.length) Toolkit.modules.map(module => module[hook] && typeof module[hook] === 'function' && module[hook](this)) } log(...args) { console.log('%c[Twitter Toolkit] LOG: ', 'color:teal', ...args) } static delay(timeout = 200) { return new Promise(resolve => setTimeout(resolve, timeout)) } } Toolkit.use(new BreakingModule()) window._$TwitterToolkit = new Toolkit() window.addEventListener('DOMContentLoaded', () => window._$TwitterToolkit.emitHook('onload')) })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址