tuwunel_api/client/membership/
forget.rs1use 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
8pub(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}