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,
|
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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],
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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?;
|
||||||
|
|
Loading…
Reference in a new issue