account-run-history.js 5.5 KB

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