fix: 修复HeroSMS运营商与接码配置刷新
This commit is contained in:
@@ -693,6 +693,7 @@ const HERO_SMS_SERVICE_CODE = 'dr';
|
|||||||
const HERO_SMS_SERVICE_LABEL = 'OpenAI';
|
const HERO_SMS_SERVICE_LABEL = 'OpenAI';
|
||||||
const HERO_SMS_COUNTRY_ID = 52;
|
const HERO_SMS_COUNTRY_ID = 52;
|
||||||
const HERO_SMS_COUNTRY_LABEL = 'Thailand';
|
const HERO_SMS_COUNTRY_LABEL = 'Thailand';
|
||||||
|
const DEFAULT_HERO_SMS_OPERATOR = 'any';
|
||||||
const PHONE_SMS_PROVIDER_HERO = 'hero-sms';
|
const PHONE_SMS_PROVIDER_HERO = 'hero-sms';
|
||||||
const PHONE_SMS_PROVIDER_5SIM = '5sim';
|
const PHONE_SMS_PROVIDER_5SIM = '5sim';
|
||||||
const PHONE_SMS_PROVIDER_HERO_SMS = PHONE_SMS_PROVIDER_HERO;
|
const PHONE_SMS_PROVIDER_HERO_SMS = PHONE_SMS_PROVIDER_HERO;
|
||||||
@@ -1457,6 +1458,7 @@ const PERSISTED_SETTING_DEFAULTS = {
|
|||||||
heroSmsApiKey: '',
|
heroSmsApiKey: '',
|
||||||
heroSmsReuseEnabled: DEFAULT_HERO_SMS_REUSE_ENABLED,
|
heroSmsReuseEnabled: DEFAULT_HERO_SMS_REUSE_ENABLED,
|
||||||
heroSmsAcquirePriority: DEFAULT_HERO_SMS_ACQUIRE_PRIORITY,
|
heroSmsAcquirePriority: DEFAULT_HERO_SMS_ACQUIRE_PRIORITY,
|
||||||
|
heroSmsOperator: DEFAULT_HERO_SMS_OPERATOR,
|
||||||
heroSmsMinPrice: '',
|
heroSmsMinPrice: '',
|
||||||
heroSmsMaxPrice: '',
|
heroSmsMaxPrice: '',
|
||||||
heroSmsPreferredPrice: '',
|
heroSmsPreferredPrice: '',
|
||||||
@@ -1790,6 +1792,21 @@ function normalizeHeroSmsAcquirePriority(value = '') {
|
|||||||
return HERO_SMS_ACQUIRE_PRIORITY_COUNTRY;
|
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 = []) {
|
function normalizeHeroSmsCountryFallback(value = []) {
|
||||||
const source = Array.isArray(value)
|
const source = Array.isArray(value)
|
||||||
? value
|
? value
|
||||||
@@ -3548,6 +3565,8 @@ function normalizePersistentSettingValue(key, value) {
|
|||||||
return Boolean(value);
|
return Boolean(value);
|
||||||
case 'heroSmsAcquirePriority':
|
case 'heroSmsAcquirePriority':
|
||||||
return normalizeHeroSmsAcquirePriority(value);
|
return normalizeHeroSmsAcquirePriority(value);
|
||||||
|
case 'heroSmsOperator':
|
||||||
|
return normalizeHeroSmsOperator(value);
|
||||||
case 'heroSmsMinPrice':
|
case 'heroSmsMinPrice':
|
||||||
case 'heroSmsMaxPrice':
|
case 'heroSmsMaxPrice':
|
||||||
return normalizeHeroSmsMaxPrice(value);
|
return normalizeHeroSmsMaxPrice(value);
|
||||||
@@ -13690,6 +13709,7 @@ const phoneVerificationHelpers = self.MultiPageBackgroundPhoneVerification?.crea
|
|||||||
DEFAULT_NEX_SMS_COUNTRY_ORDER,
|
DEFAULT_NEX_SMS_COUNTRY_ORDER,
|
||||||
DEFAULT_NEX_SMS_SERVICE_CODE,
|
DEFAULT_NEX_SMS_SERVICE_CODE,
|
||||||
DEFAULT_HERO_SMS_BASE_URL,
|
DEFAULT_HERO_SMS_BASE_URL,
|
||||||
|
DEFAULT_HERO_SMS_OPERATOR,
|
||||||
DEFAULT_HERO_SMS_REUSE_ENABLED,
|
DEFAULT_HERO_SMS_REUSE_ENABLED,
|
||||||
DEFAULT_PHONE_CODE_WAIT_SECONDS,
|
DEFAULT_PHONE_CODE_WAIT_SECONDS,
|
||||||
DEFAULT_PHONE_CODE_TIMEOUT_WINDOWS,
|
DEFAULT_PHONE_CODE_TIMEOUT_WINDOWS,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
DEFAULT_FIVE_SIM_BASE_URL = 'https://5sim.net/v1',
|
DEFAULT_FIVE_SIM_BASE_URL = 'https://5sim.net/v1',
|
||||||
DEFAULT_FIVE_SIM_PRODUCT = 'openai',
|
DEFAULT_FIVE_SIM_PRODUCT = 'openai',
|
||||||
DEFAULT_FIVE_SIM_OPERATOR = 'any',
|
DEFAULT_FIVE_SIM_OPERATOR = 'any',
|
||||||
|
DEFAULT_HERO_SMS_OPERATOR = 'any',
|
||||||
DEFAULT_FIVE_SIM_COUNTRY_ORDER = ['thailand'],
|
DEFAULT_FIVE_SIM_COUNTRY_ORDER = ['thailand'],
|
||||||
DEFAULT_NEX_SMS_BASE_URL = 'https://api.nexsms.net',
|
DEFAULT_NEX_SMS_BASE_URL = 'https://api.nexsms.net',
|
||||||
DEFAULT_NEX_SMS_COUNTRY_ORDER = [1],
|
DEFAULT_NEX_SMS_COUNTRY_ORDER = [1],
|
||||||
@@ -548,6 +549,21 @@
|
|||||||
return String(value || '').trim() || fallback;
|
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 = '') {
|
function inferHeroSmsCountryFromPhoneNumber(phoneNumber = '') {
|
||||||
const digits = String(phoneNumber || '').replace(/\D+/g, '');
|
const digits = String(phoneNumber || '').replace(/\D+/g, '');
|
||||||
if (!digits) {
|
if (!digits) {
|
||||||
@@ -927,6 +943,17 @@
|
|||||||
return normalizePhoneSmsProvider(activation?.provider || state?.phoneSmsProvider);
|
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) {
|
function getPhoneSmsProviderLabel(providerId) {
|
||||||
const provider = normalizePhoneSmsProvider(providerId);
|
const provider = normalizePhoneSmsProvider(providerId);
|
||||||
if (provider === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
if (provider === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
||||||
@@ -2100,6 +2127,7 @@
|
|||||||
provider,
|
provider,
|
||||||
apiKey,
|
apiKey,
|
||||||
baseUrl: normalizeUrl(state.heroSmsBaseUrl, DEFAULT_HERO_SMS_BASE_URL),
|
baseUrl: normalizeUrl(state.heroSmsBaseUrl, DEFAULT_HERO_SMS_BASE_URL),
|
||||||
|
operator: normalizeHeroSmsOperator(state.heroSmsOperator, DEFAULT_HERO_SMS_OPERATOR),
|
||||||
countryCandidates: resolveCountryCandidates(state),
|
countryCandidates: resolveCountryCandidates(state),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -2113,10 +2141,82 @@
|
|||||||
provider: PHONE_SMS_PROVIDER_HERO,
|
provider: PHONE_SMS_PROVIDER_HERO,
|
||||||
apiKey,
|
apiKey,
|
||||||
baseUrl: normalizeUrl(state.heroSmsBaseUrl, DEFAULT_HERO_SMS_BASE_URL),
|
baseUrl: normalizeUrl(state.heroSmsBaseUrl, DEFAULT_HERO_SMS_BASE_URL),
|
||||||
|
operator: normalizeHeroSmsOperator(state.heroSmsOperator, DEFAULT_HERO_SMS_OPERATOR),
|
||||||
countryCandidates: resolveCountryCandidates(state),
|
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) {
|
function parseActivationPayload(payload, fallback = null) {
|
||||||
const normalizedFallback = normalizeActivation(fallback) || normalizeActivationFallback(fallback);
|
const normalizedFallback = normalizeActivation(fallback) || normalizeActivationFallback(fallback);
|
||||||
const directActivation = normalizeActivation(payload);
|
const directActivation = normalizeActivation(payload);
|
||||||
@@ -2537,6 +2637,10 @@
|
|||||||
service: HERO_SMS_SERVICE_CODE,
|
service: HERO_SMS_SERVICE_CODE,
|
||||||
country: countryConfig.id,
|
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) {
|
if (options.maxPrice !== null && options.maxPrice !== undefined) {
|
||||||
query.maxPrice = options.maxPrice;
|
query.maxPrice = options.maxPrice;
|
||||||
if (options.fixedPrice !== false) {
|
if (options.fixedPrice !== false) {
|
||||||
@@ -3584,6 +3688,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function requestPhoneActivation(state = {}, options = {}) {
|
async function requestPhoneActivation(state = {}, options = {}) {
|
||||||
|
state = await mergeLatestPhoneSettingsState(state, {
|
||||||
|
preservePhoneSmsProvider: Boolean(options?.preservePhoneSmsProvider),
|
||||||
|
});
|
||||||
if (normalizePhoneSmsProvider(state?.phoneSmsProvider) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
if (normalizePhoneSmsProvider(state?.phoneSmsProvider) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
||||||
const provider = getFiveSimProviderForState(state);
|
const provider = getFiveSimProviderForState(state);
|
||||||
if (provider) {
|
if (provider) {
|
||||||
@@ -3931,11 +4038,12 @@
|
|||||||
if (getActivationProviderId(normalizedActivation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
if (getActivationProviderId(normalizedActivation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
||||||
const provider = getFiveSimProviderForState(state);
|
const provider = getFiveSimProviderForState(state);
|
||||||
if (provider) {
|
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) {
|
if (config.provider === PHONE_SMS_PROVIDER_5SIM) {
|
||||||
const payload = await fetchFiveSimPayload(
|
const payload = await fetchFiveSimPayload(
|
||||||
config,
|
config,
|
||||||
@@ -3980,7 +4088,7 @@
|
|||||||
);
|
);
|
||||||
return `free reuse setStatus(${normalizedStatus}) skipped`;
|
return `free reuse setStatus(${normalizedStatus}) skipped`;
|
||||||
}
|
}
|
||||||
const config = resolvePhoneConfig(state);
|
const config = resolvePhoneConfig(scopeStateToActivationProvider(state, normalizedActivation));
|
||||||
if (config.provider === PHONE_SMS_PROVIDER_5SIM) {
|
if (config.provider === PHONE_SMS_PROVIDER_5SIM) {
|
||||||
const endpoint = normalizedStatus === 6
|
const endpoint = normalizedStatus === 6
|
||||||
? `/user/finish/${normalizedActivation.activationId}`
|
? `/user/finish/${normalizedActivation.activationId}`
|
||||||
@@ -4029,7 +4137,7 @@
|
|||||||
if (getActivationProviderId(activation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
if (getActivationProviderId(activation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
||||||
const provider = getFiveSimProviderForState(state);
|
const provider = getFiveSimProviderForState(state);
|
||||||
if (provider) {
|
if (provider) {
|
||||||
await provider.finishActivation(state, activation);
|
await provider.finishActivation(scopeStateToActivationProvider(state, activation), activation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4050,7 +4158,7 @@
|
|||||||
if (getActivationProviderId(activation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
if (getActivationProviderId(activation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
||||||
const provider = getFiveSimProviderForState(state);
|
const provider = getFiveSimProviderForState(state);
|
||||||
if (provider) {
|
if (provider) {
|
||||||
await provider.cancelActivation(state, activation);
|
await provider.cancelActivation(scopeStateToActivationProvider(state, activation), activation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4151,7 +4259,7 @@
|
|||||||
if (getActivationProviderId(activation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
if (getActivationProviderId(activation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
||||||
const provider = getFiveSimProviderForState(state);
|
const provider = getFiveSimProviderForState(state);
|
||||||
if (provider) {
|
if (provider) {
|
||||||
await provider.banActivation(state, activation);
|
await provider.banActivation(scopeStateToActivationProvider(state, activation), activation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4162,7 +4270,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function requestAdditionalPhoneSms(state = {}, activation) {
|
async function requestAdditionalPhoneSms(state = {}, activation) {
|
||||||
const config = resolvePhoneConfig(state);
|
const config = resolvePhoneConfig(scopeStateToActivationProvider(state, activation));
|
||||||
if (config.provider !== PHONE_SMS_PROVIDER_HERO) {
|
if (config.provider !== PHONE_SMS_PROVIDER_HERO) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4342,12 +4450,13 @@
|
|||||||
if (getActivationProviderId(normalizedActivation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
if (getActivationProviderId(normalizedActivation, state) === PHONE_SMS_PROVIDER_FIVE_SIM) {
|
||||||
const provider = getFiveSimProviderForState(state);
|
const provider = getFiveSimProviderForState(state);
|
||||||
if (provider) {
|
if (provider) {
|
||||||
return provider.pollActivationCode(state, normalizedActivation, options);
|
return provider.pollActivationCode(scopeStateToActivationProvider(state, normalizedActivation), normalizedActivation, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const statusAction = resolveActivationStatusAction(normalizedActivation);
|
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 configuredTimeoutMs = Math.max(1000, Number(options.timeoutMs) || 0);
|
||||||
const timeoutMs = configuredTimeoutMs || (
|
const timeoutMs = configuredTimeoutMs || (
|
||||||
typeof getOAuthFlowStepTimeoutMs === 'function'
|
typeof getOAuthFlowStepTimeoutMs === 'function'
|
||||||
@@ -5101,6 +5210,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function acquirePhoneActivation(state = {}, options = {}) {
|
async function acquirePhoneActivation(state = {}, options = {}) {
|
||||||
|
state = await mergeLatestPhoneSettingsState(state);
|
||||||
const provider = normalizePhoneSmsProvider(state?.phoneSmsProvider || DEFAULT_PHONE_SMS_PROVIDER);
|
const provider = normalizePhoneSmsProvider(state?.phoneSmsProvider || DEFAULT_PHONE_SMS_PROVIDER);
|
||||||
const providerOrder = resolvePhoneProviderOrder(state, provider);
|
const providerOrder = resolvePhoneProviderOrder(state, provider);
|
||||||
const countryCandidates = resolveCountryCandidatesForProvider(state, provider);
|
const countryCandidates = resolveCountryCandidatesForProvider(state, provider);
|
||||||
@@ -5261,6 +5371,7 @@
|
|||||||
{
|
{
|
||||||
blockedCountryIds: useBlockedCountryIds,
|
blockedCountryIds: useBlockedCountryIds,
|
||||||
countryPriceFloorByCountryId: useCountryPriceFloorByCountryId,
|
countryPriceFloorByCountryId: useCountryPriceFloorByCountryId,
|
||||||
|
preservePhoneSmsProvider: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const providerLabel = getPhoneSmsProviderLabel(providerCandidate);
|
const providerLabel = getPhoneSmsProviderLabel(providerCandidate);
|
||||||
|
|||||||
@@ -1536,6 +1536,15 @@
|
|||||||
<option value="price_high">高价优先(同价按国家顺序)</option>
|
<option value="price_high">高价优先(同价按国家顺序)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="data-row" id="row-hero-sms-operator" style="display:none;">
|
||||||
|
<span class="data-label">运营商</span>
|
||||||
|
<div class="data-inline hero-sms-country-stack">
|
||||||
|
<select id="select-hero-sms-operator" class="data-input mono">
|
||||||
|
<option value="any" selected>不限(any)</option>
|
||||||
|
</select>
|
||||||
|
<span class="data-value hero-sms-country-note">按主国家读取 HeroSMS 运营商;不限时不附加 operator。</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="data-row" id="row-hero-sms-api-key" style="display:none;">
|
<div class="data-row" id="row-hero-sms-api-key" style="display:none;">
|
||||||
<span class="data-label">接码 API</span>
|
<span class="data-label">接码 API</span>
|
||||||
<div class="input-with-icon">
|
<div class="input-with-icon">
|
||||||
|
|||||||
@@ -460,6 +460,7 @@ const rowHeroSmsPlatform = document.getElementById('row-hero-sms-platform');
|
|||||||
const rowHeroSmsCountry = document.getElementById('row-hero-sms-country');
|
const rowHeroSmsCountry = document.getElementById('row-hero-sms-country');
|
||||||
const rowHeroSmsCountryFallback = document.getElementById('row-hero-sms-country-fallback');
|
const rowHeroSmsCountryFallback = document.getElementById('row-hero-sms-country-fallback');
|
||||||
const rowHeroSmsAcquirePriority = document.getElementById('row-hero-sms-acquire-priority');
|
const rowHeroSmsAcquirePriority = document.getElementById('row-hero-sms-acquire-priority');
|
||||||
|
const rowHeroSmsOperator = document.getElementById('row-hero-sms-operator');
|
||||||
const rowHeroSmsApiKey = document.getElementById('row-hero-sms-api-key');
|
const rowHeroSmsApiKey = document.getElementById('row-hero-sms-api-key');
|
||||||
const rowHeroSmsMaxPrice = document.getElementById('row-hero-sms-max-price');
|
const rowHeroSmsMaxPrice = document.getElementById('row-hero-sms-max-price');
|
||||||
const rowPhoneSmsProvider = document.getElementById('row-phone-sms-provider');
|
const rowPhoneSmsProvider = document.getElementById('row-phone-sms-provider');
|
||||||
@@ -514,6 +515,7 @@ const inputFreeReusablePhone = document.getElementById('input-free-reusable-phon
|
|||||||
const selectHeroSmsCountry = document.getElementById('select-hero-sms-country');
|
const selectHeroSmsCountry = document.getElementById('select-hero-sms-country');
|
||||||
const selectHeroSmsCountryFallback = document.getElementById('select-hero-sms-country-fallback');
|
const selectHeroSmsCountryFallback = document.getElementById('select-hero-sms-country-fallback');
|
||||||
const selectHeroSmsAcquirePriority = document.getElementById('select-hero-sms-acquire-priority');
|
const selectHeroSmsAcquirePriority = document.getElementById('select-hero-sms-acquire-priority');
|
||||||
|
const selectHeroSmsOperator = document.getElementById('select-hero-sms-operator');
|
||||||
const selectHeroSmsPreferredActivation = document.getElementById('select-hero-sms-preferred-activation');
|
const selectHeroSmsPreferredActivation = document.getElementById('select-hero-sms-preferred-activation');
|
||||||
const selectFiveSimCountry = document.getElementById('select-five-sim-country');
|
const selectFiveSimCountry = document.getElementById('select-five-sim-country');
|
||||||
const heroSmsCountryMenuShell = document.getElementById('hero-sms-country-menu-shell');
|
const heroSmsCountryMenuShell = document.getElementById('hero-sms-country-menu-shell');
|
||||||
@@ -606,6 +608,9 @@ let currentStepDefinitionFlowId = DEFAULT_ACTIVE_FLOW_ID;
|
|||||||
let phoneSignupReuseUiWasLocked = false;
|
let phoneSignupReuseUiWasLocked = false;
|
||||||
let kiroRsConnectionTestStatusText = '未测试';
|
let kiroRsConnectionTestStatusText = '未测试';
|
||||||
let heroSmsCountrySelectionOrder = [];
|
let heroSmsCountrySelectionOrder = [];
|
||||||
|
let heroSmsOperatorsByCountryId = new Map();
|
||||||
|
let heroSmsOperatorsLoadedAt = 0;
|
||||||
|
let isRenderingHeroSmsOperatorOptions = false;
|
||||||
let phoneSmsProviderOrderSelection = [];
|
let phoneSmsProviderOrderSelection = [];
|
||||||
let heroSmsCountryMenuSearchKeyword = '';
|
let heroSmsCountryMenuSearchKeyword = '';
|
||||||
const heroSmsCountrySearchTextById = new Map();
|
const heroSmsCountrySearchTextById = new Map();
|
||||||
@@ -680,6 +685,8 @@ const DEFAULT_FIVE_SIM_PRODUCT = 'openai';
|
|||||||
const DEFAULT_NEX_SMS_COUNTRY_ORDER = Object.freeze([1]);
|
const DEFAULT_NEX_SMS_COUNTRY_ORDER = Object.freeze([1]);
|
||||||
const DEFAULT_NEX_SMS_SERVICE_CODE = 'ot';
|
const DEFAULT_NEX_SMS_SERVICE_CODE = 'ot';
|
||||||
const HERO_SMS_COUNTRY_SELECTION_MAX = 3;
|
const HERO_SMS_COUNTRY_SELECTION_MAX = 3;
|
||||||
|
const DEFAULT_HERO_SMS_OPERATOR = 'any';
|
||||||
|
const HERO_SMS_OPERATORS_URL = 'https://hero-sms.com/stubs/handler_api.php?action=getOperators';
|
||||||
const DEFAULT_HERO_SMS_REUSE_ENABLED = true;
|
const DEFAULT_HERO_SMS_REUSE_ENABLED = true;
|
||||||
const HERO_SMS_ACQUIRE_PRIORITY_COUNTRY = 'country';
|
const HERO_SMS_ACQUIRE_PRIORITY_COUNTRY = 'country';
|
||||||
const HERO_SMS_ACQUIRE_PRIORITY_PRICE = 'price';
|
const HERO_SMS_ACQUIRE_PRIORITY_PRICE = 'price';
|
||||||
@@ -4667,6 +4674,9 @@ function collectSettingsPayload() {
|
|||||||
? DEFAULT_HERO_SMS_ACQUIRE_PRIORITY
|
? DEFAULT_HERO_SMS_ACQUIRE_PRIORITY
|
||||||
: 'country'
|
: 'country'
|
||||||
);
|
);
|
||||||
|
const heroSmsOperatorValue = typeof selectHeroSmsOperator !== 'undefined' && selectHeroSmsOperator
|
||||||
|
? normalizeHeroSmsOperatorValue(selectHeroSmsOperator.value || latestState?.heroSmsOperator)
|
||||||
|
: normalizeHeroSmsOperatorValue(latestState?.heroSmsOperator);
|
||||||
const currentPhoneSmsMaxPriceValue = typeof inputHeroSmsMaxPrice !== 'undefined' && inputHeroSmsMaxPrice
|
const currentPhoneSmsMaxPriceValue = typeof inputHeroSmsMaxPrice !== 'undefined' && inputHeroSmsMaxPrice
|
||||||
? normalizePhoneSmsMaxPriceValue(inputHeroSmsMaxPrice.value, phoneSmsProviderValue)
|
? normalizePhoneSmsMaxPriceValue(inputHeroSmsMaxPrice.value, phoneSmsProviderValue)
|
||||||
: '';
|
: '';
|
||||||
@@ -5263,6 +5273,7 @@ function collectSettingsPayload() {
|
|||||||
freePhoneReuseEnabled: freePhoneReuseEnabledValue,
|
freePhoneReuseEnabled: freePhoneReuseEnabledValue,
|
||||||
freePhoneReuseAutoEnabled: freePhoneReuseAutoEnabledValue,
|
freePhoneReuseAutoEnabled: freePhoneReuseAutoEnabledValue,
|
||||||
heroSmsAcquirePriority: heroSmsAcquirePriorityValue,
|
heroSmsAcquirePriority: heroSmsAcquirePriorityValue,
|
||||||
|
heroSmsOperator: heroSmsOperatorValue,
|
||||||
heroSmsMinPrice: heroSmsMinPriceValue,
|
heroSmsMinPrice: heroSmsMinPriceValue,
|
||||||
heroSmsMaxPrice: heroSmsMaxPriceValue,
|
heroSmsMaxPrice: heroSmsMaxPriceValue,
|
||||||
heroSmsPreferredPrice: heroSmsPreferredPriceValue,
|
heroSmsPreferredPrice: heroSmsPreferredPriceValue,
|
||||||
@@ -6151,6 +6162,21 @@ function normalizeHeroSmsAcquirePriority(value = '') {
|
|||||||
return HERO_SMS_ACQUIRE_PRIORITY_COUNTRY;
|
return HERO_SMS_ACQUIRE_PRIORITY_COUNTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeHeroSmsOperatorValue(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 normalizeHeroSmsCountryFallbackList(value = []) {
|
function normalizeHeroSmsCountryFallbackList(value = []) {
|
||||||
const source = Array.isArray(value)
|
const source = Array.isArray(value)
|
||||||
? value
|
? value
|
||||||
@@ -6323,6 +6349,35 @@ function parseHeroSmsCountryPayload(payload) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseHeroSmsOperatorsPayload(payload) {
|
||||||
|
const source = payload?.countryOperators || payload?.operators || payload?.data || payload?.result || payload;
|
||||||
|
if (!source || typeof source !== 'object' || Array.isArray(source)) {
|
||||||
|
return new Map();
|
||||||
|
}
|
||||||
|
const result = new Map();
|
||||||
|
Object.entries(source).forEach(([countryId, operators]) => {
|
||||||
|
const normalizedCountryId = Math.floor(Number(countryId));
|
||||||
|
if (!Number.isFinite(normalizedCountryId) || normalizedCountryId <= 0 || !Array.isArray(operators)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const seen = new Set();
|
||||||
|
const normalizedOperators = operators
|
||||||
|
.map((operator) => normalizeHeroSmsOperatorValue(operator, ''))
|
||||||
|
.filter(Boolean)
|
||||||
|
.filter((operator) => {
|
||||||
|
if (seen.has(operator)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
seen.add(operator);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (normalizedOperators.length) {
|
||||||
|
result.set(String(normalizedCountryId), normalizedOperators);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeHeroSmsPriceForPreview(value) {
|
function normalizeHeroSmsPriceForPreview(value) {
|
||||||
const direct = Number(value);
|
const direct = Number(value);
|
||||||
if (Number.isFinite(direct) && direct >= 0) {
|
if (Number.isFinite(direct) && direct >= 0) {
|
||||||
@@ -7693,6 +7748,141 @@ async function loadHeroSmsCountries(options = {}) {
|
|||||||
showLimitToast: false,
|
showLimitToast: false,
|
||||||
});
|
});
|
||||||
updateHeroSmsPlatformDisplay();
|
updateHeroSmsPlatformDisplay();
|
||||||
|
setHeroSmsOperatorSelectValue(latestState?.heroSmsOperator);
|
||||||
|
refreshHeroSmsOperatorOptions({ silent: true, selectedOperator: latestState?.heroSmsOperator });
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHeroSmsOperatorCountryId() {
|
||||||
|
const countrySelect = selectHeroSmsCountry || selectHeroSmsCountryFallback;
|
||||||
|
if (heroSmsCountrySelectionOrder.length) {
|
||||||
|
return normalizeHeroSmsCountryId(heroSmsCountrySelectionOrder[0], DEFAULT_HERO_SMS_COUNTRY_ID);
|
||||||
|
}
|
||||||
|
const selectedOption = countrySelect
|
||||||
|
? Array.from(countrySelect.options || []).find((option) => option.selected)
|
||||||
|
: null;
|
||||||
|
return normalizeHeroSmsCountryId(
|
||||||
|
selectedOption?.value || latestState?.heroSmsCountryId,
|
||||||
|
DEFAULT_HERO_SMS_COUNTRY_ID
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadHeroSmsOperators(options = {}) {
|
||||||
|
const silent = Boolean(options?.silent);
|
||||||
|
const force = Boolean(options?.force);
|
||||||
|
if (
|
||||||
|
!force
|
||||||
|
&& heroSmsOperatorsByCountryId instanceof Map
|
||||||
|
&& heroSmsOperatorsByCountryId.size
|
||||||
|
&& Date.now() - heroSmsOperatorsLoadedAt < 10 * 60 * 1000
|
||||||
|
) {
|
||||||
|
return heroSmsOperatorsByCountryId;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeoutId = setTimeout(() => controller.abort(), 3500);
|
||||||
|
const response = await fetch(HERO_SMS_OPERATORS_URL, {
|
||||||
|
signal: controller.signal,
|
||||||
|
cache: 'no-store',
|
||||||
|
headers: { Accept: 'application/json' },
|
||||||
|
});
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}`);
|
||||||
|
}
|
||||||
|
const payload = await response.json();
|
||||||
|
const parsed = parseHeroSmsOperatorsPayload(payload);
|
||||||
|
if (!parsed.size) {
|
||||||
|
throw new Error('运营商列表为空');
|
||||||
|
}
|
||||||
|
heroSmsOperatorsByCountryId = parsed;
|
||||||
|
heroSmsOperatorsLoadedAt = Date.now();
|
||||||
|
} catch (error) {
|
||||||
|
if (!(heroSmsOperatorsByCountryId instanceof Map)) {
|
||||||
|
heroSmsOperatorsByCountryId = new Map();
|
||||||
|
}
|
||||||
|
if (!silent && typeof showToast === 'function') {
|
||||||
|
showToast(`HeroSMS 运营商列表加载失败:${normalizeHeroSmsFetchErrorMessage(error)}(已保留“不限”)`, 'warn', 2600);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return heroSmsOperatorsByCountryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderHeroSmsOperatorOptions(selectedOperator = null) {
|
||||||
|
if (!selectHeroSmsOperator || isRenderingHeroSmsOperatorOptions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isRenderingHeroSmsOperatorOptions = true;
|
||||||
|
try {
|
||||||
|
const currentValue = normalizeHeroSmsOperatorValue(
|
||||||
|
selectedOperator !== null && selectedOperator !== undefined
|
||||||
|
? selectedOperator
|
||||||
|
: (selectHeroSmsOperator.value || latestState?.heroSmsOperator),
|
||||||
|
DEFAULT_HERO_SMS_OPERATOR
|
||||||
|
);
|
||||||
|
const countryId = String(getHeroSmsOperatorCountryId());
|
||||||
|
const operators = heroSmsOperatorsByCountryId instanceof Map
|
||||||
|
? (heroSmsOperatorsByCountryId.get(countryId) || [])
|
||||||
|
: [];
|
||||||
|
selectHeroSmsOperator.innerHTML = '';
|
||||||
|
const anyOption = document.createElement('option');
|
||||||
|
anyOption.value = DEFAULT_HERO_SMS_OPERATOR;
|
||||||
|
anyOption.textContent = '不限(any)';
|
||||||
|
selectHeroSmsOperator.appendChild(anyOption);
|
||||||
|
operators.forEach((operator) => {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = operator;
|
||||||
|
option.textContent = operator;
|
||||||
|
selectHeroSmsOperator.appendChild(option);
|
||||||
|
});
|
||||||
|
if (
|
||||||
|
currentValue
|
||||||
|
&& currentValue !== DEFAULT_HERO_SMS_OPERATOR
|
||||||
|
&& !Array.from(selectHeroSmsOperator.options).some((option) => option.value === currentValue)
|
||||||
|
) {
|
||||||
|
const selectedOption = document.createElement('option');
|
||||||
|
selectedOption.value = currentValue;
|
||||||
|
selectedOption.textContent = currentValue;
|
||||||
|
selectHeroSmsOperator.appendChild(selectedOption);
|
||||||
|
}
|
||||||
|
selectHeroSmsOperator.value = currentValue || DEFAULT_HERO_SMS_OPERATOR;
|
||||||
|
selectHeroSmsOperator.disabled = operators.length === 0;
|
||||||
|
} finally {
|
||||||
|
isRenderingHeroSmsOperatorOptions = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHeroSmsOperatorSelectValue(operator = latestState?.heroSmsOperator) {
|
||||||
|
if (!selectHeroSmsOperator) {
|
||||||
|
return DEFAULT_HERO_SMS_OPERATOR;
|
||||||
|
}
|
||||||
|
const normalized = normalizeHeroSmsOperatorValue(operator, DEFAULT_HERO_SMS_OPERATOR);
|
||||||
|
if (
|
||||||
|
normalized
|
||||||
|
&& normalized !== DEFAULT_HERO_SMS_OPERATOR
|
||||||
|
&& !Array.from(selectHeroSmsOperator.options || []).some((option) => option.value === normalized)
|
||||||
|
) {
|
||||||
|
const selectedOption = document.createElement('option');
|
||||||
|
selectedOption.value = normalized;
|
||||||
|
selectedOption.textContent = normalized;
|
||||||
|
selectHeroSmsOperator.appendChild(selectedOption);
|
||||||
|
}
|
||||||
|
selectHeroSmsOperator.value = normalized;
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshHeroSmsOperatorOptions(options = {}) {
|
||||||
|
if (!selectHeroSmsOperator) {
|
||||||
|
return Promise.resolve(heroSmsOperatorsByCountryId);
|
||||||
|
}
|
||||||
|
return loadHeroSmsOperators(options)
|
||||||
|
.then(() => {
|
||||||
|
renderHeroSmsOperatorOptions(options?.selectedOperator);
|
||||||
|
return heroSmsOperatorsByCountryId;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
renderHeroSmsOperatorOptions(options?.selectedOperator);
|
||||||
|
return heroSmsOperatorsByCountryId;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFiveSimCountryLabelByCode(code = '') {
|
function getFiveSimCountryLabelByCode(code = '') {
|
||||||
@@ -9655,6 +9845,7 @@ function updatePhoneVerificationSettingsUI() {
|
|||||||
typeof rowHeroSmsCountry !== 'undefined' ? rowHeroSmsCountry : null,
|
typeof rowHeroSmsCountry !== 'undefined' ? rowHeroSmsCountry : null,
|
||||||
typeof rowHeroSmsCountryFallback !== 'undefined' ? rowHeroSmsCountryFallback : null,
|
typeof rowHeroSmsCountryFallback !== 'undefined' ? rowHeroSmsCountryFallback : null,
|
||||||
typeof rowHeroSmsAcquirePriority !== 'undefined' ? rowHeroSmsAcquirePriority : null,
|
typeof rowHeroSmsAcquirePriority !== 'undefined' ? rowHeroSmsAcquirePriority : null,
|
||||||
|
typeof rowHeroSmsOperator !== 'undefined' ? rowHeroSmsOperator : null,
|
||||||
typeof rowHeroSmsApiKey !== 'undefined' ? rowHeroSmsApiKey : null,
|
typeof rowHeroSmsApiKey !== 'undefined' ? rowHeroSmsApiKey : null,
|
||||||
typeof rowFiveSimApiKey !== 'undefined' ? rowFiveSimApiKey : null,
|
typeof rowFiveSimApiKey !== 'undefined' ? rowFiveSimApiKey : null,
|
||||||
typeof rowFiveSimCountry !== 'undefined' ? rowFiveSimCountry : null,
|
typeof rowFiveSimCountry !== 'undefined' ? rowFiveSimCountry : null,
|
||||||
@@ -9687,6 +9878,7 @@ function updatePhoneVerificationSettingsUI() {
|
|||||||
if (rowHeroSmsCountry) rowHeroSmsCountry.style.display = showSettings && heroProvider ? '' : 'none';
|
if (rowHeroSmsCountry) rowHeroSmsCountry.style.display = showSettings && heroProvider ? '' : 'none';
|
||||||
if (rowHeroSmsCountryFallback) rowHeroSmsCountryFallback.style.display = showSettings && heroProvider ? '' : 'none';
|
if (rowHeroSmsCountryFallback) rowHeroSmsCountryFallback.style.display = showSettings && heroProvider ? '' : 'none';
|
||||||
if (rowHeroSmsAcquirePriority) rowHeroSmsAcquirePriority.style.display = showSettings && heroProvider ? '' : 'none';
|
if (rowHeroSmsAcquirePriority) rowHeroSmsAcquirePriority.style.display = showSettings && heroProvider ? '' : 'none';
|
||||||
|
if (rowHeroSmsOperator) rowHeroSmsOperator.style.display = showSettings && heroProvider ? '' : 'none';
|
||||||
if (rowHeroSmsApiKey) rowHeroSmsApiKey.style.display = showSettings && heroProvider ? '' : 'none';
|
if (rowHeroSmsApiKey) rowHeroSmsApiKey.style.display = showSettings && heroProvider ? '' : 'none';
|
||||||
if (rowFiveSimApiKey) rowFiveSimApiKey.style.display = showSettings && fiveSimProvider ? '' : 'none';
|
if (rowFiveSimApiKey) rowFiveSimApiKey.style.display = showSettings && fiveSimProvider ? '' : 'none';
|
||||||
if (rowFiveSimCountry) rowFiveSimCountry.style.display = showSettings && fiveSimProvider ? '' : 'none';
|
if (rowFiveSimCountry) rowFiveSimCountry.style.display = showSettings && fiveSimProvider ? '' : 'none';
|
||||||
@@ -11664,6 +11856,9 @@ function applySettingsState(state) {
|
|||||||
if (typeof selectHeroSmsAcquirePriority !== 'undefined' && selectHeroSmsAcquirePriority) {
|
if (typeof selectHeroSmsAcquirePriority !== 'undefined' && selectHeroSmsAcquirePriority) {
|
||||||
selectHeroSmsAcquirePriority.value = normalizeHeroSmsAcquirePriority(state?.heroSmsAcquirePriority);
|
selectHeroSmsAcquirePriority.value = normalizeHeroSmsAcquirePriority(state?.heroSmsAcquirePriority);
|
||||||
}
|
}
|
||||||
|
if (typeof selectHeroSmsOperator !== 'undefined' && selectHeroSmsOperator) {
|
||||||
|
setHeroSmsOperatorSelectValue(state?.heroSmsOperator);
|
||||||
|
}
|
||||||
if (inputHeroSmsMaxPrice) {
|
if (inputHeroSmsMaxPrice) {
|
||||||
inputHeroSmsMaxPrice.value = restoredPhoneSmsProvider === PHONE_SMS_PROVIDER_FIVE_SIM
|
inputHeroSmsMaxPrice.value = restoredPhoneSmsProvider === PHONE_SMS_PROVIDER_FIVE_SIM
|
||||||
? normalizeFiveSimMaxPriceValue(state?.fiveSimMaxPrice || '')
|
? normalizeFiveSimMaxPriceValue(state?.fiveSimMaxPrice || '')
|
||||||
@@ -11731,6 +11926,9 @@ function applySettingsState(state) {
|
|||||||
{ includePrimary: true }
|
{ includePrimary: true }
|
||||||
);
|
);
|
||||||
updateHeroSmsPlatformDisplay();
|
updateHeroSmsPlatformDisplay();
|
||||||
|
if (restoredPhoneSmsProvider === PHONE_SMS_PROVIDER_HERO_SMS) {
|
||||||
|
refreshHeroSmsOperatorOptions({ silent: true, selectedOperator: state?.heroSmsOperator });
|
||||||
|
}
|
||||||
} else if (selectHeroSmsCountry) {
|
} else if (selectHeroSmsCountry) {
|
||||||
const restoredCountryId = restoredPhoneSmsProvider === PHONE_SMS_PROVIDER_FIVE_SIM
|
const restoredCountryId = restoredPhoneSmsProvider === PHONE_SMS_PROVIDER_FIVE_SIM
|
||||||
? String(normalizeFiveSimCountryId(state?.fiveSimCountryId))
|
? String(normalizeFiveSimCountryId(state?.fiveSimCountryId))
|
||||||
@@ -16960,6 +17158,7 @@ async function switchPhoneSmsProvider(nextProvider) {
|
|||||||
patch.heroSmsApiKey = currentApiKey;
|
patch.heroSmsApiKey = currentApiKey;
|
||||||
patch.heroSmsMaxPrice = currentMaxPrice;
|
patch.heroSmsMaxPrice = currentMaxPrice;
|
||||||
patch.heroSmsMinPrice = currentMinPrice;
|
patch.heroSmsMinPrice = currentMinPrice;
|
||||||
|
patch.heroSmsOperator = normalizeHeroSmsOperatorValue(selectHeroSmsOperator?.value || latestState?.heroSmsOperator);
|
||||||
patch.heroSmsCountryId = currentPrimary.id;
|
patch.heroSmsCountryId = currentPrimary.id;
|
||||||
patch.heroSmsCountryLabel = currentPrimary.label;
|
patch.heroSmsCountryLabel = currentPrimary.label;
|
||||||
patch.heroSmsCountryFallback = currentFallback;
|
patch.heroSmsCountryFallback = currentFallback;
|
||||||
@@ -16986,6 +17185,9 @@ async function switchPhoneSmsProvider(nextProvider) {
|
|||||||
if (inputFiveSimOperator) {
|
if (inputFiveSimOperator) {
|
||||||
inputFiveSimOperator.value = normalizeFiveSimOperator(latestState?.fiveSimOperator);
|
inputFiveSimOperator.value = normalizeFiveSimOperator(latestState?.fiveSimOperator);
|
||||||
}
|
}
|
||||||
|
if (selectHeroSmsOperator) {
|
||||||
|
setHeroSmsOperatorSelectValue(latestState?.heroSmsOperator);
|
||||||
|
}
|
||||||
if (displayHeroSmsPriceTiers) displayHeroSmsPriceTiers.textContent = '未获取';
|
if (displayHeroSmsPriceTiers) displayHeroSmsPriceTiers.textContent = '未获取';
|
||||||
if (displayPhoneSmsBalance) displayPhoneSmsBalance.textContent = '余额未获取';
|
if (displayPhoneSmsBalance) displayPhoneSmsBalance.textContent = '余额未获取';
|
||||||
if (rowHeroSmsPriceTiers) rowHeroSmsPriceTiers.style.display = 'none';
|
if (rowHeroSmsPriceTiers) rowHeroSmsPriceTiers.style.display = 'none';
|
||||||
@@ -17004,6 +17206,9 @@ async function switchPhoneSmsProvider(nextProvider) {
|
|||||||
? normalizeFiveSimCountryFallbackList(latestState?.fiveSimCountryFallback || [])
|
? normalizeFiveSimCountryFallbackList(latestState?.fiveSimCountryFallback || [])
|
||||||
: normalizeHeroSmsCountryFallbackList(latestState?.heroSmsCountryFallback || []);
|
: normalizeHeroSmsCountryFallbackList(latestState?.heroSmsCountryFallback || []);
|
||||||
applyHeroSmsFallbackSelection([restoredPrimary, ...restoredFallback], { includePrimary: true });
|
applyHeroSmsFallbackSelection([restoredPrimary, ...restoredFallback], { includePrimary: true });
|
||||||
|
if (normalizedNextProvider === PHONE_SMS_PROVIDER_HERO_SMS) {
|
||||||
|
refreshHeroSmsOperatorOptions({ silent: true, selectedOperator: latestState?.heroSmsOperator });
|
||||||
|
}
|
||||||
updatePhoneVerificationSettingsUI();
|
updatePhoneVerificationSettingsUI();
|
||||||
markSettingsDirty(true);
|
markSettingsDirty(true);
|
||||||
saveSettings({ silent: true }).catch(() => {});
|
saveSettings({ silent: true }).catch(() => {});
|
||||||
@@ -17112,6 +17317,8 @@ selectPhoneSmsProvider?.addEventListener('change', async () => {
|
|||||||
],
|
],
|
||||||
{ includePrimary: true }
|
{ includePrimary: true }
|
||||||
);
|
);
|
||||||
|
setHeroSmsOperatorSelectValue(latestState?.heroSmsOperator);
|
||||||
|
refreshHeroSmsOperatorOptions({ silent: true, selectedOperator: latestState?.heroSmsOperator });
|
||||||
}
|
}
|
||||||
updateHeroSmsPlatformDisplay();
|
updateHeroSmsPlatformDisplay();
|
||||||
updatePhoneVerificationSettingsUI();
|
updatePhoneVerificationSettingsUI();
|
||||||
@@ -17330,6 +17537,19 @@ inputFiveSimOperator?.addEventListener('blur', () => {
|
|||||||
inputFiveSimOperator.value = normalizeFiveSimOperator(inputFiveSimOperator.value);
|
inputFiveSimOperator.value = normalizeFiveSimOperator(inputFiveSimOperator.value);
|
||||||
saveSettings({ silent: true }).catch(() => { });
|
saveSettings({ silent: true }).catch(() => { });
|
||||||
});
|
});
|
||||||
|
selectHeroSmsOperator?.addEventListener('change', () => {
|
||||||
|
const nextOperator = normalizeHeroSmsOperatorValue(selectHeroSmsOperator.value);
|
||||||
|
setHeroSmsOperatorSelectValue(nextOperator);
|
||||||
|
syncLatestState({ heroSmsOperator: nextOperator });
|
||||||
|
markSettingsDirty(true);
|
||||||
|
saveSettings({ silent: true }).catch(() => { });
|
||||||
|
});
|
||||||
|
selectHeroSmsOperator?.addEventListener('focus', () => {
|
||||||
|
refreshHeroSmsOperatorOptions({ silent: true, selectedOperator: selectHeroSmsOperator.value });
|
||||||
|
});
|
||||||
|
selectHeroSmsOperator?.addEventListener('pointerdown', () => {
|
||||||
|
refreshHeroSmsOperatorOptions({ silent: true, selectedOperator: selectHeroSmsOperator.value });
|
||||||
|
});
|
||||||
inputHeroSmsPreferredPrice?.addEventListener('input', () => {
|
inputHeroSmsPreferredPrice?.addEventListener('input', () => {
|
||||||
markSettingsDirty(true);
|
markSettingsDirty(true);
|
||||||
scheduleSettingsAutoSave();
|
scheduleSettingsAutoSave();
|
||||||
@@ -18259,6 +18479,9 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|||||||
if (message.payload.heroSmsAcquirePriority !== undefined && selectHeroSmsAcquirePriority) {
|
if (message.payload.heroSmsAcquirePriority !== undefined && selectHeroSmsAcquirePriority) {
|
||||||
selectHeroSmsAcquirePriority.value = normalizeHeroSmsAcquirePriority(message.payload.heroSmsAcquirePriority);
|
selectHeroSmsAcquirePriority.value = normalizeHeroSmsAcquirePriority(message.payload.heroSmsAcquirePriority);
|
||||||
}
|
}
|
||||||
|
if (message.payload.heroSmsOperator !== undefined && selectHeroSmsOperator) {
|
||||||
|
setHeroSmsOperatorSelectValue(message.payload.heroSmsOperator);
|
||||||
|
}
|
||||||
if ((message.payload.heroSmsMaxPrice !== undefined || message.payload.fiveSimMaxPrice !== undefined) && inputHeroSmsMaxPrice) {
|
if ((message.payload.heroSmsMaxPrice !== undefined || message.payload.fiveSimMaxPrice !== undefined) && inputHeroSmsMaxPrice) {
|
||||||
inputHeroSmsMaxPrice.value = getSelectedPhoneSmsProvider() === PHONE_SMS_PROVIDER_FIVE_SIM
|
inputHeroSmsMaxPrice.value = getSelectedPhoneSmsProvider() === PHONE_SMS_PROVIDER_FIVE_SIM
|
||||||
? normalizeFiveSimMaxPriceValue(message.payload.fiveSimMaxPrice !== undefined ? message.payload.fiveSimMaxPrice : latestState?.fiveSimMaxPrice)
|
? normalizeFiveSimMaxPriceValue(message.payload.fiveSimMaxPrice !== undefined ? message.payload.fiveSimMaxPrice : latestState?.fiveSimMaxPrice)
|
||||||
@@ -18427,6 +18650,9 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|||||||
{ includePrimary: true }
|
{ includePrimary: true }
|
||||||
);
|
);
|
||||||
updateHeroSmsPlatformDisplay();
|
updateHeroSmsPlatformDisplay();
|
||||||
|
if (activeProvider === PHONE_SMS_PROVIDER_HERO_SMS) {
|
||||||
|
refreshHeroSmsOperatorOptions({ silent: true, selectedOperator: latestState?.heroSmsOperator });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
message.payload.currentPhoneActivation !== undefined
|
message.payload.currentPhoneActivation !== undefined
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ test('background account history settings are normalized independently from hotm
|
|||||||
extractFunction('normalizePhoneCodePollMaxRounds'),
|
extractFunction('normalizePhoneCodePollMaxRounds'),
|
||||||
extractFunction('normalizeHeroSmsMaxPrice'),
|
extractFunction('normalizeHeroSmsMaxPrice'),
|
||||||
extractFunction('normalizeHeroSmsCountryFallback'),
|
extractFunction('normalizeHeroSmsCountryFallback'),
|
||||||
|
extractFunction('normalizeHeroSmsOperator'),
|
||||||
extractFunction('normalizePhoneSmsProvider'),
|
extractFunction('normalizePhoneSmsProvider'),
|
||||||
extractFunction('normalizeFiveSimCountryId'),
|
extractFunction('normalizeFiveSimCountryId'),
|
||||||
extractFunction('normalizeFiveSimCountryLabel'),
|
extractFunction('normalizeFiveSimCountryLabel'),
|
||||||
@@ -114,6 +115,7 @@ const VERIFICATION_RESEND_COUNT_MIN = 0;
|
|||||||
const VERIFICATION_RESEND_COUNT_MAX = 20;
|
const VERIFICATION_RESEND_COUNT_MAX = 20;
|
||||||
const HERO_SMS_COUNTRY_ID = 52;
|
const HERO_SMS_COUNTRY_ID = 52;
|
||||||
const HERO_SMS_COUNTRY_LABEL = 'Thailand';
|
const HERO_SMS_COUNTRY_LABEL = 'Thailand';
|
||||||
|
const DEFAULT_HERO_SMS_OPERATOR = 'any';
|
||||||
const PHONE_SMS_PROVIDER_HERO_SMS = 'hero-sms';
|
const PHONE_SMS_PROVIDER_HERO_SMS = 'hero-sms';
|
||||||
const PHONE_SMS_PROVIDER_FIVE_SIM = '5sim';
|
const PHONE_SMS_PROVIDER_FIVE_SIM = '5sim';
|
||||||
const PHONE_SMS_PROVIDER_NEXSMS = 'nexsms';
|
const PHONE_SMS_PROVIDER_NEXSMS = 'nexsms';
|
||||||
@@ -280,6 +282,8 @@ return {
|
|||||||
assert.equal(api.normalizePersistentSettingValue('heroSmsMaxPrice', '0.123456'), '0.1235');
|
assert.equal(api.normalizePersistentSettingValue('heroSmsMaxPrice', '0.123456'), '0.1235');
|
||||||
assert.equal(api.normalizePersistentSettingValue('heroSmsMaxPrice', '0'), '');
|
assert.equal(api.normalizePersistentSettingValue('heroSmsMaxPrice', '0'), '');
|
||||||
assert.equal(api.normalizePersistentSettingValue('heroSmsPreferredPrice', '0.051234'), '0.0512');
|
assert.equal(api.normalizePersistentSettingValue('heroSmsPreferredPrice', '0.051234'), '0.0512');
|
||||||
|
assert.equal(api.normalizePersistentSettingValue('heroSmsOperator', ' AIS!! '), 'ais');
|
||||||
|
assert.equal(api.normalizePersistentSettingValue('heroSmsOperator', ''), 'any');
|
||||||
assert.equal(api.normalizePersistentSettingValue('signupMethod', 'phone'), 'phone');
|
assert.equal(api.normalizePersistentSettingValue('signupMethod', 'phone'), 'phone');
|
||||||
assert.equal(api.normalizePersistentSettingValue('signupMethod', 'unknown'), 'email');
|
assert.equal(api.normalizePersistentSettingValue('signupMethod', 'unknown'), 'email');
|
||||||
assert.equal(api.normalizePersistentSettingValue('activeFlowId', 'codex'), 'openai');
|
assert.equal(api.normalizePersistentSettingValue('activeFlowId', 'codex'), 'openai');
|
||||||
|
|||||||
@@ -83,6 +83,78 @@ test('phone verification helper requests HeroSMS numbers with fixed OpenAI and T
|
|||||||
assert.equal(requests[1].searchParams.get('api_key'), 'demo-key');
|
assert.equal(requests[1].searchParams.get('api_key'), 'demo-key');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('phone verification helper appends HeroSMS operator when configured', async () => {
|
||||||
|
const requests = [];
|
||||||
|
const helpers = api.createPhoneVerificationHelpers({
|
||||||
|
addLog: async () => {},
|
||||||
|
ensureStep8SignupPageReady: async () => {},
|
||||||
|
fetchImpl: async (url) => {
|
||||||
|
const parsedUrl = new URL(url);
|
||||||
|
requests.push(parsedUrl);
|
||||||
|
const action = parsedUrl.searchParams.get('action');
|
||||||
|
if (action === 'getPrices') {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
text: async () => buildHeroSmsPricesPayload(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (action === 'getNumber') {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
text: async () => 'ACCESS_NUMBER:123456:66959916439',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
throw new Error(`Unexpected HeroSMS action: ${action}`);
|
||||||
|
},
|
||||||
|
getState: async () => ({ heroSmsApiKey: 'demo-key', heroSmsOperator: 'ais' }),
|
||||||
|
sendToContentScriptResilient: async () => ({}),
|
||||||
|
setState: async () => {},
|
||||||
|
sleepWithStop: async () => {},
|
||||||
|
throwIfStopped: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
await helpers.requestPhoneActivation({ heroSmsApiKey: 'demo-key', heroSmsOperator: ' AIS!! ' });
|
||||||
|
|
||||||
|
const getNumberRequest = requests.find((requestUrl) => requestUrl.searchParams.get('action') === 'getNumber');
|
||||||
|
assert.equal(getNumberRequest.searchParams.get('operator'), 'ais');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('phone verification helper reads latest HeroSMS operator from persistent state', async () => {
|
||||||
|
const requests = [];
|
||||||
|
const helpers = api.createPhoneVerificationHelpers({
|
||||||
|
addLog: async () => {},
|
||||||
|
ensureStep8SignupPageReady: async () => {},
|
||||||
|
fetchImpl: async (url) => {
|
||||||
|
const parsedUrl = new URL(url);
|
||||||
|
requests.push(parsedUrl);
|
||||||
|
const action = parsedUrl.searchParams.get('action');
|
||||||
|
if (action === 'getPrices') {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
text: async () => buildHeroSmsPricesPayload(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (action === 'getNumber') {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
text: async () => 'ACCESS_NUMBER:123456:66959916439',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
throw new Error(`Unexpected HeroSMS action: ${action}`);
|
||||||
|
},
|
||||||
|
getState: async () => ({ heroSmsApiKey: 'demo-key', heroSmsOperator: 'dtac' }),
|
||||||
|
sendToContentScriptResilient: async () => ({}),
|
||||||
|
setState: async () => {},
|
||||||
|
sleepWithStop: async () => {},
|
||||||
|
throwIfStopped: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
await helpers.requestPhoneActivation({ heroSmsApiKey: 'demo-key' });
|
||||||
|
|
||||||
|
const getNumberRequest = requests.find((requestUrl) => requestUrl.searchParams.get('action') === 'getNumber');
|
||||||
|
assert.equal(getNumberRequest.searchParams.get('operator'), 'dtac');
|
||||||
|
});
|
||||||
|
|
||||||
test('signup phone helper persists signup runtime state without touching add-phone activation', async () => {
|
test('signup phone helper persists signup runtime state without touching add-phone activation', async () => {
|
||||||
const setStateCalls = [];
|
const setStateCalls = [];
|
||||||
let currentState = {
|
let currentState = {
|
||||||
@@ -2208,6 +2280,152 @@ test('phone verification helper acquires a number from 5sim with fallback countr
|
|||||||
assert.equal(requests[3].pathname, '/v1/user/buy/activation/england/any/openai');
|
assert.equal(requests[3].pathname, '/v1/user/buy/activation/england/any/openai');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('phone verification helper preserves fallback provider while refreshing latest settings', async () => {
|
||||||
|
const heroRequests = [];
|
||||||
|
const fiveSimRequests = [];
|
||||||
|
const submittedNumbers = [];
|
||||||
|
let currentState = {
|
||||||
|
heroSmsApiKey: 'hero-key',
|
||||||
|
phoneSmsProvider: 'hero-sms',
|
||||||
|
phoneSmsProviderOrder: ['hero-sms', '5sim'],
|
||||||
|
heroSmsCountryId: 52,
|
||||||
|
heroSmsCountryLabel: 'Thailand',
|
||||||
|
fiveSimApiKey: 'five-token',
|
||||||
|
fiveSimCountryOrder: ['vietnam'],
|
||||||
|
fiveSimOperator: 'any',
|
||||||
|
fiveSimProduct: 'openai',
|
||||||
|
phoneSmsReuseEnabled: true,
|
||||||
|
verificationResendCount: 0,
|
||||||
|
phoneVerificationReplacementLimit: 1,
|
||||||
|
phoneCodeWaitSeconds: 15,
|
||||||
|
phoneCodeTimeoutWindows: 1,
|
||||||
|
phoneCodePollIntervalSeconds: 1,
|
||||||
|
phoneCodePollMaxRounds: 1,
|
||||||
|
currentPhoneActivation: null,
|
||||||
|
reusablePhoneActivation: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const helpers = api.createPhoneVerificationHelpers({
|
||||||
|
addLog: async () => {},
|
||||||
|
ensureStep8SignupPageReady: async () => {},
|
||||||
|
fetchImpl: async (url, options = {}) => {
|
||||||
|
const parsedUrl = new URL(url);
|
||||||
|
const action = parsedUrl.searchParams.get('action');
|
||||||
|
if (parsedUrl.hostname === 'hero-sms.com') {
|
||||||
|
heroRequests.push(parsedUrl);
|
||||||
|
if (action === 'getPrices') {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
text: async () => buildHeroSmsPricesPayload({ country: '52', cost: 0.05, count: 5 }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (action === 'getNumber' || action === 'getNumberV2') {
|
||||||
|
return { ok: true, text: async () => 'NO_NUMBERS' };
|
||||||
|
}
|
||||||
|
throw new Error(`Unexpected HeroSMS action: ${action}`);
|
||||||
|
}
|
||||||
|
fiveSimRequests.push({ url: parsedUrl, options });
|
||||||
|
if (parsedUrl.pathname === '/v1/guest/prices') {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
text: async () => JSON.stringify({
|
||||||
|
openai: {
|
||||||
|
vietnam: {
|
||||||
|
any: {
|
||||||
|
cost: 0.08,
|
||||||
|
count: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (parsedUrl.pathname === '/v1/user/buy/activation/vietnam/any/openai') {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
text: async () => JSON.stringify({
|
||||||
|
id: 5020,
|
||||||
|
phone: '+84901122334',
|
||||||
|
country: 'vietnam',
|
||||||
|
country_name: 'Vietnam',
|
||||||
|
product: 'openai',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (parsedUrl.pathname === '/v1/user/check/5020') {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
text: async () => JSON.stringify({
|
||||||
|
id: 5020,
|
||||||
|
phone: '+84901122334',
|
||||||
|
status: 'RECEIVED',
|
||||||
|
sms: [{ text: 'OpenAI code 123456' }],
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (parsedUrl.pathname === '/v1/user/finish/5020') {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
text: async () => JSON.stringify({ status: 'FINISHED' }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
throw new Error(`Unexpected 5sim request: ${parsedUrl.pathname}`);
|
||||||
|
},
|
||||||
|
getOAuthFlowStepTimeoutMs: async (defaultTimeoutMs) => defaultTimeoutMs,
|
||||||
|
getState: async () => ({ ...currentState }),
|
||||||
|
sendToContentScriptResilient: async (_source, message) => {
|
||||||
|
if (message.type === 'SUBMIT_PHONE_NUMBER') {
|
||||||
|
submittedNumbers.push(message.payload.phoneNumber);
|
||||||
|
return { phoneVerificationPage: true, url: 'https://auth.openai.com/phone-verification' };
|
||||||
|
}
|
||||||
|
if (message.type === 'SUBMIT_PHONE_VERIFICATION_CODE') {
|
||||||
|
return { success: true, consentReady: true, url: 'https://auth.openai.com/authorize' };
|
||||||
|
}
|
||||||
|
throw new Error(`Unexpected content-script message: ${message.type}`);
|
||||||
|
},
|
||||||
|
setState: async (updates) => {
|
||||||
|
currentState = { ...currentState, ...updates };
|
||||||
|
},
|
||||||
|
sleepWithStop: async () => {},
|
||||||
|
throwIfStopped: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await helpers.completePhoneVerificationFlow(1, {
|
||||||
|
addPhonePage: true,
|
||||||
|
phoneVerificationPage: false,
|
||||||
|
url: 'https://auth.openai.com/add-phone',
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepStrictEqual(result, {
|
||||||
|
success: true,
|
||||||
|
consentReady: true,
|
||||||
|
url: 'https://auth.openai.com/authorize',
|
||||||
|
});
|
||||||
|
assert.deepStrictEqual(submittedNumbers, ['+84901122334']);
|
||||||
|
assert.equal(currentState.reusablePhoneActivation.provider, '5sim');
|
||||||
|
assert.equal(currentState.reusablePhoneActivation.activationId, '5020');
|
||||||
|
assert.equal(heroRequests.some((requestUrl) => requestUrl.searchParams.get('action') === 'getNumber'), true);
|
||||||
|
assert.equal(heroRequests.some((requestUrl) => requestUrl.searchParams.get('action') === 'getNumberV2'), true);
|
||||||
|
assert.equal(
|
||||||
|
heroRequests.every((requestUrl) => ['getPrices', 'getNumber', 'getNumberV2'].includes(requestUrl.searchParams.get('action'))),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
fiveSimRequests.map((entry) => entry.url.pathname),
|
||||||
|
[
|
||||||
|
'/v1/guest/prices',
|
||||||
|
'/v1/user/buy/activation/vietnam/any/openai',
|
||||||
|
'/v1/user/check/5020',
|
||||||
|
'/v1/user/finish/5020',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
assert.equal(fiveSimRequests[1].options.headers.Authorization, 'Bearer five-token');
|
||||||
|
});
|
||||||
|
|
||||||
test('phone verification helper prefers phoneSmsReuseEnabled over legacy heroSmsReuseEnabled for 5sim acquisition', async () => {
|
test('phone verification helper prefers phoneSmsReuseEnabled over legacy heroSmsReuseEnabled for 5sim acquisition', async () => {
|
||||||
const requests = [];
|
const requests = [];
|
||||||
const helpers = api.createPhoneVerificationHelpers({
|
const helpers = api.createPhoneVerificationHelpers({
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ test('sidepanel html exposes phone verification toggle and multi-provider SMS ro
|
|||||||
assert.match(html, /id="row-hero-sms-country-fallback"/);
|
assert.match(html, /id="row-hero-sms-country-fallback"/);
|
||||||
assert.match(html, /id="row-hero-sms-acquire-priority"/);
|
assert.match(html, /id="row-hero-sms-acquire-priority"/);
|
||||||
assert.match(html, /id="select-hero-sms-acquire-priority"/);
|
assert.match(html, /id="select-hero-sms-acquire-priority"/);
|
||||||
|
assert.match(html, /id="row-hero-sms-operator"/);
|
||||||
|
assert.match(html, /id="select-hero-sms-operator"/);
|
||||||
assert.match(html, /id="select-hero-sms-country"[^>]*multiple/);
|
assert.match(html, /id="select-hero-sms-country"[^>]*multiple/);
|
||||||
assert.doesNotMatch(html, /id="select-hero-sms-country-fallback"/);
|
assert.doesNotMatch(html, /id="select-hero-sms-country-fallback"/);
|
||||||
assert.match(html, /id="row-hero-sms-api-key"/);
|
assert.match(html, /id="row-hero-sms-api-key"/);
|
||||||
@@ -660,6 +662,7 @@ const rowHeroSmsPlatform = { style: { display: 'none' } };
|
|||||||
const rowHeroSmsCountry = { style: { display: 'none' } };
|
const rowHeroSmsCountry = { style: { display: 'none' } };
|
||||||
const rowHeroSmsCountryFallback = { style: { display: 'none' } };
|
const rowHeroSmsCountryFallback = { style: { display: 'none' } };
|
||||||
const rowHeroSmsAcquirePriority = { style: { display: 'none' } };
|
const rowHeroSmsAcquirePriority = { style: { display: 'none' } };
|
||||||
|
const rowHeroSmsOperator = { style: { display: 'none' } };
|
||||||
const rowHeroSmsApiKey = { style: { display: 'none' } };
|
const rowHeroSmsApiKey = { style: { display: 'none' } };
|
||||||
const rowHeroSmsMaxPrice = { style: { display: 'none' } };
|
const rowHeroSmsMaxPrice = { style: { display: 'none' } };
|
||||||
const rowFiveSimApiKey = { style: { display: 'none' } };
|
const rowFiveSimApiKey = { style: { display: 'none' } };
|
||||||
@@ -741,6 +744,7 @@ return {
|
|||||||
rowHeroSmsCountry,
|
rowHeroSmsCountry,
|
||||||
rowHeroSmsCountryFallback,
|
rowHeroSmsCountryFallback,
|
||||||
rowHeroSmsAcquirePriority,
|
rowHeroSmsAcquirePriority,
|
||||||
|
rowHeroSmsOperator,
|
||||||
rowHeroSmsApiKey,
|
rowHeroSmsApiKey,
|
||||||
rowHeroSmsMaxPrice,
|
rowHeroSmsMaxPrice,
|
||||||
rowFiveSimApiKey,
|
rowFiveSimApiKey,
|
||||||
@@ -795,6 +799,7 @@ return {
|
|||||||
assert.equal(api.rowHeroSmsCountry.style.display, 'none');
|
assert.equal(api.rowHeroSmsCountry.style.display, 'none');
|
||||||
assert.equal(api.rowHeroSmsCountryFallback.style.display, 'none');
|
assert.equal(api.rowHeroSmsCountryFallback.style.display, 'none');
|
||||||
assert.equal(api.rowHeroSmsAcquirePriority.style.display, 'none');
|
assert.equal(api.rowHeroSmsAcquirePriority.style.display, 'none');
|
||||||
|
assert.equal(api.rowHeroSmsOperator.style.display, 'none');
|
||||||
assert.equal(api.rowHeroSmsApiKey.style.display, 'none');
|
assert.equal(api.rowHeroSmsApiKey.style.display, 'none');
|
||||||
assert.equal(api.rowHeroSmsMaxPrice.style.display, 'none');
|
assert.equal(api.rowHeroSmsMaxPrice.style.display, 'none');
|
||||||
assert.equal(api.rowFiveSimOperator.style.display, 'none');
|
assert.equal(api.rowFiveSimOperator.style.display, 'none');
|
||||||
@@ -845,6 +850,7 @@ return {
|
|||||||
assert.equal(api.rowHeroSmsCountry.style.display, '');
|
assert.equal(api.rowHeroSmsCountry.style.display, '');
|
||||||
assert.equal(api.rowHeroSmsCountryFallback.style.display, '');
|
assert.equal(api.rowHeroSmsCountryFallback.style.display, '');
|
||||||
assert.equal(api.rowHeroSmsAcquirePriority.style.display, '');
|
assert.equal(api.rowHeroSmsAcquirePriority.style.display, '');
|
||||||
|
assert.equal(api.rowHeroSmsOperator.style.display, '');
|
||||||
assert.equal(api.rowHeroSmsApiKey.style.display, '');
|
assert.equal(api.rowHeroSmsApiKey.style.display, '');
|
||||||
assert.equal(api.rowHeroSmsMaxPrice.style.display, '');
|
assert.equal(api.rowHeroSmsMaxPrice.style.display, '');
|
||||||
assert.equal(api.rowFiveSimOperator.style.display, 'none');
|
assert.equal(api.rowFiveSimOperator.style.display, 'none');
|
||||||
@@ -1001,6 +1007,7 @@ const inputNexSmsApiKey = { value: 'nex-key' };
|
|||||||
const inputNexSmsServiceCode = { value: 'ot' };
|
const inputNexSmsServiceCode = { value: 'ot' };
|
||||||
const inputHeroSmsReuseEnabled = { checked: true };
|
const inputHeroSmsReuseEnabled = { checked: true };
|
||||||
const selectHeroSmsAcquirePriority = { value: 'price' };
|
const selectHeroSmsAcquirePriority = { value: 'price' };
|
||||||
|
const selectHeroSmsOperator = { value: 'AIS!!' };
|
||||||
function getSelectedPhonePreferredActivation() {
|
function getSelectedPhonePreferredActivation() {
|
||||||
return {
|
return {
|
||||||
provider: 'hero-sms',
|
provider: 'hero-sms',
|
||||||
@@ -1039,6 +1046,7 @@ const DEFAULT_HERO_SMS_REUSE_ENABLED = true;
|
|||||||
const HERO_SMS_ACQUIRE_PRIORITY_COUNTRY = 'country';
|
const HERO_SMS_ACQUIRE_PRIORITY_COUNTRY = 'country';
|
||||||
const HERO_SMS_ACQUIRE_PRIORITY_PRICE = 'price';
|
const HERO_SMS_ACQUIRE_PRIORITY_PRICE = 'price';
|
||||||
const DEFAULT_HERO_SMS_ACQUIRE_PRIORITY = HERO_SMS_ACQUIRE_PRIORITY_COUNTRY;
|
const DEFAULT_HERO_SMS_ACQUIRE_PRIORITY = HERO_SMS_ACQUIRE_PRIORITY_COUNTRY;
|
||||||
|
const DEFAULT_HERO_SMS_OPERATOR = 'any';
|
||||||
const PHONE_REPLACEMENT_LIMIT_MIN = 1;
|
const PHONE_REPLACEMENT_LIMIT_MIN = 1;
|
||||||
const PHONE_REPLACEMENT_LIMIT_MAX = 20;
|
const PHONE_REPLACEMENT_LIMIT_MAX = 20;
|
||||||
const DEFAULT_HERO_SMS_COUNTRY_ID = 52;
|
const DEFAULT_HERO_SMS_COUNTRY_ID = 52;
|
||||||
@@ -1101,6 +1109,7 @@ ${extractFunction('normalizeFiveSimCountryFallbackList')}
|
|||||||
${extractFunction('normalizePhoneSmsMaxPriceValue')}
|
${extractFunction('normalizePhoneSmsMaxPriceValue')}
|
||||||
${extractFunction('normalizePhoneSmsMinPriceValue')}
|
${extractFunction('normalizePhoneSmsMinPriceValue')}
|
||||||
${extractFunction('normalizeHeroSmsMaxPriceValue')}
|
${extractFunction('normalizeHeroSmsMaxPriceValue')}
|
||||||
|
${extractFunction('normalizeHeroSmsOperatorValue')}
|
||||||
${extractFunction('normalizePhoneVerificationReplacementLimit')}
|
${extractFunction('normalizePhoneVerificationReplacementLimit')}
|
||||||
${extractFunction('normalizePhoneCodeWaitSecondsValue')}
|
${extractFunction('normalizePhoneCodeWaitSecondsValue')}
|
||||||
${extractFunction('normalizePhoneCodeTimeoutWindowsValue')}
|
${extractFunction('normalizePhoneCodeTimeoutWindowsValue')}
|
||||||
@@ -1153,6 +1162,7 @@ return { collectSettingsPayload };
|
|||||||
assert.equal(payload.freePhoneReuseEnabled, false);
|
assert.equal(payload.freePhoneReuseEnabled, false);
|
||||||
assert.equal(payload.freePhoneReuseAutoEnabled, false);
|
assert.equal(payload.freePhoneReuseAutoEnabled, false);
|
||||||
assert.equal(payload.heroSmsAcquirePriority, 'price');
|
assert.equal(payload.heroSmsAcquirePriority, 'price');
|
||||||
|
assert.equal(payload.heroSmsOperator, 'ais');
|
||||||
assert.equal(payload.heroSmsMinPrice, '0.03');
|
assert.equal(payload.heroSmsMinPrice, '0.03');
|
||||||
assert.equal(payload.heroSmsMaxPrice, '0.12');
|
assert.equal(payload.heroSmsMaxPrice, '0.12');
|
||||||
assert.equal(payload.heroSmsPreferredPrice, '0.0512');
|
assert.equal(payload.heroSmsPreferredPrice, '0.0512');
|
||||||
@@ -1201,6 +1211,7 @@ const PHONE_SMS_PROVIDER_FIVE_SIM = '5sim';
|
|||||||
const DEFAULT_FIVE_SIM_COUNTRY_ID = 'vietnam';
|
const DEFAULT_FIVE_SIM_COUNTRY_ID = 'vietnam';
|
||||||
const DEFAULT_FIVE_SIM_COUNTRY_LABEL = '越南 (Vietnam)';
|
const DEFAULT_FIVE_SIM_COUNTRY_LABEL = '越南 (Vietnam)';
|
||||||
const DEFAULT_FIVE_SIM_OPERATOR = 'any';
|
const DEFAULT_FIVE_SIM_OPERATOR = 'any';
|
||||||
|
const DEFAULT_HERO_SMS_OPERATOR = 'any';
|
||||||
const DEFAULT_HERO_SMS_COUNTRY_ID = 52;
|
const DEFAULT_HERO_SMS_COUNTRY_ID = 52;
|
||||||
const DEFAULT_HERO_SMS_COUNTRY_LABEL = 'Thailand';
|
const DEFAULT_HERO_SMS_COUNTRY_LABEL = 'Thailand';
|
||||||
const FIVE_SIM_SUPPORTED_COUNTRY_ID_SET = new Set(['indonesia', 'thailand', 'vietnam']);
|
const FIVE_SIM_SUPPORTED_COUNTRY_ID_SET = new Set(['indonesia', 'thailand', 'vietnam']);
|
||||||
@@ -1210,6 +1221,7 @@ const inputHeroSmsApiKey = { value: 'hero-live' };
|
|||||||
const inputHeroSmsMinPrice = { value: '0.03' };
|
const inputHeroSmsMinPrice = { value: '0.03' };
|
||||||
const inputHeroSmsMaxPrice = { value: '0.22' };
|
const inputHeroSmsMaxPrice = { value: '0.22' };
|
||||||
const inputFiveSimOperator = { value: 'any' };
|
const inputFiveSimOperator = { value: 'any' };
|
||||||
|
const selectHeroSmsOperator = { value: 'ais', options: [{ value: 'any' }, { value: 'ais' }] };
|
||||||
const displayHeroSmsPriceTiers = { textContent: '' };
|
const displayHeroSmsPriceTiers = { textContent: '' };
|
||||||
const displayPhoneSmsBalance = { textContent: '' };
|
const displayPhoneSmsBalance = { textContent: '' };
|
||||||
const rowHeroSmsPriceTiers = { style: { display: '' } };
|
const rowHeroSmsPriceTiers = { style: { display: '' } };
|
||||||
@@ -1229,6 +1241,7 @@ ${extractFunction('normalizePhoneSmsMinPriceValue')}
|
|||||||
${extractFunction('normalizePhoneSmsMaxPriceValue')}
|
${extractFunction('normalizePhoneSmsMaxPriceValue')}
|
||||||
${extractFunction('normalizeHeroSmsCountryId')}
|
${extractFunction('normalizeHeroSmsCountryId')}
|
||||||
${extractFunction('normalizeHeroSmsCountryLabel')}
|
${extractFunction('normalizeHeroSmsCountryLabel')}
|
||||||
|
${extractFunction('normalizeHeroSmsOperatorValue')}
|
||||||
${extractFunction('normalizeHeroSmsCountryFallbackList')}
|
${extractFunction('normalizeHeroSmsCountryFallbackList')}
|
||||||
${extractFunction('normalizeFiveSimCountryFallbackList')}
|
${extractFunction('normalizeFiveSimCountryFallbackList')}
|
||||||
function getSelectedHeroSmsCountryOption() {
|
function getSelectedHeroSmsCountryOption() {
|
||||||
@@ -1244,6 +1257,8 @@ function syncHeroSmsFallbackSelectionOrderFromSelect() {
|
|||||||
function syncLatestState(patch) { latestState = { ...latestState, ...patch }; }
|
function syncLatestState(patch) { latestState = { ...latestState, ...patch }; }
|
||||||
function loadHeroSmsCountries() { return Promise.resolve(); }
|
function loadHeroSmsCountries() { return Promise.resolve(); }
|
||||||
function applyHeroSmsFallbackSelection() {}
|
function applyHeroSmsFallbackSelection() {}
|
||||||
|
function setHeroSmsOperatorSelectValue(operator = latestState?.heroSmsOperator) { selectHeroSmsOperator.value = normalizeHeroSmsOperatorValue(operator); }
|
||||||
|
function refreshHeroSmsOperatorOptions() { return Promise.resolve(); }
|
||||||
function updatePhoneVerificationSettingsUI() {}
|
function updatePhoneVerificationSettingsUI() {}
|
||||||
function markSettingsDirty() {}
|
function markSettingsDirty() {}
|
||||||
function saveSettings() { savedPayload = { ...latestState }; return Promise.resolve(); }
|
function saveSettings() { savedPayload = { ...latestState }; return Promise.resolve(); }
|
||||||
@@ -1291,6 +1306,26 @@ return {
|
|||||||
assert.equal(api.savedPayload.fiveSimMinPrice, '0.88');
|
assert.equal(api.savedPayload.fiveSimMinPrice, '0.88');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('HeroSMS operator helpers normalize keyed operator payloads', () => {
|
||||||
|
const api = new Function(`
|
||||||
|
const DEFAULT_HERO_SMS_OPERATOR = 'any';
|
||||||
|
${extractFunction('normalizeHeroSmsOperatorValue')}
|
||||||
|
${extractFunction('parseHeroSmsOperatorsPayload')}
|
||||||
|
return { normalizeHeroSmsOperatorValue, parseHeroSmsOperatorsPayload };
|
||||||
|
`)();
|
||||||
|
|
||||||
|
assert.equal(api.normalizeHeroSmsOperatorValue(' AIS!! '), 'ais');
|
||||||
|
assert.equal(api.normalizeHeroSmsOperatorValue('', 'dtac'), 'dtac');
|
||||||
|
const parsed = api.parseHeroSmsOperatorsPayload({
|
||||||
|
operators: {
|
||||||
|
52: [' AIS ', 'dtac', 'AIS'],
|
||||||
|
6: ['telkomsel'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
assert.deepStrictEqual(parsed.get('52'), ['ais', 'dtac']);
|
||||||
|
assert.deepStrictEqual(parsed.get('6'), ['telkomsel']);
|
||||||
|
});
|
||||||
|
|
||||||
test('formatPhoneSmsPriceEntriesSummary treats HeroSMS physicalCount=0 as out of stock even when count is positive', () => {
|
test('formatPhoneSmsPriceEntriesSummary treats HeroSMS physicalCount=0 as out of stock even when count is positive', () => {
|
||||||
const api = new Function(`
|
const api = new Function(`
|
||||||
${extractFunction('normalizeHeroSmsPriceForPreview')}
|
${extractFunction('normalizeHeroSmsPriceForPreview')}
|
||||||
|
|||||||
Reference in New Issue
Block a user