From 75c36147d43987b45a58b1fab308864446f1a424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E7=AB=AF=E5=AE=A2?= <107686912+Kirito520Asuna@users.noreply.github.com> Date: Sun, 21 Dec 2025 16:23:16 +0800 Subject: [PATCH] =?UTF-8?q?[SwitchAccountMultipleMode]=E5=BC=95=E5=85=A5?= =?UTF-8?q?=20UID=20=E6=A0=A1=E9=AA=8C=E9=80=BB=E8=BE=91=20(#2529)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(SwitchAccountMultipleMode): 新增账号UID校验功能 - 引入 UID 校验逻辑,避免重复切换相同账号 - 添加 OCR 识别 UID 功能,自动读取界面 UID 信息 - 实现主界面判断与自动返回主界面功能 - 增加设置项 uid,用于配置目标账号 UID - 更新版本号至 1.5,并新增贡献者信息 - 引入 utils/uid.js 工具文件支持 UID 相关操作 * fix(utils): 修复uid工具函数中的字符串处理和异常捕获语法 - 修正saveOnlyNumber函数中空值处理逻辑 - 标准化check函数中的catch语法格式 - 提高代码健壮性和可读性 * fix(ocr): 添加OCR识别UID异常处理 - 在OCR识别UID时增加try-catch异常捕获 - 当识别失败时记录警告日志并返回默认值0 - 避免因OCR识别异常导致程序崩溃 - 优化日志记录格式,使用模板字符串替换原有拼接方式 * fix(ocr): 添加OCR识别UID异常处理 - 在OCR识别UID时增加try-catch异常捕获 - 当识别失败时记录警告日志并返回默认值0 - 避免因OCR识别异常导致程序崩溃 - 优化日志记录格式,使用模板字符串替换原有拼接方式 * fix(uid): 添加UID设置异常处理 - 在compareUid函数中增加try-catch块处理saveOnlyNumber可能的异常 - 当UID未设置或解析失败时避免程序中断 - 添加注释说明异常情况的日志记录逻辑 - 保持原有OCR识别和比较逻辑不变 * refactor(uid): 优化 UID 检查逻辑并修复语法错误 - 修复 catch 语句前缺少空格的语法问题 - 重构 check 函数,仅在启用 UID 设置时执行检查逻辑 - 提取并封装 UID 检查结果,提高代码可读性 - 避免在未设置 UID 时进行不必要的界面跳转操作 * chore(manifest): 更新版本号至1.6 - 将扩展版本从1.5更新到1.6 - 保持其他配置项不变 --- repo/js/SwitchAccountMultipleMode/main.js | 6 + .../SwitchAccountMultipleMode/manifest.json | 6 +- .../SwitchAccountMultipleMode/settings.json | 6 + .../js/SwitchAccountMultipleMode/utils/uid.js | 141 ++++++++++++++++++ 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 repo/js/SwitchAccountMultipleMode/utils/uid.js diff --git a/repo/js/SwitchAccountMultipleMode/main.js b/repo/js/SwitchAccountMultipleMode/main.js index 018036021..8377f3a22 100644 --- a/repo/js/SwitchAccountMultipleMode/main.js +++ b/repo/js/SwitchAccountMultipleMode/main.js @@ -41,6 +41,8 @@ const login_verification = { name: "verification.png" }; +eval(file.readTextSync('utils/uid.js')) + async function clickCenter(x, y, width, height) { let centerX = Math.round(x + width / 2); let centerY = Math.round(y + height / 2); @@ -423,6 +425,10 @@ async function recognizeTextAndClick(targetText, ocrRegion, timeout = 8000) { // ====================================================== // Main flow + if (await uidUtil.check()) { + log.info("当前UID与设置UID相同,无需切换账号。"); + return + } if (settings.Modes == "下拉列表") { await DropDownMode(); } else if (settings.Modes == "账号+密码") { diff --git a/repo/js/SwitchAccountMultipleMode/manifest.json b/repo/js/SwitchAccountMultipleMode/manifest.json index f23bacebe..265405f96 100644 --- a/repo/js/SwitchAccountMultipleMode/manifest.json +++ b/repo/js/SwitchAccountMultipleMode/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "切换账号多模式", - "version": "1.5", + "version": "1.6", "bgi_version": "0.53.0", "description": "多种模式的切换账号,有下拉列表、填写账号密码,OCR操作或键鼠操作\n免责申明:所有的账号密码均保存在本地,请使用者妥善保管账号密码,请勿外泄账号密码。若因使用此脚本导致的账号泄露、封禁问题与脚本作者无关。", "tags": [ @@ -25,6 +25,10 @@ "name": "彩虹QQ人", "email": "846224811@qq.com", "links": "https://github.com/KRdingsan" + }, + { + "name": "云端客", + "links": "https://github.com/Kirito520Asuna" } ], "settings_ui": "settings.json", diff --git a/repo/js/SwitchAccountMultipleMode/settings.json b/repo/js/SwitchAccountMultipleMode/settings.json index fe9cfde7e..6405c4a5c 100644 --- a/repo/js/SwitchAccountMultipleMode/settings.json +++ b/repo/js/SwitchAccountMultipleMode/settings.json @@ -19,5 +19,11 @@ "name": "password", "type": "input-text", "label": "密码(只保存在本地,请妥善保管)\n切换模式为下拉列表时无需填写" + }, + { + "name": "uid", + "type": "input-text", + "label": "账号UID(可不填)\n切换账号前识别一致将不执行切换动作", + "default": "" } ] \ No newline at end of file diff --git a/repo/js/SwitchAccountMultipleMode/utils/uid.js b/repo/js/SwitchAccountMultipleMode/utils/uid.js new file mode 100644 index 000000000..0edd0fbcd --- /dev/null +++ b/repo/js/SwitchAccountMultipleMode/utils/uid.js @@ -0,0 +1,141 @@ +const commonPath = 'Assets/RecognitionObject/' +const commonMap = new Map([ + ['main_ui', { + path: `${commonPath}`, + name: 'paimon_menu', + type: '.png', + }], +]) +const genshinJson = { + width: 1920,//genshin.width, + height: 1080,//genshin.height, +} + +/** + * 根据键值获取JSON路径 + * @param {string} key - 要查找的键值 + * @returns {any} 返回与键值对应的JSON路径值 + */ +function getJsonPath(key) { + return commonMap.get(key); // 通过commonMap的get方法获取指定键对应的值 +} + +function saveOnlyNumber(str) { + str = str ? str : ''; + // 使用正则表达式匹配字符串中的所有数字 + // \d+ 匹配一个或多个数字 + // .join('') 将匹配到的数字数组连接成一个字符串 + // parseInt 将连接后的字符串转换为整数 + return parseInt(str.match(/\d+/g).join('')); +} + +async function ocrUID() { + let uid_json = { + x: 1683, + y: 1051, + width: 234, + height: 28, + } + let recognitionObjectOcr = RecognitionObject.Ocr(uid_json.x, uid_json.y, uid_json.width, uid_json.height); + let region3 = captureGameRegion() + let res = region3.find(recognitionObjectOcr); + log.info(`[OCR识别UID]识别结果: ${res.text}, 原始坐标: x=${res.x}, y=${res.y},width:${res.width},height:${res.height}`); + //只保留数字 + let uid + try { + uid = saveOnlyNumber(res.text) + } catch (e) { + log.warn(`UID未设置`) + uid = 0 + } + log.info(`[OCR识别UID]识别结果: {uid}`, uid); + region3.dispose() + return uid +} + +// 判断是否在主界面的函数 +const isInMainUI = () => { + // let name = '主界面' + let main_ui = getJsonPath('main_ui'); + // 定义识别对象 + let paimonMenuRo = RecognitionObject.TemplateMatch( + file.ReadImageMatSync(`${main_ui.path}${main_ui.name}${main_ui.type}`), + 0, + 0, + genshinJson.width / 3.0, + genshinJson.width / 5.0 + ); + let captureRegion = captureGameRegion(); + let res = captureRegion.find(paimonMenuRo); + captureRegion.Dispose() + return !res.isEmpty(); +}; + +async function toMainUi() { + let ms = 1000 + let index = 1 + await sleep(ms); + while (!isInMainUI()) { + await sleep(ms); + await genshin.returnMainUi(); // 如果未启用,则返回游戏主界面 + await sleep(ms); + if (index > 3) { + throw new Error(`多次尝试返回主界面失败`); + } + index += 1 + } + +} + +async function compareUid(UID = settings.uid) { + let uid = await ocrUID() + let setUid = 0 + try { + setUid = saveOnlyNumber(UID) + } catch (e) { + // log.warn(`UID未设置`) + } + let compare = uid === setUid + if (compare) { + log.info(`[OCR识别UID]识别结果: {uid} 与设置UID相同`, uid); + } + return compare +} + +async function checkUid() { + let reJson = { + inMainUI: false, + isUid: false + } + if (isInMainUI()) { + reJson.isUid = await compareUid() + } + return reJson +} + +async function check() { + let check = false + if (settings.uid) { + try { + await toMainUi(); + } catch (e) { + log.warn("多次尝试返回主界面失败") + } + let checkJson = await checkUid() + if ((!checkJson.inMainUI) && (!checkJson.isUid)) { + //尝试直接识别 + checkJson.isUid = await compareUid() + } + check = checkJson.isUid + } + return check +} + +this.uidUtil = { + toMainUi, + isInMainUI, + checkUid, + ocrUID, + check, + compareUid, +} \ No newline at end of file