use std::{collections::BTreeMap, fmt, iter};
pub use matrix_sdk_common::deserialized_responses::*;
use ruma::{
events::{
room::{
member::{MembershipState, RoomMemberEvent, RoomMemberEventContent},
power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent},
},
AnyStrippedStateEvent, AnySyncStateEvent, AnySyncTimelineEvent, EventContentFromType,
PossiblyRedactedStateEventContent, RedactContent, RedactedStateEventContent,
StateEventContent, StaticStateEventContent, StrippedStateEvent, SyncStateEvent,
},
serde::Raw,
EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, OwnedUserId, UserId,
};
use serde::Serialize;
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct AmbiguityChange {
pub member_id: OwnedUserId,
pub member_ambiguous: bool,
pub disambiguated_member: Option<OwnedUserId>,
pub ambiguated_member: Option<OwnedUserId>,
}
impl AmbiguityChange {
pub fn user_ids(&self) -> impl Iterator<Item = &UserId> {
iter::once(&*self.member_id)
.chain(self.disambiguated_member.as_deref())
.chain(self.ambiguated_member.as_deref())
}
}
#[derive(Clone, Debug, Default)]
#[non_exhaustive]
pub struct AmbiguityChanges {
pub changes: BTreeMap<OwnedRoomId, BTreeMap<OwnedEventId, AmbiguityChange>>,
}
#[derive(Clone, Debug, Default)]
pub struct MembersResponse {
pub chunk: Vec<RoomMemberEvent>,
pub ambiguity_changes: AmbiguityChanges,
}
#[derive(Clone, Debug, Serialize)]
#[serde(untagged)]
pub enum RawAnySyncOrStrippedTimelineEvent {
Sync(Raw<AnySyncTimelineEvent>),
Stripped(Raw<AnyStrippedStateEvent>),
}
#[derive(Clone, Debug, Serialize)]
#[serde(untagged)]
pub enum RawAnySyncOrStrippedState {
Sync(Raw<AnySyncStateEvent>),
Stripped(Raw<AnyStrippedStateEvent>),
}
impl RawAnySyncOrStrippedState {
pub fn deserialize(&self) -> serde_json::Result<AnySyncOrStrippedState> {
match self {
Self::Sync(raw) => Ok(AnySyncOrStrippedState::Sync(raw.deserialize()?)),
Self::Stripped(raw) => Ok(AnySyncOrStrippedState::Stripped(raw.deserialize()?)),
}
}
pub fn cast<C>(self) -> RawSyncOrStrippedState<C>
where
C: StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent,
{
match self {
Self::Sync(raw) => RawSyncOrStrippedState::Sync(raw.cast()),
Self::Stripped(raw) => RawSyncOrStrippedState::Stripped(raw.cast()),
}
}
}
#[derive(Clone, Debug)]
pub enum AnySyncOrStrippedState {
Sync(AnySyncStateEvent),
Stripped(AnyStrippedStateEvent),
}
impl AnySyncOrStrippedState {
pub fn as_sync(&self) -> Option<&AnySyncStateEvent> {
match self {
Self::Sync(ev) => Some(ev),
Self::Stripped(_) => None,
}
}
pub fn as_stripped(&self) -> Option<&AnyStrippedStateEvent> {
match self {
Self::Sync(_) => None,
Self::Stripped(ev) => Some(ev),
}
}
}
#[derive(Clone, Debug, Serialize)]
#[serde(untagged)]
pub enum RawSyncOrStrippedState<C>
where
C: StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent,
{
Sync(Raw<SyncStateEvent<C>>),
Stripped(Raw<StrippedStateEvent<C::PossiblyRedacted>>),
}
impl<C> RawSyncOrStrippedState<C>
where
C: StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent + fmt::Debug + Clone,
{
pub fn deserialize(&self) -> serde_json::Result<SyncOrStrippedState<C>>
where
C: StaticStateEventContent + EventContentFromType + RedactContent,
C::Redacted: RedactedStateEventContent<StateKey = C::StateKey> + EventContentFromType,
C::PossiblyRedacted: PossiblyRedactedStateEventContent + EventContentFromType,
{
match self {
Self::Sync(ev) => Ok(SyncOrStrippedState::Sync(ev.deserialize()?)),
Self::Stripped(ev) => Ok(SyncOrStrippedState::Stripped(ev.deserialize()?)),
}
}
}
pub type RawMemberEvent = RawSyncOrStrippedState<RoomMemberEventContent>;
#[derive(Clone, Debug)]
pub enum SyncOrStrippedState<C>
where
C: StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent + fmt::Debug + Clone,
{
Sync(SyncStateEvent<C>),
Stripped(StrippedStateEvent<C::PossiblyRedacted>),
}
impl<C> SyncOrStrippedState<C>
where
C: StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent<StateKey = C::StateKey> + fmt::Debug + Clone,
C::PossiblyRedacted: PossiblyRedactedStateEventContent<StateKey = C::StateKey>,
{
pub fn as_sync(&self) -> Option<&SyncStateEvent<C>> {
match self {
Self::Sync(ev) => Some(ev),
Self::Stripped(_) => None,
}
}
pub fn as_stripped(&self) -> Option<&StrippedStateEvent<C::PossiblyRedacted>> {
match self {
Self::Sync(_) => None,
Self::Stripped(ev) => Some(ev),
}
}
pub fn sender(&self) -> &UserId {
match self {
Self::Sync(e) => e.sender(),
Self::Stripped(e) => &e.sender,
}
}
pub fn event_id(&self) -> Option<&EventId> {
match self {
Self::Sync(e) => Some(e.event_id()),
Self::Stripped(_) => None,
}
}
pub fn origin_server_ts(&self) -> Option<MilliSecondsSinceUnixEpoch> {
match self {
Self::Sync(e) => Some(e.origin_server_ts()),
Self::Stripped(_) => None,
}
}
pub fn state_key(&self) -> &C::StateKey {
match self {
Self::Sync(e) => e.state_key(),
Self::Stripped(e) => &e.state_key,
}
}
}
impl<C> SyncOrStrippedState<C>
where
C: StaticStateEventContent<PossiblyRedacted = C>
+ RedactContent
+ PossiblyRedactedStateEventContent,
C::Redacted: RedactedStateEventContent<StateKey = <C as StateEventContent>::StateKey>
+ fmt::Debug
+ Clone,
{
pub fn original_content(&self) -> Option<&C> {
match self {
Self::Sync(e) => e.as_original().map(|e| &e.content),
Self::Stripped(e) => Some(&e.content),
}
}
}
pub type MemberEvent = SyncOrStrippedState<RoomMemberEventContent>;
impl MemberEvent {
pub fn membership(&self) -> &MembershipState {
match self {
MemberEvent::Sync(e) => e.membership(),
MemberEvent::Stripped(e) => &e.content.membership,
}
}
pub fn user_id(&self) -> &UserId {
self.state_key()
}
pub fn display_name(&self) -> &str {
self.original_content()
.and_then(|c| c.displayname.as_deref())
.unwrap_or_else(|| self.user_id().localpart())
}
}
impl SyncOrStrippedState<RoomPowerLevelsEventContent> {
pub fn power_levels(&self) -> RoomPowerLevels {
match self {
Self::Sync(e) => e.power_levels(),
Self::Stripped(e) => e.power_levels(),
}
}
}