diff --git a/src/bot/event_handlers.rs b/src/bot/event_handlers.rs index f115a39..861f672 100644 --- a/src/bot/event_handlers.rs +++ b/src/bot/event_handlers.rs @@ -4,7 +4,7 @@ use log::{debug, error, info, warn}; use matrix_sdk::{ self, events::{ - room::member::{MemberEventContent, MembershipState}, + room::member::{MemberEventContent, MembershipChange}, room::message::{MessageEventContent, TextMessageEventContent}, StrippedStateEvent, SyncMessageEvent, SyncStateEvent, }, @@ -16,6 +16,11 @@ use std::clone::Clone; use std::ops::Sub; use std::time::{Duration, SystemTime}; +fn check_age(timestamp: &SystemTime, how_far_back: u64) -> bool { + let oldest_timestamp = SystemTime::now().sub(Duration::new(how_far_back, 0)); + timestamp > &oldest_timestamp +} + /// Check if a message is recent enough to actually process. If the /// message is within "oldest_message_age" seconds, this function /// returns true. If it's older than that, it returns false and logs a @@ -77,31 +82,36 @@ async fn should_process<'a>( /// Originally adapted from the matrix-rust-sdk examples. #[async_trait] impl EventEmitter for DiceBot { - async fn on_room_member( - &self, - room: SyncRoom, - room_member: &SyncStateEvent, - ) { - if let SyncRoom::Joined(room) = room { + async fn on_room_member(&self, room: SyncRoom, event: &SyncStateEvent) { + if !check_age(&event.origin_server_ts, 2) { + debug!("Ignoring old event: {:#?}", event); + return; + } + + if let SyncRoom::Joined(room) | SyncRoom::Left(room) = room { let event_affects_us = if let Some(our_user_id) = self.client.user_id().await { - room_member.state_key == our_user_id + event.state_key == our_user_id } else { false }; - let adding_user = match room_member.content.membership { - MembershipState::Join => true, - MembershipState::Leave | MembershipState::Ban => false, + use MembershipChange::*; + let adding_user = match event.membership_change() { + Joined => true, + Banned | Left | Kicked | KickedAndBanned => false, _ => return, }; //Clone to avoid holding lock. let room = room.read().await.clone(); - let (room_id, username) = (room.room_id.as_str(), &room_member.state_key); + let (room_id, username) = (room.room_id.as_str(), &event.state_key); let result = if event_affects_us && !adding_user { info!("Clearing all information for room ID {}", room_id); self.db.rooms.clear_info(room_id) + } else if event_affects_us && adding_user { + info!("Joined room {}; recording user information", room_id); + Ok(()) } else if !event_affects_us && adding_user { info!("Adding user {} to room ID {}", username, room_id); self.db.rooms.add_user_to_room(username, room_id) @@ -109,7 +119,7 @@ impl EventEmitter for DiceBot { info!("Removing user {} from room ID {}", username, room_id); self.db.rooms.remove_user_from_room(username, room_id) } else { - debug!("Ignoring a room member event: {:#?}", room_member); + debug!("Ignoring a room member event: {:#?}", event); Ok(()) };