The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Rocket.Chat/ee/app/livechat-enterprise/server/lib/LivechatEnterprise.js

248 lines
6.2 KiB

import { Meteor } from 'meteor/meteor';
import { Match, check } from 'meteor/check';
import { Users } from '../../../../../app/models';
import { LivechatInquiry, OmnichannelQueue } from '../../../../../app/models/server/raw';
import LivechatUnit from '../../../models/server/models/LivechatUnit';
import LivechatTag from '../../../models/server/models/LivechatTag';
import { LivechatRooms, Subscriptions } from '../../../../../app/models/server';
import LivechatPriority from '../../../models/server/models/LivechatPriority';
import { addUserRoles, removeUserFromRoles } from '../../../../../app/authorization/server';
import { processWaitingQueue, removePriorityFromRooms, updateInquiryQueuePriority, updatePriorityInquiries, updateRoomPriorityHistory } from './Helper';
import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager';
import { settings } from '../../../../../app/settings/server';
import { callbacks } from '../../../../../app/callbacks';
import { AutoCloseOnHoldScheduler } from './AutoCloseOnHoldScheduler';
export const LivechatEnterprise = {
addMonitor(username) {
check(username, String);
const user = Users.findOneByUsername(username, { fields: { _id: 1, username: 1 } });
if (!user) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'livechat:addMonitor' });
}
if (addUserRoles(user._id, 'livechat-monitor')) {
return user;
}
return false;
},
removeMonitor(username) {
check(username, String);
const user = Users.findOneByUsername(username, { fields: { _id: 1 } });
if (!user) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'livechat:removeMonitor' });
}
if (removeUserFromRoles(user._id, 'livechat-monitor')) {
return true;
}
return false;
},
removeUnit(_id) {
check(_id, String);
const unit = LivechatUnit.findOneById(_id, { fields: { _id: 1 } });
if (!unit) {
throw new Meteor.Error('unit-not-found', 'Unit not found', { method: 'livechat:removeUnit' });
}
return LivechatUnit.removeById(_id);
},
saveUnit(_id, unitData, unitMonitors, unitDepartments) {
check(_id, Match.Maybe(String));
check(unitData, {
name: String,
visibility: String,
enabled: Match.Optional(Boolean),
description: Match.Optional(String),
email: Match.Optional(String),
showOnOfflineForm: Match.Optional(Boolean),
});
check(unitMonitors, [
Match.ObjectIncluding({
monitorId: String,
username: String,
}),
]);
check(unitDepartments, [
Match.ObjectIncluding({
departmentId: String,
}),
]);
let ancestors = [];
if (_id) {
const unit = LivechatUnit.findOneById(_id);
if (!unit) {
throw new Meteor.Error('error-unit-not-found', 'Unit not found', { method: 'livechat:saveUnit' });
}
ancestors = unit.ancestors;
}
return LivechatUnit.createOrUpdateUnit(_id, unitData, ancestors, unitMonitors, unitDepartments);
},
removeTag(_id) {
check(_id, String);
const tag = LivechatTag.findOneById(_id, { fields: { _id: 1 } });
if (!tag) {
throw new Meteor.Error('tag-not-found', 'Tag not found', { method: 'livechat:removeTag' });
}
return LivechatTag.removeById(_id);
},
saveTag(_id, tagData, tagDepartments) {
check(_id, Match.Maybe(String));
check(tagData, {
name: String,
description: Match.Optional(String),
});
check(tagDepartments, [String]);
return LivechatTag.createOrUpdateTag(_id, tagData, tagDepartments);
},
savePriority(_id, priorityData) {
check(_id, Match.Maybe(String));
check(priorityData, {
name: String,
description: Match.Optional(String),
dueTimeInMinutes: String,
});
const oldPriority = _id && LivechatPriority.findOneById(_id, { fields: { dueTimeInMinutes: 1 } });
const priority = LivechatPriority.createOrUpdatePriority(_id, priorityData);
if (!oldPriority) {
return priority;
}
const { dueTimeInMinutes: oldDueTimeInMinutes } = oldPriority;
const { dueTimeInMinutes } = priority;
if (oldDueTimeInMinutes !== dueTimeInMinutes) {
updatePriorityInquiries(priority);
}
return priority;
},
removePriority(_id) {
check(_id, String);
const priority = LivechatPriority.findOneById(_id, { fields: { _id: 1 } });
if (!priority) {
throw new Meteor.Error('error-invalid-priority', 'Invalid priority', { method: 'livechat:removePriority' });
}
const removed = LivechatPriority.removeById(_id);
if (removed) {
removePriorityFromRooms(_id);
}
return removed;
},
updateRoomPriority(roomId, user, priority) {
updateInquiryQueuePriority(roomId, priority);
updateRoomPriorityHistory(roomId, user, priority);
},
placeRoomOnHold(room) {
const { _id: roomId, onHold } = room;
if (!roomId || onHold) {
return false;
}
LivechatRooms.setOnHold(roomId);
Subscriptions.setOnHold(roomId);
Meteor.defer(() => {
callbacks.run('livechat:afterOnHold', room);
});
return true;
},
async releaseOnHoldChat(room) {
const { _id: roomId, onHold } = room;
if (!roomId || !onHold) {
return;
}
await AutoCloseOnHoldScheduler.unscheduleRoom(roomId);
LivechatRooms.unsetAllOnHoldFieldsByRoomId(roomId);
Subscriptions.unsetOnHold(roomId);
},
};
const RACE_TIMEOUT = 1000;
const queueWorker = {
running: false,
queues: [],
async start() {
if (this.running) {
return;
}
await this.getActiveQueues();
await OmnichannelQueue.initQueue();
this.running = true;
return this.execute();
},
async stop() {
this.running = false;
return OmnichannelQueue.stopQueue();
},
async getActiveQueues() {
// undefined = public queue(without department)
return [undefined].concat(await LivechatInquiry.getDistinctQueuedDepartments());
},
async nextQueue() {
if (!this.queues.length) {
this.queues = await this.getActiveQueues();
}
return this.queues.shift();
},
async execute() {
if (!this.running) {
return;
}
const queue = await this.nextQueue();
setTimeout(this.checkQueue.bind(this, queue), RACE_TIMEOUT);
},
async checkQueue(queue) {
if (await OmnichannelQueue.lockQueue()) {
await processWaitingQueue(queue);
await OmnichannelQueue.unlockQueue();
}
this.execute();
},
};
settings.onload('Livechat_Routing_Method', function() {
RoutingManager.getConfig().autoAssignAgent ? queueWorker.start() : queueWorker.stop();
});