use async_trait::async_trait; use std::sync::Arc; use crate::bus::{BusError, InboundMessage, MessageBus, OutboundMessage}; #[derive(Debug)] pub enum ChannelError { ConfigError(String), ConnectionError(String), SendError(String), BusError(String), Other(String), } impl std::fmt::Display for ChannelError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ChannelError::ConfigError(s) => write!(f, "Config error: {}", s), ChannelError::ConnectionError(s) => write!(f, "Connection error: {}", s), ChannelError::SendError(s) => write!(f, "Send error: {}", s), ChannelError::BusError(s) => write!(f, "Bus error: {}", s), ChannelError::Other(s) => write!(f, "Error: {}", s), } } } impl std::error::Error for ChannelError {} impl From for ChannelError { fn from(e: BusError) -> Self { ChannelError::BusError(e.to_string()) } } #[async_trait] pub trait Channel: Send + Sync + 'static { fn name(&self) -> &str; fn is_running(&self) -> bool; /// Start the channel with a reference to the MessageBus async fn start(&self, bus: Arc) -> Result<(), ChannelError>; /// Stop the channel async fn stop(&self) -> Result<(), ChannelError>; /// Send a message to the channel (called by OutboundDispatcher) async fn send(&self, msg: OutboundMessage) -> Result<(), ChannelError>; /// Send a streaming delta (optional, for channels that support it) async fn send_delta(&self, chat_id: &str, delta: &str) -> Result<(), ChannelError> { let _ = chat_id; let _ = delta; Ok(()) } /// Check if a sender is allowed to use this channel fn is_allowed(&self, _sender_id: &str) -> bool { true } /// Handle an inbound message: check permissions and publish to bus async fn handle_and_publish( &self, bus: &Arc, msg: &InboundMessage, ) -> Result<(), ChannelError> { if !self.is_allowed(&msg.sender_id) { tracing::warn!( channel = %self.name(), sender = %msg.sender_id, "Access denied" ); return Ok(()); } bus.publish_inbound(msg.clone()).await?; Ok(()) } }