Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
122 lines
4.7 KiB
PHP
122 lines
4.7 KiB
PHP
<?php
|
|
/**
|
|
* API - Mensajes de un contacto en el canal turnero
|
|
* Soporta paginación hacia atrás (before / before_id) y polling (since).
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../../config/config.php';
|
|
requireAuthentication();
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
header('Cache-Control: no-cache, no-store, must-revalidate');
|
|
|
|
try {
|
|
$userId = intval($_GET['user_id'] ?? 0);
|
|
if (!$userId) {
|
|
http_response_code(400);
|
|
echo json_encode(['success' => 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']);
|
|
}
|