剪贴板图片上传lsky图床-Nodeseek

Upload clipboard images to a configurable image host, auto-fetch token if missing or expired

// ==UserScript==
// @name         剪贴板图片上传lsky图床-Nodeseek
// @namespace    http://tampermonkey.net/
// @version      1.6.4
// @description  Upload clipboard images to a configurable image host, auto-fetch token if missing or expired
// @author       You
// @match        *://*.nodeseek.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// @connect      *
// @license MIT
// ==/UserScript==

(function () {
    'use strict';

    let config = {
        baseUrl: GM_getValue('baseUrl', 'http://'),
        token: GM_getValue('token', ''),
        email: GM_getValue('email', ''),
        password: GM_getValue('password', ''),
        strategyId: GM_getValue('strategyId', 1)
    };

    function createSettingsPanel() {
        let panel = document.createElement('div');
        panel.id = 'gm-settings-panel';
        panel.innerHTML = `
            <div class="gm-panel">
                <h2>lsky 图床 配置</h2>
                <label>图床地址: <input id="gm-baseUrl" type="text" value="${config.baseUrl}"></label>
                <label>邮箱: <input id="gm-email" type="text" value="${config.email}"></label>
                <label>密码: <input id="gm-password" type="password" value="${config.password}"></label>
                <label>策略 ID: <input id="gm-strategyId" type="number" value="${config.strategyId}"></label>
                <button id="gm-save-settings">保存</button>
                <button id="gm-close-settings">关闭</button>
            </div>
        `;
        document.body.appendChild(panel);

        document.getElementById('gm-save-settings').addEventListener('click', () => {
            let baseUrl = document.getElementById('gm-baseUrl').value;

            // Check if baseUrl doesn't start with "http://" or "https://"
            if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {
                baseUrl = 'http://' + baseUrl; // Automatically add "http://"
            }

            // Save the baseUrl along with other values
            GM_setValue('baseUrl', baseUrl);
            GM_setValue('email', document.getElementById('gm-email').value);
            GM_setValue('password', document.getElementById('gm-password').value);
            GM_setValue('strategyId', Number(document.getElementById('gm-strategyId').value));

            // Update the config object
            config.baseUrl = GM_getValue('baseUrl');
            config.email = GM_getValue('email');
            config.password = GM_getValue('password');
            config.strategyId = GM_getValue('strategyId');

            panel.remove();
            showSuccessMessage("配置已保存!");
        });

        document.getElementById('gm-close-settings').addEventListener('click', () => {
            panel.remove();
        });

        GM_addStyle(`
            #gm-settings-panel {
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                background: white;
                padding: 20px;
                border-radius: 8px;
                box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
                z-index: 10000;
            }
            .gm-panel h2 { margin: 0 0 10px; font-size: 18px; }
            .gm-panel label { display: block; margin-bottom: 10px; }
            .gm-panel input { width: 100%; padding: 5px; margin-top: 5px; border: 1px solid #ddd; border-radius: 4px; }
            .gm-panel button { margin-right: 10px; padding: 5px 10px; cursor: pointer; }
        `);
    }

    GM_registerMenuCommand("⚙️ 配置 lsky 图床", createSettingsPanel);

    async function getToken() {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'POST',
                url: `${config.baseUrl}/api/v1/tokens`,
                headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
                data: JSON.stringify({ email: config.email, password: config.password }),
                onload: function (response) {
                    try {
                        let res = JSON.parse(response.responseText);
                        if (res.status && res.data?.token) {
                            GM_setValue('token', res.data.token);
                            config.token = res.data.token;
                            resolve(res.data.token);
                        } else {
                            reject(res.message || "获取 Token 失败");
                        }
                    } catch (e) {
                        reject("返回的不是有效的 JSON 响应:" + response.responseText);
                    }
                },
                onerror: () => reject("网络错误")
            });
        });
    }

    function showUploadModal() {
        let modal = document.createElement('div');
        modal.id = 'upload-modal';
        modal.innerHTML = `
            <div class="modal-content">
                <div class="loader"></div>
                <p>上传中,请稍等...</p>
            </div>
        `;
        document.body.appendChild(modal);
        GM_addStyle(`
          #upload-modal {
              position: fixed;
              top: 50%;
              left: 50%;
              transform: translate(-50%, -50%);
              background-color: rgba(0, 0, 0, 0.5);
              padding: 20px;
              border-radius: 8px;
              z-index: 9999;
              display: flex;
              justify-content: center;
              align-items: center;
          }
          .modal-content {
              background-color: white;
              padding: 20px;
              border-radius: 8px;
              text-align: center;
          }
          .loader {
              border: 4px solid #f3f3f3;
              border-top: 4px solid #3498db;
              border-radius: 50%;
              width: 50px;
              height: 50px;
              animation: spin 1s linear infinite;
              margin: auto;
          }
          @keyframes spin {
              0% { transform: rotate(0deg); }
              100% { transform: rotate(360deg); }
          }
      `);

      setTimeout(() => {
            let modal = document.getElementById('upload-modal');
            if (modal) {
                modal.remove();
            }
        }, 10000);
    }

    function hideUploadModal() {
        let modal = document.getElementById('upload-modal');
        if (modal) {
            modal.remove();
        }
    }

    function showSuccessMessage(message) {
        let successModal = document.createElement('div');
        successModal.id = 'success-modal';
        successModal.innerHTML = `
            <div class="success-modal-content">
                <p>${message}</p>
            </div>
        `;
        document.body.appendChild(successModal);

        GM_addStyle(`
            #success-modal {
                position: fixed;
                top: 20px;
                left: 50%;
                transform: translateX(-50%);
                background-color: rgba(0, 128, 0, 0.8);
                padding: 10px 20px;
                border-radius: 8px;
                color: white;
                z-index: 10000;
                box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
                font-size: 16px;
            }
            #success-modal .success-modal-content {
                text-align: center;
            }
        `);

        setTimeout(() => {
            let modal = document.getElementById('success-modal');
            if (modal) {
                modal.remove();
            }
        }, 3000);
    }

    function showFailureMessage(message) {
        let failureModal = document.createElement('div');
        failureModal.id = 'failure-modal';
        failureModal.innerHTML = `
            <div class="failure-modal-content">
                <p>${message}</p>
            </div>
        `;
        document.body.appendChild(failureModal);

        GM_addStyle(`
            #failure-modal {
                position: fixed;
                top: 20px;
                left: 50%;
                transform: translateX(-50%);
                background-color: rgba(255, 0, 0, 0.8);
                padding: 10px 20px;
                border-radius: 8px;
                color: white;
                z-index: 10000;
                box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
                font-size: 16px;
            }
            #failure-modal .failure-modal-content {
                text-align: center;
            }
        `);

        setTimeout(() => {
            let modal = document.getElementById('failure-modal');
            if (modal) {
                modal.remove();
            }
        }, 3000);
    }

    document.addEventListener('paste', async (event) => {
        let items = (event.clipboardData || event.originalEvent.clipboardData).items;
        for (let item of items) {
            if (item.type.indexOf('image') !== -1) {
                // 弹出确认框,确认是否上传
                let confirmUpload = window.confirm("确认上传图片吗?");
                if (!confirmUpload) {
                    return; // 如果用户选择取消,退出上传流程
                }
                showUploadModal();
                let file = item.getAsFile();
                if (!config.token) {
                    await getToken().catch((error) => {
                        hideUploadModal();
                        console.error("获取 Token 失败");
                        showFailureMessage("获取 Token 失败");
                        return; // Early exit if token can't be fetched
                    });
                }
                // Proceed with image upload if the token is valid
                uploadImage(file).then(insertText)
                    .catch((error) => {
                        console.error(error);
                        showFailureMessage("上传失败");
                    })
                    .finally(() => {
                        hideUploadModal();  // Ensure the upload modal is hidden when upload finishes or fails
                    });
            }
        }
    });

    async function uploadImage(file) {
        return new Promise((resolve, reject) => {
            let formData = new FormData();
            formData.append('file', file);
            GM_xmlhttpRequest({
                method: 'POST',
                url: `${config.baseUrl}/api/v1/upload`,
                headers: { 'Authorization': `Bearer ${config.token}` },
                data: formData,
                onload: function (response) {
                    try {
                        let res = JSON.parse(response.responseText);
                        if (res.status && res.data?.links?.markdown) {
                            resolve(res.data.links.markdown);
                            showSuccessMessage("上传成功!");
                        } else {
                            reject(res.message || "上传失败");
                        }
                    } catch (e) {
                        reject("返回的不是有效的 JSON 响应:" + response.responseText);
                    }
                },
                onerror: () => reject("网络错误")
            });
        });
    }

    function insertText(text) {
        let activeElement = document.activeElement;
        if (activeElement && (activeElement.tagName === 'TEXTAREA' || activeElement.tagName === 'INPUT')) {
            let start = activeElement.selectionStart;
            let end = activeElement.selectionEnd;
            activeElement.value = activeElement.value.substring(0, start) + text + activeElement.value.substring(end);
            activeElement.selectionStart = activeElement.selectionEnd = start + text.length;
        } else if (activeElement?.isContentEditable) {
            document.execCommand('insertText', false, text);
        }
    }

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址