1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use std::ops::Deref;

use thiserror::Error;

use crate::{
    room::{Common, RoomMember},
    BaseRoom, Client, Error, Result, RoomType,
};

/// A room in the invited state.
///
/// This struct contains all methods specific to a `Room` with type
/// `RoomType::Invited`. Operations may fail once the underlying `Room` changes
/// `RoomType`.
#[derive(Debug, Clone)]
pub struct Invited {
    pub(crate) inner: Common,
}

/// Details of the (latest) invite.
#[derive(Debug, Clone)]
pub struct Invite {
    /// Who has been invited.
    pub invitee: RoomMember,
    /// Who sent the invite.
    pub inviter: Option<RoomMember>,
}

#[derive(Error, Debug)]
pub enum InvitationError {
    /// The client isn't logged in.
    #[error("The client isn't authenticated")]
    NotAuthenticated,
    #[error("No membership event found")]
    EventMissing,
}

impl Invited {
    /// Create a new `room::Invited` if the underlying `Room` has type
    /// `RoomType::Invited`.
    ///
    /// # Arguments
    /// * `client` - The client used to make requests.
    ///
    /// * `room` - The underlying room.
    pub(crate) fn new(client: &Client, room: BaseRoom) -> Option<Self> {
        if room.room_type() == RoomType::Invited {
            Some(Self { inner: Common::new(client.clone(), room) })
        } else {
            None
        }
    }

    /// Reject the invitation.
    pub async fn reject_invitation(&self) -> Result<()> {
        self.inner.leave().await
    }

    /// Accept the invitation.
    pub async fn accept_invitation(&self) -> Result<()> {
        self.inner.join().await
    }

    /// The membership details of the (latest) invite for this room.
    pub async fn invite_details(&self) -> Result<Invite> {
        let user_id = self
            .inner
            .client
            .user_id()
            .ok_or_else(|| Error::UnknownError(Box::new(InvitationError::NotAuthenticated)))?;
        let invitee = self
            .inner
            .get_member_no_sync(user_id)
            .await?
            .ok_or_else(|| Error::UnknownError(Box::new(InvitationError::EventMissing)))?;
        let event = invitee.event();
        let inviter_id = event.sender();
        let inviter = self.inner.get_member_no_sync(inviter_id).await?;
        Ok(Invite { invitee, inviter })
    }
}

impl Deref for Invited {
    type Target = Common;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}