From 047f4e126981ec5254461e05c32edeebb80a06a2 Mon Sep 17 00:00:00 2001 From: QLHazyCoder <2825305047@qq.com> Date: Fri, 1 May 2026 00:18:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=8F=90=E5=8F=96?= =?UTF-8?q?=E5=92=8C=E9=AA=8C=E8=AF=81ChatGPT=E7=99=BB=E5=BD=95=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/mail-2925.js | 86 ++++++++++++++++++++++++++++++--- tests/mail-2925-content.test.js | 30 ++++++++++++ 2 files changed, 108 insertions(+), 8 deletions(-) diff --git a/content/mail-2925.js b/content/mail-2925.js index d2ba01a..7420988 100644 --- a/content/mail-2925.js +++ b/content/mail-2925.js @@ -668,12 +668,85 @@ function matchesMailFilters(text, senderFilters, subjectFilters) { return senderMatch || subjectMatch; } -function extractVerificationCode(text, strictChatGPTCodeOnly = false) { - if (strictChatGPTCodeOnly) { - const strictMatch = String(text || '').match(/(?:your\s+chatgpt\s+code\s+is|(?:chatgpt\s+log-?in\s+code|suspicious\s+log-?in)[\s\S]{0,120}enter\s+this\s+code)[^0-9]{0,24}(\d{6})/i); - return strictMatch ? strictMatch[1] : null; +function extractStrictChatGPTVerificationCode(text) { + const normalized = String(text || ''); + const patterns = [ + /your\s+(?:temporary\s+)?chatgpt\s+(?:(?:log-?in|login)\s+)?code\s+is[\s\S]{0,80}?(\d{6})/i, + /(?:chatgpt\s+log-?in\s+code|suspicious\s+log-?in)[\s\S]{0,200}?enter\s+this\s+code[\s\S]{0,80}?(\d{6})/i, + /enter\s+this\s+code[\s\S]{0,80}?(\d{6})/i, + ]; + + for (const pattern of patterns) { + const match = normalized.match(pattern); + if (match) return match[1]; } + return null; +} + +function isLikelyCompactTimeValue(value = '') { + const text = String(value || ''); + if (!/^\d{6}$/.test(text)) return false; + + const hours = Number(text.slice(0, 2)); + const minutes = Number(text.slice(2, 4)); + const seconds = Number(text.slice(4, 6)); + return hours >= 0 && hours <= 23 + && minutes >= 0 && minutes <= 59 + && seconds >= 0 && seconds <= 59; +} + +function isLikelyHeaderTimestampCode(text, index, value) { + const source = String(text || ''); + const candidate = String(value || ''); + if (!candidate) return false; + + const before = source.slice(Math.max(0, index - 80), index); + const after = source.slice(index + candidate.length, index + candidate.length + 40); + const context = `${before}${candidate}${after}`.replace(/\s+/g, ' '); + const beforeCompact = before.replace(/\s+/g, ' '); + const timeLike = isLikelyCompactTimeValue(candidate); + + if ( + timeLike + && /(?:\d{4}[-/.]\d{1,2}[-/.]\d{1,2}|\d{1,2}[-/.]\d{1,2})\s*$/.test(beforeCompact) + ) { + return true; + } + + if ( + timeLike + && /(?:\d{4}[-/.]\d{1,2}[-/.]\d{1,2}|\d{1,2}[-/.]\d{1,2})\s*(?:\d{1,2}:\d{2}(?::\d{2})?|\d{6})/.test(context) + ) { + return true; + } + + return /(?:time|date|sent|received|received\s+at|sent\s+at|\u65f6\s*\u95f4|\u65e5\s*\u671f)[\s:\uFF1A-]*$/i.test(beforeCompact) + && (timeLike || /^20\d{4}$/.test(candidate)); +} + +function findSafeStandaloneSixDigitCode(text) { + const normalized = String(text || ''); + const pattern = /\b(\d{6})\b/g; + let match = null; + + while ((match = pattern.exec(normalized)) !== null) { + const candidate = match[1]; + if (!isLikelyHeaderTimestampCode(normalized, match.index, candidate)) { + return candidate; + } + } + + return null; +} + +function extractVerificationCode(text, strictChatGPTCodeOnly = false) { + const strictCode = extractStrictChatGPTVerificationCode(text); + if (strictChatGPTCodeOnly) { + return strictCode; + } + if (strictCode) return strictCode; + const normalized = String(text || ''); const matchCn = normalized.match(/(?:代码为|验证码[^0-9]*?)[\s::]*(\d{6})/); @@ -688,10 +761,7 @@ function extractVerificationCode(text, strictChatGPTCodeOnly = false) { const matchEn = normalized.match(/code[:\s]+is[:\s]+(\d{6})|code[:\s]+(\d{6})/i); if (matchEn) return matchEn[1] || matchEn[2]; - const match6 = normalized.match(/\b(\d{6})\b/); - if (match6) return match6[1]; - - return null; + return findSafeStandaloneSixDigitCode(normalized); } function extractEmails(text = '') { diff --git a/tests/mail-2925-content.test.js b/tests/mail-2925-content.test.js index c824ee0..d212144 100644 --- a/tests/mail-2925-content.test.js +++ b/tests/mail-2925-content.test.js @@ -549,6 +549,10 @@ return { test('extractVerificationCode strict mode matches the new suspicious log-in mail body', () => { const bundle = [ + extractFunction('extractStrictChatGPTVerificationCode'), + extractFunction('isLikelyCompactTimeValue'), + extractFunction('isLikelyHeaderTimestampCode'), + extractFunction('findSafeStandaloneSixDigitCode'), extractFunction('extractVerificationCode'), ].join('\n'); @@ -562,6 +566,32 @@ return { extractVerificationCode }; assert.equal(api.extractVerificationCode(bodyText, false), '982219'); }); +test('extractVerificationCode ignores compact header time before fallback code', () => { + const bundle = [ + extractFunction('extractStrictChatGPTVerificationCode'), + extractFunction('isLikelyCompactTimeValue'), + extractFunction('isLikelyHeaderTimestampCode'), + extractFunction('findSafeStandaloneSixDigitCode'), + extractFunction('extractVerificationCode'), + ].join('\n'); + + const api = new Function(` +${bundle} +return { extractVerificationCode }; +`)(); + + const bodyText = [ + 'Your temporary ChatGPT login code', + 'From: otp ', + 'To: test@example.com', + 'Time: 2026-4-22 101755', + 'OpenAI', + '371138', + ].join('\n'); + + assert.equal(api.extractVerificationCode(bodyText, false), '371138'); +}); + test('openMailAndGetMessageText always returns to inbox after opening a 2925 message', async () => { const bundle = [ extractFunction('returnToInbox'),