Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Move functions out of livechat.js #30664

Merged
merged 7 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/meteor/app/apps/server/bridges/livechat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class AppLivechatBridge extends LivechatBridge {
throw new Error('Invalid token for livechat message');
}

const msg = await Livechat.sendMessage({
const msg = await LivechatTyped.sendMessage({
guest: this.orch.getConverters()?.get('visitors').convertAppVisitor(message.visitor),
message: await this.orch.getConverters()?.get('messages').convertAppMessage(message),
agent: undefined,
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/livechat/imports/server/rest/sms.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ API.v1.addRoute('livechat/sms-incoming/:service', {
};

try {
const msg = SMSService.response.call(this, await Livechat.sendMessage(sendMessage));
const msg = SMSService.response.call(this, await LivechatTyped.sendMessage(sendMessage));
setImmediate(async () => {
if (sms.extra) {
if (sms.extra.fromCountry) {
Expand Down
16 changes: 10 additions & 6 deletions apps/meteor/app/livechat/server/api/v1/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { isWidget } from '../../../../api/server/helpers/isWidget';
import { loadMessageHistory } from '../../../../lib/server/functions/loadMessageHistory';
import { settings } from '../../../../settings/server';
import { normalizeMessageFileUpload } from '../../../../utils/server/functions/normalizeMessageFileUpload';
import { Livechat } from '../../lib/Livechat';
import { Livechat as LivechatTyped } from '../../lib/LivechatTyped';
import { findGuest, findRoom, normalizeHttpHeaderData } from '../lib/livechat';

Expand Down Expand Up @@ -67,7 +66,7 @@ API.v1.addRoute(
},
};

const result = await Livechat.sendMessage(sendMessage);
const result = await LivechatTyped.sendMessage(sendMessage);
if (result) {
const message = await Messages.findOneById(_id);
if (!message) {
Expand Down Expand Up @@ -176,7 +175,7 @@ API.v1.addRoute(
throw new Error('invalid-message');
}

const result = await Livechat.deleteMessage({ guest, message });
const result = await LivechatTyped.deleteMessage({ guest, message });
if (result) {
return API.v1.success({
message: {
Expand Down Expand Up @@ -272,10 +271,15 @@ API.v1.addRoute(
visitor = await LivechatVisitors.findOneEnabledById(visitorId);
}

const guest = visitor;
if (!guest) {
throw new Error('error-invalid-token');
}

const sentMessages = await Promise.all(
this.bodyParams.messages.map(async (message: { msg: string }): Promise<{ username: string; msg: string; ts: number }> => {
const sendMessage = {
guest: visitor,
guest,
message: {
_id: Random.id(),
rid,
Expand All @@ -288,8 +292,8 @@ API.v1.addRoute(
},
},
};
// @ts-expect-error -- Typings on sendMessage are wrong
const sentMessage = await Livechat.sendMessage(sendMessage);

const sentMessage = await LivechatTyped.sendMessage(sendMessage);
return {
username: sentMessage.u.username,
msg: sentMessage.msg,
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/livechat/server/api/v1/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ API.v1.addRoute('livechat/visitor/:token', {
}

const { _id } = visitor;
const result = await Livechat.removeGuest(_id);
const result = await LivechatTyped.removeGuest(_id);
if (!result.modifiedCount) {
throw new Meteor.Error('error-removing-visitor', 'An error ocurred while deleting visitor');
}
Expand Down
6 changes: 3 additions & 3 deletions apps/meteor/app/livechat/server/lib/Helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ export const forwardRoomToAgent = async (room: IOmnichannelRoom, transferData: T
return false;
}

await Livechat.saveTransferHistory(room, transferData);
await LivechatTyped.saveTransferHistory(room, transferData);

const { servedBy } = roomTaken;
if (servedBy) {
Expand Down Expand Up @@ -537,7 +537,7 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi
logger.debug(
`Routing algorithm doesn't support auto assignment (using ${RoutingManager.methodName}). Chat will be on department queue`,
);
await Livechat.saveTransferHistory(room, transferData);
await LivechatTyped.saveTransferHistory(room, transferData);
return RoutingManager.unassignAgent(inquiry, departmentId);
}

Expand Down Expand Up @@ -573,7 +573,7 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi
}
}

await Livechat.saveTransferHistory(room, transferData);
await LivechatTyped.saveTransferHistory(room, transferData);
if (oldServedBy) {
// if chat is queued then we don't ignore the new servedBy agent bcs at this
// point the chat is not assigned to him/her and it is still in the queue
Expand Down
191 changes: 1 addition & 190 deletions apps/meteor/app/livechat/server/lib/Livechat.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ import {
LivechatRooms,
LivechatInquiry,
Subscriptions,
Messages,
LivechatDepartment as LivechatDepartmentRaw,
Rooms,
Users,
ReadReceipts,
} from '@rocket.chat/models';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
Expand All @@ -25,15 +23,11 @@ import { i18n } from '../../../../server/lib/i18n';
import { addUserRolesAsync } from '../../../../server/lib/roles/addUserRoles';
import { removeUserFromRolesAsync } from '../../../../server/lib/roles/removeUserFromRoles';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { FileUpload } from '../../../file-upload/server';
import { deleteMessage } from '../../../lib/server/functions/deleteMessage';
import { sendMessage } from '../../../lib/server/functions/sendMessage';
import * as Mailer from '../../../mailer/server/api';
import { settings } from '../../../settings/server';
import { businessHourManager } from '../business-hour';
import { Analytics } from './Analytics';
import { normalizeTransferredByData, parseAgentCustomFields, updateDepartmentAgents } from './Helper';
import { Livechat as LivechatTyped } from './LivechatTyped';
import { parseAgentCustomFields, updateDepartmentAgents } from './Helper';
import { RoutingManager } from './RoutingManager';

const logger = new Logger('Livechat');
Expand All @@ -43,41 +37,6 @@ export const Livechat = {

logger,

async sendMessage({ guest, message, roomInfo, agent }) {
const { room, newRoom } = await LivechatTyped.getRoom(guest, message, roomInfo, agent);
if (guest.name) {
message.alias = guest.name;
}
return Object.assign(await sendMessage(guest, message, room), {
newRoom,
showConnecting: this.showConnecting(),
});
},

async deleteMessage({ guest, message }) {
Livechat.logger.debug(`Attempting to delete a message by visitor ${guest._id}`);
check(message, Match.ObjectIncluding({ _id: String }));

const msg = await Messages.findOneById(message._id);
if (!msg || !msg._id) {
return;
}

const deleteAllowed = settings.get('Message_AllowDeleting');
const editOwn = msg.u && msg.u._id === guest._id;

if (!deleteAllowed || !editOwn) {
Livechat.logger.debug('Cannot delete message: not allowed');
throw new Meteor.Error('error-action-not-allowed', 'Message deleting not allowed', {
method: 'livechatDeleteMessage',
});
}

await deleteMessage(message, guest);

return true;
},

async saveGuest(guestData, userId) {
const { _id, name, email, phone, livechatData = {} } = guestData;
Livechat.logger.debug(`Saving data for visitor ${_id}`);
Expand Down Expand Up @@ -234,111 +193,6 @@ export const Livechat = {
return Message.saveSystemMessage('livechat_navigation_history', roomId, `${pageTitle} - ${pageUrl}`, user, extraData);
},

async saveTransferHistory(room, transferData) {
Livechat.logger.debug(`Saving transfer history for room ${room._id}`);
const { departmentId: previousDepartment } = room;
const { department: nextDepartment, transferredBy, transferredTo, scope, comment } = transferData;

check(
transferredBy,
Match.ObjectIncluding({
_id: String,
username: String,
name: Match.Maybe(String),
type: String,
}),
);

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

const transfer = {
transferData: {
transferredBy,
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,
},
groupable: false,
};

Object.assign(transferMessage, transfer);

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

async returnRoomAsInquiry(rid, departmentId, overrideTransferData = {}) {
Livechat.logger.debug(`Transfering room ${rid} to ${departmentId ? 'department' : ''} queue`);
const room = await LivechatRooms.findOneById(rid);
if (!room) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', {
method: 'livechat:returnRoomAsInquiry',
});
}

if (!room.open) {
throw new Meteor.Error('room-closed', 'Room closed', {
method: 'livechat:returnRoomAsInquiry',
});
}

if (room.onHold) {
throw new Meteor.Error('error-room-onHold', 'Room On Hold', {
method: 'livechat:returnRoomAsInquiry',
});
}

if (!room.servedBy) {
return false;
}

const user = await Users.findOneById(room.servedBy._id);
if (!user || !user._id) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'livechat:returnRoomAsInquiry',
});
}

// find inquiry corresponding to room
const inquiry = await LivechatInquiry.findOne({ rid });
if (!inquiry) {
return false;
}

const transferredBy = normalizeTransferredByData(user, room);
Livechat.logger.debug(`Transfering room ${room._id} by user ${transferredBy._id}`);
const transferData = { roomId: rid, scope: 'queue', departmentId, transferredBy, ...overrideTransferData };
try {
await this.saveTransferHistory(room, transferData);
await RoutingManager.unassignAgent(inquiry, departmentId);
} catch (e) {
this.logger.error(e);
throw new Meteor.Error('error-returning-inquiry', 'Error returning inquiry to the queue', {
method: 'livechat:returnRoomAsInquiry',
});
}

callbacks.runAsync('livechat:afterReturnRoomAsInquiry', { room });

return true;
},

async getLivechatRoomGuestInfo(room) {
const visitor = await LivechatVisitors.findOneEnabledById(room.v._id);
const agent = await Users.findOneById(room.servedBy && room.servedBy._id);
Expand Down Expand Up @@ -481,55 +335,12 @@ export const Livechat = {
return removeUserFromRolesAsync(user._id, ['livechat-manager']);
},

async removeGuest(_id) {
const guest = await LivechatVisitors.findOneEnabledById(_id, { projection: { _id: 1, token: 1 } });
if (!guest) {
throw new Meteor.Error('error-invalid-guest', 'Invalid guest', {
method: 'livechat:removeGuest',
});
}

await this.cleanGuestHistory(guest);
return LivechatVisitors.disableById(_id);
},

async setUserStatusLivechat(userId, status) {
const user = await Users.setLivechatStatus(userId, status);
callbacks.runAsync('livechat.setUserStatusLivechat', { userId, status });
return user;
},

async setUserStatusLivechatIf(userId, status, condition, fields) {
const user = await Users.setLivechatStatusIf(userId, status, condition, fields);
callbacks.runAsync('livechat.setUserStatusLivechat', { userId, status });
return user;
},

async cleanGuestHistory(guest) {
const { token } = guest;

// This shouldn't be possible, but just in case
if (!token) {
throw new Error('error-invalid-guest');
}

const extraQuery = await callbacks.run('livechat.applyRoomRestrictions', {});
const cursor = LivechatRooms.findByVisitorToken(token, extraQuery);
for await (const room of cursor) {
await Promise.all([
FileUpload.removeFilesByRoomId(room._id),
Messages.removeByRoomId(room._id),
ReadReceipts.removeByRoomId(room._id),
]);
}

await Promise.all([
Subscriptions.removeByVisitorToken(token),
LivechatRooms.removeByVisitorToken(token),
LivechatInquiry.removeByVisitorToken(token),
]);
},

async saveDepartmentAgents(_id, departmentAgents) {
check(_id, String);
check(departmentAgents, {
Expand Down
Loading
Loading