From f9dc35021d98e1618a47b43d87ff395f77e5f6e3 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 16 Nov 2023 15:21:57 -0500 Subject: [PATCH] refactor(socket.io): deprecate SocketModules.chats.searchMessages in favour of api.search.roomMessages --- public/openapi/write.yaml | 2 + .../write/search/chats/roomId/messages.yaml | 37 ++++++++++++++++++ .../write/search/chats/roomId/users.yaml | 2 +- src/api/search.js | 38 +++++++++++++++++++ src/controllers/write/search.js | 9 ++++- src/routes/write/search.js | 2 + src/socket.io/modules.js | 36 +++--------------- 7 files changed, 93 insertions(+), 33 deletions(-) create mode 100644 public/openapi/write/search/chats/roomId/messages.yaml diff --git a/public/openapi/write.yaml b/public/openapi/write.yaml index aad2bf2d16..94b90186b3 100644 --- a/public/openapi/write.yaml +++ b/public/openapi/write.yaml @@ -232,6 +232,8 @@ paths: $ref: 'write/search/categories.yaml' /search/chats/{roomId}/users: $ref: 'write/search/chats/roomId/users.yaml' + /search/chats/{roomId}/messages: + $ref: 'write/search/chats/roomId/messages.yaml' /admin/settings/{setting}: $ref: 'write/admin/settings/setting.yaml' /admin/analytics: diff --git a/public/openapi/write/search/chats/roomId/messages.yaml b/public/openapi/write/search/chats/roomId/messages.yaml new file mode 100644 index 0000000000..9969aa23ce --- /dev/null +++ b/public/openapi/write/search/chats/roomId/messages.yaml @@ -0,0 +1,37 @@ +get: + tags: + - search + summary: find chat messages by keyword + description: This operation returns a set of messages in a chat room matching the keyword search. + parameters: + - in: path + name: roomId + schema: + type: number + required: true + description: room ID to check + example: 1 + - in: query + name: 'query' + schema: + type: string + required: false + description: The keyword used in the message search + example: 'foobar' + responses: + '200': + description: matching messages successfully retrieved + content: + application/json: + schema: + type: object + properties: + status: + $ref: ../../../../components/schemas/Status.yaml#/Status + response: + type: object + properties: + messages: + type: array + items: + $ref: ../../../../components/schemas/Chats.yaml#/MessageObject \ No newline at end of file diff --git a/public/openapi/write/search/chats/roomId/users.yaml b/public/openapi/write/search/chats/roomId/users.yaml index dd94a88d02..f8457cd3a7 100644 --- a/public/openapi/write/search/chats/roomId/users.yaml +++ b/public/openapi/write/search/chats/roomId/users.yaml @@ -16,7 +16,7 @@ get: schema: type: string required: false - description: The keyword used in the category search + description: The keyword used in the user search example: 'admin' responses: '200': diff --git a/src/api/search.js b/src/api/search.js index 043c97176e..b9645ee567 100644 --- a/src/api/search.js +++ b/src/api/search.js @@ -2,6 +2,7 @@ const _ = require('lodash'); +const db = require('../database'); const user = require('../user'); const categories = require('../categories'); const messaging = require('../messaging'); @@ -152,3 +153,40 @@ searchApi.roomUsers = async (caller, { query, roomId }) => { return { users: roomUsers }; }; + +searchApi.roomMessages = async (caller, { query, roomId, uid }) => { + const [roomData, inRoom] = await Promise.all([ + messaging.getRoomData(roomId), + messaging.isUserInRoom(caller.uid, roomId), + ]); + + if (!roomData) { + throw new Error('[[error:no-room]]'); + } + if (!inRoom) { + throw new Error('[[error:no-privileges]]'); + } + const { ids } = await plugins.hooks.fire('filter:messaging.searchMessages', { + content: query, + roomId: [roomId], + uid: [uid], + matchWords: 'any', + ids: [], + }); + + let userjoinTimestamp = 0; + if (!roomData.public) { + userjoinTimestamp = await db.sortedSetScore(`chat:room:${roomId}:uids`, caller.uid); + } + let messageData = await messaging.getMessagesData(ids, caller.uid, roomId, false); + messageData = messageData + .map((msg) => { + if (msg) { + msg.newSet = true; + } + return msg; + }) + .filter(msg => msg && !msg.deleted && msg.timestamp > userjoinTimestamp); + + return { messages: messageData }; +}; diff --git a/src/controllers/write/search.js b/src/controllers/write/search.js index cfdaad44a8..6d9e96db8b 100644 --- a/src/controllers/write/search.js +++ b/src/controllers/write/search.js @@ -10,6 +10,11 @@ Search.categories = async (req, res) => { }; Search.roomUsers = async (req, res) => { - const { query } = req.query; - helpers.formatApiResponse(200, res, await api.search.roomUsers(req, { query, ...req.params })); + const { query, uid } = req.query; + helpers.formatApiResponse(200, res, await api.search.roomUsers(req, { query, uid, ...req.params })); +}; + +Search.roomMessages = async (req, res) => { + const { query } = req.query; + helpers.formatApiResponse(200, res, await api.search.roomMessages(req, { query, ...req.params })); }; diff --git a/src/routes/write/search.js b/src/routes/write/search.js index 4d4108a05b..5f0b41d516 100644 --- a/src/routes/write/search.js +++ b/src/routes/write/search.js @@ -14,7 +14,9 @@ module.exports = function () { // setupApiRoute(router, 'post', '/', [...middlewares], controllers.write.search.TBD); setupApiRoute(router, 'get', '/categories', [], controllers.write.search.categories); + setupApiRoute(router, 'get', '/chats/:roomId/users', [...middlewares, middleware.checkRequired.bind(null, ['query']), middleware.canChat, middleware.assert.room], controllers.write.search.roomUsers); + setupApiRoute(router, 'get', '/chats/:roomId/messages', [...middlewares, middleware.checkRequired.bind(null, ['query']), middleware.canChat, middleware.assert.room], controllers.write.search.roomMessages); return router; }; diff --git a/src/socket.io/modules.js b/src/socket.io/modules.js index 5bbe88c068..edbd1eeae9 100644 --- a/src/socket.io/modules.js +++ b/src/socket.io/modules.js @@ -189,40 +189,16 @@ SocketModules.chats.setNotificationSetting = async (socket, data) => { }; SocketModules.chats.searchMessages = async (socket, data) => { + sockets.warnDeprecated(socket, 'GET /api/v3/search/chats/:roomId/messages'); + if (!data || !utils.isNumber(data.roomId) || !data.content) { throw new Error('[[error:invalid-data]]'); } - const [roomData, inRoom] = await Promise.all([ - Messaging.getRoomData(data.roomId), - Messaging.isUserInRoom(socket.uid, data.roomId), - ]); - if (!roomData) { - throw new Error('[[error:no-room]]'); - } - if (!inRoom) { - throw new Error('[[error:no-privileges]]'); - } - const { ids } = await plugins.hooks.fire('filter:messaging.searchMessages', { - content: data.content, - roomId: [data.roomId], - uid: [data.uid], - matchWords: 'any', - ids: [], - }); - - let userjoinTimestamp = 0; - if (!roomData.public) { - userjoinTimestamp = await db.sortedSetScore(`chat:room:${data.roomId}:uids`, socket.uid); - } - const messageData = await Messaging.getMessagesData(ids, socket.uid, data.roomId, false); - messageData.forEach((msg) => { - if (msg) { - msg.newSet = true; - } - }); - - return messageData.filter(msg => msg && !msg.deleted && msg.timestamp > userjoinTimestamp); + // parameter renamed; backwards compatibility + data.query = data.content; + delete data.content; + return await api.search.roomMessages(socket, data); }; SocketModules.chats.loadPinnedMessages = async (socket, data) => {