fix: clear signup phone mismatch runtime state
This commit is contained in:
+86
-75
@@ -7307,6 +7307,72 @@ function isSignupPhonePasswordMismatchFailure(error) {
|
||||
return /SIGNUP_PHONE_PASSWORD_MISMATCH::/i.test(message);
|
||||
}
|
||||
|
||||
function getSignupPhonePasswordMismatchRestartPayload(preservedState = {}) {
|
||||
const preservedEmail = String(preservedState.email || '').trim();
|
||||
const preservedPassword = String(preservedState.password || '').trim();
|
||||
const accountIdentifierType = String(preservedState.accountIdentifierType || '').trim().toLowerCase();
|
||||
const activeSignupPhoneNumber = String(
|
||||
preservedState.signupPhoneNumber
|
||||
|| preservedState.signupPhoneActivation?.phoneNumber
|
||||
|| preservedState.signupPhoneCompletedActivation?.phoneNumber
|
||||
|| (accountIdentifierType === 'phone' ? preservedState.accountIdentifier : '')
|
||||
|| ''
|
||||
).trim();
|
||||
const shouldClearSignupPhoneRuntime = Boolean(
|
||||
activeSignupPhoneNumber
|
||||
|| preservedState.signupPhoneActivation
|
||||
|| preservedState.signupPhoneCompletedActivation
|
||||
|| preservedState.signupPhoneVerificationRequestedAt
|
||||
|| preservedState.signupPhoneVerificationPurpose
|
||||
|| accountIdentifierType === 'phone'
|
||||
);
|
||||
const restorePayload = {};
|
||||
if (preservedEmail) restorePayload.email = preservedEmail;
|
||||
if (preservedPassword) restorePayload.password = preservedPassword;
|
||||
if (shouldClearSignupPhoneRuntime) {
|
||||
restorePayload.signupPhoneNumber = '';
|
||||
restorePayload.signupPhoneActivation = null;
|
||||
restorePayload.signupPhoneCompletedActivation = null;
|
||||
restorePayload.signupPhoneVerificationRequestedAt = null;
|
||||
restorePayload.signupPhoneVerificationPurpose = '';
|
||||
if (accountIdentifierType === 'phone') {
|
||||
restorePayload.accountIdentifierType = null;
|
||||
restorePayload.accountIdentifier = '';
|
||||
}
|
||||
}
|
||||
return {
|
||||
activeSignupPhoneNumber,
|
||||
preservedEmail,
|
||||
restorePayload,
|
||||
shouldClearSignupPhoneRuntime,
|
||||
};
|
||||
}
|
||||
|
||||
async function restartSignupPhonePasswordMismatchAttemptFromStep(step, restartCount, error) {
|
||||
const preservedState = await getState();
|
||||
const {
|
||||
activeSignupPhoneNumber,
|
||||
preservedEmail,
|
||||
restorePayload,
|
||||
shouldClearSignupPhoneRuntime,
|
||||
} = getSignupPhonePasswordMismatchRestartPayload(preservedState);
|
||||
const emailSuffix = preservedEmail ? `当前邮箱:${preservedEmail};` : '';
|
||||
const phoneSuffix = activeSignupPhoneNumber ? `当前手机号:${activeSignupPhoneNumber};` : '';
|
||||
await addLog(
|
||||
`步骤 ${step}:检测到手机号/密码不匹配,准备丢弃当前注册手机号并回到步骤 1 重新开始(第 ${restartCount} 次重开)。${phoneSuffix}${emailSuffix}原因:${getErrorMessage(error)}`,
|
||||
'warn'
|
||||
);
|
||||
await invalidateDownstreamAfterStepRestart(1, {
|
||||
logLabel: `步骤 ${step} 检测到手机号/密码不匹配后准备回到步骤 1 重新获取手机号重试(第 ${restartCount} 次重开)`,
|
||||
});
|
||||
if (shouldClearSignupPhoneRuntime) {
|
||||
await addLog(`步骤 ${step}:已清空本轮注册手机号与接码订单,下一次重开将重新获取号码。`, 'warn');
|
||||
}
|
||||
if (Object.keys(restorePayload).length) {
|
||||
await setState(restorePayload);
|
||||
}
|
||||
}
|
||||
|
||||
function isSignupUserAlreadyExistsFailure(error) {
|
||||
if (typeof loggingStatus !== 'undefined' && loggingStatus?.isSignupUserAlreadyExistsFailure) {
|
||||
return loggingStatus.isSignupUserAlreadyExistsFailure(error);
|
||||
@@ -9984,42 +10050,7 @@ async function runAutoSequenceFromStep(startStep, context = {}) {
|
||||
}
|
||||
if (isSignupPhonePasswordMismatchFailure(err)) {
|
||||
step4RestartCount += 1;
|
||||
const preservedState = await getState();
|
||||
const preservedEmail = String(preservedState.email || '').trim();
|
||||
const preservedPassword = String(preservedState.password || '').trim();
|
||||
const activeSignupPhoneNumber = String(
|
||||
preservedState.signupPhoneNumber
|
||||
|| preservedState.signupPhoneActivation?.phoneNumber
|
||||
|| preservedState.signupPhoneCompletedActivation?.phoneNumber
|
||||
|| ''
|
||||
).trim();
|
||||
const emailSuffix = preservedEmail ? `当前邮箱:${preservedEmail};` : '';
|
||||
const phoneSuffix = activeSignupPhoneNumber ? `当前手机号:${activeSignupPhoneNumber};` : '';
|
||||
await addLog(
|
||||
`步骤 3:检测到手机号/密码不匹配,准备丢弃当前注册手机号并回到步骤 1 重新开始(第 ${step4RestartCount} 次重开)。${phoneSuffix}${emailSuffix}原因:${getErrorMessage(err)}`,
|
||||
'warn'
|
||||
);
|
||||
await invalidateDownstreamAfterStepRestart(1, {
|
||||
logLabel: `步骤 3 检测到手机号/密码不匹配后准备回到步骤 1 重新获取手机号重试(第 ${step4RestartCount} 次重开)`,
|
||||
});
|
||||
const restorePayload = {};
|
||||
if (preservedEmail) restorePayload.email = preservedEmail;
|
||||
if (preservedPassword) restorePayload.password = preservedPassword;
|
||||
if (preservedState.signupPhoneActivation) {
|
||||
restorePayload.signupPhoneNumber = '';
|
||||
restorePayload.signupPhoneActivation = null;
|
||||
restorePayload.signupPhoneCompletedActivation = null;
|
||||
restorePayload.signupPhoneVerificationRequestedAt = null;
|
||||
restorePayload.signupPhoneVerificationPurpose = '';
|
||||
if (String(preservedState.accountIdentifierType || '').trim().toLowerCase() === 'phone') {
|
||||
restorePayload.accountIdentifierType = null;
|
||||
restorePayload.accountIdentifier = '';
|
||||
}
|
||||
await addLog('步骤 3:已清空本轮注册手机号与接码订单,下一次重开将重新获取号码。', 'warn');
|
||||
}
|
||||
if (Object.keys(restorePayload).length) {
|
||||
await setState(restorePayload);
|
||||
}
|
||||
await restartSignupPhonePasswordMismatchAttemptFromStep(3, step4RestartCount, err);
|
||||
currentStartStep = 1;
|
||||
continueCurrentAttempt = true;
|
||||
restartFromStep1WithCurrentEmail = true;
|
||||
@@ -10090,46 +10121,26 @@ async function runAutoSequenceFromStep(startStep, context = {}) {
|
||||
throw err;
|
||||
}
|
||||
step4RestartCount += 1;
|
||||
const preservedState = await getState();
|
||||
const preservedEmail = String(preservedState.email || '').trim();
|
||||
const preservedPassword = String(preservedState.password || '').trim();
|
||||
const isSignupPhonePasswordMismatch = /SIGNUP_PHONE_PASSWORD_MISMATCH::/i.test(getErrorMessage(err));
|
||||
const activeSignupPhoneNumber = String(
|
||||
preservedState.signupPhoneNumber
|
||||
|| preservedState.signupPhoneActivation?.phoneNumber
|
||||
|| preservedState.signupPhoneCompletedActivation?.phoneNumber
|
||||
|| ''
|
||||
).trim();
|
||||
const emailSuffix = preservedEmail ? `当前邮箱:${preservedEmail};` : '';
|
||||
const phoneSuffix = activeSignupPhoneNumber ? `当前手机号:${activeSignupPhoneNumber};` : '';
|
||||
await addLog(
|
||||
isSignupPhonePasswordMismatch
|
||||
? `步骤 4:检测到手机号/密码不匹配,准备丢弃当前注册手机号并回到步骤 1 重新开始(第 ${step4RestartCount} 次重开)。${phoneSuffix}${emailSuffix}原因:${getErrorMessage(err)}`
|
||||
: `步骤 4:执行失败,准备沿用当前邮箱回到步骤 1 重新开始(第 ${step4RestartCount} 次重开)。${emailSuffix}原因:${getErrorMessage(err)}`,
|
||||
'warn'
|
||||
);
|
||||
await invalidateDownstreamAfterStepRestart(1, {
|
||||
logLabel: isSignupPhonePasswordMismatch
|
||||
? `步骤 4 检测到手机号/密码不匹配后准备回到步骤 1 重新获取手机号重试(第 ${step4RestartCount} 次重开)`
|
||||
: `步骤 4 报错后准备回到步骤 1 沿用当前邮箱重试(第 ${step4RestartCount} 次重开)`,
|
||||
});
|
||||
const restorePayload = {};
|
||||
if (preservedEmail) restorePayload.email = preservedEmail;
|
||||
if (preservedPassword) restorePayload.password = preservedPassword;
|
||||
if (isSignupPhonePasswordMismatch && preservedState.signupPhoneActivation) {
|
||||
restorePayload.signupPhoneNumber = '';
|
||||
restorePayload.signupPhoneActivation = null;
|
||||
restorePayload.signupPhoneCompletedActivation = null;
|
||||
restorePayload.signupPhoneVerificationRequestedAt = null;
|
||||
restorePayload.signupPhoneVerificationPurpose = '';
|
||||
if (String(preservedState.accountIdentifierType || '').trim().toLowerCase() === 'phone') {
|
||||
restorePayload.accountIdentifierType = null;
|
||||
restorePayload.accountIdentifier = '';
|
||||
if (isSignupPhonePasswordMismatchFailure(err)) {
|
||||
await restartSignupPhonePasswordMismatchAttemptFromStep(4, step4RestartCount, err);
|
||||
} else {
|
||||
const preservedState = await getState();
|
||||
const preservedEmail = String(preservedState.email || '').trim();
|
||||
const preservedPassword = String(preservedState.password || '').trim();
|
||||
const emailSuffix = preservedEmail ? `当前邮箱:${preservedEmail};` : '';
|
||||
await addLog(
|
||||
`步骤 4:执行失败,准备沿用当前邮箱回到步骤 1 重新开始(第 ${step4RestartCount} 次重开)。${emailSuffix}原因:${getErrorMessage(err)}`,
|
||||
'warn'
|
||||
);
|
||||
await invalidateDownstreamAfterStepRestart(1, {
|
||||
logLabel: `步骤 4 报错后准备回到步骤 1 沿用当前邮箱重试(第 ${step4RestartCount} 次重开)`,
|
||||
});
|
||||
const restorePayload = {};
|
||||
if (preservedEmail) restorePayload.email = preservedEmail;
|
||||
if (preservedPassword) restorePayload.password = preservedPassword;
|
||||
if (Object.keys(restorePayload).length) {
|
||||
await setState(restorePayload);
|
||||
}
|
||||
await addLog('步骤 4:已清空本轮注册手机号与接码订单,下一次重开将重新获取号码。', 'warn');
|
||||
}
|
||||
if (Object.keys(restorePayload).length) {
|
||||
await setState(restorePayload);
|
||||
}
|
||||
currentStartStep = 1;
|
||||
continueCurrentAttempt = true;
|
||||
|
||||
@@ -57,6 +57,8 @@ const bundle = [
|
||||
extractFunction('isAddPhoneAuthState'),
|
||||
extractFunction('isMail2925ThreadTerminatedError'),
|
||||
extractFunction('isSignupPhonePasswordMismatchFailure'),
|
||||
extractFunction('getSignupPhonePasswordMismatchRestartPayload'),
|
||||
extractFunction('restartSignupPhonePasswordMismatchAttemptFromStep'),
|
||||
extractFunction('isSignupUserAlreadyExistsFailure'),
|
||||
extractFunction('getPostStep6AutoRestartDecision'),
|
||||
extractFunction('runAutoSequenceFromStep'),
|
||||
@@ -621,7 +623,7 @@ return {
|
||||
assert.equal(events.logs.some(({ message }) => /已清空本轮注册手机号与接码订单/.test(message)), true);
|
||||
});
|
||||
|
||||
test('auto-run restarts from step 1 immediately when step 3 detects phone/password mismatch', async () => {
|
||||
test('auto-run clears manual signup phone state when step 3 detects phone/password mismatch', async () => {
|
||||
const api = new Function(`
|
||||
const AUTO_STEP_DELAYS = { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 0 };
|
||||
const LAST_STEP_ID = 10;
|
||||
@@ -644,14 +646,8 @@ let currentState = {
|
||||
accountIdentifierType: 'phone',
|
||||
accountIdentifier: '+56988841722',
|
||||
signupPhoneNumber: '+56988841722',
|
||||
signupPhoneActivation: {
|
||||
activationId: 'act-1',
|
||||
phoneNumber: '+56988841722',
|
||||
},
|
||||
signupPhoneCompletedActivation: {
|
||||
activationId: 'act-1',
|
||||
phoneNumber: '+56988841722',
|
||||
},
|
||||
signupPhoneActivation: null,
|
||||
signupPhoneCompletedActivation: null,
|
||||
stepStatuses: {
|
||||
1: 'pending',
|
||||
2: 'pending',
|
||||
|
||||
@@ -450,6 +450,10 @@ function getSignupPasswordDisplayedEmail() {
|
||||
return 'user@example.com';
|
||||
}
|
||||
|
||||
function getSignupPasswordFieldErrorText() {
|
||||
return '';
|
||||
}
|
||||
|
||||
function findOneTimeCodeLoginTrigger() {
|
||||
return oneTimeCodeButton;
|
||||
}
|
||||
@@ -474,6 +478,7 @@ return {
|
||||
|
||||
assert.equal(result.url, 'https://auth.openai.com/create-account/password');
|
||||
assert.equal(result.displayedEmail, 'user@example.com');
|
||||
assert.equal(result.passwordErrorText, '');
|
||||
assert.equal(result.hasVisiblePasswordInput, true);
|
||||
assert.equal(result.passwordInputCount, 1);
|
||||
assert.equal(result.visiblePasswordInputCount, 1);
|
||||
|
||||
@@ -352,6 +352,7 @@ IP 代理模块在同步、切换、Change、出口探测和自动运行成功
|
||||
7. 延迟提交真正触发前会再次检查 Stop 状态,避免用户已停止时页面仍继续自动提交
|
||||
8. 后台在真正确认 Step 3 完成前,会额外检查提交后是否切换页面;如果出现认证页 `Try again / 重试` 页面,或 `/email-verification` 上的 `405 / Route Error` 重试页,会先通过共享恢复逻辑最多自动点击 5 次 `重试` 尝试恢复,再继续后续链路
|
||||
9. Step 3 收尾阶段如果页面切换导致旧内容脚本失联,后台会把单次消息等待收口到当前收尾预算内,优先尽快重试重连;若最终仍未恢复,则输出中文的步骤级错误,而不是直接暴露底层英文通信超时
|
||||
10. 手机号注册时,如果 Step 3 收尾或 Step 4 准备验证码阶段在密码页检测到 `Incorrect phone number or password`,后台会把它视为当前注册手机号/密码不匹配:清空本轮 `signupPhoneNumber / signupPhoneActivation / signupPhoneCompletedActivation` 和手机号账号身份,回到 Step 1 重新获取号码并重开当前轮,避免继续在密码页重复点击
|
||||
|
||||
补充:
|
||||
|
||||
|
||||
+2
-2
@@ -93,7 +93,7 @@
|
||||
- `content/phone-auth.js`:认证页手机号验证脚本,负责识别 `add-phone / phone-verification` 页面、选择国家、填写手机号、提交短信验证码、触发重发短信,以及把“回到 add-phone / 进入 OAuth 同意页”的结果反馈给后台。
|
||||
- `content/plus-checkout.js`:ChatGPT Plus checkout 页面脚本,负责读取 `/api/auth/session` 创建 Plus checkout、选择 PayPal、填写账单姓名、触发 Google 地址推荐、校验结构化地址字段并点击订阅。
|
||||
- `content/qq-mail.js`:QQ 邮箱轮询脚本,负责网页邮箱验证码读取。
|
||||
- `content/signup-page.js`:注册、登录、授权主内容脚本,负责 OpenAI / ChatGPT 页面上的步骤执行;其中 Step 2 / 3 的延迟点击与延迟提交在真正触发前会先检查 Stop 状态,避免停止后页面继续自动点击;当前 Step 2 同时支持邮箱注册与手机号注册入口切换、手机号国家下拉框同步校验、手机号填写与提交;Step 7 / 8 登录链路会额外识别手机号输入页、手机号登录入口、`phone-verification` 与真实 `add-email` 页面,避免把手机验证码页或添加邮箱页误判成普通邮箱登录入口;Step 9 后置手机号验证完成后若偶发进入资料页,会复用 Step 5 的姓名生日填写逻辑再继续等待 OAuth 同意页。
|
||||
- `content/signup-page.js`:注册、登录、授权主内容脚本,负责 OpenAI / ChatGPT 页面上的步骤执行;其中 Step 2 / 3 的延迟点击与延迟提交在真正触发前会先检查 Stop 状态,避免停止后页面继续自动点击;当前 Step 2 同时支持邮箱注册与手机号注册入口切换、手机号国家下拉框同步校验、手机号填写与提交;Step 3 收尾会识别手机号注册密码页的 `Incorrect phone number or password` 并上报当前轮重开信号;Step 7 / 8 登录链路会额外识别手机号输入页、手机号登录入口、`phone-verification` 与真实 `add-email` 页面,避免把手机验证码页或添加邮箱页误判成普通邮箱登录入口;Step 9 后置手机号验证完成后若偶发进入资料页,会复用 Step 5 的姓名生日填写逻辑再继续等待 OAuth 同意页。
|
||||
- `content/sub2api-panel.js`:SUB2API 后台内容脚本,负责获取 OAuth 地址和提交 localhost 回调;平台验证请求会读取 `visibleStep`,普通模式承接步骤 10,Plus 模式承接步骤 13。
|
||||
- `content/utils.js`:内容脚本公共工具层,负责结构化日志、READY / COMPLETE / ERROR 上报、元素等待、输入与点击;内容脚本日志通过 `{ step, stepKey }` 上报,正文不再承担步骤号解析职责。
|
||||
- `content/vps-panel.js`:CPA 面板内容脚本,负责获取 OAuth 地址、提交回调 URL,并基于精确成功徽标与错误态做平台验证判定;当前支持普通步骤 10 与 Plus 可见步骤 13。
|
||||
@@ -243,7 +243,7 @@
|
||||
- `tests/sidepanel-mail2925-manager.test.js`:测试侧边栏 2925 管理器模块接线、共享号池表单脚本加载顺序、显隐交互与空态渲染。
|
||||
- `tests/sidepanel-mail2925-mode.test.js`:测试侧边栏保留 `2925 provide / receive` 模式行与独立的号池配置行,并验证 sidepanel 只在 provide 模式下把 2925 视为别名邮箱 provider。
|
||||
- `tests/sidepanel-paypal-manager.test.js`:测试侧边栏公共表单弹窗脚本与 PayPal manager 的加载顺序,以及 PayPal 账号保存后会立即选中当前账号。
|
||||
- `tests/signup-entry-diagnostics.test.js`:测试注册入口诊断快照输出。
|
||||
- `tests/signup-entry-diagnostics.test.js`:测试注册入口与密码页诊断快照输出,包括密码页错误文案字段。
|
||||
- `tests/signup-step2-email-switch.test.js`:测试 Step 2 在手机号输入模式下切回邮箱输入模式、本地化邮箱输入框识别,以及手机号注册时国家下拉框可视区号同步。
|
||||
- `tests/signup-page-tab-cleanup.test.js`:测试注册页来源标签的冲突清理逻辑。
|
||||
- `tests/step-definitions-module.test.js`:测试共享步骤定义模块及侧边栏脚本加载顺序。
|
||||
|
||||
Reference in New Issue
Block a user