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>
79 lines
2.3 KiB
PHP
79 lines
2.3 KiB
PHP
<?php
|
|
/**
|
|
* GET /api/hub/messages/search.php
|
|
*
|
|
* Search messages across channels or within a specific channel.
|
|
*
|
|
* Query params:
|
|
* Query string REQUIRED search term
|
|
* ChannelID int optional limit to a specific channel
|
|
* Limit int optional default 25, max 100
|
|
* Offset int optional default 0
|
|
*
|
|
* Response: { OK: true, Messages: [...], Total: int }
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../helpers.php';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'method_not_allowed'], 405);
|
|
}
|
|
|
|
$query = trim($_GET['Query'] ?? '');
|
|
$channelId = isset($_GET['ChannelID']) ? (int) $_GET['ChannelID'] : null;
|
|
$limit = min(max((int) ($_GET['Limit'] ?? 25), 1), 100);
|
|
$offset = max((int) ($_GET['Offset'] ?? 0), 0);
|
|
|
|
if ($query === '') jsonResponse(['OK' => false, 'ERROR' => 'query_required']);
|
|
|
|
$searchTerm = '%' . $query . '%';
|
|
|
|
// Count total
|
|
$countSql = "SELECT COUNT(*) as cnt FROM Hub_Messages WHERE Content LIKE ? AND IsDeleted = 0";
|
|
$countParams = [$searchTerm];
|
|
|
|
if ($channelId !== null) {
|
|
$countSql .= " AND ChannelID = ?";
|
|
$countParams[] = $channelId;
|
|
}
|
|
|
|
$total = (int) (queryOne($countSql, $countParams)['cnt'] ?? 0);
|
|
|
|
// Fetch results
|
|
$sql = "SELECT m.*, c.Name AS ChannelName, c.DisplayName AS ChannelDisplayName
|
|
FROM Hub_Messages m
|
|
JOIN Hub_Channels c ON c.ID = m.ChannelID
|
|
WHERE m.Content LIKE ? AND m.IsDeleted = 0";
|
|
$params = [$searchTerm];
|
|
|
|
if ($channelId !== null) {
|
|
$sql .= " AND m.ChannelID = ?";
|
|
$params[] = $channelId;
|
|
}
|
|
|
|
$sql .= " ORDER BY m.CreatedAt DESC LIMIT ? OFFSET ?";
|
|
$params[] = $limit;
|
|
$params[] = $offset;
|
|
|
|
$rows = queryTimed($sql, $params);
|
|
|
|
$messages = [];
|
|
foreach ($rows as $row) {
|
|
$messages[] = [
|
|
'ID' => (int) $row['ID'],
|
|
'ChannelID' => (int) $row['ChannelID'],
|
|
'ChannelName' => $row['ChannelName'],
|
|
'ChannelDisplayName' => $row['ChannelDisplayName'],
|
|
'SenderAddress' => $row['SenderAddress'],
|
|
'Content' => $row['Content'],
|
|
'ParentID' => $row['ParentID'] ? (int) $row['ParentID'] : null,
|
|
'IsEdited' => (bool) $row['IsEdited'],
|
|
'CreatedAt' => toISO8601($row['CreatedAt']),
|
|
];
|
|
}
|
|
|
|
jsonResponse([
|
|
'OK' => true,
|
|
'Messages' => $messages,
|
|
'Total' => $total,
|
|
]);
|