148 lines
4.7 KiB
JavaScript
148 lines
4.7 KiB
JavaScript
const { PrismaClient: MSGClient } = require("../../prisma/clients/msg");
|
|
const logger = require("./logger.services.js");
|
|
|
|
const msgPrisma = new MSGClient();
|
|
|
|
class SocketService {
|
|
constructor(io) {
|
|
this.io = io;
|
|
this.setupSocketHandlers();
|
|
}
|
|
|
|
setupSocketHandlers() {
|
|
this.io.on('connection', (socket) => {
|
|
logger.info(`New client connected: ${socket.id}`);
|
|
|
|
socket.on('join_conversation', (data) => {
|
|
this.handleJoinConversation(socket, data);
|
|
});
|
|
|
|
socket.on('send_message', async (data) => {
|
|
await this.handleSendMessage(socket, data);
|
|
});
|
|
|
|
socket.on('typing_start', (data) => {
|
|
this.handleTypingStart(socket, data);
|
|
});
|
|
|
|
socket.on('typing_stop', (data) => {
|
|
this.handleTypingStop(socket, data);
|
|
});
|
|
|
|
socket.on('disconnect', () => {
|
|
this.handleDisconnect(socket);
|
|
});
|
|
});
|
|
}
|
|
|
|
handleJoinConversation(socket, data) {
|
|
const { conversationId, userId, userType } = data;
|
|
socket.join(conversationId);
|
|
socket.userId = userId;
|
|
socket.userType = userType;
|
|
logger.info(`${userType} ${userId} joined conversation ${conversationId}`);
|
|
|
|
socket.to(conversationId).emit('user_joined', {
|
|
userId,
|
|
userType,
|
|
message: `${userType} joined the conversation`
|
|
});
|
|
}
|
|
|
|
async handleSendMessage(socket, data) {
|
|
try {
|
|
const { conversationId, message, senderId, senderType, messageType = 'text' } = data;
|
|
|
|
const savedMessage = await this.saveMessageToDatabase({
|
|
conversationId,
|
|
message,
|
|
senderId,
|
|
senderType,
|
|
messageType
|
|
});
|
|
|
|
this.io.to(conversationId).emit('receive_message', savedMessage);
|
|
|
|
logger.info(`Message sent in conversation ${conversationId} by ${senderType} ${senderId}`);
|
|
|
|
} catch (error) {
|
|
logger.error('Error sending message:', error);
|
|
socket.emit('message_error', {
|
|
error: 'Failed to send message',
|
|
details: error.message
|
|
});
|
|
}
|
|
}
|
|
|
|
handleTypingStart(socket, data) {
|
|
const { conversationId, userId, userType } = data;
|
|
socket.to(conversationId).emit('user_typing', { userId, userType });
|
|
}
|
|
|
|
handleTypingStop(socket, data) {
|
|
const { conversationId, userId, userType } = data;
|
|
socket.to(conversationId).emit('user_stopped_typing', { userId, userType });
|
|
}
|
|
|
|
handleDisconnect(socket) {
|
|
logger.info(`Client disconnected: ${socket.id}`);
|
|
|
|
if (socket.userId && socket.userType) {
|
|
// You might want to emit to specific rooms the user was in
|
|
// This would require tracking which rooms the user was in
|
|
}
|
|
}
|
|
|
|
async saveMessageToDatabase(messageData) {
|
|
try {
|
|
const message = await msgPrisma.messages.create({
|
|
data: {
|
|
conversationId: messageData.conversationId,
|
|
content: messageData.message,
|
|
messageType: messageData.messageType || 'text',
|
|
senderId: messageData.senderId,
|
|
senderType: messageData.senderType,
|
|
senderName: messageData.senderName,
|
|
status: 'sent',
|
|
metadata: messageData.metadata || {}
|
|
},
|
|
include: {
|
|
conversation: true
|
|
}
|
|
});
|
|
|
|
await msgPrisma.conversations.update({
|
|
where: { id: messageData.conversationId },
|
|
data: { lastMessageAt: new Date() }
|
|
});
|
|
|
|
return {
|
|
id: message.id,
|
|
conversationId: message.conversationId,
|
|
message: message.content,
|
|
senderId: message.senderId,
|
|
senderType: message.senderType,
|
|
senderName: message.senderName,
|
|
messageType: message.messageType,
|
|
timestamp: message.createdAt.toISOString(),
|
|
status: message.status
|
|
};
|
|
} catch (error) {
|
|
logger.error('Error saving message to database:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
sendMessageToConversation(conversationId, messageData) {
|
|
this.io.to(conversationId).emit('receive_message', messageData);
|
|
}
|
|
|
|
sendNotificationToUser(userId, notificationData) {
|
|
this.io.emit('notification', {
|
|
userId,
|
|
...notificationData
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = SocketService; |