Skip to content

Commit

Permalink
Merge branch 'develop' into feat/change-subject-on-transcript
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] authored Jul 23, 2024
2 parents 95d1b42 + 05db8aa commit e7fa992
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 67 deletions.
3 changes: 2 additions & 1 deletion apps/meteor/app/apps/server/bridges/livechat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ export class AppLivechatBridge extends LivechatBridge {
username,
name,
type,
};
userType: 'user',
} as const;

let userId;
let transferredTo;
Expand Down
18 changes: 11 additions & 7 deletions apps/meteor/app/apps/server/converters/messages.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isMessageFromVisitor } from '@rocket.chat/core-typings';
import { Messages, Rooms, Users } from '@rocket.chat/models';
import { Random } from '@rocket.chat/random';

Expand Down Expand Up @@ -107,16 +108,19 @@ export class AppMessagesConverter {
return undefined;
}

let user = await cache.get('user')(message.u._id);

// When the sender of the message is a Guest (livechat) and not a user
if (!user) {
user = this.orch.getConverters().get('users').convertToApp(message.u);
}
// When the message contains token, means the message is from the visitor(omnichannel)
const user = await (isMessageFromVisitor(msgObj)
? this.orch.getConverters().get('users').convertToApp(message.u)
: cache.get('user')(message.u._id));

delete message.u;

return user;
/**
* Old System Messages from visitor doesn't have the `token` field, to not return
* `sender` as undefined, so we need to add this fallback here.
*/

return user || this.orch.getConverters().get('users').convertToApp(message.u);
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ export async function sendMessageNotifications(message: IMessage, room: IRoom, u
return;
}

const sender = await roomCoordinator.getRoomDirectives(room.t).getMsgSender(message.u._id);
const sender = await roomCoordinator.getRoomDirectives(room.t).getMsgSender(message);
if (!sender) {
return message;
}
Expand Down
3 changes: 1 addition & 2 deletions apps/meteor/app/livechat/server/api/v1/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,7 @@ API.v1.addRoute(
throw new Error('error-invalid-visitor');
}

const transferedBy = this.user satisfies TransferByData;
transferData.transferredBy = normalizeTransferredByData(transferedBy, room);
transferData.transferredBy = normalizeTransferredByData(this.user, room);
if (transferData.userId) {
const userToTransfer = await Users.findOneById(transferData.userId);
if (userToTransfer) {
Expand Down
16 changes: 12 additions & 4 deletions apps/meteor/app/livechat/server/lib/Helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ export const createLivechatRoom = async <

await callbacks.run('livechat.newRoom', room);

await sendMessage(guest, { t: 'livechat-started', msg: '', groupable: false }, room);
// TODO: replace with `Message.saveSystemMessage`

await sendMessage(guest, { t: 'livechat-started', msg: '', groupable: false, token: guest.token }, room);

return result.value as IOmnichannelRoom;
};
Expand Down Expand Up @@ -646,6 +648,7 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi
'',
{ _id, username },
{
...(transferData.transferredBy.userType === 'visitor' && { token: room.v.token }),
transferData: {
...transferData,
prevDepartment: transferData.originalDepartmentName,
Expand Down Expand Up @@ -681,18 +684,23 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi
return true;
};

export const normalizeTransferredByData = (transferredBy: TransferByData, room: IOmnichannelRoom) => {
type MakePropertyOptional<T, K extends keyof T> = Omit<T, K> & { [P in K]?: T[P] };

export const normalizeTransferredByData = (
transferredBy: MakePropertyOptional<TransferByData, 'userType'>,
room: IOmnichannelRoom,
): TransferByData => {
if (!transferredBy || !room) {
throw new Error('You must provide "transferredBy" and "room" params to "getTransferredByData"');
}
const { servedBy: { _id: agentId } = {} } = room;
const { _id, username, name, userType: transferType } = transferredBy;
const type = transferType || (_id === agentId ? 'agent' : 'user');
const userType = transferType || (_id === agentId ? 'agent' : 'user');
return {
_id,
username,
...(name && { name }),
type,
userType,
};
};

Expand Down
78 changes: 39 additions & 39 deletions apps/meteor/app/livechat/server/lib/LivechatTyped.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,6 @@ class LivechatClass {

this.logger.debug(`DB updated for room ${room._id}`);

const message = {
t: 'livechat-close',
msg: comment,
groupable: false,
transcriptRequested: !!transcriptRequest,
};

// Retrieve the closed room
const newRoom = await LivechatRooms.findOneById(rid);

Expand All @@ -339,7 +332,17 @@ class LivechatClass {
}

this.logger.debug(`Sending closing message to room ${room._id}`);
await sendMessage(chatCloser, message, newRoom);
await sendMessage(
chatCloser,
{
t: 'livechat-close',
msg: comment,
groupable: false,
transcriptRequested: !!transcriptRequest,
...(isRoomClosedByVisitorParams(params) && { token: chatCloser.token }),
},
newRoom,
);

await Message.saveSystemMessage('command', rid, 'promptTranscript', closeData.closedBy);

Expand Down Expand Up @@ -589,7 +592,9 @@ class LivechatClass {
visitorDataToUpdate.visitorEmails = [{ address: visitorEmail }];
}

if (department) {
const livechatVisitor = await LivechatVisitors.getVisitorByToken(token, { projection: { _id: 1 } });

if (livechatVisitor?.department !== department && department) {
Livechat.logger.debug(`Attempt to find a department with id/name ${department}`);
const dep = await LivechatDepartment.findOneByIdOrName(department, { projection: { _id: 1 } });
if (!dep) {
Expand All @@ -600,8 +605,6 @@ class LivechatClass {
visitorDataToUpdate.department = dep._id;
}

const livechatVisitor = await LivechatVisitors.getVisitorByToken(token, { projection: { _id: 1 } });

visitorDataToUpdate.token = livechatVisitor?.token || token;

let existingUser = null;
Expand Down Expand Up @@ -1144,7 +1147,7 @@ class LivechatClass {
if (guest.name) {
message.alias = guest.name;
}
return Object.assign(await sendMessage(guest, message, room), {
return Object.assign(await sendMessage(guest, { ...message, token: guest.token }, room), {
newRoom,
showConnecting: this.showConnecting(),
});
Expand Down Expand Up @@ -1263,42 +1266,39 @@ class LivechatClass {
_id: String,
username: String,
name: Match.Maybe(String),
type: String,
userType: String,
}),
);

const { _id, username } = transferredBy;
const scopeData = scope || (nextDepartment ? 'department' : 'agent');
this.logger.info(`Storing new chat transfer of ${room._id} [Transfered by: ${_id} to ${scopeData}]`);

const transfer = {
transferData: {
transferredBy,
await sendMessage(
transferredBy,
{
t: 'livechat_transfer_history',
rid: room._id,
ts: new Date(),
scope: scopeData,
comment,
...(previousDepartment && { previousDepartment }),
...(nextDepartment && { nextDepartment }),
...(transferredTo && { transferredTo }),
},
};

const type = 'livechat_transfer_history';
const transferMessage = {
t: type,
rid: room._id,
ts: new Date(),
msg: '',
u: {
_id,
username,
msg: '',
u: {
_id,
username,
},
groupable: false,
...(transferData.transferredBy.userType === 'visitor' && { token: room.v.token }),
transferData: {
transferredBy,
ts: new Date(),
scope: scopeData,
comment,
...(previousDepartment && { previousDepartment }),
...(nextDepartment && { nextDepartment }),
...(transferredTo && { transferredTo }),
},
},
groupable: false,
};

Object.assign(transferMessage, transfer);

await sendMessage(transferredBy, transferMessage, room);
room,
);
}

async saveGuest(guestData: Pick<ILivechatVisitor, '_id' | 'name' | 'livechatData'> & { email?: string; phone?: string }, userId: string) {
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/definition/IRoomTypeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export interface IRoomTypeServerDirectives {
notificationMessage: string,
userId: string,
) => Promise<{ title: string | undefined; text: string; name: string | undefined }>;
getMsgSender: (senderId: IUser['_id']) => Promise<IUser | null>;
getMsgSender: (message: IMessage) => Promise<IUser | null>;
includeInRoomSearch: () => boolean;
getReadReceiptsExtraData: (message: IMessage) => Partial<ReadReceipt>;
includeInDashboard: () => boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class AutoTransferChatSchedulerClass {

await forwardRoomToAgent(room, {
userId: agent.agentId,
transferredBy,
transferredBy: { ...transferredBy, userType: 'user' },
transferredTo: agent,
scope: 'autoTransferUnansweredChatsToAgent',
comment: timeoutDuration,
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/server/lib/rooms/roomCoordinator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ class RoomCoordinatorServer extends RoomCoordinator {

return { title, text, name: room.name };
},
getMsgSender(senderId: IUser['_id']): Promise<IUser | null> {
return Users.findOneById(senderId);
getMsgSender(message: IMessage): Promise<IUser | null> {
return Users.findOneById(message.u._id);
},
includeInRoomSearch(): boolean {
return false;
Expand Down
7 changes: 5 additions & 2 deletions apps/meteor/server/lib/rooms/roomTypes/livechat.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { AtLeast, ValueOf } from '@rocket.chat/core-typings';
import { isMessageFromVisitor } from '@rocket.chat/core-typings';
import { LivechatVisitors, LivechatRooms } from '@rocket.chat/models';

import { RoomSettingsEnum, RoomMemberActions } from '../../../../definition/IRoomTypeConfig';
Expand Down Expand Up @@ -38,8 +39,10 @@ roomCoordinator.add(LivechatRoomType, {
return { title, text, name: roomName };
},

async getMsgSender(senderId) {
return LivechatVisitors.findOneEnabledById(senderId);
async getMsgSender(message) {
if (isMessageFromVisitor(message)) {
return LivechatVisitors.findOneEnabledById(message.u._id);
}
},

getReadReceiptsExtraData(message) {
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/server/lib/rooms/roomTypes/voip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ roomCoordinator.add(VoipRoomType, {
return { title, text, name: room.name };
},

async getMsgSender(senderId) {
return Users.findOneById(senderId);
async getMsgSender(message) {
return Users.findOneById(message.u._id);
},
} as AtLeast<IRoomTypeServerDirectives, 'roomName'>);
6 changes: 6 additions & 0 deletions packages/core-typings/src/IMessage/IMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,3 +401,9 @@ export type IMessageWithPendingFileImport = IMessage & {
downloaded?: boolean;
};
};

export interface IMessageFromVisitor extends IMessage {
token: string;
}

export const isMessageFromVisitor = (message: IMessage): message is IMessageFromVisitor => 'token' in message;
7 changes: 2 additions & 5 deletions packages/core-typings/src/omnichannel/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ export type TransferData = {
userId?: string;
departmentId?: string;
department?: Pick<ILivechatDepartment, '_id' | 'name'>;
transferredBy: {
_id: string;
username?: string;
};
transferredBy: TransferByData;
transferredTo?: {
username?: string;
name?: string;
Expand All @@ -47,5 +44,5 @@ export type TransferByData = {
_id: string;
username?: string;
name?: string;
userType?: 'agent' | 'user' | 'visitor';
userType: 'agent' | 'user' | 'visitor';
};

0 comments on commit e7fa992

Please sign in to comment.