use std::sync::Arc;
use std::time::Duration;
use crate::caps::ChannelCaps;
use crate::id::ChannelId;
use crate::message::{InboundEvent, RenderedMessage, ReplyTarget, SentRef};
use crate::webhook::WebhookHandler;
use crate::{BoxError, CancellationToken, async_trait};
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ChannelError {
#[error("not supported by this platform: {0}")]
Unsupported(&'static str),
#[error("authentication failed: {0}")]
Auth(String),
#[error("rate limited")]
RateLimited {
retry_after: Option<Duration>,
},
#[error("temporary failure: {0}")]
Transient(#[source] BoxError),
#[error("{0}")]
Failed(#[source] BoxError),
}
impl ChannelError {
pub fn is_retryable(&self) -> bool {
matches!(self, Self::RateLimited { .. } | Self::Transient(_))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
#[error("the runtime is no longer accepting events")]
pub struct SinkClosed;
#[async_trait]
pub trait InboundSink: Send + Sync {
async fn deliver(&self, event: InboundEvent) -> Result<(), SinkClosed>;
}
#[async_trait]
pub trait Channel: Send + Sync {
fn id(&self) -> &ChannelId;
fn caps(&self) -> &ChannelCaps;
async fn run(
&self,
sink: Arc<dyn InboundSink>,
shutdown: CancellationToken,
) -> Result<(), ChannelError>;
async fn send(
&self,
to: &ReplyTarget,
message: &RenderedMessage,
) -> Result<SentRef, ChannelError>;
async fn edit(&self, _sent: &SentRef, _message: &RenderedMessage) -> Result<(), ChannelError> {
Err(ChannelError::Unsupported("edit"))
}
async fn typing(&self, _to: &ReplyTarget) -> Result<(), ChannelError> {
Ok(())
}
fn webhook(&self) -> Option<Arc<dyn WebhookHandler>> {
None
}
}