fix: resolve architecture disconnects and codebase weaknesses

- Standardize MessageRecord types — single source of truth from @bete/shared
- Clean up config: remove unused GUILD_ID/TEXT_GUILD_ID/TEXT_CHANNEL_ID, fix WEBSERVER_PORT default (3001), remove default admin password
- Move mascot_chat_messages table to Drizzle schema with proper migration
- Remove runtime DDL (CREATE TABLE IF NOT EXISTS) from mascot-chat repository
- Remove phantom analytics/ module from documentation
- Add better-sqlite3 dependency to root devDependencies
- Replace 'as any' casts with proper type assertions across AI moderation
- Add error logging to silent catch blocks in LLM client
- Apply Biome formatting and import organization

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MythEclipse
2026-06-09 13:07:01 +07:00
co-authored by Claude Opus 4.8
parent 67d66bb5dd
commit 3614d32701
21 changed files with 206 additions and 150 deletions
@@ -4,6 +4,10 @@ import { mascotChatService } from "./mascot-chat.service.js";
const logger = createChildLogger("mascot-chat.controller");
interface AuthenticatedRequest extends Request {
userId?: string;
}
export async function handleMascotChat(req: Request, res: Response) {
try {
const { message, context } = req.body;
@@ -16,7 +20,7 @@ export async function handleMascotChat(req: Request, res: Response) {
}
// Get user ID from auth middleware (if available)
const userId = (req as any).userId || "anonymous";
const userId = (req as AuthenticatedRequest).userId || "anonymous";
logger.debug(
{ userId, messageLength: message.length, context },
@@ -56,7 +60,7 @@ export async function handleMascotChat(req: Request, res: Response) {
export async function getMascotChatHistory(req: Request, res: Response) {
try {
const userId = (req as any).userId || "anonymous";
const userId = (req as AuthenticatedRequest).userId || "anonymous";
const limit = Math.min(parseInt(req.query.limit as string) || 50, 100);
const history = await mascotChatService.getChatHistory(userId, limit);
@@ -76,7 +80,7 @@ export async function getMascotChatHistory(req: Request, res: Response) {
export async function clearMascotChatHistory(req: Request, res: Response) {
try {
const userId = (req as any).userId || "anonymous";
const userId = (req as AuthenticatedRequest).userId || "anonymous";
await mascotChatService.clearChatHistory(userId);
@@ -37,33 +37,7 @@ export interface ServerInsights {
}
export class MascotChatRepository {
private initialized = false;
async ensureSchema(): Promise<void> {
if (this.initialized) return;
const pool = getPool();
await pool.query(`
CREATE TABLE IF NOT EXISTS mascot_chat_messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id TEXT NOT NULL,
user_message TEXT NOT NULL,
mascot_response TEXT NOT NULL,
context JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
)
`);
await pool.query(`
CREATE INDEX IF NOT EXISTS idx_mascot_chat_messages_user_created
ON mascot_chat_messages (user_id, created_at DESC)
`);
this.initialized = true;
logger.info("Mascot chat schema ready");
}
async saveConversation(input: SaveConversationInput): Promise<void> {
await this.ensureSchema();
const pool = getPool();
await pool.query(
@@ -88,7 +62,6 @@ export class MascotChatRepository {
userId: string,
limit: number,
): Promise<MascotChatHistoryRow[]> {
await this.ensureSchema();
const pool = getPool();
const { rows } = await pool.query<MascotChatHistoryRow>(
@@ -107,7 +80,6 @@ export class MascotChatRepository {
}
async clearChatHistory(userId: string): Promise<void> {
await this.ensureSchema();
const pool = getPool();
const { rowCount } = await pool.query(
@@ -122,7 +94,6 @@ export class MascotChatRepository {
guildId?: string,
channelId?: string,
): Promise<ServerInsights> {
await this.ensureSchema();
const pool = getPool();
try {
+1 -1
View File
@@ -31,7 +31,7 @@ let publisherClient: Redis | null = null;
let subscriberClient: Redis | null = null;
function ensureRedisConfig(): boolean {
return !!(config.REDIS_URL);
return !!config.REDIS_URL;
}
function createClient(): Redis {