use crate::api::chat::ChatMsg; use crate::repo::Repo; use chrono::{DateTime, Utc}; use sqlx::PgPool; #[derive(Clone)] pub struct MessageRepository { pool: PgPool } impl Repo for MessageRepository { type Target = ChatMsg; fn new(pool: PgPool) -> Self { Self { pool } } // TODO: caching with redis async fn get_by_id(&self, id: i64) -> Option { sqlx::query!( "SELECT u.username, u.nickname, u.id as user_id, m.content, m.created_at FROM messages m JOIN users u ON m.user_id = u.id WHERE m.id = $1", id ).fetch_optional(&self.pool).await.ok().flatten().map(|row| ChatMsg { display_name: Some(row.nickname.unwrap_or(row.username)), user_id: row.user_id, text: row.content, timestamp: row.created_at, }) } } impl MessageRepository { // TODO! caching with redis pub async fn create_new( &self, uid: i64, channel_id: i64, text: &str, created_at: DateTime ) -> Result { sqlx::query!( "INSERT INTO messages (channel_id, user_id, content, created_at) VALUES ($1, $2, $3, $4) RETURNING id", channel_id, uid, text, created_at ).fetch_optional(&self.pool).await.and_then(|row| row.map(|r| r.id).ok_or(sqlx::Error::RowNotFound)) } /// TODO: caching with redis pub async fn get_by_channel(&self, channel_id: i64, limit: usize) -> Result, sqlx::Error> { sqlx::query!( "SELECT u.username, u.nickname, u.id as user_id, m.content, m.created_at FROM messages m JOIN users u ON m.user_id = u.id WHERE m.channel_id = $1 ORDER BY m.created_at DESC LIMIT $2", channel_id, limit as i64 ).fetch_all(&self.pool).await.map(|messages| { messages.into_iter().rev().map(|msg| { ChatMsg { display_name: Some(msg.nickname.unwrap_or(msg.username)), user_id: msg.user_id, text: msg.content, timestamp: msg.created_at, } }).collect::>() }) } }