use db::sqlx; use model::pull_request::PullRequestReactionModel; use serde::Deserialize; use session::Session; use uuid::Uuid; use crate::{ AppService, error::AppError, pull_request::types::PullRequestReactionResponse, session_user, }; #[derive(Debug, Clone, Deserialize, utoipa::ToSchema)] pub struct AddPrReaction { pub reaction: String, } impl AppService { pub async fn pr_add_reaction( &self, ctx: &Session, wk_name: &str, repo_name: &str, number: i64, params: AddPrReaction, ) -> Result { let user_uid = session_user(ctx)?; let (repo_id, _) = self.pr_resolve_repo(ctx, wk_name, repo_name).await?; let pr = self.pr_resolve(repo_id, number).await?; let now = chrono::Utc::now(); let reaction = sqlx::query_as::<_, PullRequestReactionModel>( "INSERT INTO pull_request_reaction (id, pull_request, comment, \"user\", reaction, created_at) \ VALUES ($1, $2, NULL, $3, $4, $5) \ RETURNING id, pull_request, comment, \"user\", reaction, created_at", ) .bind(uuid::Uuid::now_v7()) .bind(pr.id) .bind(user_uid) .bind(¶ms.reaction) .bind(now) .fetch_one(self.db.writer()) .await .map_err(|e| AppError::DatabaseError(e.to_string()))?; let user = self.users_find_by_id(reaction.user).await?; Ok(PullRequestReactionResponse { id: reaction.id, user: crate::issues::types::issue_author(user), reaction: reaction.reaction, created_at: reaction.created_at, }) } pub async fn pr_remove_reaction( &self, ctx: &Session, wk_name: &str, repo_name: &str, _number: i64, reaction_id: Uuid, ) -> Result<(), AppError> { let user_uid = session_user(ctx)?; let (_repo_id, _) = self.pr_resolve_repo(ctx, wk_name, repo_name).await?; sqlx::query( "DELETE FROM pull_request_reaction WHERE id = $1 AND \"user\" = $2", ) .bind(reaction_id) .bind(user_uid) .execute(self.db.writer()) .await .map_err(|e| AppError::DatabaseError(e.to_string()))?; Ok(()) } pub async fn pr_comment_add_reaction( &self, ctx: &Session, wk_name: &str, repo_name: &str, _number: i64, comment_id: Uuid, params: AddPrReaction, ) -> Result { let user_uid = session_user(ctx)?; let (repo_id, _) = self.pr_resolve_repo(ctx, wk_name, repo_name).await?; let now = chrono::Utc::now(); let reaction = sqlx::query_as::<_, PullRequestReactionModel>( "INSERT INTO pull_request_reaction (id, pull_request, comment, \"user\", reaction, created_at) \ VALUES ($1, $2, $3, $4, $5, $6) \ RETURNING id, pull_request, comment, \"user\", reaction, created_at", ) .bind(uuid::Uuid::now_v7()) .bind(repo_id) .bind(comment_id) .bind(user_uid) .bind(¶ms.reaction) .bind(now) .fetch_one(self.db.writer()) .await .map_err(|e| AppError::DatabaseError(e.to_string()))?; let user = self.users_find_by_id(reaction.user).await?; Ok(PullRequestReactionResponse { id: reaction.id, user: crate::issues::types::issue_author(user), reaction: reaction.reaction, created_at: reaction.created_at, }) } pub async fn pr_comment_remove_reaction( &self, ctx: &Session, wk_name: &str, repo_name: &str, _number: i64, reaction_id: Uuid, ) -> Result<(), AppError> { let user_uid = session_user(ctx)?; let (_repo_id, _) = self.pr_resolve_repo(ctx, wk_name, repo_name).await?; sqlx::query( "DELETE FROM pull_request_reaction WHERE id = $1 AND \"user\" = $2", ) .bind(reaction_id) .bind(user_uid) .execute(self.db.writer()) .await .map_err(|e| AppError::DatabaseError(e.to_string()))?; Ok(()) } }