mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-05-18 20:08:19 +00:00
Provider-agnostic WhatsApp integration for AI-driven appointment booking: - MessagingProvider interface (sendText, sendButtons, sendList, parseInbound) - GupshupProvider implementation (Gupshup WhatsApp API) - MessagingService — AI orchestration with tools (department/doctor/slot lists via interactive WhatsApp messages, appointment booking, caller resolution + context injection) - Redis conversation history (24h TTL, matches WhatsApp session window) - Webhook controller at POST /api/messaging/webhook Swappable to Ozonetel or Meta Cloud API by implementing MessagingProvider and switching MESSAGING_PROVIDER env var. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
42 lines
1.4 KiB
TypeScript
42 lines
1.4 KiB
TypeScript
import { Injectable, Logger } from '@nestjs/common';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import Redis from 'ioredis';
|
|
import { ConversationEntry } from './types';
|
|
|
|
@Injectable()
|
|
export class MessagingConversationService {
|
|
private readonly logger = new Logger(MessagingConversationService.name);
|
|
private readonly redis: Redis;
|
|
private readonly ttlSec = 24 * 60 * 60; // 24h — matches WhatsApp session window
|
|
private readonly maxHistory = 20;
|
|
|
|
constructor(config: ConfigService) {
|
|
const redisUrl = config.get<string>('redis.url') ?? 'redis://localhost:6379';
|
|
this.redis = new Redis(redisUrl);
|
|
}
|
|
|
|
private key(phone: string): string {
|
|
return `wa:conv:${phone}`;
|
|
}
|
|
|
|
async getHistory(phone: string): Promise<ConversationEntry[]> {
|
|
const raw = await this.redis.get(this.key(phone));
|
|
if (!raw) return [];
|
|
try {
|
|
return JSON.parse(raw);
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
async addMessages(phone: string, entries: ConversationEntry[]): Promise<void> {
|
|
const existing = await this.getHistory(phone);
|
|
const updated = [...existing, ...entries].slice(-this.maxHistory);
|
|
await this.redis.setex(this.key(phone), this.ttlSec, JSON.stringify(updated));
|
|
}
|
|
|
|
async clear(phone: string): Promise<void> {
|
|
await this.redis.del(this.key(phone));
|
|
}
|
|
}
|