拖拽文字搜索|拖拽图片下载

Drag text to search or drag images to download

// ==UserScript==
// @name         拖拽文字搜索|拖拽图片下载
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Drag text to search or drag images to download
// @author       Dost
// @match        *://*/*
// @grant        GM_download
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_openInTab
// @grant        GM_notification
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 默认搜索引擎配置
    const defaultEngines = [
        { name: "Google", url: "https://www.google.com/search?q={query}", enabled: false },
        { name: "Bing", url: "https://www.bing.com/search?q={query}", enabled: false },
        { name: "Yandex", url: "https://yandex.com/search/?text={query}", enabled: false },
        { name: "DuckDuckGo", url: "https://duckduckgo.com/?q={query}", enabled: false }
    ];

    // 图片扩展名列表
    const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'];

    // 初始化配置
    let engines = GM_getValue('engines', defaultEngines);
    let tabBehavior = GM_getValue('tabBehavior', 1);

    // 注册脚本菜单
    function registerMenu() {
        GM_registerMenuCommand('🔍 设置搜索引擎', setSearchEngines);
        GM_registerMenuCommand('🔄 设置标签页行为', setTabBehavior);
    }

    // 设置搜索引擎
    function setSearchEngines() {
        let engineList = engines.map((engine, index) =>
            `${engine.enabled ? '✅' : '❌'} ${index + 1}. ${engine.name}`).join('\n');

        const input = prompt(
            `输入需要启用的引擎序号(用逗号分隔):\n\n${engineList}\n\n示例:输入 "1,3"`,
            engines.map((e, i) => e.enabled ? i + 1 : '').filter(Boolean).join(',')
        );

        if (input === null) return;

        engines.forEach(engine => engine.enabled = false);

        if (input.trim() !== '') {
            input.split(',').forEach(num => {
                const index = parseInt(num.trim()) - 1;
                if (index >= 0 && index < engines.length) engines[index].enabled = true;
            });
        }

        GM_setValue('engines', engines);
        alert(`已启用:${engines.filter(e => e.enabled).map(e => e.name).join(', ') || "无"}`);
    }

    // 设置标签页行为
    function setTabBehavior() {
        const behaviors = [
            "1. 在新标签页打开并跳转",
            "2. 在新标签页打开但不跳转",
            "3. 在当前标签页打开"
        ];

        const currentBehavior = behaviors[tabBehavior - 1];
        const choice = prompt(
            `选择标签页行为(输入序号):\n\n${behaviors.join('\n')}\n\n当前:${currentBehavior}`,
            tabBehavior
        );

        if (choice && [1, 2, 3].includes(parseInt(choice))) {
            tabBehavior = parseInt(choice);
            GM_setValue('tabBehavior', tabBehavior);
            alert(`已设置为:${behaviors[tabBehavior - 1]}`);
        }
    }

    // 检查是否是图片URL
    function isImageUrl(url) {
        try {
            const pathname = new URL(url).pathname.toLowerCase();
            const ext = pathname.split('.').pop();
            return imageExtensions.includes(ext);
        } catch {
            return false;
        }
    }

    // 执行搜索
    function searchText(query) {
        // 如果是图片URL则不搜索
        if (isImageUrl(query)) return;

        engines.forEach(engine => {
            if (engine.enabled) {
                const url = engine.url.replace('{query}', encodeURIComponent(query));
                switch (tabBehavior) {
                    case 1: GM_openInTab(url, { active: true }); break;
                    case 2: GM_openInTab(url, { active: false }); break;
                    case 3: window.location.href = url; break;
                }
            }
        });
    }

    // 生成图片文件名
    function generateImageFilename() {
        const domain = window.location.hostname
            .replace('www.', '')
            .replace(/[^a-z0-9]/gi, '_')
            .toLowerCase();

        const now = new Date();
        const timestamp = [
            now.getFullYear(),
            (now.getMonth()+1).toString().padStart(2, '0'),
            now.getDate().toString().padStart(2, '0'),
            now.getHours().toString().padStart(2, '0'),
            now.getMinutes().toString().padStart(2, '0'),
            now.getSeconds().toString().padStart(2, '0')
        ].join('');

        return `${domain}_${timestamp}.jpg`;
    }

    // 拖拽事件处理
    document.addEventListener('dragstart', (e) => {
        if (e.target.tagName === 'IMG') {
            e.dataTransfer.setData('text/uri-list', e.target.src);
            e.dataTransfer.effectAllowed = 'copy';
        } else if (window.getSelection().toString().trim()) {
            e.dataTransfer.setData('text/plain', window.getSelection().toString().trim());
        }
    });

    document.addEventListener('dragend', (e) => {
        if (e.target.tagName === 'IMG') {
            e.preventDefault();
            const imageUrl = e.target.src;
            const filename = generateImageFilename();

            GM_download({
                url: imageUrl,
                name: filename,
                saveAs: true, // 让用户选择保存位置
                onload: () => GM_notification({
                    title: '图片下载成功',
                    text: `已保存为: ${filename}`,
                    timeout: 2000
                }),
                onerror: (err) => GM_notification({
                    title: '下载失败',
                    text: `错误: ${err.details}`,
                    timeout: 3000
                })
            });
        }
    });

    document.addEventListener('drop', (e) => {
        const text = e.dataTransfer.getData('text/plain');
        if (text && !isImageUrl(text)) {  // 只搜索非图片URL的文本
            e.preventDefault();
            searchText(text);
        }
    });

    document.addEventListener('dragover', (e) => e.preventDefault());

    // 初始化
    registerMenu();
})();