diff --git a/js/qdreader_sign_autman.js b/js/qdreader_sign_autman.js index 217c125..7f16874 100644 --- a/js/qdreader_sign_autman.js +++ b/js/qdreader_sign_autman.js @@ -4,7 +4,7 @@ //[author: Hermes] //[service: BOSS] //[class: 工具类] -//[version: 2.4.1] +//[version: 2.4.2] //[platform: web,qq,wx,tg,tb,fs,we] //[public: false] //[price: 0] @@ -124,6 +124,23 @@ function currentUserId() { function currentOwnerId() { return currentUserId() } +function currentIsAdmin() { + try { if (typeof isAdmin === "function" && isAdmin()) return true } catch (e) {} + try { if (typeof sender !== "undefined" && sender && typeof sender.isAdmin === "function" && sender.isAdmin()) return true } catch (e2) {} + try { if (typeof Sender !== "undefined" && Sender && typeof Sender.isAdmin === "function" && Sender.isAdmin()) return true } catch (e3) {} + return false +} +function looksLikeLegacyFallbackOwner(owner) { + owner = trim(owner) + if (!owner) return false + if (owner === "__qdreader_default_owner__") return true + if (/^[A-Za-z0-9._-]{1,32}$/.test(owner) && !/^\d{5,}$/.test(owner)) return true + return false +} +function canRepairBinding(oldOwner, me) { + if (!oldOwner || oldOwner === me) return true + return currentIsAdmin() && looksLikeLegacyFallbackOwner(oldOwner) +} function currentUserDebug() { var parts = [] var fns = ["GetUserID", "GetChatID", "GetImType", "ImType", "GetUsername"] @@ -242,7 +259,7 @@ function contentText() { } function usage() { return [ - "启点读书签到插件 v2.4.1", + "启点读书签到插件 v2.4.2", "【一级菜单】", "账号管理:启点账号", "执行查询:启点查询", @@ -658,6 +675,10 @@ function handleSaveCookie(arg, store, bind) { oldOwner = "" lines.push("检测到 uid: " + uid + " 只有旧绑定没有CK,已自动清理残留绑定") } + if (store[uid] && oldOwner && oldOwner !== me && canRepairBinding(oldOwner, me)) { + lines.push("检测到 uid: " + uid + " 旧绑定来自历史兜底标识 " + maskUid(oldOwner) + ",已修复为当前用户") + oldOwner = "" + } if (store[uid] && oldOwner && me && oldOwner !== me) { lines.push("无权更新 uid: " + uid + "(该账号已绑定其他用户)") continue diff --git a/plugins/qdreader/qdreader_sign_autman.js b/plugins/qdreader/qdreader_sign_autman.js index 217c125..7f16874 100644 --- a/plugins/qdreader/qdreader_sign_autman.js +++ b/plugins/qdreader/qdreader_sign_autman.js @@ -4,7 +4,7 @@ //[author: Hermes] //[service: BOSS] //[class: 工具类] -//[version: 2.4.1] +//[version: 2.4.2] //[platform: web,qq,wx,tg,tb,fs,we] //[public: false] //[price: 0] @@ -124,6 +124,23 @@ function currentUserId() { function currentOwnerId() { return currentUserId() } +function currentIsAdmin() { + try { if (typeof isAdmin === "function" && isAdmin()) return true } catch (e) {} + try { if (typeof sender !== "undefined" && sender && typeof sender.isAdmin === "function" && sender.isAdmin()) return true } catch (e2) {} + try { if (typeof Sender !== "undefined" && Sender && typeof Sender.isAdmin === "function" && Sender.isAdmin()) return true } catch (e3) {} + return false +} +function looksLikeLegacyFallbackOwner(owner) { + owner = trim(owner) + if (!owner) return false + if (owner === "__qdreader_default_owner__") return true + if (/^[A-Za-z0-9._-]{1,32}$/.test(owner) && !/^\d{5,}$/.test(owner)) return true + return false +} +function canRepairBinding(oldOwner, me) { + if (!oldOwner || oldOwner === me) return true + return currentIsAdmin() && looksLikeLegacyFallbackOwner(oldOwner) +} function currentUserDebug() { var parts = [] var fns = ["GetUserID", "GetChatID", "GetImType", "ImType", "GetUsername"] @@ -242,7 +259,7 @@ function contentText() { } function usage() { return [ - "启点读书签到插件 v2.4.1", + "启点读书签到插件 v2.4.2", "【一级菜单】", "账号管理:启点账号", "执行查询:启点查询", @@ -658,6 +675,10 @@ function handleSaveCookie(arg, store, bind) { oldOwner = "" lines.push("检测到 uid: " + uid + " 只有旧绑定没有CK,已自动清理残留绑定") } + if (store[uid] && oldOwner && oldOwner !== me && canRepairBinding(oldOwner, me)) { + lines.push("检测到 uid: " + uid + " 旧绑定来自历史兜底标识 " + maskUid(oldOwner) + ",已修复为当前用户") + oldOwner = "" + } if (store[uid] && oldOwner && me && oldOwner !== me) { lines.push("无权更新 uid: " + uid + "(该账号已绑定其他用户)") continue diff --git a/tests/qdreader_plugin.test.mjs b/tests/qdreader_plugin.test.mjs index d7121eb..ebba8c3 100644 --- a/tests/qdreader_plugin.test.mjs +++ b/tests/qdreader_plugin.test.mjs @@ -5,7 +5,7 @@ import vm from 'node:vm'; const pluginPath = new URL('../plugins/qdreader/qdreader_sign_autman.js', import.meta.url).pathname; const code = fs.readFileSync(pluginPath, 'utf8'); -function runPlugin({ content = '', store = {}, bucketStore = {}, requests = [], userId = 'user-a', listens = [], senderOverrides = {}, globals = {} } = {}) { +function runPlugin({ content = '', store = {}, bucketStore = {}, requests = [], userId = 'user-a', listens = [], senderOverrides = {}, globals = {}, admin = true } = {}) { const replies = []; const calls = []; let requestIndex = 0; @@ -14,7 +14,7 @@ function runPlugin({ content = '', store = {}, bucketStore = {}, requests = [], reply: (msg) => replies.push(String(msg)), getMessage: () => content, getContent: () => content, - isAdmin: () => true, + isAdmin: () => admin, getUserID: () => userId, listen: () => (listenIndex < listens.length ? listens[listenIndex++] : 'q'), }; @@ -178,15 +178,38 @@ test('quick submit can re-add cookie when old binding remains but cookie was man assert.equal(JSON.parse(r.store.qdreader_user_bind_json)['12345'], 'user-a'); }); -test('quick submit still rejects overwrite when cookie and another owner binding both exist', () => { +test('quick submit still rejects overwrite when cookie and real another owner binding both exist', () => { const store = { qdreader_cookie_json: JSON.stringify({ '12345': cookie }), - qdreader_user_bind_json: JSON.stringify({ '12345': 'old-user' }), + qdreader_user_bind_json: JSON.stringify({ '12345': '987654321' }), }; const r = runPlugin({ content: '启点ck ' + cookie.replace('qdh=qdh', 'qdh=newqdh'), store, userId: 'user-a', listens: ['n'] }); assert.match(r.replies.join('\n'), /无权更新 uid: 12345/); assert.equal(JSON.parse(r.store.qdreader_cookie_json)['12345'], cookie); - assert.equal(JSON.parse(r.store.qdreader_user_bind_json)['12345'], 'old-user'); + assert.equal(JSON.parse(r.store.qdreader_user_bind_json)['12345'], '987654321'); +}); + +test('quick submit can repair legacy fallback owner when admin submits existing cookie', () => { + const store = { + qdreader_cookie_json: JSON.stringify({ '12345': cookie }), + qdreader_user_bind_json: JSON.stringify({ '12345': 'chickliu' }), + }; + const r = runPlugin({ content: '启点ck ' + cookie.replace('qdh=qdh', 'qdh=newqdh'), store, userId: 'real-user', admin: true, listens: ['n'] }); + assert.match(r.replies.join('\n'), /旧绑定来自历史兜底标识/); + assert.match(r.replies.join('\n'), /CK更新成功/); + assert.equal(JSON.parse(r.store.qdreader_user_bind_json)['12345'], 'real-user'); + assert.match(JSON.parse(r.store.qdreader_cookie_json)['12345'], /qdh=newqdh/); +}); + +test('non-admin quick submit still rejects existing cookie bound to legacy fallback owner', () => { + const store = { + qdreader_cookie_json: JSON.stringify({ '12345': cookie }), + qdreader_user_bind_json: JSON.stringify({ '12345': 'chickliu' }), + }; + const r = runPlugin({ content: '启点ck ' + cookie.replace('qdh=qdh', 'qdh=newqdh'), store, userId: 'real-user', admin: false, listens: ['n'] }); + assert.match(r.replies.join('\n'), /无权更新 uid: 12345/); + assert.equal(JSON.parse(r.store.qdreader_user_bind_json)['12345'], 'chickliu'); + assert.equal(JSON.parse(r.store.qdreader_cookie_json)['12345'], cookie); }); test('quick submit rejects save when Autman JS has no user identity', () => { @@ -422,11 +445,11 @@ test('unbound global cookies are not visible or usable by normal users', () => { test('user cannot overwrite another user bound cookie', () => { const store = { qdreader_cookie_json: JSON.stringify({ '12345': cookie }), - qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }), + qdreader_user_bind_json: JSON.stringify({ '12345': '987654321' }), }; const newCookie = cookie.replace('sessionyw=s', 'sessionyw=changed'); const r = runPlugin({ content: '启点ck ' + newCookie, store, userId: 'user-b' }); assert.match(r.replies.join('\n'), /无权更新 uid: 12345/); assert.equal(JSON.parse(r.store.qdreader_cookie_json)['12345'], cookie); - assert.equal(JSON.parse(r.store.qdreader_user_bind_json)['12345'], 'user-a'); + assert.equal(JSON.parse(r.store.qdreader_user_bind_json)['12345'], '987654321'); });