Greasy Fork

Greasy Fork is available in English.

腾讯元宝/谷歌ai/扣子文件盒子上传增强

粘贴或拖放时自动为代码文件添加.txt后缀并修正MIME类型,使其可正常上传。可能仍会提示不支持,但看到上传成功即可。目前选择上传方式尚未修改。

当前为 2025-03-29 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         腾讯元宝/谷歌ai/扣子文件盒子上传增强
// @namespace    https://gist.github.com/youzhiran/4fc8fa8a34c35c34ab455cd3f76d8236
// @version      1.5
// @description  粘贴或拖放时自动为代码文件添加.txt后缀并修正MIME类型,使其可正常上传。可能仍会提示不支持,但看到上传成功即可。目前选择上传方式尚未修改。
// @author       yooyi
// @match        *://yuanbao.tencent.com/*
// @match        *://aistudio.google.com/*
// @match        *://www.coze.cn/space/*
// @grant        none
// @license      MIT
// ==/UserScript==

// 1.5更新:移除元宝官方支持的语言

(function () {
    'use strict';

    const UNSUPPORTED_EXT = ['.dart', '.kt', '.html', '.scss',
        '.php', '.vbs', '.xml', '.cmd', '.rs', '.ts'];

    let eventsInitialized = false;

    function checkCozeCondition() {
        if (window.location.hostname.includes('www.coze.cn')) {
            const targetElement = document.querySelector('#semi-modal-body > div > div');
            if (targetElement && !eventsInitialized) {
                initDropEvent();
                eventsInitialized = true;
                return true;
            }
        } else if (
            (window.location.hostname.includes('yuanbao.tencent.com') ||
                window.location.hostname.includes('aistudio.google.com')) &&
            !eventsInitialized
        ) {
            initPasteEvent();
            initDropEvent();
            eventsInitialized = true;
            return true;
        }
        return false;
    }

    function initPasteEvent() {
        document.addEventListener('paste', handlePaste, true);
    }

    function initDropEvent() {
        document.addEventListener('drop', handleDrop, true);
    }

    function processFile(file) {
        const originalName = file.name;
        if (UNSUPPORTED_EXT.some(ext => originalName.toLowerCase().endsWith(ext))) {
            return new File([file], `${originalName}.txt`, {type: 'text/plain'});
        }
        return file;
    }

    function handlePaste(e) {
        const items = e.clipboardData.items;
        const files = [];
        let shouldModify = false;

        for (let i = 0; i < items.length; i++) {
            const item = items[i];
            if (item.kind === 'file') {
                const file = item.getAsFile();
                const processedFile = processFile(file);
                files.push(processedFile);
                if (processedFile !== file) shouldModify = true;
            }
        }

        if (shouldModify) {
            e.preventDefault();
            const newData = new DataTransfer();
            files.forEach(f => newData.items.add(f));

            const target = document.activeElement.closest('input, [contenteditable]') || document.activeElement;
            if (target instanceof HTMLInputElement) {
                target.files = newData.files;
            } else {
                const pasteEvent = new ClipboardEvent('paste', {
                    clipboardData: newData,
                    bubbles: true,
                    cancelable: true
                });
                target.dispatchEvent(pasteEvent);
            }
        }
    }

    function handleDrop(e) {
        // 检测脚本生成标记
        if (e.dataTransfer.types.includes('application/x-script-processed')) return;

        const items = e.dataTransfer.items;
        if (!items.length) return;

        const files = [];
        let shouldModify = false;

        for (let i = 0; i < items.length; i++) {
            const item = items[i];
            if (item.kind === 'file') {
                const file = item.getAsFile();
                const processedFile = processFile(file);
                files.push(processedFile);
                if (processedFile !== file) shouldModify = true;
            }
        }

        if (shouldModify) {
            e.preventDefault();
            e.stopPropagation();

            const newData = new DataTransfer();
            files.forEach(f => newData.items.add(f));
            newData.setData('application/x-script-processed', 'true'); // 添加标记

            // 创建完整拖放事件序列
            ['dragenter', 'dragover', 'drop'].forEach(eventName => {
                const event = new DragEvent(eventName, {
                    bubbles: true,
                    cancelable: true,
                    dataTransfer: newData
                });

                // 强制设置dataTransfer属性
                Object.defineProperty(event, 'dataTransfer', {
                    value: newData,
                    enumerable: true
                });

                e.target.dispatchEvent(event);
            });

            // 特殊处理文件输入
            if (e.target.tagName === 'INPUT' && e.target.type === 'file') {
                e.target.files = newData.files;
            }
        }
    }

    // 初始检测
    checkCozeCondition();

    // 动态监听(仅扣子需要)
    const observer = new MutationObserver(() => {
        if (!eventsInitialized) checkCozeCondition();
    });
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

})();