Greasy Fork

Greasy Fork is available in English.

🔍聚合快搜

为Via设计的第三方聚合搜索栏

当前为 2024-08-04 提交的版本,查看 最新版本

// ==UserScript==
// @name         🔍聚合快搜
// @namespace    https://ez118.github.io/
// @version      0.2
// @description  为Via设计的第三方聚合搜索栏
// @author       ZZY_WISU
// @match        *://*/*
// @license      GNU GPLv3
// @icon         data:image/svg+xml;charset=utf-8;base64,PHN2ZyB2ZXJzaW9uPSIxLjIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDEyOCAxMjgiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCI+PHBhdGggZD0iTTY0IDEyOEMyOC42IDEyOCAwIDk5LjQgMCA2NFMyOC42IDAgNjQgMHM2NCAyOC42IDY0IDY0LTI4LjYgNjQtNjQgNjR6IiBzdHlsZT0iZmlsbDojZjJmN2ZmIi8+PHBhdGggZD0iTTM0LjMgNzkuNUMyMy4xIDc5LjUgMTQgNzAuNCAxNCA1OS4yIDE0IDQ4LjEgMjMuMSAzOSAzNC4zIDM5YzExLjEgMCAyMC4yIDkuMSAyMC4yIDIwLjMgMCAxMS4xLTkuMSAyMC4yLTIwLjIgMjAuMnoiIHN0eWxlPSJmaWxsOiMwMGE1ZjYiLz48cGF0aCBkPSJNNTkgMTA0Yy0xMy44IDAtMjUtMTEuMi0yNS0yNXMxMS4yLTI1IDI1LTI1IDI1IDExLjIgMjUgMjUtMTEuMiAyNS0yNSAyNXoiIHN0eWxlPSJmaWxsOiNmZjNlMDAiLz48cGF0aCBkPSJNODguMiA4MC41QzcxLjUgODAuNSA1OCA2NyA1OCA1MC4yIDU4IDMzLjUgNzEuNSAyMCA4OC4yIDIwYzE2LjggMCAzMC4zIDEzLjUgMzAuMyAzMC4yIDAgMTYuOC0xMy41IDMwLjMtMzAuMyAzMC4zeiIgc3R5bGU9ImZpbGw6I2ZmYjcwMCIvPjwvc3ZnPg==
// @run-at document-start
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addElement
// @grant        window.onurlchange
// @require      https://update.greasyfork.icu/scripts/499192/1402326/jquery_360.js
// ==/UserScript==

const searchEngine = [
    {
        "id":"duckduckgo",
        "name":"DuckDuckGo",
        "link":"https://duckduckgo.com/?t=h_&q=%s"
    },
    {
        "id":"bing",
        "name":"Bing",
        "link":"https://www.bing.com/search?q=%s"
    },
    {
        "id":"github",
        "name":"Github",
        "link":"https://github.com/search?q=%s&type=repositories"
    },
    {
        "id":"fdroid",
        "name":"F-Droid",
        "link":"https://search.f-droid.org/?q=%s&lang=zh_Hans"
    },
    {
        "id":"baidu",
        "name":"百度",
        "link":"https://www.baidu.com/s?wd=%s"
    }
];

var currentEngine = null; /* 存储当前正在使用的搜索引擎 */
var currentQuery = null; /* 存储当前检索词 */




function invertHex(hex) {
    hex = hex.replace("#", "");

    // 补全短的 hex 颜色代码
    if (hex.length === 3) {
        hex = hex.split('').map(c => c + c).join('');
    }

    // 确保 hex 长度为 6
    if (hex.length !== 6) {
        throw new Error("Invalid HEX color.");
    }

    // 计算反色
    let inverted = (Number(`0x${hex}`) ^ 0xFFFFFF).toString(16).toUpperCase();

    // 补全不足位数的 0
    inverted = ("000000" + inverted).slice(-6);

    return `#${inverted}`;
}

function invertRgb(rgb) {
    // 匹配 rgb(r, g, b) 格式
    const match = rgb.match(/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/);
    if (!match) {
        throw new Error("Invalid RGB color.");
    }

    const r = 255 - parseInt(match[1], 10);
    const g = 255 - parseInt(match[2], 10);
    const b = 255 - parseInt(match[3], 10);

    return `rgb(${r}, ${g}, ${b})`;
}

function invertRgba(rgba) {
    // 匹配 rgba(r, g, b, a) 格式
    const match = rgba.match(/^rgba\((\d{1,3}), (\d{1,3}), (\d{1,3}), (0|0?\.\d+|1(\.0)?)\)$/);
    if (!match) {
        throw new Error("Invalid RGBA color.");
    }

    const r = 255 - parseInt(match[1], 10);
    const g = 255 - parseInt(match[2], 10);
    const b = 255 - parseInt(match[3], 10);
    const a = 1;//parseFloat(match[4]);

    return `rgba(${r}, ${g}, ${b}, ${a})`;
}
function invertColor(color) {
    if (color.startsWith("#")) {
        return invertHex(color);
    } else if (color.startsWith("rgb(")) {
        return invertRgb(color);
    } else if (color.startsWith("rgba(")) {
        return invertRgba(color);
    } else {
        throw new Error("Invalid color format.");
    }
}

function findByKeyValue(array, key, value) {
    for (let i = 0; i < array.length; i++) {
        if (array[i][key] === value) {
            return i;
        }
    }
    return -1; // 如果没有找到匹配的item,返回-1
}

function isSearchEngine() {
    const currentUrl = window.location.href;
    return searchEngine.filter(engine => {
        const prefix = engine.link.split('%s')[0];
        return currentUrl.includes(prefix);
    });
}

function initEle() {
    // 创建搜索栏元素并添加到页面
    var $quickSearchBar = $('<div>', {
        class: 'userscript-quickSearchBar',
        id: 'userscript-quickSearchBar'
    }).appendTo('body');

    var html = "";
    const currentURL = window.location.href;

    // 生成搜索引擎按钮的 HTML 内容
    $.each(searchEngine, (index, item) => {
        const link = item.link;
        const splitLink = link.split('%s');
        let prefix = null;
        let suffix = null;

        if (splitLink.length === 2) {
            prefix = splitLink[0];
            suffix = splitLink[1];
        } else if (splitLink.length > 2) {
            prefix = splitLink[0];
            suffix = splitLink.slice(1).join('%s');
        }

        if (currentURL.startsWith(prefix) && currentURL.endsWith(suffix)) {
            currentEngine = item;
            currentQuery = currentURL.slice(prefix.length, currentURL.length - suffix.length);
            html += `<div class="item active" seid="${item.id}">${item.name}</div>`;
        } else {
            html += `<div class="item" seid="${item.id}">${item.name}</div>`;
        }
    });

    // 清理 HTML 内容并插入到搜索栏
    $quickSearchBar.append(html + `
        <div id="userscript-quickSearchBar-optBtn">⚙️</div>
        <div class="blank"></div>
    `);

    // 添加点击事件监听器
    $("#userscript-quickSearchBar>.item").click((e) => {
        var seid = $(e.target).attr("seid");
        var seIndex = findByKeyValue(searchEngine, "id", seid);
        location.href = searchEngine[seIndex].link.replace("%s", currentQuery);
    });
}


(function () {
    'use strict';

    var websiteThemeColor = $('body').css('background-color') || "#FFF";
    var websiteFontColor = invertColor(websiteThemeColor);

    /* 适配黑暗模式 */
    if(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
        /* 黑暗模式下的样式 */
        GM_addStyle(`
            .userscript-quickSearchBar{ user-select:none; background-color:` + websiteThemeColor + `; color:` + websiteFontColor + `; padding:6px 10px; font-size:12px; line-height:20px; width:100vw; height:30px; border-top:1px solid #AAA; position:fixed; bottom:-1px; left:0; right:0; display:flex; flex-direction:row; overflow-x:auto; overflow-y:hidden; box-sizing: initial; z-index:100000; }
            .userscript-quickSearchBar>.item{ margin:0px 5px; border-radius:20px; border:1px solid #ddd; padding:5px 9px; width:fit-content; flex-basis:fit-content; flex-shrink:0; cursor:pointer; background-color:transparent; }
            .userscript-quickSearchBar>.active{ border:1px solid #6d7fb4; color:#6d7fb4; }
            .userscript-quickSearchBar>.blank{ flex-basis:25px; flex-shrink:0; width:25px; }
            #userscript-quickSearchBar-optBtn{ flex-shrink:0; flex-basis:fit-content; width:fit-content; border-radius:20px; border:1px solid #ddd; padding:4px 6px; cursor:pointer; }
        `);
    } else {
        /* 日间模式下的样式 */
        GM_addStyle(`
            .userscript-quickSearchBar{ user-select:none; background-color:` + websiteThemeColor + `; color:` + websiteFontColor + `; padding:6px 10px; font-size:12px; line-height:20px; width:100vw; height:30px; border-top:1px solid #AAA; position:fixed; bottom:-1px; left:0; right:0; display:flex; flex-direction:row; overflow-x:auto; overflow-y:hidden; box-sizing: initial; z-index:100000; }
            .userscript-quickSearchBar>.item{ margin:0px 5px; border-radius:20px; border:1px solid #ddd; padding:5px 9px; width:fit-content; flex-basis:fit-content; flex-shrink:0; cursor:pointer; background-color:transparent; }
            .userscript-quickSearchBar>.active{ border:1px solid #6d7fb4; color:#6d7fb4; }
            .userscript-quickSearchBar>.blank{ flex-basis:25px; flex-shrink:0; width:25px; }
            #userscript-quickSearchBar-optBtn{ flex-shrink:0; flex-basis:fit-content; width:fit-content; border-radius:20px; border:1px solid #ddd; padding:4px 6px; cursor:pointer; }
        `);
    }

    if(isSearchEngine()){
        console.log("【提示】已保存的搜素引擎")
        initEle();
    }
})();