import { api } from '@rocket.chat/core-services'; import type { UserStatus, IUser } from '@rocket.chat/core-typings'; import { LivechatDepartment, LivechatDepartmentAgents, LivechatRooms, Users } from '@rocket.chat/models'; import { removeEmpty } from '@rocket.chat/tools'; import { updateDepartmentAgents } from './Helper'; import { afterAgentAdded, afterRemoveAgent } from './hooks'; import { settings } from '../../settings'; import { callbacks } from '../callbacks'; import { addUserRolesAsync } from '../roles/addUserRoles'; import { removeUserFromRolesAsync } from '../roles/removeUserFromRoles'; export async function notifyAgentStatusChanged(userId: string, status?: UserStatus) { if (!status) { return; } void callbacks.runAsync('livechat.agentStatusChanged', { userId, status }); if (!settings.get('Livechat_show_agent_info')) { return; } for await (const room of LivechatRooms.findOpenByAgent(userId, { projection: { _id: 1 } })) { void api.broadcast('omnichannel.room', room._id, { type: 'agentStatus', status, }); } } export async function addManager(username: string) { const user = await Users.findOneByUsername(username, { projection: { _id: 1, username: 1 } }); if (!user) { throw new Error('error-invalid-user'); } if (await addUserRolesAsync(user._id, ['livechat-manager'])) { return user; } return false; } export async function addAgent(username: string) { // `status` is deliberately not projected: this endpoint has always turned the new agent available // regardless of the user's presence, and `afterAgentAdded` relies on the field being absent to do so. const user = await Users.findOneByUsername(username, { projection: { _id: 1, username: 1 } }); if (!user) { throw new Error('error-invalid-user'); } if (await addUserRolesAsync(user._id, ['livechat-agent'])) { return afterAgentAdded(user); } return false; } export async function removeAgent(id: IUser['_id']) { const user = await Users.findOneById>(id, { projection: { _id: 1, username: 1 } }); if (!user) { throw new Error('error-invalid-user'); } const { _id } = user; if (await removeUserFromRolesAsync(_id, ['livechat-agent'])) { return afterRemoveAgent(user); } return false; } export async function removeManager(id: IUser['_id']) { const user = await Users.findOneById>(id, { projection: { _id: 1 } }); if (!user) { throw new Error('error-invalid-user'); } return removeUserFromRolesAsync(user._id, ['livechat-manager']); } export async function saveAgentInfo(_id: string, agentData: any, agentDepartments: string[]) { await Users.setLivechatData(_id, removeEmpty(agentData)); const currentDepartmentsForAgent = await LivechatDepartmentAgents.findByAgentId(_id).toArray(); const toRemoveIds = currentDepartmentsForAgent .filter((dept) => !agentDepartments.includes(dept.departmentId)) .map((dept) => dept.departmentId); const toAddIds = agentDepartments.filter((d) => !currentDepartmentsForAgent.some((c) => c.departmentId === d)); await Promise.all( await LivechatDepartment.findInIds([...toRemoveIds, ...toAddIds], { projection: { _id: 1, enabled: 1, }, }) .map((dep) => { return updateDepartmentAgents( dep._id, { ...(toRemoveIds.includes(dep._id) ? { remove: [{ agentId: _id }] } : { upsert: [{ agentId: _id, count: 0, order: 0 }] }), }, dep.enabled, ); }) .toArray(), ); return true; }