From 665fee99a9ce60afb685a1895f06a5bf432f0818 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Fri, 3 Jul 2026 00:41:40 -0500 Subject: [PATCH] fix(turnero): restaurar APIs del chat perdidas por force push del servidor Co-Authored-By: Claude Sonnet 4.6 --- modules/turnero/api/chat_get_list.php | 91 ++++++++++++++++ modules/turnero/api/chat_get_messages.php | 121 ++++++++++++++++++++++ modules/turnero/api/chat_mark_read.php | 40 +++++++ modules/turnero/api/chat_send_message.php | 66 ++++++++++++ 4 files changed, 318 insertions(+) create mode 100644 modules/turnero/api/chat_get_list.php create mode 100644 modules/turnero/api/chat_get_messages.php create mode 100644 modules/turnero/api/chat_mark_read.php create mode 100644 modules/turnero/api/chat_send_message.php diff --git a/modules/turnero/api/chat_get_list.php b/modules/turnero/api/chat_get_list.php new file mode 100644 index 0000000..c0c188d --- /dev/null +++ b/modules/turnero/api/chat_get_list.php @@ -0,0 +1,91 @@ +fetchAll($sql, $params); + + $totalRow = $db->fetch( + "SELECT COUNT(DISTINCT c.user_id) AS cnt FROM conversations c + JOIN users u ON u.id = c.user_id + WHERE c.canal = 'turnero'" . ($search !== '' ? " AND (u.name LIKE :s1 OR u.phone_number LIKE :s2)" : ''), + $search !== '' ? [':s1' => '%'.$search.'%', ':s2' => '%'.$search.'%'] : [] + ); + + $data = array_map(function($r) { + return [ + 'user_id' => intval($r['user_id']), + 'name' => $r['name'], + 'phone_number' => $r['phone_number'], + 'avatar_url' => $r['avatar_url'] ?? null, + 'last_message' => $r['last_message'] ?? '', + 'last_direction' => $r['last_direction'] ?? 'incoming', + 'last_message_type' => $r['last_message_type'] ?? 'text', + 'last_time' => $r['last_time'] ?? null, + 'unread_count' => intval($r['unread_count']), + ]; + }, $rows ?: []); + + $total = intval($totalRow['cnt'] ?? 0); + $hasMore = ($page * $limit) < $total; + + echo json_encode(['success' => true, 'data' => $data, 'total' => $total, 'has_more' => $hasMore, 'page' => $page]); + +} catch (Exception $e) { + error_log('chat_get_list.php: ' . $e->getMessage()); + http_response_code(500); + echo json_encode(['success' => false, 'error' => 'Error interno']); +} diff --git a/modules/turnero/api/chat_get_messages.php b/modules/turnero/api/chat_get_messages.php new file mode 100644 index 0000000..6853df2 --- /dev/null +++ b/modules/turnero/api/chat_get_messages.php @@ -0,0 +1,121 @@ + false, 'error' => 'user_id requerido']); + exit; + } + + $limit = max(1, min(200, intval($_GET['limit'] ?? 50))); + $before = !empty($_GET['before']) ? $_GET['before'] : null; + $beforeId = !empty($_GET['before_id']) ? intval($_GET['before_id']) : null; + $since = !empty($_GET['since']) ? $_GET['since'] : null; + + $tsRegex = '/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/'; + if ($before && !preg_match($tsRegex, $before)) { + http_response_code(400); echo json_encode(['success' => false, 'error' => 'before inválido']); exit; + } + if ($since && !preg_match($tsRegex, $since)) { + http_response_code(400); echo json_encode(['success' => false, 'error' => 'since inválido']); exit; + } + + $db = Database::getInstance(); + $params = ['user_id' => $userId]; + + $sql = "SELECT + c.id, c.user_id, c.content, c.message_id, + c.media_url, c.local_file, c.local_thumb, + c.filename, c.mime_type, + c.direction, c.message_type, c.status, + c.created_at, COALESCE(c.is_read, 0) AS is_read, + c.reply_to_message_id, c.reaction_emoji, c.reaction_to_message_id, + u.phone_number AS user_phone + FROM conversations c + LEFT JOIN users u ON u.id = c.user_id + WHERE c.user_id = :user_id AND c.canal = 'turnero'"; + + if ($since) { + $sql .= " AND c.created_at > :since"; + $params['since'] = $since; + $sql .= " ORDER BY c.created_at ASC, c.id ASC LIMIT {$limit}"; + } else { + if ($before) { + $sql .= " AND (c.created_at < :before_lt"; + $params['before_lt'] = $before; + if ($beforeId) { + $sql .= " OR (c.created_at = :before_eq AND c.id < :before_id)"; + $params['before_eq'] = $before; + $params['before_id'] = $beforeId; + } + $sql .= ")"; + } + $sql .= " ORDER BY c.created_at DESC, c.id DESC LIMIT {$limit}"; + } + + $rows = $db->fetchAll($sql, $params); + + if (!$since) { + $rows = array_reverse($rows ?: []); + } + + $hasMore = count($rows) === $limit; + $earliest = $rows[0]['created_at'] ?? null; + $earliestId = $rows[0]['id'] ?? null; + + $data = array_map(function($m) { + $mediaUrl = $m['media_url'] ?? null; + $external = null; + if ($mediaUrl) { + if (preg_match('#^https?://#i', $mediaUrl)) { + $external = $mediaUrl; + } else { + $external = '../../../api/get_media.php?id=' . urlencode($mediaUrl); + } + } + return [ + 'id' => intval($m['id']), + 'user_id' => intval($m['user_id']), + 'content' => $m['content'] ?? '', + 'message_id' => $m['message_id'] ?? null, + 'local_file' => $m['local_file'] ?? null, + 'local_thumb' => $m['local_thumb'] ?? null, + 'media_url_external' => $external, + 'filename' => $m['filename'] ?? null, + 'mime_type' => $m['mime_type'] ?? null, + 'user_phone' => $m['user_phone'] ?? null, + 'direction' => $m['direction'] ?? 'incoming', + 'message_type' => $m['message_type'] ?? 'text', + 'status' => $m['status'] ?? 'received', + 'created_at' => $m['created_at'], + 'is_read' => intval($m['is_read']), + 'reply_to_message_id' => $m['reply_to_message_id'] ?? null, + 'reaction_emoji' => $m['reaction_emoji'] ?? null, + 'reaction_to_message_id' => $m['reaction_to_message_id'] ?? null, + ]; + }, $rows); + + echo json_encode([ + 'success' => true, + 'data' => $data, + 'has_more' => $hasMore, + 'earliest' => $earliest, + 'earliest_id' => $earliestId, + ], JSON_UNESCAPED_UNICODE); + +} catch (Exception $e) { + error_log('chat_get_messages.php: ' . $e->getMessage()); + http_response_code(500); + echo json_encode(['success' => false, 'error' => 'Error interno']); +} diff --git a/modules/turnero/api/chat_mark_read.php b/modules/turnero/api/chat_mark_read.php new file mode 100644 index 0000000..cced0b0 --- /dev/null +++ b/modules/turnero/api/chat_mark_read.php @@ -0,0 +1,40 @@ + false, 'error' => 'Método no permitido']); + exit; +} + +try { + $input = json_decode(file_get_contents('php://input'), true) ?: $_POST; + $userId = intval($input['user_id'] ?? 0); + + if (!$userId) { + http_response_code(400); + echo json_encode(['success' => false, 'error' => 'user_id requerido']); + exit; + } + + $db = Database::getInstance(); + $db->query( + "UPDATE conversations SET is_read = 1 + WHERE user_id = :uid AND canal = 'turnero' AND direction = 'incoming' AND (is_read IS NULL OR is_read = 0)", + ['uid' => $userId] + ); + + echo json_encode(['success' => true]); + +} catch (Exception $e) { + error_log('chat_mark_read.php: ' . $e->getMessage()); + http_response_code(500); + echo json_encode(['success' => false, 'error' => 'Error interno']); +} diff --git a/modules/turnero/api/chat_send_message.php b/modules/turnero/api/chat_send_message.php new file mode 100644 index 0000000..f9beb05 --- /dev/null +++ b/modules/turnero/api/chat_send_message.php @@ -0,0 +1,66 @@ + false, 'error' => 'Método no permitido']); + exit; +} + +try { + $input = json_decode(file_get_contents('php://input'), true); + if (!$input) { + $input = $_POST; + } + + $userId = intval($input['user_id'] ?? 0); + $message = trim($input['message'] ?? ''); + + if (!$userId || $message === '') { + http_response_code(400); + echo json_encode(['success' => false, 'error' => 'user_id y message son requeridos']); + exit; + } + + $db = Database::getInstance(); + $user = $db->fetch("SELECT phone_number, name FROM users WHERE id = :id", ['id' => $userId]); + + if (!$user) { + http_response_code(404); + echo json_encode(['success' => false, 'error' => 'Usuario no encontrado']); + exit; + } + + // Verificar que el número turnero esté configurado + $turneroPhoneId = getConfigFromDB('whatsapp_phone_number_id_turnero', ''); + if (empty($turneroPhoneId)) { + http_response_code(503); + echo json_encode(['success' => false, 'error' => 'El número de WhatsApp del turnero no está configurado']); + exit; + } + + $operatorId = $_SESSION['admin_id'] ?? $_SESSION['user_id'] ?? null; + + $wa = new WhatsAppService('turnero'); + $response = $wa->sendTextMessage( + $user['phone_number'], + $message, + $operatorId ? ['operator_id' => $operatorId, 'canal' => 'turnero'] : ['canal' => 'turnero'] + ); + + echo json_encode(['success' => true, 'whatsapp_response' => $response]); + +} catch (Exception $e) { + error_log('chat_send_message.php: ' . $e->getMessage()); + http_response_code(500); + echo json_encode(['success' => false, 'error' => $e->getMessage()]); +}