推特工具箱 | twitter toolkit

鼠标🖱放到用户ID(.e.g @author)上时显示用户的注册时间 - 显示更多信息以便识别网络水军

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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'))
})();