RocketChat/Rocket.Chat

View on GitHub
apps/meteor/ee/app/livechat-enterprise/server/methods/resumeOnHold.ts

Summary

Maintainability
A
3 hrs
Test Coverage
import { Message } from '@rocket.chat/core-services';
import type { ILivechatVisitor, IOmnichannelSystemMessage } from '@rocket.chat/core-typings';
import { isOmnichannelRoom } from '@rocket.chat/core-typings';
import type { ServerMethods } from '@rocket.chat/ddp-client';
import { LivechatVisitors, LivechatInquiry, LivechatRooms, Users } from '@rocket.chat/models';
import { Meteor } from 'meteor/meteor';

import { methodDeprecationLogger } from '../../../../../app/lib/server/lib/deprecationWarningLogger';
import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager';
import { callbacks } from '../../../../../lib/callbacks';
import { i18n } from '../../../../../server/lib/i18n';

async function resolveOnHoldCommentInfo(options: { clientAction: boolean }, room: any, onHoldChatResumedBy: any): Promise<string> {
    if (options.clientAction) {
        return i18n.t('Omnichannel_on_hold_chat_resumed_manually', {
            user: onHoldChatResumedBy.name || onHoldChatResumedBy.username,
        });
    }
    const {
        v: { _id: visitorId },
    } = room;
    const visitor = await LivechatVisitors.findOneEnabledById<Pick<ILivechatVisitor, 'name' | 'username'>>(visitorId, {
        projection: { name: 1, username: 1 },
    });
    if (!visitor) {
        throw new Meteor.Error('error-invalid_visitor', 'Visitor Not found');
    }

    const guest = visitor.name || visitor.username;

    return i18n.t('Omnichannel_on_hold_chat_automatically', { guest });
}

declare module '@rocket.chat/ddp-client' {
    // eslint-disable-next-line @typescript-eslint/naming-convention
    interface ServerMethods {
        'livechat:resumeOnHold'(roomId: string, options?: { clientAction: boolean }): void;
    }
}

Meteor.methods<ServerMethods>({
    async 'livechat:resumeOnHold'(roomId, options = { clientAction: false }) {
        methodDeprecationLogger.warn(
            'Method "livechat:resumeOnHold" is deprecated and will be removed in next major version. Please use "livechat/room.resumeOnHold" API instead.',
        );

        const room = await LivechatRooms.findOneById(roomId);
        if (!room || !isOmnichannelRoom(room)) {
            throw new Meteor.Error('error-invalid-room', 'Invalid room', {
                method: 'livechat:resumeOnHold',
            });
        }

        if (!room.onHold) {
            throw new Meteor.Error('room-closed', 'Room is not OnHold', {
                method: 'livechat:resumeOnHold',
            });
        }

        const inquiry = await LivechatInquiry.findOneByRoomId(roomId, {});
        if (!inquiry) {
            throw new Meteor.Error('inquiry-not-found', 'Error! No inquiry found for this room', {
                method: 'livechat:resumeOnHold',
            });
        }

        if (!room.servedBy) {
            throw new Meteor.Error('error-unserved-rooms-cannot-be-placed-onhold', 'Error! Un-served rooms cannot be placed OnHold', {
                method: 'livechat:resumeOnHold',
            });
        }

        const {
            servedBy: { _id: agentId, username },
        } = room;
        await RoutingManager.takeInquiry(inquiry, { agentId, username }, options, room);

        const onHoldChatResumedBy = options.clientAction ? await Meteor.userAsync() : await Users.findOneById('rocket.cat');
        if (!onHoldChatResumedBy) {
            throw new Meteor.Error('error-invalid-user', 'Invalid user', {
                method: 'livechat:resumeOnHold',
            });
        }

        const comment = await resolveOnHoldCommentInfo(options, room, onHoldChatResumedBy);

        await Message.saveSystemMessage<IOmnichannelSystemMessage>('omnichannel_on_hold_chat_resumed', roomId, '', onHoldChatResumedBy, {
            comment,
        });

        setImmediate(() => callbacks.run('livechat:afterOnHoldChatResumed', room));
    },
});