logging-status.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. (function attachBackgroundLoggingStatus(root, factory) {
  2. root.MultiPageBackgroundLoggingStatus = factory();
  3. })(typeof self !== 'undefined' ? self : globalThis, function createBackgroundLoggingStatusModule() {
  4. function createLoggingStatus(deps = {}) {
  5. const {
  6. chrome,
  7. DEFAULT_STATE,
  8. getState,
  9. isRecoverableStep9AuthFailure,
  10. LOG_PREFIX,
  11. setState,
  12. STOP_ERROR_MESSAGE,
  13. } = deps;
  14. function getSourceLabel(source) {
  15. const labels = {
  16. 'gmail-mail': 'Gmail 邮箱',
  17. 'sidepanel': '侧边栏',
  18. 'signup-page': '认证页',
  19. 'vps-panel': 'CPA 面板',
  20. 'sub2api-panel': 'SUB2API 后台',
  21. 'qq-mail': 'QQ 邮箱',
  22. 'mail-163': '163 邮箱',
  23. 'mail-2925': '2925 邮箱',
  24. 'inbucket-mail': 'Inbucket 邮箱',
  25. 'duck-mail': 'Duck 邮箱',
  26. 'hotmail-api': 'Hotmail(API对接/本地助手)',
  27. 'luckmail-api': 'LuckMail(API 购邮)',
  28. 'cloudflare-temp-email': 'Cloudflare Temp Email',
  29. 'checkout-stripe': 'Stripe 结账',
  30. 'checkout-paypal': 'PayPal 结账',
  31. };
  32. return labels[source] || source || '未知来源';
  33. }
  34. async function addLog(message, level = 'info') {
  35. const state = await getState();
  36. const logs = state.logs || [];
  37. const entry = { message, level, timestamp: Date.now() };
  38. logs.push(entry);
  39. if (logs.length > 500) logs.splice(0, logs.length - 500);
  40. await setState({ logs });
  41. chrome.runtime.sendMessage({ type: 'LOG_ENTRY', payload: entry }).catch(() => { });
  42. }
  43. async function setStepStatus(step, status) {
  44. const state = await getState();
  45. const statuses = { ...state.stepStatuses };
  46. statuses[step] = status;
  47. await setState({ stepStatuses: statuses, currentStep: step });
  48. chrome.runtime.sendMessage({
  49. type: 'STEP_STATUS_CHANGED',
  50. payload: { step, status },
  51. }).catch(() => { });
  52. }
  53. function getErrorMessage(error) {
  54. return String(typeof error === 'string' ? error : error?.message || '');
  55. }
  56. function isVerificationMailPollingError(error) {
  57. const message = getErrorMessage(error);
  58. return /未在 .*邮箱中找到新的匹配邮件|未在 Hotmail 收件箱中找到新的匹配验证码|邮箱轮询结束,但未获取到验证码|无法获取新的(?:注册|登录)验证码|页面未能重新就绪|页面通信异常|did not respond in \d+s/i.test(message);
  59. }
  60. function isAddPhoneAuthFailure(error) {
  61. const message = getErrorMessage(error);
  62. return /https:\/\/auth\.openai\.com\/add-phone(?:[/?#]|$)|\badd-phone\b|添加手机号|手机号码|手机号页|手机号页面|手机号|phone\s+number|telephone/i.test(message);
  63. }
  64. function getLoginAuthStateLabel(state) {
  65. state = state === 'oauth_consent_page' ? 'unknown' : state;
  66. switch (state) {
  67. case 'verification_page':
  68. return '登录验证码页';
  69. case 'password_page':
  70. return '密码页';
  71. case 'email_page':
  72. return '邮箱输入页';
  73. case 'login_timeout_error_page':
  74. return '登录超时报错页';
  75. case 'oauth_consent_page':
  76. return 'OAuth 授权页';
  77. case 'add_phone_page':
  78. return '手机号页';
  79. default:
  80. return '未知页面';
  81. }
  82. }
  83. function isRestartCurrentAttemptError(error) {
  84. const message = String(typeof error === 'string' ? error : error?.message || '');
  85. return /当前邮箱已存在,需要重新开始新一轮/.test(message);
  86. }
  87. function isStep9RecoverableAuthError(error) {
  88. const message = String(typeof error === 'string' ? error : error?.message || '');
  89. return /STEP9_OAUTH_RETRY::/i.test(message)
  90. || isRecoverableStep9AuthFailure(message);
  91. }
  92. function isLegacyStep9RecoverableAuthError(error) {
  93. const message = String(typeof error === 'string' ? error : error?.message || '');
  94. return /STEP9_OAUTH_TIMEOUT::|认证失败:\s*(?:Timeout waiting for OAuth callback|timeout of \d+ms exceeded)/i.test(message);
  95. }
  96. function isStepDoneStatus(status) {
  97. return status === 'completed' || status === 'manual_completed' || status === 'skipped';
  98. }
  99. function getFirstUnfinishedStep(statuses = {}) {
  100. const stepIds = Object.keys(DEFAULT_STATE.stepStatuses || {})
  101. .map((step) => Number(step))
  102. .filter(Number.isFinite)
  103. .sort((left, right) => left - right);
  104. for (const step of stepIds) {
  105. if (!isStepDoneStatus(statuses[step] || 'pending')) {
  106. return step;
  107. }
  108. }
  109. return null;
  110. }
  111. function hasSavedProgress(statuses = {}) {
  112. return Object.values({ ...DEFAULT_STATE.stepStatuses, ...statuses }).some((status) => status !== 'pending');
  113. }
  114. function getRunningSteps(statuses = {}) {
  115. return Object.entries({ ...DEFAULT_STATE.stepStatuses, ...statuses })
  116. .filter(([, status]) => status === 'running')
  117. .map(([step]) => Number(step))
  118. .sort((a, b) => a - b);
  119. }
  120. function getAutoRunStatusPayload(phase, payload = {}) {
  121. return {
  122. autoRunning: phase === 'scheduled'
  123. || phase === 'running'
  124. || phase === 'waiting_step'
  125. || phase === 'waiting_email'
  126. || phase === 'retrying'
  127. || phase === 'waiting_interval',
  128. autoRunPhase: phase,
  129. autoRunCurrentRun: payload.currentRun ?? 0,
  130. autoRunTotalRuns: payload.totalRuns ?? 1,
  131. autoRunAttemptRun: payload.attemptRun ?? 0,
  132. autoRunSessionId: Math.max(0, Math.floor(Number(payload.sessionId ?? payload.autoRunSessionId) || 0)),
  133. scheduledAutoRunAt: Number.isFinite(Number(payload.scheduledAt)) ? Number(payload.scheduledAt) : null,
  134. autoRunCountdownAt: Number.isFinite(Number(payload.countdownAt)) ? Number(payload.countdownAt) : null,
  135. autoRunCountdownTitle: payload.countdownTitle === undefined ? '' : String(payload.countdownTitle || ''),
  136. autoRunCountdownNote: payload.countdownNote === undefined ? '' : String(payload.countdownNote || ''),
  137. };
  138. }
  139. return {
  140. addLog,
  141. getAutoRunStatusPayload,
  142. isAddPhoneAuthFailure,
  143. getErrorMessage,
  144. getFirstUnfinishedStep,
  145. getLoginAuthStateLabel,
  146. getRunningSteps,
  147. getSourceLabel,
  148. hasSavedProgress,
  149. isLegacyStep9RecoverableAuthError,
  150. isRestartCurrentAttemptError,
  151. isStep9RecoverableAuthError,
  152. isStepDoneStatus,
  153. isVerificationMailPollingError,
  154. setStepStatus,
  155. };
  156. }
  157. return {
  158. createLoggingStatus,
  159. };
  160. });