Skip to main content

tuwunel_api/client/membership/
forget.rs

1use axum::extract::State;
2use futures::pin_mut;
3use ruma::{api::client::membership::forget_room, events::room::member::MembershipState};
4use tuwunel_core::{Err, Result, is_matching, result::NotFound, utils::FutureBoolExt};
5
6use crate::Ruma;
7
8/// # `POST /_matrix/client/v3/rooms/{roomId}/forget`
9///
10/// Forgets about a room.
11///
12/// - If the sender user currently left the room: Stops sender user from
13///   receiving information about the room
14///
15/// Note: Other devices of the user have no way of knowing the room was
16/// forgotten, so this has to be called from every device
17pub(crate) async fn forget_room_route(
18	State(services): State<crate::State>,
19	body: Ruma<forget_room::v3::Request>,
20) -> Result<forget_room::v3::Response> {
21	let user_id = body.sender_user();
22	let room_id = &body.room_id;
23
24	let joined = services.state_cache.is_joined(user_id, room_id);
25	let knocked = services.state_cache.is_knocked(user_id, room_id);
26	let invited = services.state_cache.is_invited(user_id, room_id);
27
28	pin_mut!(joined, knocked, invited);
29	if joined.or(knocked).or(invited).await {
30		return Err!(Request(Unknown("You must leave the room before forgetting it")));
31	}
32
33	let membership = services
34		.state_accessor
35		.get_member(room_id, user_id)
36		.await;
37
38	if membership.is_not_found() {
39		return Err!(Request(Unknown("No membership event was found, room was never joined")));
40	}
41
42	let non_membership = membership
43		.map(|member| member.membership)
44		.is_ok_and(is_matching!(MembershipState::Leave | MembershipState::Ban));
45
46	if non_membership
47		|| services
48			.state_cache
49			.is_left(user_id, room_id)
50			.await
51	{
52		services.state_cache.forget(room_id, user_id);
53	}
54
55	Ok(forget_room::v3::Response::new())
56}