Files
storkit/server/src/transport.rs

86 lines
3.0 KiB
Rust
Raw Normal View History

//! Transport abstraction for chat platforms.
//!
//! The [`ChatTransport`] trait defines a platform-agnostic interface for
//! sending and editing messages, allowing the bot logic (commands, htop,
//! notifications) to work against any chat platform — Matrix, WhatsApp, etc.
use async_trait::async_trait;
/// A platform-agnostic identifier for a sent message.
///
/// On Matrix this is the event ID; on other platforms it may be a message ID
/// or similar opaque string. The transport implementation is responsible for
/// producing and consuming these identifiers.
pub type MessageId = String;
/// A platform-agnostic identifier for a chat room / channel / conversation.
pub type RoomId = String;
/// Abstraction over a chat platform's message-sending capabilities.
///
/// Implementations must be `Send + Sync` so they can be shared across
/// async tasks via `Arc<dyn ChatTransport>`.
#[async_trait]
pub trait ChatTransport: Send + Sync {
/// Send a plain-text + HTML message to a room.
///
/// Returns the platform-specific message ID on success so it can be
/// referenced later (e.g. for edits or reply detection).
async fn send_message(
&self,
room_id: &str,
plain: &str,
html: &str,
) -> Result<MessageId, String>;
/// Edit a previously sent message.
///
/// `original_message_id` is the [`MessageId`] returned by a prior
/// [`send_message`](ChatTransport::send_message) call.
///
/// Platforms that do not support editing (e.g. WhatsApp) should send a
/// new message instead.
async fn edit_message(
&self,
room_id: &str,
original_message_id: &str,
plain: &str,
html: &str,
) -> Result<(), String>;
/// Signal that the bot is typing (or has stopped typing) in a room.
///
/// Platforms that do not support typing indicators should no-op.
async fn send_typing(&self, room_id: &str, typing: bool) -> Result<(), String>;
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
/// Verify that WhatsAppTransport satisfies the ChatTransport trait and
/// can be used as `Arc<dyn ChatTransport>` (compile-time check).
/// Functional tests are in `whatsapp::tests` using mockito.
#[test]
fn whatsapp_transport_satisfies_trait() {
fn assert_transport<T: ChatTransport>() {}
assert_transport::<crate::whatsapp::WhatsAppTransport>();
// Verify it can be wrapped in Arc<dyn ChatTransport>.
let _: Arc<dyn ChatTransport> =
Arc::new(crate::whatsapp::WhatsAppTransport::new(
"test-phone".to_string(),
"test-token".to_string(),
));
}
/// MatrixTransport cannot be tested without a live homeserver, but we
/// can verify the type implements the trait at compile time.
#[test]
fn matrix_transport_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<crate::matrix::transport_impl::MatrixTransport>();
}
}