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::{
|
use matrix_sdk::{
|
||||||
self,
|
self,
|
||||||
events::{
|
events::{
|
||||||
room::member::MemberEventContent,
|
room::member::{MemberEventContent, MembershipState},
|
||||||
room::message::{MessageEventContent, NoticeMessageEventContent, TextMessageEventContent},
|
room::message::{MessageEventContent, NoticeMessageEventContent, TextMessageEventContent},
|
||||||
AnyMessageEventContent, StrippedStateEvent, SyncMessageEvent,
|
AnyMessageEventContent, StrippedStateEvent, SyncMessageEvent, SyncStateEvent,
|
||||||
},
|
},
|
||||||
Client, ClientConfig, EventEmitter, JsonStore, Room, SyncRoom, SyncSettings,
|
Client, ClientConfig, EventEmitter, JsonStore, Room, SyncRoom, SyncSettings,
|
||||||
};
|
};
|
||||||
|
@ -229,6 +229,37 @@ async fn should_process<'a>(
|
||||||
/// Originally adapted from the matrix-rust-sdk examples.
|
/// Originally adapted from the matrix-rust-sdk examples.
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EventEmitter for DiceBot {
|
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(
|
async fn on_stripped_state_member(
|
||||||
&self,
|
&self,
|
||||||
room: SyncRoom,
|
room: SyncRoom,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::db::errors::{DataError, MigrationError};
|
use crate::db::errors::{DataError, MigrationError};
|
||||||
use crate::db::migrations::{get_migration_version, Migrations};
|
use crate::db::migrations::{get_migration_version, Migrations};
|
||||||
|
use crate::db::rooms::Rooms;
|
||||||
use crate::db::variables::Variables;
|
use crate::db::variables::Variables;
|
||||||
use log::info;
|
use log::info;
|
||||||
use sled::{Config, Db};
|
use sled::{Config, Db};
|
||||||
|
@ -8,6 +9,7 @@ use std::path::Path;
|
||||||
pub mod data_migrations;
|
pub mod data_migrations;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod migrations;
|
pub mod migrations;
|
||||||
|
pub mod rooms;
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
pub mod variables;
|
pub mod variables;
|
||||||
|
|
||||||
|
@ -16,6 +18,7 @@ pub struct Database {
|
||||||
db: Db,
|
db: Db,
|
||||||
pub(crate) variables: Variables,
|
pub(crate) variables: Variables,
|
||||||
pub(crate) migrations: Migrations,
|
pub(crate) migrations: Migrations,
|
||||||
|
pub(crate) rooms: Rooms,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Database {
|
impl Database {
|
||||||
|
@ -26,6 +29,7 @@ impl Database {
|
||||||
db: db.clone(),
|
db: db.clone(),
|
||||||
variables: Variables::new(&db)?,
|
variables: Variables::new(&db)?,
|
||||||
migrations: Migrations(migrations),
|
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.