account-run-history.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. (function attachBackgroundAccountRunHistory(root, factory) {
  2. root.MultiPageBackgroundAccountRunHistory = factory();
  3. })(typeof self !== 'undefined' ? self : globalThis, function createBackgroundAccountRunHistoryModule() {
  4. function createAccountRunHistoryHelpers(deps = {}) {
  5. const {
  6. ACCOUNT_RUN_HISTORY_STORAGE_KEY = 'accountRunHistory',
  7. addLog,
  8. buildHotmailLocalEndpoint,
  9. chrome,
  10. getErrorMessage,
  11. getState,
  12. HOTMAIL_SERVICE_MODE_LOCAL = 'local',
  13. normalizeHotmailLocalBaseUrl,
  14. } = deps;
  15. function normalizeAccountRunHistory(records) {
  16. if (!Array.isArray(records)) {
  17. return [];
  18. }
  19. return records
  20. .filter((item) => item && typeof item === 'object')
  21. .map((item) => ({
  22. email: String(item.email || '').trim(),
  23. password: String(item.password || '').trim(),
  24. status: String(item.status || '').trim().toLowerCase(),
  25. recordedAt: String(item.recordedAt || '').trim(),
  26. reason: String(item.reason || '').trim(),
  27. }))
  28. .filter((item) => item.email && item.password && item.status);
  29. }
  30. async function getPersistedAccountRunHistory() {
  31. try {
  32. const stored = await chrome.storage.local.get(ACCOUNT_RUN_HISTORY_STORAGE_KEY);
  33. return normalizeAccountRunHistory(stored[ACCOUNT_RUN_HISTORY_STORAGE_KEY]);
  34. } catch (err) {
  35. console.warn('[MultiPage:account-run-history] Failed to read account run history:', err?.message || err);
  36. return [];
  37. }
  38. }
  39. function buildAccountRunHistoryRecord(state = {}, status = '', reason = '') {
  40. const email = String(state.email || '').trim();
  41. const password = String(state.password || state.customPassword || '').trim();
  42. const normalizedStatus = String(status || '').trim().toLowerCase();
  43. const normalizedReason = String(reason || '').trim();
  44. if (!email || !password || !normalizedStatus) {
  45. return null;
  46. }
  47. return {
  48. email,
  49. password,
  50. status: normalizedStatus,
  51. recordedAt: new Date().toISOString(),
  52. reason: normalizedReason,
  53. };
  54. }
  55. async function appendAccountRunHistoryRecord(status, stateOverride = null, reason = '') {
  56. const state = stateOverride || await getState();
  57. const record = buildAccountRunHistoryRecord(state, status, reason);
  58. if (!record) {
  59. return null;
  60. }
  61. const history = await getPersistedAccountRunHistory();
  62. history.push(record);
  63. await chrome.storage.local.set({
  64. [ACCOUNT_RUN_HISTORY_STORAGE_KEY]: history,
  65. });
  66. return record;
  67. }
  68. function shouldAppendAccountRunTextFile(state = {}) {
  69. const serviceMode = String(state.hotmailServiceMode || '').trim().toLowerCase();
  70. if (serviceMode !== HOTMAIL_SERVICE_MODE_LOCAL) {
  71. return false;
  72. }
  73. const helperBaseUrl = normalizeHotmailLocalBaseUrl(state.hotmailLocalBaseUrl);
  74. return Boolean(helperBaseUrl);
  75. }
  76. async function appendAccountRunHistoryTextFile(record, stateOverride = null) {
  77. const normalizedRecord = record && typeof record === 'object'
  78. ? record
  79. : buildAccountRunHistoryRecord(stateOverride || await getState(), '');
  80. if (!normalizedRecord?.email || !normalizedRecord?.password || !normalizedRecord?.status) {
  81. return null;
  82. }
  83. const state = stateOverride || await getState();
  84. if (!shouldAppendAccountRunTextFile(state)) {
  85. return null;
  86. }
  87. const helperBaseUrl = normalizeHotmailLocalBaseUrl(state.hotmailLocalBaseUrl);
  88. let response;
  89. try {
  90. response = await fetch(buildHotmailLocalEndpoint(helperBaseUrl, '/append-account-log'), {
  91. method: 'POST',
  92. headers: {
  93. 'Content-Type': 'application/json',
  94. Accept: 'application/json',
  95. },
  96. body: JSON.stringify({
  97. email: normalizedRecord.email,
  98. password: normalizedRecord.password,
  99. status: normalizedRecord.status,
  100. recordedAt: normalizedRecord.recordedAt,
  101. reason: normalizedRecord.reason || '',
  102. }),
  103. });
  104. } catch (err) {
  105. throw new Error(`账号文本记录写入失败:无法连接本地 helper(${getErrorMessage(err)})`);
  106. }
  107. let payload = null;
  108. try {
  109. payload = await response.json();
  110. } catch (err) {
  111. throw new Error(`账号文本记录写入失败:本地 helper 返回了无法解析的响应(${getErrorMessage(err)})`);
  112. }
  113. if (!response.ok || payload?.ok === false) {
  114. throw new Error(`账号文本记录写入失败:${payload?.error || `HTTP ${response.status}`}`);
  115. }
  116. return payload?.filePath || '';
  117. }
  118. async function appendAccountRunRecord(status, stateOverride = null, reason = '') {
  119. const state = stateOverride || await getState();
  120. const record = await appendAccountRunHistoryRecord(status, state, reason);
  121. if (!record) {
  122. return null;
  123. }
  124. try {
  125. const filePath = await appendAccountRunHistoryTextFile(record, state);
  126. if (filePath) {
  127. await addLog(`账号记录已追加到本地文本:${filePath}`, 'info');
  128. }
  129. } catch (err) {
  130. await addLog(getErrorMessage(err), 'warn');
  131. }
  132. return record;
  133. }
  134. return {
  135. appendAccountRunRecord,
  136. appendAccountRunHistoryRecord,
  137. appendAccountRunHistoryTextFile,
  138. buildAccountRunHistoryRecord,
  139. getPersistedAccountRunHistory,
  140. normalizeAccountRunHistory,
  141. shouldAppendAccountRunTextFile,
  142. };
  143. }
  144. return {
  145. createAccountRunHistoryHelpers,
  146. };
  147. });