Skip to content

Commit b3e1aff

Browse files
JS: 切换账号解决循环跳出问题 (#1211)
* Update README.md * Update main.js 解决循环无法跳出 * Update README.md 增加更新记录 * Update README.md * Update manifest.json --------- Co-authored-by: 起个名字好难 <[email protected]>
1 parent 5eb10ad commit b3e1aff

File tree

3 files changed

+101
-85
lines changed

3 files changed

+101
-85
lines changed

repo/js/切换账号(OCR)版本/README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@
3131
---
3232
# 脚本信息
3333
@name 原神自动化登录脚本
34-
@version 1.1
34+
@version 1.2
3535
@description 原神自动登录工具(仅供学习交流,请勿商业用途)
3636
@author 彩虹QQ人
3737
@match 原神版本:≥5.5;BGI版本:≥0.44.6
38+
39+
# 更新记录
40+
2025年6月26日 version 1.1 整合代码
41+
42+
2025年6月27日 version 1.2 解决循环无法跳出的问题

repo/js/切换账号(OCR)版本/main.js

Lines changed: 94 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -39,61 +39,66 @@ const login_verification = {
3939
name: "verification.png"
4040
};
4141

42-
async function matchImgAndClick(obj, desc,timeout = 8000) {
42+
async function clickCenter(x, y, width, height) {
43+
let centerX = Math.round(x + width / 2);
44+
let centerY = Math.round(y + height / 2);
45+
await click(centerX, centerY);
46+
await sleep(500); // 确保点击后有足够的时间等待
47+
return { success: true, x: centerX, y: centerY };
48+
}
49+
50+
async function matchImgAndClick(obj, desc, timeout = 8000) {
4351
const start = Date.now();
44-
let x = 1; // 识别次数计数
45-
while (Date.now() - start < timeout) {
46-
try {
47-
await sleep(500); // 短暂延迟,避免过快循环
52+
let retryCount = 0; // 识别次数计数
53+
let status = false; // 用于记录是否匹配成功
54+
try {
55+
while (Date.now() - start < timeout && !status) {
4856
let result = captureGameRegion().Find(obj.template);
4957
await sleep(500); // 短暂延迟,避免过快循环
5058
if (result.isExist()) {
51-
let centerX = Math.round(result.x + result.width / 2);
52-
let centerY = Math.round(result.y + result.height / 2);
53-
result.click();
54-
log.info(`成功识别并点击 ${desc}| 耗时: ${Date.now() - start}ms`);
55-
return { success: true, x: centerX, y: centerY };
59+
let clickResult = await clickCenter(result.x, result.y, result.width, result.height);
60+
log.info(`【IMG】成功识别并点击 ${desc}| 耗时: ${Date.now() - start}ms`);
61+
status = true; // 设置匹配成功状态
62+
return {success: true, x: clickResult.x, y: clickResult.y};
5663
}
57-
} catch (error) {
58-
log.error(`识别图像时发生异常: ${error.message}`);
64+
await sleep(200); // 短暂延迟,避免过快循环
65+
log.info(`【IMG】第${retryCount++}次识别并点击 ${desc} 失败 | 耗时: ${Date.now() - start}ms`);
5966
}
60-
log.info(`第${x++}次识别并点击 ${desc} 失败 | 耗时: ${Date.now() - start}ms`);
67+
} catch (error) {
68+
log.error(`【IMG】${script_name}等待超时,请人工介入。===待切换账号:${settings.username}===超时原因:未找到目标 [${desc}] | 文件:${obj.name}`);
69+
//如果有配置通知……
70+
notification.error(`【IMG】${script_name}等待超时,请人工介入。===待切换账号:${settings.username}===超时原因:未找到目标 [${desc}] | 文件:${obj.name}`);
71+
throw new Error(`【IMG】识别图像时发生异常: ${error.message}`);
6172
}
62-
log.warn(`${script_name}等待超时,请人工介入。===待切换账号:${settings.username}===超时原因:未找到目标 [${desc}] | 文件:${obj.name}`);
63-
//这里配置通知方法
64-
notification.error(`${script_name}等待超时,请人工介入。===待切换账号:${settings.username}===超时原因:未找到目标 [${desc}] | 文件:${obj.name}`);
65-
return { success: false };
73+
return {success: false};
6674
}
6775
async function recognizeTextAndClick(targetText, ocrRegion, timeout = 8000) {
68-
let startTime = Date.now();
76+
let start = Date.now();
6977
let retryCount = 0; // 重试计数
70-
while (Date.now() - startTime < timeout) {
71-
try {
72-
// 尝试 OCR 识别
73-
let resList = captureGameRegion().findMulti(ocrRegion); // 指定识别区域
74-
// 遍历识别结果,检查是否找到目标文本
75-
for (let res of resList) {
76-
if (res.text.includes(targetText)) {
77-
// 如果找到目标文本,计算并点击文字的中心坐标
78-
let centerX = Math.round(res.x + res.width / 2);
79-
let centerY = Math.round(res.y + res.height / 2);
80-
await click(centerX, centerY);
81-
await sleep(500); // 确保点击后有足够的时间等待
82-
return { success: true, x: centerX, y: centerY };
78+
let status = false; // 用于记录是否匹配成功
79+
try {
80+
while (Date.now() - start < timeout && !status) {
81+
let resultList = captureGameRegion().findMulti(ocrRegion);
82+
await sleep(500); // 短暂延迟,避免过快循环
83+
for (let result of resultList) {
84+
if (result.text.includes(targetText)) {
85+
let clickResult = await clickCenter(result.x, result.y, result.width, result.height);
86+
log.info(`【OCR】成功识别并点击 ${targetText}| 耗时: ${Date.now() - start}ms`);
87+
status = true; // 设置匹配成功状态
88+
return {success: true, x: clickResult.x, y: clickResult.y};
8389
}
8490
}
85-
} catch (error) {
86-
retryCount++; // 增加重试计数
87-
log.warn(`页面标志识别失败,正在进行第 ${retryCount} 次重试...`);
91+
// await sleep(200); // 短暂延迟,避免过快循环
92+
log.info(`【OCR】${targetText}失败,正在进行第 ${retryCount++} 次重试...`);
8893
}
89-
await sleep(1000); // 短暂延迟,避免过快循环
94+
}catch (error) {
95+
log.warn(`【OCR】经过多次尝试,仍然无法识别文字: ”${targetText}“,尝试点击默认中心位置`);
96+
await clickCenter(result.x, result.y, result.width, result.height);
97+
//如果有配置通知……
98+
notification.error(`【OCR】识别文字: “${targetText}”,发生异常`);
99+
throw new Error(`【OCR】识别文字时发生异常: ${error.message}`);
90100
}
91-
log.warn(`经过多次尝试,仍然无法识别文字: ${targetText},尝试点击默认中心位置`);
92-
let centerX = Math.round(ocrRegion.x + ocrRegion.width / 2);
93-
let centerY = Math.round(ocrRegion.y + ocrRegion.height / 2);
94-
await click(centerX, centerY);
95-
await sleep(1000);
96-
return { success: false };
101+
return {success: false };
97102
}
98103
/**
99104
* main流程开始
@@ -110,50 +115,56 @@ async function recognizeTextAndClick(targetText, ocrRegion, timeout = 8000) {
110115

111116
await keyPress("VK_ESCAPE");
112117
await sleep(500);
113-
114-
await matchImgAndClick(pm_out,"左下角退出门");
115-
await matchImgAndClick(out_to_login,"退出至登陆页面");
116-
//这一步根据 电脑配置和当前网络情况不同休眠时间不同,建议实际运行之后,如果有日志 : 第x次 识别失败,就适当增加休眠时间
117-
await sleep(9000);
118-
await matchImgAndClick(login_out_account,"登录页的右下角退出按钮");
119-
await matchImgAndClick(out_account,"退出当前账号");
120-
await matchImgAndClick(login_other_account,"登录其他账号");
121-
await sleep(1000);
122-
await matchImgAndClick(input_phone_or_email,"填写邮箱/手机号");
123-
await inputText(settings.username);
124-
await sleep(1000);
125-
await matchImgAndClick(input_password,"填写密码");
126-
await inputText(settings.password);
127-
await sleep(1000);
128-
//按下回车登录账号,弹出用户协议对话框
129-
await keyPress("VK_RETURN");
130-
//点击回车后,等待特瓦特大门加载
131-
await matchImgAndClick(agree,"同意用户协议");
132-
//如果当天上下线次数过于频繁
133-
for(let i = 1;i<=2;i++){
134-
let verify = captureGameRegion().Find(login_verification.template);
135-
//等待1s避免循环速度过快
118+
try {
119+
await matchImgAndClick(pm_out,"左下角退出门");
120+
await matchImgAndClick(out_to_login,"退出至登陆页面");
121+
//这一步根据 电脑配置和当前网络情况不同休眠时间不同,建议实际运行之后,如果有日志 : 第x次 识别失败,就适当增加休眠时间
122+
await sleep(9000);
123+
await matchImgAndClick(login_out_account,"登录页的右下角退出按钮");
124+
await matchImgAndClick(out_account,"退出当前账号");
125+
await matchImgAndClick(login_other_account,"登录其他账号");
136126
await sleep(1000);
137-
if (verify.isExist()) {
138-
//这里可配置通知方法
139-
notification.error(`${script_name}触发人机验证,请手动登录。===待切换UID:${settings.UID}`);
140-
log.error(`${script_name}触发人机验证,请手动登录。===待切换UID:${settings.UID}`);
127+
await matchImgAndClick(input_phone_or_email,"填写邮箱/手机号");
128+
await inputText(settings.username);
129+
await sleep(1000);
130+
await matchImgAndClick(input_password,"填写密码");
131+
await inputText(settings.password);
132+
await sleep(1000);
133+
//按下回车登录账号,弹出用户协议对话框
134+
await keyPress("VK_RETURN");
135+
//点击回车后,等待特瓦特大门加载
136+
await matchImgAndClick(agree,"同意用户协议");
137+
//如果当天上下线次数过于频繁
138+
for(let i = 1;i<=2;i++){
139+
let verify = captureGameRegion().Find(login_verification.template);
140+
//等待1s避免循环速度过快
141+
await sleep(1000);
142+
if (verify.isExist()) {
143+
//这里可配置通知方法
144+
notification.error(`${script_name}触发人机验证,请手动登录。===待切换UID:${settings.UID}`);
145+
log.error(`${script_name}触发人机验证,请手动登录。===待切换UID:${settings.UID}`);
146+
}
141147
}
142-
}
143-
/**
144-
* 根据不同网络环境和电脑配置,此操作可能会将领取月卡操作取代,但是不影响使用
145-
* 如果发现卡在这一步,请适当延长sleep时间
146-
*/
147-
await sleep(8000);
148-
await recognizeTextAndClick("点击进入", RecognitionObject.Ocr(862, 966, 206, 104), 960, 540, 5000);
149-
await sleep(12000);
148+
/**
149+
* 根据不同网络环境和电脑配置,此操作可能会将领取月卡操作取代,但是不影响使用
150+
* 如果发现卡在这一步,请适当延长sleep时间
151+
*/
152+
await sleep(8000);
153+
await recognizeTextAndClick("点击进入", RecognitionObject.Ocr(862, 966, 206, 104), 960, 540, 5000);
154+
await sleep(12000);
150155

151-
//可能登录账号的时候出现月卡提醒,则先点击一次月卡。
152-
await genshin.blessingOfTheWelkinMoon();
153-
await sleep(1000);
154-
await genshin.blessingOfTheWelkinMoon();
155-
await sleep(1000);
156-
//如果配置了通知
157-
notification.send("账号切换成功【UID:" + settings.UID + "】");
156+
//可能登录账号的时候出现月卡提醒,则先点击一次月卡。
157+
await genshin.blessingOfTheWelkinMoon();
158+
await sleep(1000);
159+
await genshin.blessingOfTheWelkinMoon();
160+
await sleep(1000);
161+
// 如果配置了通知
162+
notification.send("【UID:" + settings.UID + "】切换成功");
163+
}catch (error) {
164+
log.error(`${script_name}脚本执行过程中发生错误:${error.message}`);
165+
//如果发生错误,则发送通知
166+
notification.error(`${script_name}脚本执行过程中发生错误:${error.message}`);
167+
throw new Error(`${script_name}脚本执行过程中发生错误:${error.message}`);
168+
}
158169

159170
})();

repo/js/切换账号(OCR)版本/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 1,
33
"name": "切换账号(OCR)版本",
4-
"version": "1.1",
4+
"version": "1.2",
55
"description": "使用OCR实现:从主页面退出登录实现切换选定账号。脚本维护/脚本问题请联系作者。\n免责申明:所有的账号密码均保存在本地,请使用者妥善保管账号密码,请勿外泄账号密码。若因使用此脚本导致的账号泄露、封禁问题与脚本作者无关。",
66
"authors": [
77
{

0 commit comments

Comments
 (0)