Files
dukang/scripts/sms-test-helper.mjs
2026-07-12 22:52:40 +08:00

86 lines
2.5 KiB
JavaScript

import { execSync } from 'node:child_process';
const API = process.env.SMOKE_API ?? 'http://localhost:3000/api/v1';
const REDIS_CONTAINER = process.env.REDIS_CONTAINER ?? 'dukang-v1-redis';
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function fetchJson(path, options = {}) {
const res = await fetch(`${API}${path}`, options);
return res.json();
}
function readSmsCodeFromRedis(phone, scene) {
const key = `dukang:sms:${scene}:${phone}`;
try {
const code = execSync(`docker exec ${REDIS_CONTAINER} redis-cli GET "${key}"`, {
encoding: 'utf8',
}).trim();
if (code && code !== '(nil)') return code;
} catch {
/* docker/redis unavailable */
}
return null;
}
export async function loadClientConfig() {
const json = await fetchJson('/common/client-config');
if (json.code !== 0) throw new Error(`client-config: ${json.message}`);
return json.data;
}
export async function resolveSmsCode(phone, scene) {
const fromRedis = readSmsCodeFromRedis(phone, scene);
if (fromRedis) return fromRedis;
throw new Error(
`SMS code not found for ${phone} (${scene}); send SMS first and ensure Redis is reachable`,
);
}
export async function sendSmsOnce(clientApp, sendPath, phone, scene) {
const headers = {
'Content-Type': 'application/json',
'X-Client-App': clientApp,
};
const res = await fetch(`${API}${sendPath}`, {
method: 'POST',
headers,
body: JSON.stringify({ phone, scene }),
});
return res.json();
}
export async function sendSmsWithCooldown(clientApp, sendPath, phone, scene) {
let json = await sendSmsOnce(clientApp, sendPath, phone, scene);
if (json.code !== 0 && String(json.message).includes('过于频繁')) {
await sleep(65_000);
json = await sendSmsOnce(clientApp, sendPath, phone, scene);
}
if (json.code !== 0) {
const existing = readSmsCodeFromRedis(phone, scene);
if (existing) return { reusedCode: true };
throw new Error(`${sendPath}: ${json.message}`);
}
return json.data;
}
export async function loginWithSms(clientApp, phone, scene, loginPath, sendPath) {
await sendSmsWithCooldown(clientApp, sendPath, phone, scene);
const code = await resolveSmsCode(phone, scene);
const headers = {
'Content-Type': 'application/json',
'X-Client-App': clientApp,
};
const res = await fetch(`${API}${loginPath}`, {
method: 'POST',
headers,
body: JSON.stringify({ phone, code }),
});
const json = await res.json();
if (json.code !== 0) throw new Error(`${loginPath}: ${json.message}`);
return json.data;
}