matrix_sdk/room/
knock_requests.rsuse js_int::UInt;
use ruma::{EventId, OwnedEventId, OwnedMxcUri, OwnedUserId, RoomId};
use crate::{room::RoomMember, Error, Room};
#[derive(Debug, Clone)]
pub struct KnockRequest {
room: Room,
pub event_id: OwnedEventId,
pub timestamp: Option<UInt>,
pub member_info: KnockRequestMemberInfo,
pub is_seen: bool,
}
impl KnockRequest {
pub(crate) fn new(
room: &Room,
event_id: &EventId,
timestamp: Option<UInt>,
member: KnockRequestMemberInfo,
is_seen: bool,
) -> Self {
Self {
room: room.clone(),
event_id: event_id.to_owned(),
timestamp,
member_info: member,
is_seen,
}
}
pub fn room_id(&self) -> &RoomId {
self.room.room_id()
}
pub async fn mark_as_seen(&self) -> Result<(), Error> {
self.room.mark_knock_requests_as_seen(&[self.member_info.user_id.to_owned()]).await?;
Ok(())
}
pub async fn accept(&self) -> Result<(), Error> {
self.room.invite_user_by_id(&self.member_info.user_id).await
}
pub async fn decline(&self, reason: Option<&str>) -> Result<(), Error> {
self.room.kick_user(&self.member_info.user_id, reason).await
}
pub async fn decline_and_ban(&self, reason: Option<&str>) -> Result<(), Error> {
self.room.ban_user(&self.member_info.user_id, reason).await
}
}
#[derive(Debug, Clone)]
pub struct KnockRequestMemberInfo {
pub user_id: OwnedUserId,
pub display_name: Option<String>,
pub avatar_url: Option<OwnedMxcUri>,
pub reason: Option<String>,
}
impl KnockRequestMemberInfo {
pub(crate) fn from_member(member: &RoomMember) -> Self {
Self {
user_id: member.user_id().to_owned(),
display_name: member.display_name().map(ToOwned::to_owned),
avatar_url: member.avatar_url().map(ToOwned::to_owned),
reason: member.event().reason().map(ToOwned::to_owned),
}
}
}
#[cfg(all(test, not(target_arch = "wasm32")))]
mod tests {
use matrix_sdk_test::{async_test, event_factory::EventFactory, JoinedRoomBuilder};
use ruma::{
event_id,
events::room::member::{MembershipState, RoomMemberEventContent},
owned_user_id, room_id, user_id, EventId,
};
use crate::{
room::knock_requests::{KnockRequest, KnockRequestMemberInfo},
test_utils::mocks::MatrixMockServer,
Room,
};
#[async_test]
async fn test_mark_as_seen() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let event_id = event_id!("$a:b.c");
let user_id = user_id!("@alice:b.c");
let f = EventFactory::new().room(room_id);
let joined_room_builder = JoinedRoomBuilder::new(room_id).add_state_bulk(vec![f
.event(RoomMemberEventContent::new(MembershipState::Knock))
.event_id(event_id)
.sender(user_id)
.state_key(user_id)
.into_raw_timeline()
.cast()]);
let room = server.sync_room(&client, joined_room_builder).await;
let knock_request = make_knock_request(&room, Some(event_id));
knock_request.mark_as_seen().await.expect("Failed to mark as seen");
let seen_ids =
room.get_seen_knock_request_ids().await.expect("Failed to get seen join request ids");
assert_eq!(seen_ids.len(), 1);
assert_eq!(
seen_ids.into_iter().next().expect("Couldn't load next item"),
(event_id.to_owned(), user_id.to_owned())
);
}
#[async_test]
async fn test_accept() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
let knock_request = make_knock_request(&room, None);
server.mock_invite_user_by_id().ok().mock_once().mount().await;
knock_request.accept().await.expect("Failed to accept the request");
}
#[async_test]
async fn test_decline() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
let knock_request = make_knock_request(&room, None);
server.mock_kick_user().ok().mock_once().mount().await;
knock_request.decline(None).await.expect("Failed to decline the request");
}
#[async_test]
async fn test_decline_and_ban() {
let server = MatrixMockServer::new().await;
let client = server.client_builder().build().await;
let room_id = room_id!("!a:b.c");
let room = server.sync_joined_room(&client, room_id).await;
let knock_request = make_knock_request(&room, None);
server.mock_ban_user().ok().mock_once().mount().await;
knock_request
.decline_and_ban(None)
.await
.expect("Failed to decline the request and ban the user");
}
fn make_knock_request(room: &Room, event_id: Option<&EventId>) -> KnockRequest {
KnockRequest::new(
room,
event_id.unwrap_or(event_id!("$a:b.c")),
None,
KnockRequestMemberInfo {
user_id: owned_user_id!("@alice:b.c"),
display_name: None,
avatar_url: None,
reason: None,
},
false,
)
}
}