mirror of
https://github.com/zc-zhangchen/any-auto-register.git
synced 2026-05-10 01:04:15 +08:00
fix(chatgpt): correct passwordless OTP request and reset email on retries
This commit is contained in:
@@ -684,7 +684,6 @@ class OAuthClient:
|
||||
|
||||
try:
|
||||
kwargs = {
|
||||
"json": {"email": email},
|
||||
"headers": headers,
|
||||
"timeout": 30,
|
||||
"allow_redirects": False,
|
||||
|
||||
@@ -313,6 +313,7 @@ class RefreshTokenRegistrationEngine:
|
||||
def run(self) -> RegistrationResult:
|
||||
result = RegistrationResult(success=False, logs=self.logs)
|
||||
last_error = ""
|
||||
fixed_email = str(self.email or "").strip()
|
||||
|
||||
try:
|
||||
for attempt in range(self.max_retries):
|
||||
@@ -330,6 +331,11 @@ class RefreshTokenRegistrationEngine:
|
||||
self._log(f"整流程重试 {attempt + 1}/{self.max_retries} ...")
|
||||
time.sleep(1)
|
||||
|
||||
# 用户未显式指定邮箱时,每轮都必须使用本轮新购邮箱,
|
||||
# 避免重试时误复用上一轮邮箱导致收不到验证码。
|
||||
if not fixed_email:
|
||||
self.email = None
|
||||
|
||||
self._log("1. 创建邮箱...")
|
||||
if not self._create_email():
|
||||
last_error = "创建邮箱失败"
|
||||
|
||||
@@ -145,6 +145,76 @@ class RefreshTokenRegistrationEngineTests(unittest.TestCase):
|
||||
login_kwargs = oauth_client.login_and_get_tokens.call_args.kwargs
|
||||
self.assertEqual(login_kwargs["login_source"], "existing_account_recovery")
|
||||
|
||||
@mock.patch("platforms.chatgpt.refresh_token_registration_engine.OAuthManager")
|
||||
@mock.patch("platforms.chatgpt.refresh_token_registration_engine.OAuthClient")
|
||||
@mock.patch("platforms.chatgpt.refresh_token_registration_engine.ChatGPTClient")
|
||||
def test_run_retry_uses_newly_created_email_in_next_attempt(
|
||||
self,
|
||||
mock_chatgpt_client_cls,
|
||||
mock_oauth_client_cls,
|
||||
mock_oauth_manager_cls,
|
||||
):
|
||||
class RotatingEmailService:
|
||||
service_type = type("ST", (), {"value": "dummy"})()
|
||||
|
||||
def __init__(self):
|
||||
self.index = 0
|
||||
|
||||
def create_email(self):
|
||||
self.index += 1
|
||||
return {
|
||||
"email": f"user{self.index}@example.com",
|
||||
"service_id": f"svc-{self.index}",
|
||||
}
|
||||
|
||||
def get_verification_code(self, **kwargs):
|
||||
return "123456"
|
||||
|
||||
register_client = mock.Mock()
|
||||
register_client.device_id = "device-fixed"
|
||||
register_client.ua = "UA"
|
||||
register_client.sec_ch_ua = '"Chromium";v="136"'
|
||||
register_client.impersonate = "chrome136"
|
||||
register_client.register_complete_flow.side_effect = [
|
||||
(False, "network timeout"),
|
||||
(True, "注册成功"),
|
||||
]
|
||||
mock_chatgpt_client_cls.return_value = register_client
|
||||
|
||||
oauth_client = mock.Mock()
|
||||
oauth_client.login_and_get_tokens.return_value = {
|
||||
"access_token": "at",
|
||||
"refresh_token": "rt",
|
||||
"id_token": "id-token",
|
||||
"account_id": "acct-1",
|
||||
}
|
||||
oauth_client.last_workspace_id = "ws-1"
|
||||
oauth_client._decode_oauth_session_cookie.return_value = {
|
||||
"workspaces": [{"id": "ws-1"}]
|
||||
}
|
||||
oauth_client._get_cookie_value.return_value = "session-1"
|
||||
mock_oauth_client_cls.return_value = oauth_client
|
||||
|
||||
oauth_manager = mock.Mock()
|
||||
oauth_manager.extract_account_info.return_value = {
|
||||
"email": "user2@example.com",
|
||||
"account_id": "acct-1",
|
||||
}
|
||||
mock_oauth_manager_cls.return_value = oauth_manager
|
||||
|
||||
engine = RefreshTokenRegistrationEngine(
|
||||
email_service=RotatingEmailService(),
|
||||
proxy_url="http://127.0.0.1:7890",
|
||||
callback_logger=lambda msg: None,
|
||||
max_retries=2,
|
||||
)
|
||||
result = engine.run()
|
||||
|
||||
self.assertTrue(result.success)
|
||||
call_args = register_client.register_complete_flow.call_args_list
|
||||
self.assertEqual(call_args[0].args[0], "user1@example.com")
|
||||
self.assertEqual(call_args[1].args[0], "user2@example.com")
|
||||
|
||||
|
||||
class OAuthClientPasswordlessTests(unittest.TestCase):
|
||||
def _make_client(self):
|
||||
@@ -225,6 +295,34 @@ class OAuthClientPasswordlessTests(unittest.TestCase):
|
||||
follow_state.assert_called_once()
|
||||
handle_phone.assert_not_called()
|
||||
|
||||
def test_send_passwordless_login_otp_does_not_send_email_field(self):
|
||||
client = self._make_client()
|
||||
response = mock.Mock()
|
||||
response.status_code = 200
|
||||
response.url = "https://auth.openai.com/api/accounts/passwordless/send-otp"
|
||||
response.json.return_value = {"page": {"type": "email_otp_verification"}}
|
||||
client.session.post = mock.Mock(return_value=response)
|
||||
|
||||
expected_state = FlowState(
|
||||
page_type="email_otp_verification",
|
||||
continue_url="https://auth.openai.com/email-verification",
|
||||
current_url="https://auth.openai.com/email-verification",
|
||||
)
|
||||
with mock.patch.object(
|
||||
client,
|
||||
"_state_from_payload",
|
||||
return_value=expected_state,
|
||||
):
|
||||
state = client._send_passwordless_login_otp(
|
||||
"user@example.com",
|
||||
"device-fixed",
|
||||
)
|
||||
|
||||
self.assertEqual(state, expected_state)
|
||||
kwargs = client.session.post.call_args.kwargs
|
||||
self.assertNotIn("json", kwargs)
|
||||
self.assertNotIn("data", kwargs)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user