import { ChatMessageAttachment, QBChatMessage } from 'quickblox/quickblox'; import { IDTOMapper } from './IDTOMapper'; import { RemoteMessageDTO } from '../../../dto/message/RemoteMessageDTO'; import { INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, MapperDTOException, } from '../../exception/MapperDTOException'; import ChatMessageAttachmentEntity from '../../../../Domain/entity/ChatMessageAttachmentEntity'; import { getQB } from '../../../../qb-api-calls'; type DtoValidator = { [key in keyof T]: (v: unknown) => v is T[key]; }; export class MessageDTOMapper implements IDTOMapper { private static normalizeUidToString( uid: string | number | undefined, ): string | undefined { if (uid === undefined || uid === null) { return undefined; } return String(uid); } // eslint-disable-next-line class-methods-use-this fromDTO(dto: TArg): Promise { const messageDTO: RemoteMessageDTO = dto as RemoteMessageDTO; MessageDTOMapper.validateDTO(messageDTO); // eslint-disable-next-line @typescript-eslint/no-shadow const message: QBChatMessage = { _id: '', attachments: [], chat_dialog_id: '', created_at: '', date_sent: 0, delivered_ids: [], message: '', read: 0, read_ids: [], recipient_id: 0, sender_id: 0, updated_at: '', }; return Promise.resolve(message as TResult); } // eslint-disable-next-line class-methods-use-this public static transformAttachment( qbMessage: string, qbAtts: ChatMessageAttachment[], ) { const result: ChatMessageAttachmentEntity[] = qbAtts.map((item) => { const QB = getQB(); const normalizedUid = MessageDTOMapper.normalizeUidToString(item.uid); const normalizedUrl = normalizedUid ? QB.content.privateUrl(normalizedUid) : undefined; const newItem: ChatMessageAttachmentEntity = { id: item.id, name: item.name, size: item.size, type: item.type, uid: normalizedUid, url: normalizedUrl, file: { id: item.id, name: item.name, size: item.size, type: item.type, uid: normalizedUid || '', url: normalizedUrl, }, }; const messageParts = MessageDTOMapper.getMessageParts(qbMessage); if (messageParts && messageParts.length > 3) { // val messageBody = "${MediaContentEntity::class.java.simpleName}|$fileName|$uid|$fileMimeType" // 0, 1, 2, 3 // eslint-disable-next-line prefer-destructuring newItem.uid = messageParts[2]; // eslint-disable-next-line prefer-destructuring newItem.name = messageParts[1]; // eslint-disable-next-line prefer-destructuring newItem.type = messageParts[3]; const parsedUid = MessageDTOMapper.normalizeUidToString(newItem.uid); newItem.uid = parsedUid; newItem.url = parsedUid ? QB.content.privateUrl(parsedUid) : undefined; if (newItem.file) { newItem.file.uid = parsedUid || ''; newItem.file.name = newItem.name; newItem.file.url = parsedUid ? QB.content.privateUrl(parsedUid) : undefined; newItem.file.type = newItem.type; } } return newItem; }); return result; } // eslint-disable-next-line class-methods-use-this toTDO(entity: TArg): Promise { const qbMessage: QBChatMessage = entity as unknown as QBChatMessage; const dto = this.QBChatMessageToRemoteMessageDTO(qbMessage); // let operationResult = true; dto.qb_original_messages = MessageDTOMapper.translateJSONToOriginalData( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument qbMessage.qb_original_messages, )?.map((item) => { let result: RemoteMessageDTO; try { result = this.QBChatMessageToRemoteMessageDTO(item, true); } catch (e) { operationResult = false; console.log(e); } // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore return result; }); dto.qb_message_action = qbMessage.qb_message_action; dto.origin_sender_name = qbMessage.origin_sender_name; if (!operationResult) { dto.qb_original_messages = undefined; dto.qb_message_action = undefined; dto.origin_sender_name = undefined; } return Promise.resolve(dto as TResult); } // eslint-disable-next-line class-methods-use-this private QBChatMessageToRemoteMessageDTO( qbMessage: QBChatMessage, offValidate = false, ): RemoteMessageDTO { const dto: RemoteMessageDTO = new RemoteMessageDTO(); if (!offValidate) { // original version try { MessageDTOMapper.validateQBMessage(qbMessage); } catch (e) { console.log( `Error validating QBChatMessage: (${JSON.stringify(qbMessage)})`, ); console.error(e); } dto.id = qbMessage._id; dto.dialogId = qbMessage.chat_dialog_id; dto.message = qbMessage.message; // MessageDTOMapper.formatMessage(qbMessage.message); dto.created_at = qbMessage.created_at; dto.date_sent = qbMessage.date_sent * 1000; dto.delivered_ids = qbMessage.delivered_ids || []; dto.read_ids = qbMessage.read_ids || []; dto.recipient_id = qbMessage.recipient_id || 0; dto.attachments = MessageDTOMapper.transformAttachment( qbMessage.message || '', qbMessage.attachments || [], ); dto.read = qbMessage.read; dto.sender_id = qbMessage.sender_id; dto.updated_at = qbMessage.updated_at; dto.notification_type = qbMessage.notification_type || ''; dto.markable = qbMessage.notification_type || ''; } else { dto.id = qbMessage._id; dto.dialogId = qbMessage.chat_dialog_id; dto.message = qbMessage.message; dto.created_at = qbMessage.created_at || Date.now().toString(); dto.date_sent = qbMessage.date_sent || Date.now() * 1000; dto.delivered_ids = qbMessage.delivered_ids || []; dto.read_ids = qbMessage.read_ids || []; dto.recipient_id = qbMessage.recipient_id || 0; dto.attachments = MessageDTOMapper.transformAttachment( qbMessage.message || '', qbMessage.attachments || [], ); dto.read = qbMessage.read || 1; dto.sender_id = qbMessage.sender_id; dto.updated_at = qbMessage.updated_at || Date.now().toString(); dto.notification_type = qbMessage.notification_type || ''; dto.markable = qbMessage.notification_type || ''; } return dto; } // // public static convertAttachment( // attachment: ChatMessageAttachmentEntity, // ): ChatMessageAttachment { // return { // id: attachment.id.toString(), // uid: attachment.uid || '', // type: attachment.type.toString(), // url: attachment.url || '', // name: attachment.name || '', // size: attachment.size || 0, // }; // } public static convertAttachment( attachment: ChatMessageAttachmentEntity, ): ChatMessageAttachment { return { id: attachment.id.toString(), uid: attachment.uid?.toString() || '', type: attachment.type.toString(), url: attachment.url?.toString() || '', name: attachment.name?.toString() || '', size: attachment.size?.toString() || '', } as ChatMessageAttachment; } public static convertToQBChatNewMessage( messages: RemoteMessageDTO[], ): QBChatMessage[] { return messages.map((message) => { const qbMessage: QBChatMessage = { _id: message.id, attachments: message.attachments?.map((attachment) => MessageDTOMapper.convertAttachment(attachment), ) || [], chat_dialog_id: message.dialogId, created_at: message.created_at, date_sent: message.date_sent, delivered_ids: message.delivered_ids, message: message.message, read_ids: message.read_ids, read: message.read, recipient_id: message.recipient_id, sender_id: message.sender_id, updated_at: message.updated_at, notification_type: message.notification_type, qb_message_action: message.qb_message_action, origin_sender_name: message.origin_sender_name, qb_original_messages: message.qb_original_messages ? MessageDTOMapper.translateOriginalDataToJSON( MessageDTOMapper.convertToQBChatNewMessage( message.qb_original_messages || [], ) || [], ) : undefined, }; return qbMessage; }); } // // public static translateOriginalDataToJSON( qb_original_message?: QBChatMessage[], ) { if (qb_original_message && qb_original_message.length > 0) { return JSON.stringify(qb_original_message); } return ''; } public static translateJSONToOriginalData( json_data?: string, ): QBChatMessage[] | undefined { if (json_data) { try { const originalData = JSON.parse(json_data); if ( Array.isArray(originalData) && originalData.every((item) => item instanceof Object) ) { return originalData as QBChatMessage[]; } } catch (error) { console.error('Error parsing JSON:', error); } } return undefined; } // public static FORWARD_MESSAGE_PREFIX = '[Forwarded_Message]'; public static REPLY_MESSAGE_PREFIX = '[Replied_Message]'; public static ATTACHMENT_PREFIX = '[Attachment]'; public static MEDIA_CONTENT_ENTITY_PREFIX = 'MediaContentEntity'; private static isForwardedOrRepliedMessage(qbMessage: string) { return ( qbMessage.includes(MessageDTOMapper.FORWARD_MESSAGE_PREFIX) || qbMessage.includes(MessageDTOMapper.REPLY_MESSAGE_PREFIX) ); } private static isMediaOrAttachmentMessage(message: string) { return ( message.includes(MessageDTOMapper.MEDIA_CONTENT_ENTITY_PREFIX) || message.includes(MessageDTOMapper.ATTACHMENT_PREFIX) ); } public static formatMessage(qbMessage: string) { if (MessageDTOMapper.isMediaOrAttachmentMessage(qbMessage)) { return this.splitMessageParts(qbMessage)[1] || ''; } if (MessageDTOMapper.isForwardedOrRepliedMessage(qbMessage)) { return ''; } return qbMessage; } public static getMessageParts(qbMessage: string) { if (MessageDTOMapper.isMediaOrAttachmentMessage(qbMessage)) { return MessageDTOMapper.splitMessageParts(qbMessage); } return []; } private static splitMessageParts(message: string) { // val messageBody = "${MediaContentEntity::class.java.simpleName}|$fileName|$uid|$fileMimeType" // 0, 1, 2, 3 return message.split('|'); } private static validateDTO(messageDTO: RemoteMessageDTO) { const messageDTOValidator: DtoValidator = { created_at(v: unknown): v is RemoteMessageDTO['created_at'] { const { created_at } = v as RemoteMessageDTO; return ( created_at !== undefined && created_at !== null && created_at.length > 0 ); }, date_sent(v: unknown): v is RemoteMessageDTO['date_sent'] { const { date_sent } = v as RemoteMessageDTO; return date_sent !== undefined && date_sent !== null; }, delivered_ids(v: unknown): v is RemoteMessageDTO['delivered_ids'] { const { delivered_ids } = v as RemoteMessageDTO; return ( delivered_ids !== undefined && delivered_ids !== null // && delivered_ids.length >= 0 ); }, dialogId(v: unknown): v is RemoteMessageDTO['dialogId'] { const { dialogId } = v as RemoteMessageDTO; return ( dialogId !== undefined && dialogId !== null && dialogId.length > 0 ); }, id(v: unknown): v is RemoteMessageDTO['id'] { const { id } = v as RemoteMessageDTO; return id !== undefined && id !== null; }, message(v: unknown): v is RemoteMessageDTO['message'] { const { message } = v as RemoteMessageDTO; return message !== undefined && message !== null && message.length > 0; }, read(v: unknown): v is RemoteMessageDTO['read'] { const { read } = v as RemoteMessageDTO; return read !== undefined && read !== null; }, read_ids(v: unknown): v is RemoteMessageDTO['read_ids'] { const { read_ids } = v as RemoteMessageDTO; return ( read_ids !== undefined && read_ids !== null // && read_ids.length >= 0 ); }, recipient_id(v: unknown): v is RemoteMessageDTO['recipient_id'] { const { recipient_id } = v as RemoteMessageDTO; return recipient_id !== undefined && recipient_id !== null; }, sender_id(v: unknown): v is RemoteMessageDTO['sender_id'] { const { sender_id } = v as RemoteMessageDTO; return sender_id !== undefined && sender_id !== null; }, updated_at(v: unknown): v is RemoteMessageDTO['updated_at'] { const { updated_at } = v as RemoteMessageDTO; return ( updated_at !== undefined && updated_at !== null && updated_at.length > 0 ); }, // attachments(v: unknown): v is RemoteMessageDTO['attachments'] { const { attachments } = v as RemoteMessageDTO; return attachments !== undefined && attachments !== null; }, }; if (!messageDTOValidator.created_at(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {created_at} does not exist or empty', ); if (!messageDTOValidator.date_sent(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {date_sent} does not exist or empty', ); if (!messageDTOValidator.delivered_ids(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {delivered_ids} does not exist or empty', ); if (!messageDTOValidator.dialogId(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {dialogId} does not exist or empty', ); if (!messageDTOValidator.id(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {id} does not exist or empty', ); if (!messageDTOValidator.message(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {message} does not exist or empty', ); if (!messageDTOValidator.read(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {read} does not exist or empty', ); if (!messageDTOValidator.read_ids(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {read_ids} does not exist or empty', ); if (!messageDTOValidator.recipient_id(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {recipient_id} does not exist or empty', ); if (!messageDTOValidator.sender_id(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {sender_id} does not exist or empty', ); if (!messageDTOValidator.updated_at(messageDTO)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {updated_at} does not exist or empty', ); } private static validateQBMessage(qbMessage: QBChatMessage) { const qbMessageValidator: DtoValidator = { delivered_ids(v: unknown): v is QBChatMessage['delivered_ids'] { const { delivered_ids } = v as QBChatMessage; return delivered_ids !== undefined && delivered_ids !== null; }, read_ids(v: unknown): v is QBChatMessage['read_ids'] { const { read_ids } = v as QBChatMessage; return read_ids !== undefined && read_ids !== null; }, _id(v: unknown): v is QBChatMessage['_id'] { const { _id } = v as QBChatMessage; return _id !== undefined && _id !== null && _id.length > 0; }, attachments(v: unknown): v is QBChatMessage['attachments'] { const { attachments } = v as QBChatMessage; return attachments !== undefined && attachments !== null; }, chat_dialog_id(v: unknown): v is QBChatMessage['chat_dialog_id'] { const { chat_dialog_id } = v as QBChatMessage; return ( chat_dialog_id !== undefined && chat_dialog_id !== null && chat_dialog_id.length > 0 ); }, created_at(v: unknown): v is QBChatMessage['created_at'] { const { created_at } = v as QBChatMessage; return ( created_at !== undefined && created_at !== null && created_at.length > 0 ); }, date_sent(v: unknown): v is QBChatMessage['date_sent'] { const { date_sent } = v as QBChatMessage; return date_sent !== undefined && date_sent !== null; }, message(v: unknown): v is QBChatMessage['message'] { const { message } = v as QBChatMessage; return message !== undefined && message !== null && message.length > 0; }, read(v: unknown): v is QBChatMessage['read'] { const { read } = v as QBChatMessage; return read !== undefined && read !== null; }, recipient_id(v: unknown): v is QBChatMessage['recipient_id'] { const { recipient_id } = v as QBChatMessage; return recipient_id !== undefined && recipient_id !== null; }, sender_id(v: unknown): v is QBChatMessage['sender_id'] { const { sender_id } = v as QBChatMessage; return sender_id !== undefined && sender_id !== null; }, updated_at(v: unknown): v is QBChatMessage['updated_at'] { const { updated_at } = v as QBChatMessage; return ( updated_at !== undefined && updated_at !== null && updated_at.length > 0 ); }, }; if (!qbMessageValidator._id(qbMessage)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {_id} does not exist or empty', ); if (!qbMessageValidator.chat_dialog_id(qbMessage)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {chat_dialog_id} does not exist or empty', ); if (!qbMessageValidator.created_at(qbMessage)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {created_at} does not exist or empty', ); if (!qbMessageValidator.date_sent(qbMessage)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {date_sent} does not exist or empty', ); if (!qbMessageValidator.message(qbMessage)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {message} does not exist or empty', ); if (!qbMessageValidator.read(qbMessage)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {read} does not exist or empty', ); if (!qbMessageValidator.recipient_id(qbMessage)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {recipient_id} does not exist or empty', ); if (!qbMessageValidator.sender_id(qbMessage)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {sender_id} does not exist or empty', ); if (!qbMessageValidator.updated_at(qbMessage)) throw new MapperDTOException( INCORRECT_DATA_MAPPER_DTO_EXCEPTION_MESSAGE, INCORRECT_DATA_MAPPER_DTO_EXCEPTION_CODE, 'field {updated_at} does not exist or empty', ); } }