80 lines
2.9 KiB
JavaScript
80 lines
2.9 KiB
JavaScript
const base = () => (process.env.TELEGRAM_GATEWAY_URL || 'http://host.docker.internal:3000/api').replace(/\/$/, '')
|
|
|
|
let gatewayToken = process.env.TELEGRAM_GATEWAY_TOKEN || ''
|
|
let refreshPromise
|
|
|
|
function tokenExpiresSoon(token) {
|
|
try {
|
|
const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64url').toString('utf8'))
|
|
return !payload.exp || payload.exp * 1000 < Date.now() + 5 * 60 * 1000
|
|
} catch {
|
|
return true
|
|
}
|
|
}
|
|
|
|
async function refreshGatewayToken() {
|
|
if (refreshPromise) return refreshPromise
|
|
refreshPromise = (async () => {
|
|
const email = process.env.TELEGRAM_GATEWAY_SERVICE_EMAIL
|
|
const password = process.env.TELEGRAM_GATEWAY_SERVICE_PASSWORD
|
|
const tenantId = process.env.TELEGRAM_GATEWAY_TENANT_ID
|
|
if (!email || !password || !tenantId) {
|
|
throw Object.assign(new Error('Telegram 网关服务账号凭据尚未配置'), { status: 503 })
|
|
}
|
|
const response = await fetch(`${base()}/auth/login`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json' },
|
|
body: JSON.stringify({ email, password, tenantId }),
|
|
})
|
|
const raw = await response.text()
|
|
let result
|
|
try { result = raw ? JSON.parse(raw) : null } catch { result = raw }
|
|
const token = result?.data?.token || result?.token
|
|
if (!response.ok || !token) {
|
|
throw Object.assign(new Error(result?.message || 'Telegram 网关服务账号续签失败'), { status: response.status || 503 })
|
|
}
|
|
gatewayToken = token
|
|
return token
|
|
})().finally(() => { refreshPromise = undefined })
|
|
return refreshPromise
|
|
}
|
|
|
|
export async function gatewayRequest(path, options = {}) {
|
|
const tenantId = process.env.TELEGRAM_GATEWAY_TENANT_ID
|
|
if (!tenantId) throw Object.assign(new Error('Telegram 网关租户尚未配置'), { status: 503 })
|
|
if (!gatewayToken || tokenExpiresSoon(gatewayToken)) await refreshGatewayToken()
|
|
const send = () => fetch(`${base()}${path}`, {
|
|
...options,
|
|
headers: {
|
|
...(options.body instanceof FormData ? {} : { 'content-type': 'application/json' }),
|
|
authorization: `Bearer ${gatewayToken}`,
|
|
'x-tenant-id': tenantId,
|
|
...(options.headers || {}),
|
|
},
|
|
})
|
|
let response = await send()
|
|
if (response.status === 401) {
|
|
await refreshGatewayToken()
|
|
response = await send()
|
|
}
|
|
const raw = await response.text()
|
|
let result
|
|
try { result = raw ? JSON.parse(raw) : null } catch { result = raw }
|
|
if (!response.ok) {
|
|
throw Object.assign(new Error(result?.message || `Telegram 网关请求失败 (${response.status})`), { status: response.status })
|
|
}
|
|
return result?.data ?? result
|
|
}
|
|
|
|
export function postGateway(path, body) {
|
|
return gatewayRequest(path, { method: 'POST', body: JSON.stringify(body) })
|
|
}
|
|
|
|
export function putGateway(path, body) {
|
|
return gatewayRequest(path, { method: 'PUT', body: JSON.stringify(body) })
|
|
}
|
|
|
|
export function uploadGateway(path, formData) {
|
|
return gatewayRequest(path, { method: 'POST', body: formData })
|
|
}
|