feat: Implement real-time message delivery for conversations via WebSocket integration and update admin seed email.

This commit is contained in:
pradeepkumar
2026-03-18 16:49:13 +05:30
parent 2cb4a649bd
commit c3a3df704e
3 changed files with 31 additions and 10 deletions

View File

@@ -1317,7 +1317,7 @@ async function main() {
// ============================================= // =============================================
console.log('👤 Seeding Admin User...'); console.log('👤 Seeding Admin User...');
const adminEmail = process.env.ADMIN_EMAIL || 'admin@realestate.com'; const adminEmail = process.env.ADMIN_EMAIL || 'admin@re-quest.com';
const adminPassword = process.env.ADMIN_PASSWORD || 'Admin@123456'; const adminPassword = process.env.ADMIN_PASSWORD || 'Admin@123456';
// Hash password with Argon2 (more secure than bcrypt) // Hash password with Argon2 (more secure than bcrypt)

View File

@@ -20,6 +20,7 @@ import {
ApiParam, ApiParam,
} from '@nestjs/swagger'; } from '@nestjs/swagger';
import { MessagesService } from './messages.service'; import { MessagesService } from './messages.service';
import { MessagesGateway } from './messages.gateway';
import { CreateMessageDto, StartConversationDto } from './dto'; import { CreateMessageDto, StartConversationDto } from './dto';
import { JwtAuthGuard } from '../auth/guards'; import { JwtAuthGuard } from '../auth/guards';
import { CurrentUser } from '../auth/decorators'; import { CurrentUser } from '../auth/decorators';
@@ -30,7 +31,10 @@ import { UserRole } from '@prisma/client';
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@ApiBearerAuth('JWT-auth') @ApiBearerAuth('JWT-auth')
export class MessagesController { export class MessagesController {
constructor(private readonly messagesService: MessagesService) {} constructor(
private readonly messagesService: MessagesService,
private readonly messagesGateway: MessagesGateway,
) {}
// ========================================== // ==========================================
// GET CONVERSATIONS LIST // GET CONVERSATIONS LIST
@@ -177,7 +181,23 @@ export class MessagesController {
@CurrentUser('id') userId: string, @CurrentUser('id') userId: string,
@Body() dto: CreateMessageDto, @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;
} }
// ========================================== // ==========================================

View File

@@ -175,13 +175,8 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
data.message, data.message,
); );
// Broadcast to other clients in the conversation room (exclude sender) // Send directly to the other participant's socket(s)
client // This is the primary delivery mechanism — works even if they haven't joined the room
.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
try { try {
const participants = await this.messagesService.getConversationParticipants(data.conversationId); const participants = await this.messagesService.getConversationParticipants(data.conversationId);
if (participants) { 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}`); 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 }; return { success: true, message };
} catch (error) { } catch (error) {
return { error: error.message }; return { error: error.message };