From bf7d37e4da1085f438bab9f58c15be49d1139e50 Mon Sep 17 00:00:00 2001 From: QLHazyCoder <2825305047@qq.com> Date: Thu, 28 May 2026 12:41:57 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DHeroSMS=E8=BF=90?= =?UTF-8?q?=E8=90=A5=E5=95=86=E4=B8=8E=E6=8E=A5=E7=A0=81=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- background.js | 20 ++ background/phone-verification-flow.js | 129 +++++++++- sidepanel/sidepanel.html | 9 + sidepanel/sidepanel.js | 226 ++++++++++++++++++ ...ackground-account-history-settings.test.js | 4 + tests/phone-verification-flow.test.js | 218 +++++++++++++++++ ...epanel-phone-verification-settings.test.js | 35 +++ 7 files changed, 632 insertions(+), 9 deletions(-) diff --git a/background.js b/background.js index 71fd75b..5178673 100644 --- a/background.js +++ b/background.js @@ -693,6 +693,7 @@ const HERO_SMS_SERVICE_CODE = 'dr'; const HERO_SMS_SERVICE_LABEL = 'OpenAI'; const HERO_SMS_COUNTRY_ID = 52; const HERO_SMS_COUNTRY_LABEL = 'Thailand'; +const DEFAULT_HERO_SMS_OPERATOR = 'any'; const PHONE_SMS_PROVIDER_HERO = 'hero-sms'; const PHONE_SMS_PROVIDER_5SIM = '5sim'; const PHONE_SMS_PROVIDER_HERO_SMS = PHONE_SMS_PROVIDER_HERO; @@ -1457,6 +1458,7 @@ const PERSISTED_SETTING_DEFAULTS = { heroSmsApiKey: '', heroSmsReuseEnabled: DEFAULT_HERO_SMS_REUSE_ENABLED, heroSmsAcquirePriority: DEFAULT_HERO_SMS_ACQUIRE_PRIORITY, + heroSmsOperator: DEFAULT_HERO_SMS_OPERATOR, heroSmsMinPrice: '', heroSmsMaxPrice: '', heroSmsPreferredPrice: '', @@ -1790,6 +1792,21 @@ function normalizeHeroSmsAcquirePriority(value = '') { return HERO_SMS_ACQUIRE_PRIORITY_COUNTRY; } +function normalizeHeroSmsOperator(value = '', fallback = DEFAULT_HERO_SMS_OPERATOR) { + const normalized = String(value || '') + .trim() + .toLowerCase() + .replace(/[^a-z0-9_-]+/g, ''); + if (normalized) { + return normalized; + } + const fallbackNormalized = String(fallback || '') + .trim() + .toLowerCase() + .replace(/[^a-z0-9_-]+/g, ''); + return fallbackNormalized || DEFAULT_HERO_SMS_OPERATOR; +} + function normalizeHeroSmsCountryFallback(value = []) { const source = Array.isArray(value) ? value @@ -3548,6 +3565,8 @@ function normalizePersistentSettingValue(key, value) { return Boolean(value); case 'heroSmsAcquirePriority': return normalizeHeroSmsAcquirePriority(value); + case 'heroSmsOperator': + return normalizeHeroSmsOperator(value); case 'heroSmsMinPrice': case 'heroSmsMaxPrice': return normalizeHeroSmsMaxPrice(value); @@ -13690,6 +13709,7 @@ const phoneVerificationHelpers = self.MultiPageBackgroundPhoneVerification?.crea DEFAULT_NEX_SMS_COUNTRY_ORDER, DEFAULT_NEX_SMS_SERVICE_CODE, DEFAULT_HERO_SMS_BASE_URL, + DEFAULT_HERO_SMS_OPERATOR, DEFAULT_HERO_SMS_REUSE_ENABLED, DEFAULT_PHONE_CODE_WAIT_SECONDS, DEFAULT_PHONE_CODE_TIMEOUT_WINDOWS, diff --git a/background/phone-verification-flow.js b/background/phone-verification-flow.js index 08141ef..7f10099 100644 --- a/background/phone-verification-flow.js +++ b/background/phone-verification-flow.js @@ -23,6 +23,7 @@ DEFAULT_FIVE_SIM_BASE_URL = 'https://5sim.net/v1', DEFAULT_FIVE_SIM_PRODUCT = 'openai', DEFAULT_FIVE_SIM_OPERATOR = 'any', + DEFAULT_HERO_SMS_OPERATOR = 'any', DEFAULT_FIVE_SIM_COUNTRY_ORDER = ['thailand'], DEFAULT_NEX_SMS_BASE_URL = 'https://api.nexsms.net', DEFAULT_NEX_SMS_COUNTRY_ORDER = [1], @@ -548,6 +549,21 @@ return String(value || '').trim() || fallback; } + function normalizeHeroSmsOperator(value = '', fallback = DEFAULT_HERO_SMS_OPERATOR) { + const normalized = String(value || '') + .trim() + .toLowerCase() + .replace(/[^a-z0-9_-]+/g, ''); + if (normalized) { + return normalized; + } + const fallbackNormalized = String(fallback || '') + .trim() + .toLowerCase() + .replace(/[^a-z0-9_-]+/g, ''); + return fallbackNormalized || DEFAULT_HERO_SMS_OPERATOR; + } + function inferHeroSmsCountryFromPhoneNumber(phoneNumber = '') { const digits = String(phoneNumber || '').replace(/\D+/g, ''); if (!digits) { @@ -927,6 +943,17 @@ return normalizePhoneSmsProvider(activation?.provider || state?.phoneSmsProvider); } + function scopeStateToActivationProvider(state = {}, activation = {}) { + const provider = getActivationProviderId(activation, state); + if (!provider) { + return state || {}; + } + return { + ...(state || {}), + phoneSmsProvider: provider, + }; + } + function getPhoneSmsProviderLabel(providerId) { const provider = normalizePhoneSmsProvider(providerId); if (provider === PHONE_SMS_PROVIDER_FIVE_SIM) { @@ -2100,6 +2127,7 @@ provider, apiKey, baseUrl: normalizeUrl(state.heroSmsBaseUrl, DEFAULT_HERO_SMS_BASE_URL), + operator: normalizeHeroSmsOperator(state.heroSmsOperator, DEFAULT_HERO_SMS_OPERATOR), countryCandidates: resolveCountryCandidates(state), }; } @@ -2113,10 +2141,82 @@ provider: PHONE_SMS_PROVIDER_HERO, apiKey, baseUrl: normalizeUrl(state.heroSmsBaseUrl, DEFAULT_HERO_SMS_BASE_URL), + operator: normalizeHeroSmsOperator(state.heroSmsOperator, DEFAULT_HERO_SMS_OPERATOR), countryCandidates: resolveCountryCandidates(state), }; } + const LATEST_PHONE_SETTING_KEYS = Object.freeze([ + 'phoneSmsProvider', + 'phoneSmsProviderOrder', + 'phoneSmsReuseEnabled', + 'heroSmsApiKey', + 'heroSmsBaseUrl', + 'heroSmsCountryId', + 'heroSmsCountryLabel', + 'heroSmsCountryFallback', + 'heroSmsAcquirePriority', + 'heroSmsOperator', + 'heroSmsMinPrice', + 'heroSmsMaxPrice', + 'heroSmsPreferredPrice', + 'heroSmsActivationRetryRounds', + 'heroSmsActivationRetryDelayMs', + 'fiveSimApiKey', + 'fiveSimBaseUrl', + 'fiveSimCountryId', + 'fiveSimCountryLabel', + 'fiveSimCountryFallback', + 'fiveSimCountryOrder', + 'fiveSimOperator', + 'fiveSimProduct', + 'fiveSimMinPrice', + 'fiveSimMaxPrice', + 'nexSmsApiKey', + 'nexSmsBaseUrl', + 'nexSmsCountryOrder', + 'nexSmsServiceCode', + 'phoneVerificationReplacementLimit', + 'phoneCodeWaitSeconds', + 'phoneCodeTimeoutWindows', + 'phoneCodePollIntervalSeconds', + 'phoneCodePollMaxRounds', + 'freePhoneReuseEnabled', + 'freePhoneReuseAutoEnabled', + ]); + + async function mergeLatestPhoneSettingsState(state = {}, options = {}) { + if (typeof getState !== 'function') { + return state || {}; + } + try { + const latestState = await getState(); + if (!latestState || typeof latestState !== 'object') { + return state || {}; + } + const mergedState = { + ...latestState, + ...(state || {}), + }; + const preservePhoneSmsProvider = Boolean(options?.preservePhoneSmsProvider); + LATEST_PHONE_SETTING_KEYS.forEach((key) => { + if (preservePhoneSmsProvider && key === 'phoneSmsProvider') { + return; + } + if (Object.prototype.hasOwnProperty.call(latestState, key)) { + mergedState[key] = latestState[key]; + } + }); + mergedState.heroSmsOperator = normalizeHeroSmsOperator( + mergedState.heroSmsOperator, + DEFAULT_HERO_SMS_OPERATOR + ); + return mergedState; + } catch (_) { + return state || {}; + } + } + function parseActivationPayload(payload, fallback = null) { const normalizedFallback = normalizeActivation(fallback) || normalizeActivationFallback(fallback); const directActivation = normalizeActivation(payload); @@ -2537,6 +2637,10 @@ service: HERO_SMS_SERVICE_CODE, country: countryConfig.id, }; + const operator = normalizeHeroSmsOperator(config?.operator, DEFAULT_HERO_SMS_OPERATOR); + if (operator && operator !== DEFAULT_HERO_SMS_OPERATOR) { + query.operator = operator; + } if (options.maxPrice !== null && options.maxPrice !== undefined) { query.maxPrice = options.maxPrice; if (options.fixedPrice !== false) { @@ -3584,6 +3688,9 @@ } async function requestPhoneActivation(state = {}, options = {}) { + state = await mergeLatestPhoneSettingsState(state, { + preservePhoneSmsProvider: Boolean(options?.preservePhoneSmsProvider), + }); if (normalizePhoneSmsProvider(state?.phoneSmsProvider) === PHONE_SMS_PROVIDER_FIVE_SIM) { const provider = getFiveSimProviderForState(state); if (provider) { @@ -3931,11 +4038,12 @@ if (getActivationProviderId(normalizedActivation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) { const provider = getFiveSimProviderForState(state); if (provider) { - return provider.reuseActivation(state, normalizedActivation); + return provider.reuseActivation(scopeStateToActivationProvider(state, normalizedActivation), normalizedActivation); } } - const config = resolvePhoneConfig(state); + const scopedState = scopeStateToActivationProvider(state, normalizedActivation); + const config = resolvePhoneConfig(scopedState); if (config.provider === PHONE_SMS_PROVIDER_5SIM) { const payload = await fetchFiveSimPayload( config, @@ -3980,7 +4088,7 @@ ); return `free reuse setStatus(${normalizedStatus}) skipped`; } - const config = resolvePhoneConfig(state); + const config = resolvePhoneConfig(scopeStateToActivationProvider(state, normalizedActivation)); if (config.provider === PHONE_SMS_PROVIDER_5SIM) { const endpoint = normalizedStatus === 6 ? `/user/finish/${normalizedActivation.activationId}` @@ -4029,7 +4137,7 @@ if (getActivationProviderId(activation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) { const provider = getFiveSimProviderForState(state); if (provider) { - await provider.finishActivation(state, activation); + await provider.finishActivation(scopeStateToActivationProvider(state, activation), activation); return; } } @@ -4050,7 +4158,7 @@ if (getActivationProviderId(activation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) { const provider = getFiveSimProviderForState(state); if (provider) { - await provider.cancelActivation(state, activation); + await provider.cancelActivation(scopeStateToActivationProvider(state, activation), activation); return; } } @@ -4151,7 +4259,7 @@ if (getActivationProviderId(activation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) { const provider = getFiveSimProviderForState(state); if (provider) { - await provider.banActivation(state, activation); + await provider.banActivation(scopeStateToActivationProvider(state, activation), activation); return; } } @@ -4162,7 +4270,7 @@ } async function requestAdditionalPhoneSms(state = {}, activation) { - const config = resolvePhoneConfig(state); + const config = resolvePhoneConfig(scopeStateToActivationProvider(state, activation)); if (config.provider !== PHONE_SMS_PROVIDER_HERO) { return; } @@ -4342,12 +4450,13 @@ if (getActivationProviderId(normalizedActivation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) { const provider = getFiveSimProviderForState(state); if (provider) { - return provider.pollActivationCode(state, normalizedActivation, options); + return provider.pollActivationCode(scopeStateToActivationProvider(state, normalizedActivation), normalizedActivation, options); } } const statusAction = resolveActivationStatusAction(normalizedActivation); - const config = resolvePhoneConfig(state); + const scopedState = scopeStateToActivationProvider(state, normalizedActivation); + const config = resolvePhoneConfig(scopedState); const configuredTimeoutMs = Math.max(1000, Number(options.timeoutMs) || 0); const timeoutMs = configuredTimeoutMs || ( typeof getOAuthFlowStepTimeoutMs === 'function' @@ -5101,6 +5210,7 @@ } async function acquirePhoneActivation(state = {}, options = {}) { + state = await mergeLatestPhoneSettingsState(state); const provider = normalizePhoneSmsProvider(state?.phoneSmsProvider || DEFAULT_PHONE_SMS_PROVIDER); const providerOrder = resolvePhoneProviderOrder(state, provider); const countryCandidates = resolveCountryCandidatesForProvider(state, provider); @@ -5261,6 +5371,7 @@ { blockedCountryIds: useBlockedCountryIds, countryPriceFloorByCountryId: useCountryPriceFloorByCountryId, + preservePhoneSmsProvider: true, } ); const providerLabel = getPhoneSmsProviderLabel(providerCandidate); diff --git a/sidepanel/sidepanel.html b/sidepanel/sidepanel.html index 26dcee2..e35dc8d 100644 --- a/sidepanel/sidepanel.html +++ b/sidepanel/sidepanel.html @@ -1536,6 +1536,15 @@ +