oauth-login.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. (function attachBackgroundStep7(root, factory) {
  2. root.MultiPageBackgroundStep7 = factory();
  3. })(typeof self !== 'undefined' ? self : globalThis, function createBackgroundStep7Module() {
  4. function createStep7Executor(deps = {}) {
  5. const {
  6. addLog,
  7. completeStepFromBackground,
  8. getErrorMessage,
  9. getLoginAuthStateLabel,
  10. getOAuthFlowStepTimeoutMs,
  11. getState,
  12. isStep6RecoverableResult,
  13. isStep6SuccessResult,
  14. refreshOAuthUrlBeforeStep6,
  15. reuseOrCreateTab,
  16. sendToContentScriptResilient,
  17. startOAuthFlowTimeoutWindow,
  18. STEP6_MAX_ATTEMPTS,
  19. throwIfStopped,
  20. } = deps;
  21. async function executeStep7(state) {
  22. if (!state.email) {
  23. throw new Error('缺少邮箱地址,请先完成步骤 3。');
  24. }
  25. let attempt = 0;
  26. let lastError = null;
  27. while (attempt < STEP6_MAX_ATTEMPTS) {
  28. throwIfStopped();
  29. attempt += 1;
  30. try {
  31. const currentState = attempt === 1 ? state : await getState();
  32. const password = currentState.password || currentState.customPassword || '';
  33. const oauthUrl = await refreshOAuthUrlBeforeStep6(currentState);
  34. if (typeof startOAuthFlowTimeoutWindow === 'function') {
  35. await startOAuthFlowTimeoutWindow({ step: 7, oauthUrl });
  36. }
  37. const loginTimeoutMs = typeof getOAuthFlowStepTimeoutMs === 'function'
  38. ? await getOAuthFlowStepTimeoutMs(180000, {
  39. step: 7,
  40. actionLabel: 'OAuth 登录并进入验证码页',
  41. })
  42. : 180000;
  43. if (attempt === 1) {
  44. await addLog('步骤 7:正在打开最新 OAuth 链接并登录...');
  45. } else {
  46. await addLog(`步骤 7:上一轮失败后,正在进行第 ${attempt} 次尝试(最多 ${STEP6_MAX_ATTEMPTS} 次)...`, 'warn');
  47. }
  48. await reuseOrCreateTab('signup-page', oauthUrl);
  49. const result = await sendToContentScriptResilient(
  50. 'signup-page',
  51. {
  52. type: 'EXECUTE_STEP',
  53. step: 7,
  54. source: 'background',
  55. payload: {
  56. email: currentState.email,
  57. password,
  58. },
  59. },
  60. {
  61. timeoutMs: loginTimeoutMs,
  62. responseTimeoutMs: loginTimeoutMs,
  63. retryDelayMs: 700,
  64. logMessage: '步骤 7:认证页正在切换,等待页面重新就绪后继续登录...',
  65. }
  66. );
  67. if (result?.error) {
  68. throw new Error(result.error);
  69. }
  70. if (isStep6SuccessResult(result)) {
  71. await completeStepFromBackground(7, {
  72. loginVerificationRequestedAt: result.loginVerificationRequestedAt || null,
  73. });
  74. return;
  75. }
  76. if (isStep6RecoverableResult(result)) {
  77. const reasonMessage = result.message
  78. || `当前停留在${getLoginAuthStateLabel(result.state)},准备重新执行步骤 7。`;
  79. throw new Error(reasonMessage);
  80. }
  81. throw new Error('步骤 7:认证页未返回可识别的登录结果。');
  82. } catch (err) {
  83. throwIfStopped(err);
  84. lastError = err;
  85. if (attempt >= STEP6_MAX_ATTEMPTS) {
  86. break;
  87. }
  88. await addLog(`步骤 7:第 ${attempt} 次尝试失败,原因:${getErrorMessage(err)};准备重试...`, 'warn');
  89. }
  90. }
  91. throw new Error(`步骤 7:判断失败后已重试 ${STEP6_MAX_ATTEMPTS - 1} 次,仍未成功。最后原因:${getErrorMessage(lastError)}`);
  92. }
  93. return { executeStep7 };
  94. }
  95. return { createStep7Executor };
  96. });