import GuJumpgate snapshot from GitHub

This commit is contained in:
2026-05-20 20:33:51 +08:00
commit f8903dcd14
335 changed files with 179790 additions and 0 deletions
+213
View File
@@ -0,0 +1,213 @@
// phone-sms/providers/hero-sms.js — HeroSMS 接码平台适配层
(function attachHeroSmsProvider(root, factory) {
root.PhoneSmsHeroSmsProvider = factory();
})(typeof self !== 'undefined' ? self : globalThis, function createHeroSmsProviderModule() {
const PROVIDER_ID = 'hero-sms';
const DEFAULT_BASE_URL = 'https://hero-sms.com/stubs/handler_api.php';
const DEFAULT_SERVICE_CODE = 'dr';
const DEFAULT_SERVICE_LABEL = 'OpenAI';
const DEFAULT_COUNTRY_ID = 52;
const DEFAULT_COUNTRY_LABEL = 'Thailand';
const DEFAULT_REQUEST_TIMEOUT_MS = 20000;
function normalizeHeroSmsCountryId(value, fallback = DEFAULT_COUNTRY_ID) {
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 : DEFAULT_COUNTRY_ID;
}
function normalizeHeroSmsCountryLabel(value = '', fallback = DEFAULT_COUNTRY_LABEL) {
return String(value || '').trim() || fallback;
}
function normalizeHeroSmsMaxPrice(value = '') {
const rawValue = String(value ?? '').trim();
if (!rawValue) return '';
const numeric = Number(rawValue);
if (!Number.isFinite(numeric) || numeric <= 0) return '';
return String(Math.round(numeric * 10000) / 10000);
}
function normalizeHeroSmsCountryFallback(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 = [];
for (const entry of source) {
let id = 0;
let label = '';
if (entry && typeof entry === 'object' && !Array.isArray(entry)) {
id = normalizeHeroSmsCountryId(entry.id ?? entry.countryId, 0);
label = String((entry.label ?? entry.countryLabel) || '').trim();
} else {
const text = String(entry || '').trim();
const structured = text.match(/^(\d+)\s*(?:[:|/-]\s*(.+))?$/);
id = normalizeHeroSmsCountryId(structured?.[1] || text, 0);
label = String(structured?.[2] || '').trim();
}
if (!id || seen.has(id)) continue;
seen.add(id);
normalized.push({ id, label: label || `Country #${id}` });
if (normalized.length >= 20) break;
}
return normalized;
}
function normalizeBaseUrl(value = '') {
const trimmed = String(value || '').trim() || DEFAULT_BASE_URL;
try {
return new URL(trimmed).toString();
} catch {
return DEFAULT_BASE_URL;
}
}
function buildUrl(config = {}, query = {}) {
const url = new URL(normalizeBaseUrl(config.baseUrl));
Object.entries(query || {}).forEach(([key, value]) => {
if (value === undefined || value === null || value === '') return;
url.searchParams.set(key, String(value));
});
return url.toString();
}
function parsePayload(text) {
const trimmed = String(text || '').trim();
if (!trimmed) return '';
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
try { return JSON.parse(trimmed); } catch { return trimmed; }
}
return trimmed;
}
function describePayload(raw) {
if (typeof raw === 'string') return raw.trim();
if (raw && typeof raw === 'object') {
const direct = String(raw.message || raw.msg || raw.error || raw.title || raw.status || '').trim();
if (direct) return direct;
try { return JSON.stringify(raw); } catch { return String(raw); }
}
return String(raw || '').trim();
}
function resolveConfig(state = {}, deps = {}) {
return {
apiKey: String(state.heroSmsApiKey || '').trim(),
baseUrl: state.heroSmsBaseUrl || DEFAULT_BASE_URL,
fetchImpl: deps.fetchImpl || (typeof fetch === 'function' ? fetch.bind(globalThis) : null),
requestTimeoutMs: deps.requestTimeoutMs || DEFAULT_REQUEST_TIMEOUT_MS,
};
}
async function fetchPayload(config, query, actionLabel = 'HeroSMS request') {
if (query.api_key === undefined && config.apiKey) {
query = { api_key: config.apiKey, ...query };
}
if (!config.fetchImpl) {
throw new Error('HeroSMS 网络请求实现不可用。');
}
const controller = typeof AbortController === 'function' ? new AbortController() : null;
const timeoutId = controller
? setTimeout(() => controller.abort(), Number(config.requestTimeoutMs) || DEFAULT_REQUEST_TIMEOUT_MS)
: null;
try {
const response = await config.fetchImpl(buildUrl(config, query), {
method: 'GET',
signal: controller?.signal,
});
const text = await response.text();
const payload = parsePayload(text);
if (!response.ok) {
const error = new Error(`${actionLabel}失败:${describePayload(payload) || response.status}`);
error.payload = payload;
error.status = response.status;
throw error;
}
return payload;
} catch (error) {
if (error?.name === 'AbortError') {
throw new Error(`${actionLabel}超时。`);
}
throw error;
} finally {
if (timeoutId) clearTimeout(timeoutId);
}
}
function resolveCountryConfig(state = {}) {
return {
id: normalizeHeroSmsCountryId(state.heroSmsCountryId),
label: normalizeHeroSmsCountryLabel(state.heroSmsCountryLabel),
};
}
function resolveCountryCandidates(state = {}) {
const primary = resolveCountryConfig(state);
const seen = new Set([primary.id]);
const candidates = [primary];
normalizeHeroSmsCountryFallback(state.heroSmsCountryFallback).forEach((entry) => {
const id = normalizeHeroSmsCountryId(entry.id, 0);
if (!id || seen.has(id)) return;
seen.add(id);
candidates.push({ id, label: normalizeHeroSmsCountryLabel(entry.label, `Country #${id}`) });
});
return candidates;
}
async function fetchBalance(state = {}, deps = {}) {
const config = resolveConfig(state, deps);
if (!config.apiKey) {
throw new Error('HeroSMS API Key 缺失,请先在侧边栏保存接码 API Key。');
}
const payload = await fetchPayload(config, { action: 'getBalance' }, 'HeroSMS getBalance');
const balance = Number(String(describePayload(payload)).replace(/^ACCESS_BALANCE:/i, '').trim());
return { balance, raw: payload };
}
async function fetchPrices(state = {}, countryConfig = resolveCountryConfig(state), deps = {}) {
const config = resolveConfig(state, deps);
return fetchPayload(config, {
action: 'getPrices',
service: DEFAULT_SERVICE_CODE,
country: normalizeHeroSmsCountryId(countryConfig?.id),
}, 'HeroSMS getPrices');
}
function createProvider(deps = {}) {
return {
id: PROVIDER_ID,
label: 'HeroSMS',
defaultCountryId: DEFAULT_COUNTRY_ID,
defaultCountryLabel: DEFAULT_COUNTRY_LABEL,
defaultProduct: DEFAULT_SERVICE_LABEL,
normalizeCountryId: normalizeHeroSmsCountryId,
normalizeCountryLabel: normalizeHeroSmsCountryLabel,
normalizeCountryFallback: normalizeHeroSmsCountryFallback,
normalizeMaxPrice: normalizeHeroSmsMaxPrice,
resolveCountryCandidates,
fetchBalance: (state) => fetchBalance(state, deps),
fetchPrices: (state, countryConfig) => fetchPrices(state, countryConfig, deps),
describePayload,
};
}
return {
PROVIDER_ID,
DEFAULT_BASE_URL,
DEFAULT_COUNTRY_ID,
DEFAULT_COUNTRY_LABEL,
DEFAULT_SERVICE_CODE,
DEFAULT_SERVICE_LABEL,
createProvider,
describePayload,
normalizeHeroSmsCountryFallback,
normalizeHeroSmsCountryId,
normalizeHeroSmsCountryLabel,
normalizeHeroSmsMaxPrice,
};
});