botserver/src/channels/mod.rs

143 lines
4.1 KiB
Rust

use async_trait::async_trait;
use log::{debug, info};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::{mpsc, Mutex};
use crate::shared::models::BotResponse;
#[async_trait]
pub trait ChannelAdapter: Send + Sync {
async fn send_message(
&self,
response: BotResponse,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
}
pub struct WebChannelAdapter {
connections: Arc<Mutex<HashMap<String, mpsc::Sender<BotResponse>>>>,
}
impl WebChannelAdapter {
pub fn new() -> Self {
Self {
connections: Arc::new(Mutex::new(HashMap::new())),
}
}
pub async fn add_connection(&self, session_id: String, tx: mpsc::Sender<BotResponse>) {
self.connections.lock().await.insert(session_id, tx);
}
pub async fn remove_connection(&self, session_id: &str) {
self.connections.lock().await.remove(session_id);
}
pub async fn send_message_to_session(
&self,
session_id: &str,
message: BotResponse,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let connections = self.connections.lock().await;
if let Some(tx) = connections.get(session_id) {
if let Err(e) = tx.send(message).await {
log::error!(
"Failed to send message to WebSocket session {}: {}",
session_id,
e
);
return Err(Box::new(e));
}
debug!("Message sent to WebSocket session: {}", session_id);
Ok(())
} else {
debug!("No WebSocket connection found for session: {}", session_id);
Err("No WebSocket connection found".into())
}
}
}
#[async_trait]
impl ChannelAdapter for WebChannelAdapter {
async fn send_message(
&self,
response: BotResponse,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let connections = self.connections.lock().await;
if let Some(tx) = connections.get(&response.session_id) {
tx.send(response).await?;
}
Ok(())
}
}
pub struct VoiceAdapter {
livekit_url: String,
api_key: String,
api_secret: String,
rooms: Arc<Mutex<HashMap<String, String>>>,
connections: Arc<Mutex<HashMap<String, mpsc::Sender<BotResponse>>>>,
}
impl VoiceAdapter {
pub fn new(livekit_url: String, api_key: String, api_secret: String) -> Self {
Self {
livekit_url,
api_key,
api_secret,
rooms: Arc::new(Mutex::new(HashMap::new())),
connections: Arc::new(Mutex::new(HashMap::new())),
}
}
pub async fn start_voice_session(
&self,
session_id: &str,
user_id: &str,
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
info!(
"Starting voice session for user: {} with session: {}",
user_id, session_id
);
let token = format!("mock_token_{}_{}", session_id, user_id);
self.rooms
.lock()
.await
.insert(session_id.to_string(), token.clone());
Ok(token)
}
pub async fn stop_voice_session(
&self,
session_id: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
self.rooms.lock().await.remove(session_id);
Ok(())
}
pub async fn add_connection(&self, session_id: String, tx: mpsc::Sender<BotResponse>) {
self.connections.lock().await.insert(session_id, tx);
}
pub async fn send_voice_response(
&self,
session_id: &str,
text: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
info!("Sending voice response to session {}: {}", session_id, text);
Ok(())
}
}
#[async_trait]
impl ChannelAdapter for VoiceAdapter {
async fn send_message(
&self,
response: BotResponse,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
info!("Sending voice response to: {}", response.user_id);
self.send_voice_response(&response.session_id, &response.content)
.await
}
}