98 lines
2.9 KiB
Rust
98 lines
2.9 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
|
|
use super::MembershipState;
|
|
use crate::{MxcUri, UserId};
|
|
|
|
/// The details of a member event required to calculate a [`MembershipChange`].
|
|
pub struct MembershipDetails<'a> {
|
|
pub(crate) avatar_url: Option<&'a MxcUri>,
|
|
pub(crate) displayname: Option<&'a str>,
|
|
pub(crate) membership: &'a MembershipState,
|
|
}
|
|
|
|
/// Translation of the membership change in `m.room.member` event.
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
|
pub enum MembershipChange {
|
|
/// No change.
|
|
None,
|
|
|
|
/// Must never happen.
|
|
Error,
|
|
|
|
/// User joined the room.
|
|
Joined,
|
|
|
|
/// User left the room.
|
|
Left,
|
|
|
|
/// User was banned.
|
|
Banned,
|
|
|
|
/// User was unbanned.
|
|
Unbanned,
|
|
|
|
/// User was kicked.
|
|
Kicked,
|
|
|
|
/// User was invited.
|
|
Invited,
|
|
|
|
/// User was kicked and banned.
|
|
KickedAndBanned,
|
|
|
|
/// User rejected the invite.
|
|
InvitationRejected,
|
|
|
|
/// User had their invite revoked.
|
|
InvitationRevoked,
|
|
|
|
/// `displayname` or `avatar_url` changed.
|
|
ProfileChanged {
|
|
/// Whether the `displayname` changed.
|
|
displayname_changed: bool,
|
|
|
|
/// Whether the `avatar_url` changed.
|
|
avatar_url_changed: bool,
|
|
},
|
|
|
|
/// Not implemented.
|
|
NotImplemented,
|
|
}
|
|
|
|
/// Internal function so all `RoomMemberEventContent` state event kinds can share the same
|
|
/// implementation.
|
|
pub(super) fn membership_change(
|
|
details: MembershipDetails<'_>,
|
|
prev_details: Option<MembershipDetails<'_>>,
|
|
sender: &UserId,
|
|
state_key: &UserId,
|
|
) -> MembershipChange {
|
|
use MembershipChange as Ch;
|
|
use MembershipState as St;
|
|
|
|
let prev_details = match prev_details {
|
|
Some(prev) => prev,
|
|
None => MembershipDetails { avatar_url: None, displayname: None, membership: &St::Leave },
|
|
};
|
|
|
|
match (&prev_details.membership, &details.membership) {
|
|
(St::Invite, St::Invite) | (St::Leave, St::Leave) | (St::Ban, St::Ban) => Ch::None,
|
|
(St::Invite, St::Join) | (St::Leave, St::Join) => Ch::Joined,
|
|
(St::Invite, St::Leave) if sender == state_key => Ch::InvitationRevoked,
|
|
(St::Invite, St::Leave) => Ch::InvitationRejected,
|
|
(St::Invite, St::Ban) | (St::Leave, St::Ban) => Ch::Banned,
|
|
(St::Join, St::Invite) | (St::Ban, St::Invite) | (St::Ban, St::Join) => Ch::Error,
|
|
(St::Join, St::Join) => Ch::ProfileChanged {
|
|
displayname_changed: prev_details.displayname != details.displayname,
|
|
avatar_url_changed: prev_details.avatar_url != details.avatar_url,
|
|
},
|
|
(St::Join, St::Leave) if sender == state_key => Ch::Left,
|
|
(St::Join, St::Leave) => Ch::Kicked,
|
|
(St::Join, St::Ban) => Ch::KickedAndBanned,
|
|
(St::Leave, St::Invite) => Ch::Invited,
|
|
(St::Ban, St::Leave) => Ch::Unbanned,
|
|
_ => Ch::NotImplemented,
|
|
}
|
|
}
|