素问搜索助手

为爱发电、知乎文章添加跳转素问按钮

目前为 2025-04-07 提交的版本。查看 最新版本

// ==UserScript==
// @name         素问搜索助手
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  为爱发电、知乎文章添加跳转素问按钮
// @author       You
// @match        https://www.zhihu.com/question/*/answer/*
// @match        https://sooon.ai/home/read/**
// @match        https://afdian.com/p/*
// @grant        GM_log
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Utility functions
    async function timeSleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    async function queryEle(selector, all = false) {
        const maxAttempts = 10;
        const baseDelay = 100; // 100ms base delay
        let totalWaitTime = 0;

        for (let attempt = 1; attempt <= maxAttempts; attempt++) {
            const ele = all ? document.querySelectorAll(selector) : document.querySelector(selector);
            if (ele && (!all || ele.length > 0)) {
                return ele;
            }

            // Calculate exponential delay with jitter
            const delay = Math.min(
                baseDelay * Math.pow(2, attempt - 1) + Math.random() * 100,
                2000 // Cap at 2s to prevent extremely long waits
            );

            totalWaitTime += delay;
            if (totalWaitTime >= 10000) { // Don't exceed 10s total
                break;
            }

            await new Promise(resolve => setTimeout(resolve, delay));
        }

        return null;
    }



    // Zhihu specific functionality
    function handleZhihuPage() {
        // 全局样式


        // 从特定元素中提取#tag#
        function extractTag(element) {
            if (!element) return "知乎回答";

            // 先尝试找第一个段落
            const firstParagraph = element.querySelector('p[data-first-child], p:first-child');
            let text = firstParagraph ? firstParagraph.textContent.trim() : element.textContent.trim();

            // 查找#tag#格式
            const tagMatch = text.match(/#([^#]+)#/);
            if (tagMatch) {
                return tagMatch[1].trim();
            }

            return "知乎回答";
        }

        // 添加跳转素问按钮
        function addSuwenRedirectButton() {
            const existingBtn = document.querySelector('.go-sooon-link');
            if (existingBtn) return;

            const contentElement = document.querySelector('#root > div > main > div > div > div.Question-main > div.ListShortcut > div > div.Card.AnswerCard.css-0 > div > div > div > div.RichContent.RichContent--unescapable');
            const firstParagraph = contentElement.querySelector('p[data-first-child], p:first-child');
            const tag = extractTag(contentElement);


            const button = document.createElement('button');
            button.className = 'go-sooon-link';
            button.textContent = '跳转素问';

            button.addEventListener('click', () => {
                window.location.href = `https://sooon.ai/home/read/feed?search=${encodeURIComponent(tag)}`;
            });

            firstParagraph.parentNode.insertBefore(button, firstParagraph.nextSibling);
        }

        // 观察页面变化
        function observePageChanges() {
            const observer = new MutationObserver(mutations => {
                const contentElement = document.querySelector('#root > div > main > div > div > div.Question-main > div.ListShortcut > div > div.Card.AnswerCard.css-0 > div > div > div > div.RichContent.RichContent--unescapable');
                if (!contentElement) return;

                const firstParagraph = contentElement.querySelector('p[data-first-child], p:first-child');
                if (firstParagraph && (!firstParagraph.nextElementSibling || !firstParagraph.nextElementSibling.classList.contains('copy-md-link'))) {
                    console.log('addSuwenRedirectButton');
                    addSuwenRedirectButton();
                }
            });

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

        // 初始化Zhihu页面
        function initZhihu() {
            observePageChanges();
            console.log('Zhihu page initialized');
        }

        initZhihu();
    }

    // Afdian specific functionality
    function handleAfdianPage() {

        async function addGoSooonLink() {
            const pageTitle = document.title.slice(0, document.title.length - 10);
            await timeSleep(600)
            let textEle = document.querySelector("div.feed-content.mt16.post-page.unlock>pre")
            if (!textEle) {
                textEle = await queryEle("article > p")
            }
            let text = textEle?.textContent.trim();

            const tagMatch = text?.match(/#(.+)#/);
            const tagText = tagMatch ? tagMatch[1] : "untagged";
            console.log('Afdian tag:', tagText);
            const existingBtn = document.querySelector('.go-sooon-link');
            if (existingBtn) return;
            // 添加到 article 内第一个元素
            const goSooonLink = document.createElement('button');
            goSooonLink.textContent = '跳转素问';
            goSooonLink.className = 'go-sooon-link';
            goSooonLink.style.cssText = `
                font-size: .75em;
                color: #946CE6;
                border: 1px solid #946CE6;
            `;
            goSooonLink.addEventListener('click', () => {
                window.location.href = `https://sooon.ai/home/read/feed?search=${encodeURIComponent(tagText)}`;
            });
            // 插到text前
            const parent = document.querySelector(".title-box")
                parent.appendChild(goSooonLink)
            }

        addGoSooonLink()
        // 检查页面 resize
        window.addEventListener('resize', addGoSooonLink)
    }

    // Soon.ai specific functionality
    async function handleSoonPage() {
        const queryParams = new URLSearchParams(window.location.search);
        const searchQuery = queryParams.get('search');

        if (!searchQuery) return;

        console.log('Search query found:', searchQuery);


        // Click search button
        const searchBtn = await queryEle('button[aria-label="快速搜索"]');
        if (!searchBtn) {
            console.log('Search button not found');
            return;
        }

        searchBtn.click();

        // Input search query
        const input = await queryEle('input[name="input"]');
        if (!input) {
            console.log('Search input not found');
            return;
        }

        input.value = searchQuery;

        // Submit search
        const submitBtn = await queryEle('button[type="submit"]');
        if (!submitBtn) {
            console.log('Submit button not found');
            return;
        }
        submitBtn.focus();
        submitBtn.click();

        // Check results
        await timeSleep(1200);
        const titles = await queryEle('form div.mantine-focus-never button span.inline-block', true);
        if (titles && titles.length > 0) {
            // 默认点击第一个button, 即父级div
            let target = titles[0].parentElement;
            target.focus();
            target.click();
        } else {
            console.log('没有找到搜索结果');
        }
    }

    // Main router
    function init() {
        const url = window.location.href;
        const style = document.createElement('style');
        style.textContent = `
            .go-sooon-link {
                background: none;
                font-size: 1em;
                font-weight: 500;
                color: #0066FF;
                border: 1px solid #228BE6;
                padding: 2px 8px;
                margin-left: 10px;
                border-radius: 3px;
                cursor: pointer;
                display: inline-block;
                vertical-align: middle;
            }
            .go-sooon-link:hover {
                opacity: 0.8;
                color: gray;
                border-color: gray;
            }
        `;
        document.head.appendChild(style);
        if (url.includes('zhihu.com')) {
            handleZhihuPage();
        }
        else if (url.includes('afdian.com')) {
            handleAfdianPage();
        }
        else if (url.includes('sooon.ai')) {
            handleSoonPage();
        }
    }

    // Wait for page to load before initializing
    if (document.readyState === 'complete') {
        init();
    } else {
        window.addEventListener('load', init);
    }
})();