cargo fmt/clippy, move power levels into Room

master
Devin R 2020-04-05 12:41:00 -04:00
parent e987a9006b
commit c2b3210cc9
4 changed files with 100 additions and 44 deletions

View File

@ -25,10 +25,7 @@ impl EventEmitter for EventCallback {
let member = rooms.members.get(&sender).unwrap(); let member = rooms.members.get(&sender).unwrap();
println!( println!(
"{}: {}", "{}: {}",
member member.display_name.as_ref().unwrap_or(&sender.to_string()),
.display_name
.as_ref()
.unwrap_or(&sender.to_string()),
msg_body msg_body
); );
} }

View File

@ -69,7 +69,6 @@ use tokio::sync::Mutex;
/// println!( /// println!(
/// "{}: {}", /// "{}: {}",
/// member /// member
/// .user
/// .display_name /// .display_name
/// .as_ref() /// .as_ref()
/// .unwrap_or(&sender.to_string()), /// .unwrap_or(&sender.to_string()),

View File

@ -26,11 +26,12 @@ use crate::events::room::{
encryption::EncryptionEvent, encryption::EncryptionEvent,
member::{MemberEvent, MembershipChange}, member::{MemberEvent, MembershipChange},
name::NameEvent, name::NameEvent,
power_levels::PowerLevelsEvent, power_levels::{NotificationPowerLevels, PowerLevelsEvent, PowerLevelsEventContent},
}; };
use crate::events::EventType;
use crate::identifiers::{RoomAliasId, RoomId, UserId}; use crate::identifiers::{RoomAliasId, RoomId, UserId};
use js_int::UInt; use js_int::{Int, UInt};
#[derive(Debug, Default)] #[derive(Debug, Default)]
/// `RoomName` allows the calculation of a text room name. /// `RoomName` allows the calculation of a text room name.
@ -43,6 +44,32 @@ pub struct RoomName {
aliases: Vec<RoomAliasId>, aliases: Vec<RoomAliasId>,
} }
#[derive(Debug, PartialEq, Eq)]
pub struct PowerLevels {
/// The level required to ban a user.
pub ban: Int,
/// The level required to send specific event types.
///
/// This is a mapping from event type to power level required.
pub events: HashMap<EventType, Int>,
/// The default level required to send message events.
pub events_default: Int,
/// The level required to invite a user.
pub invite: Int,
/// The level required to kick a user.
pub kick: Int,
/// The level required to redact an event.
pub redact: Int,
/// The default level required to send state events.
pub state_default: Int,
/// The default power level for every user in the room.
pub users_default: Int,
/// The power level requirements for specific notification types.
///
/// This is a mapping from `key` to power level for that notifications key.
pub notifications: Int,
}
#[derive(Debug)] #[derive(Debug)]
/// A Matrix rooom. /// A Matrix rooom.
pub struct Room { pub struct Room {
@ -58,6 +85,8 @@ pub struct Room {
pub members: HashMap<UserId, RoomMember>, pub members: HashMap<UserId, RoomMember>,
/// A list of users that are currently typing. /// A list of users that are currently typing.
pub typing_users: Vec<UserId>, pub typing_users: Vec<UserId>,
/// The power level requirements for specific actions in this room
pub power_levels: Option<PowerLevels>,
// TODO when encryption events are handled we store algorithm used and rotation time. // TODO when encryption events are handled we store algorithm used and rotation time.
/// A flag indicating if the room is encrypted. /// A flag indicating if the room is encrypted.
pub encrypted: bool, pub encrypted: bool,
@ -131,6 +160,7 @@ impl Room {
creator: None, creator: None,
members: HashMap::new(), members: HashMap::new(),
typing_users: Vec::new(), typing_users: Vec::new(),
power_levels: None,
encrypted: false, encrypted: false,
unread_highlight: None, unread_highlight: None,
unread_notifications: None, unread_notifications: None,
@ -180,6 +210,35 @@ impl Room {
true true
} }
fn set_room_power_level(&mut self, event: &PowerLevelsEvent) -> bool {
let PowerLevelsEventContent {
ban,
events,
events_default,
invite,
kick,
redact,
state_default,
users_default,
notifications: NotificationPowerLevels { room },
..
} = &event.content;
let power = PowerLevels {
ban: *ban,
events: events.clone(),
events_default: *events_default,
invite: *invite,
kick: *kick,
redact: *redact,
state_default: *state_default,
users_default: *users_default,
notifications: *room,
};
self.power_levels = Some(power);
true
}
/// Handle a room.member updating the room state if necessary. /// Handle a room.member updating the room state if necessary.
/// ///
/// Returns true if the joined member list changed, false otherwise. /// Returns true if the joined member list changed, false otherwise.
@ -192,10 +251,7 @@ impl Room {
} else { } else {
return false; return false;
}; };
if let Some(member) = self if let Some(member) = self.members.get_mut(&user) {
.members
.get_mut(&user)
{
member.update_member(event) member.update_member(event)
} else { } else {
false false
@ -239,22 +295,22 @@ impl Room {
/// ///
/// Returns true if the room name changed, false otherwise. /// Returns true if the room name changed, false otherwise.
pub fn handle_power_level(&mut self, event: &PowerLevelsEvent) -> bool { pub fn handle_power_level(&mut self, event: &PowerLevelsEvent) -> bool {
// when getting a response from the actual matrix server `state_key` // NOTE: this is always true, we assume that if we get an event their is an update.
// was empty, the spec says "state_key: A zero-length string." let mut updated = self.set_room_power_level(event);
// for `m.room.power_levels` events
let user = if let Ok(id) = UserId::try_from(event.state_key.as_str()) { let mut max_power = event.content.users_default;
id for power in event.content.users.values() {
} else { max_power = *power.max(&max_power);
return false;
};
if let Some(member) = self
.members
.get_mut(&user)
{
member.update_power(event)
} else {
false
} }
for user in event.content.users.keys() {
if let Some(member) = self.members.get_mut(user) {
if member.update_power(event, max_power) {
updated = true;
}
}
}
updated
} }
fn handle_encryption_event(&mut self, _event: &EncryptionEvent) -> bool { fn handle_encryption_event(&mut self, _event: &EncryptionEvent) -> bool {
@ -297,6 +353,7 @@ impl Room {
StateEvent::RoomName(n) => self.handle_room_name(n), StateEvent::RoomName(n) => self.handle_room_name(n),
StateEvent::RoomCanonicalAlias(ca) => self.handle_canonical(ca), StateEvent::RoomCanonicalAlias(ca) => self.handle_canonical(ca),
StateEvent::RoomAliases(a) => self.handle_room_aliases(a), StateEvent::RoomAliases(a) => self.handle_room_aliases(a),
StateEvent::RoomPowerLevels(p) => self.handle_power_level(p),
StateEvent::RoomEncryption(e) => self.handle_encryption_event(e), StateEvent::RoomEncryption(e) => self.handle_encryption_event(e),
_ => false, _ => false,
} }
@ -337,6 +394,7 @@ mod test {
use url::Url; use url::Url;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ops::Deref;
use std::str::FromStr; use std::str::FromStr;
use std::time::Duration; use std::time::Duration;
@ -375,5 +433,7 @@ mod test {
for (_id, member) in &room.members { for (_id, member) in &room.members {
assert_eq!(MembershipState::Join, member.membership); assert_eq!(MembershipState::Join, member.membership);
} }
assert!(room.deref().power_levels.is_some())
} }
} }

View File

@ -16,11 +16,11 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use crate::events::collections::all::Event; use crate::events::collections::all::Event;
use crate::events::presence::{PresenceEvent, PresenceEventContent, PresenceState};
use crate::events::room::{ use crate::events::room::{
member::{MemberEvent, MembershipChange, MembershipState}, member::{MemberEvent, MembershipChange, MembershipState},
power_levels::PowerLevelsEvent, power_levels::PowerLevelsEvent,
}; };
use crate::events::presence::{PresenceEvent, PresenceEventContent, PresenceState};
use crate::identifiers::UserId; use crate::identifiers::UserId;
use js_int::{Int, UInt}; use js_int::{Int, UInt};
@ -106,12 +106,7 @@ impl RoomMember {
} }
} }
pub fn update_power(&mut self, event: &PowerLevelsEvent) -> bool { pub fn update_power(&mut self, event: &PowerLevelsEvent, max_power: Int) -> bool {
let mut max_power = event.content.users_default;
for power in event.content.users.values() {
max_power = *power.max(&max_power);
}
let changed; let changed;
if let Some(user_power) = event.content.users.get(&self.user_id) { if let Some(user_power) = event.content.users.get(&self.user_id) {
changed = self.power_level != Some(*user_power); changed = self.power_level != Some(*user_power);
@ -179,18 +174,16 @@ impl RoomMember {
self.presence_events.push(presence_ev.clone()); self.presence_events.push(presence_ev.clone());
self.avatar_url = avatar_url.clone(); self.avatar_url = avatar_url.clone();
self.currently_active = currently_active.clone(); self.currently_active = *currently_active;
self.display_name = displayname.clone(); self.display_name = displayname.clone();
self.last_active_ago = last_active_ago.clone(); self.last_active_ago = *last_active_ago;
self.presence = Some(presence.clone()); self.presence = Some(*presence);
self.status_msg = status_msg.clone(); self.status_msg = status_msg.clone();
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*;
use crate::identifiers::{EventId, RoomId, UserId}; use crate::identifiers::{EventId, RoomId, UserId};
use crate::{AsyncClient, Session, SyncSettings}; use crate::{AsyncClient, Session, SyncSettings};
@ -202,6 +195,7 @@ mod test {
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ops::Deref;
use std::str::FromStr; use std::str::FromStr;
use std::time::Duration; use std::time::Duration;
@ -240,11 +234,17 @@ mod test {
.lock() .lock()
.await; .await;
for (_id, member) in &mut room.members { let power = power_levels();
let power = power_levels(); assert!(room.handle_power_level(&power));
assert!(member.update_power(&power));
assert_eq!(MembershipState::Join, member.membership); assert_eq!(
} room.deref().power_levels.as_ref().unwrap().ban,
Int::new(40).unwrap()
);
assert_eq!(
room.deref().power_levels.as_ref().unwrap().notifications,
Int::new(35).unwrap()
);
} }
fn power_levels() -> PowerLevelsEvent { fn power_levels() -> PowerLevelsEvent {