Notify user about new replies
This commit is contained in:
parent
43256fa4b1
commit
bc65186f00
4 changed files with 64 additions and 2 deletions
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Vec<Notification>, 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],
|
||||
|
|
|
@ -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<EventType> for i16 {
|
||||
fn from(value: EventType) -> i16 {
|
||||
match value {
|
||||
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> {
|
||||
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<i16> for EventType {
|
|||
pub struct Notification {
|
||||
pub id: i32,
|
||||
pub sender: DbActorProfile,
|
||||
pub post: Option<Post>,
|
||||
pub event_type: EventType,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
@ -58,9 +67,19 @@ impl TryFrom<&Row> for Notification {
|
|||
fn try_from(row: &Row) -> Result<Self, Self::Error> {
|
||||
let db_notification: DbNotification = row.try_get("notification")?;
|
||||
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 {
|
||||
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,
|
||||
};
|
||||
|
|
|
@ -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?;
|
||||
|
|
Loading…
Reference in a new issue