| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- (function luckmailUtilsModule(root, factory) {
- if (typeof module !== 'undefined' && module.exports) {
- module.exports = factory();
- return;
- }
- root.LuckMailUtils = factory();
- })(typeof self !== 'undefined' ? self : globalThis, function createLuckmailUtils() {
- const DEFAULT_LUCKMAIL_BASE_URL = 'https://mails.luckyous.com';
- const DEFAULT_LUCKMAIL_EMAIL_TYPE = 'ms_graph';
- const DEFAULT_LUCKMAIL_PROJECT_CODE = 'openai';
- const DEFAULT_LUCKMAIL_PRESERVE_TAG_NAME = '保留';
- const LUCKMAIL_EMAIL_TYPES = ['self_built', 'ms_imap', 'ms_graph', 'google_variant'];
- function firstNonEmptyString(values) {
- for (const value of values) {
- if (value === undefined || value === null) continue;
- const normalized = String(value).trim();
- if (normalized) return normalized;
- }
- return '';
- }
- function normalizeText(value) {
- return String(value || '')
- .replace(/\s+/g, ' ')
- .trim()
- .toLowerCase();
- }
- function normalizeTimestamp(value) {
- if (!value) return 0;
- if (typeof value === 'number' && Number.isFinite(value)) {
- return value > 0 ? value : 0;
- }
- const rawValue = String(value || '').trim();
- const utcLikeMatch = rawValue.match(
- /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2})(?::(\d{2}))?$/
- );
- if (utcLikeMatch && !/[zZ]|[+\-]\d{2}:?\d{2}$/.test(rawValue)) {
- const [, year, month, day, hour, minute, second = '0'] = utcLikeMatch;
- return Date.UTC(
- Number(year),
- Number(month) - 1,
- Number(day),
- Number(hour),
- Number(minute),
- Number(second),
- 0
- );
- }
- const timestamp = Date.parse(rawValue);
- return Number.isFinite(timestamp) ? timestamp : 0;
- }
- function normalizeLuckmailBaseUrl(rawValue = '') {
- const value = String(rawValue || '').trim();
- if (!value) return DEFAULT_LUCKMAIL_BASE_URL;
- try {
- const parsed = new URL(value);
- if (!['http:', 'https:'].includes(parsed.protocol)) {
- return DEFAULT_LUCKMAIL_BASE_URL;
- }
- parsed.pathname = parsed.pathname.replace(/\/+$/, '');
- parsed.search = '';
- parsed.hash = '';
- return parsed.toString().replace(/\/$/, '');
- } catch {
- return DEFAULT_LUCKMAIL_BASE_URL;
- }
- }
- function normalizeLuckmailEmailType(rawValue = '') {
- const normalized = String(rawValue || '').trim().toLowerCase();
- return LUCKMAIL_EMAIL_TYPES.includes(normalized)
- ? normalized
- : DEFAULT_LUCKMAIL_EMAIL_TYPE;
- }
- function normalizeLuckmailProjectName(rawValue = '') {
- return normalizeText(rawValue);
- }
- function extractLuckmailVerificationCode(text) {
- const source = String(text || '');
- const matchCn = source.match(/(?:代码为|验证码[^0-9]*?)[\s::]*(\d{6})/i);
- if (matchCn) return matchCn[1];
- const matchChatGPT = source.match(/your\s+chatgpt\s+code\s+is\s+(\d{6})/i);
- if (matchChatGPT) return matchChatGPT[1];
- const matchEn = source.match(/code(?:\s+is|[\s:])+(\d{6})/i);
- if (matchEn) return matchEn[1];
- const matchStandalone = source.match(/\b(\d{6})\b/);
- return matchStandalone ? matchStandalone[1] : null;
- }
- function normalizeLuckmailTag(item = {}) {
- const safeItem = item && typeof item === 'object' ? item : {};
- return {
- id: Number(safeItem.id) || 0,
- name: firstNonEmptyString([safeItem.name, safeItem.tag_name]),
- remark: firstNonEmptyString([safeItem.remark]),
- limit_type: Number(safeItem.limit_type) || 0,
- purchase_count: Number(safeItem.purchase_count) || 0,
- created_at: firstNonEmptyString([safeItem.created_at]) || null,
- };
- }
- function normalizeLuckmailTags(input) {
- const list = Array.isArray(input?.list)
- ? input.list
- : (Array.isArray(input) ? input : []);
- return list
- .map((item) => normalizeLuckmailTag(item))
- .filter((item) => item.id > 0 || item.name);
- }
- function normalizeLuckmailPurchase(item = {}) {
- const safeItem = item && typeof item === 'object' ? item : {};
- const projectName = firstNonEmptyString([safeItem.project_name, safeItem.project]);
- return {
- id: Number(safeItem.id) || 0,
- email_address: firstNonEmptyString([safeItem.email_address, safeItem.address]),
- token: firstNonEmptyString([safeItem.token]),
- project_name: projectName,
- project_code: normalizeLuckmailProjectName(projectName),
- price: firstNonEmptyString([safeItem.price]) || '0.0000',
- status: Number(safeItem.status) || 0,
- tag_id: Number(safeItem.tag_id) || 0,
- tag_name: firstNonEmptyString([safeItem.tag_name]),
- user_disabled: Number(safeItem.user_disabled) || 0,
- warranty_hours: Number(safeItem.warranty_hours) || 0,
- warranty_until: firstNonEmptyString([safeItem.warranty_until]) || null,
- created_at: firstNonEmptyString([safeItem.created_at]) || null,
- };
- }
- function normalizeLuckmailPurchases(result) {
- const list = Array.isArray(result?.purchases)
- ? result.purchases
- : (Array.isArray(result) ? result : []);
- return list.map((item) => normalizeLuckmailPurchase(item));
- }
- function normalizeLuckmailPurchaseListPage(result = {}) {
- const safeResult = result && typeof result === 'object' ? result : {};
- const list = Array.isArray(safeResult.list)
- ? safeResult.list
- : (Array.isArray(safeResult.purchases) ? safeResult.purchases : []);
- const total = Number(safeResult.total);
- return {
- list: list.map((item) => normalizeLuckmailPurchase(item)),
- total: Number.isFinite(total) && total >= 0 ? total : 0,
- page: Math.max(1, Number(safeResult.page) || 1),
- page_size: Math.max(1, Number(safeResult.page_size || safeResult.pageSize) || list.length || 1),
- };
- }
- function normalizeLuckmailPurchaseId(value) {
- const numeric = Number(value);
- if (!Number.isFinite(numeric) || numeric <= 0) {
- return '';
- }
- return String(Math.floor(numeric));
- }
- function normalizeLuckmailUsedPurchases(rawValue = {}) {
- if (!rawValue || typeof rawValue !== 'object' || Array.isArray(rawValue)) {
- return {};
- }
- return Object.entries(rawValue).reduce((result, [key, value]) => {
- const normalizedKey = normalizeLuckmailPurchaseId(key);
- if (!normalizedKey) {
- return result;
- }
- result[normalizedKey] = Boolean(value);
- return result;
- }, {});
- }
- function isLuckmailPurchaseForProject(purchase, projectCode = DEFAULT_LUCKMAIL_PROJECT_CODE) {
- const normalizedPurchase = normalizeLuckmailPurchase(purchase);
- return normalizeLuckmailProjectName(normalizedPurchase.project_name) === normalizeLuckmailProjectName(projectCode);
- }
- function normalizeLuckmailTokenMail(mail = {}) {
- const safeMail = mail && typeof mail === 'object' ? mail : {};
- const subject = firstNonEmptyString([safeMail.subject, safeMail.title]);
- const body = firstNonEmptyString([safeMail.body, safeMail.body_text, safeMail.text]);
- const htmlBody = firstNonEmptyString([safeMail.html_body, safeMail.body_html, safeMail.html]);
- const from = firstNonEmptyString([safeMail.from, safeMail.sender]);
- const verificationCode = firstNonEmptyString([safeMail.verification_code])
- || extractLuckmailVerificationCode([subject, body, htmlBody, from].filter(Boolean).join(' '));
- return {
- message_id: firstNonEmptyString([safeMail.message_id, safeMail.id]),
- from,
- subject,
- body,
- html_body: htmlBody,
- received_at: firstNonEmptyString([safeMail.received_at, safeMail.receivedAt, safeMail.created_at]),
- verification_code: verificationCode || '',
- };
- }
- function normalizeLuckmailTokenMails(input) {
- const list = Array.isArray(input?.mails)
- ? input.mails
- : (Array.isArray(input) ? input : []);
- return list.map((mail) => normalizeLuckmailTokenMail(mail));
- }
- function normalizeLuckmailTokenCode(result = {}) {
- return {
- email_address: firstNonEmptyString([result.email_address, result.address]),
- project: firstNonEmptyString([result.project]),
- has_new_mail: Boolean(result.has_new_mail),
- verification_code: firstNonEmptyString([result.verification_code]) || null,
- mail: result.mail ? normalizeLuckmailTokenMail(result.mail) : null,
- };
- }
- function normalizeLuckmailMailCursor(cursor = {}) {
- const safeCursor = cursor && typeof cursor === 'object' ? cursor : {};
- return {
- messageId: firstNonEmptyString([safeCursor.messageId, safeCursor.message_id]),
- receivedAt: firstNonEmptyString([safeCursor.receivedAt, safeCursor.received_at]),
- };
- }
- function buildLuckmailMailCursor(mail = {}) {
- const normalizedMail = normalizeLuckmailTokenMail(mail);
- return normalizeLuckmailMailCursor({
- messageId: normalizedMail.message_id,
- receivedAt: normalizedMail.received_at,
- });
- }
- function buildLuckmailBaselineCursor(mails) {
- const latestMail = normalizeLuckmailTokenMails(mails)
- .sort((left, right) => {
- const leftTimestamp = normalizeTimestamp(left.received_at);
- const rightTimestamp = normalizeTimestamp(right.received_at);
- if (leftTimestamp !== rightTimestamp) {
- return rightTimestamp - leftTimestamp;
- }
- return String(right.message_id || '').localeCompare(String(left.message_id || ''));
- })[0] || null;
- return latestMail ? buildLuckmailMailCursor(latestMail) : null;
- }
- function isLuckmailMailNewerThanCursor(mail = {}, cursor = {}) {
- const normalizedMail = normalizeLuckmailTokenMail(mail);
- const normalizedCursor = normalizeLuckmailMailCursor(cursor);
- if (!normalizedCursor.messageId && !normalizedCursor.receivedAt) {
- return true;
- }
- if (normalizedMail.message_id && normalizedCursor.messageId && normalizedMail.message_id === normalizedCursor.messageId) {
- return false;
- }
- const mailTimestamp = normalizeTimestamp(normalizedMail.received_at);
- const cursorTimestamp = normalizeTimestamp(normalizedCursor.receivedAt);
- if (mailTimestamp && cursorTimestamp) {
- if (mailTimestamp > cursorTimestamp) return true;
- if (mailTimestamp < cursorTimestamp) return false;
- return Boolean(
- normalizedMail.message_id
- && normalizedCursor.messageId
- && normalizedMail.message_id !== normalizedCursor.messageId
- );
- }
- if (normalizedMail.message_id && normalizedCursor.messageId) {
- return normalizedMail.message_id !== normalizedCursor.messageId;
- }
- return !cursorTimestamp || Boolean(mailTimestamp && mailTimestamp > cursorTimestamp);
- }
- function isLuckmailPurchaseExpired(purchase, now = Date.now()) {
- const normalizedPurchase = normalizeLuckmailPurchase(purchase);
- const expiresAt = normalizeTimestamp(normalizedPurchase.warranty_until);
- return Boolean(expiresAt && expiresAt <= Number(now || 0));
- }
- function isLuckmailPurchaseDisabled(purchase) {
- return Number(normalizeLuckmailPurchase(purchase).user_disabled) === 1;
- }
- function isLuckmailPurchasePreserved(purchase, options = {}) {
- const normalizedPurchase = normalizeLuckmailPurchase(purchase);
- const expectedTagId = Number(options.preserveTagId) || 0;
- const expectedTagName = normalizeText(options.preserveTagName || DEFAULT_LUCKMAIL_PRESERVE_TAG_NAME);
- if (expectedTagId > 0 && normalizedPurchase.tag_id === expectedTagId) {
- return true;
- }
- return Boolean(normalizedPurchase.tag_name && normalizeText(normalizedPurchase.tag_name) === expectedTagName);
- }
- function isLuckmailPurchaseReusable(purchase, options = {}) {
- const normalizedPurchase = normalizeLuckmailPurchase(purchase);
- const usedPurchases = normalizeLuckmailUsedPurchases(options.usedPurchases);
- const purchaseId = normalizeLuckmailPurchaseId(normalizedPurchase.id);
- if (!isLuckmailPurchaseForProject(normalizedPurchase, options.projectCode || DEFAULT_LUCKMAIL_PROJECT_CODE)) {
- return false;
- }
- if (!normalizedPurchase.email_address || !normalizedPurchase.token) {
- return false;
- }
- if (isLuckmailPurchaseDisabled(normalizedPurchase)) {
- return false;
- }
- if (purchaseId && usedPurchases[purchaseId]) {
- return false;
- }
- if (isLuckmailPurchasePreserved(normalizedPurchase, options)) {
- return false;
- }
- if (isLuckmailPurchaseExpired(normalizedPurchase, options.now || Date.now())) {
- return false;
- }
- return true;
- }
- function filterReusableLuckmailPurchases(purchases, options = {}) {
- const list = Array.isArray(purchases)
- ? purchases
- : normalizeLuckmailPurchaseListPage(purchases).list;
- return list
- .map((purchase) => normalizeLuckmailPurchase(purchase))
- .filter((purchase) => isLuckmailPurchaseReusable(purchase, options));
- }
- function pickReusableLuckmailPurchase(purchases, options = {}) {
- return filterReusableLuckmailPurchases(purchases, options)[0] || null;
- }
- function mailMatchesLuckmailFilters(mail, filters = {}) {
- const normalizedMail = normalizeLuckmailTokenMail(mail);
- const afterTimestamp = normalizeTimestamp(filters.afterTimestamp);
- const receivedAt = normalizeTimestamp(normalizedMail.received_at);
- if (afterTimestamp && receivedAt && receivedAt < afterTimestamp) {
- return null;
- }
- const senderFilters = (filters.senderFilters || []).map(normalizeText).filter(Boolean);
- const subjectFilters = (filters.subjectFilters || []).map(normalizeText).filter(Boolean);
- const excludedCodes = new Set((filters.excludeCodes || []).filter(Boolean));
- const combinedText = [
- normalizedMail.subject,
- normalizedMail.from,
- normalizedMail.body,
- normalizedMail.html_body,
- ].filter(Boolean).join(' ');
- const combinedTextNormalized = normalizeText(combinedText);
- const senderNormalized = normalizeText(normalizedMail.from);
- const subjectNormalized = normalizeText(normalizedMail.subject);
- const code = normalizedMail.verification_code || extractLuckmailVerificationCode(combinedText);
- if (!code || excludedCodes.has(code)) {
- return null;
- }
- const senderMatch = senderFilters.length === 0
- ? true
- : senderFilters.some((item) => senderNormalized.includes(item) || combinedTextNormalized.includes(item));
- const subjectMatch = subjectFilters.length === 0
- ? true
- : subjectFilters.some((item) => subjectNormalized.includes(item) || combinedTextNormalized.includes(item));
- if (!senderMatch && !subjectMatch) {
- return null;
- }
- return {
- code,
- mail: normalizedMail,
- receivedAt,
- };
- }
- function pickLuckmailVerificationMail(mails, filters = {}) {
- const matches = normalizeLuckmailTokenMails(mails)
- .map((mail) => mailMatchesLuckmailFilters(mail, filters))
- .filter(Boolean)
- .sort((left, right) => {
- if (left.receivedAt !== right.receivedAt) {
- return right.receivedAt - left.receivedAt;
- }
- return String(right.mail.message_id || '').localeCompare(String(left.mail.message_id || ''));
- });
- return matches[0] || null;
- }
- return {
- DEFAULT_LUCKMAIL_BASE_URL,
- DEFAULT_LUCKMAIL_EMAIL_TYPE,
- DEFAULT_LUCKMAIL_PROJECT_CODE,
- DEFAULT_LUCKMAIL_PRESERVE_TAG_NAME,
- LUCKMAIL_EMAIL_TYPES,
- buildLuckmailBaselineCursor,
- buildLuckmailMailCursor,
- extractLuckmailVerificationCode,
- filterReusableLuckmailPurchases,
- isLuckmailMailNewerThanCursor,
- isLuckmailPurchaseDisabled,
- isLuckmailPurchaseExpired,
- isLuckmailPurchaseForProject,
- isLuckmailPurchasePreserved,
- isLuckmailPurchaseReusable,
- normalizeLuckmailBaseUrl,
- normalizeLuckmailEmailType,
- normalizeLuckmailMailCursor,
- normalizeLuckmailProjectName,
- normalizeLuckmailPurchase,
- normalizeLuckmailPurchaseId,
- normalizeLuckmailPurchaseListPage,
- normalizeLuckmailPurchases,
- normalizeLuckmailTag,
- normalizeLuckmailTags,
- normalizeLuckmailTokenCode,
- normalizeLuckmailTokenMail,
- normalizeLuckmailTokenMails,
- normalizeLuckmailUsedPurchases,
- normalizeText,
- normalizeTimestamp,
- pickLuckmailVerificationMail,
- pickReusableLuckmailPurchase,
- };
- });
|