From 08a68a3f96518513076d0e1f1751d7abec7ad60c Mon Sep 17 00:00:00 2001 From: Jamil Daoud Date: Tue, 29 Aug 2023 20:19:11 +0300 Subject: [PATCH 1/4] Added File after translating --- src/api/chats.ts | 168 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 src/api/chats.ts diff --git a/src/api/chats.ts b/src/api/chats.ts new file mode 100644 index 000000000..2e4c4a612 --- /dev/null +++ b/src/api/chats.ts @@ -0,0 +1,168 @@ + + +// import { __createBinding, __importStar, __awaiter, __importDefault } from 'tslib'; +import validator from 'validator'; +import user from '../user'; +import meta from '../meta'; +import messaging from '../messaging'; +import plugins from '../plugins'; +import socketHelpers from '../socket.io/helpers'; + + +// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call +const chatsAPI: { [key: string]: Function } = {}; + +interface SessionData { + lastChatMessageTime?: number; +} + +interface Caller { + uid: number; + request?: { + session: SessionData; + }; + session?: SessionData; + ip?: string; +} + +interface UsersResponse { + users: Caller[]; +} + + +interface Data { + uids?: number[]; + roomId?: number; + message?: string; + name?: string; +} + + +// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + +function rateLimitExceeded(caller: Caller): boolean { + const session = caller.request ? caller.request.session : caller.session; // socket vs req + const now = Date.now(); + session.lastChatMessageTime = session.lastChatMessageTime || 0; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (now - session.lastChatMessageTime < meta.config.chatMessageDelay) { + return true; + } + session.lastChatMessageTime = now; + return false; +} + +chatsAPI.create = async function (caller: Caller, data: Data) { + if (rateLimitExceeded(caller)) { + throw new Error('[[error:too-many-messages]]'); + } + + if (!data.uids || !Array.isArray(data.uids)) { + throw new Error(`[[error:wrong-parameter-type, uids, ${typeof data.uids}, Array]]`); + } + + await Promise.all(data.uids.map(async uid => messaging.canMessageUser(caller.uid, uid))); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + const roomId = await messaging.newRoom(caller.uid, data.uids!); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + return await messaging.getRoomData(roomId); +}; + +chatsAPI.post = async (caller: Caller, data: Data) => { + if (rateLimitExceeded(caller)) { + throw new Error('[[error:too-many-messages]]'); + } + + ({ data } = await plugins.hooks.fire('filter:messaging.send', { + data, + uid: caller.uid, + }) as { data: Data }); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + await messaging.canMessageRoom(caller.uid, data.roomId!); + const message = await messaging.sendMessage({ + uid: caller.uid, + roomId: data.roomId!, + content: data.message!, + timestamp: Date.now(), + ip: caller.ip, + }); + messaging.notifyUsersInRoom(caller.uid, data.roomId!, message); + user.updateOnlineUsers(caller.uid); + + return message; +}; + +chatsAPI.rename = async (caller: Caller, data: Data) => { + await messaging.renameRoom(caller.uid, data.roomId!, data.name!); + const uids = await messaging.getUidsInRoom(data.roomId!, 0, -1); + const eventData = { roomId: data.roomId!, newName: validator.escape(String(data.name)) }; + + socketHelpers.emitToUids('event:chats.roomRename', eventData, uids); + return messaging.loadRoom(caller.uid, { + roomId: data.roomId!, + }); +}; + +chatsAPI.users = async (caller: Caller, data: Data) => { + const [isOwner, users] = await Promise.all([ + messaging.isRoomOwner(caller.uid, data.roomId!), + messaging.getUsersInRoom(data.roomId!, 0, -1), + ]); + + users.forEach((user) => { + + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call + + user.canKick = (parseInt(user.uid, 10) !== caller.uid) && isOwner; + }); + + return { users }; +}; + +chatsAPI.invite = async (caller: Caller, data: Data) => { + const userCount = await messaging.getUserCountInRoom(data.roomId!); + const maxUsers = meta.config.maximumUsersInChatRoom; + if (maxUsers && userCount >= maxUsers) { + throw new Error('[[error:cant-add-more-users-to-chat-room]]'); + } + + const uidsExist = await user.exists(data.uids!); + if (!uidsExist.every(Boolean)) { + throw new Error('[[error:no-user]]'); + } + + await Promise.all(data.uids!.map(async uid => messaging.canMessageUser(caller.uid, uid))); + await messaging.addUsersToRoom(caller.uid, data.uids!, data.roomId!); + + delete data.uids; + return chatsAPI.users(caller, data); +}; + + + + + +chatsAPI.kick = async (caller: Caller, data: Data): Promise => { + const uidsExist = await user.exists(data.uids); + + if (!uidsExist.every((val: any) => !!val)) { + throw new Error('[[error:no-user]]'); + } + + const userIDsAsString = data.uids!.map(uid => uid.toString()); + + if (userIDsAsString.length === 1 && userIDsAsString[0] === caller.uid.toString()) { + await messaging.leaveRoom([caller.uid.toString()], data.roomId!); + } else { + await messaging.removeUsersFromRoom(caller.uid, userIDsAsString, data.roomId!); + } + + delete data.uids; + + // Assuming `chatsAPI.users` returns an object of type UsersResponse + const usersResponse = await chatsAPI.users(caller, data) as UsersResponse; + return usersResponse; +}; + + +export = chatsAPI; From c7ca904a0944daf01336477ec9fd1a1b993fd66f Mon Sep 17 00:00:00 2001 From: Jamil Daoud Date: Tue, 29 Aug 2023 21:32:38 +0300 Subject: [PATCH 2/4] Fixed some errors including types and create function --- src/api/chats.ts | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/api/chats.ts b/src/api/chats.ts index 2e4c4a612..bcedb944b 100644 --- a/src/api/chats.ts +++ b/src/api/chats.ts @@ -26,10 +26,9 @@ interface Caller { } interface UsersResponse { - users: Caller[]; + user: Caller[]; } - interface Data { uids?: number[]; roomId?: number; @@ -52,22 +51,30 @@ function rateLimitExceeded(caller: Caller): boolean { return false; } -chatsAPI.create = async function (caller: Caller, data: Data) { +interface RoomData { + roomId: number +} + +chatsAPI.create = async (caller: Caller, data: Data): Promise => { if (rateLimitExceeded(caller)) { throw new Error('[[error:too-many-messages]]'); } - if (!data.uids || !Array.isArray(data.uids)) { throw new Error(`[[error:wrong-parameter-type, uids, ${typeof data.uids}, Array]]`); } - await Promise.all(data.uids.map(async uid => messaging.canMessageUser(caller.uid, uid))); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const roomId = await messaging.newRoom(caller.uid, data.uids!); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return await messaging.getRoomData(roomId); + await Promise.all(data.uids.map(async (uid) => { + await messaging.canMessageUser(caller.uid, uid); + })); + + const roomId = await messaging.newRoom(caller.uid, data.uids); + const roomData = await messaging.getRoomData(roomId); + return roomData; }; + + + chatsAPI.post = async (caller: Caller, data: Data) => { if (rateLimitExceeded(caller)) { throw new Error('[[error:too-many-messages]]'); From 1522a1c48f5f9eb21fb9ab890438144d5054d9ae Mon Sep 17 00:00:00 2001 From: Jamil Daoud Date: Tue, 29 Aug 2023 22:06:34 +0300 Subject: [PATCH 3/4] Fixed rename function and solved many errors --- src/api/chats.ts | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/api/chats.ts b/src/api/chats.ts index bcedb944b..50acf9a19 100644 --- a/src/api/chats.ts +++ b/src/api/chats.ts @@ -80,36 +80,55 @@ chatsAPI.post = async (caller: Caller, data: Data) => { throw new Error('[[error:too-many-messages]]'); } + // Fire a hook and destructure the result into the 'data' variable ({ data } = await plugins.hooks.fire('filter:messaging.send', { data, uid: caller.uid, }) as { data: Data }); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - await messaging.canMessageRoom(caller.uid, data.roomId!); + + // Check if data.roomId, data.message, and caller.ip are defined + if (!data.roomId || !data.message || !caller.ip) { + throw new Error('Some required data is missing'); + } + + // Check if data.roomId is not null, then check if caller can message the room + await messaging.canMessageRoom(caller.uid, data.roomId); + + // Construct and send the message const message = await messaging.sendMessage({ uid: caller.uid, - roomId: data.roomId!, - content: data.message!, + roomId: data.roomId, + content: data.message, timestamp: Date.now(), ip: caller.ip, }); - messaging.notifyUsersInRoom(caller.uid, data.roomId!, message); + + // Notify users in the room about the new message + messaging.notifyUsersInRoom(caller.uid, data.roomId, message); + + // Update online user status user.updateOnlineUsers(caller.uid); + // Return the sent message return message; }; + chatsAPI.rename = async (caller: Caller, data: Data) => { - await messaging.renameRoom(caller.uid, data.roomId!, data.name!); - const uids = await messaging.getUidsInRoom(data.roomId!, 0, -1); - const eventData = { roomId: data.roomId!, newName: validator.escape(String(data.name)) }; + await messaging.renameRoom(caller.uid, data.roomId, data.name); + const uids = await messaging.getUidsInRoom(data.roomId, 0, -1); + const eventData = { roomId: data.roomId, newName: validator.escape(String(data.name)) }; socketHelpers.emitToUids('event:chats.roomRename', eventData, uids); - return messaging.loadRoom(caller.uid, { - roomId: data.roomId!, + + // Assuming `messaging.loadRoom` returns a Promise + return await messaging.loadRoom(caller.uid, { + roomId: data.roomId, }); }; + + chatsAPI.users = async (caller: Caller, data: Data) => { const [isOwner, users] = await Promise.all([ messaging.isRoomOwner(caller.uid, data.roomId!), From 0ba06f6743e8269b8754e0f198d38a29f5f34cb6 Mon Sep 17 00:00:00 2001 From: Jamil Daoud Date: Tue, 29 Aug 2023 22:45:27 +0300 Subject: [PATCH 4/4] Fixed users and invite function and brought numbers of errors down substantially --- src/api/chats.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/api/chats.ts b/src/api/chats.ts index 50acf9a19..8153a8e70 100644 --- a/src/api/chats.ts +++ b/src/api/chats.ts @@ -127,27 +127,29 @@ chatsAPI.rename = async (caller: Caller, data: Data) => { }); }; +interface User { + uid: number; + canKick: boolean; +} chatsAPI.users = async (caller: Caller, data: Data) => { const [isOwner, users] = await Promise.all([ messaging.isRoomOwner(caller.uid, data.roomId!), messaging.getUsersInRoom(data.roomId!, 0, -1), - ]); + ]) as [boolean, User[]]; users.forEach((user) => { - - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - - user.canKick = (parseInt(user.uid, 10) !== caller.uid) && isOwner; + user.canKick = (parseInt(user.uid.toString(), 10) !== caller.uid) && isOwner; }); return { users }; }; + chatsAPI.invite = async (caller: Caller, data: Data) => { const userCount = await messaging.getUserCountInRoom(data.roomId!); - const maxUsers = meta.config.maximumUsersInChatRoom; + const maxUsers = (meta.config as { maximumUsersInChatRoom: number }).maximumUsersInChatRoom; if (maxUsers && userCount >= maxUsers) { throw new Error('[[error:cant-add-more-users-to-chat-room]]'); } @@ -157,17 +159,19 @@ chatsAPI.invite = async (caller: Caller, data: Data) => { throw new Error('[[error:no-user]]'); } - await Promise.all(data.uids!.map(async uid => messaging.canMessageUser(caller.uid, uid))); + await Promise.all(data.uids!.map(async (uid: string | number) => messaging.canMessageUser(caller.uid, uid))); await messaging.addUsersToRoom(caller.uid, data.uids!, data.roomId!); delete data.uids; - return chatsAPI.users(caller, data); + return chatsAPI.users(caller, data) as UsersResponse; // Assuming UsersResponse is the correct type }; + + chatsAPI.kick = async (caller: Caller, data: Data): Promise => { const uidsExist = await user.exists(data.uids);