From 94a1119bc707a97ce538f5a2ee4fbac772f8b22d Mon Sep 17 00:00:00 2001 From: Douglas Gubert Date: Fri, 18 Oct 2024 12:18:51 -0300 Subject: [PATCH] chore: sync latest Apps-engine alpha (#33649) --- .../src/definition/accessors/IRoomRead.ts | 20 +++++++++++++++++ .../src/server/accessors/RoomRead.ts | 22 +++++++++++++++++++ .../src/server/bridges/RoomBridge.ts | 16 ++++++++++++++ .../src/server/bridges/UserBridge.ts | 4 ++-- .../src/server/managers/AppListenerManager.ts | 18 ++++++++------- .../tests/server/accessors/RoomRead.spec.ts | 21 ++++++++++++++++++ .../tests/test-data/bridges/roomBridge.ts | 8 +++++++ .../tests/test-data/bridges/userBridge.ts | 2 +- 8 files changed, 100 insertions(+), 11 deletions(-) diff --git a/packages/apps-engine/src/definition/accessors/IRoomRead.ts b/packages/apps-engine/src/definition/accessors/IRoomRead.ts index f4e0df33239..dd7fa1b2a68 100644 --- a/packages/apps-engine/src/definition/accessors/IRoomRead.ts +++ b/packages/apps-engine/src/definition/accessors/IRoomRead.ts @@ -90,4 +90,24 @@ export interface IRoomRead { * @returns a list of the users with the leader role in the room */ getLeaders(roomId: string): Promise>; + + /** + * Retrieves an array of unread messages for a specific user in a specific room. + * + * @param roomId The unique identifier of the room from which to retrieve unread messages. + * @param uid The unique identifier of the user for whom to retrieve unread messages. + * @param options Optional parameters for retrieving messages: + * - limit: The maximum number of messages to retrieve. If more than 100 is passed, it defaults to 100. + * - skip: The number of messages to skip (for pagination). + * - sort: An object defining the sorting order of the messages. Each key is a field to sort by, and the value is either 'asc' for ascending order or 'desc' for descending order. + * @returns A Promise that resolves to an array of IMessage objects representing the unread messages for the specified user in the specified room. + */ + getUnreadByUser(roomId: string, uid: string, options?: Partial): Promise; + + /** + * Gets the user's unread messages count in a room. + * @param roomId room's id + * @param uid user's id + */ + getUserUnreadMessageCount(roomId: string, uid: string): Promise; } diff --git a/packages/apps-engine/src/server/accessors/RoomRead.ts b/packages/apps-engine/src/server/accessors/RoomRead.ts index 32786f529e5..5b7d58ef67e 100644 --- a/packages/apps-engine/src/server/accessors/RoomRead.ts +++ b/packages/apps-engine/src/server/accessors/RoomRead.ts @@ -58,6 +58,28 @@ export class RoomRead implements IRoomRead { return this.roomBridge.doGetLeaders(roomId, this.appId); } + public async getUnreadByUser(roomId: string, uid: string, options: Partial = {}): Promise { + const { limit = 100, sort = { createdAt: 'asc' }, skip = 0 } = options; + + if (typeof roomId !== 'string' || roomId.trim().length === 0) { + throw new Error('Invalid roomId: must be a non-empty string'); + } + + if (!Number.isFinite(limit) || limit <= 0 || limit > 100) { + throw new Error(`Invalid limit provided. Expected number between 1 and 100, got ${limit}`); + } + + this.validateSort(sort); + + const completeOptions: GetMessagesOptions = { limit, sort, skip }; + + return this.roomBridge.doGetUnreadByUser(roomId, uid, completeOptions, this.appId); + } + + public getUserUnreadMessageCount(roomId: string, uid: string): Promise { + return this.roomBridge.doGetUserUnreadMessageCount(roomId, uid, this.appId); + } + // If there are any invalid fields or values, throw private validateSort(sort: Record) { Object.entries(sort).forEach(([key, value]) => { diff --git a/packages/apps-engine/src/server/bridges/RoomBridge.ts b/packages/apps-engine/src/server/bridges/RoomBridge.ts index 19fecfab966..deb6f81667d 100644 --- a/packages/apps-engine/src/server/bridges/RoomBridge.ts +++ b/packages/apps-engine/src/server/bridges/RoomBridge.ts @@ -111,6 +111,18 @@ export abstract class RoomBridge extends BaseBridge { } } + public async doGetUnreadByUser(roomId: string, uid: string, options: GetMessagesOptions, appId: string): Promise { + if (this.hasReadPermission(appId)) { + return this.getUnreadByUser(roomId, uid, options, appId); + } + } + + public async doGetUserUnreadMessageCount(roomId: string, uid: string, appId: string): Promise { + if (this.hasReadPermission(appId)) { + return this.getUserUnreadMessageCount(roomId, uid, appId); + } + } + protected abstract create(room: IRoom, members: Array, appId: string): Promise; protected abstract getById(roomId: string, appId: string): Promise; @@ -147,6 +159,10 @@ export abstract class RoomBridge extends BaseBridge { protected abstract removeUsers(roomId: string, usernames: Array, appId: string): Promise; + protected abstract getUnreadByUser(roomId: string, uid: string, options: GetMessagesOptions, appId: string): Promise; + + protected abstract getUserUnreadMessageCount(roomId: string, uid: string, appId: string): Promise; + private hasWritePermission(appId: string): boolean { if (AppPermissionManager.hasPermission(appId, AppPermissions.room.write)) { return true; diff --git a/packages/apps-engine/src/server/bridges/UserBridge.ts b/packages/apps-engine/src/server/bridges/UserBridge.ts index 232f665078f..d67f2a091dd 100644 --- a/packages/apps-engine/src/server/bridges/UserBridge.ts +++ b/packages/apps-engine/src/server/bridges/UserBridge.ts @@ -41,7 +41,7 @@ export abstract class UserBridge extends BaseBridge { public async doGetUserUnreadMessageCount(uid: string, appId: string): Promise { if (this.hasReadPermission(appId)) { - return this.getUserUnreadMessageCount(uid); + return this.getUserUnreadMessageCount(uid, appId); } } @@ -65,7 +65,7 @@ export abstract class UserBridge extends BaseBridge { protected abstract getActiveUserCount(): Promise; - protected abstract getUserUnreadMessageCount(uid: string): Promise; + protected abstract getUserUnreadMessageCount(uid: string, appId: string): Promise; /** * Creates a user. diff --git a/packages/apps-engine/src/server/managers/AppListenerManager.ts b/packages/apps-engine/src/server/managers/AppListenerManager.ts index 40c1a78725e..dc145408a79 100644 --- a/packages/apps-engine/src/server/managers/AppListenerManager.ts +++ b/packages/apps-engine/src/server/managers/AppListenerManager.ts @@ -22,8 +22,7 @@ import type { IUIKitIncomingInteractionMessageContainer, IUIKitIncomingInteractionModalContainer, } from '../../definition/uikit/UIKitIncomingInteractionContainer'; -import type { IUIKitLivechatIncomingInteraction } from '../../definition/uikit/livechat'; -import { UIKitLivechatBlockInteractionContext } from '../../definition/uikit/livechat'; +import type { IUIKitLivechatBlockIncomingInteraction, IUIKitLivechatIncomingInteraction } from '../../definition/uikit/livechat'; import type { IFileUploadContext } from '../../definition/uploads/IFileUploadContext'; import type { IUser, IUserContext, IUserStatusContext, IUserUpdateContext } from '../../definition/users'; import type { AppManager } from '../AppManager'; @@ -1016,14 +1015,17 @@ export class AppListenerManager { const app = this.manager.getOneById(appId); - const interactionContext = ((interactionType: UIKitIncomingInteractionType, interactionData: IUIKitLivechatIncomingInteraction) => { - const { actionId, message, visitor, room, triggerId, container } = interactionData; + const interactionData = (( + interactionType: UIKitIncomingInteractionType, + interaction: IUIKitLivechatIncomingInteraction, + ): IUIKitLivechatBlockIncomingInteraction => { + const { actionId, message, visitor, room, triggerId, container } = interaction; switch (interactionType) { case UIKitIncomingInteractionType.BLOCK: { - const { value, blockId } = interactionData.payload as { value: string; blockId: string }; + const { value, blockId } = interaction.payload as { value: string; blockId: string }; - return new UIKitLivechatBlockInteractionContext({ + return { appId, actionId, blockId, @@ -1033,12 +1035,12 @@ export class AppListenerManager { value, message, container: container as IUIKitIncomingInteractionModalContainer | IUIKitIncomingInteractionMessageContainer, - }); + }; } } })(type, data); - return app.call(method, interactionContext); + return app.call(method, interactionData); } // Livechat diff --git a/packages/apps-engine/tests/server/accessors/RoomRead.spec.ts b/packages/apps-engine/tests/server/accessors/RoomRead.spec.ts index 0fe209a4161..7d5ca58eb48 100644 --- a/packages/apps-engine/tests/server/accessors/RoomRead.spec.ts +++ b/packages/apps-engine/tests/server/accessors/RoomRead.spec.ts @@ -14,6 +14,10 @@ export class RoomReadAccessorTestFixture { private messages: IMessageRaw[]; + private unreadRoomId: string; + + private unreadUserId: string; + private mockRoomBridgeWithRoom: RoomBridge; @SetupFixture @@ -21,10 +25,16 @@ export class RoomReadAccessorTestFixture { this.room = TestData.getRoom(); this.user = TestData.getUser(); this.messages = ['507f1f77bcf86cd799439011', '507f191e810c19729de860ea'].map((id) => TestData.getMessageRaw(id)); + this.unreadRoomId = this.messages[0].roomId; + this.unreadUserId = this.messages[0].sender._id; const theRoom = this.room; const theUser = this.user; const theMessages = this.messages; + + const theUnreadMsg = this.messages; + const { unreadRoomId } = this; + const { unreadUserId } = this; this.mockRoomBridgeWithRoom = { doGetById(id, appId): Promise { return Promise.resolve(theRoom); @@ -47,6 +57,12 @@ export class RoomReadAccessorTestFixture { doGetMessages(roomId, options, appId): Promise { return Promise.resolve(theMessages); }, + doGetUnreadByUser(roomId, uid, options, appId): Promise { + if (roomId === unreadRoomId && uid === unreadUserId) { + return Promise.resolve(theUnreadMsg); + } + return Promise.resolve([]); + }, } as RoomBridge; } @@ -68,6 +84,11 @@ export class RoomReadAccessorTestFixture { Expect(await rr.getDirectByUsernames([this.user.username])).toBe(this.room); Expect(await rr.getMessages('testing')).toBeDefined(); Expect(await rr.getMessages('testing')).toBe(this.messages); + Expect(await rr.getUnreadByUser(this.unreadRoomId, this.unreadUserId)).toBeDefined(); + Expect(await rr.getUnreadByUser(this.unreadRoomId, this.unreadUserId)).toEqual(this.messages); + + Expect(await rr.getUnreadByUser('fake', 'fake')).toBeDefined(); + Expect(await rr.getUnreadByUser('fake', 'fake')).toEqual([]); } @AsyncTest() diff --git a/packages/apps-engine/tests/test-data/bridges/roomBridge.ts b/packages/apps-engine/tests/test-data/bridges/roomBridge.ts index e5e7408b3d9..05fa810c5a6 100644 --- a/packages/apps-engine/tests/test-data/bridges/roomBridge.ts +++ b/packages/apps-engine/tests/test-data/bridges/roomBridge.ts @@ -64,4 +64,12 @@ export class TestsRoomBridge extends RoomBridge { public removeUsers(roomId: string, usernames: string[], appId: string): Promise { throw new Error('Method not implemented'); } + + public getUnreadByUser(roomId: string, uid: string, options: GetMessagesOptions, appId: string): Promise { + throw new Error('Method not implemented.'); + } + + protected getUserUnreadMessageCount(roomId: string, uid: string, appId: string): Promise { + throw new Error('Method not implemented.'); + } } diff --git a/packages/apps-engine/tests/test-data/bridges/userBridge.ts b/packages/apps-engine/tests/test-data/bridges/userBridge.ts index c9399f5b6c7..83464315b00 100644 --- a/packages/apps-engine/tests/test-data/bridges/userBridge.ts +++ b/packages/apps-engine/tests/test-data/bridges/userBridge.ts @@ -34,7 +34,7 @@ export class TestsUserBridge extends UserBridge { throw new Error('Method not implemented'); } - protected getUserUnreadMessageCount(uid: string): Promise { + protected getUserUnreadMessageCount(uid: string, appId: string): Promise { throw new Error('Method not implemented.'); }