Cliente SOAP + servicios de personaje SOAP (revive/unstuck) en Next.js
- lib/soap.ts: executeSoapCommand (port de ac_soap.py; POST SOAP + basic auth al worldserver, timeout 5s, null si inaccesible). AC_SOAP_* en .env.local. - lib/characters.ts: getGameCharacters / characterIsOfflineAndOwned (acore_characters). - lib/character-services.ts: soapCharacterAction genérico (valida propiedad+offline, cooldown 12h vía home_revive/unstuckhistory, SOAP, registra historial) -> reviveCharacter / unstuckCharacter. - components/CharacterActionForm.tsx (cliente reutilizable: select + botón). - Routes /api/character/revive|unstuck (guard de sesión) y páginas app/[locale]/revive|unstuck (SSR, guardas, i18n). Namespace Services. Verificado: API sin sesión 401, páginas redirigen a login, cliente SOAP devuelve null limpio sin worldserver. Patrón base para el resto de servicios de personaje. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
// Cliente SOAP al worldserver de AzerothCore (port de home/ac_soap.py).
|
||||
function escapeXml(s: string): string {
|
||||
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
}
|
||||
|
||||
/** Ejecuta un comando en el worldserver por SOAP. Devuelve el texto de respuesta o null. */
|
||||
export async function executeSoapCommand(command: string): Promise<string | null> {
|
||||
const url = process.env.AC_SOAP_URL
|
||||
const user = process.env.AC_SOAP_USER ?? ''
|
||||
const pass = process.env.AC_SOAP_PASSWORD ?? ''
|
||||
const urn = process.env.AC_SOAP_URN ?? 'urn:AC'
|
||||
if (!url) return null
|
||||
|
||||
const soap = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="${urn}">
|
||||
<SOAP-ENV:Body><ns1:executeCommand><command>${escapeXml(command)}</command></ns1:executeCommand></SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>`
|
||||
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: 'Basic ' + Buffer.from(`${user}:${pass}`).toString('base64'),
|
||||
'Content-Type': 'application/xml',
|
||||
},
|
||||
body: soap,
|
||||
signal: AbortSignal.timeout(5000),
|
||||
})
|
||||
if (!res.ok) return null
|
||||
return await res.text()
|
||||
} catch {
|
||||
return null // worldserver inaccesible
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user