oauth-login.js 3.6 KB

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