diff --git a/src/mastodon_api/notifications/types.rs b/src/mastodon_api/notifications/types.rs index 516bd3f..aec92b2 100644 --- a/src/mastodon_api/notifications/types.rs +++ b/src/mastodon_api/notifications/types.rs @@ -25,15 +25,20 @@ impl ApiNotification { notification.sender, instance_url, ); + let status = notification.post.map(|post| { + Status::from_post(post, instance_url) + }); let event_type_mastodon = match notification.event_type { EventType::Follow => "follow", + EventType::FollowRequest => "follow_request", + EventType::Reply => "reply", }; Self { id: notification.id.to_string(), event_type: event_type_mastodon.to_string(), created_at: notification.created_at, account, - status: None, + status, } } } diff --git a/src/models/notifications/queries.rs b/src/models/notifications/queries.rs index a5415fc..054f0ff 100644 --- a/src/models/notifications/queries.rs +++ b/src/models/notifications/queries.rs @@ -4,6 +4,7 @@ use tokio_postgres::GenericClient; use uuid::Uuid; use crate::errors::DatabaseError; +use crate::models::posts::types::DbPost; use super::types::{EventType, Notification}; pub async fn create_notification( @@ -26,16 +27,51 @@ pub async fn create_notification( Ok(()) } +pub async fn create_reply_notification( + db_client: &impl GenericClient, + reply: &DbPost, +) -> Result<(), DatabaseError> { + let event_type: i16 = EventType::Reply.into(); + db_client.execute( + " + INSERT INTO notification ( + sender_id, + recipient_id, + post_id, + event_type + ) + SELECT $1, post.author_id, $2, $3 + FROM post WHERE id = $4 + ", + &[ + &reply.author_id, + &reply.id, + &event_type, + &reply.in_reply_to_id, + ], + ).await?; + Ok(()) +} + pub async fn get_notifications( db_client: &impl GenericClient, recipient_id: &Uuid, ) -> Result, DatabaseError> { let rows = db_client.query( " - SELECT notification, sender + SELECT + notification, sender, post, post_author, + ARRAY( + SELECT media_attachment + FROM media_attachment WHERE post_id = post.id + ) AS attachments FROM notification JOIN actor_profile AS sender ON notification.sender_id = sender.id + LEFT JOIN post + ON notification.post_id = post.id + LEFT JOIN actor_profile AS post_author + ON post.author_id = post_author.id WHERE recipient_id = $1 ", &[&recipient_id], diff --git a/src/models/notifications/types.rs b/src/models/notifications/types.rs index 4a82417..49a39fb 100644 --- a/src/models/notifications/types.rs +++ b/src/models/notifications/types.rs @@ -6,6 +6,8 @@ use tokio_postgres::Row; use uuid::Uuid; use crate::errors::{ConversionError, DatabaseError}; +use crate::models::attachments::types::DbMediaAttachment; +use crate::models::posts::types::{DbPost, Post}; use crate::models::profiles::types::DbActorProfile; #[allow(dead_code)] @@ -22,12 +24,16 @@ struct DbNotification { pub enum EventType { Follow, + FollowRequest, + Reply, } impl From for i16 { fn from(value: EventType) -> i16 { match value { EventType::Follow => 1, + EventType::FollowRequest => 2, + EventType::Reply => 3, } } } @@ -38,6 +44,8 @@ impl TryFrom for EventType { fn try_from(value: i16) -> Result { let event_type = match value { 1 => Self::Follow, + 2 => Self::FollowRequest, + 3 => Self::Reply, _ => return Err(ConversionError), }; Ok(event_type) @@ -47,6 +55,7 @@ impl TryFrom for EventType { pub struct Notification { pub id: i32, pub sender: DbActorProfile, + pub post: Option, pub event_type: EventType, pub created_at: DateTime, } @@ -58,9 +67,19 @@ impl TryFrom<&Row> for Notification { fn try_from(row: &Row) -> Result { let db_notification: DbNotification = row.try_get("notification")?; let db_sender: DbActorProfile = row.try_get("sender")?; + let maybe_db_post: Option = row.try_get("post")?; + let maybe_post = match maybe_db_post { + Some(db_post) => { + let db_post_author: DbActorProfile = row.try_get("post_author")?; + let db_attachments: Vec = row.try_get("attachments")?; + Some(Post::new(db_post, db_post_author, db_attachments)) + }, + None => None, + }; let notification = Self { id: db_notification.id, sender: db_sender, + post: maybe_post, event_type: EventType::try_from(db_notification.event_type)?, created_at: db_notification.created_at, }; diff --git a/src/models/posts/queries.rs b/src/models/posts/queries.rs index 0ad614a..4121dc5 100644 --- a/src/models/posts/queries.rs +++ b/src/models/posts/queries.rs @@ -11,6 +11,7 @@ use crate::models::cleanup::{ find_orphaned_ipfs_objects, DeletionQueue, }; +use crate::models::notifications::queries::create_reply_notification; use crate::models::profiles::queries::update_post_count; use super::types::{DbPost, Post, PostCreateData}; @@ -125,6 +126,7 @@ pub async fn create_post( let author = update_post_count(&transaction, &db_post.author_id, 1).await?; if let Some(in_reply_to_id) = &db_post.in_reply_to_id { update_reply_count(&transaction, in_reply_to_id, 1).await?; + create_reply_notification(&transaction, &db_post).await?; } transaction.commit().await?;