Add action attributes to Status entity when served to authorized user
This commit is contained in:
parent
d2462e9e96
commit
b6be5c8489
9 changed files with 119 additions and 9 deletions
|
@ -15,6 +15,7 @@ use crate::errors::HttpError;
|
|||
use crate::mastodon_api::statuses::types::Status;
|
||||
use crate::mastodon_api::oauth::auth::get_current_user;
|
||||
use crate::mastodon_api::users::views::create_user_view;
|
||||
use crate::models::posts::helpers::get_actions_for_posts;
|
||||
use crate::models::posts::queries::get_posts_by_author;
|
||||
use crate::models::profiles::queries::{
|
||||
get_profile_by_id,
|
||||
|
@ -194,12 +195,24 @@ async fn unfollow(
|
|||
|
||||
#[get("/{account_id}/statuses")]
|
||||
async fn get_account_statuses(
|
||||
auth: Option<BearerAuth>,
|
||||
config: web::Data<Config>,
|
||||
db_pool: web::Data<Pool>,
|
||||
web::Path(account_id): web::Path<Uuid>,
|
||||
) -> Result<HttpResponse, HttpError> {
|
||||
let db_client = &**get_database_client(&db_pool).await?;
|
||||
let posts = get_posts_by_author(db_client, &account_id).await?;
|
||||
let maybe_current_user = match auth {
|
||||
Some(auth) => Some(get_current_user(db_client, auth.token()).await?),
|
||||
None => None,
|
||||
};
|
||||
let mut posts = get_posts_by_author(db_client, &account_id).await?;
|
||||
if let Some(user) = maybe_current_user {
|
||||
get_actions_for_posts(
|
||||
db_client,
|
||||
&user.id,
|
||||
posts.iter_mut().collect(),
|
||||
).await?;
|
||||
}
|
||||
let statuses: Vec<Status> = posts.into_iter()
|
||||
.map(|post| Status::from_post(post, &config.instance_url()))
|
||||
.collect();
|
||||
|
|
|
@ -42,7 +42,7 @@ impl Status {
|
|||
replies_count: post.reply_count,
|
||||
favourites_count: post.reaction_count,
|
||||
media_attachments: attachments,
|
||||
favourited: false,
|
||||
favourited: post.actions.map_or(false, |actions| actions.favourited),
|
||||
ipfs_cid: post.ipfs_cid,
|
||||
token_id: post.token_id,
|
||||
token_tx_id: post.token_tx_id,
|
||||
|
|
|
@ -16,6 +16,10 @@ use crate::ipfs::utils::{IPFS_LOGO, get_ipfs_url};
|
|||
use crate::mastodon_api::oauth::auth::get_current_user;
|
||||
use crate::models::attachments::queries::set_attachment_ipfs_cid;
|
||||
use crate::models::profiles::queries::get_followers;
|
||||
use crate::models::posts::helpers::{
|
||||
get_actions_for_post,
|
||||
get_actions_for_posts,
|
||||
};
|
||||
use crate::models::posts::queries::{
|
||||
create_post,
|
||||
get_post_by_id,
|
||||
|
@ -76,24 +80,45 @@ async fn create_status(
|
|||
|
||||
#[get("/{status_id}")]
|
||||
async fn get_status(
|
||||
auth: Option<BearerAuth>,
|
||||
config: web::Data<Config>,
|
||||
db_pool: web::Data<Pool>,
|
||||
web::Path(status_id): web::Path<Uuid>,
|
||||
) -> Result<HttpResponse, HttpError> {
|
||||
let db_client = &**get_database_client(&db_pool).await?;
|
||||
let post = get_post_by_id(db_client, &status_id).await?;
|
||||
let maybe_current_user = match auth {
|
||||
Some(auth) => Some(get_current_user(db_client, auth.token()).await?),
|
||||
None => None,
|
||||
};
|
||||
let mut post = get_post_by_id(db_client, &status_id).await?;
|
||||
if let Some(user) = maybe_current_user {
|
||||
get_actions_for_post(db_client, &user.id, &mut post).await?;
|
||||
}
|
||||
let status = Status::from_post(post, &config.instance_url());
|
||||
Ok(HttpResponse::Ok().json(status))
|
||||
}
|
||||
|
||||
#[get("/{status_id}/context")]
|
||||
async fn get_context(
|
||||
auth: Option<BearerAuth>,
|
||||
config: web::Data<Config>,
|
||||
db_pool: web::Data<Pool>,
|
||||
web::Path(status_id): web::Path<Uuid>,
|
||||
) -> Result<HttpResponse, HttpError> {
|
||||
let db_client = &**get_database_client(&db_pool).await?;
|
||||
let statuses: Vec<Status> = get_thread(db_client, &status_id).await?
|
||||
let maybe_current_user = match auth {
|
||||
Some(auth) => Some(get_current_user(db_client, auth.token()).await?),
|
||||
None => None,
|
||||
};
|
||||
let mut posts = get_thread(db_client, &status_id).await?;
|
||||
if let Some(user) = maybe_current_user {
|
||||
get_actions_for_posts(
|
||||
db_client,
|
||||
&user.id,
|
||||
posts.iter_mut().collect(),
|
||||
).await?;
|
||||
}
|
||||
let statuses: Vec<Status> = posts
|
||||
.into_iter()
|
||||
.map(|post| Status::from_post(post, &config.instance_url()))
|
||||
.collect();
|
||||
|
@ -113,7 +138,8 @@ async fn favourite(
|
|||
Err(DatabaseError::AlreadyExists(_)) => (), // post already favourited
|
||||
other_result => other_result?,
|
||||
}
|
||||
let post = get_post_by_id(db_client, &status_id).await?;
|
||||
let mut post = get_post_by_id(db_client, &status_id).await?;
|
||||
get_actions_for_post(db_client, ¤t_user.id, &mut post).await?;
|
||||
let status = Status::from_post(post, &config.instance_url());
|
||||
Ok(HttpResponse::Ok().json(status))
|
||||
}
|
||||
|
@ -135,7 +161,7 @@ async fn make_permanent(
|
|||
web::Path(status_id): web::Path<Uuid>,
|
||||
) -> Result<HttpResponse, HttpError> {
|
||||
let db_client = &**get_database_client(&db_pool).await?;
|
||||
get_current_user(db_client, auth.token()).await?;
|
||||
let current_user = get_current_user(db_client, auth.token()).await?;
|
||||
let mut post = get_post_by_id(db_client, &status_id).await?;
|
||||
let ipfs_api_url = config.ipfs_api_url.as_ref()
|
||||
.ok_or(HttpError::NotSupported)?;
|
||||
|
@ -169,6 +195,7 @@ async fn make_permanent(
|
|||
// Update post
|
||||
post.ipfs_cid = Some(post_metadata_cid);
|
||||
update_post(db_client, &post).await?;
|
||||
get_actions_for_post(db_client, ¤t_user.id, &mut post).await?;
|
||||
let status = Status::from_post(post, &config.instance_url());
|
||||
Ok(HttpResponse::Ok().json(status))
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::database::{Pool, get_database_client};
|
|||
use crate::errors::HttpError;
|
||||
use crate::mastodon_api::oauth::auth::get_current_user;
|
||||
use crate::mastodon_api::statuses::types::Status;
|
||||
use crate::models::posts::helpers::get_actions_for_posts;
|
||||
use crate::models::posts::queries::get_posts;
|
||||
|
||||
#[get("/api/v1/timelines/home")]
|
||||
|
@ -16,7 +17,13 @@ pub async fn home_timeline(
|
|||
) -> Result<HttpResponse, HttpError> {
|
||||
let db_client = &**get_database_client(&db_pool).await?;
|
||||
let current_user = get_current_user(db_client, auth.token()).await?;
|
||||
let statuses: Vec<Status> = get_posts(db_client, ¤t_user.id).await?
|
||||
let mut posts = get_posts(db_client, ¤t_user.id).await?;
|
||||
get_actions_for_posts(
|
||||
db_client,
|
||||
¤t_user.id,
|
||||
posts.iter_mut().collect(),
|
||||
).await?;
|
||||
let statuses: Vec<Status> = posts
|
||||
.into_iter()
|
||||
.map(|post| Status::from_post(post, &config.instance_url()))
|
||||
.collect();
|
||||
|
|
|
@ -4,6 +4,7 @@ use tokio_postgres::GenericClient;
|
|||
use uuid::Uuid;
|
||||
|
||||
use crate::errors::DatabaseError;
|
||||
use crate::models::posts::helpers::get_actions_for_posts;
|
||||
use crate::models::posts::types::DbPost;
|
||||
use super::types::{EventType, Notification};
|
||||
|
||||
|
@ -76,8 +77,12 @@ pub async fn get_notifications(
|
|||
",
|
||||
&[&recipient_id],
|
||||
).await?;
|
||||
let notifications: Vec<Notification> = rows.iter()
|
||||
let mut notifications: Vec<Notification> = rows.iter()
|
||||
.map(|row| Notification::try_from(row))
|
||||
.collect::<Result<_, _>>()?;
|
||||
let posts = notifications.iter_mut()
|
||||
.filter_map(|item| item.post.as_mut())
|
||||
.collect();
|
||||
get_actions_for_posts(db_client, recipient_id, posts).await?;
|
||||
Ok(notifications)
|
||||
}
|
||||
|
|
31
src/models/posts/helpers.rs
Normal file
31
src/models/posts/helpers.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use tokio_postgres::GenericClient;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::errors::DatabaseError;
|
||||
use crate::models::reactions::queries::get_favourited;
|
||||
use super::types::{Post, PostActions};
|
||||
|
||||
pub async fn get_actions_for_post(
|
||||
db_client: &impl GenericClient,
|
||||
user_id: &Uuid,
|
||||
post: &mut Post,
|
||||
) -> Result<(), DatabaseError> {
|
||||
let favourited = get_favourited(db_client, user_id, vec![post.id]).await?;
|
||||
let actions = PostActions { favourited: favourited.contains(&post.id) };
|
||||
post.actions = Some(actions);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_actions_for_posts(
|
||||
db_client: &impl GenericClient,
|
||||
user_id: &Uuid,
|
||||
posts: Vec<&mut Post>,
|
||||
) -> Result<(), DatabaseError> {
|
||||
let posts_ids = posts.iter().map(|post| post.id).collect();
|
||||
let favourited = get_favourited(db_client, user_id, posts_ids).await?;
|
||||
for post in posts {
|
||||
let actions = PostActions { favourited: favourited.contains(&post.id) };
|
||||
post.actions = Some(actions);
|
||||
}
|
||||
Ok(())
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
pub mod helpers;
|
||||
pub mod queries;
|
||||
pub mod types;
|
||||
|
|
|
@ -26,7 +26,11 @@ pub struct DbPost {
|
|||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
// List of user's actions
|
||||
pub struct PostActions {
|
||||
pub favourited: bool,
|
||||
}
|
||||
|
||||
pub struct Post {
|
||||
pub id: Uuid,
|
||||
pub author: DbActorProfile,
|
||||
|
@ -40,6 +44,7 @@ pub struct Post {
|
|||
pub token_id: Option<i32>,
|
||||
pub token_tx_id: Option<String>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub actions: Option<PostActions>,
|
||||
}
|
||||
|
||||
impl Post {
|
||||
|
@ -62,6 +67,7 @@ impl Post {
|
|||
token_id: db_post.token_id,
|
||||
token_tx_id: db_post.token_tx_id,
|
||||
created_at: db_post.created_at,
|
||||
actions: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,6 +88,7 @@ impl Default for Post {
|
|||
token_id: None,
|
||||
token_tx_id: None,
|
||||
created_at: Utc::now(),
|
||||
actions: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,3 +23,22 @@ pub async fn create_reaction(
|
|||
transaction.commit().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_favourited(
|
||||
db_client: &impl GenericClient,
|
||||
user_id: &Uuid,
|
||||
posts_ids: Vec<Uuid>,
|
||||
) -> Result<Vec<Uuid>, DatabaseError> {
|
||||
let rows = db_client.query(
|
||||
"
|
||||
SELECT post_id
|
||||
FROM post_reaction
|
||||
WHERE author_id = $1 AND post_id = ANY($2)
|
||||
",
|
||||
&[&user_id, &posts_ids],
|
||||
).await?;
|
||||
let favourited: Vec<Uuid> = rows.iter()
|
||||
.map(|row| row.try_get("post_id"))
|
||||
.collect::<Result<_, _>>()?;
|
||||
Ok(favourited)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue