Skip to content

Commit

Permalink
Merge branch 'feat/single-contact-id' into feat/sci/use-contact-name-…
Browse files Browse the repository at this point in the history
…on-rooms
  • Loading branch information
pierre-lehnen-rc authored Nov 6, 2024
2 parents a2470d2 + 0977ef1 commit 3591e0b
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 22 deletions.
97 changes: 81 additions & 16 deletions apps/meteor/app/apps/server/converters/rooms.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { RoomType } from '@rocket.chat/apps-engine/definition/rooms';
import { LivechatVisitors, Rooms, LivechatDepartment, Users } from '@rocket.chat/models';
import { LivechatVisitors, Rooms, LivechatDepartment, Users, LivechatContacts, LivechatRooms } from '@rocket.chat/models';

import { transformMappedData } from './transformMappedData';

Expand All @@ -20,6 +20,76 @@ export class AppRoomsConverter {
return this.convertRoom(room);
}

async convertVisitorToRoomV(room, visitorId, contactId) {
const visitor = await LivechatVisitors.findOneEnabledById(room.visitor.id);

const { lastMessageTs, phone } = room.visitorChannelInfo;

return {
_id: visitor._id,
username: visitor.username,
token: visitor.token,
status: visitor.status || 'online',
...(lastMessageTs && { lastMessageTs }),
...(phone && { phone }),
...(contactId && { contactId }),
};
}

async convertAppVisitorData(room) {
const contact = room.contact?._id && (await LivechatContacts.findOneById(room.contact._id, { projection: { _id: 1 } }));

if (room.contact?._id && !contact) {
throw new Error('error-invalid-contact-id');
}

if (room.visitor) {
return this.convertVisitorToRoomV(room, room.visitor.id, contact?._id);
}

// If a livechat room has a contact but no visitor, we try to find the visitor data from elsewhere
if (!room.contact?._id || room.type !== RoomType.LIVE_CHAT) {
return;
}

// If the contact only has one channel, use the visitor from it
if (contact.channels?.length === 1 && contact.channels[0].visitorId) {
return this.convertVisitorToRoomV(room, contact.channels[0].visitorId, contact._id);
}

// if the room already exists, we just use the visitor data from it
const existingRoom = await LivechatRooms.findOneById(room.id);
if (existingRoom?.v) {
return {
...existingRoom.v,
contactId: contact._id,
};
}

// If the contact has no channels or the room has no source type, there's nothing else we can do, so drop the contactId
if (!contact.channels?.length || !room.source?.type) {
return undefined;
}

const channel = contact.channels?.find(({ visitor }) => {
if (visitor.source.type !== room.source.type) {
return false;
}

if (visitor.source.id && room.source.id !== visitor.source.id) {
return false;
}

return true;
});

if (!channel) {
return undefined;
}

return this.convertVisitorToRoomV(room, channel.visitorId, contact._id);
}

async convertAppRoom(room) {
if (!room) {
return undefined;
Expand All @@ -35,21 +105,7 @@ export class AppRoomsConverter {
};
}

let v;
if (room.visitor) {
const visitor = await LivechatVisitors.findOneEnabledById(room.visitor.id);

const { lastMessageTs, phone } = room.visitorChannelInfo;

v = {
_id: visitor._id,
username: visitor.username,
token: visitor.token,
status: visitor.status || 'online',
...(lastMessageTs && { lastMessageTs }),
...(phone && { phone }),
};
}
const v = await this.convertAppVisitorData(room);

let departmentId;
if (room.department) {
Expand Down Expand Up @@ -180,6 +236,15 @@ export class AppRoomsConverter {

return this.orch.getConverters().get('visitors').convertById(v._id);
},
contact: (room) => {
const { v } = room;

if (!v?.contactId) {
return undefined;
}

return this.orch.getConverters().get('contacts').convertById(v.contactId);
},
// Note: room.v is not just visitor, it also contains channel related visitor data
// so we need to pass this data to the converter
// So suppose you have a contact whom we're contacting using SMS via 2 phone no's,
Expand Down
25 changes: 20 additions & 5 deletions apps/meteor/app/livechat/server/lib/contacts/getContacts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ILivechatContact } from '@rocket.chat/core-typings';
import { LivechatContacts } from '@rocket.chat/models';
import type { PaginatedResult } from '@rocket.chat/rest-typings';
import type { IUser } from '@rocket.chat/core-typings';
import { LivechatContacts, Users } from '@rocket.chat/models';
import type { PaginatedResult, ILivechatContactWithManagerData } from '@rocket.chat/rest-typings';
import type { Sort } from 'mongodb';

export type GetContactsParams = {
Expand All @@ -11,7 +11,7 @@ export type GetContactsParams = {
unknown?: boolean;
};

export async function getContacts(params: GetContactsParams): Promise<PaginatedResult<{ contacts: ILivechatContact[] }>> {
export async function getContacts(params: GetContactsParams): Promise<PaginatedResult<{ contacts: ILivechatContactWithManagerData[] }>> {
const { searchText, count, offset, sort, unknown } = params;

const { cursor, totalCount } = LivechatContacts.findPaginatedContacts(
Expand All @@ -23,7 +23,22 @@ export async function getContacts(params: GetContactsParams): Promise<PaginatedR
},
);

const [contacts, total] = await Promise.all([cursor.toArray(), totalCount]);
const [rawContacts, total] = await Promise.all([cursor.toArray(), totalCount]);

const managerIds = [...new Set(rawContacts.map(({ contactManager }) => contactManager))];
const managersData = await Users.findByIds<Pick<IUser, '_id' | 'name' | 'username'>>(managerIds, {
projection: { name: 1, username: 1 },
}).toArray();
const mappedManagers = Object.fromEntries(managersData.map((manager) => [manager._id, manager]));

const contacts: ILivechatContactWithManagerData[] = rawContacts.map((contact) => {
const { contactManager, ...data } = contact;

return {
...data,
...(contactManager ? { contactManager: mappedManagers[contactManager] } : {}),
};
});

return {
contacts,
Expand Down
2 changes: 2 additions & 0 deletions packages/apps-engine/src/definition/livechat/ILivechatRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { RoomType } from '../rooms';
import type { IRoom } from '../rooms/IRoom';
import type { IUser } from '../users';
import type { IDepartment } from './IDepartment';
import type { ILivechatContact } from './ILivechatContact';
import type { IVisitor } from './IVisitor';

export enum OmnichannelSourceType {
Expand Down Expand Up @@ -68,6 +69,7 @@ export interface ILivechatRoom extends IRoom {
isOpen: boolean;
closedAt?: Date;
source?: OmnichannelSource;
contact?: ILivechatContact;
}

export const isLivechatRoom = (room: IRoom): room is ILivechatRoom => {
Expand Down
7 changes: 6 additions & 1 deletion packages/rest-typings/src/v1/omnichannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import type {
ILivechatContact,
ILivechatContactVisitorAssociation,
ILivechatContactChannel,
IUser,
} from '@rocket.chat/core-typings';
import { ILivechatAgentStatus } from '@rocket.chat/core-typings';
import type { WithId } from 'mongodb';
Expand Down Expand Up @@ -3571,6 +3572,10 @@ const LivechatTriggerWebhookCallParamsSchema = {

export const isLivechatTriggerWebhookCallParams = ajv.compile<LivechatTriggerWebhookCallParams>(LivechatTriggerWebhookCallParamsSchema);

export type ILivechatContactWithManagerData = Omit<ILivechatContact, 'contactManager'> & {
contactManager?: Pick<IUser, '_id' | 'name' | 'username'>;
};

export type OmnichannelEndpoints = {
'/v1/livechat/appearance': {
GET: () => {
Expand Down Expand Up @@ -3860,7 +3865,7 @@ export type OmnichannelEndpoints = {
GET: (params: GETOmnichannelContactsProps) => { contact: ILivechatContact | null };
};
'/v1/omnichannel/contacts.search': {
GET: (params: GETOmnichannelContactsSearchProps) => PaginatedResult<{ contacts: ILivechatContact[] }>;
GET: (params: GETOmnichannelContactsSearchProps) => PaginatedResult<{ contacts: ILivechatContactWithManagerData[] }>;
};
'/v1/omnichannel/contacts.history': {
GET: (params: GETOmnichannelContactHistoryProps) => PaginatedResult<{ history: ContactSearchChatsResult[] }>;
Expand Down

0 comments on commit 3591e0b

Please sign in to comment.