Complete backend for SprintChat Hub migration: - Messages: send, edit, delete, list (paginated cursor), thread, search - Files: upload (multipart), download, thumbnail, info, list - Users: get, getByIds, search, status (online detection) - Reactions: add, remove, list (grouped by emoji) - Pins: pin, unpin, list (with message content) - Channel stats: member/message/pinned/unread counts 4 new DB tables: Hub_Messages, Hub_Files, Hub_Reactions, Hub_PinnedPosts 21 new endpoints added to PUBLIC_ROUTES Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
87 lines
2.6 KiB
PHP
87 lines
2.6 KiB
PHP
<?php
|
|
/**
|
|
* GET /api/hub/messages/list.php
|
|
*
|
|
* Get messages for a channel, paginated, newest first.
|
|
*
|
|
* Query params:
|
|
* ChannelID int REQUIRED
|
|
* Limit int optional default 50, max 200
|
|
* Before int optional message ID — get messages before this ID (cursor pagination)
|
|
* After int optional message ID — get messages after this ID
|
|
*
|
|
* Response: { OK: true, Messages: [...], HasMore: bool }
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../helpers.php';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'method_not_allowed'], 405);
|
|
}
|
|
|
|
$channelId = (int) ($_GET['ChannelID'] ?? 0);
|
|
$limit = min(max((int) ($_GET['Limit'] ?? 50), 1), 200);
|
|
$before = isset($_GET['Before']) ? (int) $_GET['Before'] : null;
|
|
$after = isset($_GET['After']) ? (int) $_GET['After'] : null;
|
|
|
|
if ($channelId <= 0) jsonResponse(['OK' => false, 'ERROR' => 'channel_id_required']);
|
|
|
|
// Verify channel exists
|
|
$channel = queryOne("SELECT ID FROM Hub_Channels WHERE ID = ?", [$channelId]);
|
|
if (!$channel) jsonResponse(['OK' => false, 'ERROR' => 'channel_not_found']);
|
|
|
|
// Build query
|
|
$sql = "SELECT * FROM Hub_Messages WHERE ChannelID = ? AND IsDeleted = 0 AND ParentID IS NULL";
|
|
$params = [$channelId];
|
|
|
|
if ($before !== null) {
|
|
$sql .= " AND ID < ?";
|
|
$params[] = $before;
|
|
}
|
|
if ($after !== null) {
|
|
$sql .= " AND ID > ?";
|
|
$params[] = $after;
|
|
}
|
|
|
|
if ($after !== null) {
|
|
$sql .= " ORDER BY ID ASC LIMIT ?";
|
|
} else {
|
|
$sql .= " ORDER BY ID DESC LIMIT ?";
|
|
}
|
|
$params[] = $limit + 1; // fetch one extra to determine HasMore
|
|
|
|
$rows = queryTimed($sql, $params);
|
|
$hasMore = count($rows) > $limit;
|
|
if ($hasMore) array_pop($rows);
|
|
|
|
// If we used ASC (After), reverse for consistent newest-first output
|
|
if ($after !== null) {
|
|
$rows = array_reverse($rows);
|
|
}
|
|
|
|
$messages = [];
|
|
foreach ($rows as $row) {
|
|
// Get reply count for each root message
|
|
$replyCount = queryOne(
|
|
"SELECT COUNT(*) as cnt FROM Hub_Messages WHERE ParentID = ? AND IsDeleted = 0",
|
|
[(int) $row['ID']]
|
|
);
|
|
|
|
$messages[] = [
|
|
'ID' => (int) $row['ID'],
|
|
'ChannelID' => (int) $row['ChannelID'],
|
|
'SenderAddress' => $row['SenderAddress'],
|
|
'Content' => $row['Content'],
|
|
'ParentID' => null,
|
|
'IsEdited' => (bool) $row['IsEdited'],
|
|
'ReplyCount' => (int) ($replyCount['cnt'] ?? 0),
|
|
'CreatedAt' => toISO8601($row['CreatedAt']),
|
|
'UpdatedAt' => toISO8601($row['UpdatedAt']),
|
|
];
|
|
}
|
|
|
|
jsonResponse([
|
|
'OK' => true,
|
|
'Messages' => $messages,
|
|
'HasMore' => $hasMore,
|
|
]);
|