Files
sistema_para_juego/discord/webhook/index.php

92 lines
3.0 KiB
PHP
Executable File

<?php
/**
* Webhook Principal de Discord
* Punto de entrada para interacciones de Discord que redirige al daemon
*/
// Habilitar logging de errores en archivo, no en salida
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/../../logs/webhook_errors.log');
require_once __DIR__ . '/../../shared/utils/helpers.php';
// Cargar variables de entorno
if (file_exists(__DIR__ . '/../../.env')) {
$lines = file(__DIR__ . '/../../.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (strpos(trim($line), '#') === 0) continue;
if (strpos($line, '=') === false) continue;
list($key, $value) = explode('=', $line, 2);
$_ENV[trim($key)] = trim($value);
}
}
// Constantes de Discord
define('DISCORD_PUBLIC_KEY', $_ENV['DISCORD_PUBLIC_KEY'] ?? getenv('DISCORD_PUBLIC_KEY'));
// Verificar firma de seguridad (Ed25519)
function verifySignature($body, $headers) {
$signature = $headers['x-signature-ed25519'] ?? '';
$timestamp = $headers['x-signature-timestamp'] ?? '';
$publicKey = DISCORD_PUBLIC_KEY;
if (\!$signature || \!$timestamp || \!$publicKey) {
error_log("Faltan parámetros de firma");
return false;
}
if (function_exists('sodium_crypto_sign_verify_detached')) {
try {
$sig = hex2bin($signature);
$msg = $timestamp . $body;
$key = hex2bin($publicKey);
return sodium_crypto_sign_verify_detached($sig, $msg, $key);
} catch (Exception $e) {
error_log("Error verificando firma (sodium): " . $e->getMessage());
return false;
}
} else {
error_log("ADVERTENCIA: La extensión 'sodium' de PHP no está instalada. La verificación de firma de Discord es INSEGURA.");
return false;
}
}
// Obtener headers y body
$headers = array_change_key_case(getallheaders(), CASE_LOWER);
$body = file_get_contents('php://input');
// Registrar la solicitud para depuración
error_log("Solicitud recibida: " . json_encode([
'headers' => array_intersect_key($headers, ['x-signature-ed25519' => true, 'x-signature-timestamp' => true]),
'body' => $body
]));
// Verificar firma
if (\!verifySignature($body, $headers)) {
http_response_code(401);
error_log("Firma no válida");
echo 'Invalid Signature';
exit;
}
// Decodificar JSON para verificar si es un PING
$data = json_decode($body, true);
$type = $data['type'] ?? 0;
// Manejar PING (requerido por Discord para validar la URL del webhook)
if ($type === 1) {
header('Content-Type: application/json');
echo json_encode(['type' => 1]);
exit;
}
// Para otras interacciones, redirigir al daemon
$interactionId = $data['id'] ?? 'unknown';
error_log("Interacción recibida (ID: $interactionId). El daemon debería manejar esto.");
// NO responder aquí. El daemon se encargará de la respuesta completa.
// Simplemente terminamos el script del webhook con un 200 OK.
http_response_code(200);
exit;