Files
telegram-bot-workers/src/services/conversation-service.ts
kappa 92ddc239ef feat: save messages to new conversation storage
Integrate new conversation-storage.ts system while maintaining backward
compatibility with existing message_buffer system:

- Import saveConversationMessage from conversation-storage.ts
- Save user messages to both new system (role: 'user') and old buffer
- Save assistant responses to both new system (role: 'assistant') and old buffer
- Preserve existing functionality during migration period

Changes:
- Add saveConversationMessage import
- Call saveConversationMessage before addToBuffer for user messages
- Call saveConversationMessage before addToBuffer for bot responses
- Updated step numbering in comments (1-7)

Note: Old buffer system will be removed after migration is complete.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 12:47:35 +09:00

107 lines
3.5 KiB
TypeScript

import type { Env, KeyboardData } from '../types';
import {
addToBuffer,
processAndSummarize,
generateAIResponse,
} from '../summary-service';
import { sendChatAction } from '../telegram';
import { createLogger } from '../utils/logger';
import { saveConversationMessage } from './conversation-storage';
const logger = createLogger('conversation');
export interface ConversationResult {
responseText: string;
isProfileUpdated: boolean;
keyboardData?: KeyboardData | null;
}
export class ConversationService {
constructor(private env: Env) {}
/**
* 사용자 메시지를 처리하고 AI 응답을 생성합니다.
* 버퍼링, AI 생성, 요약 프로세스를 포함합니다.
*/
async processUserMessage(
userId: number,
chatId: string,
text: string,
telegramUserId: string
): Promise<ConversationResult> {
// 1. 타이핑 액션 전송 (비동기로 실행, 기다리지 않음)
sendChatAction(this.env.BOT_TOKEN, Number(chatId), 'typing').catch(err =>
logger.error('타이핑 액션 전송 실패', err as Error)
);
// 2. 새 시스템에 사용자 메시지 저장
await saveConversationMessage(this.env.DB, telegramUserId, {
role: 'user',
content: text,
});
// 3. 기존 버퍼에도 저장 (호환성 - 나중에 제거)
await addToBuffer(this.env.DB, userId, chatId, 'user', text);
// 4. AI 응답 생성
let responseText = await generateAIResponse(
this.env,
userId,
chatId,
text,
telegramUserId
);
// __DIRECT__ 마커 제거 (AI가 그대로 전달한 경우 대비)
if (responseText.includes('__DIRECT__')) {
const directIndex = responseText.indexOf('__DIRECT__');
responseText = responseText.slice(directIndex + '__DIRECT__'.length).trim();
}
// 5. 새 시스템에 봇 응답 저장
await saveConversationMessage(this.env.DB, telegramUserId, {
role: 'assistant',
content: responseText,
});
// 6. 기존 버퍼에도 저장 (호환성 - 나중에 제거)
// 봇 응답 버퍼에 추가 (키보드 데이터 마커 등은 그대로 저장)
// 실제 사용자에게 보여질 텍스트만 저장하는 것이 좋으나,
// 현재 구조상 전체를 저장하고 나중에 컨텍스트로 활용 시 정제될 수 있음
await addToBuffer(this.env.DB, userId, chatId, 'bot', responseText);
// 7. 임계값 도달 시 프로필 업데이트 (요약)
const { summarized } = await processAndSummarize(
this.env,
userId,
chatId
);
// 키보드 데이터 파싱
let keyboardData: KeyboardData | null = null;
// s 플래그로 .이 줄바꿈도 매칭하도록 (멀티라인 JSON 대응)
const keyboardMatch = responseText.match(/__KEYBOARD__(.+?)__END__\n?/s);
if (keyboardMatch) {
logger.debug('키보드 마커 감지', { preview: keyboardMatch[1].substring(0, 100) });
responseText = responseText.replace(/__KEYBOARD__.+?__END__\n?/s, '');
try {
keyboardData = JSON.parse(keyboardMatch[1]) as KeyboardData;
logger.debug('키보드 파싱 성공', { type: keyboardData.type });
} catch (e) {
logger.error('키보드 파싱 오류', e as Error, { rawData: keyboardMatch[1] });
}
} else if (responseText.includes('__KEYBOARD__')) {
logger.warn('키보드 마커 발견했으나 정규식 매칭 실패', {
preview: responseText.substring(0, 200)
});
}
return {
responseText,
isProfileUpdated: summarized,
keyboardData
};
}
}