// ==UserScript==
// @name 京东CK获取并提交青龙_优化版
// @namespace jdck
// @version 1.0.0
// @description 在前台显示美化面板,一键推送CK并提交到青龙,支持一键登出,带日志记录;支持单独复制CK
// @author 超级帅气 + ChatGPT
// @match https://home.m.jd.com/myJd/newhome.action*
// @match https://m.jd.com/*
// @grant GM_cookie
// @grant GM_addValueChangeListener
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_notification
// @grant GM_xmlhttpRequest
// @grant GM_setClipboard
// @grant GM_log
// @connect jd.com
// ==/UserScript==
/* ==UserConfig==
青龙配置:
url:
title: 青龙面板地址
description: '例如: http://127.0.0.1:5700'
clientId:
title: clientId
description: 系统设置->应用设置->client id
clientSecret:
title: clientSecret
description: 系统设置->应用设置->client secret
==/UserConfig== */
(function () {
// ----------- 前台UI部分 -----------
const panel = document.createElement('div');
panel.id = "jdck-panel";
panel.innerHTML = `
京东CK工具
`;
document.body.appendChild(panel);
const style = document.createElement('style');
style.innerHTML = `
#jdck-panel {
position: fixed;
top: 180px;
left: 10px;
background: #fff;
border: 1px solid #ddd;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
padding: 12px;
z-index: 99999;
font-family: "Segoe UI", Arial, sans-serif;
text-align: center;
}
#jdck-panel button {
display: block;
width: 120px;
margin: 6px auto;
padding: 8px 0;
font-size: 13px;
border: none;
border-radius: 8px;
cursor: pointer;
transition: 0.2s;
}
#push-ck { background: #4CAF50; color: #fff; }
#push-ck:hover { background: #45a049; }
#copy-ck { background: #2196F3; color: #fff; }
#copy-ck:hover { background: #0b7dda; }
#logout { background: #f44336; color: #fff; }
#logout:hover { background: #da190b; }
`;
document.head.appendChild(style);
// 前台按钮绑定
panel.addEventListener('click', e => {
switch (e.target.id) {
case 'push-ck':
GM_log("📢 用户点击了『推送CK』按钮");
GM_setValue('push-ck', null);
GM_setValue('push-ck', 'request');
break;
case 'copy-ck':
GM_log("📢 用户点击了『复制CK』按钮");
GM_setValue('push-ck', null);
GM_setValue('copy-ck', 'request');
break;
case 'logout':
GM_log("📢 用户点击了『一键登出』按钮");
GM_setValue('push-ck', null);
GM_setValue('logout', 'true');
setTimeout(() => {
location.href = 'https://m.jd.com/';
}, 1000);
break;
}
});
// ----------- 后台逻辑部分 -----------
if (!window.GM_getCookieStore) {
window.GM_getCookieStore = (_, cb) => cb(0, undefined);
}
function getCk(tabid) {
return new Promise((resolve, reject) => {
GM_getCookieStore(tabid, (storeId, err) => {
if (err) return reject(err);
GM_cookie('list', { domain: '.jd.com', name: "pt_key", storeId }, (item) => {
if (!item.length) return reject("未找到 pt_key");
let jdCookie = "pt_key=" + item[0].value;
GM_cookie('list', { domain: '.jd.com', name: "pt_pin", storeId }, (item2) => {
if (!item2.length) return reject("未找到 pt_pin");
jdCookie += ";pt_pin=" + item2[0].value + ";";
GM_log("✅ 成功获取CK:" + jdCookie);
resolve({ jdCookie, pt_pin: decodeURI(item2[0].value) });
});
});
});
});
}
function ajax(method, url, token, data) {
return new Promise((resolve, reject) => {
let headers = {};
if (method !== 'get') headers['Content-Type'] = 'application/json';
if (token) headers['Authorization'] = 'Bearer ' + token;
GM_xmlhttpRequest({
url,
method,
data: data ? JSON.stringify(data) : null,
headers,
responseType: "json",
onload: resp => {
if (resp.status === 200) {
GM_log("🌐 请求成功: " + url);
resolve(resp.response);
} else {
GM_log("❌ 请求失败: " + url + " 状态码: " + resp.status);
reject(resp.response?.message || "请求失败");
}
},
onerror: err => {
GM_log("⚠️ 网络错误: " + url + " 错误: " + JSON.stringify(err));
reject(err);
}
});
});
}
async function updateToken() {
let url = GM_getValue('青龙配置.url');
let clientId = GM_getValue('青龙配置.clientId');
let clientSecret = GM_getValue('青龙配置.clientSecret');
GM_log("🔑 正在更新青龙 token...");
let resp = await ajax('get', `${url}/open/auth/token?client_id=${clientId}&client_secret=${clientSecret}`);
GM_setValue('ql.token', resp.data.token);
GM_setValue('ql.expiration', resp.data.expiration);
GM_log("✅ 获取到青龙 token:" + resp.data.token);
return resp.data.token;
}
async function setQlCk(ck, pt_pin) {
GM_log("📤 正在提交CK到青龙...");
let url = GM_getValue('青龙配置.url');
if (!url) throw "未配置青龙地址";
let ckName = 'JD_COOKIE';
let token = GM_getValue('ql.token');
let expiration = GM_getValue('ql.expiration');
if (!token || expiration < Date.now() / 1000 - 1000) token = await updateToken();
try {
let envs = await ajax('get', `${url}/open/envs?searchValue=${ckName}`, token);
let found = envs.data.find(e => e.remarks?.startsWith(pt_pin));
if (found) {
GM_log("🔄 更新已有环境变量 _id=" + found._id);
await ajax('put', `${url}/open/envs`, token, { name: ckName, value: ck, remarks: pt_pin + ' by ScriptCat', _id: found._id });
await ajax('put', `${url}/open/envs/enable`, token, [found._id]);
} else {
GM_log("➕ 新建环境变量 JD_COOKIE");
await ajax('post', `${url}/open/envs`, token, [{ name: ckName, value: ck, remarks: pt_pin + ' by ScriptCat' }]);
}
GM_log("✅ CK 提交青龙成功");
} catch (e) {
GM_log("❌ CK 提交青龙失败:" + JSON.stringify(e));
throw e;
}
}
// 监听登出
GM_addValueChangeListener('logout', (_, __, val, ___, tabid) => {
if (!val) return;
GM_log("🧹 正在删除京东登录Cookie...");
GM_getCookieStore(tabid, (storeId, err) => {
if (err) return;
const cookiesToDelete = ["pt_key", "pt_pin", "pt_token", "pwdt_id", "s_key", "s_pin", "sfstoken", "sid", "thor1", "wq_skey"];
cookiesToDelete.forEach(name => {
GM_cookie('delete', { url: 'https://home.m.jd.com/', name, storeId });
});
GM_log("✅ Cookie 清理完成");
});
});
// 监听推送CK(直接推送,无弹窗)
GM_addValueChangeListener('push-ck', (_, __, val, ___, tabid) => {
if (!val) return;
getCk(tabid).then(({ jdCookie, pt_pin }) => {
setQlCk(jdCookie, pt_pin).then(() => {
GM_notification({ title: "京东CK工具", text: "CK 已推送到青龙 ✅" });
}).catch(e => {
GM_notification({ title: "京东CK工具", text: "推送失败: " + e });
});
}).catch(() => {
GM_log("❌ 获取CK失败,用户未登录");
GM_notification({ title: "京东CK工具", text: "未登录,无法获取CK ❌" });
});
});
// 监听复制CK
GM_addValueChangeListener('copy-ck', (_, __, val, ___, tabid) => {
if (!val) return;
getCk(tabid).then(({ jdCookie }) => {
GM_setClipboard(jdCookie);
GM_log("📋 CK 已复制到剪贴板");
GM_notification({ title: "京东CK工具", text: "CK 已复制到剪贴板 ✅" });
}).catch(() => {
GM_log("❌ 获取CK失败,用户未登录");
GM_notification({ title: "京东CK工具", text: "未登录,无法获取CK ❌" });
});
});
})();