//[create_at: 2026-03-18 20:45:00] //[router: /m/myck] //[method: get] //[method: post] //[title: qlck] //[author: authook] //[class: 工具类] //[price: 0] //[disable: false] //[version: 2.3] //[service: authook] //[description: 青龙CK同步API:将CK同步到autMan已对接的青龙面板。] //==========================参数配置数据=============================== //[param: {"required":true,"key":"otto.vhook_qlck_token","bool":false,"placeholder":"鉴权token","name":"接口鉴权Token","desc":"鉴权token,自定义鉴权token(防止恶意调用)"}] //[param: {"required":false,"key":"otto.vhook_ql_default","bool":false,"placeholder":"青龙容器全称","name":"默认青龙容器名","desc":"未指定容器时,默认同步到此名称的青龙容器(全称匹配)"}] /** * 核心逻辑: * 1. 参考 消息推送群1.js 的解析风格。 * 2. 支持 GET/POST 参数混合读取。 * 3. 探测回复使用 JSON 对象以防网页无法渲染。 */ const method = getMethod() const params = getRouterParams() || {} var j = { "ok": true, "status": "ok", "retcode": 0, "msg": "success" } // 1. 数据解析 let access_token = params.access_token || params.token || "" let ck = params.ck || params.cookie || "" let env_name = params.env_name || "" let ql_name = params.ql_name || "" let mode = params.mode || "replace" let joiner = params.joiner || "\n" if (method == "post") { const data = getRouterData() if (data) { try { const body = JSON.parse(data) access_token = body.access_token || body.token || access_token ck = body.ck || body.cookie || ck env_name = body.env_name || env_name ql_name = body.ql_name || ql_name mode = body.mode || mode joiner = body.joiner || joiner match = body.match || "" // 新增:匹配关键字 } catch (e) { console.error("JSON解析失败: " + e.message) } } } // 如果 GET 方式下也有 match if (typeof match === "undefined") match = "" // --- 探测逻辑提示 (无参数访问) --- if (!access_token && !ck && !env_name) { j.msg = "接口已启用" j.version = "2.3" sender.reply(j) // 退出 } else { // 2. 鉴权 const configured_token = get("vhook_qlck_token") if (configured_token && configured_token !== access_token) { sender.reply({ "ok": false, "status": "fail", "retcode": -1, "msg": "token错误" }) } else if (!ck || !env_name) { sender.reply({ "ok": false, "status": "fail", "retcode": -2, "msg": "ck 或 env_name 不能为空" }) } else { // 3. 执行同步逻辑 try { main_sync(ck, env_name, ql_name, mode, joiner) } catch (e) { sender.reply({ "ok": false, "status": "error", "msg": "执行中出现异常: " + e.message }) } } } function main_sync(ck, env_name, ql_name, mode, joiner) { // 读取容器 let ql_configs = [] const ql_ids = bucketKeys("qls") if (ql_ids) { for (let id of ql_ids) { let val = bucketGet("qls", id) if (val) { try { let conf = JSON.parse(val) ql_configs.push(conf) } catch (e) { } } } } if (ql_configs.length === 0) { sender.reply({ "ok": false, "retcode": -3, "msg": "未在面板[青龙管理]中添加容器" }) return } // 确定容器列表 let target_ql_name = ql_name || get("vhook_ql_default") || "" let target_qls = [] if (target_ql_name) { target_qls = ql_configs.filter(ql => ql.name === target_ql_name) } else { target_qls = [ql_configs[0]] } if (target_qls.length === 0) { sender.reply({ "ok": false, "retcode": -4, "msg": "未找到名为 [" + target_ql_name + "] 的容器" }) return } let results = [] for (let target_ql of target_qls) { let ql_res = { container: target_ql.name, ok: false, msg: "" } let host = target_ql.host.replace(/\/+$/, "") // 分步执行 let loginUrl = host + "/open/auth/token?client_id=" + target_ql.client_id + "&client_secret=" + target_ql.client_secret let loginResp = request({ url: loginUrl, method: "get", dataType: "json" }) if (loginResp && loginResp.code == 200 && loginResp.data && loginResp.data.token) { let ql_token = loginResp.data.token let envsResp = request({ url: host + "/open/envs?searchValue=" + env_name, method: "get", headers: { "Authorization": "Bearer " + ql_token }, dataType: "json" }) let existing = null if (envsResp && envsResp.code == 200 && Array.isArray(envsResp.data)) { existing = envsResp.data.find(e => e.name === env_name) } if (existing && mode !== "add") { let final_ck = ck let envId = existing.id || existing._id if (mode === "append") { // 追加/精准聚合模式 if (match) { // 如果提供了匹配键,执行“局部替换” let items = existing.value.split(joiner) let found = false items = items.map(item => { if (item.indexOf(match) > -1) { found = true return ck // 用新 CK 替换该子项 } return item }) if (!found) items.push(ck) // 如果没找到匹配项,仍执行追加 final_ck = items.join(joiner) } else { // 原有的普通去重追加逻辑 if (existing.value.indexOf(ck) === -1) { final_ck = existing.value + joiner + ck } else { ql_res.ok = true; ql_res.msg = "CK已存在,跳过"; results.push(ql_res); continue } } } let updateResp = request({ url: host + "/open/envs", method: "put", headers: { "Authorization": "Bearer " + ql_token, "Content-Type": "application/json" }, body: { id: envId, name: env_name, value: final_ck, remarks: existing.remarks || "" }, dataType: "json" }) if (updateResp && updateResp.code == 200) { ql_res.ok = true; ql_res.msg = "更新成功" } else { ql_res.msg = "更新失败: " + JSON.stringify(updateResp) } } else { let createResp = request({ url: host + "/open/envs", method: "post", headers: { "Authorization": "Bearer " + ql_token, "Content-Type": "application/json" }, body: [{ name: env_name, value: ck, remarks: "qlck同步" }], dataType: "json" }) if (createResp && createResp.code == 200) { ql_res.ok = true; ql_res.msg = "新建成功" } else { ql_res.msg = "新建失败: " + JSON.stringify(createResp) } } } else { ql_res.msg = "登录失败: " + JSON.stringify(loginResp) } results.push(ql_res) } sender.reply({ "ok": results.every(r => r.ok), "results": results }) }