import GuJumpgate snapshot from GitHub

This commit is contained in:
2026-05-20 20:33:51 +08:00
commit f8903dcd14
335 changed files with 179790 additions and 0 deletions
+609
View File
@@ -0,0 +1,609 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const {
buildHotmailMailApiLatestUrl,
extractVerificationCodeFromMessage,
filterHotmailAccountsByUsage,
extractVerificationCode,
getLatestHotmailMessage,
getHotmailBulkActionLabel,
getHotmailListToggleLabel,
getHotmailMailApiRequestConfig,
getHotmailVerificationPollConfig,
getHotmailVerificationRequestTimestamp,
buildOutlookPlusAliasEmail,
findSubscriptionMessageForAlias,
isHotmailAliasCapacityExhausted,
normalizeHotmailServiceMode,
normalizeOutlookAliasMaxPerAccount,
normalizeHotmailMailApiMessages,
parseHotmailImportText,
pickHotmailAccountForRun,
pickVerificationMessage,
pickVerificationMessageWithFallback,
pickVerificationMessageWithTimeFallback,
shouldClearHotmailCurrentSelection,
upsertHotmailAccountInList,
} = require('../hotmail-utils.js');
test('pickHotmailAccountForRun prefers authorized account with oldest lastUsedAt', () => {
const now = Date.UTC(2026, 3, 10, 10, 0, 0);
const accounts = [
{
id: 'recent',
email: 'recent@hotmail.com',
status: 'authorized',
refreshToken: 'rt-recent',
lastUsedAt: now - 1_000,
},
{
id: 'oldest',
email: 'oldest@hotmail.com',
status: 'authorized',
refreshToken: 'rt-oldest',
lastUsedAt: now - 50_000,
},
{
id: 'pending',
email: 'pending@hotmail.com',
status: 'pending',
refreshToken: '',
lastUsedAt: 0,
},
];
const selected = pickHotmailAccountForRun(accounts, { now });
assert.equal(selected.id, 'oldest');
});
test('pickHotmailAccountForRun skips used accounts but ignores legacy enabled flag', () => {
const accounts = [
{
id: 'disabled',
email: 'disabled@hotmail.com',
status: 'authorized',
refreshToken: 'rt-disabled',
enabled: false,
used: false,
lastUsedAt: 1,
},
{
id: 'used',
email: 'used@hotmail.com',
status: 'authorized',
refreshToken: 'rt-used',
enabled: true,
used: true,
lastUsedAt: 0,
},
{
id: 'available',
email: 'available@hotmail.com',
status: 'authorized',
refreshToken: 'rt-available',
enabled: true,
used: false,
lastUsedAt: 2,
},
];
const selected = pickHotmailAccountForRun(accounts, {});
assert.equal(selected.id, 'disabled');
});
test('Outlook alias helpers generate plus aliases and enforce default capacity', () => {
assert.equal(buildOutlookPlusAliasEmail('user@outlook.com', 'AbC_123'), 'user+abc_123@outlook.com');
assert.equal(normalizeOutlookAliasMaxPerAccount(undefined), 5);
const account = { id: 'base-1', email: 'user@outlook.com' };
const usage = {
'base-1': {
aliases: Object.fromEntries(Array.from({ length: 5 }, (_, index) => [
`user+tag${index}@outlook.com`,
{
email: `user+tag${index}@outlook.com`,
used: true,
reason: 'flow_completed',
},
])),
},
};
assert.equal(isHotmailAliasCapacityExhausted(account, usage, undefined), true);
assert.equal(isHotmailAliasCapacityExhausted(account, usage, 6), false);
});
test('Outlook alias subscription precheck requires matching recipient fields', () => {
const alias = 'user+tag1@outlook.com';
const matched = findSubscriptionMessageForAlias([
{
subject: 'ChatGPT Plus Subscription',
bodyPreview: 'subscription receipt',
recipients: {
to: [alias],
all: [alias],
},
},
], alias);
assert.equal(matched.matched, true);
const missingRecipients = findSubscriptionMessageForAlias([
{
subject: 'ChatGPT Plus Subscription',
bodyPreview: 'subscription receipt',
},
], alias);
assert.equal(missingRecipients.matched, false);
assert.equal(missingRecipients.missingRecipients, true);
const otherRecipient = findSubscriptionMessageForAlias([
{
subject: 'ChatGPT Plus Subscription',
recipients: {
to: ['user+other@outlook.com'],
all: ['user+other@outlook.com'],
},
},
], alias);
assert.equal(otherRecipient.matched, false);
assert.equal(otherRecipient.missingRecipients, false);
});
test('pickHotmailAccountForRun returns null for used-only pools', () => {
assert.equal(
pickHotmailAccountForRun([{
id: 'used-only',
email: 'used-only@hotmail.com',
status: 'authorized',
refreshToken: 'rt-used-only',
used: true,
lastUsedAt: 0,
}], {}),
null
);
});
test('pickHotmailAccountForRun falls back to never-used authorized account first', () => {
const accounts = [
{
id: 'used',
email: 'used@hotmail.com',
status: 'authorized',
refreshToken: 'rt-used',
lastUsedAt: Date.UTC(2026, 3, 10, 9, 0, 0),
},
{
id: 'fresh',
email: 'fresh@hotmail.com',
status: 'authorized',
refreshToken: 'rt-fresh',
lastUsedAt: 0,
},
];
const selected = pickHotmailAccountForRun(accounts, { now: Date.UTC(2026, 3, 10, 10, 0, 0) });
assert.equal(selected.id, 'fresh');
});
test('upsertHotmailAccountInList replaces matching account state by id', () => {
const accounts = [
{
id: 'active',
email: 'active@hotmail.com',
status: 'authorized',
used: false,
},
{
id: 'other',
email: 'other@hotmail.com',
status: 'authorized',
used: false,
},
];
const nextAccounts = upsertHotmailAccountInList(accounts, {
id: 'active',
email: 'active@hotmail.com',
status: 'authorized',
used: true,
});
assert.deepEqual(nextAccounts, [
{
id: 'active',
email: 'active@hotmail.com',
status: 'authorized',
used: true,
},
{
id: 'other',
email: 'other@hotmail.com',
status: 'authorized',
used: false,
},
]);
});
test('shouldClearHotmailCurrentSelection returns true only when account becomes used', () => {
assert.equal(shouldClearHotmailCurrentSelection({
id: 'used',
used: true,
}), true);
assert.equal(shouldClearHotmailCurrentSelection({
id: 'available',
used: false,
}), false);
});
test('extractVerificationCode returns first six-digit code from multilingual mail text', () => {
assert.equal(extractVerificationCode('你的 ChatGPT 验证码为 370794,请勿泄露。'), '370794');
assert.equal(extractVerificationCode('Your verification code is 654321.'), '654321');
assert.equal(extractVerificationCode('ChatGPT Log-in Code\nIf that was you, enter this code:\n\n982219'), '982219');
assert.equal(extractVerificationCode('No code here'), null);
});
test('extractVerificationCode supports runtime mail rule patterns', () => {
assert.equal(
extractVerificationCode('Mailbox notice: use pin A-778899 to continue.', {
codePatterns: [{ source: 'pin\\s+A-(\\d{6})', flags: 'i' }],
}),
'778899'
);
});
test('extractVerificationCodeFromMessage reads code from the latest message subject or preview', () => {
assert.equal(
extractVerificationCodeFromMessage({
subject: '你的 ChatGPT 代码为 192742',
bodyPreview: 'OpenAI 验证邮件',
from: { emailAddress: { address: 'noreply@openai.com' } },
}),
'192742'
);
assert.equal(
extractVerificationCodeFromMessage({
subject: 'OpenAI security message',
bodyPreview: 'Your verification code is 654321.',
from: { emailAddress: { address: 'noreply@openai.com' } },
}),
'654321'
);
assert.equal(
extractVerificationCodeFromMessage({
subject: 'ChatGPT Log-in Code',
bodyPreview: 'We noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219',
from: { emailAddress: { address: 'noreply@openai.com' } },
}),
'982219'
);
});
test('pickVerificationMessageWithTimeFallback supports required keyword hints and runtime code patterns', () => {
const messages = [
{
id: 'mail-1',
subject: 'Security center',
from: { emailAddress: { address: 'alerts@example.com' } },
bodyPreview: 'Use pin A-661122 to continue',
receivedDateTime: '2026-04-14T10:06:00.000Z',
},
];
const result = pickVerificationMessageWithTimeFallback(messages, {
afterTimestamp: 0,
senderFilters: [],
subjectFilters: [],
requiredKeywords: ['security'],
codePatterns: [{ source: 'pin\\s+A-(\\d{6})', flags: 'i' }],
excludeCodes: [],
});
assert.equal(result.match?.code, '661122');
assert.equal(result.usedTimeFallback, false);
});
test('getHotmailListToggleLabel reflects expanded state and account count', () => {
assert.equal(getHotmailListToggleLabel(false, 0), '展开列表');
assert.equal(getHotmailListToggleLabel(false, 7), '展开列表(7');
assert.equal(getHotmailListToggleLabel(true, 7), '收起列表(7');
});
test('filterHotmailAccountsByUsage can pick only used accounts or return all accounts', () => {
const accounts = [
{ id: 'used-1', email: 'used-1@hotmail.com', used: true },
{ id: 'fresh-1', email: 'fresh-1@hotmail.com', used: false },
{ id: 'used-2', email: 'used-2@hotmail.com', used: true },
];
assert.deepEqual(
filterHotmailAccountsByUsage(accounts, 'used').map((account) => account.id),
['used-1', 'used-2']
);
assert.deepEqual(
filterHotmailAccountsByUsage(accounts, 'all').map((account) => account.id),
['used-1', 'fresh-1', 'used-2']
);
});
test('getHotmailBulkActionLabel reflects action type and count', () => {
assert.equal(getHotmailBulkActionLabel('used', 0), '清空已用');
assert.equal(getHotmailBulkActionLabel('used', 3), '清空已用(3');
assert.equal(getHotmailBulkActionLabel('all', 5), '全部删除(5');
});
test('getLatestHotmailMessage picks the newest received mail', () => {
const latest = getLatestHotmailMessage([
{
id: 'older',
subject: 'older',
receivedDateTime: '2026-04-11T00:01:00.000Z',
},
{
id: 'newest',
subject: 'newest',
receivedDateTime: '2026-04-11T00:05:00.000Z',
},
{
id: 'middle',
subject: 'middle',
receivedDateTime: '2026-04-11T00:03:00.000Z',
},
]);
assert.equal(latest.id, 'newest');
});
test('pickVerificationMessage filters by time, sender, subject, and excluded codes', () => {
const messages = [
{
id: 'old-mail',
subject: 'Your code is 111111',
from: { emailAddress: { address: 'noreply@openai.com' } },
bodyPreview: '111111',
receivedDateTime: '2026-04-10T09:00:00.000Z',
},
{
id: 'wrong-sender',
subject: 'Your code is 222222',
from: { emailAddress: { address: 'noreply@example.com' } },
bodyPreview: '222222',
receivedDateTime: '2026-04-10T10:01:00.000Z',
},
{
id: 'good-mail',
subject: 'ChatGPT verification code 333333',
from: { emailAddress: { address: 'noreply@openai.com' } },
bodyPreview: 'Use 333333 to continue',
receivedDateTime: '2026-04-10T10:02:00.000Z',
},
{
id: 'excluded-mail',
subject: 'ChatGPT verification code 444444',
from: { emailAddress: { address: 'noreply@openai.com' } },
bodyPreview: 'Use 444444 to continue',
receivedDateTime: '2026-04-10T10:03:00.000Z',
},
];
const match = pickVerificationMessage(messages, {
afterTimestamp: Date.UTC(2026, 3, 10, 10, 0, 0),
senderFilters: ['openai', 'noreply'],
subjectFilters: ['verification', 'code', 'chatgpt'],
excludeCodes: ['444444'],
});
assert.equal(match.message.id, 'good-mail');
assert.equal(match.code, '333333');
});
test('pickVerificationMessageWithFallback no longer matches arbitrary recent mails when filters miss', () => {
const messages = [
{
id: 'login-mail',
subject: 'Use this security code to continue 555666',
from: { emailAddress: { address: 'account-security@openai.com' } },
bodyPreview: 'Your one-time security code is 555666',
receivedDateTime: '2026-04-10T10:05:00.000Z',
},
];
const result = pickVerificationMessageWithFallback(messages, {
afterTimestamp: Date.UTC(2026, 3, 10, 10, 0, 0),
senderFilters: ['noreply'],
subjectFilters: ['verification'],
excludeCodes: [],
});
assert.equal(result.match, null);
assert.equal(result.usedRelaxedFilters, false);
assert.equal(result.usedTimeFallback, false);
});
test('pickVerificationMessageWithTimeFallback can ignore afterTimestamp while keeping sender and subject filters', () => {
const messages = [
{
id: 'slightly-old-mail',
subject: '你的 ChatGPT 代码为 141735',
from: { emailAddress: { address: 'unknown' } },
bodyPreview: 'OpenAI logo ...',
receivedDateTime: '2026-04-10T10:00:02.000Z',
},
];
const result = pickVerificationMessageWithTimeFallback(messages, {
afterTimestamp: Date.UTC(2026, 3, 10, 10, 0, 10),
senderFilters: ['openai', 'noreply'],
subjectFilters: ['verify', 'verification', 'code'],
excludeCodes: [],
});
assert.equal(result.match.message.id, 'slightly-old-mail');
assert.equal(result.match.code, '141735');
assert.equal(result.usedRelaxedFilters, false);
assert.equal(result.usedTimeFallback, true);
});
test('buildHotmailMailApiLatestUrl includes email, client id, refresh token, and mailbox', () => {
const url = new URL(buildHotmailMailApiLatestUrl({
apiUrl: 'https://example.com/api/mail-new',
clientId: 'client-123',
email: 'user@hotmail.com',
refreshToken: 'refresh-token-xyz',
mailbox: 'Junk',
}));
assert.equal(url.origin + url.pathname, 'https://example.com/api/mail-new');
assert.equal(url.searchParams.get('client_id'), 'client-123');
assert.equal(url.searchParams.get('email'), 'user@hotmail.com');
assert.equal(url.searchParams.get('refresh_token'), 'refresh-token-xyz');
assert.equal(url.searchParams.get('mailbox'), 'Junk');
assert.equal(url.searchParams.get('response_type'), 'json');
});
test('buildHotmailMailApiLatestUrl requires an explicit api url', () => {
assert.throws(
() => buildHotmailMailApiLatestUrl({ email: 'user@hotmail.com' }),
/Hotmail mail API URL is required/
);
});
test('buildHotmailMailApiLatestUrl supports custom api url and can omit response_type', () => {
const url = new URL(buildHotmailMailApiLatestUrl({
apiUrl: 'https://example.com/custom-mail-api',
clientId: 'client-789',
email: 'custom@hotmail.com',
refreshToken: 'refresh-token-custom',
mailbox: 'Spam',
responseType: '',
}));
assert.equal(url.origin + url.pathname, 'https://example.com/custom-mail-api');
assert.equal(url.searchParams.get('client_id'), 'client-789');
assert.equal(url.searchParams.get('email'), 'custom@hotmail.com');
assert.equal(url.searchParams.get('refresh_token'), 'refresh-token-custom');
assert.equal(url.searchParams.get('mailbox'), 'Spam');
assert.equal(url.searchParams.has('response_type'), false);
});
test('normalizeHotmailMailApiMessages maps third-party payload fields into verification message shape', () => {
const messages = normalizeHotmailMailApiMessages([
{
id: 'mail-1',
from: 'noreply@openai.com',
subject: 'ChatGPT verification code',
text: 'Use 135790 to continue',
date: '2026-04-10T10:02:00.000Z',
},
{
message_id: 'mail-2',
sender_email: 'alerts@example.com',
title: 'Ignored',
body: 'No code here',
received_at: '2026-04-10T10:03:00.000Z',
},
]);
assert.deepEqual(messages, [
{
id: 'mail-1',
subject: 'ChatGPT verification code',
from: { emailAddress: { address: 'noreply@openai.com' } },
bodyPreview: 'Use 135790 to continue',
receivedDateTime: '2026-04-10T10:02:00.000Z',
recipients: { to: [], cc: [], bcc: [], all: [] },
},
{
id: 'mail-2',
subject: 'Ignored',
from: { emailAddress: { address: 'alerts@example.com' } },
bodyPreview: 'No code here',
receivedDateTime: '2026-04-10T10:03:00.000Z',
recipients: { to: [], cc: [], bcc: [], all: [] },
},
]);
});
test('getHotmailVerificationPollConfig gives Hotmail a slower initial wait and longer polling window', () => {
assert.deepEqual(getHotmailVerificationPollConfig(4), {
initialDelayMs: 5000,
maxAttempts: 12,
intervalMs: 5000,
requestFreshCodeFirst: false,
ignorePersistedLastCode: true,
});
assert.deepEqual(getHotmailVerificationPollConfig(7), {
initialDelayMs: 5000,
maxAttempts: 12,
intervalMs: 5000,
requestFreshCodeFirst: false,
ignorePersistedLastCode: true,
});
});
test('getHotmailVerificationRequestTimestamp prefers actual request timestamps with a safety buffer', () => {
const signupRequestedAt = Date.UTC(2026, 3, 10, 12, 0, 30);
const loginRequestedAt = Date.UTC(2026, 3, 10, 12, 5, 45);
assert.equal(
getHotmailVerificationRequestTimestamp(4, {
signupVerificationRequestedAt: signupRequestedAt,
flowStartTime: signupRequestedAt - 60_000,
}),
signupRequestedAt - 15_000
);
assert.equal(
getHotmailVerificationRequestTimestamp(7, {
loginVerificationRequestedAt: loginRequestedAt,
lastEmailTimestamp: loginRequestedAt - 120_000,
flowStartTime: loginRequestedAt - 300_000,
}),
loginRequestedAt - 15_000
);
});
test('getHotmailMailApiRequestConfig defines third-party mail API request defaults', () => {
assert.deepEqual(getHotmailMailApiRequestConfig(), {
timeoutMs: 15000,
});
});
test('normalizeHotmailServiceMode supports API对接 remote 模式并默认回退到本地助手', () => {
assert.equal(normalizeHotmailServiceMode('remote'), 'remote');
assert.equal(normalizeHotmailServiceMode('REMOTE'), 'remote');
assert.equal(normalizeHotmailServiceMode('local'), 'local');
assert.equal(normalizeHotmailServiceMode(''), 'local');
assert.equal(normalizeHotmailServiceMode('unknown'), 'local');
});
test('parseHotmailImportText parses account lines in email----password----clientId----token format', () => {
const parsed = parseHotmailImportText(`
账号----密码----ID----Token
JohnRodriguez5425@hotmail.com----nb4ta1OK----9e5f94bc-e8a4-4e73-b8be-63364c29d753----refresh-token-1
alice@hotmail.com----pass-2----client-2----refresh-token-2
`.trim());
assert.deepEqual(parsed, [
{
email: 'JohnRodriguez5425@hotmail.com',
password: 'nb4ta1OK',
clientId: '9e5f94bc-e8a4-4e73-b8be-63364c29d753',
refreshToken: 'refresh-token-1',
},
{
email: 'alice@hotmail.com',
password: 'pass-2',
clientId: 'client-2',
refreshToken: 'refresh-token-2',
},
]);
});