From b3e1affaa64a3b50928d586c4e9f544c3e60df50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=A9=E8=99=B9QQ=E4=BA=BA?= <90805948+KRdingsan@users.noreply.github.com> Date: Fri, 27 Jun 2025 15:40:32 +0800 Subject: [PATCH] =?UTF-8?q?JS:=20=20=E5=88=87=E6=8D=A2=E8=B4=A6=E5=8F=B7?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=BE=AA=E7=8E=AF=E8=B7=B3=E5=87=BA=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(#1211)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update README.md * Update main.js 解决循环无法跳出 * Update README.md 增加更新记录 * Update README.md * Update manifest.json --------- Co-authored-by: 起个名字好难 <25520958+MisakaAldrich@users.noreply.github.com> --- repo/js/切换账号(OCR)版本/README.md | 7 +- repo/js/切换账号(OCR)版本/main.js | 177 +++++++++++++----------- repo/js/切换账号(OCR)版本/manifest.json | 2 +- 3 files changed, 101 insertions(+), 85 deletions(-) diff --git a/repo/js/切换账号(OCR)版本/README.md b/repo/js/切换账号(OCR)版本/README.md index 8c2cbb4a..f0d48ab5 100644 --- a/repo/js/切换账号(OCR)版本/README.md +++ b/repo/js/切换账号(OCR)版本/README.md @@ -31,7 +31,12 @@ --- # 脚本信息 @name 原神自动化登录脚本 - @version 1.1 + @version 1.2 @description 原神自动登录工具(仅供学习交流,请勿商业用途) @author 彩虹QQ人 @match 原神版本:≥5.5;BGI版本:≥0.44.6 + + # 更新记录 +2025年6月26日 version 1.1 整合代码 + +2025年6月27日 version 1.2 解决循环无法跳出的问题 diff --git a/repo/js/切换账号(OCR)版本/main.js b/repo/js/切换账号(OCR)版本/main.js index 6f76e98b..99804ee9 100644 --- a/repo/js/切换账号(OCR)版本/main.js +++ b/repo/js/切换账号(OCR)版本/main.js @@ -39,61 +39,66 @@ const login_verification = { name: "verification.png" }; -async function matchImgAndClick(obj, desc,timeout = 8000) { +async function clickCenter(x, y, width, height) { + let centerX = Math.round(x + width / 2); + let centerY = Math.round(y + height / 2); + await click(centerX, centerY); + await sleep(500); // 确保点击后有足够的时间等待 + return { success: true, x: centerX, y: centerY }; +} + +async function matchImgAndClick(obj, desc, timeout = 8000) { const start = Date.now(); - let x = 1; // 识别次数计数 - while (Date.now() - start < timeout) { - try { - await sleep(500); // 短暂延迟,避免过快循环 + let retryCount = 0; // 识别次数计数 + let status = false; // 用于记录是否匹配成功 + try { + while (Date.now() - start < timeout && !status) { let result = captureGameRegion().Find(obj.template); await sleep(500); // 短暂延迟,避免过快循环 if (result.isExist()) { - let centerX = Math.round(result.x + result.width / 2); - let centerY = Math.round(result.y + result.height / 2); - result.click(); - log.info(`成功识别并点击 ${desc}| 耗时: ${Date.now() - start}ms`); - return { success: true, x: centerX, y: centerY }; + let clickResult = await clickCenter(result.x, result.y, result.width, result.height); + log.info(`【IMG】成功识别并点击 ${desc}| 耗时: ${Date.now() - start}ms`); + status = true; // 设置匹配成功状态 + return {success: true, x: clickResult.x, y: clickResult.y}; } - } catch (error) { - log.error(`识别图像时发生异常: ${error.message}`); + await sleep(200); // 短暂延迟,避免过快循环 + log.info(`【IMG】第${retryCount++}次识别并点击 ${desc} 失败 | 耗时: ${Date.now() - start}ms`); } - log.info(`第${x++}次识别并点击 ${desc} 失败 | 耗时: ${Date.now() - start}ms`); + } catch (error) { + log.error(`【IMG】${script_name}等待超时,请人工介入。===待切换账号:${settings.username}===超时原因:未找到目标 [${desc}] | 文件:${obj.name}`); + //如果有配置通知…… + notification.error(`【IMG】${script_name}等待超时,请人工介入。===待切换账号:${settings.username}===超时原因:未找到目标 [${desc}] | 文件:${obj.name}`); + throw new Error(`【IMG】识别图像时发生异常: ${error.message}`); } - log.warn(`${script_name}等待超时,请人工介入。===待切换账号:${settings.username}===超时原因:未找到目标 [${desc}] | 文件:${obj.name}`); - //这里配置通知方法 - notification.error(`${script_name}等待超时,请人工介入。===待切换账号:${settings.username}===超时原因:未找到目标 [${desc}] | 文件:${obj.name}`); - return { success: false }; + return {success: false}; } async function recognizeTextAndClick(targetText, ocrRegion, timeout = 8000) { - let startTime = Date.now(); + let start = Date.now(); let retryCount = 0; // 重试计数 - while (Date.now() - startTime < timeout) { - try { - // 尝试 OCR 识别 - let resList = captureGameRegion().findMulti(ocrRegion); // 指定识别区域 - // 遍历识别结果,检查是否找到目标文本 - for (let res of resList) { - if (res.text.includes(targetText)) { - // 如果找到目标文本,计算并点击文字的中心坐标 - let centerX = Math.round(res.x + res.width / 2); - let centerY = Math.round(res.y + res.height / 2); - await click(centerX, centerY); - await sleep(500); // 确保点击后有足够的时间等待 - return { success: true, x: centerX, y: centerY }; + let status = false; // 用于记录是否匹配成功 + try { + while (Date.now() - start < timeout && !status) { + let resultList = captureGameRegion().findMulti(ocrRegion); + await sleep(500); // 短暂延迟,避免过快循环 + for (let result of resultList) { + if (result.text.includes(targetText)) { + let clickResult = await clickCenter(result.x, result.y, result.width, result.height); + log.info(`【OCR】成功识别并点击 ${targetText}| 耗时: ${Date.now() - start}ms`); + status = true; // 设置匹配成功状态 + return {success: true, x: clickResult.x, y: clickResult.y}; } } - } catch (error) { - retryCount++; // 增加重试计数 - log.warn(`页面标志识别失败,正在进行第 ${retryCount} 次重试...`); + // await sleep(200); // 短暂延迟,避免过快循环 + log.info(`【OCR】${targetText}失败,正在进行第 ${retryCount++} 次重试...`); } - await sleep(1000); // 短暂延迟,避免过快循环 + }catch (error) { + log.warn(`【OCR】经过多次尝试,仍然无法识别文字: ”${targetText}“,尝试点击默认中心位置`); + await clickCenter(result.x, result.y, result.width, result.height); + //如果有配置通知…… + notification.error(`【OCR】识别文字: “${targetText}”,发生异常`); + throw new Error(`【OCR】识别文字时发生异常: ${error.message}`); } - log.warn(`经过多次尝试,仍然无法识别文字: ${targetText},尝试点击默认中心位置`); - let centerX = Math.round(ocrRegion.x + ocrRegion.width / 2); - let centerY = Math.round(ocrRegion.y + ocrRegion.height / 2); - await click(centerX, centerY); - await sleep(1000); - return { success: false }; + return {success: false }; } /** * main流程开始 @@ -110,50 +115,56 @@ async function recognizeTextAndClick(targetText, ocrRegion, timeout = 8000) { await keyPress("VK_ESCAPE"); await sleep(500); - - await matchImgAndClick(pm_out,"左下角退出门"); - await matchImgAndClick(out_to_login,"退出至登陆页面"); - //这一步根据 电脑配置和当前网络情况不同休眠时间不同,建议实际运行之后,如果有日志 : 第x次 识别失败,就适当增加休眠时间 - await sleep(9000); - await matchImgAndClick(login_out_account,"登录页的右下角退出按钮"); - await matchImgAndClick(out_account,"退出当前账号"); - await matchImgAndClick(login_other_account,"登录其他账号"); - await sleep(1000); - await matchImgAndClick(input_phone_or_email,"填写邮箱/手机号"); - await inputText(settings.username); - await sleep(1000); - await matchImgAndClick(input_password,"填写密码"); - await inputText(settings.password); - await sleep(1000); - //按下回车登录账号,弹出用户协议对话框 - await keyPress("VK_RETURN"); - //点击回车后,等待特瓦特大门加载 - await matchImgAndClick(agree,"同意用户协议"); - //如果当天上下线次数过于频繁 - for(let i = 1;i<=2;i++){ - let verify = captureGameRegion().Find(login_verification.template); - //等待1s避免循环速度过快 + try { + await matchImgAndClick(pm_out,"左下角退出门"); + await matchImgAndClick(out_to_login,"退出至登陆页面"); + //这一步根据 电脑配置和当前网络情况不同休眠时间不同,建议实际运行之后,如果有日志 : 第x次 识别失败,就适当增加休眠时间 + await sleep(9000); + await matchImgAndClick(login_out_account,"登录页的右下角退出按钮"); + await matchImgAndClick(out_account,"退出当前账号"); + await matchImgAndClick(login_other_account,"登录其他账号"); await sleep(1000); - if (verify.isExist()) { - //这里可配置通知方法 - notification.error(`${script_name}触发人机验证,请手动登录。===待切换UID:${settings.UID}`); - log.error(`${script_name}触发人机验证,请手动登录。===待切换UID:${settings.UID}`); + await matchImgAndClick(input_phone_or_email,"填写邮箱/手机号"); + await inputText(settings.username); + await sleep(1000); + await matchImgAndClick(input_password,"填写密码"); + await inputText(settings.password); + await sleep(1000); + //按下回车登录账号,弹出用户协议对话框 + await keyPress("VK_RETURN"); + //点击回车后,等待特瓦特大门加载 + await matchImgAndClick(agree,"同意用户协议"); + //如果当天上下线次数过于频繁 + for(let i = 1;i<=2;i++){ + let verify = captureGameRegion().Find(login_verification.template); + //等待1s避免循环速度过快 + await sleep(1000); + if (verify.isExist()) { + //这里可配置通知方法 + notification.error(`${script_name}触发人机验证,请手动登录。===待切换UID:${settings.UID}`); + log.error(`${script_name}触发人机验证,请手动登录。===待切换UID:${settings.UID}`); + } } - } - /** - * 根据不同网络环境和电脑配置,此操作可能会将领取月卡操作取代,但是不影响使用 - * 如果发现卡在这一步,请适当延长sleep时间 - */ - await sleep(8000); - await recognizeTextAndClick("点击进入", RecognitionObject.Ocr(862, 966, 206, 104), 960, 540, 5000); - await sleep(12000); + /** + * 根据不同网络环境和电脑配置,此操作可能会将领取月卡操作取代,但是不影响使用 + * 如果发现卡在这一步,请适当延长sleep时间 + */ + await sleep(8000); + await recognizeTextAndClick("点击进入", RecognitionObject.Ocr(862, 966, 206, 104), 960, 540, 5000); + await sleep(12000); - //可能登录账号的时候出现月卡提醒,则先点击一次月卡。 - await genshin.blessingOfTheWelkinMoon(); - await sleep(1000); - await genshin.blessingOfTheWelkinMoon(); - await sleep(1000); - //如果配置了通知 - notification.send("账号切换成功【UID:" + settings.UID + "】"); + //可能登录账号的时候出现月卡提醒,则先点击一次月卡。 + await genshin.blessingOfTheWelkinMoon(); + await sleep(1000); + await genshin.blessingOfTheWelkinMoon(); + await sleep(1000); + // 如果配置了通知 + notification.send("【UID:" + settings.UID + "】切换成功"); + }catch (error) { + log.error(`${script_name}脚本执行过程中发生错误:${error.message}`); + //如果发生错误,则发送通知 + notification.error(`${script_name}脚本执行过程中发生错误:${error.message}`); + throw new Error(`${script_name}脚本执行过程中发生错误:${error.message}`); + } })(); diff --git a/repo/js/切换账号(OCR)版本/manifest.json b/repo/js/切换账号(OCR)版本/manifest.json index cc841aba..919c7b3f 100644 --- a/repo/js/切换账号(OCR)版本/manifest.json +++ b/repo/js/切换账号(OCR)版本/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 1, "name": "切换账号(OCR)版本", - "version": "1.1", + "version": "1.2", "description": "使用OCR实现:从主页面退出登录实现切换选定账号。脚本维护/脚本问题请联系作者。\n免责申明:所有的账号密码均保存在本地,请使用者妥善保管账号密码,请勿外泄账号密码。若因使用此脚本导致的账号泄露、封禁问题与脚本作者无关。", "authors": [ {