// ==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
// ==/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);
}
}
}
})();