98 lines
3.0 KiB
Rust
98 lines
3.0 KiB
Rust
//! Matrix implementation of [`ChatTransport`].
|
|
//!
|
|
//! Wraps a [`matrix_sdk::Client`] and delegates message sending / editing
|
|
//! to the Matrix SDK.
|
|
|
|
use async_trait::async_trait;
|
|
use matrix_sdk::Client;
|
|
use matrix_sdk::ruma::OwnedRoomId;
|
|
use matrix_sdk::ruma::events::room::message::{
|
|
ReplacementMetadata, RoomMessageEventContent, RoomMessageEventContentWithoutRelation,
|
|
};
|
|
|
|
use crate::chat::{ChatTransport, MessageId};
|
|
|
|
/// Matrix-backed [`ChatTransport`] implementation.
|
|
///
|
|
/// Holds a [`Client`] and resolves room IDs at send time.
|
|
pub struct MatrixTransport {
|
|
client: Client,
|
|
}
|
|
|
|
impl MatrixTransport {
|
|
/// Creates a new `MatrixTransport` wrapping the given Matrix SDK `Client`.
|
|
pub fn new(client: Client) -> Self {
|
|
Self { client }
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl ChatTransport for MatrixTransport {
|
|
async fn send_message(
|
|
&self,
|
|
room_id: &str,
|
|
plain: &str,
|
|
html: &str,
|
|
) -> Result<MessageId, String> {
|
|
let room_id: OwnedRoomId = room_id
|
|
.parse()
|
|
.map_err(|e| format!("Invalid room ID '{room_id}': {e}"))?;
|
|
let room = self
|
|
.client
|
|
.get_room(&room_id)
|
|
.ok_or_else(|| format!("Room {room_id} not found in client state"))?;
|
|
|
|
let content = RoomMessageEventContent::text_html(plain.to_string(), html.to_string());
|
|
let resp = room
|
|
.send(content)
|
|
.await
|
|
.map_err(|e| format!("Matrix send error: {e}"))?;
|
|
|
|
Ok(resp.event_id.to_string())
|
|
}
|
|
|
|
async fn edit_message(
|
|
&self,
|
|
room_id: &str,
|
|
original_message_id: &str,
|
|
plain: &str,
|
|
html: &str,
|
|
) -> Result<(), String> {
|
|
let room_id: OwnedRoomId = room_id
|
|
.parse()
|
|
.map_err(|e| format!("Invalid room ID '{room_id}': {e}"))?;
|
|
let room = self
|
|
.client
|
|
.get_room(&room_id)
|
|
.ok_or_else(|| format!("Room {room_id} not found in client state"))?;
|
|
|
|
let original_event_id = original_message_id
|
|
.parse()
|
|
.map_err(|e| format!("Invalid event ID '{original_message_id}': {e}"))?;
|
|
|
|
let new_content =
|
|
RoomMessageEventContentWithoutRelation::text_html(plain.to_string(), html.to_string());
|
|
let metadata = ReplacementMetadata::new(original_event_id, None);
|
|
let content = new_content.make_replacement(metadata);
|
|
|
|
room.send(content)
|
|
.await
|
|
.map(|_| ())
|
|
.map_err(|e| format!("Matrix edit error: {e}"))
|
|
}
|
|
|
|
async fn send_typing(&self, room_id: &str, typing: bool) -> Result<(), String> {
|
|
let room_id: OwnedRoomId = room_id
|
|
.parse()
|
|
.map_err(|e| format!("Invalid room ID '{room_id}': {e}"))?;
|
|
let room = self
|
|
.client
|
|
.get_room(&room_id)
|
|
.ok_or_else(|| format!("Room {room_id} not found in client state"))?;
|
|
|
|
room.typing_notice(typing)
|
|
.await
|
|
.map_err(|e| format!("Matrix typing indicator error: {e}"))
|
|
}
|
|
}
|