Room State Management #44
35
src/bot.rs
35
src/bot.rs
|
@ -11,9 +11,9 @@ use matrix_sdk::Error as MatrixError;
|
|||
use matrix_sdk::{
|
||||
self,
|
||||
events::{
|
||||
room::member::MemberEventContent,
|
||||
room::member::{MemberEventContent, MembershipState},
|
||||
room::message::{MessageEventContent, NoticeMessageEventContent, TextMessageEventContent},
|
||||
AnyMessageEventContent, StrippedStateEvent, SyncMessageEvent,
|
||||
AnyMessageEventContent, StrippedStateEvent, SyncMessageEvent, SyncStateEvent,
|
||||
},
|
||||
Client, ClientConfig, EventEmitter, JsonStore, Room, SyncRoom, SyncSettings,
|
||||
};
|
||||
|
@ -229,6 +229,37 @@ 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<MemberEventContent>,
|
||||
) {
|
||||
//When joining a channel, we get join events from other users.
|
||||
//content is MemberContent, and it has a membership type.
|
||||
|
||||
//Ignore if state_key is our username, because we only care about other users.
|
||||
let event_affects_us = if let Some(our_user_id) = self.client.user_id().await {
|
||||
room_member.state_key == our_user_id
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let should_add = match room_member.content.membership {
|
||||
MembershipState::Join => true,
|
||||
MembershipState::Leave | MembershipState::Ban => false,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
//if event affects us and is leave/ban, delete all our info.
|
||||
//if event does not affect us, delete info only for that user.
|
||||
|
||||
//TODO replace with call to new db.rooms thing.
|
||||
println!(
|
||||
"member {} recorded with action {:?} to/from db.",
|
||||
room_member.state_key, should_add
|
||||
);
|
||||
}
|
||||
|
||||
async fn on_stripped_state_member(
|
||||
&self,
|
||||
room: SyncRoom,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::db::errors::{DataError, MigrationError};
|
||||
use crate::db::migrations::{get_migration_version, Migrations};
|
||||
use crate::db::rooms::Rooms;
|
||||
use crate::db::variables::Variables;
|
||||
use log::info;
|
||||
use sled::{Config, Db};
|
||||
|
@ -8,6 +9,7 @@ use std::path::Path;
|
|||
pub mod data_migrations;
|
||||
pub mod errors;
|
||||
pub mod migrations;
|
||||
pub mod rooms;
|
||||
pub mod schema;
|
||||
pub mod variables;
|
||||
|
||||
|
@ -16,6 +18,7 @@ pub struct Database {
|
|||
db: Db,
|
||||
pub(crate) variables: Variables,
|
||||
pub(crate) migrations: Migrations,
|
||||
pub(crate) rooms: Rooms,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
|
@ -26,6 +29,7 @@ impl Database {
|
|||
db: db.clone(),
|
||||
variables: Variables::new(&db)?,
|
||||
migrations: Migrations(migrations),
|
||||
rooms: Rooms::new(&db)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
use crate::db::errors::DataError;
|
||||
use crate::db::schema::convert_i32;
|
||||
use byteorder::LittleEndian;
|
||||
use sled::transaction::{abort, TransactionalTree};
|
||||
use sled::Transactional;
|
||||
use sled::Tree;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::convert::From;
|
||||
use std::str;
|
||||
use zerocopy::byteorder::I32;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Rooms {
|
||||
/// Room ID -> RoomInfo struct (single entries)
|
||||
pub(in crate::db) roomid_roominfo: Tree,
|
||||
|
||||
/// Room ID -> list of usernames in room.
|
||||
pub(in crate::db) roomid_usernames: Tree,
|
||||
|
||||
/// Username -> list of room IDs user is in.
|
||||
pub(in crate::db) username_roomids: Tree,
|
||||
}
|
||||
|
||||
// /// Request soemthing by a username and room ID.
|
||||
// pub struct UserAndRoom<'a>(pub &'a str, pub &'a str);
|
||||
|
||||
// fn to_vec(value: &UserAndRoom<'_>) -> Vec<u8> {
|
||||
// let mut bytes = vec![];
|
||||
// bytes.extend_from_slice(value.0.as_bytes());
|
||||
// bytes.push(0xfe);
|
||||
// bytes.extend_from_slice(value.1.as_bytes());
|
||||
// bytes
|
||||
// }
|
||||
|
||||
// impl From<UserAndRoom<'_>> for Vec<u8> {
|
||||
// fn from(value: UserAndRoom) -> Vec<u8> {
|
||||
// to_vec(&value)
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl From<&UserAndRoom<'_>> for Vec<u8> {
|
||||
// fn from(value: &UserAndRoom) -> Vec<u8> {
|
||||
// to_vec(value)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Rooms {
|
||||
pub(in crate::db) fn new(db: &sled::Db) -> Result<Rooms, sled::Error> {
|
||||
Ok(Rooms {
|
||||
roomid_roominfo: db.open_tree("roomid_roominfo")?,
|
||||
roomid_usernames: db.open_tree("roomid_usernames")?,
|
||||
username_roomids: db.open_tree("username_roomids")?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_user_to_room(&self, username: &str, room_id: &str) -> Result<(), DataError> {
|
||||
//in txn:
|
||||
//get or create list of users in room
|
||||
//get or create list of rooms user is in
|
||||
//deserialize/create set and add username to set for roomid
|
||||
//deserialize/create set and add roomid to set for username
|
||||
//store both again
|
||||
projectmoon marked this conversation as resolved
|
||||
let user_to_rooms: HashSet<String> = self
|
||||
.username_roomids
|
||||
.get(username.as_bytes())?
|
||||
.map(|bytes| bincode::deserialize::<HashSet<String>>(&bytes))
|
||||
.unwrap_or(Ok(HashSet::new()))?;
|
||||
|
||||
let room_to_users: HashSet<String> = self
|
||||
.roomid_usernames
|
||||
.get(room_id.as_bytes())?
|
||||
.map(|bytes| bincode::deserialize::<HashSet<String>>(&bytes))
|
||||
.unwrap_or(Ok(HashSet::new()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_user_from_room(&self, username: &str, room_id: &str) -> Result<(), DataError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Perhaps move this and
TxableTree
into a common part of the database code. Maybe also convert it to a trait. The atomicity issues withTree
instances also should be addressed. Usefetch_and_update
when it's a regular Tree, and the existing code if it's aTransactionalTree
(since the atomicity is controlled by the transaction).Deferring to a future changeset.