Remove Room enum
This commit is contained in:
committed by
Jonas Platte
parent
85f66b1f96
commit
67ef9c3fa0
@@ -3,7 +3,6 @@ use std::sync::{Arc, RwLock};
|
||||
use anyhow::{anyhow, Context};
|
||||
use matrix_sdk::{
|
||||
media::{MediaFileHandle as SdkMediaFileHandle, MediaFormat, MediaRequest, MediaThumbnailSize},
|
||||
room::Room as SdkRoom,
|
||||
ruma::{
|
||||
api::client::{
|
||||
account::whoami,
|
||||
@@ -537,7 +536,7 @@ impl Client {
|
||||
|
||||
pub fn get_dm_room(&self, user_id: String) -> Result<Option<Arc<Room>>, ClientError> {
|
||||
let user_id = UserId::parse(user_id)?;
|
||||
let sdk_room = self.inner.get_dm_room(&user_id).map(SdkRoom::Joined);
|
||||
let sdk_room = self.inner.get_dm_room(&user_id);
|
||||
let dm = sdk_room.map(|room| Arc::new(Room::new(room)));
|
||||
Ok(dm)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use matrix_sdk::{
|
||||
AttachmentConfig, AttachmentInfo, BaseAudioInfo, BaseFileInfo, BaseImageInfo,
|
||||
BaseThumbnailInfo, BaseVideoInfo, Thumbnail,
|
||||
},
|
||||
room::{Receipts, Room as SdkRoom},
|
||||
room::{Common as SdkRoom, Receipts},
|
||||
ruma::{
|
||||
api::client::{receipt::create_receipt::v3::ReceiptType, room::report_content},
|
||||
events::{
|
||||
@@ -21,7 +21,7 @@ use matrix_sdk::{
|
||||
},
|
||||
EventId, UserId,
|
||||
},
|
||||
RoomMemberships,
|
||||
RoomMemberships, RoomState,
|
||||
};
|
||||
use matrix_sdk_ui::timeline::{BackPaginationStatus, RoomExt, Timeline};
|
||||
use mime::Mime;
|
||||
@@ -111,24 +111,25 @@ impl Room {
|
||||
}
|
||||
|
||||
pub fn membership(&self) -> Membership {
|
||||
match &self.inner {
|
||||
SdkRoom::Invited(_) => Membership::Invited,
|
||||
SdkRoom::Joined(_) => Membership::Joined,
|
||||
SdkRoom::Left(_) => Membership::Left,
|
||||
match self.inner.state() {
|
||||
RoomState::Invited => Membership::Invited,
|
||||
RoomState::Joined => Membership::Joined,
|
||||
RoomState::Left => Membership::Left,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inviter(&self) -> Option<Arc<RoomMember>> {
|
||||
match &self.inner {
|
||||
SdkRoom::Invited(i) => RUNTIME.block_on(async move {
|
||||
i.invite_details()
|
||||
if self.inner.state() == RoomState::Invited {
|
||||
RUNTIME.block_on(async move {
|
||||
self.inner
|
||||
.invite_details()
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|a| a.inviter)
|
||||
.map(|m| Arc::new(RoomMember::new(m)))
|
||||
}),
|
||||
SdkRoom::Joined(_) => None,
|
||||
SdkRoom::Left(_) => None,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,19 +298,11 @@ impl Room {
|
||||
}
|
||||
|
||||
pub fn send_read_receipt(&self, event_id: String) -> Result<(), ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => {
|
||||
return Err(
|
||||
anyhow!("Can't send read receipts to room that isn't in joined state").into()
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let event_id = EventId::parse(event_id)?;
|
||||
|
||||
RUNTIME.block_on(async move {
|
||||
room.send_single_receipt(ReceiptType::Read, ReceiptThread::Unthreaded, event_id)
|
||||
self.inner
|
||||
.send_single_receipt(ReceiptType::Read, ReceiptThread::Unthreaded, event_id)
|
||||
.await?;
|
||||
Ok(())
|
||||
})
|
||||
@@ -320,15 +313,6 @@ impl Room {
|
||||
fully_read_event_id: String,
|
||||
read_receipt_event_id: Option<String>,
|
||||
) -> Result<(), ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => {
|
||||
return Err(
|
||||
anyhow!("Can't send read markers to room that isn't in joined state").into()
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let fully_read =
|
||||
EventId::parse(fully_read_event_id).context("parsing fully read event ID")?;
|
||||
let read_receipt = read_receipt_event_id
|
||||
@@ -339,7 +323,7 @@ impl Room {
|
||||
Receipts::new().fully_read_marker(fully_read).public_read_receipt(read_receipt);
|
||||
|
||||
RUNTIME.block_on(async move {
|
||||
room.send_multiple_receipts(receipts).await?;
|
||||
self.inner.send_multiple_receipts(receipts).await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@@ -364,11 +348,6 @@ impl Room {
|
||||
in_reply_to_event_id: String,
|
||||
txn_id: Option<String>,
|
||||
) -> Result<(), ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => return Err(anyhow!("Can't send to a room that isn't in joined state").into()),
|
||||
};
|
||||
|
||||
let timeline = match &*RUNTIME.block_on(self.timeline.read()) {
|
||||
Some(t) => Arc::clone(t),
|
||||
None => return Err(anyhow!("Timeline not set up, can't send message").into()),
|
||||
@@ -378,7 +357,8 @@ impl Room {
|
||||
in_reply_to_event_id.as_str().try_into().context("Failed to create EventId.")?;
|
||||
|
||||
let reply_content = RUNTIME.block_on(async move {
|
||||
let timeline_event = room.event(event_id).await.context("Couldn't find event.")?;
|
||||
let timeline_event =
|
||||
self.inner.event(event_id).await.context("Couldn't find event.")?;
|
||||
|
||||
let event_content = timeline_event
|
||||
.event
|
||||
@@ -406,11 +386,6 @@ impl Room {
|
||||
original_event_id: String,
|
||||
txn_id: Option<String>,
|
||||
) -> Result<(), ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => return Err(anyhow!("Can't send to a room that isn't in joined state").into()),
|
||||
};
|
||||
|
||||
let timeline = match &*RUNTIME.block_on(self.timeline.read()) {
|
||||
Some(t) => Arc::clone(t),
|
||||
None => return Err(anyhow!("Timeline not set up, can't send message").into()),
|
||||
@@ -420,7 +395,8 @@ impl Room {
|
||||
original_event_id.as_str().try_into().context("Failed to create EventId.")?;
|
||||
|
||||
let edited_content = RUNTIME.block_on(async move {
|
||||
let timeline_event = room.event(event_id).await.context("Couldn't find event.")?;
|
||||
let timeline_event =
|
||||
self.inner.event(event_id).await.context("Couldn't find event.")?;
|
||||
|
||||
let event_content = timeline_event
|
||||
.event
|
||||
@@ -463,14 +439,9 @@ impl Room {
|
||||
reason: Option<String>,
|
||||
txn_id: Option<String>,
|
||||
) -> Result<(), ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => return Err(anyhow!("Can't redact in a room that isn't in joined state").into()),
|
||||
};
|
||||
|
||||
RUNTIME.block_on(async move {
|
||||
let event_id = EventId::parse(event_id)?;
|
||||
room.redact(&event_id, reason.as_deref(), txn_id.map(Into::into)).await?;
|
||||
self.inner.redact(&event_id, reason.as_deref(), txn_id.map(Into::into)).await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@@ -570,30 +541,16 @@ impl Room {
|
||||
|
||||
/// Sets a new name to the room.
|
||||
pub fn set_name(&self, name: Option<String>) -> Result<(), ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => {
|
||||
return Err(anyhow!("Can't set a name in a room that isn't in joined state").into())
|
||||
}
|
||||
};
|
||||
|
||||
RUNTIME.block_on(async move {
|
||||
room.set_name(name).await?;
|
||||
self.inner.set_name(name).await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets a new topic in the room.
|
||||
pub fn set_topic(&self, topic: String) -> Result<(), ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => {
|
||||
return Err(anyhow!("Can't set a topic in a room that isn't in joined state").into())
|
||||
}
|
||||
};
|
||||
|
||||
RUNTIME.block_on(async move {
|
||||
room.set_room_topic(&topic).await?;
|
||||
self.inner.set_room_topic(&topic).await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@@ -611,50 +568,27 @@ impl Room {
|
||||
/// * `data` - The raw data that will be uploaded to the homeserver's
|
||||
/// content repository
|
||||
pub fn upload_avatar(&self, mime_type: String, data: Vec<u8>) -> Result<(), ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => {
|
||||
return Err(
|
||||
anyhow!("Can't set a avatar in a room that isn't in joined state").into()
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
RUNTIME.block_on(async move {
|
||||
let mime: Mime = mime_type.parse()?;
|
||||
// TODO: We could add an FFI ImageInfo struct in the future
|
||||
room.upload_avatar(&mime, data, None).await?;
|
||||
self.inner.upload_avatar(&mime, data, None).await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Removes the current room avatar
|
||||
pub fn remove_avatar(&self) -> Result<(), ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => {
|
||||
return Err(
|
||||
anyhow!("Can't remove a avatar in a room that isn't in joined state").into()
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
RUNTIME.block_on(async move {
|
||||
room.remove_avatar().await?;
|
||||
self.inner.remove_avatar().await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn invite_user_by_id(&self, user_id: String) -> Result<(), ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(joined_room) => joined_room.clone(),
|
||||
_ => return Err(anyhow!("Can't invite user to room that isn't in joined state").into()),
|
||||
};
|
||||
|
||||
RUNTIME.block_on(async move {
|
||||
let user = <&UserId>::try_from(user_id.as_str())
|
||||
.context("Could not create user from string")?;
|
||||
room.invite_user_by_id(user).await?;
|
||||
self.inner.invite_user_by_id(user).await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@@ -869,43 +803,23 @@ impl Room {
|
||||
}
|
||||
|
||||
pub async fn can_user_redact(&self, user_id: String) -> Result<bool, ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => return Err(anyhow!("Can't check permissions for non joined rooms").into()),
|
||||
};
|
||||
|
||||
let user_id = UserId::parse(&user_id)?;
|
||||
Ok(room.can_user_redact(&user_id).await?)
|
||||
Ok(self.inner.can_user_redact(&user_id).await?)
|
||||
}
|
||||
|
||||
pub async fn can_user_ban(&self, user_id: String) -> Result<bool, ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => return Err(anyhow!("Can't check permissions for non joined rooms").into()),
|
||||
};
|
||||
|
||||
let user_id = UserId::parse(&user_id)?;
|
||||
Ok(room.can_user_ban(&user_id).await?)
|
||||
Ok(self.inner.can_user_ban(&user_id).await?)
|
||||
}
|
||||
|
||||
pub async fn can_user_invite(&self, user_id: String) -> Result<bool, ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => return Err(anyhow!("Can't check permissions for non joined rooms").into()),
|
||||
};
|
||||
|
||||
let user_id = UserId::parse(&user_id)?;
|
||||
Ok(room.can_user_invite(&user_id).await?)
|
||||
Ok(self.inner.can_user_invite(&user_id).await?)
|
||||
}
|
||||
|
||||
pub async fn can_user_kick(&self, user_id: String) -> Result<bool, ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => return Err(anyhow!("Can't check permissions for non joined rooms").into()),
|
||||
};
|
||||
|
||||
let user_id = UserId::parse(&user_id)?;
|
||||
Ok(room.can_user_kick(&user_id).await?)
|
||||
Ok(self.inner.can_user_kick(&user_id).await?)
|
||||
}
|
||||
|
||||
pub async fn can_user_send_state(
|
||||
@@ -913,13 +827,8 @@ impl Room {
|
||||
user_id: String,
|
||||
state_event: StateEventType,
|
||||
) -> Result<bool, ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => return Err(anyhow!("Can't check permissions for non joined rooms").into()),
|
||||
};
|
||||
|
||||
let user_id = UserId::parse(&user_id)?;
|
||||
Ok(room.can_user_send_state(&user_id, state_event.into()).await?)
|
||||
Ok(self.inner.can_user_send_state(&user_id, state_event.into()).await?)
|
||||
}
|
||||
|
||||
pub async fn can_user_send_message(
|
||||
@@ -927,26 +836,16 @@ impl Room {
|
||||
user_id: String,
|
||||
message: MessageLikeEventType,
|
||||
) -> Result<bool, ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => return Err(anyhow!("Can't check permissions for non joined rooms").into()),
|
||||
};
|
||||
|
||||
let user_id = UserId::parse(&user_id)?;
|
||||
Ok(room.can_user_send_message(&user_id, message.into()).await?)
|
||||
Ok(self.inner.can_user_send_message(&user_id, message.into()).await?)
|
||||
}
|
||||
|
||||
pub async fn can_user_trigger_room_notification(
|
||||
&self,
|
||||
user_id: String,
|
||||
) -> Result<bool, ClientError> {
|
||||
let room = match &self.inner {
|
||||
SdkRoom::Joined(j) => j.clone(),
|
||||
_ => return Err(anyhow!("Can't check permissions for non joined rooms").into()),
|
||||
};
|
||||
|
||||
let user_id = UserId::parse(&user_id)?;
|
||||
Ok(room.can_user_trigger_room_notification(&user_id).await?)
|
||||
Ok(self.inner.can_user_trigger_room_notification(&user_id).await?)
|
||||
}
|
||||
|
||||
pub fn own_user_id(&self) -> String {
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use matrix_sdk::{room::Room, Client};
|
||||
use matrix_sdk_base::StoreError;
|
||||
use matrix_sdk::Client;
|
||||
use matrix_sdk_base::{RoomState, StoreError};
|
||||
use ruma::{events::AnySyncTimelineEvent, EventId, RoomId};
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -140,8 +140,8 @@ impl NotificationClient {
|
||||
}
|
||||
}
|
||||
|
||||
let sender = match &room {
|
||||
Room::Invited(invited) => invited.invite_details().await?.inviter,
|
||||
let sender = match room.state() {
|
||||
RoomState::Invited => room.invite_details().await?.inviter,
|
||||
_ => room.get_member(raw_event.sender()).await?,
|
||||
};
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ struct RoomInner {
|
||||
sliding_sync_room: SlidingSyncRoom,
|
||||
|
||||
/// The underlying client room.
|
||||
room: matrix_sdk::room::Room,
|
||||
room: matrix_sdk::room::Common,
|
||||
|
||||
/// The timeline of the room.
|
||||
timeline: AsyncOnceCell<Arc<Timeline>>,
|
||||
@@ -89,8 +89,8 @@ impl Room {
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the underlying [`matrix_sdk::room::Room`].
|
||||
pub fn inner_room(&self) -> &matrix_sdk::room::Room {
|
||||
/// Get the underlying [`matrix_sdk::room::Common`].
|
||||
pub fn inner_room(&self) -> &matrix_sdk::room::Common {
|
||||
&self.inner.room
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::{
|
||||
};
|
||||
|
||||
use eyeball::{SharedObservable, Subscriber};
|
||||
use matrix_sdk::{attachment::AttachmentConfig, room::Room, TransmissionProgress};
|
||||
use matrix_sdk::{attachment::AttachmentConfig, TransmissionProgress};
|
||||
use mime::Mime;
|
||||
|
||||
use super::{Error, Timeline};
|
||||
@@ -47,10 +47,6 @@ impl<'a> IntoFuture for SendAttachment<'a> {
|
||||
fn into_future(self) -> Self::IntoFuture {
|
||||
let Self { timeline, url, mime_type, config, send_progress } = self;
|
||||
Box::pin(async move {
|
||||
let Room::Joined(room) = Room::from(timeline.room().clone()) else {
|
||||
return Err(Error::RoomNotJoined);
|
||||
};
|
||||
|
||||
let body = Path::new(&url)
|
||||
.file_name()
|
||||
.ok_or(Error::InvalidAttachmentFileName)?
|
||||
@@ -58,7 +54,9 @@ impl<'a> IntoFuture for SendAttachment<'a> {
|
||||
.expect("path was created from UTF-8 string, hence filename part is UTF-8 too");
|
||||
let data = fs::read(&url).map_err(|_| Error::InvalidAttachmentData)?;
|
||||
|
||||
room.send_attachment(body, &mime_type, data, config)
|
||||
timeline
|
||||
.room()
|
||||
.send_attachment(body, &mime_type, data, config)
|
||||
.with_send_progress_observable(send_progress)
|
||||
.await
|
||||
.map_err(|_| Error::FailedSendingAttachment)?;
|
||||
|
||||
@@ -27,9 +27,10 @@ use matrix_sdk::{
|
||||
attachment::AttachmentConfig,
|
||||
event_handler::EventHandlerHandle,
|
||||
executor::JoinHandle,
|
||||
room::{self, MessagesOptions, Receipts, Room},
|
||||
room::{self, MessagesOptions, Receipts},
|
||||
Client, Result,
|
||||
};
|
||||
use matrix_sdk_base::RoomState;
|
||||
use mime::Mime;
|
||||
use pin_project_lite::pin_project;
|
||||
use ruma::{
|
||||
@@ -135,13 +136,6 @@ impl Timeline {
|
||||
self.inner.room()
|
||||
}
|
||||
|
||||
fn joined_room(&self) -> Result<room::Common, Error> {
|
||||
match Room::from(self.room().clone()) {
|
||||
Room::Joined(room) => Ok(room),
|
||||
_ => Err(Error::RoomNotJoined),
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear all timeline items, and reset pagination parameters.
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
pub async fn clear(&self) {
|
||||
@@ -408,13 +402,13 @@ impl Timeline {
|
||||
|
||||
/// Redact a reaction event from the homeserver
|
||||
async fn redact_reaction(&self, event_id: &EventId) -> ReactionToggleResult {
|
||||
let room = self.room();
|
||||
if room.state() != RoomState::Joined {
|
||||
return ReactionToggleResult::RedactFailure { event_id: event_id.to_owned() };
|
||||
}
|
||||
|
||||
let txn_id = TransactionId::new();
|
||||
let no_reason = RoomRedactionEventContent::default();
|
||||
let room = self.joined_room();
|
||||
|
||||
let Ok(room) = room else {
|
||||
return ReactionToggleResult::RedactFailure { event_id: event_id.to_owned() };
|
||||
};
|
||||
|
||||
let response = room.redact(event_id, no_reason.reason.as_deref(), Some(txn_id)).await;
|
||||
|
||||
@@ -430,8 +424,10 @@ impl Timeline {
|
||||
annotation: &Annotation,
|
||||
txn_id: OwnedTransactionId,
|
||||
) -> ReactionToggleResult {
|
||||
let room = self.joined_room();
|
||||
let Ok(room) = room else { return ReactionToggleResult::AddFailure { txn_id } };
|
||||
let room = self.room();
|
||||
if room.state() != RoomState::Joined {
|
||||
return ReactionToggleResult::AddFailure { txn_id };
|
||||
}
|
||||
|
||||
let event_content =
|
||||
AnyMessageLikeEventContent::Reaction(ReactionEventContent::from(annotation.clone()));
|
||||
@@ -605,12 +601,7 @@ impl Timeline {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let Room::Joined(room) = Room::from(self.room().clone()) else {
|
||||
// FIXME: Probably not exactly right
|
||||
return Err(matrix_sdk::Error::InconsistentState);
|
||||
};
|
||||
|
||||
room.send_single_receipt(receipt_type, thread, event_id).await
|
||||
self.room().send_single_receipt(receipt_type, thread, event_id).await
|
||||
}
|
||||
|
||||
/// Send the given receipts.
|
||||
@@ -659,12 +650,7 @@ impl Timeline {
|
||||
}
|
||||
}
|
||||
|
||||
let Room::Joined(room) = Room::from(self.room().clone()) else {
|
||||
// FIXME: Probably not exactly right
|
||||
return Err(matrix_sdk::Error::InconsistentState);
|
||||
};
|
||||
|
||||
room.send_multiple_receipts(receipts).await
|
||||
self.room().send_multiple_receipts(receipts).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,9 @@ use std::{
|
||||
use futures_util::future::Either;
|
||||
use matrix_sdk::{
|
||||
executor::{spawn, JoinError, JoinHandle},
|
||||
room::{self, Room},
|
||||
room,
|
||||
};
|
||||
use matrix_sdk_base::RoomState;
|
||||
use ruma::{events::AnyMessageLikeEventContent, OwnedTransactionId};
|
||||
use tokio::{select, sync::mpsc::Receiver};
|
||||
use tracing::{debug, error, info, instrument, trace, warn};
|
||||
@@ -103,22 +104,19 @@ async fn handle_message(
|
||||
timeline_inner: &TimelineInner,
|
||||
) {
|
||||
if queue.is_empty() && send_task.is_idle() {
|
||||
match Room::from(room) {
|
||||
Room::Joined(room) => {
|
||||
send_task.start(room, timeline_inner.clone(), msg);
|
||||
}
|
||||
_ => {
|
||||
info!("Refusing to send message, room is not joined");
|
||||
timeline_inner
|
||||
.update_event_send_state(
|
||||
&msg.txn_id,
|
||||
EventSendState::SendingFailed {
|
||||
// FIXME: Probably not exactly right
|
||||
error: Arc::new(matrix_sdk::Error::InconsistentState),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
}
|
||||
if room.state() == RoomState::Joined {
|
||||
send_task.start(room, timeline_inner.clone(), msg);
|
||||
} else {
|
||||
info!("Refusing to send message, room is not joined");
|
||||
timeline_inner
|
||||
.update_event_send_state(
|
||||
&msg.txn_id,
|
||||
EventSendState::SendingFailed {
|
||||
// FIXME: Probably not exactly right
|
||||
error: Arc::new(matrix_sdk::Error::InconsistentState),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
}
|
||||
} else {
|
||||
queue.push_back(msg);
|
||||
|
||||
@@ -104,10 +104,10 @@ type NotificationHandlerFut = Pin<Box<dyn Future<Output = ()>>>;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
type NotificationHandlerFn =
|
||||
Box<dyn Fn(Notification, room::Room, Client) -> NotificationHandlerFut + Send + Sync>;
|
||||
Box<dyn Fn(Notification, room::Common, Client) -> NotificationHandlerFut + Send + Sync>;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
type NotificationHandlerFn =
|
||||
Box<dyn Fn(Notification, room::Room, Client) -> NotificationHandlerFut>;
|
||||
Box<dyn Fn(Notification, room::Common, Client) -> NotificationHandlerFut>;
|
||||
|
||||
/// Enum controlling if a loop running callbacks should continue or abort.
|
||||
///
|
||||
@@ -477,8 +477,8 @@ impl Client {
|
||||
/// the event handler being skipped and an error being logged. The following
|
||||
/// context argument types are only available for a subset of event types:
|
||||
///
|
||||
/// * [`Room`][room::Room] is only available for room-specific events, i.e.
|
||||
/// not for events like global account data events or presence events.
|
||||
/// * [`room::Common`] is only available for room-specific events, i.e. not
|
||||
/// for events like global account data events or presence events.
|
||||
///
|
||||
/// You can provide custom context via
|
||||
/// [`add_event_handler_context`](Client::add_event_handler_context) and
|
||||
@@ -495,7 +495,7 @@ impl Client {
|
||||
/// use matrix_sdk::{
|
||||
/// deserialized_responses::EncryptionInfo,
|
||||
/// event_handler::Ctx,
|
||||
/// room::Room,
|
||||
/// room::Common,
|
||||
/// ruma::{
|
||||
/// events::{
|
||||
/// macros::EventContent,
|
||||
@@ -518,12 +518,12 @@ impl Client {
|
||||
/// # .unwrap();
|
||||
/// #
|
||||
/// client.add_event_handler(
|
||||
/// |ev: SyncRoomMessageEvent, room: Room, client: Client| async move {
|
||||
/// |ev: SyncRoomMessageEvent, room: Common, client: Client| async move {
|
||||
/// // Common usage: Room event plus room and client.
|
||||
/// },
|
||||
/// );
|
||||
/// client.add_event_handler(
|
||||
/// |ev: SyncRoomMessageEvent, room: Room, encryption_info: Option<EncryptionInfo>| {
|
||||
/// |ev: SyncRoomMessageEvent, room: Common, encryption_info: Option<EncryptionInfo>| {
|
||||
/// async move {
|
||||
/// // An `Option<EncryptionInfo>` parameter lets you distinguish between
|
||||
/// // unencrypted events and events that were decrypted by the SDK.
|
||||
@@ -531,7 +531,7 @@ impl Client {
|
||||
/// },
|
||||
/// );
|
||||
/// client.add_event_handler(
|
||||
/// |ev: SyncRoomMessageEvent, room: Room, push_actions: Vec<Action>| {
|
||||
/// |ev: SyncRoomMessageEvent, room: Common, push_actions: Vec<Action>| {
|
||||
/// async move {
|
||||
/// // A `Vec<Action>` parameter allows you to know which push actions
|
||||
/// // are applicable for an event. For example, an event with
|
||||
@@ -570,7 +570,7 @@ impl Client {
|
||||
/// expires_at: MilliSecondsSinceUnixEpoch,
|
||||
/// }
|
||||
///
|
||||
/// client.add_event_handler(|ev: SyncTokenEvent, room: Room| async move {
|
||||
/// client.add_event_handler(|ev: SyncTokenEvent, room: Common| async move {
|
||||
/// todo!("Display the token");
|
||||
/// });
|
||||
///
|
||||
@@ -699,7 +699,7 @@ impl Client {
|
||||
///
|
||||
/// ```
|
||||
/// use matrix_sdk::{
|
||||
/// event_handler::Ctx, room::Room,
|
||||
/// event_handler::Ctx, room::Common,
|
||||
/// ruma::events::room::message::SyncRoomMessageEvent,
|
||||
/// };
|
||||
/// # #[derive(Clone)]
|
||||
@@ -719,7 +719,7 @@ impl Client {
|
||||
///
|
||||
/// client.add_event_handler_context(my_gui_handle.clone());
|
||||
/// client.add_event_handler(
|
||||
/// |ev: SyncRoomMessageEvent, room: Room, gui_handle: Ctx<SomeType>| {
|
||||
/// |ev: SyncRoomMessageEvent, room: Common, gui_handle: Ctx<SomeType>| {
|
||||
/// async move {
|
||||
/// // gui_handle.send(DisplayMessage { message: ev });
|
||||
/// }
|
||||
@@ -738,10 +738,10 @@ impl Client {
|
||||
///
|
||||
/// Similar to [`Client::add_event_handler`], but only allows functions
|
||||
/// or closures with exactly the three arguments [`Notification`],
|
||||
/// [`room::Room`], [`Client`] for now.
|
||||
/// [`room::Common`], [`Client`] for now.
|
||||
pub async fn register_notification_handler<H, Fut>(&self, handler: H) -> &Self
|
||||
where
|
||||
H: Fn(Notification, room::Room, Client) -> Fut
|
||||
H: Fn(Notification, room::Common, Client) -> Fut
|
||||
+ SendOutsideWasm
|
||||
+ SyncOutsideWasm
|
||||
+ 'static,
|
||||
@@ -778,20 +778,20 @@ impl Client {
|
||||
/// Get all the rooms the client knows about.
|
||||
///
|
||||
/// This will return the list of joined, invited, and left rooms.
|
||||
pub fn rooms(&self) -> Vec<room::Room> {
|
||||
pub fn rooms(&self) -> Vec<room::Common> {
|
||||
self.base_client()
|
||||
.get_rooms()
|
||||
.into_iter()
|
||||
.map(|room| room::Common::new(self.clone(), room).into())
|
||||
.map(|room| room::Common::new(self.clone(), room))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Get all the rooms the client knows about, filtered by room state.
|
||||
pub fn rooms_filtered(&self, filter: RoomStateFilter) -> Vec<room::Room> {
|
||||
pub fn rooms_filtered(&self, filter: RoomStateFilter) -> Vec<room::Common> {
|
||||
self.base_client()
|
||||
.get_rooms_filtered(filter)
|
||||
.into_iter()
|
||||
.map(|room| room::Common::new(self.clone(), room).into())
|
||||
.map(|room| room::Common::new(self.clone(), room))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -827,10 +827,8 @@ impl Client {
|
||||
/// # Arguments
|
||||
///
|
||||
/// `room_id` - The unique id of the room that should be fetched.
|
||||
pub fn get_room(&self, room_id: &RoomId) -> Option<room::Room> {
|
||||
self.base_client()
|
||||
.get_room(room_id)
|
||||
.map(|room| room::Common::new(self.clone(), room).into())
|
||||
pub fn get_room(&self, room_id: &RoomId) -> Option<room::Common> {
|
||||
self.base_client().get_room(room_id).map(|room| room::Common::new(self.clone(), room))
|
||||
}
|
||||
|
||||
/// Resolve a room alias to a room id and a list of servers which know
|
||||
|
||||
@@ -49,7 +49,7 @@ impl EventHandlerContext for EventHandlerHandle {
|
||||
/// Trying to use it in the event handler for another event, for example a
|
||||
/// global account data or presence event, will result in the event handler
|
||||
/// being skipped and an error getting logged.
|
||||
impl EventHandlerContext for room::Room {
|
||||
impl EventHandlerContext for room::Common {
|
||||
fn from_data(data: &EventHandlerData<'_>) -> Option<Self> {
|
||||
data.room.clone()
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ where
|
||||
#[derive(Debug)]
|
||||
pub struct EventHandlerData<'a> {
|
||||
client: Client,
|
||||
room: Option<room::Room>,
|
||||
room: Option<room::Common>,
|
||||
raw: &'a RawJsonValue,
|
||||
encryption_info: Option<&'a EncryptionInfo>,
|
||||
push_actions: &'a [Action],
|
||||
@@ -328,7 +328,7 @@ impl Client {
|
||||
pub(crate) async fn handle_sync_events<T>(
|
||||
&self,
|
||||
kind: HandlerKind,
|
||||
room: Option<&room::Room>,
|
||||
room: Option<&room::Common>,
|
||||
events: &[Raw<T>],
|
||||
) -> serde_json::Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
@@ -347,7 +347,7 @@ impl Client {
|
||||
|
||||
pub(crate) async fn handle_sync_state_events(
|
||||
&self,
|
||||
room: Option<&room::Room>,
|
||||
room: Option<&room::Common>,
|
||||
state_events: &[Raw<AnySyncStateEvent>],
|
||||
) -> serde_json::Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
@@ -375,7 +375,7 @@ impl Client {
|
||||
|
||||
pub(crate) async fn handle_sync_timeline_events(
|
||||
&self,
|
||||
room: Option<&room::Room>,
|
||||
room: Option<&room::Common>,
|
||||
timeline_events: &[SyncTimelineEvent],
|
||||
) -> serde_json::Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
@@ -441,7 +441,7 @@ impl Client {
|
||||
#[instrument(skip_all, fields(?event_kind, ?event_type, room_id))]
|
||||
async fn call_event_handlers(
|
||||
&self,
|
||||
room: Option<&room::Room>,
|
||||
room: Option<&room::Common>,
|
||||
raw: &RawJsonValue,
|
||||
event_kind: HandlerKind,
|
||||
event_type: &str,
|
||||
@@ -571,7 +571,7 @@ mod tests {
|
||||
|
||||
use crate::{
|
||||
event_handler::Ctx,
|
||||
room::Room,
|
||||
room,
|
||||
test_utils::{logged_in_client, no_retry_test_client},
|
||||
Client,
|
||||
};
|
||||
@@ -587,7 +587,7 @@ mod tests {
|
||||
|
||||
client.add_event_handler({
|
||||
let member_count = member_count.clone();
|
||||
move |_ev: OriginalSyncRoomMemberEvent, _room: Room| {
|
||||
move |_ev: OriginalSyncRoomMemberEvent, _room: room::Common| {
|
||||
member_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
@@ -601,7 +601,7 @@ mod tests {
|
||||
});
|
||||
client.add_event_handler({
|
||||
let power_levels_count = power_levels_count.clone();
|
||||
move |_ev: OriginalSyncRoomPowerLevelsEvent, _client: Client, _room: Room| {
|
||||
move |_ev: OriginalSyncRoomPowerLevelsEvent, _client: Client, _room: room::Common| {
|
||||
power_levels_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
@@ -683,14 +683,14 @@ mod tests {
|
||||
// Room event handlers for member events in both rooms
|
||||
client.add_room_event_handler(room_id_a, {
|
||||
let member_count = member_count.clone();
|
||||
move |_ev: OriginalSyncRoomMemberEvent, _room: Room| {
|
||||
move |_ev: OriginalSyncRoomMemberEvent, _room: room::Common| {
|
||||
member_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
});
|
||||
client.add_room_event_handler(room_id_b, {
|
||||
let member_count = member_count.clone();
|
||||
move |_ev: OriginalSyncRoomMemberEvent, _room: Room| {
|
||||
move |_ev: OriginalSyncRoomMemberEvent, _room: room::Common| {
|
||||
member_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
@@ -699,7 +699,7 @@ mod tests {
|
||||
// Power levels event handlers for member events in room A
|
||||
client.add_room_event_handler(room_id_a, {
|
||||
let power_levels_count = power_levels_count.clone();
|
||||
move |_ev: OriginalSyncRoomPowerLevelsEvent, _client: Client, _room: Room| {
|
||||
move |_ev: OriginalSyncRoomPowerLevelsEvent, _client: Client, _room: room::Common| {
|
||||
power_levels_count.fetch_add(1, SeqCst);
|
||||
future::ready(())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
//! High-level room API
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::RoomState;
|
||||
|
||||
mod common;
|
||||
@@ -15,36 +13,3 @@ pub use self::{
|
||||
member::RoomMember,
|
||||
messages::{Messages, MessagesOptions},
|
||||
};
|
||||
|
||||
/// An enum that abstracts over the different states a room can be in.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Room {
|
||||
/// The room in the `join` state.
|
||||
Joined(Common),
|
||||
/// The room in the `left` state.
|
||||
Left(Common),
|
||||
/// The room in the `invited` state.
|
||||
Invited(Common),
|
||||
}
|
||||
|
||||
impl Deref for Room {
|
||||
type Target = Common;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
Self::Joined(room) => room,
|
||||
Self::Left(room) => room,
|
||||
Self::Invited(room) => room,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Common> for Room {
|
||||
fn from(room: Common) -> Self {
|
||||
match room.state() {
|
||||
RoomState::Joined => Self::Joined(room),
|
||||
RoomState::Left => Self::Left(room),
|
||||
RoomState::Invited => Self::Invited(room),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ impl SlidingSyncRoom {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SlidingSyncRoomInner {
|
||||
/// The client, used to fetch [`Room`][crate::room::Room].
|
||||
/// The client, used to fetch [`room::Common`][crate::room::Common].
|
||||
client: Client,
|
||||
|
||||
/// The room ID.
|
||||
|
||||
@@ -195,7 +195,7 @@ impl Client {
|
||||
};
|
||||
|
||||
self.send_room_update(room_id, || RoomUpdate::Joined {
|
||||
room: (*room).clone(),
|
||||
room: room.clone(),
|
||||
updates: room_info.clone(),
|
||||
});
|
||||
|
||||
@@ -222,7 +222,7 @@ impl Client {
|
||||
};
|
||||
|
||||
self.send_room_update(room_id, || RoomUpdate::Left {
|
||||
room: (*room).clone(),
|
||||
room: room.clone(),
|
||||
updates: room_info.clone(),
|
||||
});
|
||||
|
||||
@@ -241,7 +241,7 @@ impl Client {
|
||||
};
|
||||
|
||||
self.send_room_update(room_id, || RoomUpdate::Invited {
|
||||
room: (*room).clone(),
|
||||
room: room.clone(),
|
||||
updates: room_info.clone(),
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::env;
|
||||
use matrix_sdk_appservice::{
|
||||
matrix_sdk::{
|
||||
event_handler::Ctx,
|
||||
room::Room,
|
||||
room,
|
||||
ruma::{
|
||||
events::room::member::{MembershipState, OriginalSyncRoomMemberEvent},
|
||||
UserId,
|
||||
@@ -16,7 +16,7 @@ use tracing::trace;
|
||||
|
||||
pub async fn handle_room_member(
|
||||
appservice: AppService,
|
||||
room: Room,
|
||||
room: room::Common,
|
||||
event: OriginalSyncRoomMemberEvent,
|
||||
) -> Result<()> {
|
||||
if !appservice.user_id_is_in_namespace(&event.state_key) {
|
||||
@@ -68,7 +68,9 @@ pub async fn main() -> anyhow::Result<()> {
|
||||
|
||||
user.add_event_handler_context(appservice.clone());
|
||||
user.add_event_handler(
|
||||
move |event: OriginalSyncRoomMemberEvent, room: Room, Ctx(appservice): Ctx<AppService>| {
|
||||
move |event: OriginalSyncRoomMemberEvent,
|
||||
room: room::Common,
|
||||
Ctx(appservice): Ctx<AppService>| {
|
||||
handle_room_member(appservice, room, event)
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,41 +1,43 @@
|
||||
use std::{env, process::exit};
|
||||
|
||||
use matrix_sdk::{
|
||||
config::SyncSettings, room::Room, ruma::events::room::member::StrippedRoomMemberEvent, Client,
|
||||
config::SyncSettings, room, ruma::events::room::member::StrippedRoomMemberEvent, Client,
|
||||
RoomState,
|
||||
};
|
||||
use tokio::time::{sleep, Duration};
|
||||
|
||||
async fn on_stripped_state_member(
|
||||
room_member: StrippedRoomMemberEvent,
|
||||
client: Client,
|
||||
room: Room,
|
||||
room: room::Common,
|
||||
) {
|
||||
if room_member.state_key != client.user_id().unwrap() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Room::Invited(room) = room {
|
||||
tokio::spawn(async move {
|
||||
println!("Autojoining room {}", room.room_id());
|
||||
let mut delay = 2;
|
||||
|
||||
while let Err(err) = room.join().await {
|
||||
// retry autojoin due to synapse sending invites, before the
|
||||
// invited user can join for more information see
|
||||
// https://github.com/matrix-org/synapse/issues/4345
|
||||
eprintln!("Failed to join room {} ({err:?}), retrying in {delay}s", room.room_id());
|
||||
|
||||
sleep(Duration::from_secs(delay)).await;
|
||||
delay *= 2;
|
||||
|
||||
if delay > 3600 {
|
||||
eprintln!("Can't join room {} ({err:?})", room.room_id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
println!("Successfully joined room {}", room.room_id());
|
||||
});
|
||||
if room.state() != RoomState::Joined {
|
||||
return;
|
||||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
println!("Autojoining room {}", room.room_id());
|
||||
let mut delay = 2;
|
||||
|
||||
while let Err(err) = room.join().await {
|
||||
// retry autojoin due to synapse sending invites, before the
|
||||
// invited user can join for more information see
|
||||
// https://github.com/matrix-org/synapse/issues/4345
|
||||
eprintln!("Failed to join room {} ({err:?}), retrying in {delay}s", room.room_id());
|
||||
|
||||
sleep(Duration::from_secs(delay)).await;
|
||||
delay *= 2;
|
||||
|
||||
if delay > 3600 {
|
||||
eprintln!("Can't join room {} ({err:?})", room.room_id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
println!("Successfully joined room {}", room.room_id());
|
||||
});
|
||||
}
|
||||
|
||||
async fn login_and_sync(
|
||||
|
||||
@@ -2,31 +2,32 @@ use std::{env, process::exit};
|
||||
|
||||
use matrix_sdk::{
|
||||
config::SyncSettings,
|
||||
room::Room,
|
||||
room,
|
||||
ruma::events::room::message::{
|
||||
MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent,
|
||||
},
|
||||
Client,
|
||||
Client, RoomState,
|
||||
};
|
||||
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) {
|
||||
if let Room::Joined(room) = room {
|
||||
let MessageType::Text(text_content) = event.content.msgtype else {
|
||||
return;
|
||||
};
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: room::Common) {
|
||||
if room.state() != RoomState::Joined {
|
||||
return;
|
||||
}
|
||||
let MessageType::Text(text_content) = event.content.msgtype else {
|
||||
return;
|
||||
};
|
||||
|
||||
if text_content.body.contains("!party") {
|
||||
let content = RoomMessageEventContent::text_plain("🎉🎊🥳 let's PARTY!! 🥳🎊🎉");
|
||||
if text_content.body.contains("!party") {
|
||||
let content = RoomMessageEventContent::text_plain("🎉🎊🥳 let's PARTY!! 🥳🎊🎉");
|
||||
|
||||
println!("sending");
|
||||
println!("sending");
|
||||
|
||||
// send our message to the room we found the "!party" command in
|
||||
// the last parameter is an optional transaction id which we don't
|
||||
// care about.
|
||||
room.send(content, None).await.unwrap();
|
||||
// send our message to the room we found the "!party" command in
|
||||
// the last parameter is an optional transaction id which we don't
|
||||
// care about.
|
||||
room.send(content, None).await.unwrap();
|
||||
|
||||
println!("message sent");
|
||||
}
|
||||
println!("message sent");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use std::{env, process::exit};
|
||||
|
||||
use matrix_sdk::{
|
||||
config::SyncSettings,
|
||||
room::Room,
|
||||
room,
|
||||
ruma::{
|
||||
events::{
|
||||
macros::EventContent,
|
||||
@@ -24,7 +24,7 @@ use matrix_sdk::{
|
||||
},
|
||||
OwnedEventId,
|
||||
},
|
||||
Client,
|
||||
Client, RoomState,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::time::{sleep, Duration};
|
||||
@@ -50,8 +50,10 @@ pub struct AckEventContent {
|
||||
// use that for `on_ping_event`.
|
||||
|
||||
// we want to start the ping-ack-flow on "!ping" messages.
|
||||
async fn on_regular_room_message(event: OriginalSyncRoomMessageEvent, room: Room) {
|
||||
let Room::Joined(room) = room else { return };
|
||||
async fn on_regular_room_message(event: OriginalSyncRoomMessageEvent, room: room::Common) {
|
||||
if room.state() != RoomState::Joined {
|
||||
return;
|
||||
}
|
||||
let MessageType::Text(text_content) = event.content.msgtype else { return };
|
||||
|
||||
if text_content.body.contains("!ping") {
|
||||
@@ -64,17 +66,19 @@ async fn on_regular_room_message(event: OriginalSyncRoomMessageEvent, room: Room
|
||||
}
|
||||
|
||||
// call this on any PingEvent we receive
|
||||
async fn on_ping_event(event: SyncPingEvent, room: Room) {
|
||||
if let Room::Joined(room) = room {
|
||||
let event_id = event.event_id().to_owned();
|
||||
|
||||
// Send an ack with the event_id of the ping, as our 'protocol' demands
|
||||
let content = AckEventContent { ping_id: event_id };
|
||||
println!("sending ack");
|
||||
room.send(content, None).await.unwrap();
|
||||
|
||||
println!("ack sent");
|
||||
async fn on_ping_event(event: SyncPingEvent, room: room::Common) {
|
||||
if room.state() != RoomState::Joined {
|
||||
return;
|
||||
}
|
||||
|
||||
let event_id = event.event_id().to_owned();
|
||||
|
||||
// Send an ack with the event_id of the ping, as our 'protocol' demands
|
||||
let content = AckEventContent { ping_id: event_id };
|
||||
println!("sending ack");
|
||||
room.send(content, None).await.unwrap();
|
||||
|
||||
println!("ack sent");
|
||||
}
|
||||
|
||||
// once logged in, this is called where we configure the handlers
|
||||
@@ -120,36 +124,34 @@ async fn login_and_sync(
|
||||
async fn on_stripped_state_member(
|
||||
room_member: StrippedRoomMemberEvent,
|
||||
client: Client,
|
||||
room: Room,
|
||||
room: room::Common,
|
||||
) {
|
||||
if room_member.state_key != client.user_id().unwrap() {
|
||||
// the invite we've seen isn't for us, but for someone else. ignore
|
||||
return;
|
||||
}
|
||||
|
||||
// looks like the room is an invited room, let's attempt to join then
|
||||
if let Room::Invited(room) = room {
|
||||
tokio::spawn(async move {
|
||||
println!("Autojoining room {}", room.room_id());
|
||||
let mut delay = 2;
|
||||
tokio::spawn(async move {
|
||||
println!("Autojoining room {}", room.room_id());
|
||||
let mut delay = 2;
|
||||
|
||||
while let Err(err) = room.join().await {
|
||||
// retry autojoin due to synapse sending invites, before the
|
||||
// invited user can join for more information see
|
||||
// https://github.com/matrix-org/synapse/issues/4345
|
||||
eprintln!("Failed to join room {} ({err:?}), retrying in {delay}s", room.room_id());
|
||||
while let Err(err) = room.join().await {
|
||||
// retry autojoin due to synapse sending invites, before the
|
||||
// invited user can join for more information see
|
||||
// https://github.com/matrix-org/synapse/issues/4345
|
||||
eprintln!("Failed to join room {} ({err:?}), retrying in {delay}s", room.room_id());
|
||||
|
||||
sleep(Duration::from_secs(delay)).await;
|
||||
delay *= 2;
|
||||
sleep(Duration::from_secs(delay)).await;
|
||||
delay *= 2;
|
||||
|
||||
if delay > 3600 {
|
||||
eprintln!("Can't join room {} ({err:?})", room.room_id());
|
||||
break;
|
||||
}
|
||||
if delay > 3600 {
|
||||
eprintln!("Can't join room {} ({err:?})", room.room_id());
|
||||
break;
|
||||
}
|
||||
println!("Successfully joined room {}", room.room_id());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
println!("Successfully joined room {}", room.room_id());
|
||||
});
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
|
||||
@@ -14,12 +14,12 @@ use std::{env, process::exit};
|
||||
|
||||
use matrix_sdk::{
|
||||
config::SyncSettings,
|
||||
room::Room,
|
||||
room,
|
||||
ruma::events::room::{
|
||||
member::StrippedRoomMemberEvent,
|
||||
message::{MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent},
|
||||
},
|
||||
Client,
|
||||
Client, RoomState,
|
||||
};
|
||||
use tokio::time::{sleep, Duration};
|
||||
|
||||
@@ -108,40 +108,37 @@ async fn login_and_sync(
|
||||
async fn on_stripped_state_member(
|
||||
room_member: StrippedRoomMemberEvent,
|
||||
client: Client,
|
||||
room: Room,
|
||||
room: room::Common,
|
||||
) {
|
||||
if room_member.state_key != client.user_id().unwrap() {
|
||||
// the invite we've seen isn't for us, but for someone else. ignore
|
||||
return;
|
||||
}
|
||||
|
||||
// looks like the room is an invited room, let's attempt to join then
|
||||
if let Room::Invited(room) = room {
|
||||
// The event handlers are called before the next sync begins, but
|
||||
// methods that change the state of a room (joining, leaving a room)
|
||||
// wait for the sync to return the new room state so we need to spawn
|
||||
// a new task for them.
|
||||
tokio::spawn(async move {
|
||||
println!("Autojoining room {}", room.room_id());
|
||||
let mut delay = 2;
|
||||
// The event handlers are called before the next sync begins, but
|
||||
// methods that change the state of a room (joining, leaving a room)
|
||||
// wait for the sync to return the new room state so we need to spawn
|
||||
// a new task for them.
|
||||
tokio::spawn(async move {
|
||||
println!("Autojoining room {}", room.room_id());
|
||||
let mut delay = 2;
|
||||
|
||||
while let Err(err) = room.join().await {
|
||||
// retry autojoin due to synapse sending invites, before the
|
||||
// invited user can join for more information see
|
||||
// https://github.com/matrix-org/synapse/issues/4345
|
||||
eprintln!("Failed to join room {} ({err:?}), retrying in {delay}s", room.room_id());
|
||||
while let Err(err) = room.join().await {
|
||||
// retry autojoin due to synapse sending invites, before the
|
||||
// invited user can join for more information see
|
||||
// https://github.com/matrix-org/synapse/issues/4345
|
||||
eprintln!("Failed to join room {} ({err:?}), retrying in {delay}s", room.room_id());
|
||||
|
||||
sleep(Duration::from_secs(delay)).await;
|
||||
delay *= 2;
|
||||
sleep(Duration::from_secs(delay)).await;
|
||||
delay *= 2;
|
||||
|
||||
if delay > 3600 {
|
||||
eprintln!("Can't join room {} ({err:?})", room.room_id());
|
||||
break;
|
||||
}
|
||||
if delay > 3600 {
|
||||
eprintln!("Can't join room {} ({err:?})", room.room_id());
|
||||
break;
|
||||
}
|
||||
println!("Successfully joined room {}", room.room_id());
|
||||
});
|
||||
}
|
||||
}
|
||||
println!("Successfully joined room {}", room.room_id());
|
||||
});
|
||||
}
|
||||
|
||||
// This fn is called whenever we see a new room message event. You notice that
|
||||
@@ -149,10 +146,12 @@ async fn on_stripped_state_member(
|
||||
// handler lies only in their input parameters. However, that is enough for the
|
||||
// rust-sdk to figure out which one to call one and only do so, when
|
||||
// the parameters are available.
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) {
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: room::Common) {
|
||||
// First, we need to unpack the message: We only want messages from rooms we are
|
||||
// still in and that are regular text messages - ignoring everything else.
|
||||
let Room::Joined(room) = room else { return };
|
||||
if room.state() != RoomState::Joined {
|
||||
return;
|
||||
}
|
||||
let MessageType::Text(text_content) = event.content.msgtype else { return };
|
||||
|
||||
// here comes the actual "logic": when the bot see's a `!party` in the message,
|
||||
|
||||
@@ -4,14 +4,16 @@ use matrix_sdk::{
|
||||
self,
|
||||
attachment::AttachmentConfig,
|
||||
config::SyncSettings,
|
||||
room::Room,
|
||||
room,
|
||||
ruma::events::room::message::{MessageType, OriginalSyncRoomMessageEvent},
|
||||
Client,
|
||||
Client, RoomState,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room, image: Vec<u8>) {
|
||||
let Room::Joined(room) = room else { return };
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: room::Common, image: Vec<u8>) {
|
||||
if room.state() != RoomState::Joined {
|
||||
return;
|
||||
}
|
||||
let MessageType::Text(text_content) = event.content.msgtype else { return };
|
||||
|
||||
if text_content.body.contains("!image") {
|
||||
|
||||
@@ -8,12 +8,12 @@ use anyhow::anyhow;
|
||||
use matrix_sdk::{
|
||||
self,
|
||||
config::SyncSettings,
|
||||
room::Room,
|
||||
room,
|
||||
ruma::{
|
||||
api::client::session::get_login_types::v3::{IdentityProvider, LoginType},
|
||||
events::room::message::{MessageType, OriginalSyncRoomMessageEvent},
|
||||
},
|
||||
Client,
|
||||
Client, RoomState,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
@@ -60,7 +60,7 @@ async fn login_and_sync(homeserver_url: String) -> anyhow::Result<()> {
|
||||
choices.extend(sso.identity_providers.into_iter().map(LoginChoice::SsoIdp))
|
||||
}
|
||||
}
|
||||
// This is used for SSO, so it's not a separate choice.
|
||||
// This is used for SSO, so it's not a separate choice.
|
||||
LoginType::Token(_) |
|
||||
// This is only for application services, ignore it here.
|
||||
LoginType::ApplicationService(_) => {},
|
||||
@@ -208,11 +208,11 @@ async fn login_with_sso(client: &Client, idp: Option<&IdentityProvider>) -> anyh
|
||||
}
|
||||
|
||||
/// Handle room messages by logging them.
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) {
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: room::Common) {
|
||||
// We only want to listen to joined rooms.
|
||||
let Room::Joined(room) = room else {
|
||||
if room.state() != RoomState::Joined {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
// We only want to log text messages.
|
||||
let MessageType::Text(msgtype) = &event.content.msgtype else {
|
||||
|
||||
@@ -5,12 +5,12 @@ use std::{
|
||||
|
||||
use matrix_sdk::{
|
||||
config::SyncSettings,
|
||||
room::Room,
|
||||
room,
|
||||
ruma::{
|
||||
api::client::filter::FilterDefinition,
|
||||
events::room::message::{MessageType, OriginalSyncRoomMessageEvent},
|
||||
},
|
||||
AuthSession, Client, Error, LoopCtrl,
|
||||
AuthSession, Client, Error, LoopCtrl, RoomState,
|
||||
};
|
||||
use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -290,9 +290,11 @@ async fn persist_sync_token(session_file: &Path, sync_token: String) -> anyhow::
|
||||
}
|
||||
|
||||
/// Handle room messages.
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) {
|
||||
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: room::Common) {
|
||||
// We only want to log text messages in joined rooms.
|
||||
let Room::Joined(room) = room else { return };
|
||||
if room.state() != RoomState::Joined {
|
||||
return;
|
||||
}
|
||||
let MessageType::Text(text_content) = &event.content.msgtype else { return };
|
||||
|
||||
let room_name = match room.display_name().await {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::{bail, Result};
|
||||
use anyhow::{ensure, Result};
|
||||
use assign::assign;
|
||||
use matrix_sdk::{
|
||||
room::Room, ruma::api::client::room::create_room::v3::Request as CreateRoomRequest,
|
||||
ruma::api::client::room::create_room::v3::Request as CreateRoomRequest, RoomState,
|
||||
};
|
||||
|
||||
use crate::helpers::get_client_for_user;
|
||||
@@ -25,12 +25,14 @@ async fn test_invitation_details() -> Result<()> {
|
||||
sebastian.sync_once(Default::default()).await?;
|
||||
let room = sebastian.get_room(&room_id).expect("Sebstian doesn't know about the room");
|
||||
|
||||
if let Room::Invited(iv) = room {
|
||||
let details = iv.invite_details().await?;
|
||||
let sender = details.inviter.expect("invite details doesn't have inviter");
|
||||
assert_eq!(sender.user_id(), tamatoa.user_id().expect("tamatoa has a user_id"));
|
||||
} else {
|
||||
bail!("The room tamatoa invited sebastian in isn't an invite: {:?}", room);
|
||||
}
|
||||
ensure!(
|
||||
room.state() == RoomState::Invited,
|
||||
"The room tamatoa invited sebastian in isn't an invite: {room:?}"
|
||||
);
|
||||
|
||||
let details = room.invite_details().await?;
|
||||
let sender = details.inviter.expect("invite details doesn't have inviter");
|
||||
assert_eq!(sender.user_id(), tamatoa.user_id().expect("tamatoa has a user_id"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use anyhow::Result;
|
||||
use assign::assign;
|
||||
use matrix_sdk::{
|
||||
event_handler::Ctx,
|
||||
room::Room,
|
||||
room,
|
||||
ruma::{
|
||||
api::client::room::create_room::v3::Request as CreateRoomRequest,
|
||||
events::room::member::{MembershipState, StrippedRoomMemberEvent},
|
||||
@@ -120,7 +120,7 @@ async fn test_repeated_join_leave() -> Result<()> {
|
||||
|
||||
async fn signal_on_invite(
|
||||
event: StrippedRoomMemberEvent,
|
||||
room: Room,
|
||||
room: room::Common,
|
||||
client: Client,
|
||||
sender: Ctx<Arc<Notify>>,
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user