初始化提交:go比特版本精简
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const {
|
||||
classifyRefundSubjects,
|
||||
mapLoginFailureToRefundStatus,
|
||||
retryPageOperation,
|
||||
_private,
|
||||
} = require('../src/services/refund_query_service');
|
||||
|
||||
(async () => {
|
||||
assert.deepStrictEqual(
|
||||
classifyRefundSubjects(['Your refund from OpenAI OpCo, LLC #3877-6793']).status,
|
||||
'已退款',
|
||||
);
|
||||
assert.strictEqual(
|
||||
classifyRefundSubjects(['OpenAI ChatGPT - Usage Policy Violation & Deactivation Warning [C-123]']).status,
|
||||
'gpt警告',
|
||||
);
|
||||
assert.strictEqual(
|
||||
classifyRefundSubjects(['OpenAI - Access Deactivated [C-456]']).status,
|
||||
'gpt封号退款失败',
|
||||
);
|
||||
assert.strictEqual(
|
||||
classifyRefundSubjects(['您收到了一笔来自 OpenAI OpCo, LLC 的退款 #3877-6793']).status,
|
||||
'已退款',
|
||||
'中文退款标题必须识别',
|
||||
);
|
||||
assert.strictEqual(
|
||||
classifyRefundSubjects(['OpenAI ChatGPT - 使用政策违规和停用警告 [C-123]']).status,
|
||||
'gpt警告',
|
||||
'中文违规警告标题必须识别',
|
||||
);
|
||||
assert.strictEqual(
|
||||
classifyRefundSubjects(['OpenAI - 您的访问权限已停用 [C-456]']).status,
|
||||
'gpt封号退款失败',
|
||||
'中文访问停用标题必须识别',
|
||||
);
|
||||
assert.strictEqual(
|
||||
classifyRefundSubjects(['OpenAI API - 访问权限已停用 [C-bOXrf90AwRpd]']).status,
|
||||
'gpt封号退款失败',
|
||||
'OpenAI API 中文访问停用标题必须识别',
|
||||
);
|
||||
assert.strictEqual(
|
||||
classifyRefundSubjects(['OpenAI - 访问权限已停用 [C-eizUkbcm0bCv]']).status,
|
||||
'gpt封号退款失败',
|
||||
'OpenAI 中文访问停用标题必须识别',
|
||||
);
|
||||
assert.strictEqual(
|
||||
classifyRefundSubjects([
|
||||
'OpenAI ChatGPT - Usage Policy Violation & Deactivation Warning',
|
||||
'OpenAI - Access Deactivated',
|
||||
]).status,
|
||||
'gpt封号退款失败',
|
||||
);
|
||||
assert.strictEqual(
|
||||
classifyRefundSubjects([
|
||||
'OpenAI ChatGPT - Usage Policy Violation & Deactivation Warning',
|
||||
'OpenAI - Access Deactivated',
|
||||
'Your refund from OpenAI OpCo #1234',
|
||||
]).status,
|
||||
'已退款',
|
||||
'退款邮件必须拥有最高优先级',
|
||||
);
|
||||
assert.strictEqual(classifyRefundSubjects(['ChatGPT - Your new plan']).status, null);
|
||||
|
||||
assert.strictEqual(mapLoginFailureToRefundStatus('Wrong password', { code: 'PASSWORD_WRONG' }), '已被改密无法查询');
|
||||
assert.strictEqual(mapLoginFailureToRefundStatus('2fa密钥不正确', { code: 'TOTP_KEY_INCORRECT' }), '已被改2FA无法查询');
|
||||
assert.strictEqual(mapLoginFailureToRefundStatus("Confirm you’re not a robot", { code: 'CAPTCHA' }), '需要手机号查询');
|
||||
assert.strictEqual(mapLoginFailureToRefundStatus('账号已被锁定/封停', { code: 'ACCOUNT_LOCKED' }), 'google封号无法查询');
|
||||
assert.strictEqual(mapLoginFailureToRefundStatus('页面加载失败', { code: 'NETWORK_PROXY' }), null);
|
||||
|
||||
let attempts = 0;
|
||||
const retryLogs = [];
|
||||
const retryResult = await retryPageOperation(async () => {
|
||||
attempts++;
|
||||
if (attempts < 4) throw new Error('页面尚未加载');
|
||||
return 'ok';
|
||||
}, {
|
||||
maxRetries: 3,
|
||||
onRetry: async info => retryLogs.push(info.retry),
|
||||
});
|
||||
assert.strictEqual(retryResult, 'ok');
|
||||
assert.strictEqual(attempts, 4, '首次访问失败后应最多再重试3次');
|
||||
assert.deepStrictEqual(retryLogs, [1, 2, 3]);
|
||||
|
||||
let captchaAttempts = 0;
|
||||
await assert.rejects(
|
||||
retryPageOperation(async () => {
|
||||
captchaAttempts++;
|
||||
const error = new Error('captcha');
|
||||
error.code = 'CAPTCHA';
|
||||
throw error;
|
||||
}, {
|
||||
maxRetries: 3,
|
||||
shouldRetry: error => error.code !== 'CAPTCHA',
|
||||
}),
|
||||
/captcha/,
|
||||
);
|
||||
assert.strictEqual(captchaAttempts, 1, '人机验证不是页面访问失败,不应重复提交');
|
||||
assert.strictEqual(_private.PAGE_RETRY_COUNT, 3);
|
||||
|
||||
{
|
||||
const emptyLocator = {
|
||||
count: async () => 0,
|
||||
nth() { return this; },
|
||||
first() { return this; },
|
||||
isVisible: async () => false,
|
||||
innerText: async () => '',
|
||||
};
|
||||
const directPasswordPage = {
|
||||
url: () => 'https://accounts.google.com/v3/signin/challenge/pwd?continue=https%3A%2F%2Fmail.google.com',
|
||||
locator: selector => selector === 'body' ? { innerText: async () => 'Welcome Enter your password Show password Next' } : emptyLocator,
|
||||
waitForTimeout: async () => {},
|
||||
};
|
||||
assert.strictEqual(
|
||||
await _private.waitForPostAccountSelectionState(directPasswordPage, 10),
|
||||
'password',
|
||||
'点击已保存账号后直接出现的密码页必须等待并识别,不能重新跳回账号选择页',
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const subjects = ['OpenAI ChatGPT - 使用政策违规和停用警告 [C-中文]'];
|
||||
const emptySubjectLocator = { allTextContents: async () => [] };
|
||||
const inboxPage = {
|
||||
locator: selector => selector === 'tr.zA span.bog'
|
||||
? { allTextContents: async () => subjects }
|
||||
: emptySubjectLocator,
|
||||
evaluate: async () => false,
|
||||
waitForTimeout: async () => {},
|
||||
};
|
||||
const direct = await _private.classifyCurrentInbox(inboxPage);
|
||||
assert.strictEqual(direct.status, 'gpt警告', '搜索前应直接扫描当前收件箱标题');
|
||||
}
|
||||
|
||||
function pageWithText(text, { signedOutButton = false } = {}) {
|
||||
let clicked = false;
|
||||
const emptyLocator = {
|
||||
count: async () => 0,
|
||||
nth() { return this; },
|
||||
first() { return this; },
|
||||
isVisible: async () => false,
|
||||
innerText: async () => '',
|
||||
};
|
||||
const buttonLocator = {
|
||||
count: async () => signedOutButton ? 1 : 0,
|
||||
nth() { return this; },
|
||||
first() { return this; },
|
||||
isVisible: async () => signedOutButton,
|
||||
click: async () => { clicked = true; },
|
||||
waitFor: async () => {},
|
||||
innerText: async () => 'Try again',
|
||||
};
|
||||
const page = {
|
||||
url: () => 'https://accounts.google.com/',
|
||||
locator(selector) {
|
||||
if (selector === 'body') return { innerText: async () => text };
|
||||
if (/Try again/.test(selector)) return buttonLocator;
|
||||
return emptyLocator;
|
||||
},
|
||||
waitForLoadState: async () => {},
|
||||
waitForTimeout: async () => {},
|
||||
wasClicked: () => clicked,
|
||||
};
|
||||
return page;
|
||||
}
|
||||
|
||||
const restrictedPage = pageWithText(
|
||||
'Review service restriction Access to a service or feature has been restricted. Gmail Entire service unavailable',
|
||||
);
|
||||
assert.strictEqual(await _private.isGmailServiceRestricted(restrictedPage), true);
|
||||
|
||||
const signedOutPage = pageWithText(
|
||||
"You're not signed in Your session ended because there was no activity. Try signing in again. Try again",
|
||||
{ signedOutButton: true },
|
||||
);
|
||||
const signedOutProgress = [];
|
||||
assert.strictEqual(
|
||||
await _private.handleSignedOutSessionGate(signedOutPage, () => {}, message => signedOutProgress.push(message)),
|
||||
true,
|
||||
);
|
||||
assert.strictEqual(signedOutPage.wasClicked(), true, '会话结束页必须点击 Try again');
|
||||
assert.match(signedOutProgress.join(' '), /Try again/);
|
||||
|
||||
const root = path.join(__dirname, '..');
|
||||
const html = fs.readFileSync(path.join(root, 'public', 'index.html'), 'utf8');
|
||||
const app = fs.readFileSync(path.join(root, 'public', 'app.js'), 'utf8');
|
||||
const recipes = fs.readFileSync(path.join(root, 'src', 'pipeline', 'recipes.js'), 'utf8');
|
||||
const operations = fs.readFileSync(path.join(root, 'src', 'routes', 'operations.js'), 'utf8');
|
||||
const runner = fs.readFileSync(path.join(root, 'src', 'workers', 'task_runner.js'), 'utf8');
|
||||
const refundService = fs.readFileSync(path.join(root, 'src', 'services', 'refund_query_service.js'), 'utf8');
|
||||
assert.match(
|
||||
refundService,
|
||||
/allowIapChallengeContinuation:\s*true/,
|
||||
'退款查询必须允许 IAP 页面继续按实际元素处理',
|
||||
);
|
||||
|
||||
const planButton = html.indexOf('runOpenAIQueryPlan()');
|
||||
const refundButton = html.indexOf('runRefundQuery()');
|
||||
const rechargeButton = html.indexOf('openRechargeModal()');
|
||||
assert(planButton >= 0 && refundButton > planButton && rechargeButton > refundButton, '查询退款按钮应位于查询套餐右侧');
|
||||
assert.match(app, /runRefundQuery\(\)\s*\{\s*this\.runTask\('refund_query'\);/);
|
||||
assert.match(recipes, /refund_query:\s*\[refundQueryStep\]/);
|
||||
assert.match(operations, /updateAccountRefundStatus:\s*\(args\)\s*=>\s*db\.updateAccountRefundStatus/);
|
||||
assert.match(operations, /account_refund_status:/);
|
||||
assert.match(runner, /taskType === 'refund_query'/);
|
||||
assert.match(runner, /taskType === 'refund_query' \? '等待查询退款\.\.\.'/);
|
||||
assert.match(runner, /shouldRotateProxyForFailure\(directMeta/);
|
||||
assert.match(
|
||||
refundService,
|
||||
/const inboxClassified = await classifyCurrentInbox\(page\);[\s\S]*if \(inboxClassified\.status\)[\s\S]*无需搜索[\s\S]*searchOpenAIWithRetry\(page/,
|
||||
'必须先扫描当前收件箱,未命中时才执行 openai 搜索',
|
||||
);
|
||||
|
||||
console.log('refund_query_feature.test.js: PASS');
|
||||
})().catch(error => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
Reference in New Issue
Block a user