diff --git a/migrations/V0015__post_reaction__add_activity_id.sql b/migrations/V0015__post_reaction__add_activity_id.sql new file mode 100644 index 0000000..534a31a --- /dev/null +++ b/migrations/V0015__post_reaction__add_activity_id.sql @@ -0,0 +1 @@ +ALTER TABLE post_reaction ADD COLUMN activity_id VARCHAR(250) UNIQUE; diff --git a/migrations/schema.sql b/migrations/schema.sql index dbe75f5..0d35c7b 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -51,6 +51,7 @@ CREATE TABLE post_reaction ( id UUID PRIMARY KEY, author_id UUID NOT NULL REFERENCES actor_profile (id) ON DELETE CASCADE, post_id UUID NOT NULL REFERENCES post (id) ON DELETE CASCADE, + activity_id VARCHAR(250) UNIQUE, created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), UNIQUE (author_id, post_id) ); diff --git a/src/activitypub/receiver.rs b/src/activitypub/receiver.rs index 0cd75ce..7767d8d 100644 --- a/src/activitypub/receiver.rs +++ b/src/activitypub/receiver.rs @@ -389,7 +389,12 @@ pub async fn receive_activity( post.id }, }; - create_reaction(db_client, &author.id, &post_id).await?; + create_reaction( + db_client, + &author.id, + &post_id, + Some(&activity.id), + ).await?; }, (FOLLOW, _) => { let source_profile = get_or_fetch_profile_by_actor_id( diff --git a/src/mastodon_api/statuses/views.rs b/src/mastodon_api/statuses/views.rs index ed84726..513e17b 100644 --- a/src/mastodon_api/statuses/views.rs +++ b/src/mastodon_api/statuses/views.rs @@ -233,7 +233,7 @@ async fn favourite( return Err(HttpError::NotFoundError("post")); }; let reaction_created = match create_reaction( - db_client, ¤t_user.id, &status_id, + db_client, ¤t_user.id, &status_id, None, ).await { Ok(_) => { post.reaction_count += 1; diff --git a/src/models/reactions/mod.rs b/src/models/reactions/mod.rs index 84c032e..ec98503 100644 --- a/src/models/reactions/mod.rs +++ b/src/models/reactions/mod.rs @@ -1 +1,2 @@ pub mod queries; +mod types; diff --git a/src/models/reactions/queries.rs b/src/models/reactions/queries.rs index c528168..3c9d93f 100644 --- a/src/models/reactions/queries.rs +++ b/src/models/reactions/queries.rs @@ -9,21 +9,25 @@ use crate::models::posts::queries::{ get_post_author, }; use crate::utils::id::new_uuid; +use super::types::DbReaction; pub async fn create_reaction( db_client: &mut impl GenericClient, author_id: &Uuid, post_id: &Uuid, -) -> Result<(), DatabaseError> { + activity_id: Option<&String>, +) -> Result { let transaction = db_client.transaction().await?; let reaction_id = new_uuid(); - transaction.execute( + let row = transaction.query_one( " - INSERT INTO post_reaction (id, author_id, post_id) - VALUES ($1, $2, $3) + INSERT INTO post_reaction (id, author_id, post_id, activity_id) + VALUES ($1, $2, $3, $4) + RETURNING post_reaction ", - &[&reaction_id, &author_id, &post_id], + &[&reaction_id, &author_id, &post_id, &activity_id], ).await.map_err(catch_unique_violation("reaction"))?; + let reaction: DbReaction = row.try_get("post_reaction")?; update_reaction_count(&transaction, post_id, 1).await?; let post_author = get_post_author(&transaction, post_id).await?; if post_author.is_local() && post_author.id != *author_id { @@ -33,9 +37,9 @@ pub async fn create_reaction( &post_author.id, post_id, ).await?; - } + }; transaction.commit().await?; - Ok(()) + Ok(reaction) } pub async fn delete_reaction( diff --git a/src/models/reactions/types.rs b/src/models/reactions/types.rs new file mode 100644 index 0000000..0d0869c --- /dev/null +++ b/src/models/reactions/types.rs @@ -0,0 +1,13 @@ +use chrono::{DateTime, Utc}; +use postgres_types::FromSql; +use uuid::Uuid; + +#[derive(FromSql)] +#[postgres(name = "post_reaction")] +pub struct DbReaction { + pub id: Uuid, + pub author_id: Uuid, + pub post_id: Uuid, + pub activity_id: Option, + pub created_at: DateTime, +}