Files
pagodera/lib/chat/system-messages.ts
2025-11-11 03:08:36 -03:00

143 lines
4.5 KiB
TypeScript

/**
* Funções para criar mensagens do sistema no chat
*/
import { connectMongoDB } from "@/lib/mongodb/connection";
import { Chat } from "@/lib/mongodb/models/Chat";
import { Message } from "@/lib/mongodb/models/Message";
import { secureLogger } from "@/lib/secure-logger";
import { getSocketIO } from "@/lib/socket/server";
interface CreateSystemMessageParams {
listingId: number;
buyerId: number;
sellerId: number;
message: string;
metadata?: {
action?: string;
[key: string]: any;
};
}
/**
* Cria uma mensagem do sistema no chat e notifica os participantes
*/
export async function createSystemMessageInChat(
params: CreateSystemMessageParams,
): Promise<void> {
try {
await connectMongoDB();
// Gerar chat_id (mesmo formato usado na criação de chat)
const chatId = `${params.listingId}_${params.buyerId}_${params.sellerId}`;
// Buscar ou criar chat
let chat = await Chat.findOne({ chat_id: chatId });
if (!chat) {
// Se o chat não existe, criar (isso pode acontecer se a intenção foi criada antes do chat)
// Buscar dados do listing para cache
const { getListingById } = await import("@/lib/prisma/queries/listings");
const listing = await getListingById(params.listingId);
if (!listing) {
throw new Error("Listing não encontrado");
}
// Buscar dados dos usuários
const { getUserById } = await import("@/lib/prisma/queries/users");
const buyer = await getUserById(params.buyerId);
const seller = await getUserById(params.sellerId);
if (!buyer || !seller) {
throw new Error("Usuário não encontrado");
}
// Buscar personagem principal do comprador e vendedor
const { getMainCharacter } = await import(
"@/lib/prisma/queries/characters"
);
const buyerCharacter = await getMainCharacter(params.buyerId);
const sellerCharacter = await getMainCharacter(params.sellerId);
chat = new Chat({
chat_id: chatId,
listing_id: params.listingId,
buyer_id: params.buyerId,
seller_id: params.sellerId,
is_active: true,
buyer_unread_count: 0,
seller_unread_count: 1, // Vendedor será notificado
listing_cache: {
item_name: listing.item_name,
item_image_url: null, // Pode ser preenchido depois se necessário
price_pix: listing.price_pix ? Number(listing.price_pix) : undefined,
price_tibia_coins: listing.price_tibia_coins || undefined,
price_gold_coins: listing.price_gold_coins
? Number(listing.price_gold_coins)
: undefined,
server_name: listing.server_name,
listing_status: listing.listing_status,
},
buyer_cache: {
user_id: buyer.user_id,
username: buyer.username,
character_name: buyerCharacter?.character_name || null,
},
seller_cache: {
user_id: seller.user_id,
username: seller.username,
character_name: sellerCharacter?.character_name || null,
},
});
await chat.save();
}
// Criar mensagem do sistema
const systemMessage = new Message({
chat_id: chatId,
sender_id: 0, // 0 = sistema
content: params.message,
message_type: "system",
metadata: params.metadata || {},
});
await systemMessage.save();
// Atualizar chat
chat.last_message_at = new Date();
chat.last_message_preview = params.message.substring(0, 100);
chat.seller_unread_count += 1; // Notificar vendedor
await chat.save();
// Emitir mensagem via Socket.io para participantes do chat
const io = getSocketIO();
if (io) {
io.to(`chat:${chatId}`).emit("new_message", {
message: {
_id: systemMessage._id.toString(),
chat_id: systemMessage.chat_id,
sender_id: 0,
content: systemMessage.content,
created_at: systemMessage.created_at.toISOString(),
read_at: null,
message_type: "system",
metadata: systemMessage.metadata,
},
});
}
secureLogger.info("✅ Mensagem do sistema criada no chat", {
chatId,
message: params.message,
action: params.metadata?.action,
});
} catch (error) {
secureLogger.error("❌ Erro ao criar mensagem do sistema no chat", {
error: error instanceof Error ? error.message : "Erro desconhecido",
stack: error instanceof Error ? error.stack : undefined,
});
throw error;
}
}