Compare commits
4 Commits
5f871c3c40
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| c360e3f569 | |||
| 39af4f9ca4 | |||
| b69490e632 | |||
| b5980f5b46 |
+69
-2
@@ -719,8 +719,6 @@ const DEFAULT_FIVE_SIM_COUNTRY_ORDER = Object.freeze(['thailand']);
|
|||||||
const DEFAULT_NEX_SMS_BASE_URL = 'https://api.nexsms.net';
|
const DEFAULT_NEX_SMS_BASE_URL = 'https://api.nexsms.net';
|
||||||
const DEFAULT_NEX_SMS_SERVICE_CODE = 'ot';
|
const DEFAULT_NEX_SMS_SERVICE_CODE = 'ot';
|
||||||
const DEFAULT_NEX_SMS_COUNTRY_ORDER = Object.freeze([1]);
|
const DEFAULT_NEX_SMS_COUNTRY_ORDER = Object.freeze([1]);
|
||||||
const DEFAULT_SMS_BOWER_SERVICE_CODE = 'ot';
|
|
||||||
const DEFAULT_SMS_BOWER_COUNTRY_ORDER = Object.freeze([52]);
|
|
||||||
const DEFAULT_MADAO_BASE_URL = 'http://127.0.0.1:7822';
|
const DEFAULT_MADAO_BASE_URL = 'http://127.0.0.1:7822';
|
||||||
const DEFAULT_MADAO_MODE = 'routing_plan';
|
const DEFAULT_MADAO_MODE = 'routing_plan';
|
||||||
const DEFAULT_HERO_SMS_REUSE_ENABLED = true;
|
const DEFAULT_HERO_SMS_REUSE_ENABLED = true;
|
||||||
@@ -1453,6 +1451,11 @@ const PERSISTED_SETTING_DEFAULTS = {
|
|||||||
nexSmsCountryOrder: [...DEFAULT_NEX_SMS_COUNTRY_ORDER],
|
nexSmsCountryOrder: [...DEFAULT_NEX_SMS_COUNTRY_ORDER],
|
||||||
nexSmsServiceCode: DEFAULT_NEX_SMS_SERVICE_CODE,
|
nexSmsServiceCode: DEFAULT_NEX_SMS_SERVICE_CODE,
|
||||||
smsBowerApiKey: '',
|
smsBowerApiKey: '',
|
||||||
|
smsBowerCountryId: 6,
|
||||||
|
smsBowerCountryLabel: 'Indonesia',
|
||||||
|
smsBowerCountryOrder: [6],
|
||||||
|
smsBowerMinPrice: '',
|
||||||
|
smsBowerMaxPrice: '',
|
||||||
madaoBaseUrl: DEFAULT_MADAO_BASE_URL,
|
madaoBaseUrl: DEFAULT_MADAO_BASE_URL,
|
||||||
madaoHttpSecret: '',
|
madaoHttpSecret: '',
|
||||||
madaoMode: DEFAULT_MADAO_MODE,
|
madaoMode: DEFAULT_MADAO_MODE,
|
||||||
@@ -2205,6 +2208,59 @@ function normalizeNexSmsServiceCode(value = '', fallback = DEFAULT_NEX_SMS_SERVI
|
|||||||
return fallbackNormalized || DEFAULT_NEX_SMS_SERVICE_CODE;
|
return fallbackNormalized || DEFAULT_NEX_SMS_SERVICE_CODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSmsBowerCountryId(value, fallback = 6) {
|
||||||
|
const parsed = Math.floor(Number(value));
|
||||||
|
if (Number.isFinite(parsed) && parsed >= 0) {
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
const fallbackParsed = Math.floor(Number(fallback));
|
||||||
|
if (Number.isFinite(fallbackParsed) && fallbackParsed >= 0) {
|
||||||
|
return fallbackParsed;
|
||||||
|
}
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeSmsBowerCountryLabel(value = '', fallback = 'Indonesia') {
|
||||||
|
return String(value || '').trim() || fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeSmsBowerCountryOrder(value = []) {
|
||||||
|
const source = Array.isArray(value)
|
||||||
|
? value
|
||||||
|
: String(value || '')
|
||||||
|
.split(/[\r\n,,;;]+/)
|
||||||
|
.map((entry) => String(entry || '').trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
const normalized = [];
|
||||||
|
const seen = new Set();
|
||||||
|
source.forEach((entry) => {
|
||||||
|
const id = normalizeSmsBowerCountryId(
|
||||||
|
entry && typeof entry === 'object' && !Array.isArray(entry)
|
||||||
|
? (entry.id ?? entry.countryId ?? entry.country ?? '')
|
||||||
|
: entry,
|
||||||
|
-1
|
||||||
|
);
|
||||||
|
if (id < 0 || seen.has(id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
seen.add(id);
|
||||||
|
normalized.push(id);
|
||||||
|
});
|
||||||
|
return normalized.length ? normalized.slice(0, 10) : [6];
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeSmsBowerMaxPrice(value = '') {
|
||||||
|
const normalized = String(value || '').trim();
|
||||||
|
if (!normalized) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
const numeric = Number(normalized.replace(',', '.'));
|
||||||
|
if (!Number.isFinite(numeric) || numeric < 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return String(Number(numeric.toFixed(4))).replace(/\.0+$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeMaDaoBaseUrl(value = '') {
|
function normalizeMaDaoBaseUrl(value = '') {
|
||||||
const normalized = normalizeLocalHttpBaseUrl(value, DEFAULT_MADAO_BASE_URL);
|
const normalized = normalizeLocalHttpBaseUrl(value, DEFAULT_MADAO_BASE_URL);
|
||||||
try {
|
try {
|
||||||
@@ -3600,6 +3656,17 @@ function normalizePersistentSettingValue(key, value) {
|
|||||||
return normalizeNexSmsCountryOrder(value);
|
return normalizeNexSmsCountryOrder(value);
|
||||||
case 'nexSmsServiceCode':
|
case 'nexSmsServiceCode':
|
||||||
return normalizeNexSmsServiceCode(value);
|
return normalizeNexSmsServiceCode(value);
|
||||||
|
case 'smsBowerApiKey':
|
||||||
|
return String(value || '');
|
||||||
|
case 'smsBowerCountryId':
|
||||||
|
return normalizeSmsBowerCountryId(value);
|
||||||
|
case 'smsBowerCountryLabel':
|
||||||
|
return normalizeSmsBowerCountryLabel(value);
|
||||||
|
case 'smsBowerCountryOrder':
|
||||||
|
return normalizeSmsBowerCountryOrder(value);
|
||||||
|
case 'smsBowerMinPrice':
|
||||||
|
case 'smsBowerMaxPrice':
|
||||||
|
return normalizeSmsBowerMaxPrice(value);
|
||||||
case 'madaoBaseUrl':
|
case 'madaoBaseUrl':
|
||||||
return normalizeMaDaoBaseUrl(value);
|
return normalizeMaDaoBaseUrl(value);
|
||||||
case 'madaoHttpSecret':
|
case 'madaoHttpSecret':
|
||||||
|
|||||||
@@ -208,9 +208,9 @@
|
|||||||
throw new Error(`步骤 ${completionStepForState(currentState)}:邮箱注册模式 OAuth 登录不应进入添加邮箱页。URL: ${result?.url || ''}`.trim());
|
throw new Error(`步骤 ${completionStepForState(currentState)}:邮箱注册模式 OAuth 登录不应进入添加邮箱页。URL: ${result?.url || ''}`.trim());
|
||||||
}
|
}
|
||||||
if (isStep7AddPhoneResult(result) || isStep7PhoneVerificationResult(result)) {
|
if (isStep7AddPhoneResult(result) || isStep7PhoneVerificationResult(result)) {
|
||||||
payload.skipLoginVerificationStep = true;
|
|
||||||
payload.addPhonePage = isStep7AddPhoneResult(result);
|
payload.addPhonePage = isStep7AddPhoneResult(result);
|
||||||
payload.phoneVerificationPage = isStep7PhoneVerificationResult(result);
|
payload.phoneVerificationPage = isStep7PhoneVerificationResult(result);
|
||||||
|
payload.directOAuthConsentPage = false;
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
if (isStep7PlainVerificationResult(result)) {
|
if (isStep7PlainVerificationResult(result)) {
|
||||||
@@ -233,8 +233,8 @@
|
|||||||
}
|
}
|
||||||
await completeNodeFromBackground(state?.nodeId || 'oauth-login', {
|
await completeNodeFromBackground(state?.nodeId || 'oauth-login', {
|
||||||
loginVerificationRequestedAt: null,
|
loginVerificationRequestedAt: null,
|
||||||
skipLoginVerificationStep: true,
|
|
||||||
addPhonePage: true,
|
addPhonePage: true,
|
||||||
|
phoneVerificationPage: false,
|
||||||
directOAuthConsentPage: false,
|
directOAuthConsentPage: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
})(typeof self !== 'undefined' ? self : globalThis, function createSmsBowerProviderModule() {
|
})(typeof self !== 'undefined' ? self : globalThis, function createSmsBowerProviderModule() {
|
||||||
const PROVIDER_ID = 'sms-bower';
|
const PROVIDER_ID = 'sms-bower';
|
||||||
const DEFAULT_BASE_URL = 'https://smsbower.page/stubs/handler_api.php';
|
const DEFAULT_BASE_URL = 'https://smsbower.page/stubs/handler_api.php';
|
||||||
const DEFAULT_SERVICE_CODE = 'ot';
|
const DEFAULT_SERVICE_CODE = 'dr';
|
||||||
const DEFAULT_SERVICE_LABEL = 'OpenAI';
|
const DEFAULT_SERVICE_LABEL = 'OpenAI';
|
||||||
const DEFAULT_COUNTRY_ID = 52;
|
const DEFAULT_COUNTRY_ID = 6;
|
||||||
const DEFAULT_COUNTRY_LABEL = 'Thailand';
|
const DEFAULT_COUNTRY_LABEL = 'Indonesia';
|
||||||
const DEFAULT_REQUEST_TIMEOUT_MS = 20000;
|
const DEFAULT_REQUEST_TIMEOUT_MS = 20000;
|
||||||
const DEFAULT_POLL_TIMEOUT_MS = 180000;
|
const DEFAULT_POLL_TIMEOUT_MS = 180000;
|
||||||
const DEFAULT_POLL_INTERVAL_MS = 5000;
|
const DEFAULT_POLL_INTERVAL_MS = 5000;
|
||||||
@@ -160,8 +160,9 @@
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
const message = describePayload(payload);
|
const message = describePayload(payload);
|
||||||
if (/^(BAD_KEY|BAD_ACTION|BAD_SERVICE|BAD_STATUS|NO_ACTIVATION|EARLY_CANCEL_DENIED|BAD_COUNTRY)\b/i.test(message)) {
|
const apiStatus = payload && typeof payload === 'object' && !Array.isArray(payload) ? Number(payload.status) : null;
|
||||||
const error = new Error(`${actionLabel}失败:${message}`);
|
if (apiStatus === 0 || /^(BAD_KEY|BAD_ACTION|BAD_SERVICE|BAD_STATUS|NO_ACTIVATION|EARLY_CANCEL_DENIED|BAD_COUNTRY)\b/i.test(message)) {
|
||||||
|
const error = new Error(`${actionLabel}失败:${message || 'SMS Bower API 返回失败状态'}`);
|
||||||
error.payload = payload;
|
error.payload = payload;
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@@ -220,7 +221,7 @@
|
|||||||
async function fetchPrices(state = {}, countryConfig = {}, deps = {}) {
|
async function fetchPrices(state = {}, countryConfig = {}, deps = {}) {
|
||||||
const config = resolveConfig(state, deps);
|
const config = resolveConfig(state, deps);
|
||||||
return fetchPayload(config, {
|
return fetchPayload(config, {
|
||||||
action: 'getPrices',
|
action: 'getPricesV3',
|
||||||
service: config.serviceCode,
|
service: config.serviceCode,
|
||||||
country: normalizeSmsBowerCountryId(countryConfig?.id ?? state.smsBowerCountryId, DEFAULT_COUNTRY_ID),
|
country: normalizeSmsBowerCountryId(countryConfig?.id ?? state.smsBowerCountryId, DEFAULT_COUNTRY_ID),
|
||||||
}, 'SMS Bower 查询价格');
|
}, 'SMS Bower 查询价格');
|
||||||
@@ -232,12 +233,21 @@
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
if (!payload || typeof payload !== 'object') return entries;
|
if (!payload || typeof payload !== 'object') return entries;
|
||||||
const cost = Number(payload.cost ?? payload.price ?? payload.Price);
|
const directCount = Number(payload.count ?? payload.qty ?? payload.Qty);
|
||||||
if (Number.isFinite(cost) && cost >= 0) {
|
const directPrice = Number(payload.cost ?? payload.price ?? payload.Price);
|
||||||
const count = Number(payload.count ?? payload.qty ?? payload.Qty);
|
if (Number.isFinite(directPrice) && directPrice >= 0) {
|
||||||
entries.push({ cost, count: Number.isFinite(count) ? count : 0, inStock: !Number.isFinite(count) || count > 0 });
|
entries.push({ cost: directPrice, count: Number.isFinite(directCount) ? directCount : 0, inStock: !Number.isFinite(directCount) || directCount > 0 });
|
||||||
}
|
}
|
||||||
Object.values(payload).forEach((entry) => collectPriceEntries(entry, entries));
|
Object.entries(payload).forEach(([key, entry]) => {
|
||||||
|
if (entry && typeof entry === 'object' && !Array.isArray(entry)) {
|
||||||
|
const keyedPrice = Number(key);
|
||||||
|
const keyedCount = Number(entry.count ?? entry.qty ?? entry.Qty);
|
||||||
|
if (/^\d+(?:\.\d+)?$/.test(String(key)) && String(key).includes('.') && Number.isFinite(keyedPrice) && keyedPrice >= 0 && !Number.isFinite(Number(entry.cost ?? entry.price ?? entry.Price))) {
|
||||||
|
entries.push({ cost: keyedPrice, count: Number.isFinite(keyedCount) ? keyedCount : 0, inStock: !Number.isFinite(keyedCount) || keyedCount > 0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collectPriceEntries(entry, entries);
|
||||||
|
});
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,10 +259,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const source = payload && typeof payload === 'object' && !Array.isArray(payload) ? payload : {};
|
const source = payload && typeof payload === 'object' && !Array.isArray(payload) ? payload : {};
|
||||||
const activationId = normalizeText(source.activationId ?? source.id ?? fallback.activationId);
|
const activationId = normalizeText(source.activationId ?? source.activation_id ?? source.id ?? fallback.activationId);
|
||||||
const phoneNumber = normalizeText(source.phoneNumber ?? source.phone ?? fallback.phoneNumber);
|
const phoneNumber = normalizeText(source.phoneNumber ?? source.phone_number ?? source.phone ?? fallback.phoneNumber);
|
||||||
if (!activationId || !phoneNumber) return null;
|
if (!activationId || !phoneNumber) return null;
|
||||||
const countryId = normalizeSmsBowerCountryId(source.countryId ?? source.country ?? fallback.countryId, DEFAULT_COUNTRY_ID);
|
const countryId = normalizeSmsBowerCountryId(source.countryId ?? source.country_id ?? source.countryCode ?? source.country ?? fallback.countryId, DEFAULT_COUNTRY_ID);
|
||||||
return {
|
return {
|
||||||
activationId,
|
activationId,
|
||||||
phoneNumber,
|
phoneNumber,
|
||||||
@@ -287,14 +297,11 @@
|
|||||||
throw new Error(`SMS Bower 价格区间无效:最低购买价 ${range.minPriceLimit} 高于价格上限 ${range.maxPriceLimit}。`);
|
throw new Error(`SMS Bower 价格区间无效:最低购买价 ${range.minPriceLimit} 高于价格上限 ${range.maxPriceLimit}。`);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
action: 'getNumber',
|
action: 'getNumberV2',
|
||||||
service: config.serviceCode,
|
service: config.serviceCode,
|
||||||
country: normalizeSmsBowerCountryId(countryConfig.id, DEFAULT_COUNTRY_ID),
|
country: normalizeSmsBowerCountryId(countryConfig.id, DEFAULT_COUNTRY_ID),
|
||||||
maxPrice: range.maxPriceLimit,
|
maxPrice: range.maxPriceLimit,
|
||||||
minPrice: range.minPriceLimit,
|
minPrice: range.minPriceLimit,
|
||||||
providerIds: normalizeCsvIds(state.smsBowerProviderIds),
|
|
||||||
exceptProviderIds: normalizeCsvIds(state.smsBowerExceptProviderIds),
|
|
||||||
phoneException: normalizeCsvIds(state.smsBowerPhoneException),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +365,11 @@
|
|||||||
await (String(options?.releaseAction || '').trim().toLowerCase() === 'ban'
|
await (String(options?.releaseAction || '').trim().toLowerCase() === 'ban'
|
||||||
? banActivation(state, activation, deps)
|
? banActivation(state, activation, deps)
|
||||||
: cancelActivation(state, activation, deps));
|
: cancelActivation(state, activation, deps));
|
||||||
return { currentTicketId: String(activation?.activationId || activation?.id || ''), nextActivation: null };
|
const nextActivation = await requestActivation(state, {
|
||||||
|
...options,
|
||||||
|
skipPreferredActivation: true,
|
||||||
|
}, deps);
|
||||||
|
return { currentTicketId: String(activation?.activationId || activation?.id || ''), nextActivation };
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractVerificationCode(raw = '') {
|
function extractVerificationCode(raw = '') {
|
||||||
|
|||||||
@@ -1546,6 +1546,26 @@
|
|||||||
data-hide-label="隐藏 SMS Bower Token" aria-label="显示 SMS Bower Token" title="显示 SMS Bower Token"></button>
|
data-hide-label="隐藏 SMS Bower Token" aria-label="显示 SMS Bower Token" title="显示 SMS Bower Token"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="data-row" id="row-sms-bower-country" style="display:none;">
|
||||||
|
<span class="data-label">地区选择</span>
|
||||||
|
<div class="data-inline hero-sms-country-stack">
|
||||||
|
<select id="select-sms-bower-country" class="data-input mono" multiple size="6">
|
||||||
|
<option value="6" selected>印度尼西亚 (Indonesia) #6</option>
|
||||||
|
<option value="52">泰国 (Thailand) #52</option>
|
||||||
|
<option value="16">英国 (United Kingdom) #16</option>
|
||||||
|
<option value="12">美国 (United States) #12</option>
|
||||||
|
<option value="0">俄罗斯 (Russia) #0</option>
|
||||||
|
</select>
|
||||||
|
<span class="data-value hero-sms-country-note">可多选,按列表顺序作为购买重试顺序。</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="data-row" id="row-sms-bower-country-fallback" style="display:none;">
|
||||||
|
<span class="data-label">生效顺序</span>
|
||||||
|
<div class="data-inline data-value-actions">
|
||||||
|
<span id="display-sms-bower-country-fallback-order" class="data-value data-value-fill mono country-order-list">Indonesia #6</span>
|
||||||
|
<button id="btn-sms-bower-country-clear" class="btn btn-ghost btn-xs data-inline-btn" type="button">清空</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="data-row" id="row-madao-base-url" style="display:none;">
|
<div class="data-row" id="row-madao-base-url" style="display:none;">
|
||||||
<span class="data-label">MaDao 地址</span>
|
<span class="data-label">MaDao 地址</span>
|
||||||
<input type="text" id="input-madao-base-url" class="data-input mono"
|
<input type="text" id="input-madao-base-url" class="data-input mono"
|
||||||
|
|||||||
+202
-9
@@ -455,6 +455,8 @@ const rowNexSmsCountry = document.getElementById('row-nex-sms-country');
|
|||||||
const rowNexSmsCountryFallback = document.getElementById('row-nex-sms-country-fallback');
|
const rowNexSmsCountryFallback = document.getElementById('row-nex-sms-country-fallback');
|
||||||
const rowNexSmsServiceCode = document.getElementById('row-nex-sms-service-code');
|
const rowNexSmsServiceCode = document.getElementById('row-nex-sms-service-code');
|
||||||
const rowSmsBowerApiKey = document.getElementById('row-sms-bower-api-key');
|
const rowSmsBowerApiKey = document.getElementById('row-sms-bower-api-key');
|
||||||
|
const rowSmsBowerCountry = document.getElementById('row-sms-bower-country');
|
||||||
|
const rowSmsBowerCountryFallback = document.getElementById('row-sms-bower-country-fallback');
|
||||||
const rowMaDaoBaseUrl = document.getElementById('row-madao-base-url');
|
const rowMaDaoBaseUrl = document.getElementById('row-madao-base-url');
|
||||||
const rowMaDaoHttpSecret = document.getElementById('row-madao-http-secret');
|
const rowMaDaoHttpSecret = document.getElementById('row-madao-http-secret');
|
||||||
const rowMaDaoMode = document.getElementById('row-madao-mode');
|
const rowMaDaoMode = document.getElementById('row-madao-mode');
|
||||||
@@ -541,6 +543,9 @@ const nexSmsCountryMenuShell = document.getElementById('nex-sms-country-menu-she
|
|||||||
const btnNexSmsCountryMenu = document.getElementById('btn-nex-sms-country-menu');
|
const btnNexSmsCountryMenu = document.getElementById('btn-nex-sms-country-menu');
|
||||||
const nexSmsCountryMenu = document.getElementById('nex-sms-country-menu');
|
const nexSmsCountryMenu = document.getElementById('nex-sms-country-menu');
|
||||||
const btnNexSmsCountryClear = document.getElementById('btn-nex-sms-country-clear');
|
const btnNexSmsCountryClear = document.getElementById('btn-nex-sms-country-clear');
|
||||||
|
const selectSmsBowerCountry = document.getElementById('select-sms-bower-country');
|
||||||
|
const displaySmsBowerCountryFallbackOrder = document.getElementById('display-sms-bower-country-fallback-order');
|
||||||
|
const btnSmsBowerCountryClear = document.getElementById('btn-sms-bower-country-clear');
|
||||||
const selectPhoneSmsProviderOrder = document.getElementById('select-phone-sms-provider-order');
|
const selectPhoneSmsProviderOrder = document.getElementById('select-phone-sms-provider-order');
|
||||||
const phoneSmsProviderOrderMenuShell = document.getElementById('phone-sms-provider-order-menu-shell');
|
const phoneSmsProviderOrderMenuShell = document.getElementById('phone-sms-provider-order-menu-shell');
|
||||||
const btnPhoneSmsProviderOrderMenu = document.getElementById('btn-phone-sms-provider-order-menu');
|
const btnPhoneSmsProviderOrderMenu = document.getElementById('btn-phone-sms-provider-order-menu');
|
||||||
@@ -696,8 +701,6 @@ const DEFAULT_FIVE_SIM_OPERATOR = 'any';
|
|||||||
const DEFAULT_FIVE_SIM_PRODUCT = 'openai';
|
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 DEFAULT_SMS_BOWER_COUNTRY_ORDER = Object.freeze([52]);
|
|
||||||
const DEFAULT_SMS_BOWER_SERVICE_CODE = 'ot';
|
|
||||||
const DEFAULT_MADAO_BASE_URL = 'http://127.0.0.1:7822';
|
const DEFAULT_MADAO_BASE_URL = 'http://127.0.0.1:7822';
|
||||||
const MADAO_MODE_ROUTING_PLAN = 'routing_plan';
|
const MADAO_MODE_ROUTING_PLAN = 'routing_plan';
|
||||||
const MADAO_MODE_DIRECT = 'direct';
|
const MADAO_MODE_DIRECT = 'direct';
|
||||||
@@ -742,6 +745,9 @@ const PHONE_SMS_PROVIDER_UI_DESCRIPTORS = Object.freeze({
|
|||||||
[PHONE_SMS_PROVIDER_SMS_BOWER]: Object.freeze({
|
[PHONE_SMS_PROVIDER_SMS_BOWER]: Object.freeze({
|
||||||
rowKeys: Object.freeze([
|
rowKeys: Object.freeze([
|
||||||
'rowSmsBowerApiKey',
|
'rowSmsBowerApiKey',
|
||||||
|
'rowSmsBowerCountry',
|
||||||
|
'rowSmsBowerCountryFallback',
|
||||||
|
'rowHeroSmsMaxPrice',
|
||||||
]),
|
]),
|
||||||
}),
|
}),
|
||||||
[PHONE_SMS_PROVIDER_MADAO]: Object.freeze({
|
[PHONE_SMS_PROVIDER_MADAO]: Object.freeze({
|
||||||
@@ -781,6 +787,8 @@ function getPhoneSmsProviderUiRowMap() {
|
|||||||
rowNexSmsCountryFallback,
|
rowNexSmsCountryFallback,
|
||||||
rowNexSmsServiceCode,
|
rowNexSmsServiceCode,
|
||||||
rowSmsBowerApiKey,
|
rowSmsBowerApiKey,
|
||||||
|
rowSmsBowerCountry,
|
||||||
|
rowSmsBowerCountryFallback,
|
||||||
rowMaDaoBaseUrl,
|
rowMaDaoBaseUrl,
|
||||||
rowMaDaoHttpSecret,
|
rowMaDaoHttpSecret,
|
||||||
rowMaDaoMode,
|
rowMaDaoMode,
|
||||||
@@ -4785,6 +4793,15 @@ function collectSettingsPayload() {
|
|||||||
const fiveSimMinPriceValue = phoneSmsProviderValue === PHONE_SMS_PROVIDER_FIVE_SIM
|
const fiveSimMinPriceValue = phoneSmsProviderValue === PHONE_SMS_PROVIDER_FIVE_SIM
|
||||||
? currentPhoneSmsMinPriceValue
|
? currentPhoneSmsMinPriceValue
|
||||||
: normalizePhoneSmsMinPriceValueSafe(latestState?.fiveSimMinPrice || '', PHONE_SMS_PROVIDER_FIVE_SIM);
|
: normalizePhoneSmsMinPriceValueSafe(latestState?.fiveSimMinPrice || '', PHONE_SMS_PROVIDER_FIVE_SIM);
|
||||||
|
const smsBowerProviderConstant = typeof PHONE_SMS_PROVIDER_SMS_BOWER !== 'undefined'
|
||||||
|
? PHONE_SMS_PROVIDER_SMS_BOWER
|
||||||
|
: 'sms-bower';
|
||||||
|
const smsBowerMaxPriceValue = phoneSmsProviderValue === smsBowerProviderConstant
|
||||||
|
? currentPhoneSmsMaxPriceValue
|
||||||
|
: normalizeHeroSmsMaxPriceValue(latestState?.smsBowerMaxPrice || '');
|
||||||
|
const smsBowerMinPriceValue = phoneSmsProviderValue === smsBowerProviderConstant
|
||||||
|
? currentPhoneSmsMinPriceValue
|
||||||
|
: normalizePhoneSmsMinPriceValueSafe(latestState?.smsBowerMinPrice || '', smsBowerProviderConstant);
|
||||||
const defaultFiveSimProduct = typeof DEFAULT_FIVE_SIM_PRODUCT !== 'undefined'
|
const defaultFiveSimProduct = typeof DEFAULT_FIVE_SIM_PRODUCT !== 'undefined'
|
||||||
? DEFAULT_FIVE_SIM_PRODUCT
|
? DEFAULT_FIVE_SIM_PRODUCT
|
||||||
: 'openai';
|
: 'openai';
|
||||||
@@ -4912,6 +4929,34 @@ function collectSettingsPayload() {
|
|||||||
.map((country) => normalizeNexSmsCountryIdForPayload(country.id, -1))
|
.map((country) => normalizeNexSmsCountryIdForPayload(country.id, -1))
|
||||||
.filter((countryId) => countryId >= 0)
|
.filter((countryId) => countryId >= 0)
|
||||||
: normalizeNexSmsCountryOrderForPayload(latestState?.nexSmsCountryOrder || []);
|
: normalizeNexSmsCountryOrderForPayload(latestState?.nexSmsCountryOrder || []);
|
||||||
|
const normalizeSmsBowerCountryIdForPayload = typeof normalizeSmsBowerCountryIdValue === 'function'
|
||||||
|
? normalizeSmsBowerCountryIdValue
|
||||||
|
: ((value, fallback = 6) => {
|
||||||
|
const parsed = Math.floor(Number(value));
|
||||||
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
||||||
|
});
|
||||||
|
const normalizeSmsBowerCountryLabelForPayload = typeof normalizeSmsBowerCountryLabelValue === 'function'
|
||||||
|
? normalizeSmsBowerCountryLabelValue
|
||||||
|
: ((value = '', fallback = 'Indonesia') => String(value || '').trim() || fallback);
|
||||||
|
const normalizeSmsBowerCountryOrderForPayload = typeof normalizeSmsBowerCountryOrderValue === 'function'
|
||||||
|
? normalizeSmsBowerCountryOrderValue
|
||||||
|
: ((value = []) => {
|
||||||
|
const values = Array.isArray(value) ? value : [value];
|
||||||
|
const mapped = values
|
||||||
|
.map((entry) => normalizeSmsBowerCountryIdForPayload(entry && typeof entry === 'object' ? entry.id : entry, -1))
|
||||||
|
.filter((entry) => entry >= 0);
|
||||||
|
return mapped.length > 0
|
||||||
|
? mapped.map((id) => ({ id, label: id === 6 ? 'Indonesia' : `Country #${id}` }))
|
||||||
|
: [{ id: 6, label: 'Indonesia' }];
|
||||||
|
});
|
||||||
|
const smsBowerSelectedCountries = phoneSmsProviderValue === smsBowerProviderConstant && typeof getSelectedSmsBowerCountries === 'function'
|
||||||
|
? getSelectedSmsBowerCountries()
|
||||||
|
: normalizeSmsBowerCountryOrderForPayload(latestState?.smsBowerCountryOrder || []);
|
||||||
|
const smsBowerCountry = smsBowerSelectedCountries[0] || {
|
||||||
|
id: normalizeSmsBowerCountryIdForPayload(latestState?.smsBowerCountryId),
|
||||||
|
label: normalizeSmsBowerCountryLabelForPayload(latestState?.smsBowerCountryLabel),
|
||||||
|
};
|
||||||
|
const smsBowerCountryOrderValue = smsBowerSelectedCountries.map((country) => country.id);
|
||||||
const heroSmsCountryFallback = phoneSmsProviderValue === PHONE_SMS_PROVIDER_HERO_SMS
|
const heroSmsCountryFallback = phoneSmsProviderValue === PHONE_SMS_PROVIDER_HERO_SMS
|
||||||
? selectedPhoneSmsCountryFallback
|
? selectedPhoneSmsCountryFallback
|
||||||
: normalizeHeroSmsCountryFallbackList(latestState?.heroSmsCountryFallback || []);
|
: normalizeHeroSmsCountryFallbackList(latestState?.heroSmsCountryFallback || []);
|
||||||
@@ -5304,6 +5349,11 @@ function collectSettingsPayload() {
|
|||||||
nexSmsCountryOrder: nexSmsCountryOrderValue,
|
nexSmsCountryOrder: nexSmsCountryOrderValue,
|
||||||
nexSmsServiceCode: nexSmsServiceCodeValue,
|
nexSmsServiceCode: nexSmsServiceCodeValue,
|
||||||
smsBowerApiKey: smsBowerApiKeyValue,
|
smsBowerApiKey: smsBowerApiKeyValue,
|
||||||
|
smsBowerCountryId: smsBowerCountry.id,
|
||||||
|
smsBowerCountryLabel: smsBowerCountry.label,
|
||||||
|
smsBowerCountryOrder: smsBowerCountryOrderValue,
|
||||||
|
smsBowerMinPrice: smsBowerMinPriceValue,
|
||||||
|
smsBowerMaxPrice: smsBowerMaxPriceValue,
|
||||||
madaoBaseUrl: maDaoBaseUrlValue,
|
madaoBaseUrl: maDaoBaseUrlValue,
|
||||||
madaoHttpSecret: maDaoHttpSecretValue,
|
madaoHttpSecret: maDaoHttpSecretValue,
|
||||||
madaoMode: maDaoModeValue,
|
madaoMode: maDaoModeValue,
|
||||||
@@ -5544,6 +5594,9 @@ function normalizePhoneSmsMaxPriceValue(value = '', provider = getSelectedPhoneS
|
|||||||
if (normalizedProvider === PHONE_SMS_PROVIDER_MADAO) {
|
if (normalizedProvider === PHONE_SMS_PROVIDER_MADAO) {
|
||||||
return normalizeMaDaoPriceValue(value);
|
return normalizeMaDaoPriceValue(value);
|
||||||
}
|
}
|
||||||
|
if (normalizedProvider === PHONE_SMS_PROVIDER_SMS_BOWER && typeof window !== 'undefined' && window.PhoneSmsBowerProvider?.normalizeSmsBowerMaxPrice) {
|
||||||
|
return window.PhoneSmsBowerProvider.normalizeSmsBowerMaxPrice(value);
|
||||||
|
}
|
||||||
return normalizeHeroSmsMaxPriceValue(value);
|
return normalizeHeroSmsMaxPriceValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5555,9 +5608,54 @@ function normalizePhoneSmsMinPriceValue(value = '', provider = getSelectedPhoneS
|
|||||||
if (normalizedProvider === PHONE_SMS_PROVIDER_MADAO) {
|
if (normalizedProvider === PHONE_SMS_PROVIDER_MADAO) {
|
||||||
return normalizeMaDaoPriceValue(value);
|
return normalizeMaDaoPriceValue(value);
|
||||||
}
|
}
|
||||||
|
if (normalizedProvider === PHONE_SMS_PROVIDER_SMS_BOWER && typeof window !== 'undefined' && window.PhoneSmsBowerProvider?.normalizeSmsBowerMaxPrice) {
|
||||||
|
return window.PhoneSmsBowerProvider.normalizeSmsBowerMaxPrice(value);
|
||||||
|
}
|
||||||
return normalizeHeroSmsMaxPriceValue(value);
|
return normalizeHeroSmsMaxPriceValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSmsBowerCountryIdValue(value, fallback = 6) {
|
||||||
|
if (typeof window !== 'undefined' && window.PhoneSmsBowerProvider?.normalizeSmsBowerCountryId) {
|
||||||
|
return window.PhoneSmsBowerProvider.normalizeSmsBowerCountryId(value, fallback);
|
||||||
|
}
|
||||||
|
const parsed = Math.floor(Number(value));
|
||||||
|
if (Number.isFinite(parsed) && parsed >= 0) {
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
const fallbackParsed = Math.floor(Number(fallback));
|
||||||
|
return Number.isFinite(fallbackParsed) && fallbackParsed >= 0 ? fallbackParsed : 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeSmsBowerCountryLabelValue(value = '', fallback = 'Indonesia') {
|
||||||
|
if (typeof window !== 'undefined' && window.PhoneSmsBowerProvider?.normalizeSmsBowerCountryLabel) {
|
||||||
|
return window.PhoneSmsBowerProvider.normalizeSmsBowerCountryLabel(value, fallback);
|
||||||
|
}
|
||||||
|
return String(value || '').trim() || fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeSmsBowerCountryOrderValue(value = []) {
|
||||||
|
const source = Array.isArray(value)
|
||||||
|
? value
|
||||||
|
: String(value || '').split(/[\r\n,,;;]+/).map((entry) => String(entry || '').trim()).filter(Boolean);
|
||||||
|
const seen = new Set();
|
||||||
|
const normalized = [];
|
||||||
|
source.forEach((entry) => {
|
||||||
|
const rawId = entry && typeof entry === 'object' && !Array.isArray(entry)
|
||||||
|
? (entry.id ?? entry.countryId)
|
||||||
|
: String(entry || '').trim().match(/^(\d+)/)?.[1];
|
||||||
|
const id = normalizeSmsBowerCountryIdValue(rawId, -1);
|
||||||
|
if (id < 0 || seen.has(id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
seen.add(id);
|
||||||
|
const rawLabel = entry && typeof entry === 'object' && !Array.isArray(entry)
|
||||||
|
? (entry.label ?? entry.countryLabel)
|
||||||
|
: String(entry || '').trim().replace(/^\d+\s*(?:[:|/-]\s*)?/, '');
|
||||||
|
normalized.push({ id, label: normalizeSmsBowerCountryLabelValue(rawLabel, id === 6 ? 'Indonesia' : `Country #${id}`) });
|
||||||
|
});
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
function getPhoneSmsProviderCount() {
|
function getPhoneSmsProviderCount() {
|
||||||
const rootScope = typeof window !== 'undefined' ? window : globalThis;
|
const rootScope = typeof window !== 'undefined' ? window : globalThis;
|
||||||
const registryIds = rootScope.PhoneSmsProviderRegistry?.getProviderIds?.();
|
const registryIds = rootScope.PhoneSmsProviderRegistry?.getProviderIds?.();
|
||||||
@@ -7624,6 +7722,27 @@ function getSelectedNexSmsCountries() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSelectedSmsBowerCountries() {
|
||||||
|
const selected = Array.from(selectSmsBowerCountry?.options || [])
|
||||||
|
.filter((option) => option.selected)
|
||||||
|
.map((option) => ({
|
||||||
|
id: normalizeSmsBowerCountryIdValue(option.value, -1),
|
||||||
|
label: normalizeSmsBowerCountryLabelValue(option.textContent, `Country #${option.value}`),
|
||||||
|
}))
|
||||||
|
.filter((country) => country.id >= 0);
|
||||||
|
return selected.length ? selected : [{ id: 6, label: 'Indonesia' }];
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderSmsBowerCountryFallbackOrder(countries = getSelectedSmsBowerCountries()) {
|
||||||
|
if (!displaySmsBowerCountryFallbackOrder) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const normalized = normalizeSmsBowerCountryOrderValue(countries);
|
||||||
|
displaySmsBowerCountryFallbackOrder.textContent = normalized.length
|
||||||
|
? normalized.map((country, index) => `${index + 1}. ${country.label}(${country.id})`).join(' → ')
|
||||||
|
: 'Indonesia #6';
|
||||||
|
}
|
||||||
|
|
||||||
function updateHeroSmsPlatformDisplay() {
|
function updateHeroSmsPlatformDisplay() {
|
||||||
if (!displayHeroSmsPlatform) {
|
if (!displayHeroSmsPlatform) {
|
||||||
return;
|
return;
|
||||||
@@ -7633,9 +7752,11 @@ function updateHeroSmsPlatformDisplay() {
|
|||||||
? (getSelectedFiveSimCountries()[0] || { id: DEFAULT_FIVE_SIM_COUNTRY_ID, label: DEFAULT_FIVE_SIM_COUNTRY_LABEL })
|
? (getSelectedFiveSimCountries()[0] || { id: DEFAULT_FIVE_SIM_COUNTRY_ID, label: DEFAULT_FIVE_SIM_COUNTRY_LABEL })
|
||||||
: (provider === PHONE_SMS_PROVIDER_NEXSMS
|
: (provider === PHONE_SMS_PROVIDER_NEXSMS
|
||||||
? (getSelectedNexSmsCountries()[0] || { id: DEFAULT_NEX_SMS_COUNTRY_ORDER[0], label: `Country #${DEFAULT_NEX_SMS_COUNTRY_ORDER[0]}` })
|
? (getSelectedNexSmsCountries()[0] || { id: DEFAULT_NEX_SMS_COUNTRY_ORDER[0], label: `Country #${DEFAULT_NEX_SMS_COUNTRY_ORDER[0]}` })
|
||||||
: (provider === PHONE_SMS_PROVIDER_MADAO
|
: (provider === PHONE_SMS_PROVIDER_SMS_BOWER
|
||||||
? { id: '', label: normalizeMaDaoModeValue(selectMaDaoMode?.value || latestState?.madaoMode) === MADAO_MODE_DIRECT ? 'direct' : getSelectedMaDaoRoutingPlanLabel() }
|
? (getSelectedSmsBowerCountries()[0] || { id: 6, label: 'Indonesia' })
|
||||||
: getSelectedHeroSmsCountryOption()));
|
: (provider === PHONE_SMS_PROVIDER_MADAO
|
||||||
|
? { id: '', label: normalizeMaDaoModeValue(selectMaDaoMode?.value || latestState?.madaoMode) === MADAO_MODE_DIRECT ? 'direct' : getSelectedMaDaoRoutingPlanLabel() }
|
||||||
|
: getSelectedHeroSmsCountryOption())));
|
||||||
const countryText = selected?.label ? ` / ${selected.label}` : '';
|
const countryText = selected?.label ? ` / ${selected.label}` : '';
|
||||||
displayHeroSmsPlatform.textContent = `${getPhoneSmsProviderLabel(provider)} / OpenAI${countryText}`;
|
displayHeroSmsPlatform.textContent = `${getPhoneSmsProviderLabel(provider)} / OpenAI${countryText}`;
|
||||||
if (inputHeroSmsApiKey) {
|
if (inputHeroSmsApiKey) {
|
||||||
@@ -12419,6 +12540,22 @@ function applySettingsState(state) {
|
|||||||
? normalizeNexSmsServiceCodeValue(state?.nexSmsServiceCode || defaultNexSmsServiceCode)
|
? normalizeNexSmsServiceCodeValue(state?.nexSmsServiceCode || defaultNexSmsServiceCode)
|
||||||
: String(state?.nexSmsServiceCode || defaultNexSmsServiceCode).trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '') || defaultNexSmsServiceCode;
|
: String(state?.nexSmsServiceCode || defaultNexSmsServiceCode).trim().toLowerCase().replace(/[^a-z0-9_-]+/g, '') || defaultNexSmsServiceCode;
|
||||||
}
|
}
|
||||||
|
if (typeof inputSmsBowerApiKey !== 'undefined' && inputSmsBowerApiKey) {
|
||||||
|
inputSmsBowerApiKey.value = String(state?.smsBowerApiKey || '');
|
||||||
|
}
|
||||||
|
if (typeof selectSmsBowerCountry !== 'undefined' && selectSmsBowerCountry) {
|
||||||
|
const selectedIds = new Set(
|
||||||
|
normalizeSmsBowerCountryOrderValue(state?.smsBowerCountryOrder || [state?.smsBowerCountryId || 6])
|
||||||
|
.map((country) => String(country.id))
|
||||||
|
);
|
||||||
|
if (!selectedIds.size) {
|
||||||
|
selectedIds.add('6');
|
||||||
|
}
|
||||||
|
Array.from(selectSmsBowerCountry.options || []).forEach((option) => {
|
||||||
|
option.selected = selectedIds.has(String(option.value));
|
||||||
|
});
|
||||||
|
renderSmsBowerCountryFallbackOrder();
|
||||||
|
}
|
||||||
if (typeof inputMaDaoBaseUrl !== 'undefined' && inputMaDaoBaseUrl) {
|
if (typeof inputMaDaoBaseUrl !== 'undefined' && inputMaDaoBaseUrl) {
|
||||||
inputMaDaoBaseUrl.value = normalizeMaDaoBaseUrlValue(state?.madaoBaseUrl);
|
inputMaDaoBaseUrl.value = normalizeMaDaoBaseUrlValue(state?.madaoBaseUrl);
|
||||||
}
|
}
|
||||||
@@ -12474,15 +12611,22 @@ function applySettingsState(state) {
|
|||||||
if (typeof selectHeroSmsOperator !== 'undefined' && selectHeroSmsOperator) {
|
if (typeof selectHeroSmsOperator !== 'undefined' && selectHeroSmsOperator) {
|
||||||
setHeroSmsOperatorSelectValue(state?.heroSmsOperator);
|
setHeroSmsOperatorSelectValue(state?.heroSmsOperator);
|
||||||
}
|
}
|
||||||
|
const smsBowerProviderConstant = typeof PHONE_SMS_PROVIDER_SMS_BOWER !== 'undefined'
|
||||||
|
? PHONE_SMS_PROVIDER_SMS_BOWER
|
||||||
|
: 'sms-bower';
|
||||||
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 || '')
|
||||||
: normalizeHeroSmsMaxPriceValue(state?.heroSmsMaxPrice || '');
|
: (restoredPhoneSmsProvider === smsBowerProviderConstant
|
||||||
|
? normalizePhoneSmsMaxPriceValue(state?.smsBowerMaxPrice || '', smsBowerProviderConstant)
|
||||||
|
: normalizeHeroSmsMaxPriceValue(state?.heroSmsMaxPrice || ''));
|
||||||
}
|
}
|
||||||
if (typeof inputHeroSmsMinPrice !== 'undefined' && inputHeroSmsMinPrice) {
|
if (typeof inputHeroSmsMinPrice !== 'undefined' && inputHeroSmsMinPrice) {
|
||||||
inputHeroSmsMinPrice.value = restoredPhoneSmsProvider === PHONE_SMS_PROVIDER_FIVE_SIM
|
inputHeroSmsMinPrice.value = restoredPhoneSmsProvider === PHONE_SMS_PROVIDER_FIVE_SIM
|
||||||
? normalizePhoneSmsMinPriceValue(state?.fiveSimMinPrice || '', PHONE_SMS_PROVIDER_FIVE_SIM)
|
? normalizePhoneSmsMinPriceValue(state?.fiveSimMinPrice || '', PHONE_SMS_PROVIDER_FIVE_SIM)
|
||||||
: normalizePhoneSmsMinPriceValue(state?.heroSmsMinPrice || '', restoredPhoneSmsProvider);
|
: (restoredPhoneSmsProvider === smsBowerProviderConstant
|
||||||
|
? normalizePhoneSmsMinPriceValue(state?.smsBowerMinPrice || '', smsBowerProviderConstant)
|
||||||
|
: normalizePhoneSmsMinPriceValue(state?.heroSmsMinPrice || '', restoredPhoneSmsProvider));
|
||||||
}
|
}
|
||||||
if (inputFiveSimOperator) {
|
if (inputFiveSimOperator) {
|
||||||
inputFiveSimOperator.value = normalizeFiveSimOperator(state?.fiveSimOperator);
|
inputFiveSimOperator.value = normalizeFiveSimOperator(state?.fiveSimOperator);
|
||||||
@@ -17735,6 +17879,23 @@ function buildPhoneSmsProviderStatePatch(provider = getSelectedPhoneSmsProvider(
|
|||||||
nexSmsServiceCode: normalizeNexSmsServiceCodeValue(inputNexSmsServiceCode?.value || latestState?.nexSmsServiceCode || DEFAULT_NEX_SMS_SERVICE_CODE),
|
nexSmsServiceCode: normalizeNexSmsServiceCodeValue(inputNexSmsServiceCode?.value || latestState?.nexSmsServiceCode || DEFAULT_NEX_SMS_SERVICE_CODE),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (normalizedProvider === PHONE_SMS_PROVIDER_SMS_BOWER) {
|
||||||
|
const smsBowerCountries = typeof getSelectedSmsBowerCountries === 'function'
|
||||||
|
? getSelectedSmsBowerCountries()
|
||||||
|
: normalizeSmsBowerCountryOrderValue(latestState?.smsBowerCountryOrder || []);
|
||||||
|
const currentPrimary = smsBowerCountries[0] || {
|
||||||
|
id: normalizeSmsBowerCountryIdValue(latestState?.smsBowerCountryId || 6),
|
||||||
|
label: normalizeSmsBowerCountryLabelValue(latestState?.smsBowerCountryLabel || 'Indonesia'),
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
smsBowerApiKey: String(inputSmsBowerApiKey?.value || ''),
|
||||||
|
smsBowerCountryId: currentPrimary.id,
|
||||||
|
smsBowerCountryLabel: currentPrimary.label,
|
||||||
|
smsBowerCountryOrder: smsBowerCountries.map((country) => country.id),
|
||||||
|
smsBowerMinPrice: normalizePhoneSmsMinPriceValue(inputHeroSmsMinPrice?.value || '', PHONE_SMS_PROVIDER_SMS_BOWER),
|
||||||
|
smsBowerMaxPrice: normalizePhoneSmsMaxPriceValue(inputHeroSmsMaxPrice?.value || '', PHONE_SMS_PROVIDER_SMS_BOWER),
|
||||||
|
};
|
||||||
|
}
|
||||||
if (normalizedProvider === PHONE_SMS_PROVIDER_MADAO) {
|
if (normalizedProvider === PHONE_SMS_PROVIDER_MADAO) {
|
||||||
const maDaoMode = normalizeMaDaoModeValue(selectMaDaoMode?.value || latestState?.madaoMode);
|
const maDaoMode = normalizeMaDaoModeValue(selectMaDaoMode?.value || latestState?.madaoMode);
|
||||||
const maDaoDirectModeValue = typeof MADAO_MODE_DIRECT !== 'undefined'
|
const maDaoDirectModeValue = typeof MADAO_MODE_DIRECT !== 'undefined'
|
||||||
@@ -17801,6 +17962,17 @@ function applyPhoneSmsProviderFieldsToInputs(provider = getSelectedPhoneSmsProvi
|
|||||||
if (typeof inputSmsBowerApiKey !== 'undefined' && inputSmsBowerApiKey) {
|
if (typeof inputSmsBowerApiKey !== 'undefined' && inputSmsBowerApiKey) {
|
||||||
inputSmsBowerApiKey.value = String(state?.smsBowerApiKey || '');
|
inputSmsBowerApiKey.value = String(state?.smsBowerApiKey || '');
|
||||||
}
|
}
|
||||||
|
if (typeof selectSmsBowerCountry !== 'undefined' && selectSmsBowerCountry) {
|
||||||
|
const selectedIds = new Set(
|
||||||
|
normalizeSmsBowerCountryOrderValue(state?.smsBowerCountryOrder || [state?.smsBowerCountryId || 6])
|
||||||
|
.map((country) => String(country.id))
|
||||||
|
);
|
||||||
|
if (!selectedIds.size) selectedIds.add('6');
|
||||||
|
Array.from(selectSmsBowerCountry.options || []).forEach((option) => {
|
||||||
|
option.selected = selectedIds.has(String(option.value));
|
||||||
|
});
|
||||||
|
renderSmsBowerCountryFallbackOrder();
|
||||||
|
}
|
||||||
if (typeof inputMaDaoBaseUrl !== 'undefined' && inputMaDaoBaseUrl) {
|
if (typeof inputMaDaoBaseUrl !== 'undefined' && inputMaDaoBaseUrl) {
|
||||||
inputMaDaoBaseUrl.value = normalizeMaDaoBaseUrlValue(state?.madaoBaseUrl);
|
inputMaDaoBaseUrl.value = normalizeMaDaoBaseUrlValue(state?.madaoBaseUrl);
|
||||||
}
|
}
|
||||||
@@ -17841,12 +18013,16 @@ function applyPhoneSmsProviderFieldsToInputs(provider = getSelectedPhoneSmsProvi
|
|||||||
if (inputHeroSmsMaxPrice) {
|
if (inputHeroSmsMaxPrice) {
|
||||||
inputHeroSmsMaxPrice.value = normalizedProvider === PHONE_SMS_PROVIDER_FIVE_SIM
|
inputHeroSmsMaxPrice.value = normalizedProvider === PHONE_SMS_PROVIDER_FIVE_SIM
|
||||||
? normalizeFiveSimMaxPriceValue(state?.fiveSimMaxPrice || '')
|
? normalizeFiveSimMaxPriceValue(state?.fiveSimMaxPrice || '')
|
||||||
: normalizeHeroSmsMaxPriceValue(state?.heroSmsMaxPrice || '');
|
: (normalizedProvider === PHONE_SMS_PROVIDER_SMS_BOWER
|
||||||
|
? normalizePhoneSmsMaxPriceValue(state?.smsBowerMaxPrice || '', PHONE_SMS_PROVIDER_SMS_BOWER)
|
||||||
|
: normalizeHeroSmsMaxPriceValue(state?.heroSmsMaxPrice || ''));
|
||||||
}
|
}
|
||||||
if (typeof inputHeroSmsMinPrice !== 'undefined' && inputHeroSmsMinPrice) {
|
if (typeof inputHeroSmsMinPrice !== 'undefined' && inputHeroSmsMinPrice) {
|
||||||
inputHeroSmsMinPrice.value = normalizedProvider === PHONE_SMS_PROVIDER_FIVE_SIM
|
inputHeroSmsMinPrice.value = normalizedProvider === PHONE_SMS_PROVIDER_FIVE_SIM
|
||||||
? normalizePhoneSmsMinPriceValue(state?.fiveSimMinPrice || '', PHONE_SMS_PROVIDER_FIVE_SIM)
|
? normalizePhoneSmsMinPriceValue(state?.fiveSimMinPrice || '', PHONE_SMS_PROVIDER_FIVE_SIM)
|
||||||
: normalizePhoneSmsMinPriceValue(state?.heroSmsMinPrice || '', PHONE_SMS_PROVIDER_HERO_SMS);
|
: (normalizedProvider === PHONE_SMS_PROVIDER_SMS_BOWER
|
||||||
|
? normalizePhoneSmsMinPriceValue(state?.smsBowerMinPrice || '', PHONE_SMS_PROVIDER_SMS_BOWER)
|
||||||
|
: normalizePhoneSmsMinPriceValue(state?.heroSmsMinPrice || '', PHONE_SMS_PROVIDER_HERO_SMS));
|
||||||
}
|
}
|
||||||
if (typeof inputHeroSmsPreferredPrice !== 'undefined' && inputHeroSmsPreferredPrice) {
|
if (typeof inputHeroSmsPreferredPrice !== 'undefined' && inputHeroSmsPreferredPrice) {
|
||||||
inputHeroSmsPreferredPrice.value = normalizeHeroSmsMaxPriceValue(state?.heroSmsPreferredPrice || '');
|
inputHeroSmsPreferredPrice.value = normalizeHeroSmsMaxPriceValue(state?.heroSmsPreferredPrice || '');
|
||||||
@@ -18379,6 +18555,23 @@ selectNexSmsCountry?.addEventListener('change', () => {
|
|||||||
saveSettings({ silent: true }).catch(() => { });
|
saveSettings({ silent: true }).catch(() => { });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
selectSmsBowerCountry?.addEventListener('change', () => {
|
||||||
|
renderSmsBowerCountryFallbackOrder();
|
||||||
|
updateHeroSmsPlatformDisplay();
|
||||||
|
markSettingsDirty(true);
|
||||||
|
saveSettings({ silent: true }).catch(() => { });
|
||||||
|
});
|
||||||
|
|
||||||
|
btnSmsBowerCountryClear?.addEventListener('click', () => {
|
||||||
|
Array.from(selectSmsBowerCountry?.options || []).forEach((option) => {
|
||||||
|
option.selected = String(option.value) === '6';
|
||||||
|
});
|
||||||
|
renderSmsBowerCountryFallbackOrder();
|
||||||
|
updateHeroSmsPlatformDisplay();
|
||||||
|
markSettingsDirty(true);
|
||||||
|
saveSettings({ silent: true }).catch(() => { });
|
||||||
|
});
|
||||||
|
|
||||||
btnHeroSmsPricePreview?.addEventListener('click', async () => {
|
btnHeroSmsPricePreview?.addEventListener('click', async () => {
|
||||||
try {
|
try {
|
||||||
await previewHeroSmsPriceTiers();
|
await previewHeroSmsPriceTiers();
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ test('step 7 preserves visible step when refreshing OAuth after retry', async ()
|
|||||||
assert.deepStrictEqual(events.refreshSteps, [9, 9, 9]);
|
assert.deepStrictEqual(events.refreshSteps, [9, 9, 9]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('step 7 hands add-phone to the dedicated post-login phone node without internal retry', async () => {
|
test('step 7 hands add-phone to the dedicated post-login phone node without internal retry and keeps login code node active', async () => {
|
||||||
const source = fs.readFileSync('flows/openai/background/steps/oauth-login.js', 'utf8');
|
const source = fs.readFileSync('flows/openai/background/steps/oauth-login.js', 'utf8');
|
||||||
const globalScope = {};
|
const globalScope = {};
|
||||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundStep7;`)(globalScope);
|
const api = new Function('self', `${source}; return self.MultiPageBackgroundStep7;`)(globalScope);
|
||||||
@@ -222,12 +222,16 @@ test('step 7 hands add-phone to the dedicated post-login phone node without inte
|
|||||||
step: 'oauth-login',
|
step: 'oauth-login',
|
||||||
payload: {
|
payload: {
|
||||||
loginVerificationRequestedAt: null,
|
loginVerificationRequestedAt: null,
|
||||||
skipLoginVerificationStep: true,
|
|
||||||
addPhonePage: true,
|
addPhonePage: true,
|
||||||
|
phoneVerificationPage: false,
|
||||||
directOAuthConsentPage: false,
|
directOAuthConsentPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
assert.ok(
|
||||||
|
!Object.prototype.hasOwnProperty.call(events.completions[0].payload, 'skipLoginVerificationStep'),
|
||||||
|
'add-phone handoff must keep the login-code node active so step 9 phone verification can run next'
|
||||||
|
);
|
||||||
assert.ok(
|
assert.ok(
|
||||||
!events.logs.some(({ message }) => /准备重试/.test(message)),
|
!events.logs.some(({ message }) => /准备重试/.test(message)),
|
||||||
'add-phone failure should not be logged as an internal retryable attempt'
|
'add-phone failure should not be logged as an internal retryable attempt'
|
||||||
@@ -291,8 +295,8 @@ test('step 7 no longer runs shared phone verification inside oauth-login', async
|
|||||||
step: 'oauth-login',
|
step: 'oauth-login',
|
||||||
payload: {
|
payload: {
|
||||||
loginVerificationRequestedAt: null,
|
loginVerificationRequestedAt: null,
|
||||||
skipLoginVerificationStep: true,
|
|
||||||
addPhonePage: true,
|
addPhonePage: true,
|
||||||
|
phoneVerificationPage: false,
|
||||||
directOAuthConsentPage: false,
|
directOAuthConsentPage: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -149,6 +149,14 @@ test('sidepanel html exposes phone verification toggle and multi-provider SMS ro
|
|||||||
assert.match(html, /id="row-nex-sms-country-fallback"/);
|
assert.match(html, /id="row-nex-sms-country-fallback"/);
|
||||||
assert.match(html, /id="row-nex-sms-service-code"/);
|
assert.match(html, /id="row-nex-sms-service-code"/);
|
||||||
assert.match(html, /id="input-nex-sms-service-code"/);
|
assert.match(html, /id="input-nex-sms-service-code"/);
|
||||||
|
assert.match(html, /id="row-sms-bower-api-key"/);
|
||||||
|
assert.match(html, /id="input-sms-bower-api-key"/);
|
||||||
|
assert.match(html, /id="row-sms-bower-country"/);
|
||||||
|
assert.match(html, /id="select-sms-bower-country"/);
|
||||||
|
assert.match(html, /id="row-sms-bower-country-fallback"/);
|
||||||
|
assert.doesNotMatch(html, /id="row-sms-bower-max-price"/);
|
||||||
|
assert.doesNotMatch(html, /id="input-sms-bower-min-price"/);
|
||||||
|
assert.doesNotMatch(html, /id="input-sms-bower-max-price"/);
|
||||||
assert.match(html, /id="row-madao-base-url"/);
|
assert.match(html, /id="row-madao-base-url"/);
|
||||||
assert.match(html, /id="input-madao-base-url"/);
|
assert.match(html, /id="input-madao-base-url"/);
|
||||||
assert.match(html, /id="row-madao-http-secret"/);
|
assert.match(html, /id="row-madao-http-secret"/);
|
||||||
@@ -185,6 +193,30 @@ test('sidepanel html exposes phone verification toggle and multi-provider SMS ro
|
|||||||
assert.doesNotMatch(html, /id="input-account-run-history-text-enabled"/);
|
assert.doesNotMatch(html, /id="input-account-run-history-text-enabled"/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('SMS Bower sidepanel exposes HeroSMS-like user controls while hiding internal IDs', () => {
|
||||||
|
assert.match(sidepanelSource, /smsBowerApiKey:/);
|
||||||
|
assert.match(sidepanelSource, /rowSmsBowerApiKey/);
|
||||||
|
assert.match(sidepanelSource, /\[PHONE_SMS_PROVIDER_SMS_BOWER\]: Object\.freeze\(\{\s*rowKeys: Object\.freeze\(\[\s*'rowSmsBowerApiKey',\s*'rowSmsBowerCountry',\s*'rowSmsBowerCountryFallback',\s*'rowHeroSmsMaxPrice',\s*\]\),\s*\}\)/);
|
||||||
|
assert.match(sidepanelSource, /smsBowerApiKey:\s*smsBowerApiKeyValue/);
|
||||||
|
assert.match(sidepanelSource, /smsBowerCountryId:/);
|
||||||
|
assert.match(sidepanelSource, /smsBowerCountryLabel:/);
|
||||||
|
assert.match(sidepanelSource, /smsBowerCountryOrder:/);
|
||||||
|
assert.match(sidepanelSource, /smsBowerMinPrice:/);
|
||||||
|
assert.match(sidepanelSource, /smsBowerMaxPrice:/);
|
||||||
|
assert.match(sidepanelSource, /inputVerificationResendCount/);
|
||||||
|
assert.match(sidepanelSource, /rowPhoneVerificationResendCount/);
|
||||||
|
assert.match(sidepanelHtml, /id="row-sms-bower-country"/);
|
||||||
|
assert.match(sidepanelHtml, /id="select-sms-bower-country"/);
|
||||||
|
assert.match(sidepanelHtml, /id="row-sms-bower-country-fallback"/);
|
||||||
|
assert.doesNotMatch(sidepanelSource, /smsBowerProviderIds:/);
|
||||||
|
assert.doesNotMatch(sidepanelSource, /smsBowerExceptProviderIds:/);
|
||||||
|
assert.doesNotMatch(sidepanelSource, /case 'smsBowerProviderIds':/);
|
||||||
|
assert.doesNotMatch(sidepanelHtml, /id="input-sms-bower-country-id"/);
|
||||||
|
assert.doesNotMatch(sidepanelHtml, /id="input-sms-bower-provider-ids"/);
|
||||||
|
assert.doesNotMatch(sidepanelHtml, /id="input-sms-bower-except-provider-ids"/);
|
||||||
|
});
|
||||||
|
|
||||||
test('sidepanel loads live SMS country lists silently during startup', () => {
|
test('sidepanel loads live SMS country lists silently during startup', () => {
|
||||||
const heroLoader = extractFunction('loadHeroSmsCountries');
|
const heroLoader = extractFunction('loadHeroSmsCountries');
|
||||||
const fiveSimLoader = extractFunction('loadFiveSimCountries');
|
const fiveSimLoader = extractFunction('loadFiveSimCountries');
|
||||||
@@ -934,6 +966,8 @@ const rowNexSmsCountry = { style: { display: 'none' } };
|
|||||||
const rowNexSmsCountryFallback = { style: { display: 'none' } };
|
const rowNexSmsCountryFallback = { style: { display: 'none' } };
|
||||||
const rowNexSmsServiceCode = { style: { display: 'none' } };
|
const rowNexSmsServiceCode = { style: { display: 'none' } };
|
||||||
const rowSmsBowerApiKey = { style: { display: 'none' } };
|
const rowSmsBowerApiKey = { style: { display: 'none' } };
|
||||||
|
const rowSmsBowerCountry = { style: { display: 'none' } };
|
||||||
|
const rowSmsBowerCountryFallback = { style: { display: 'none' } };
|
||||||
const rowMaDaoBaseUrl = { style: { display: 'none' } };
|
const rowMaDaoBaseUrl = { style: { display: 'none' } };
|
||||||
const rowMaDaoHttpSecret = { style: { display: 'none' } };
|
const rowMaDaoHttpSecret = { style: { display: 'none' } };
|
||||||
const rowMaDaoMode = { style: { display: 'none' } };
|
const rowMaDaoMode = { style: { display: 'none' } };
|
||||||
@@ -973,6 +1007,7 @@ const PHONE_SMS_PROVIDER_HERO_SMS = 'hero-sms';
|
|||||||
const PHONE_SMS_PROVIDER_HERO = PHONE_SMS_PROVIDER_HERO_SMS;
|
const PHONE_SMS_PROVIDER_HERO = PHONE_SMS_PROVIDER_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';
|
||||||
|
const PHONE_SMS_PROVIDER_SMS_BOWER = 'sms-bower';
|
||||||
const PHONE_SMS_PROVIDER_MADAO = 'madao';
|
const PHONE_SMS_PROVIDER_MADAO = 'madao';
|
||||||
const MADAO_MODE_ROUTING_PLAN = 'routing_plan';
|
const MADAO_MODE_ROUTING_PLAN = 'routing_plan';
|
||||||
const MADAO_MODE_DIRECT = 'direct';
|
const MADAO_MODE_DIRECT = 'direct';
|
||||||
@@ -1013,6 +1048,9 @@ const PHONE_SMS_PROVIDER_UI_DESCRIPTORS = ${JSON.stringify({
|
|||||||
'sms-bower': {
|
'sms-bower': {
|
||||||
rowKeys: [
|
rowKeys: [
|
||||||
'rowSmsBowerApiKey',
|
'rowSmsBowerApiKey',
|
||||||
|
'rowSmsBowerCountry',
|
||||||
|
'rowSmsBowerCountryFallback',
|
||||||
|
'rowHeroSmsMaxPrice',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
madao: {
|
madao: {
|
||||||
@@ -1464,6 +1502,7 @@ const PHONE_SMS_PROVIDER_HERO_SMS = 'hero-sms';
|
|||||||
const PHONE_SMS_PROVIDER_HERO = PHONE_SMS_PROVIDER_HERO_SMS;
|
const PHONE_SMS_PROVIDER_HERO = PHONE_SMS_PROVIDER_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';
|
||||||
|
const PHONE_SMS_PROVIDER_SMS_BOWER = 'sms-bower';
|
||||||
const PHONE_SMS_PROVIDER_MADAO = 'madao';
|
const PHONE_SMS_PROVIDER_MADAO = 'madao';
|
||||||
const DEFAULT_PHONE_SMS_PROVIDER = PHONE_SMS_PROVIDER_HERO_SMS;
|
const DEFAULT_PHONE_SMS_PROVIDER = PHONE_SMS_PROVIDER_HERO_SMS;
|
||||||
const DEFAULT_MADAO_BASE_URL = 'http://127.0.0.1:7822';
|
const DEFAULT_MADAO_BASE_URL = 'http://127.0.0.1:7822';
|
||||||
@@ -1523,6 +1562,9 @@ ${extractFunction('normalizeFiveSimProductValue')}
|
|||||||
${extractFunction('normalizeNexSmsCountryIdValue')}
|
${extractFunction('normalizeNexSmsCountryIdValue')}
|
||||||
${extractFunction('normalizeNexSmsCountryOrderValue')}
|
${extractFunction('normalizeNexSmsCountryOrderValue')}
|
||||||
${extractFunction('normalizeNexSmsServiceCodeValue')}
|
${extractFunction('normalizeNexSmsServiceCodeValue')}
|
||||||
|
${extractFunction('normalizeSmsBowerCountryIdValue')}
|
||||||
|
${extractFunction('normalizeSmsBowerCountryLabelValue')}
|
||||||
|
${extractFunction('normalizeSmsBowerCountryOrderValue')}
|
||||||
function getSelectedPhoneSmsProvider() { return normalizePhoneSmsProvider(selectPhoneSmsProvider?.value || latestState?.phoneSmsProvider); }
|
function getSelectedPhoneSmsProvider() { return normalizePhoneSmsProvider(selectPhoneSmsProvider?.value || latestState?.phoneSmsProvider); }
|
||||||
function getSelectedPhoneSmsProviderOrder() { return ['nexsms', '5sim']; }
|
function getSelectedPhoneSmsProviderOrder() { return ['nexsms', '5sim']; }
|
||||||
${extractFunction('normalizeFiveSimCountryId')}
|
${extractFunction('normalizeFiveSimCountryId')}
|
||||||
@@ -1660,6 +1702,7 @@ const PHONE_SMS_PROVIDER_HERO_SMS = 'hero-sms';
|
|||||||
const PHONE_SMS_PROVIDER_HERO = PHONE_SMS_PROVIDER_HERO_SMS;
|
const PHONE_SMS_PROVIDER_HERO = PHONE_SMS_PROVIDER_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';
|
||||||
|
const PHONE_SMS_PROVIDER_SMS_BOWER = 'sms-bower';
|
||||||
const PHONE_SMS_PROVIDER_MADAO = 'madao';
|
const PHONE_SMS_PROVIDER_MADAO = 'madao';
|
||||||
const DEFAULT_PHONE_SMS_PROVIDER = PHONE_SMS_PROVIDER_HERO_SMS;
|
const DEFAULT_PHONE_SMS_PROVIDER = PHONE_SMS_PROVIDER_HERO_SMS;
|
||||||
const DEFAULT_PHONE_SMS_PROVIDER_ORDER = ['hero-sms', '5sim', 'nexsms', 'madao'];
|
const DEFAULT_PHONE_SMS_PROVIDER_ORDER = ['hero-sms', '5sim', 'nexsms', 'madao'];
|
||||||
@@ -1877,6 +1920,7 @@ const PHONE_SMS_PROVIDER_HERO_SMS = 'hero-sms';
|
|||||||
const PHONE_SMS_PROVIDER_HERO = PHONE_SMS_PROVIDER_HERO_SMS;
|
const PHONE_SMS_PROVIDER_HERO = PHONE_SMS_PROVIDER_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';
|
||||||
|
const PHONE_SMS_PROVIDER_SMS_BOWER = 'sms-bower';
|
||||||
const PHONE_SMS_PROVIDER_MADAO = 'madao';
|
const PHONE_SMS_PROVIDER_MADAO = 'madao';
|
||||||
const DEFAULT_PHONE_SMS_PROVIDER = PHONE_SMS_PROVIDER_HERO_SMS;
|
const DEFAULT_PHONE_SMS_PROVIDER = PHONE_SMS_PROVIDER_HERO_SMS;
|
||||||
const DEFAULT_FIVE_SIM_COUNTRY_ID = 'vietnam';
|
const DEFAULT_FIVE_SIM_COUNTRY_ID = 'vietnam';
|
||||||
|
|||||||
@@ -14,7 +14,28 @@ function createTextResponse(payload, ok = true, status = ok ? 200 : 400, statusT
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
test('SMS Bower provider uses handler API key query for balance and price catalog', async () => {
|
test('SMS Bower provider defaults to Indonesia and documented OpenAI service code', async () => {
|
||||||
|
const requests = [];
|
||||||
|
const provider = api.createProvider({
|
||||||
|
fetchImpl: async (url, options = {}) => {
|
||||||
|
const parsed = new URL(url);
|
||||||
|
requests.push({ url: parsed, options });
|
||||||
|
if (parsed.searchParams.get('action') === 'getNumberV2') {
|
||||||
|
return createTextResponse('ACCESS_NUMBER:67890:6281234567890');
|
||||||
|
}
|
||||||
|
throw new Error(`unexpected ${parsed.toString()}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const activation = await provider.requestActivation({ smsBowerApiKey: 'demo-key' });
|
||||||
|
|
||||||
|
assert.equal(requests[0].url.searchParams.get('country'), '6');
|
||||||
|
assert.equal(requests[0].url.searchParams.get('service'), 'dr');
|
||||||
|
assert.equal(activation.countryId, 6);
|
||||||
|
assert.equal(activation.countryLabel, 'Indonesia');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('SMS Bower provider uses documented handler API methods for balance and price catalog', async () => {
|
||||||
const requests = [];
|
const requests = [];
|
||||||
const provider = api.createProvider({
|
const provider = api.createProvider({
|
||||||
fetchImpl: async (url, options = {}) => {
|
fetchImpl: async (url, options = {}) => {
|
||||||
@@ -23,8 +44,8 @@ test('SMS Bower provider uses handler API key query for balance and price catalo
|
|||||||
if (parsed.searchParams.get('action') === 'getBalance') {
|
if (parsed.searchParams.get('action') === 'getBalance') {
|
||||||
return createTextResponse('ACCESS_BALANCE:12.34');
|
return createTextResponse('ACCESS_BALANCE:12.34');
|
||||||
}
|
}
|
||||||
if (parsed.searchParams.get('action') === 'getPrices') {
|
if (parsed.searchParams.get('action') === 'getPricesV3') {
|
||||||
return createTextResponse({ 52: { ot: { cost: 0.21, count: 7 } } });
|
return createTextResponse({ 52: { dr: { 3170: { price: 0.21, count: 7 } } } });
|
||||||
}
|
}
|
||||||
throw new Error(`unexpected ${parsed.toString()}`);
|
throw new Error(`unexpected ${parsed.toString()}`);
|
||||||
},
|
},
|
||||||
@@ -38,21 +59,32 @@ test('SMS Bower provider uses handler API key query for balance and price catalo
|
|||||||
assert.equal(requests[0].url.searchParams.get('api_key'), 'demo-key');
|
assert.equal(requests[0].url.searchParams.get('api_key'), 'demo-key');
|
||||||
assert.equal(requests[0].url.searchParams.get('action'), 'getBalance');
|
assert.equal(requests[0].url.searchParams.get('action'), 'getBalance');
|
||||||
assert.equal(balance.balance, 12.34);
|
assert.equal(balance.balance, 12.34);
|
||||||
assert.equal(requests[1].url.searchParams.get('action'), 'getPrices');
|
assert.equal(requests[1].url.searchParams.get('action'), 'getPricesV3');
|
||||||
assert.equal(requests[1].url.searchParams.get('service'), 'ot');
|
assert.equal(requests[1].url.searchParams.get('service'), 'dr');
|
||||||
assert.equal(requests[1].url.searchParams.get('country'), '52');
|
assert.equal(requests[1].url.searchParams.get('country'), '52');
|
||||||
assert.deepStrictEqual(entries, [{ cost: 0.21, count: 7, inStock: true }]);
|
assert.deepStrictEqual(entries, [{ cost: 0.21, count: 7, inStock: true }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('SMS Bower provider acquires number, polls code, and updates activation statuses', async () => {
|
test('SMS Bower provider treats JSON status 0 responses as API errors even when HTTP is ok', async () => {
|
||||||
|
const provider = api.createProvider({
|
||||||
|
fetchImpl: async () => createTextResponse({ status: 0, message: 'No access', data: [] }, true, 200),
|
||||||
|
});
|
||||||
|
|
||||||
|
await assert.rejects(
|
||||||
|
() => provider.fetchBalance({ smsBowerApiKey: 'bad-key' }),
|
||||||
|
/SMS Bower 查询余额失败:No access/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('SMS Bower provider acquires number with getNumberV2, polls code, and updates activation statuses', async () => {
|
||||||
const requests = [];
|
const requests = [];
|
||||||
const provider = api.createProvider({
|
const provider = api.createProvider({
|
||||||
fetchImpl: async (url, options = {}) => {
|
fetchImpl: async (url, options = {}) => {
|
||||||
const parsed = new URL(url);
|
const parsed = new URL(url);
|
||||||
const action = parsed.searchParams.get('action');
|
const action = parsed.searchParams.get('action');
|
||||||
requests.push({ url: parsed, options });
|
requests.push({ url: parsed, options });
|
||||||
if (action === 'getNumber') {
|
if (action === 'getNumberV2') {
|
||||||
return createTextResponse('ACCESS_NUMBER:12345:447700900123');
|
return createTextResponse({ activationId: '12345', phoneNumber: '447700900123', activationCost: 0.3, countryCode: 16 });
|
||||||
}
|
}
|
||||||
if (action === 'getStatus') {
|
if (action === 'getStatus') {
|
||||||
return createTextResponse('STATUS_OK:Your OpenAI code is 654321');
|
return createTextResponse('STATUS_OK:Your OpenAI code is 654321');
|
||||||
@@ -68,12 +100,11 @@ test('SMS Bower provider acquires number, polls code, and updates activation sta
|
|||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
smsBowerApiKey: 'demo-key',
|
smsBowerApiKey: 'demo-key',
|
||||||
smsBowerServiceCode: 'ot',
|
smsBowerServiceCode: 'dr',
|
||||||
smsBowerCountryId: 16,
|
smsBowerCountryId: 16,
|
||||||
smsBowerCountryLabel: 'United Kingdom',
|
smsBowerCountryLabel: 'United Kingdom',
|
||||||
smsBowerMaxPrice: '0.3',
|
|
||||||
smsBowerMinPrice: '0.1',
|
smsBowerMinPrice: '0.1',
|
||||||
smsBowerProviderIds: '3170,3180',
|
smsBowerMaxPrice: '0.3',
|
||||||
};
|
};
|
||||||
|
|
||||||
const activation = await provider.requestActivation(state);
|
const activation = await provider.requestActivation(state);
|
||||||
@@ -91,16 +122,18 @@ test('SMS Bower provider acquires number, polls code, and updates activation sta
|
|||||||
assert.equal(reused.activationId, '12345');
|
assert.equal(reused.activationId, '12345');
|
||||||
|
|
||||||
const acquireUrl = requests[0].url;
|
const acquireUrl = requests[0].url;
|
||||||
assert.equal(acquireUrl.searchParams.get('action'), 'getNumber');
|
assert.equal(acquireUrl.searchParams.get('action'), 'getNumberV2');
|
||||||
assert.equal(acquireUrl.searchParams.get('service'), 'ot');
|
assert.equal(acquireUrl.searchParams.get('service'), 'dr');
|
||||||
assert.equal(acquireUrl.searchParams.get('country'), '16');
|
assert.equal(acquireUrl.searchParams.get('country'), '16');
|
||||||
assert.equal(acquireUrl.searchParams.get('maxPrice'), '0.3');
|
assert.equal(acquireUrl.searchParams.get('maxPrice'), '0.3');
|
||||||
assert.equal(acquireUrl.searchParams.get('minPrice'), '0.1');
|
assert.equal(acquireUrl.searchParams.get('minPrice'), '0.1');
|
||||||
assert.equal(acquireUrl.searchParams.get('providerIds'), '3170,3180');
|
assert.equal(acquireUrl.searchParams.get('providerIds'), null);
|
||||||
|
assert.equal(acquireUrl.searchParams.get('exceptProviderIds'), null);
|
||||||
|
assert.equal(acquireUrl.searchParams.get('phoneException'), null);
|
||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
requests.map((entry) => [entry.url.searchParams.get('action'), entry.url.searchParams.get('status')]),
|
requests.map((entry) => [entry.url.searchParams.get('action'), entry.url.searchParams.get('status')]),
|
||||||
[
|
[
|
||||||
['getNumber', null],
|
['getNumberV2', null],
|
||||||
['getStatus', null],
|
['getStatus', null],
|
||||||
['setStatus', '6'],
|
['setStatus', '6'],
|
||||||
['setStatus', '8'],
|
['setStatus', '8'],
|
||||||
@@ -109,3 +142,54 @@ test('SMS Bower provider acquires number, polls code, and updates activation sta
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('SMS Bower rotate cancels rejected number then immediately acquires the next number', async () => {
|
||||||
|
const requests = [];
|
||||||
|
const provider = api.createProvider({
|
||||||
|
fetchImpl: async (url, options = {}) => {
|
||||||
|
const parsed = new URL(url);
|
||||||
|
const action = parsed.searchParams.get('action');
|
||||||
|
requests.push({ url: parsed, options });
|
||||||
|
if (action === 'setStatus') {
|
||||||
|
return createTextResponse('ACCESS_CANCEL');
|
||||||
|
}
|
||||||
|
if (action === 'getNumberV2') {
|
||||||
|
return createTextResponse({ activationId: 'next-activation', phoneNumber: '447700900456', activationCost: 0.22, countryCode: 16 });
|
||||||
|
}
|
||||||
|
throw new Error(`unexpected ${parsed.toString()}`);
|
||||||
|
},
|
||||||
|
sleepWithStop: async () => {},
|
||||||
|
throwIfStopped: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
smsBowerApiKey: 'demo-key',
|
||||||
|
smsBowerServiceCode: 'dr',
|
||||||
|
smsBowerCountryId: 16,
|
||||||
|
smsBowerCountryLabel: 'United Kingdom',
|
||||||
|
smsBowerMinPrice: '0.1',
|
||||||
|
smsBowerMaxPrice: '0.3',
|
||||||
|
};
|
||||||
|
|
||||||
|
const rotated = await provider.rotateActivation(
|
||||||
|
state,
|
||||||
|
{ activationId: 'old-activation', phoneNumber: '447700900123', provider: 'sms-bower', countryId: 16 },
|
||||||
|
{ releaseAction: 'cancel', blockedCountryIds: [] }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(rotated.currentTicketId, 'old-activation');
|
||||||
|
assert.equal(rotated.nextActivation.activationId, 'next-activation');
|
||||||
|
assert.equal(rotated.nextActivation.phoneNumber, '447700900456');
|
||||||
|
assert.deepStrictEqual(
|
||||||
|
requests.map((entry) => [
|
||||||
|
entry.url.searchParams.get('action'),
|
||||||
|
entry.url.searchParams.get('id'),
|
||||||
|
entry.url.searchParams.get('status'),
|
||||||
|
]),
|
||||||
|
[
|
||||||
|
['setStatus', 'old-activation', '8'],
|
||||||
|
['getNumberV2', null, null],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user