diff options
Diffstat (limited to 'src/channel/repo/messages.rs')
| -rw-r--r-- | src/channel/repo/messages.rs | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/channel/repo/messages.rs b/src/channel/repo/messages.rs new file mode 100644 index 0000000..bdb0d29 --- /dev/null +++ b/src/channel/repo/messages.rs @@ -0,0 +1,111 @@ +use std::fmt; + +use sqlx::{sqlite::Sqlite, SqliteConnection, Transaction}; + +use super::channels::Id as ChannelId; +use crate::{ + clock::DateTime, error::BoxedError, id::Id as BaseId, login::repo::logins::Id as LoginId, +}; + +pub trait Provider { + fn messages(&mut self) -> Messages; +} + +impl<'c> Provider for Transaction<'c, Sqlite> { + fn messages(&mut self) -> Messages { + Messages(self) + } +} + +pub struct Messages<'t>(&'t mut SqliteConnection); + +#[derive(Clone, Debug, serde::Serialize)] +pub struct Message { + pub id: Id, + pub sender: LoginId, + pub channel: ChannelId, + pub body: String, + pub sent_at: DateTime, +} + +impl<'c> Messages<'c> { + pub async fn create( + &mut self, + sender: &LoginId, + channel: &ChannelId, + body: &str, + sent_at: &DateTime, + ) -> Result<Message, BoxedError> { + let id = Id::generate(); + + let message = sqlx::query_as!( + Message, + r#" + insert into message + (id, sender, channel, body, sent_at) + values ($1, $2, $3, $4, $5) + returning + id as "id: Id", + sender as "sender: LoginId", + channel as "channel: ChannelId", + body, + sent_at as "sent_at: DateTime" + "#, + id, + sender, + channel, + body, + sent_at, + ) + .fetch_one(&mut *self.0) + .await?; + + Ok(message) + } + + pub async fn all(&mut self, channel: &ChannelId) -> Result<Vec<Message>, BoxedError> { + let messages = sqlx::query_as!( + Message, + r#" + select + id as "id: Id", + sender as "sender: LoginId", + channel as "channel: ChannelId", + body, + sent_at as "sent_at: DateTime" + from message + where channel = $1 + order by sent_at asc + "#, + channel, + ) + .fetch_all(&mut *self.0) + .await?; + + Ok(messages) + } +} + +/// Stable identifier for a [Message]. Prefixed with `M`. +#[derive(Clone, Debug, Eq, Hash, PartialEq, sqlx::Type, serde::Deserialize, serde::Serialize)] +#[sqlx(transparent)] +#[serde(transparent)] +pub struct Id(BaseId); + +impl From<BaseId> for Id { + fn from(id: BaseId) -> Self { + Self(id) + } +} + +impl Id { + pub fn generate() -> Self { + BaseId::generate("M") + } +} + +impl fmt::Display for Id { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} |
