forked from lavina/lavina
persistence of chat messages
This commit is contained in:
parent
f401aa786e
commit
5c07c8368d
|
@ -30,3 +30,22 @@ Make sure `xmpp.key` starts and ends with:
|
||||||
XMPP XSDs - [https://xmpp.org/schemas/index.shtml]
|
XMPP XSDs - [https://xmpp.org/schemas/index.shtml]
|
||||||
|
|
||||||
IRC modern spec - [https://modern.ircdocs.horse/]
|
IRC modern spec - [https://modern.ircdocs.horse/]
|
||||||
|
|
||||||
|
## Initializing DB with some users
|
||||||
|
|
||||||
|
sqlite3 db.sqlite < test/init_state.sql
|
||||||
|
|
||||||
|
Same test migration could be used for integration tests in the future.
|
||||||
|
|
||||||
|
## Using irssi
|
||||||
|
|
||||||
|
irssi in a TUI-based IRC client.
|
||||||
|
|
||||||
|
Connecting:
|
||||||
|
|
||||||
|
/connect -nocap <address> [<port> [<password> [<nick>]]]
|
||||||
|
|
||||||
|
Password should be the same as in storage.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
/connect -nocap 127.0.0.1 6667 parolchik1 kek
|
|
@ -61,9 +61,9 @@ impl Storage {
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_new_room(&mut self, name: &str, topic: &str) -> Result<()> {
|
pub async fn create_new_room(&mut self, name: &str, topic: &str) -> Result<u32> {
|
||||||
let mut executor = self.conn.lock().await;
|
let mut executor = self.conn.lock().await;
|
||||||
let _: (u32,) = sqlx::query_as(
|
let (id,): (u32,) = sqlx::query_as(
|
||||||
"insert into rooms(name, topic)
|
"insert into rooms(name, topic)
|
||||||
values (?, ?)
|
values (?, ?)
|
||||||
returning id;",
|
returning id;",
|
||||||
|
@ -73,6 +73,23 @@ impl Storage {
|
||||||
.fetch_one(&mut *executor)
|
.fetch_one(&mut *executor)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
Ok(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn insert_message(&mut self, room_id: u32, id: u32, content: &str) -> Result<()> {
|
||||||
|
let mut executor = self.conn.lock().await;
|
||||||
|
let (_,): (u32,) = sqlx::query_as(
|
||||||
|
"insert into messages(room_id, id, content)
|
||||||
|
values (?, ?, ?);
|
||||||
|
update rooms set message_count = message_count + 1 where id = ?;",
|
||||||
|
)
|
||||||
|
.bind(room_id)
|
||||||
|
.bind(id)
|
||||||
|
.bind(content)
|
||||||
|
.bind(room_id)
|
||||||
|
.fetch_one(&mut *executor)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,10 +63,12 @@ impl RoomRegistry {
|
||||||
// room exists, but was not loaded
|
// room exists, but was not loaded
|
||||||
log::debug!("Loading room {}...", &room_id.0);
|
log::debug!("Loading room {}...", &room_id.0);
|
||||||
let room = Room {
|
let room = Room {
|
||||||
|
storage_id: stored_room.id,
|
||||||
room_id: room_id.clone(),
|
room_id: room_id.clone(),
|
||||||
subscriptions: HashMap::new(),
|
subscriptions: HashMap::new(), // TODO figure out how to populate subscriptions
|
||||||
topic: stored_room.topic.into(),
|
topic: stored_room.topic.into(),
|
||||||
message_count: stored_room.message_count,
|
message_count: stored_room.message_count,
|
||||||
|
storage: inner.storage.clone(),
|
||||||
};
|
};
|
||||||
let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room)));
|
let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room)));
|
||||||
inner.rooms.insert(room_id, room_handle.clone());
|
inner.rooms.insert(room_id, room_handle.clone());
|
||||||
|
@ -76,12 +78,14 @@ impl RoomRegistry {
|
||||||
// room does not exist, create it and load
|
// room does not exist, create it and load
|
||||||
log::debug!("Creating room {}...", &room_id.0);
|
log::debug!("Creating room {}...", &room_id.0);
|
||||||
let topic = "New room";
|
let topic = "New room";
|
||||||
let _ = inner.storage.create_new_room(&*room_id.0, &*topic).await?;
|
let id = inner.storage.create_new_room(&*room_id.0, &*topic).await?;
|
||||||
let room = Room {
|
let room = Room {
|
||||||
|
storage_id: id,
|
||||||
room_id: room_id.clone(),
|
room_id: room_id.clone(),
|
||||||
subscriptions: HashMap::new(),
|
subscriptions: HashMap::new(),
|
||||||
topic: topic.into(),
|
topic: topic.into(),
|
||||||
message_count: 0,
|
message_count: 0,
|
||||||
|
storage: inner.storage.clone(),
|
||||||
};
|
};
|
||||||
let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room)));
|
let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room)));
|
||||||
inner.rooms.insert(room_id, room_handle.clone());
|
inner.rooms.insert(room_id, room_handle.clone());
|
||||||
|
@ -135,7 +139,7 @@ impl RoomHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_message(&self, player_id: PlayerId, body: Str) {
|
pub async fn send_message(&self, player_id: PlayerId, body: Str) {
|
||||||
let lock = self.0.read().await;
|
let mut lock = self.0.write().await;
|
||||||
lock.send_message(player_id, body).await;
|
lock.send_message(player_id, body).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,10 +168,12 @@ impl RoomHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Room {
|
struct Room {
|
||||||
|
storage_id: u32,
|
||||||
room_id: RoomId,
|
room_id: RoomId,
|
||||||
subscriptions: HashMap<PlayerId, PlayerHandle>,
|
subscriptions: HashMap<PlayerId, PlayerHandle>,
|
||||||
message_count: u32,
|
message_count: u32,
|
||||||
topic: Str,
|
topic: Str,
|
||||||
|
storage: Storage,
|
||||||
}
|
}
|
||||||
impl Room {
|
impl Room {
|
||||||
async fn add_subscriber(&mut self, player_id: PlayerId, player_handle: PlayerHandle) {
|
async fn add_subscriber(&mut self, player_id: PlayerId, player_handle: PlayerHandle) {
|
||||||
|
@ -180,14 +186,17 @@ impl Room {
|
||||||
self.broadcast_update(update, &player_id).await;
|
self.broadcast_update(update, &player_id).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_message(&self, author_id: PlayerId, body: Str) {
|
async fn send_message(&mut self, author_id: PlayerId, body: Str) -> Result<()> {
|
||||||
tracing::info!("Adding a message to room");
|
tracing::info!("Adding a message to room");
|
||||||
|
self.storage.insert_message(self.storage_id, self.message_count, &body).await?;
|
||||||
|
self.message_count += 1;
|
||||||
let update = Updates::NewMessage {
|
let update = Updates::NewMessage {
|
||||||
room_id: self.room_id.clone(),
|
room_id: self.room_id.clone(),
|
||||||
author_id: author_id.clone(),
|
author_id: author_id.clone(),
|
||||||
body,
|
body,
|
||||||
};
|
};
|
||||||
self.broadcast_update(update, &author_id).await;
|
self.broadcast_update(update, &author_id).await;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn broadcast_update(&self, update: Updates, except: &PlayerId) {
|
async fn broadcast_update(&self, update: Updates, except: &PlayerId) {
|
||||||
|
|
Loading…
Reference in New Issue