85 lines
3.1 KiB
TypeScript
85 lines
3.1 KiB
TypeScript
import { SendMessageCommand } from './ChatCommands';
|
|
import { IChatRepository } from '../../../Domain/IRepository/IChatRepository';
|
|
import { Message } from '../../../Domain/Chat/ChatAggregate';
|
|
import { logAuth, logError } from '../../Services/Logger';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
export class SendMessageCommandHandler {
|
|
constructor(private chatRepository: IChatRepository) {}
|
|
|
|
async execute(command: SendMessageCommand): Promise<Message | null> {
|
|
try {
|
|
// Validate message is non-empty string
|
|
if (typeof command.message !== 'string' || !command.message.trim()) {
|
|
throw new Error('Message must be a non-empty string');
|
|
}
|
|
|
|
const chat = await this.chatRepository.findById(command.chatId);
|
|
if (!chat) {
|
|
throw new Error('Chat not found');
|
|
}
|
|
|
|
// Check if user is member of this chat
|
|
if (!chat.users.includes(command.userId)) {
|
|
throw new Error('User is not a member of this chat');
|
|
}
|
|
|
|
// Create message
|
|
const message: Message = {
|
|
id: uuidv4(),
|
|
date: new Date(),
|
|
userid: command.userId,
|
|
text: command.message.trim()
|
|
};
|
|
|
|
// Manage message history (keep last 10 per user, up to 2 weeks)
|
|
let updatedMessages = [...chat.messages, message];
|
|
updatedMessages = this.pruneMessages(updatedMessages);
|
|
|
|
// Update chat
|
|
await this.chatRepository.update(command.chatId, {
|
|
messages: updatedMessages,
|
|
lastActivity: new Date()
|
|
});
|
|
|
|
logAuth('Message sent successfully', command.userId, {
|
|
chatId: command.chatId,
|
|
messageLength: command.message.length,
|
|
totalMessages: updatedMessages.length
|
|
});
|
|
|
|
return message;
|
|
|
|
} catch (error) {
|
|
logError('SendMessageCommandHandler error', error as Error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private pruneMessages(messages: Message[]): Message[] {
|
|
const twoWeeksAgo = new Date(Date.now() - 14 * 24 * 60 * 60 * 1000);
|
|
|
|
// Remove messages older than 2 weeks
|
|
let prunedMessages = messages.filter(msg => new Date(msg.date) > twoWeeksAgo);
|
|
|
|
// Group by user and keep last 10 messages per user
|
|
const messagesByUser = new Map<string, Message[]>();
|
|
prunedMessages.forEach(msg => {
|
|
if (!messagesByUser.has(msg.userid)) {
|
|
messagesByUser.set(msg.userid, []);
|
|
}
|
|
messagesByUser.get(msg.userid)!.push(msg);
|
|
});
|
|
|
|
// Keep only last 10 messages per user
|
|
const finalMessages: Message[] = [];
|
|
messagesByUser.forEach((userMessages, userId) => {
|
|
const last10 = userMessages.slice(-10);
|
|
finalMessages.push(...last10);
|
|
});
|
|
|
|
// Sort by date
|
|
return finalMessages.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
|
}
|
|
}
|