cargo fmt/clippy, move power levels into Room
This commit is contained in:
parent
e987a9006b
commit
c2b3210cc9
4 changed files with 100 additions and 44 deletions
|
@ -25,10 +25,7 @@ impl EventEmitter for EventCallback {
|
|||
let member = rooms.members.get(&sender).unwrap();
|
||||
println!(
|
||||
"{}: {}",
|
||||
member
|
||||
.display_name
|
||||
.as_ref()
|
||||
.unwrap_or(&sender.to_string()),
|
||||
member.display_name.as_ref().unwrap_or(&sender.to_string()),
|
||||
msg_body
|
||||
);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,6 @@ use tokio::sync::Mutex;
|
|||
/// println!(
|
||||
/// "{}: {}",
|
||||
/// member
|
||||
/// .user
|
||||
/// .display_name
|
||||
/// .as_ref()
|
||||
/// .unwrap_or(&sender.to_string()),
|
||||
|
|
|
@ -26,11 +26,12 @@ use crate::events::room::{
|
|||
encryption::EncryptionEvent,
|
||||
member::{MemberEvent, MembershipChange},
|
||||
name::NameEvent,
|
||||
power_levels::PowerLevelsEvent,
|
||||
power_levels::{NotificationPowerLevels, PowerLevelsEvent, PowerLevelsEventContent},
|
||||
};
|
||||
use crate::events::EventType;
|
||||
use crate::identifiers::{RoomAliasId, RoomId, UserId};
|
||||
|
||||
use js_int::UInt;
|
||||
use js_int::{Int, UInt};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
/// `RoomName` allows the calculation of a text room name.
|
||||
|
@ -43,6 +44,32 @@ pub struct RoomName {
|
|||
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)]
|
||||
/// A Matrix rooom.
|
||||
pub struct Room {
|
||||
|
@ -58,6 +85,8 @@ pub struct Room {
|
|||
pub members: HashMap<UserId, RoomMember>,
|
||||
/// A list of users that are currently typing.
|
||||
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.
|
||||
/// A flag indicating if the room is encrypted.
|
||||
pub encrypted: bool,
|
||||
|
@ -131,6 +160,7 @@ impl Room {
|
|||
creator: None,
|
||||
members: HashMap::new(),
|
||||
typing_users: Vec::new(),
|
||||
power_levels: None,
|
||||
encrypted: false,
|
||||
unread_highlight: None,
|
||||
unread_notifications: None,
|
||||
|
@ -156,7 +186,7 @@ impl Room {
|
|||
}
|
||||
|
||||
let member = RoomMember::new(event);
|
||||
|
||||
|
||||
self.members
|
||||
.insert(UserId::try_from(event.state_key.as_str()).unwrap(), member);
|
||||
|
||||
|
@ -180,6 +210,35 @@ impl Room {
|
|||
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.
|
||||
///
|
||||
/// Returns true if the joined member list changed, false otherwise.
|
||||
|
@ -192,10 +251,7 @@ impl Room {
|
|||
} else {
|
||||
return false;
|
||||
};
|
||||
if let Some(member) = self
|
||||
.members
|
||||
.get_mut(&user)
|
||||
{
|
||||
if let Some(member) = self.members.get_mut(&user) {
|
||||
member.update_member(event)
|
||||
} else {
|
||||
false
|
||||
|
@ -239,22 +295,22 @@ impl Room {
|
|||
///
|
||||
/// Returns true if the room name changed, false otherwise.
|
||||
pub fn handle_power_level(&mut self, event: &PowerLevelsEvent) -> bool {
|
||||
// when getting a response from the actual matrix server `state_key`
|
||||
// was empty, the spec says "state_key: A zero-length string."
|
||||
// for `m.room.power_levels` events
|
||||
let user = if let Ok(id) = UserId::try_from(event.state_key.as_str()) {
|
||||
id
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
if let Some(member) = self
|
||||
.members
|
||||
.get_mut(&user)
|
||||
{
|
||||
member.update_power(event)
|
||||
} else {
|
||||
false
|
||||
// NOTE: this is always true, we assume that if we get an event their is an update.
|
||||
let mut updated = self.set_room_power_level(event);
|
||||
|
||||
let mut max_power = event.content.users_default;
|
||||
for power in event.content.users.values() {
|
||||
max_power = *power.max(&max_power);
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -297,6 +353,7 @@ impl Room {
|
|||
StateEvent::RoomName(n) => self.handle_room_name(n),
|
||||
StateEvent::RoomCanonicalAlias(ca) => self.handle_canonical(ca),
|
||||
StateEvent::RoomAliases(a) => self.handle_room_aliases(a),
|
||||
StateEvent::RoomPowerLevels(p) => self.handle_power_level(p),
|
||||
StateEvent::RoomEncryption(e) => self.handle_encryption_event(e),
|
||||
_ => false,
|
||||
}
|
||||
|
@ -337,6 +394,7 @@ mod test {
|
|||
use url::Url;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -375,5 +433,7 @@ mod test {
|
|||
for (_id, member) in &room.members {
|
||||
assert_eq!(MembershipState::Join, member.membership);
|
||||
}
|
||||
|
||||
assert!(room.deref().power_levels.is_some())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use crate::events::collections::all::Event;
|
||||
use crate::events::presence::{PresenceEvent, PresenceEventContent, PresenceState};
|
||||
use crate::events::room::{
|
||||
member::{MemberEvent, MembershipChange, MembershipState},
|
||||
power_levels::PowerLevelsEvent,
|
||||
};
|
||||
use crate::events::presence::{PresenceEvent, PresenceEventContent, PresenceState};
|
||||
use crate::identifiers::UserId;
|
||||
|
||||
use js_int::{Int, UInt};
|
||||
|
@ -106,12 +106,7 @@ impl RoomMember {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update_power(&mut self, event: &PowerLevelsEvent) -> bool {
|
||||
let mut max_power = event.content.users_default;
|
||||
for power in event.content.users.values() {
|
||||
max_power = *power.max(&max_power);
|
||||
}
|
||||
|
||||
pub fn update_power(&mut self, event: &PowerLevelsEvent, max_power: Int) -> bool {
|
||||
let changed;
|
||||
if let Some(user_power) = event.content.users.get(&self.user_id) {
|
||||
changed = self.power_level != Some(*user_power);
|
||||
|
@ -179,18 +174,16 @@ impl RoomMember {
|
|||
|
||||
self.presence_events.push(presence_ev.clone());
|
||||
self.avatar_url = avatar_url.clone();
|
||||
self.currently_active = currently_active.clone();
|
||||
self.currently_active = *currently_active;
|
||||
self.display_name = displayname.clone();
|
||||
self.last_active_ago = last_active_ago.clone();
|
||||
self.presence = Some(presence.clone());
|
||||
self.last_active_ago = *last_active_ago;
|
||||
self.presence = Some(*presence);
|
||||
self.status_msg = status_msg.clone();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
use crate::identifiers::{EventId, RoomId, UserId};
|
||||
use crate::{AsyncClient, Session, SyncSettings};
|
||||
|
||||
|
@ -202,6 +195,7 @@ mod test {
|
|||
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -240,11 +234,17 @@ mod test {
|
|||
.lock()
|
||||
.await;
|
||||
|
||||
for (_id, member) in &mut room.members {
|
||||
let power = power_levels();
|
||||
assert!(member.update_power(&power));
|
||||
assert_eq!(MembershipState::Join, member.membership);
|
||||
}
|
||||
let power = power_levels();
|
||||
assert!(room.handle_power_level(&power));
|
||||
|
||||
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 {
|
||||
|
|
Loading…
Reference in a new issue