feat: auto rotate phone on detected errors

This commit is contained in:
chick
2026-05-31 16:28:53 +08:00
parent a9c7cf4ae1
commit f4288bc939
3 changed files with 106 additions and 13 deletions
+16 -1
View File
@@ -25,7 +25,7 @@ function load(extra = {}) {
Set,
...extra,
};
const fn = new Function('globalThis', 'self', `with (globalThis) { ${source}; return { collectPriceEntries, filterPriceEntries, normalizeActivation, extractVerificationCode, isPhoneNumberUsedError, isPhoneNumberDeliveryRefusedError, getPhoneReplacementReleaseAction, fetchNextPhone, normalizeSettings }; }`);
const fn = new Function('globalThis', 'self', `with (globalThis) { ${source}; return { collectPriceEntries, filterPriceEntries, normalizeActivation, extractVerificationCode, isPhoneNumberUsedError, isPhoneNumberDeliveryRefusedError, getPhoneReplacementReleaseAction, fetchNextPhone, normalizeSettings, buildUrl }; }`);
return fn(sandbox, sandbox);
}
test('collectPriceEntries parses keyed price inventory', () => {
@@ -53,10 +53,25 @@ test('extractVerificationCode parses STATUS_OK response', () => {
test('FlowPilot-style phone failure classifiers choose release action', () => {
const api = load();
assert.equal(api.isPhoneNumberUsedError('该电话已被使用,请换一个号码'), true);
assert.equal(api.isPhoneNumberUsedError('手机号已绑定,请换一个号码'), true);
assert.equal(api.isPhoneNumberDeliveryRefusedError('无法向此电话号码发送验证码'), true);
assert.equal(api.getPhoneReplacementReleaseAction('phone_number_used'), 'ban');
assert.equal(api.getPhoneReplacementReleaseAction('phone_delivery_refused'), 'cancel');
});
test('buildUrl keeps api_key and replacement queries explicit', () => {
const api = load();
const url = new URL(api.buildUrl(
{ baseUrl: 'https://smsbower.app/stubs/handler_api.php', apiKey: 'demo-key' },
{ action: 'getNumberV2', service: 'dr', country: 6, maxPrice: 0.2 }
));
assert.equal(url.searchParams.get('api_key'), 'demo-key');
assert.equal(url.searchParams.get('action'), 'getNumberV2');
assert.equal(url.searchParams.get('service'), 'dr');
assert.equal(url.searchParams.get('country'), '6');
assert.equal(url.searchParams.get('maxPrice'), '0.2');
});
test('fetchNextPhone releases previous activation then acquires replacement', async () => {
const requests = [];
const stored = {