Files
GMW/services/backend/src/modules/chatbot/chatbot.controller.ts
T

97 lines
2.6 KiB
TypeScript
Raw Normal View History

import type { Request, Response } from "express";
import { createChildLogger } from "@/shared/logger/index";
import { asyncHandler } from "../../shared/middlewares/index.js";
import { chatbotService } from "./chatbot.service.js";
2026-06-03 15:01:34 +07:00
const logger = createChildLogger("chatbot.controller");
2026-06-03 15:01:34 +07:00
interface AuthenticatedRequest extends Request {
userId?: string;
}
/**
* Resolve the actor id for a request. Frontend (no-login) sends a per-device
* UUID via X-User-Id so chat history stays isolated per visitor; a registered
* auth middleware userId takes precedence when present.
*/
function resolveUserId(req: Request): string {
const authId = (req as AuthenticatedRequest).userId;
if (authId) return authId;
const header = (req.headers["x-user-id"] as string | undefined)?.trim();
return header || "anonymous";
}
export const handleChatbotChat = asyncHandler(
async (req: Request, res: Response) => {
const { message, context } = req.body as {
message: string;
context?: Record<string, unknown>;
};
// Validate required fields
if (!message || typeof message !== "string") {
2026-06-03 15:01:34 +07:00
return res.status(400).json({
error: "INVALID_INPUT",
message: "Message is required and must be a string",
2026-06-03 15:01:34 +07:00
});
}
// Get user ID from X-User-Id header (no-login device uuid) or auth
const userId = resolveUserId(req);
2026-06-03 15:01:34 +07:00
logger.debug(
{ userId, messageLength: message.length, context },
"Received chatbot chat message",
2026-06-03 15:01:34 +07:00
);
// Process message & generate response
const response = await chatbotService.processMessage(
message,
context,
userId,
);
2026-06-03 15:01:34 +07:00
// Save conversation to database
await chatbotService.saveConversation({
2026-06-03 15:01:34 +07:00
userId,
userMessage: message,
botResponse: response,
2026-06-03 15:01:34 +07:00
context,
timestamp: new Date(),
});
logger.info({ userId }, "Chatbot chat processed successfully");
2026-06-03 15:01:34 +07:00
res.status(200).json({
response,
timestamp: new Date().toISOString(),
});
},
);
2026-06-03 15:01:34 +07:00
export const getChatbotHistory = asyncHandler(
async (req: Request, res: Response) => {
const userId = resolveUserId(req);
const limit = Math.min(parseInt(req.query.limit as string, 10) || 50, 100);
2026-06-03 15:01:34 +07:00
const history = await chatbotService.getChatHistory(userId, limit);
2026-06-03 15:01:34 +07:00
res.status(200).json({
history,
total: history.length,
});
},
);
2026-06-03 15:01:34 +07:00
export const clearChatbotHistory = asyncHandler(
async (req: Request, res: Response) => {
const userId = resolveUserId(req);
2026-06-03 15:01:34 +07:00
await chatbotService.clearChatHistory(userId);
2026-06-03 15:01:34 +07:00
res.status(200).json({
message: "Chat history cleared successfully",
});
},
);