Onekey Multiplatform Search

Query the homepage links of users on different social media platforms

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name               一键多平台搜索
// @name:zh-CN         一键多平台搜索
// @name:en            Onekey Multiplatform Search
// @description        一键查询「用户名」在不同社交平台的主页链接,一键查询「视频标题」在不同平台的链接。
// @description:zh-CN  一键查询「用户名」在不同社交平台的主页链接,一键查询「视频标题」在不同平台的链接。
// @description:en     Query the homepage links of users on different social media platforms
// @namespace          https://www.runningcheese.com/userscripts
// @author             RunningCheese
// @version            2.0
// @match              https://space.bilibili.com/*
// @match              https://*.weibo.com/u/*
// @match              https://www.weibo.com/*
// @match              https://www.zhihu.com/people/*
// @match              https://www.douyin.com/user/*
// @match              https://www.douban.com/people/*
// @match              https://www.xiaohongshu.com/user/profile/*
// @match              https://mp.weixin.qq.com/s*
// @match              https://www.toutiao.com/c/user/*
// @match              https://tieba.baidu.com/f?kw=*
// @match              https://www.tiktok.com/@*
// @match              https://x.com/*
// @match              https://www.youtube.com/@*
// @match              https://www.reddit.com/user/*
// @match              https://www.bilibili.com/video/*
// @match              https://www.youtube.com/watch*
// @match              https://www.douyin.com/video/*
// @match              https://www.tiktok.com/@*/video/*
// @match              https://www.pinterest.com/*/*
// @match              https://github.com/*
// @match              https://www.threads.com/*
// @match              https://www.facebook.com/*/
// @match              https://www.instagram.com/*
// @grant              none
// @license            MIT
// @icon               data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2aWV3Qm94PSIwIDAgMTIwMCAxMjAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxwYXRoIGQ9Ik0wIDBoMTIwMHYxMjAwSDB6IiBmaWxsPSJub25lIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAxLCAyLjI3MzczNjc1NDQzMjMyMDZlLTEzLCAwKSIvPgogIDxwYXRoIGZpbGw9IiMyNzdiZTAiIGQ9Ik0gNjAwIDEyMDAgQyAyNjguNjI5IDEyMDAgMCA5MzEuMzcxIDAgNjAwIEMgMCAyNjguNjI5IDI2OC42MjkgMCA2MDAgMCBDIDkzMS4zNzEgMCAxMjAwIDI2OC42MjkgMTIwMCA2MDAgQyAxMjAwIDkzMS4zNzEgOTMxLjM3MSAxMjAwIDYwMCAxMjAwIE0gNjQxLjE2MiA5MzkuOTkgQyA4MDEuNjk1IDkzOS45OSA5MzEuNzg3IDgwOS44MjQgOTMxLjc4NyA2NDkuMjkyIEMgOTMxLjc4NyA0ODguNzU5IDgwMS42OTUgMzU4LjY2NyA2NDEuMTYyIDM1OC42NjcgQyA1OTIuNTgxIDM1OC42NjcgNTQ2Ljc5NCAzNzAuNTUyIDUwNi41NDMgMzkxLjYyNiBDIDUwNi41ODQgMzkxLjQ0IDUwNi42NDkgMzkxLjIyNSA1MDYuNjg5IDM5MS4wNCBMIDM3NS41ODYgMjYwLjAxIEwgMjY4LjIxMyAzNjcuNDU2IEwgMzk0LjYyOSA0OTMuOTQ1IEMgMzk0LjgzOCA0OTQuMDM5IDM5NS4wNzkgNDk0LjA3NCAzOTUuMjg4IDQ5NC4xNjUgQyAzNjYuOTAxIDUzOS4wNTggMzUwLjQ2NCA1OTIuMjUzIDM1MC40NjQgNjQ5LjI5MiBDIDM1MC40NjQgODA5LjgyNSA0ODAuNjI5IDkzOS45OSA2NDEuMTYyIDkzOS45OSBNIDY0MS4xNjIgODEwLjg2NCBDIDU1MS45NDkgODEwLjg2NCA0NzkuNTkgNzM4LjUwNSA0NzkuNTkgNjQ5LjI5MiBDIDQ3OS41OSA1NjAuMDc5IDU1MS45NDkgNDg3Ljc5MyA2NDEuMTYyIDQ4Ny43OTMgQyA3MzAuMzc1IDQ4Ny43OTMgODAyLjY2MSA1NjAuMDc5IDgwMi42NjEgNjQ5LjI5MiBDIDgwMi42NjEgNzM4LjUwNSA3MzAuMzc2IDgxMC44NjQgNjQxLjE2MiA4MTAuODY0IiBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNjAwcHggNjAwcHg7IiB0cmFuc2Zvcm09Im1hdHJpeCgtMSwgMCwgMCwgLTEsIDAsIDApIi8+Cjwvc3ZnPg==
// ==/UserScript==

(function() {
    'use strict';

    // 平台用户名选择器映射
    const platformSelectors = {
        'space.bilibili.com': 'div[class*="nickname"]',
        'weibo.com/u/': 'div._name_1yc79_291',
        'www.weibo.com/': 'div._name_1yc79_291',
        'zhihu.com/people/': '.ProfileHeader-name',
        'douyin.com/user': [
            '[data-e2e="user-info"] h1',
            '[data-e2e="user-title"]',
            'h1[class*="name"]',
            '.arnSiSbK'
        ],
        'xiaohongshu.com/user': 'div[class*="user-name"], .user-name',
        'tieba.baidu.com/f?kw': '.card_title_fname',
        'douban.com/people/': '.info h1',
        'mp.weixin.qq.com/s': ['#js_name', '#js_ip_wording', '#publish_time'],
        'toutiao.com/c/user/': '.name',
        'tiktok.com/@': 'h1[data-e2e="user-title"]',
        'x.com/': 'div[data-testid="UserName"]',
        'twitter.com/': 'div[data-testid="UserName"]',
        'facebook.com/': '.html-h1',
        'instagram.com': [
            'header h2',
            'h2[class*="x"]',
            'section h2'
        ],
        'reddit.com/user/': 'h1[class*="Header__username"]',
        'threads.com/@':  '.xcrlgei h1',
        'github.com/': '.p-name.vcard-fullname',
        'youtube.com': [
            'h1.dynamicTextViewModelH1',
            'yt-dynamic-text-view-model[class*="ytPageHeaderViewModelTitle"] h1',
            '#page-header yt-dynamic-text-view-model h1',
            '#channel-name yt-formatted-string:not([is-empty])',
            '#text-container yt-formatted-string:not([is-empty])',
            '.yt-core-attributed-string--white-space-pre-wrap',
            '#channel-name #text',
            '#channel-header-container h1',
            '#channel-title'
        ]
    };

    // 视频标题选择器映射
    const videoTitleSelectors = {
        'bilibili.com/video/': [
            'h1.video-title',
            '.video-title',
            'h1[class*="video-title"]',
            '.video-title > .tit'
        ],
        'youtube.com/watch': [
            'h1.ytd-watch-metadata yt-formatted-string',
            '#title h1',
            'h1.style-scope.ytd-watch-metadata'
        ],
        'douyin.com/video/': [
            '.video-info-detail .title',
            'h1[class*="title"]',
            '[data-e2e="video-desc"]'
        ],
        'tiktok.com/video/': [
            'h1[data-e2e="video-desc"]',
            'h1[class*="title"]'
        ]
    };

    // 创建浮动窗口
    const panel = document.createElement('div');
    panel.id = 'social-query-panel';
    panel.style.cssText = 'position:fixed;top:12%;left:45%;background:#fff;border:none;border-radius:8px;padding:4px;width:300px;box-shadow:0 4px 12px rgba(0,0,0,0.25);z-index:999999;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;display:none;';

    // 增强样式隔离性
    const styleElement = document.createElement('style');
    styleElement.textContent = `
        #social-query-panel input[type="checkbox"] {
            appearance: auto !important;
        }
        .social-query-icon {
            display: inline-flex !important;
            align-items: center !important;
            justify-content: center !important;
            width: 18px;
            height: 18px;
            border-radius: 4px;
            cursor: pointer;
            margin-left: 10px;
            vertical-align: middle;
            transition: background-color 0.3s;
            flex-shrink: 0;
            color: white;
            background-color: #277BE0;
            box-sizing: content-box;
            line-height: 1;
            overflow: visible !important;
        }
        .social-query-icon svg {
            display: block !important;
            width: 14px;
            height: 14px;
            fill: currentColor;
            flex-shrink: 0;
            pointer-events: none;
        }
        .social-query-icon:hover {
            background-color: #0088ff;
            transform: scale(1.1);
        }
        .sq-btn {
            flex: 1;
            padding: 5px 12px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 13px;
            font-family: inherit;
            transition: background 0.15s;
            text-align: center;
        }
        .sq-btn-default {
            background: #e5e5ea;
            color: #333;
        }
        .sq-btn-default:hover {
            background: #d1d1d6;
        }
        .sq-btn-primary {
            background: #007aff;
            color: #fff;
        }
        .sq-btn-primary:hover {
            background: #0062cc;
        }
    `;
    document.head.appendChild(styleElement);

    // 当前模式:'username' 或 'title'
    let currentMode = 'username';

    // 创建放大镜图标
    function createMagnifierIcon() {
        const icon = document.createElement('span');
        icon.className = 'social-query-icon';
        icon.title = '多平台搜索';
        icon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="currentColor"><circle cx="6.5" cy="6.5" r="5" fill="none" stroke="currentColor" stroke-width="2.5"/><path d="M10.5 10.5l1.5 2" stroke="currentColor" stroke-width="3" stroke-linecap="round"/></svg>';

        icon.addEventListener('click', function(e) {
            e.stopPropagation();
            panel.style.display = 'block';
            contentContainer.style.display = 'block';

            const rect = icon.getBoundingClientRect();
            panel.style.top = (rect.bottom + window.scrollY + 10) + 'px';
            panel.style.left = (rect.left + window.scrollX - 150) + 'px';

            setTimeout(() => inputField.focus(), 100);
        });

        return icon;
    }

    // 根据不同平台添加交互(用户名页面显示图标,视频页面双击标题)
    function addMagnifierIcon() {
        const currentURL = window.location.href;
        let targetElement = null;
        let targetText = '';
        let detectedMode = 'username';

        // 1. 先检查是否为视频页面(视频标题选择器)
        for (const [urlPart, selector] of Object.entries(videoTitleSelectors)) {
            if (currentURL.includes(urlPart)) {
                detectedMode = 'title';
                const selectors = Array.isArray(selector) ? selector : [selector];
                for (const sel of selectors) {
                    const element = document.querySelector(sel);
                    if (element && element.textContent.trim()) {
                        targetElement = element;
                        targetText = element.textContent.trim();
                        break;
                    }
                }
                if (targetElement) break;
            }
        }

        // 2. 如果不是视频页面,退回到用户名选择器(原有逻辑)
        if (!targetElement) {
            for (const [urlPart, selector] of Object.entries(platformSelectors)) {
                if (currentURL.includes(urlPart)) {
                    if (Array.isArray(selector)) {
                        for (const sel of selector) {
                            const element = document.querySelector(sel);
                            if (element && element.textContent.trim()) {
                                if (urlPart === 'mp.weixin.qq.com/s') {
                                    if (sel === '#js_name') {
                                        targetText = element.textContent.trim();
                                    } else if (sel === '#js_ip_wording') {
                                        targetElement = element;
                                    } else if (sel === '#publish_time' && !targetElement) {
                                        targetElement = element;
                                    }
                                } else {
                                    targetElement = element;
                                    break;
                                }
                            }
                        }
                        if (targetText && !targetElement) {
                            targetElement = document.querySelector('#js_ip_wording') || document.querySelector('#publish_time');
                        }
                    } else {
                        targetElement = document.querySelector(selector);
                    }
                    break;
                }
            }
        }

        // 3. 如果找到目标元素
        if (targetElement) {
            if (detectedMode === 'title') {
                // 视频页面:添加双击事件
                if (targetElement.dataset.socialQueryBound) return;
                targetElement.dataset.socialQueryBound = 'true';

                targetElement.addEventListener('dblclick', function(e) {
                    e.stopPropagation();
                    panel.style.display = 'block';
                    contentContainer.style.display = 'block';

                    // 面板出现在鼠标位置下方,自适应边界
                    const panelW = panel.offsetWidth || 300;
                    const panelH = panel.offsetHeight || 400;
                    let top = e.clientY + 10;
                    let left = e.clientX - Math.round(panelW / 2);
                    if (top + panelH > window.innerHeight) top = window.innerHeight - panelH - 10;
                    if (left + panelW > window.innerWidth) left = window.innerWidth - panelW - 10;
                    if (left < 10) left = 10;
                    panel.style.top = top + 'px';
                    panel.style.left = left + 'px';

                    // 自动填充文本
                    inputField.value = targetText || targetElement.textContent.trim();
                    currentMode = detectedMode;
                    inputField.placeholder = '输入要搜索的视频标题';

                    setTimeout(() => inputField.focus(), 100);
                });
            } else {
                // 用户名页面:插入图标
                if (targetElement.querySelector('.social-query-icon')) return;
                const icon = createMagnifierIcon();

                if (currentURL.includes('douyin.com') || currentURL.includes('instagram.com')) {
                    targetElement.style.display = 'inline-flex';
                    targetElement.style.alignItems = 'center';
                }

                // 追加到标题文本之后
                // 防止父元素 text-overflow/overflow 导致图标显示为 ... 或被裁切
                const parentStyle = getComputedStyle(targetElement);
                if (parentStyle.textOverflow === 'ellipsis') {
                    targetElement.style.setProperty('text-overflow', 'clip', 'important');
                }
                if (parentStyle.overflow === 'hidden') {
                    targetElement.style.overflow = 'visible';
                }
                targetElement.appendChild(icon);
                // 将无文本的第三方图标移到本图标后面
                const allChildren = Array.from(targetElement.children);
                const myIdx = allChildren.indexOf(icon);
                for (let i = 0; i < myIdx; i++) {
                    const el = allChildren[i];
                    if (el.tagName === 'SPAN' || el.tagName === 'A' || el.tagName === 'IMG') {
                        if (!(el.textContent || '').trim()) {
                            targetElement.appendChild(el);
                        }
                    }
                }
            }

            // 自动填充文本
            inputField.value = targetText || targetElement.textContent.trim();
            currentMode = detectedMode;
            inputField.placeholder = detectedMode === 'title' ? '输入要搜索的视频标题' : '输入要查询的用户名';
        }
    }

    // 创建标题栏
    const titleBar = document.createElement('div');
    titleBar.style.cssText = 'display:flex;justify-content:space-between;align-items:center;padding:4px 10px;font-size:14px;color:#333;border-bottom:1px solid #eee;margin-bottom:4px;cursor:move;border-radius:8px 8px 0 0;';

    // 创建标题文本
    const titleText = document.createElement('span');
    titleText.textContent = '▼ 一键多平台搜索';
    titleText.style.cssText = 'flex:1;';
    titleBar.appendChild(titleText);

    // 创建关闭按钮
    const closeBtn = document.createElement('span');
    closeBtn.textContent = '\u2715';
    closeBtn.style.cssText = 'cursor:pointer;color:#999;width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:all 0.2s ease;margin-left:10px;';

    closeBtn.addEventListener('mouseover', () => closeBtn.style.backgroundColor = '#dadada');
    closeBtn.addEventListener('mouseout', () => closeBtn.style.backgroundColor = '');
    closeBtn.addEventListener('click', (e) => {
        e.stopPropagation();
        panel.style.display = 'none';
    });

    titleBar.appendChild(closeBtn);

    // 创建内容容器
    const contentContainer = document.createElement('div');
    contentContainer.style.cssText = 'display:block;'; // 默认展开

    // 拖动相关变量和事件
    let startX = 0, startY = 0, startLeft = 0, startTop = 0, isDragging = false;

    titleBar.addEventListener('mousedown', function(e) {
        if (e.target === closeBtn) return;
        isDragging = true;
        startX = e.clientX;
        startY = e.clientY;
        startLeft = parseInt(window.getComputedStyle(panel).left);
        startTop = parseInt(window.getComputedStyle(panel).top);
        e.preventDefault();
    });

    function mouseMoveHandler(e) {
        if (!isDragging) return;
        const deltaX = e.clientX - startX;
        const deltaY = e.clientY - startY;
        panel.style.left = (startLeft + deltaX) + 'px';
        panel.style.top = (startTop + deltaY) + 'px';
    }

    function mouseUpHandler() {
        isDragging = false;
    }

    document.addEventListener('mousemove', mouseMoveHandler);
    document.addEventListener('mouseup', mouseUpHandler);

    // 双击Esc关闭窗口
    let lastEscTime = 0;
    function escHandler(evt) {
        if (evt.key === 'Escape') {
            const now = Date.now();
            if (now - lastEscTime <= 300) {
                panel.style.display = 'none';
            }
            lastEscTime = now;
        }
    }
    document.addEventListener('keydown', escHandler);

    // 创建输入框
    const inputContainer = document.createElement('div');
    inputContainer.style.cssText = 'padding:8px 10px;display:flex;align-items:center;';

    const inputField = document.createElement('input');
    inputField.style.cssText = 'flex:1;padding:4px 8px;border:1px solid #ccc;border-radius:4px;font-size:14px;width:100%;';
    inputField.placeholder = '输入要查询的用户名';

    inputContainer.appendChild(inputField);

    // 社交平台列表
    const chinesePlatforms = [
        {title: '微博', url: 'https://s.weibo.com/weibo/'},
        {title: '抖音', url: 'https://www.douyin.com/search/'},
        {title: '哔哩哔哩', url: 'https://search.bilibili.com/all?keyword='},
        {title: '小红书', url: 'https://www.xiaohongshu.com/search_result?keyword='},
        {title: '知乎', url: 'https://www.zhihu.com/search?q='},
        {title: '豆瓣', url: 'https://www.douban.com/search?cat=1005&q='},
        {title: '公众号', url: 'https://weixin.sogou.com/weixin?type=2&query='},
        {title: '头条', url: 'https://so.toutiao.com/search?dvpf=pc&source=input&keyword='},
        {title: '贴吧', url: 'https://tieba.baidu.com/f?kw='}
    ];

    const foreignPlatforms = [
        {title: 'Twitter', url: 'https://x.com/search?q='},
        {title: 'TikTok', url: 'https://www.tiktok.com/search/user?q='},
        {title: 'YouTube', url: 'https://www.youtube.com/results?search_query='},
        {title: 'Instagram', url: 'https://www.instagram.com/explore/search/keyword/?q='},
        {title: 'Facebook', url: 'https://www.facebook.com/search/top/?q='},
        {title: 'Pinterest', url: 'https://www.pinterest.com/search/pins/?q='},
        {title: 'GitHub', url: 'https://github.com/search?type=users&q='},
        {title: 'Reddit', url: 'https://www.reddit.com/search/?q='},
        {title: 'Threads', url: 'https://www.threads.com/search?q='}
    ];

    // 创建平台容器
    const platformContainer = document.createElement('div');
    platformContainer.style.cssText = 'display:flex;flex-wrap:wrap;padding:10px;';

    // 添加复选框
    function createCheckboxItem(platform, container, isDefault = false) {
        const item = document.createElement('div');
        item.style.cssText = 'width:33.33%;padding:5px 5px 5px 1px;box-sizing:border-box;';

        const label = document.createElement('label');
        label.style.cssText = 'display:flex;align-items:center;font-size:14px;cursor:pointer;color:#333;white-space:nowrap;';

        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.dataset.url = platform.url;
        checkbox.style.marginRight = '5px';
        checkbox.checked = isDefault;

        // 阻止事件冒泡
        checkbox.addEventListener('mousedown', e => e.stopPropagation());
        label.addEventListener('mousedown', e => e.stopPropagation());

        label.appendChild(checkbox);
        label.appendChild(document.createTextNode(platform.title));
        item.appendChild(label);
        container.appendChild(item);
    }

    // 合并所有平台到同一个容器
    const allPlatforms = [...chinesePlatforms, ...foreignPlatforms];
    allPlatforms.forEach(platform => {
        const isDefault = ['哔哩哔哩', '微博', '抖音'].includes(platform.title);
        createCheckboxItem(platform, platformContainer, isDefault);
    });

    // 添加按钮区域
    const buttonContainer = document.createElement('div');
    buttonContainer.style.cssText = 'display:flex;gap:8px;padding:12px 8px 8px 8px;border-top:1px solid #eee;font-size:14px;';

    // 创建按钮函数
    function createButton(text, className, clickHandler) {
        const button = document.createElement('button');
        button.textContent = text;
        button.className = className;
        button.addEventListener('mousedown', e => e.stopPropagation());
        button.addEventListener('click', clickHandler);
        return button;
    }

    // 全选按钮
    const selectAllBtn = createButton(
        '全选',
        'sq-btn sq-btn-default',
        e => {
            e.stopPropagation();
            panel.querySelectorAll('input[type="checkbox"]').forEach(cb => cb.checked = true);
        }
    );

    // 取消全选按钮
    const deselectAllBtn = createButton(
        '取消',
        'sq-btn sq-btn-default',
        e => {
            e.stopPropagation();
            panel.querySelectorAll('input[type="checkbox"]').forEach(cb => cb.checked = false);
        }
    );

    // 查询按钮
    const queryBtn = createButton(
        '查询',
        'sq-btn sq-btn-primary',
        e => {
            e.stopPropagation();
            const username = inputField.value.trim();
            if (!username) {
                alert(currentMode === 'title' ? '请输入视频标题' : '请输入用户名');
                return;
            }

            const selectedCheckboxes = panel.querySelectorAll('input[type="checkbox"]:checked');
            if (selectedCheckboxes.length === 0) {
                alert('请至少选择一个平台');
                return;
            }

            // 打开选中的平台
            selectedCheckboxes.forEach(checkbox => {
                window.open(checkbox.dataset.url + username);
            });
        }
    );

    buttonContainer.appendChild(selectAllBtn);
    buttonContainer.appendChild(deselectAllBtn);
    buttonContainer.appendChild(queryBtn);

    // 将所有内容添加到内容容器
    contentContainer.appendChild(inputContainer);
    contentContainer.appendChild(platformContainer);
    contentContainer.appendChild(buttonContainer);

    // 组装面板
    panel.appendChild(titleBar);
    panel.appendChild(contentContainer);

    // 添加到页面
    document.body.appendChild(panel);

    // 添加点击页面其他区域关闭面板
    document.addEventListener('click', function(e) {
        if (!panel.contains(e.target) && !e.target.classList.contains('social-query-icon')) {
            panel.style.display = 'none';
        }
    });

    // 添加放大镜图标 — 第一时间尝试
    addMagnifierIcon();

    // DOM 就绪后再次尝试
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', addMagnifierIcon);
    }

    // 监听DOM变化,确保在动态加载的页面上也能添加图标
    let iconAddPending = false;
    const observer = new MutationObserver(function() {
        if (iconAddPending) return;
        iconAddPending = true;
        requestAnimationFrame(function() {
            addMagnifierIcon();
            iconAddPending = false;
        });
    });

    observer.observe(document.body, { childList: true, subtree: true });
})();