// ==UserScript== // @name 剪贴板图片上传lsky图床-Nodeseek // @namespace http://tampermonkey.net/ // @version 1.5 // @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 // @connect * // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 配置项 let config = { baseUrl: GM_getValue('baseUrl', ''), token: GM_getValue('token', ''), email: GM_getValue('email', ''), password: GM_getValue('password', ''), strategyId: GM_getValue('strategyId', 1) // 默认策略ID }; // 注册菜单以更改设置 GM_registerMenuCommand("设置lsky图床地址", function() { let newUrl = prompt("请输入图床地址", config.baseUrl); if (newUrl) { GM_setValue('baseUrl', newUrl); config.baseUrl = newUrl; } }); GM_registerMenuCommand("设置账户", function() { let newEmail = prompt("请输入邮箱", config.email); if (newEmail) { GM_setValue('email', newEmail); config.email = newEmail; } }); GM_registerMenuCommand("设置密码", function() { let newPassword = prompt("请输入密码", config.password); if (newPassword) { GM_setValue('password', newPassword); config.password = newPassword; } }); GM_registerMenuCommand("设置策略ID", function() { let newStrategyId = prompt("请输入新的策略ID", config.strategyId); if (newStrategyId) { GM_setValue('strategyId', newStrategyId); config.strategyId = newStrategyId; } }); async function getToken() { return new Promise((resolve, reject) => { console.log("尝试获取 Token..."); GM_xmlhttpRequest({ method: 'POST', url: `${config.baseUrl} kens`, headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, data: JSON.stringify({ email: config.email, password: config.password }), onload: function(response) { let res; try { res = JSON.parse(response.responseText); } catch (e) { console.error("解析 Token 响应失败", e); return reject("解析 Token 失败"); } if (res.status && res.data && res.data.token) { GM_setValue('token', res.data.token); config.token = res.data.token; console.log("Token 获取成功"); resolve(res.data.token); } else { console.error("获取 Token 失败: ", res.message); reject(res.message || "未知错误"); } }, onerror: function(err) { console.error("获取 Token 请求失败", err); reject("网络错误"); } }); }); } 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 file = item.getAsFile(); console.log("检测到剪贴板图片,开始上传..."); // 确保有 token if (!config.token) { console.log("Token 缺失,尝试获取..."); try { await getToken(); } catch (e) { console.error("无法获取 Token: ", e); return; } } let url = await uploadImage(file); if (url) { insertText(url); } } } }); async function uploadImage(file) { return new Promise(async (resolve, reject) => { let reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function () { let base64Data = reader.result.split(',')[1]; // 获取 Base64 数据 let boundary = "----WebKitFormBoundary" + Math.random().toString(36).substr(2); let body = `--${boundary}\r\n` + `Content-Disposition: form-data; name="file"; filename="image.png"\r\n` + `Content-Type: image/png\r\n\r\n` + `${base64Data}\r\n` + `--${boundary}--`; function doUpload() { GM_xmlhttpRequest({ method: 'POST', url: `${config.baseUrl}/api/v1/upload`, headers: { 'Authorization': `Bearer ${config.token}`, 'Content-Type': `multipart/form-data; boundary=${boundary}`, 'Accept': 'application/json' }, data: body, onload: async function(response) { let res; try { res = JSON.parse(response.responseText); } catch (e) { console.error("解析上传响应失败", e); return reject("解析失败"); } if (res.status && res.data && res.data.links && res.data.links.markdown) { console.log("图片上传成功: ", res.data.links.url); resolve(res.data.links.markdown); } else if (res.code === 401) { // Token 失效 console.warn("Token 失效,尝试重新获取..."); try { await getToken(); console.log("Token 更新成功,重新上传..."); doUpload(); // 重新尝试上传 } catch (err) { console.error("重新获取 Token 失败: ", err); reject("Token 失效,无法上传"); } } else { console.error("图片上传失败: ", res.message); reject(res.message || "上传失败"); } }, onerror: function(err) { console.error("上传请求失败", err); reject("网络错误"); } }); } doUpload(); }; }); } function insertText(text) { let activeElement = document.activeElement; if (activeElement) { if (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) { let range = document.getSelection().getRangeAt(0); let textNode = document.createTextNode(text); range.deleteContents(); range.insertNode(textNode); range.setStartAfter(textNode); range.setEndAfter(textNode); let selection = document.getSelection(); selection.removeAllRanges(); selection.addRange(range); } } } })();