Files
whatsapp/api/delete_message.php
2026-02-03 21:30:55 -05:00

194 lines
7.3 KiB
PHP

<?php
/**
* API - Eliminar mensaje
* Permite eliminar un mensaje de la conversación
* Fecha: 28 de enero de 2026
*/
// Habilitar display de errores para debug
ini_set('display_errors', 1);
error_reporting(E_ALL);
require_once '../config/config.php';
// Log para debug
error_log("delete_message.php: Iniciando, session_id=" . session_id() . ", admin_logged_in=" . (isset($_SESSION['admin_logged_in']) ? $_SESSION['admin_logged_in'] : 'no definido'));
requireAuthentication();
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
// Manejar preflight OPTIONS request
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST' && $_SERVER['REQUEST_METHOD'] !== 'DELETE') {
http_response_code(405);
echo json_encode(['success' => false, 'error' => 'Método no permitido. Use POST o DELETE.']);
exit;
}
try {
$input = json_decode(file_get_contents('php://input'), true);
// También soportar query params para DELETE
if (!$input && $_SERVER['REQUEST_METHOD'] === 'DELETE') {
$input = [
'message_id' => $_GET['message_id'] ?? $_GET['id'] ?? null,
'delete_for_everyone' => $_GET['delete_for_everyone'] ?? false
];
}
if (!$input) {
http_response_code(400);
echo json_encode(['success' => false, 'error' => 'JSON inválido']);
exit;
}
$messageId = $input['message_id'] ?? $input['id'] ?? null;
$deleteForEveryone = $input['delete_for_everyone'] ?? false;
$softDelete = $input['soft_delete'] ?? true; // Por defecto, soft delete
if (!$messageId) {
http_response_code(400);
echo json_encode(['success' => false, 'error' => 'message_id es requerido']);
exit;
}
$db = Database::getInstance();
// Buscar el mensaje
$sql = "SELECT id, user_id, direction, message_type, content, message_id as wa_message_id,
local_file, local_thumb, media_url
FROM conversations
WHERE id = :mid1 OR message_id = :mid2
LIMIT 1";
$message = $db->fetch($sql, ['mid1' => $messageId, 'mid2' => $messageId]);
if (!$message) {
http_response_code(404);
echo json_encode(['success' => false, 'error' => 'Mensaje no encontrado']);
exit;
}
// Solo permitir eliminar mensajes salientes (outgoing) a menos que sea admin
$isAdmin = isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'];
if ($message['direction'] !== 'outgoing' && !$isAdmin) {
http_response_code(403);
echo json_encode(['success' => false, 'error' => 'Solo puedes eliminar tus propios mensajes']);
exit;
}
$deletedMessageId = $message['id'];
$userId = $message['user_id'];
$waMessageId = $message['wa_message_id'];
if ($softDelete) {
// Soft delete: marcar como eliminado pero mantener registro
// Verificar si existen las columnas deleted_at y original_content
$hasDeletedAt = false;
$hasOriginalContent = false;
try {
$columns = $db->fetchAll("SHOW COLUMNS FROM conversations WHERE Field IN ('deleted_at', 'original_content')");
foreach ($columns as $col) {
if ($col['Field'] === 'deleted_at') $hasDeletedAt = true;
if ($col['Field'] === 'original_content') $hasOriginalContent = true;
}
} catch (Exception $e) {
// Ignorar
}
// Construir la query según las columnas disponibles
// IMPORTANTE: Guardar original_content ANTES de modificar content
if ($hasDeletedAt && $hasOriginalContent) {
// Primero guardamos el contenido original
$db->execute("UPDATE conversations SET original_content = content WHERE id = :id AND original_content IS NULL", ['id' => $deletedMessageId]);
// Luego marcamos como eliminado
$updateSql = "UPDATE conversations SET content = '[Mensaje eliminado]', deleted_at = NOW() WHERE id = :id";
} elseif ($hasDeletedAt) {
$updateSql = "UPDATE conversations SET content = '[Mensaje eliminado]', deleted_at = NOW() WHERE id = :id";
} else {
$updateSql = "UPDATE conversations SET content = '[Mensaje eliminado]' WHERE id = :id";
}
$db->execute($updateSql, ['id' => $deletedMessageId]);
error_log("Message soft-deleted: ID={$deletedMessageId}, User={$userId}");
} else {
// Hard delete: eliminar completamente
// Primero, eliminar archivos multimedia asociados si existen
if (!empty($message['local_file'])) {
$filePath = dirname(__DIR__) . '/' . $message['local_file'];
if (file_exists($filePath)) {
@unlink($filePath);
error_log("Deleted media file: {$filePath}");
}
}
if (!empty($message['local_thumb'])) {
$thumbPath = dirname(__DIR__) . '/' . $message['local_thumb'];
if (file_exists($thumbPath)) {
@unlink($thumbPath);
error_log("Deleted thumbnail: {$thumbPath}");
}
}
// Eliminar el mensaje de la base de datos
$deleteSql = "DELETE FROM conversations WHERE id = :id";
$db->execute($deleteSql, ['id' => $deletedMessageId]);
error_log("Message hard-deleted: ID={$deletedMessageId}, User={$userId}");
}
// Intentar notificar por SSE si está disponible
try {
$ssePayload = [
'type' => 'message_deleted',
'user_id' => $userId,
'message_id' => $deletedMessageId,
'wa_message_id' => $waMessageId,
'soft_delete' => $softDelete,
'deleted_at' => date('Y-m-d H:i:s')
];
// Llamar al endpoint push_event interno
$pushUrl = 'http://127.0.0.1' . dirname($_SERVER['SCRIPT_NAME']) . '/push_event.php';
$ch = curl_init($pushUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'event_type' => 'message_deleted',
'data' => $ssePayload,
'target_user_id' => 'all'
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
curl_exec($ch);
curl_close($ch);
} catch (Exception $sseErr) {
error_log("delete_message: SSE notification failed: " . $sseErr->getMessage());
}
echo json_encode([
'success' => true,
'message' => $softDelete ? 'Mensaje eliminado' : 'Mensaje eliminado permanentemente',
'data' => [
'id' => $deletedMessageId,
'message_id' => $waMessageId,
'soft_delete' => $softDelete,
'deleted_at' => date('Y-m-d H:i:s')
]
]);
} catch (Exception $e) {
error_log('delete_message.php error: ' . $e->getMessage() . ' | Trace: ' . $e->getTraceAsString());
http_response_code(500);
echo json_encode(['success' => false, 'error' => 'Error interno del servidor', 'debug' => $e->getMessage()]);
}