2026-06-03 15:01:34 +07:00
|
|
|
import { createChildLogger } from "@bete/shared/logger";
|
2026-06-09 10:16:04 +07:00
|
|
|
import type { Request, Response } from "express";
|
2026-06-03 15:01:34 +07:00
|
|
|
import { mascotChatService } from "./mascot-chat.service.js";
|
|
|
|
|
|
|
|
|
|
const logger = createChildLogger("mascot-chat.controller");
|
|
|
|
|
|
2026-06-09 13:07:01 +07:00
|
|
|
interface AuthenticatedRequest extends Request {
|
|
|
|
|
userId?: string;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-03 15:01:34 +07:00
|
|
|
export async function handleMascotChat(req: Request, res: Response) {
|
|
|
|
|
try {
|
|
|
|
|
const { message, context } = req.body;
|
|
|
|
|
|
|
|
|
|
if (!message || typeof message !== "string") {
|
|
|
|
|
return res.status(400).json({
|
|
|
|
|
error: "INVALID_INPUT",
|
|
|
|
|
message: "Message is required and must be a string",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get user ID from auth middleware (if available)
|
2026-06-09 13:07:01 +07:00
|
|
|
const userId = (req as AuthenticatedRequest).userId || "anonymous";
|
2026-06-03 15:01:34 +07:00
|
|
|
|
|
|
|
|
logger.debug(
|
|
|
|
|
{ userId, messageLength: message.length, context },
|
2026-06-09 10:16:04 +07:00
|
|
|
"Received mascot chat message",
|
2026-06-03 15:01:34 +07:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Process message & generate response
|
2026-06-09 10:16:04 +07:00
|
|
|
const response = await mascotChatService.processMessage(
|
|
|
|
|
message,
|
|
|
|
|
context,
|
|
|
|
|
userId,
|
|
|
|
|
);
|
2026-06-03 15:01:34 +07:00
|
|
|
|
|
|
|
|
// Save conversation to database
|
|
|
|
|
await mascotChatService.saveConversation({
|
|
|
|
|
userId,
|
|
|
|
|
userMessage: message,
|
|
|
|
|
mascotResponse: response,
|
|
|
|
|
context,
|
|
|
|
|
timestamp: new Date(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
logger.info({ userId }, "Mascot chat processed successfully");
|
|
|
|
|
|
|
|
|
|
res.status(200).json({
|
|
|
|
|
response,
|
|
|
|
|
timestamp: new Date().toISOString(),
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.error({ error }, "Error processing mascot chat");
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
error: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: "Failed to process mascot chat",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function getMascotChatHistory(req: Request, res: Response) {
|
|
|
|
|
try {
|
2026-06-09 13:07:01 +07:00
|
|
|
const userId = (req as AuthenticatedRequest).userId || "anonymous";
|
2026-06-03 15:01:34 +07:00
|
|
|
const limit = Math.min(parseInt(req.query.limit as string) || 50, 100);
|
|
|
|
|
|
|
|
|
|
const history = await mascotChatService.getChatHistory(userId, limit);
|
|
|
|
|
|
|
|
|
|
res.status(200).json({
|
|
|
|
|
history,
|
|
|
|
|
total: history.length,
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.error({ error }, "Error fetching chat history");
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
error: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: "Failed to fetch chat history",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function clearMascotChatHistory(req: Request, res: Response) {
|
|
|
|
|
try {
|
2026-06-09 13:07:01 +07:00
|
|
|
const userId = (req as AuthenticatedRequest).userId || "anonymous";
|
2026-06-03 15:01:34 +07:00
|
|
|
|
|
|
|
|
await mascotChatService.clearChatHistory(userId);
|
|
|
|
|
|
|
|
|
|
res.status(200).json({
|
|
|
|
|
message: "Chat history cleared successfully",
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.error({ error }, "Error clearing chat history");
|
|
|
|
|
res.status(500).json({
|
|
|
|
|
error: "INTERNAL_SERVER_ERROR",
|
|
|
|
|
message: "Failed to clear chat history",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|