up
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/**
|
||||
* API - Forzar descarga inmediata de un archivo multimedia
|
||||
* Agrega/reinicia el item en la cola y ejecuta el worker sincrónicamente para ese item.
|
||||
*/
|
||||
|
||||
require_once '../config/config.php';
|
||||
requireAuthentication();
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Cache-Control: no-cache, no-store, must-revalidate');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'error' => 'Method not allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?: [];
|
||||
$messageId = isset($input['message_id']) ? intval($input['message_id']) : 0;
|
||||
|
||||
if (!$messageId) {
|
||||
echo json_encode(['success' => false, 'error' => 'message_id requerido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$db = Database::getInstance();
|
||||
|
||||
// Obtener info del mensaje
|
||||
$msg = $db->fetchOne(
|
||||
"SELECT id, media_url, whatsapp_media_id, message_type, local_file, conversation_id
|
||||
FROM conversations
|
||||
WHERE id = ?",
|
||||
[$messageId]
|
||||
);
|
||||
|
||||
if (!$msg) {
|
||||
echo json_encode(['success' => false, 'error' => 'Mensaje no encontrado']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Si ya tiene archivo local, retornar éxito directo
|
||||
if (!empty($msg['local_file']) && file_exists($_SERVER['DOCUMENT_ROOT'] . '/' . $msg['local_file'])) {
|
||||
echo json_encode(['success' => true, 'status' => 'already_downloaded', 'local_file' => $msg['local_file']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Determinar el media_id a descargar
|
||||
$mediaId = !empty($msg['whatsapp_media_id']) ? $msg['whatsapp_media_id'] : $msg['media_url'];
|
||||
if (empty($mediaId)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Sin media_id disponible']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Buscar o crear entrada en media_queue
|
||||
$existing = $db->fetchOne(
|
||||
"SELECT id, status, attempts FROM media_queue WHERE conversation_id = ? OR media_id = ? LIMIT 1",
|
||||
[$msg['id'], $mediaId]
|
||||
);
|
||||
|
||||
if ($existing) {
|
||||
// Resetear a pending para que sea procesado
|
||||
$db->query(
|
||||
"UPDATE media_queue SET status = 'pending', attempts = 0, result = NULL, updated_at = NOW() WHERE id = ?",
|
||||
[$existing['id']]
|
||||
);
|
||||
$queueId = $existing['id'];
|
||||
} else {
|
||||
// Crear nueva entrada en la cola
|
||||
$convInfo = $db->fetchOne("SELECT user_id FROM conversations WHERE id = ?", [$msg['id']]);
|
||||
$userId = $convInfo['user_id'] ?? 0;
|
||||
|
||||
// Determinar subdirectorio por mes
|
||||
$subdir = date('Y/m');
|
||||
|
||||
$db->query(
|
||||
"INSERT INTO media_queue (media_id, subdir, status, attempts, conversation_id, media_url, message_type, created_at)
|
||||
VALUES (?, ?, 'pending', 0, ?, ?, ?, NOW())",
|
||||
[$mediaId, $subdir, $msg['id'], $mediaId, $msg['message_type'] ?? 'image']
|
||||
);
|
||||
$queueId = $db->lastInsertId();
|
||||
}
|
||||
|
||||
// Ejecutar descarga inmediata usando MediaService
|
||||
$result = ['success' => false, 'status' => 'queued'];
|
||||
|
||||
try {
|
||||
require_once '../classes/MediaService.php';
|
||||
$mediaService = new MediaService();
|
||||
|
||||
$subdir = date('Y/m');
|
||||
$localPath = $mediaService->fetchAndStoreFromGraph($mediaId, $subdir);
|
||||
|
||||
if ($localPath) {
|
||||
// Actualizar el mensaje con el archivo local
|
||||
$db->query(
|
||||
"UPDATE conversations SET local_file = ?, updated_at = NOW() WHERE id = ?",
|
||||
[$localPath, $messageId]
|
||||
);
|
||||
// Marcar como completado en la cola
|
||||
$db->query(
|
||||
"UPDATE media_queue SET status = 'completed', result = ?, updated_at = NOW() WHERE id = ?",
|
||||
['OK: ' . $localPath, $queueId]
|
||||
);
|
||||
|
||||
$result = ['success' => true, 'status' => 'downloaded', 'local_file' => $localPath];
|
||||
} else {
|
||||
// Falló la descarga pero quedó en cola para el worker
|
||||
$db->query(
|
||||
"UPDATE media_queue SET status = 'failed', attempts = attempts + 1, updated_at = NOW() WHERE id = ?",
|
||||
[$queueId]
|
||||
);
|
||||
$result = ['success' => false, 'status' => 'failed', 'message' => 'No se pudo descargar ahora. Quedó en cola para reintento automático.'];
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log('[force_download_media] Error al descargar: ' . $e->getMessage());
|
||||
$result = ['success' => false, 'status' => 'failed', 'message' => 'Error: ' . $e->getMessage()];
|
||||
}
|
||||
|
||||
echo json_encode($result);
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('[force_download_media] Exception: ' . $e->getMessage());
|
||||
http_response_code(500);
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
@@ -159,8 +159,35 @@ try {
|
||||
$conversations = [];
|
||||
}
|
||||
|
||||
// Si hay búsqueda, obtener el snippet del mensaje que coincidió (no solo el último)
|
||||
$matchedContentMap = [];
|
||||
if (!empty($search)) {
|
||||
$userIds = array_column($conversations, 'user_id');
|
||||
if (!empty($userIds)) {
|
||||
$placeholders = implode(',', array_fill(0, count($userIds), '?'));
|
||||
$searchParam = '%' . $search . '%';
|
||||
$params2 = array_merge([$searchParam], $userIds);
|
||||
$matchedRows = $db->fetchAll(
|
||||
"SELECT user_id, content FROM conversations
|
||||
WHERE content LIKE ? AND user_id IN ($placeholders)
|
||||
ORDER BY created_at DESC",
|
||||
$params2
|
||||
);
|
||||
// Guardar el primer mensaje coincidente por usuario
|
||||
foreach ($matchedRows as $row) {
|
||||
if (!isset($matchedContentMap[$row['user_id']])) {
|
||||
$matchedContentMap[$row['user_id']] = mb_substr($row['content'], 0, 80);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Formatear datos para el frontend
|
||||
$conversations = array_map(function($conv) {
|
||||
$conversations = array_map(function($conv) use ($matchedContentMap, $search) {
|
||||
$matched = null;
|
||||
if (!empty($search) && isset($matchedContentMap[$conv['user_id']])) {
|
||||
$matched = $matchedContentMap[$conv['user_id']];
|
||||
}
|
||||
return [
|
||||
'user_id' => intval($conv['user_id']),
|
||||
'name' => $conv['name'] ?? $conv['phone_number'],
|
||||
@@ -178,7 +205,8 @@ try {
|
||||
'advisor_requested' => isset($conv['advisor_requested']) ? (bool)$conv['advisor_requested'] : false,
|
||||
'in_service' => isset($conv['in_service']) ? (bool)$conv['in_service'] : false,
|
||||
'in_service_by' => isset($conv['in_service_by']) ? intval($conv['in_service_by']) : null,
|
||||
'in_service_at' => $conv['in_service_at'] ?? null
|
||||
'in_service_at' => $conv['in_service_at'] ?? null,
|
||||
'matched_content' => $matched // snippet del mensaje que coincidió (solo en búsqueda)
|
||||
];
|
||||
}, $conversations);
|
||||
|
||||
|
||||
@@ -326,3 +326,12 @@
|
||||
[2026-02-21 08:41:55] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSODUxOUM2MzM5RUU4NDE0RjA4AA=="}]}
|
||||
[2026-02-21 08:41:55] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSODUxOUM2MzM5RUU4NDE0RjA4AA=="}]}
|
||||
[2026-02-21 08:41:55] Saving to DB - content: 3 (2).png, media_url: 2095167437923441, local_file: uploads/media_6999b620bce0e2.99054574.png, local_thumb: uploads/media_6999b620bce0e2.99054574.png
|
||||
[2026-02-21 11:19:23] Raw input: {"recipient":"573022548060","media_url":"https://bot.u-s.app/uploads/media_6999db0b6b3f01.27857143.png","media_type":"image","caption":null,"filename":"image.png","is_voice":false}
|
||||
[2026-02-21 11:19:23] Input decoded: {"recipient":"573022548060","media_url":"https:\/\/bot.u-s.app\/uploads\/media_6999db0b6b3f01.27857143.png","media_type":"image","caption":null,"filename":"image.png","is_voice":false}
|
||||
[2026-02-21 11:19:23] is_voice: false
|
||||
[2026-02-21 11:19:23] Local file: /var/www/html/api/../uploads/media_6999db0b6b3f01.27857143.png exists=yes size=2515546
|
||||
[2026-02-21 11:19:25] Upload result: {"id":"25968821909466059"}
|
||||
[2026-02-21 11:19:25] Media ID obtained: 25968821909466059
|
||||
[2026-02-21 11:19:26] Send media by id response: {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSNEI4QkZFQjk2QjEyNkQ4RkMwAA=="}]}
|
||||
[2026-02-21 11:19:26] WhatsApp response (successful): {"messaging_product":"whatsapp","contacts":[{"input":"573022548060","wa_id":"573022548060"}],"messages":[{"id":"wamid.HBgMNTczMDIyNTQ4MDYwFQIAERgSNEI4QkZFQjk2QjEyNkQ4RkMwAA=="}]}
|
||||
[2026-02-21 11:19:26] Saving to DB - content: image.png, media_url: 25968821909466059, local_file: uploads/media_6999db0b6b3f01.27857143.png, local_thumb: uploads/media_6999db0b6b3f01.27857143.png
|
||||
|
||||
Reference in New Issue
Block a user