feat: Implement real-time message delivery for conversations via WebSocket integration and update admin seed email.
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
ApiParam,
|
||||
} from '@nestjs/swagger';
|
||||
import { MessagesService } from './messages.service';
|
||||
import { MessagesGateway } from './messages.gateway';
|
||||
import { CreateMessageDto, StartConversationDto } from './dto';
|
||||
import { JwtAuthGuard } from '../auth/guards';
|
||||
import { CurrentUser } from '../auth/decorators';
|
||||
@@ -30,7 +31,10 @@ import { UserRole } from '@prisma/client';
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth('JWT-auth')
|
||||
export class MessagesController {
|
||||
constructor(private readonly messagesService: MessagesService) {}
|
||||
constructor(
|
||||
private readonly messagesService: MessagesService,
|
||||
private readonly messagesGateway: MessagesGateway,
|
||||
) {}
|
||||
|
||||
// ==========================================
|
||||
// GET CONVERSATIONS LIST
|
||||
@@ -177,7 +181,23 @@ export class MessagesController {
|
||||
@CurrentUser('id') userId: string,
|
||||
@Body() dto: CreateMessageDto,
|
||||
) {
|
||||
return this.messagesService.createMessage(conversationId, userId, dto);
|
||||
const message = await this.messagesService.createMessage(conversationId, userId, dto);
|
||||
|
||||
// Broadcast via WebSocket so the other party gets real-time delivery
|
||||
try {
|
||||
const participants = await this.messagesService.getConversationParticipants(conversationId);
|
||||
if (participants) {
|
||||
const otherUserId = userId === participants.userId
|
||||
? participants.agentUserId
|
||||
: participants.userId;
|
||||
// Send to the other participant's socket(s)
|
||||
this.messagesGateway.sendToUser(otherUserId, 'new_message', message);
|
||||
}
|
||||
} catch {
|
||||
// Socket broadcast failure shouldn't fail the REST response
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
|
||||
@@ -175,13 +175,8 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
|
||||
data.message,
|
||||
);
|
||||
|
||||
// Broadcast to other clients in the conversation room (exclude sender)
|
||||
client
|
||||
.to(`conversation:${data.conversationId}`)
|
||||
.emit('new_message', message);
|
||||
|
||||
// Also send directly to the other participant's socket(s)
|
||||
// so they receive the message even if they haven't joined this room
|
||||
// Send directly to the other participant's socket(s)
|
||||
// This is the primary delivery mechanism — works even if they haven't joined the room
|
||||
try {
|
||||
const participants = await this.messagesService.getConversationParticipants(data.conversationId);
|
||||
if (participants) {
|
||||
@@ -194,6 +189,12 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
|
||||
this.logger.warn(`Failed to get participants for direct delivery in ${data.conversationId}: ${participantError.message}`);
|
||||
}
|
||||
|
||||
// Also broadcast to the conversation room as a fallback
|
||||
// (client.to excludes sender; recipients dedup by message ID)
|
||||
client
|
||||
.to(`conversation:${data.conversationId}`)
|
||||
.emit('new_message', message);
|
||||
|
||||
return { success: true, message };
|
||||
} catch (error) {
|
||||
return { error: error.message };
|
||||
|
||||
Reference in New Issue
Block a user