From 224f8cd0f15f8ac06548f09cba729514f640885a Mon Sep 17 00:00:00 2001 From: projectmoon Date: Sun, 29 Nov 2020 13:59:59 +0000 Subject: [PATCH 01/10] Functions for storing RoomInfo in db. Refactor bot joins room event. Add get/insert functions for RoomInfo in the rooms db. Move 'bot joins room' code to single method, so we can also record a RoomInfo struct into the database. --- src/bot/event_handlers.rs | 22 ++++++++++++++++------ src/db/rooms.rs | 22 +++++++++++++++++++++- src/models.rs | 3 +++ 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/bot/event_handlers.rs b/src/bot/event_handlers.rs index 0e22433..c44f6db 100644 --- a/src/bot/event_handlers.rs +++ b/src/bot/event_handlers.rs @@ -92,6 +92,21 @@ fn should_process_event(db: &Database, room_id: &str, event_id: &str) -> bool { }) } +async fn record_users_in_room( + client: &matrix_sdk::Client, + db: &crate::db::Database, + room: &matrix_sdk::Room, + our_username: &str, +) -> Result<(), crate::db::errors::DataError> { + let room_id_str = room.room_id.as_str(); + let usernames = matrix::get_users_in_room(&client, &room.room_id).await; + usernames + .into_iter() + .filter(|username| username != our_username) + .map(|username| db.rooms.add_user_to_room(&username, room_id_str)) + .collect() //Make use of collect impl on Result. +} + /// This event emitter listens for messages with dice rolling commands. /// Originally adapted from the matrix-rust-sdk examples. #[async_trait] @@ -124,12 +139,7 @@ impl EventEmitter for DiceBot { self.db.rooms.clear_info(room_id) } else if event_affects_us && adding_user { info!("Joined room {}; recording user information", room_id); - let usernames = matrix::get_users_in_room(&self.client, &room.room_id).await; - usernames - .into_iter() - .filter(|username| username != &event.state_key) - .map(|username| self.db.rooms.add_user_to_room(&username, room_id)) - .collect() //Make use of collect impl on Result. + record_users_in_room(&self.client, &self.db, &room, &event.state_key).await } 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) diff --git a/src/db/rooms.rs b/src/db/rooms.rs index 02a80ea..af6b1a2 100644 --- a/src/db/rooms.rs +++ b/src/db/rooms.rs @@ -1,5 +1,6 @@ use crate::db::errors::DataError; use crate::db::schema::convert_u64; +use crate::models::RoomInfo; use byteorder::BigEndian; use log::{debug, error, log_enabled}; use sled::transaction::TransactionalTree; @@ -14,7 +15,8 @@ use zerocopy::AsBytes; #[derive(Clone)] pub struct Rooms { - /// Room ID -> RoomInfo struct (single entries) + /// Room ID -> RoomInfo struct (single entries). + /// Key is just room ID as bytes. pub(in crate::db) roomid_roominfo: Tree, /// Room ID -> list of usernames in room. @@ -225,6 +227,24 @@ impl Rooms { } } + pub fn insert_room_info(&self, info: &RoomInfo) -> Result<(), DataError> { + let key = info.room_id.as_bytes(); + let serialized = bincode::serialize(&info)?; + self.roomid_roominfo.insert(key, serialized)?; + Ok(()) + } + + pub fn get_room_info(&self, info: &RoomInfo) -> Result, DataError> { + let key = info.room_id.as_bytes(); + + //swap/flatten Result> down into the return type. + self.roomid_roominfo + .get(key) + .map(|bytes| bytes.map(|b| bincode::deserialize::(&b)))? + .transpose() + .map_err(|e| e.into()) + } + pub fn get_rooms_for_user(&self, username: &str) -> Result, DataError> { hashset_tree::get_set(&self.username_roomids, username.as_bytes()) } diff --git a/src/models.rs b/src/models.rs index 5d76f96..3040a80 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,4 +1,7 @@ +use serde::{Deserialize, Serialize}; + /// RoomInfo has basic metadata about a room: its name, ID, etc. +#[derive(Serialize, Deserialize, Clone, Debug)] pub struct RoomInfo { pub room_id: String, pub room_name: String, From 91cfc52e5b94833353022fe90ffd7b647ca2f69c Mon Sep 17 00:00:00 2001 From: projectmoon Date: Sun, 29 Nov 2020 14:02:40 +0000 Subject: [PATCH 02/10] Change record_users_in_room to record_room_information. --- src/bot/event_handlers.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bot/event_handlers.rs b/src/bot/event_handlers.rs index c44f6db..3792916 100644 --- a/src/bot/event_handlers.rs +++ b/src/bot/event_handlers.rs @@ -92,7 +92,7 @@ fn should_process_event(db: &Database, room_id: &str, event_id: &str) -> bool { }) } -async fn record_users_in_room( +async fn record_room_information( client: &matrix_sdk::Client, db: &crate::db::Database, room: &matrix_sdk::Room, @@ -138,8 +138,8 @@ impl EventEmitter for DiceBot { 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); - record_users_in_room(&self.client, &self.db, &room, &event.state_key).await + info!("Joined room {}; recording room information", room_id); + record_room_information(&self.client, &self.db, &room, &event.state_key).await } 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) From c8c38ac1d42085d2070ef643b219ac667738d94f Mon Sep 17 00:00:00 2001 From: projectmoon Date: Sun, 29 Nov 2020 16:55:23 +0000 Subject: [PATCH 03/10] Avoid nested map when retrieving room info from db. --- src/db/rooms.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/db/rooms.rs b/src/db/rooms.rs index af6b1a2..6d7380e 100644 --- a/src/db/rooms.rs +++ b/src/db/rooms.rs @@ -237,12 +237,13 @@ impl Rooms { pub fn get_room_info(&self, info: &RoomInfo) -> Result, DataError> { let key = info.room_id.as_bytes(); - //swap/flatten Result> down into the return type. - self.roomid_roominfo - .get(key) - .map(|bytes| bytes.map(|b| bincode::deserialize::(&b)))? - .transpose() - .map_err(|e| e.into()) + let room_info: Option = self + .roomid_roominfo + .get(key)? + .map(|bytes| bincode::deserialize(&bytes)) + .transpose()?; + + Ok(room_info) } pub fn get_rooms_for_user(&self, username: &str) -> Result, DataError> { From 118e4b00c7a6de39404f8b441381151cb4c58cf7 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Sun, 29 Nov 2020 17:06:04 +0000 Subject: [PATCH 04/10] Store room info when joining a room. --- src/bot/event_handlers.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/bot/event_handlers.rs b/src/bot/event_handlers.rs index 3792916..1b71cd6 100644 --- a/src/bot/event_handlers.rs +++ b/src/bot/event_handlers.rs @@ -100,6 +100,16 @@ async fn record_room_information( ) -> Result<(), crate::db::errors::DataError> { let room_id_str = room.room_id.as_str(); let usernames = matrix::get_users_in_room(&client, &room.room_id).await; + + let info = crate::models::RoomInfo { + room_id: room_id_str.to_owned(), + room_name: room.display_name(), + }; + + // TODO this and the username adding should be one whole + // transaction in the db. + db.rooms.insert_room_info(&info)?; + usernames .into_iter() .filter(|username| username != our_username) From 569ba4f2e0d230b9c580da9b8179f3ad28550a31 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Sun, 29 Nov 2020 21:03:45 +0000 Subject: [PATCH 05/10] Carry full room instance in context instead of just room id. --- src/bin/dicebot-cmd.rs | 16 +++++++++++++--- src/bot.rs | 2 +- src/cofd/dice.rs | 19 +++++++++++++++---- src/commands.rs | 10 +++++++++- src/commands/management.rs | 5 ++--- src/commands/variables.rs | 8 ++++---- src/context.rs | 3 ++- src/cthulhu/dice.rs | 10 +++++++++- src/dice.rs | 2 +- 9 files changed, 56 insertions(+), 19 deletions(-) diff --git a/src/bin/dicebot-cmd.rs b/src/bin/dicebot-cmd.rs index 8af1121..c9b93da 100644 --- a/src/bin/dicebot-cmd.rs +++ b/src/bin/dicebot-cmd.rs @@ -2,10 +2,20 @@ use chronicle_dicebot::commands; use chronicle_dicebot::context::Context; use chronicle_dicebot::db::Database; use chronicle_dicebot::error::BotError; +use matrix_sdk::{ + identifiers::{room_id, user_id}, + Room, +}; + +fn dummy_room() -> Room { + Room::new( + &room_id!("!fakeroomid:example.com"), + &user_id!("@fakeuserid:example.com"), + ) +} #[tokio::main] async fn main() -> Result<(), BotError> { - let db = Database::new_temp()?; let input = std::env::args().skip(1).collect::>().join(" "); let command = match commands::parser::parse_command(&input) { Ok(command) => command, @@ -13,10 +23,10 @@ async fn main() -> Result<(), BotError> { }; let context = Context { - db: db, + db: Database::new_temp()?, matrix_client: &matrix_sdk::Client::new("http://example.com") .expect("Could not create matrix client"), - room_id: "roomid", + room: &dummy_room(), username: "@localuser:example.com", message_body: &input, }; diff --git a/src/bot.rs b/src/bot.rs index 0886381..9d2d5c7 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -130,7 +130,7 @@ impl DiceBot { let ctx = Context { db: self.db.clone(), matrix_client: &self.client, - room_id: room_id.as_str(), + room: room, username: &sender_username, message_body: &command, }; diff --git a/src/cofd/dice.rs b/src/cofd/dice.rs index df18dfa..64e798c 100644 --- a/src/cofd/dice.rs +++ b/src/cofd/dice.rs @@ -323,6 +323,14 @@ mod tests { use super::*; use crate::db::Database; + /// Create dummy room instance. + fn dummy_room() -> matrix_sdk::Room { + matrix_sdk::Room::new( + &matrix_sdk::identifiers::room_id!("!fakeroomid:example.com"), + &matrix_sdk::identifiers::user_id!("@fakeuserid:example.com"), + ) + } + ///Instead of being random, generate a series of numbers we have complete ///control over. struct SequentialDieRoller { @@ -464,7 +472,7 @@ mod tests { let ctx = Context { db: db, matrix_client: &matrix_sdk::Client::new("http://example.com").unwrap(), - room_id: "roomid", + room: &dummy_room(), username: "username", message_body: "message", }; @@ -495,7 +503,7 @@ mod tests { let ctx = Context { db: db, matrix_client: &matrix_sdk::Client::new("http://example.com").unwrap(), - room_id: "roomid", + room: &dummy_room(), username: "username", message_body: "message", }; @@ -519,15 +527,18 @@ mod tests { #[tokio::test] async fn can_resolve_variables_test() { + use crate::db::variables::UserAndRoom; + let db = Database::new_temp().unwrap(); let ctx = Context { db: db.clone(), matrix_client: &matrix_sdk::Client::new("http://example.com").unwrap(), - room_id: "roomid", + room: &dummy_room(), username: "username", message_body: "message", }; - let user_and_room = crate::db::variables::UserAndRoom(&ctx.username, &ctx.room_id); + + let user_and_room = UserAndRoom(&ctx.username, &ctx.room.room_id.as_str()); db.variables .set_user_variable(&user_and_room, "myvariable", 10) diff --git a/src/commands.rs b/src/commands.rs index dd2c89e..8bb950a 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -78,13 +78,21 @@ pub async fn execute_command(ctx: &Context<'_>) -> CommandResult { mod tests { use super::*; + /// Create a dummy room instance. + fn dummy_room() -> matrix_sdk::Room { + matrix_sdk::Room::new( + &matrix_sdk::identifiers::room_id!("!fakeroomid:example.com"), + &matrix_sdk::identifiers::user_id!("@fakeuserid:example.com"), + ) + } + #[tokio::test] async fn unrecognized_command() { let db = crate::db::Database::new_temp().unwrap(); let ctx = Context { db: db, matrix_client: &matrix_sdk::Client::new("http://example.com").unwrap(), - room_id: "myroomid", + room: &dummy_room(), username: "myusername", message_body: "!notacommand", }; diff --git a/src/commands/management.rs b/src/commands/management.rs index 564a59f..ac150cf 100644 --- a/src/commands/management.rs +++ b/src/commands/management.rs @@ -3,8 +3,7 @@ use crate::context::Context; use crate::db::errors::DataError; use crate::matrix; use async_trait::async_trait; -use matrix_sdk::identifiers::{RoomId, UserId}; -use std::convert::TryFrom; +use matrix_sdk::identifiers::UserId; pub struct ResyncCommand; @@ -17,7 +16,7 @@ impl Command for ResyncCommand { } async fn execute(&self, ctx: &Context<'_>) -> Execution { - let room_id = RoomId::try_from(ctx.room_id).expect("failed to decode room ID"); + let room_id = &ctx.room.room_id; let our_username: Option = ctx.matrix_client.user_id().await; let our_username: &str = our_username.as_ref().map_or("", UserId::as_str); diff --git a/src/commands/variables.rs b/src/commands/variables.rs index 3f5cb50..8e47dbd 100644 --- a/src/commands/variables.rs +++ b/src/commands/variables.rs @@ -13,7 +13,7 @@ impl Command for GetAllVariablesCommand { } async fn execute(&self, ctx: &Context<'_>) -> Execution { - let key = UserAndRoom(&ctx.username, &ctx.room_id); + let key = UserAndRoom(&ctx.username, &ctx.room.room_id.as_str()); let result = ctx.db.variables.get_user_variables(&key); let value = match result { @@ -48,7 +48,7 @@ impl Command for GetVariableCommand { async fn execute(&self, ctx: &Context<'_>) -> Execution { let name = &self.0; - let key = UserAndRoom(&ctx.username, &ctx.room_id); + let key = UserAndRoom(&ctx.username, &ctx.room.room_id.as_str()); let result = ctx.db.variables.get_user_variable(&key, name); let value = match result { @@ -74,7 +74,7 @@ impl Command for SetVariableCommand { async fn execute(&self, ctx: &Context<'_>) -> Execution { let name = &self.0; let value = self.1; - let key = UserAndRoom(&ctx.username, ctx.room_id); + let key = UserAndRoom(&ctx.username, ctx.room.room_id.as_str()); let result = ctx.db.variables.set_user_variable(&key, name, value); let content = match result { @@ -98,7 +98,7 @@ impl Command for DeleteVariableCommand { async fn execute(&self, ctx: &Context<'_>) -> Execution { let name = &self.0; - let key = UserAndRoom(&ctx.username, ctx.room_id); + let key = UserAndRoom(&ctx.username, ctx.room.room_id.as_str()); let result = ctx.db.variables.delete_user_variable(&key, name); let value = match result { diff --git a/src/context.rs b/src/context.rs index 42a854a..7fead4b 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,5 +1,6 @@ use crate::db::Database; use matrix_sdk::Client; +use matrix_sdk::Room; /// A context carried through the system providing access to things /// like the database. @@ -7,7 +8,7 @@ use matrix_sdk::Client; pub struct Context<'a> { pub db: Database, pub matrix_client: &'a Client, - pub room_id: &'a str, + pub room: &'a Room, pub username: &'a str, pub message_body: &'a str, } diff --git a/src/cthulhu/dice.rs b/src/cthulhu/dice.rs index 4851034..0aeb015 100644 --- a/src/cthulhu/dice.rs +++ b/src/cthulhu/dice.rs @@ -343,6 +343,14 @@ mod tests { use crate::db::Database; use crate::parser::{Amount, Element, Operator}; + /// Create a dummy room instance. + fn dummy_room() -> matrix_sdk::Room { + matrix_sdk::Room::new( + &matrix_sdk::identifiers::room_id!("!fakeroomid:example.com"), + &matrix_sdk::identifiers::user_id!("@fakeuserid:example.com"), + ) + } + /// Generate a series of numbers manually for testing. For this /// die system, the first roll in the Vec should be the unit roll, /// and any subsequent rolls should be the tens place roll. The @@ -383,7 +391,7 @@ mod tests { let ctx = Context { db: db, matrix_client: &matrix_sdk::Client::new("https://example.com").unwrap(), - room_id: "roomid", + room: &dummy_room(), username: "username", message_body: "message", }; diff --git a/src/dice.rs b/src/dice.rs index 1472559..f2e0fba 100644 --- a/src/dice.rs +++ b/src/dice.rs @@ -9,7 +9,7 @@ use futures::stream::{self, StreamExt, TryStreamExt}; //New hotness pub async fn calculate_dice_amount(amounts: &[Amount], ctx: &Context<'_>) -> Result { let stream = stream::iter(amounts); - let key = UserAndRoom(&ctx.username, &ctx.room_id); + let key = UserAndRoom(&ctx.username, ctx.room.room_id.as_str()); let variables = &ctx.db.variables.get_user_variables(&key)?; use DiceRollingError::VariableNotFound; From 7e1abab66d6fd6d723e2429f01d104dc1a06ec36 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Sun, 29 Nov 2020 21:18:41 +0000 Subject: [PATCH 06/10] Resync command now uses record_room_information. --- src/bot/event_handlers.rs | 4 +++- src/commands/management.rs | 16 +++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/bot/event_handlers.rs b/src/bot/event_handlers.rs index 1b71cd6..7d735cd 100644 --- a/src/bot/event_handlers.rs +++ b/src/bot/event_handlers.rs @@ -92,7 +92,9 @@ fn should_process_event(db: &Database, room_id: &str, event_id: &str) -> bool { }) } -async fn record_room_information( +//TODO this needs to be moved to a common API layer. +/// Record the information about a room, including users in it. +pub async fn record_room_information( client: &matrix_sdk::Client, db: &crate::db::Database, room: &matrix_sdk::Room, diff --git a/src/commands/management.rs b/src/commands/management.rs index ac150cf..2243936 100644 --- a/src/commands/management.rs +++ b/src/commands/management.rs @@ -1,7 +1,6 @@ use super::{Command, Execution}; use crate::context::Context; use crate::db::errors::DataError; -use crate::matrix; use async_trait::async_trait; use matrix_sdk::identifiers::UserId; @@ -16,17 +15,16 @@ impl Command for ResyncCommand { } async fn execute(&self, ctx: &Context<'_>) -> Execution { - let room_id = &ctx.room.room_id; let our_username: Option = ctx.matrix_client.user_id().await; let our_username: &str = our_username.as_ref().map_or("", UserId::as_str); - let usernames = matrix::get_users_in_room(&ctx.matrix_client, &room_id).await; - - let result: ResyncResult = usernames - .into_iter() - .filter(|username| username != our_username) - .map(|username| ctx.db.rooms.add_user_to_room(&username, room_id.as_str())) - .collect(); //Make use of collect impl on Result. + let result: ResyncResult = crate::bot::event_handlers::record_room_information( + ctx.matrix_client, + &ctx.db, + &ctx.room, + our_username, + ) + .await; let (plain, html) = match result { Ok(()) => { From 0b2246cbd5c3c113ef1e0066ade62a71e874c901 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Sun, 29 Nov 2020 21:29:13 +0000 Subject: [PATCH 07/10] Unit tests for inserting and loading room info from db. --- src/db/rooms.rs | 38 ++++++++++++++++++++++++++++++++++++-- src/models.rs | 2 +- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/db/rooms.rs b/src/db/rooms.rs index 6d7380e..b028cbd 100644 --- a/src/db/rooms.rs +++ b/src/db/rooms.rs @@ -234,8 +234,8 @@ impl Rooms { Ok(()) } - pub fn get_room_info(&self, info: &RoomInfo) -> Result, DataError> { - let key = info.room_id.as_bytes(); + pub fn get_room_info(&self, room_id: &str) -> Result, DataError> { + let key = room_id.as_bytes(); let room_info: Option = self .roomid_roominfo @@ -377,6 +377,40 @@ mod tests { assert_eq!(HashSet::new(), rooms_for_user); } + #[test] + fn insert_room_info_works() { + let rooms = create_test_instance(); + + let info = RoomInfo { + room_id: matrix_sdk::identifiers::room_id!("!fakeroom:example.com") + .as_str() + .to_owned(), + room_name: "fake room name".to_owned(), + }; + + rooms + .insert_room_info(&info) + .expect("Could insert room info"); + + let found_info = rooms + .get_room_info("!fakeroom:example.com") + .expect("Error loading room info"); + + assert!(found_info.is_some()); + assert_eq!(info, found_info.unwrap()); + } + + #[test] + fn get_room_info_none_when_room_does_not_exist() { + let rooms = create_test_instance(); + + let found_info = rooms + .get_room_info("!fakeroom:example.com") + .expect("Error loading room info"); + + assert!(found_info.is_none()); + } + #[test] fn clear_info() { let rooms = create_test_instance(); diff --git a/src/models.rs b/src/models.rs index 3040a80..83802cb 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; /// RoomInfo has basic metadata about a room: its name, ID, etc. -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] pub struct RoomInfo { pub room_id: String, pub room_name: String, From 979dc8ea34ba3fa55c0ac53a252c91c40ec1a125 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Sun, 29 Nov 2020 21:29:35 +0000 Subject: [PATCH 08/10] Clearer test name for clearing room info. --- src/db/rooms.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/db/rooms.rs b/src/db/rooms.rs index b028cbd..4fa0e2d 100644 --- a/src/db/rooms.rs +++ b/src/db/rooms.rs @@ -412,7 +412,7 @@ mod tests { } #[test] - fn clear_info() { + fn clear_info_modifies_removes_requested_room() { let rooms = create_test_instance(); rooms From a65084e04a5df3b7f59a3a9f2abd7d2294bef33e Mon Sep 17 00:00:00 2001 From: projectmoon Date: Sun, 29 Nov 2020 21:33:46 +0000 Subject: [PATCH 09/10] Unit test for updating room info data. --- src/db/rooms.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/db/rooms.rs b/src/db/rooms.rs index 4fa0e2d..be79fd3 100644 --- a/src/db/rooms.rs +++ b/src/db/rooms.rs @@ -400,6 +400,36 @@ mod tests { assert_eq!(info, found_info.unwrap()); } + #[test] + fn insert_room_info_updates_data() { + let rooms = create_test_instance(); + + let mut info = RoomInfo { + room_id: matrix_sdk::identifiers::room_id!("!fakeroom:example.com") + .as_str() + .to_owned(), + room_name: "fake room name".to_owned(), + }; + + rooms + .insert_room_info(&info) + .expect("Could insert room info"); + + //Update info to have a new room name before inserting again. + info.room_name = "new fake room name".to_owned(); + + rooms + .insert_room_info(&info) + .expect("Could insert room info"); + + let found_info = rooms + .get_room_info("!fakeroom:example.com") + .expect("Error loading room info"); + + assert!(found_info.is_some()); + assert_eq!(info, found_info.unwrap()); + } + #[test] fn get_room_info_none_when_room_does_not_exist() { let rooms = create_test_instance(); From e177da9c256689c7eb90381f45ffb3addb81c865 Mon Sep 17 00:00:00 2001 From: projectmoon Date: Mon, 30 Nov 2020 19:53:26 +0000 Subject: [PATCH 10/10] Centralize record_room_information function. --- src/bot/event_handlers.rs | 29 +---------------------------- src/commands/management.rs | 10 +++------- src/lib.rs | 1 + src/logic.rs | 30 ++++++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 35 deletions(-) create mode 100644 src/logic.rs diff --git a/src/bot/event_handlers.rs b/src/bot/event_handlers.rs index 7d735cd..afb725f 100644 --- a/src/bot/event_handlers.rs +++ b/src/bot/event_handlers.rs @@ -1,7 +1,7 @@ use super::DiceBot; use crate::db::Database; use crate::error::BotError; -use crate::matrix; +use crate::logic::record_room_information; use async_trait::async_trait; use log::{debug, error, info, warn}; use matrix_sdk::{ @@ -92,33 +92,6 @@ fn should_process_event(db: &Database, room_id: &str, event_id: &str) -> bool { }) } -//TODO this needs to be moved to a common API layer. -/// Record the information about a room, including users in it. -pub async fn record_room_information( - client: &matrix_sdk::Client, - db: &crate::db::Database, - room: &matrix_sdk::Room, - our_username: &str, -) -> Result<(), crate::db::errors::DataError> { - let room_id_str = room.room_id.as_str(); - let usernames = matrix::get_users_in_room(&client, &room.room_id).await; - - let info = crate::models::RoomInfo { - room_id: room_id_str.to_owned(), - room_name: room.display_name(), - }; - - // TODO this and the username adding should be one whole - // transaction in the db. - db.rooms.insert_room_info(&info)?; - - usernames - .into_iter() - .filter(|username| username != our_username) - .map(|username| db.rooms.add_user_to_room(&username, room_id_str)) - .collect() //Make use of collect impl on Result. -} - /// This event emitter listens for messages with dice rolling commands. /// Originally adapted from the matrix-rust-sdk examples. #[async_trait] diff --git a/src/commands/management.rs b/src/commands/management.rs index 2243936..e71630b 100644 --- a/src/commands/management.rs +++ b/src/commands/management.rs @@ -1,6 +1,7 @@ use super::{Command, Execution}; use crate::context::Context; use crate::db::errors::DataError; +use crate::logic::record_room_information; use async_trait::async_trait; use matrix_sdk::identifiers::UserId; @@ -18,13 +19,8 @@ impl Command for ResyncCommand { let our_username: Option = ctx.matrix_client.user_id().await; let our_username: &str = our_username.as_ref().map_or("", UserId::as_str); - let result: ResyncResult = crate::bot::event_handlers::record_room_information( - ctx.matrix_client, - &ctx.db, - &ctx.room, - our_username, - ) - .await; + let result: ResyncResult = + record_room_information(ctx.matrix_client, &ctx.db, &ctx.room, our_username).await; let (plain, html) = match result { Ok(()) => { diff --git a/src/lib.rs b/src/lib.rs index 8340421..d67ade8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ pub mod db; pub mod dice; pub mod error; mod help; +pub mod logic; pub mod matrix; pub mod models; mod parser; diff --git a/src/logic.rs b/src/logic.rs new file mode 100644 index 0000000..8649956 --- /dev/null +++ b/src/logic.rs @@ -0,0 +1,30 @@ +use crate::db::errors::DataError; +use crate::matrix; +use crate::models::RoomInfo; +use matrix_sdk::{self, Client, Room}; + +/// Record the information about a room, including users in it. +pub async fn record_room_information( + client: &Client, + db: &crate::db::Database, + room: &Room, + our_username: &str, +) -> Result<(), DataError> { + let room_id_str = room.room_id.as_str(); + let usernames = matrix::get_users_in_room(&client, &room.room_id).await; + + let info = RoomInfo { + room_id: room_id_str.to_owned(), + room_name: room.display_name(), + }; + + // TODO this and the username adding should be one whole + // transaction in the db. + db.rooms.insert_room_info(&info)?; + + usernames + .into_iter() + .filter(|username| username != our_username) + .map(|username| db.rooms.add_user_to_room(&username, room_id_str)) + .collect() //Make use of collect impl on Result. +}