Notify user about new replies

This commit is contained in:
silverpill 2021-10-15 00:27:39 +00:00
parent 43256fa4b1
commit bc65186f00
4 changed files with 64 additions and 2 deletions

View file

@ -25,15 +25,20 @@ impl ApiNotification {
notification.sender, notification.sender,
instance_url, instance_url,
); );
let status = notification.post.map(|post| {
Status::from_post(post, instance_url)
});
let event_type_mastodon = match notification.event_type { let event_type_mastodon = match notification.event_type {
EventType::Follow => "follow", EventType::Follow => "follow",
EventType::FollowRequest => "follow_request",
EventType::Reply => "reply",
}; };
Self { Self {
id: notification.id.to_string(), id: notification.id.to_string(),
event_type: event_type_mastodon.to_string(), event_type: event_type_mastodon.to_string(),
created_at: notification.created_at, created_at: notification.created_at,
account, account,
status: None, status,
} }
} }
} }

View file

@ -4,6 +4,7 @@ use tokio_postgres::GenericClient;
use uuid::Uuid; use uuid::Uuid;
use crate::errors::DatabaseError; use crate::errors::DatabaseError;
use crate::models::posts::types::DbPost;
use super::types::{EventType, Notification}; use super::types::{EventType, Notification};
pub async fn create_notification( pub async fn create_notification(
@ -26,16 +27,51 @@ pub async fn create_notification(
Ok(()) 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( pub async fn get_notifications(
db_client: &impl GenericClient, db_client: &impl GenericClient,
recipient_id: &Uuid, recipient_id: &Uuid,
) -> Result<Vec<Notification>, DatabaseError> { ) -> Result<Vec<Notification>, DatabaseError> {
let rows = db_client.query( 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 FROM notification
JOIN actor_profile AS sender JOIN actor_profile AS sender
ON notification.sender_id = sender.id 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 WHERE recipient_id = $1
", ",
&[&recipient_id], &[&recipient_id],

View file

@ -6,6 +6,8 @@ use tokio_postgres::Row;
use uuid::Uuid; use uuid::Uuid;
use crate::errors::{ConversionError, DatabaseError}; use crate::errors::{ConversionError, DatabaseError};
use crate::models::attachments::types::DbMediaAttachment;
use crate::models::posts::types::{DbPost, Post};
use crate::models::profiles::types::DbActorProfile; use crate::models::profiles::types::DbActorProfile;
#[allow(dead_code)] #[allow(dead_code)]
@ -22,12 +24,16 @@ struct DbNotification {
pub enum EventType { pub enum EventType {
Follow, Follow,
FollowRequest,
Reply,
} }
impl From<EventType> for i16 { impl From<EventType> for i16 {
fn from(value: EventType) -> i16 { fn from(value: EventType) -> i16 {
match value { match value {
EventType::Follow => 1, EventType::Follow => 1,
EventType::FollowRequest => 2,
EventType::Reply => 3,
} }
} }
} }
@ -38,6 +44,8 @@ impl TryFrom<i16> for EventType {
fn try_from(value: i16) -> Result<Self, Self::Error> { fn try_from(value: i16) -> Result<Self, Self::Error> {
let event_type = match value { let event_type = match value {
1 => Self::Follow, 1 => Self::Follow,
2 => Self::FollowRequest,
3 => Self::Reply,
_ => return Err(ConversionError), _ => return Err(ConversionError),
}; };
Ok(event_type) Ok(event_type)
@ -47,6 +55,7 @@ impl TryFrom<i16> for EventType {
pub struct Notification { pub struct Notification {
pub id: i32, pub id: i32,
pub sender: DbActorProfile, pub sender: DbActorProfile,
pub post: Option<Post>,
pub event_type: EventType, pub event_type: EventType,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
} }
@ -58,9 +67,19 @@ impl TryFrom<&Row> for Notification {
fn try_from(row: &Row) -> Result<Self, Self::Error> { fn try_from(row: &Row) -> Result<Self, Self::Error> {
let db_notification: DbNotification = row.try_get("notification")?; let db_notification: DbNotification = row.try_get("notification")?;
let db_sender: DbActorProfile = row.try_get("sender")?; let db_sender: DbActorProfile = row.try_get("sender")?;
let maybe_db_post: Option<DbPost> = 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<DbMediaAttachment> = row.try_get("attachments")?;
Some(Post::new(db_post, db_post_author, db_attachments))
},
None => None,
};
let notification = Self { let notification = Self {
id: db_notification.id, id: db_notification.id,
sender: db_sender, sender: db_sender,
post: maybe_post,
event_type: EventType::try_from(db_notification.event_type)?, event_type: EventType::try_from(db_notification.event_type)?,
created_at: db_notification.created_at, created_at: db_notification.created_at,
}; };

View file

@ -11,6 +11,7 @@ use crate::models::cleanup::{
find_orphaned_ipfs_objects, find_orphaned_ipfs_objects,
DeletionQueue, DeletionQueue,
}; };
use crate::models::notifications::queries::create_reply_notification;
use crate::models::profiles::queries::update_post_count; use crate::models::profiles::queries::update_post_count;
use super::types::{DbPost, Post, PostCreateData}; 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?; 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 { if let Some(in_reply_to_id) = &db_post.in_reply_to_id {
update_reply_count(&transaction, in_reply_to_id, 1).await?; update_reply_count(&transaction, in_reply_to_id, 1).await?;
create_reply_notification(&transaction, &db_post).await?;
} }
transaction.commit().await?; transaction.commit().await?;