Refactor Status API views
This commit is contained in:
parent
54c32c5f00
commit
e6e7e6f42a
9 changed files with 134 additions and 104 deletions
|
@ -21,10 +21,7 @@ use crate::ethereum::identity::{
|
|||
};
|
||||
use crate::ethereum::subscriptions::create_subscription_signature;
|
||||
use crate::mastodon_api::oauth::auth::get_current_user;
|
||||
use crate::models::posts::helpers::{
|
||||
get_actions_for_posts,
|
||||
get_reposted_posts,
|
||||
};
|
||||
use crate::mastodon_api::statuses::helpers::build_status_list;
|
||||
use crate::mastodon_api::statuses::types::Status;
|
||||
use crate::models::posts::queries::get_posts_by_author;
|
||||
use crate::models::profiles::queries::{
|
||||
|
@ -442,7 +439,7 @@ async fn get_account_statuses(
|
|||
};
|
||||
let profile = get_profile_by_id(db_client, &account_id).await?;
|
||||
// Include reposts but not replies
|
||||
let mut posts = get_posts_by_author(
|
||||
let posts = get_posts_by_author(
|
||||
db_client,
|
||||
&profile.id,
|
||||
maybe_current_user.as_ref().map(|user| &user.id),
|
||||
|
@ -451,17 +448,12 @@ async fn get_account_statuses(
|
|||
query_params.max_id,
|
||||
query_params.limit,
|
||||
).await?;
|
||||
get_reposted_posts(db_client, posts.iter_mut().collect()).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();
|
||||
let statuses = build_status_list(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
maybe_current_user.as_ref(),
|
||||
posts,
|
||||
).await?;
|
||||
Ok(HttpResponse::Ok().json(statuses))
|
||||
}
|
||||
|
||||
|
|
|
@ -10,11 +10,8 @@ use crate::activitypub::fetcher::helpers::{
|
|||
use crate::config::Config;
|
||||
use crate::errors::{ValidationError, HttpError};
|
||||
use crate::mastodon_api::accounts::types::Account;
|
||||
use crate::mastodon_api::statuses::types::Status;
|
||||
use crate::models::posts::helpers::{
|
||||
can_view_post,
|
||||
get_actions_for_posts,
|
||||
};
|
||||
use crate::mastodon_api::statuses::helpers::build_status_list;
|
||||
use crate::models::posts::helpers::can_view_post;
|
||||
use crate::models::posts::types::Post;
|
||||
use crate::models::profiles::queries::{
|
||||
search_profile,
|
||||
|
@ -158,9 +155,11 @@ pub async fn search(
|
|||
let accounts: Vec<Account> = profiles.into_iter()
|
||||
.map(|profile| Account::from_profile(profile, &config.instance_url()))
|
||||
.collect();
|
||||
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();
|
||||
let statuses = build_status_list(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
Some(current_user),
|
||||
posts,
|
||||
).await?;
|
||||
Ok(SearchResults { accounts, statuses })
|
||||
}
|
||||
|
|
|
@ -2,10 +2,15 @@ use tokio_postgres::GenericClient;
|
|||
|
||||
use crate::activitypub::actor::Actor;
|
||||
use crate::errors::DatabaseError;
|
||||
use crate::models::posts::helpers::{
|
||||
add_user_actions,
|
||||
add_reposted_posts,
|
||||
};
|
||||
use crate::models::posts::queries::get_post_author;
|
||||
use crate::models::posts::types::{Post, Visibility};
|
||||
use crate::models::relationships::queries::{get_followers, get_subscribers};
|
||||
use crate::models::users::types::User;
|
||||
use super::types::Status;
|
||||
|
||||
pub async fn get_note_recipients(
|
||||
db_client: &impl GenericClient,
|
||||
|
@ -77,3 +82,35 @@ pub async fn get_announce_recipients(
|
|||
};
|
||||
Ok(Audience { recipients, primary_recipient })
|
||||
}
|
||||
|
||||
/// Load related objects and build status for API response
|
||||
pub async fn build_status(
|
||||
db_client: &impl GenericClient,
|
||||
instance_url: &str,
|
||||
user: Option<&User>,
|
||||
mut post: Post,
|
||||
) -> Result<Status, DatabaseError> {
|
||||
add_reposted_posts(db_client, vec![&mut post]).await?;
|
||||
if let Some(user) = user {
|
||||
add_user_actions(db_client, &user.id, vec![&mut post]).await?;
|
||||
};
|
||||
let status = Status::from_post(post, instance_url);
|
||||
Ok(status)
|
||||
}
|
||||
|
||||
pub async fn build_status_list(
|
||||
db_client: &impl GenericClient,
|
||||
instance_url: &str,
|
||||
user: Option<&User>,
|
||||
mut posts: Vec<Post>,
|
||||
) -> Result<Vec<Status>, DatabaseError> {
|
||||
add_reposted_posts(db_client, posts.iter_mut().collect()).await?;
|
||||
if let Some(user) = user {
|
||||
add_user_actions(db_client, &user.id, posts.iter_mut().collect()).await?;
|
||||
};
|
||||
let statuses: Vec<Status> = posts
|
||||
.into_iter()
|
||||
.map(|post| Status::from_post(post, instance_url))
|
||||
.collect();
|
||||
Ok(statuses)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
mod helpers;
|
||||
pub mod helpers;
|
||||
pub mod types;
|
||||
pub mod views;
|
||||
|
|
|
@ -26,10 +26,6 @@ use crate::models::attachments::queries::set_attachment_ipfs_cid;
|
|||
use crate::models::posts::helpers::can_view_post;
|
||||
use crate::models::posts::mentions::{find_mentioned_profiles, replace_mentions};
|
||||
use crate::models::posts::tags::{find_tags, replace_tags};
|
||||
use crate::models::posts::helpers::{
|
||||
get_actions_for_posts,
|
||||
get_reposted_posts,
|
||||
};
|
||||
use crate::models::posts::queries::{
|
||||
create_post,
|
||||
get_post_by_id,
|
||||
|
@ -44,6 +40,8 @@ use crate::models::reactions::queries::{
|
|||
delete_reaction,
|
||||
};
|
||||
use super::helpers::{
|
||||
build_status,
|
||||
build_status_list,
|
||||
get_announce_recipients,
|
||||
get_like_recipients,
|
||||
get_note_recipients,
|
||||
|
@ -128,6 +126,7 @@ async fn create_status(
|
|||
);
|
||||
let recipients = get_note_recipients(db_client, ¤t_user, &post).await?;
|
||||
deliver_activity(&config, ¤t_user, activity, recipients);
|
||||
|
||||
let status = Status::from_post(post, &instance.url());
|
||||
Ok(HttpResponse::Created().json(status))
|
||||
}
|
||||
|
@ -144,15 +143,16 @@ async fn get_status(
|
|||
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?;
|
||||
let post = get_post_by_id(db_client, &status_id).await?;
|
||||
if !can_view_post(db_client, maybe_current_user.as_ref(), &post).await? {
|
||||
return Err(HttpError::NotFoundError("post"));
|
||||
};
|
||||
get_reposted_posts(db_client, vec![&mut post]).await?;
|
||||
if let Some(user) = maybe_current_user {
|
||||
get_actions_for_posts(db_client, &user.id, vec![&mut post]).await?;
|
||||
}
|
||||
let status = Status::from_post(post, &config.instance_url());
|
||||
let status = build_status(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
maybe_current_user.as_ref(),
|
||||
post,
|
||||
).await?;
|
||||
Ok(HttpResponse::Ok().json(status))
|
||||
}
|
||||
|
||||
|
@ -197,23 +197,17 @@ async fn get_context(
|
|||
Some(auth) => Some(get_current_user(db_client, auth.token()).await?),
|
||||
None => None,
|
||||
};
|
||||
let mut posts = get_thread(
|
||||
let posts = get_thread(
|
||||
db_client,
|
||||
&status_id,
|
||||
maybe_current_user.as_ref().map(|user| &user.id),
|
||||
).await?;
|
||||
get_reposted_posts(db_client, posts.iter_mut().collect()).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();
|
||||
let statuses = build_status_list(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
maybe_current_user.as_ref(),
|
||||
posts,
|
||||
).await?;
|
||||
Ok(HttpResponse::Ok().json(statuses))
|
||||
}
|
||||
|
||||
|
@ -240,8 +234,6 @@ async fn favourite(
|
|||
Err(DatabaseError::AlreadyExists(_)) => None, // post already favourited
|
||||
Err(other_error) => return Err(other_error.into()),
|
||||
};
|
||||
get_reposted_posts(db_client, vec![&mut post]).await?;
|
||||
get_actions_for_posts(db_client, ¤t_user.id, vec![&mut post]).await?;
|
||||
|
||||
if let Some(reaction) = maybe_reaction_created {
|
||||
// Federate
|
||||
|
@ -256,9 +248,14 @@ async fn favourite(
|
|||
&primary_recipient,
|
||||
);
|
||||
deliver_activity(&config, ¤t_user, activity, recipients);
|
||||
}
|
||||
};
|
||||
|
||||
let status = Status::from_post(post, &config.instance_url());
|
||||
let status = build_status(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
Some(¤t_user),
|
||||
post,
|
||||
).await?;
|
||||
Ok(HttpResponse::Ok().json(status))
|
||||
}
|
||||
|
||||
|
@ -282,8 +279,6 @@ async fn unfavourite(
|
|||
Err(DatabaseError::NotFound(_)) => None, // post not favourited
|
||||
Err(other_error) => return Err(other_error.into()),
|
||||
};
|
||||
get_reposted_posts(db_client, vec![&mut post]).await?;
|
||||
get_actions_for_posts(db_client, ¤t_user.id, vec![&mut post]).await?;
|
||||
|
||||
if let Some(reaction_id) = maybe_reaction_deleted {
|
||||
// Federate
|
||||
|
@ -298,7 +293,12 @@ async fn unfavourite(
|
|||
deliver_activity(&config, ¤t_user, activity, recipients);
|
||||
};
|
||||
|
||||
let status = Status::from_post(post, &config.instance_url());
|
||||
let status = build_status(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
Some(¤t_user),
|
||||
post,
|
||||
).await?;
|
||||
Ok(HttpResponse::Ok().json(status))
|
||||
}
|
||||
|
||||
|
@ -319,10 +319,8 @@ async fn reblog(
|
|||
repost_of_id: Some(status_id.into_inner()),
|
||||
..Default::default()
|
||||
};
|
||||
let mut repost = create_post(db_client, ¤t_user.id, repost_data).await?;
|
||||
let repost = create_post(db_client, ¤t_user.id, repost_data).await?;
|
||||
post.repost_count += 1;
|
||||
get_reposted_posts(db_client, vec![&mut post]).await?;
|
||||
get_actions_for_posts(db_client, ¤t_user.id, vec![&mut post]).await?;
|
||||
|
||||
// Federate
|
||||
let Audience { recipients, .. } =
|
||||
|
@ -335,8 +333,12 @@ async fn reblog(
|
|||
);
|
||||
deliver_activity(&config, ¤t_user, activity, recipients);
|
||||
|
||||
repost.repost_of = Some(Box::new(post));
|
||||
let status = Status::from_post(repost, &config.instance_url());
|
||||
let status = build_status(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
Some(¤t_user),
|
||||
repost,
|
||||
).await?;
|
||||
Ok(HttpResponse::Ok().json(status))
|
||||
}
|
||||
|
||||
|
@ -357,9 +359,7 @@ async fn unreblog(
|
|||
let repost_id = reposts.first().ok_or(HttpError::NotFoundError("post"))?;
|
||||
// Ignore returned data because reposts don't have attached files
|
||||
delete_post(db_client, repost_id).await?;
|
||||
let mut post = get_post_by_id(db_client, &status_id).await?;
|
||||
get_reposted_posts(db_client, vec![&mut post]).await?;
|
||||
get_actions_for_posts(db_client, ¤t_user.id, vec![&mut post]).await?;
|
||||
let post = get_post_by_id(db_client, &status_id).await?;
|
||||
|
||||
// Federate
|
||||
let Audience { recipients, primary_recipient } =
|
||||
|
@ -372,7 +372,12 @@ async fn unreblog(
|
|||
);
|
||||
deliver_activity(&config, ¤t_user, activity, recipients);
|
||||
|
||||
let status = Status::from_post(post, &config.instance_url());
|
||||
let status = build_status(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
Some(¤t_user),
|
||||
post,
|
||||
).await?;
|
||||
Ok(HttpResponse::Ok().json(status))
|
||||
}
|
||||
|
||||
|
@ -426,9 +431,13 @@ async fn make_permanent(
|
|||
// Update post
|
||||
post.ipfs_cid = Some(post_metadata_cid);
|
||||
update_post(db_client, &post).await?;
|
||||
get_reposted_posts(db_client, vec![&mut post]).await?;
|
||||
get_actions_for_posts(db_client, ¤t_user.id, vec![&mut post]).await?;
|
||||
let status = Status::from_post(post, &config.instance_url());
|
||||
|
||||
let status = build_status(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
Some(¤t_user),
|
||||
post,
|
||||
).await?;
|
||||
Ok(HttpResponse::Ok().json(status))
|
||||
}
|
||||
|
||||
|
@ -481,9 +490,13 @@ async fn token_minted(
|
|||
};
|
||||
post.token_tx_id = Some(transaction_data.into_inner().transaction_id);
|
||||
update_post(db_client, &post).await?;
|
||||
get_reposted_posts(db_client, vec![&mut post]).await?;
|
||||
get_actions_for_posts(db_client, ¤t_user.id, vec![&mut post]).await?;
|
||||
let status = Status::from_post(post, &config.instance_url());
|
||||
|
||||
let status = build_status(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
Some(¤t_user),
|
||||
post,
|
||||
).await?;
|
||||
Ok(HttpResponse::Ok().json(status))
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,7 @@ use crate::config::Config;
|
|||
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,
|
||||
get_reposted_posts,
|
||||
};
|
||||
use crate::mastodon_api::statuses::helpers::build_status_list;
|
||||
use crate::models::posts::queries::{get_home_timeline, get_posts_by_tag};
|
||||
use super::types::TimelineQueryParams;
|
||||
|
||||
|
@ -23,22 +19,18 @@ 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 mut posts = get_home_timeline(
|
||||
let posts = get_home_timeline(
|
||||
db_client,
|
||||
¤t_user.id,
|
||||
query_params.max_id,
|
||||
query_params.limit,
|
||||
).await?;
|
||||
get_reposted_posts(db_client, posts.iter_mut().collect()).await?;
|
||||
get_actions_for_posts(
|
||||
let statuses = build_status_list(
|
||||
db_client,
|
||||
¤t_user.id,
|
||||
posts.iter_mut().collect(),
|
||||
&config.instance_url(),
|
||||
Some(¤t_user),
|
||||
posts,
|
||||
).await?;
|
||||
let statuses: Vec<Status> = posts
|
||||
.into_iter()
|
||||
.map(|post| Status::from_post(post, &config.instance_url()))
|
||||
.collect();
|
||||
Ok(HttpResponse::Ok().json(statuses))
|
||||
}
|
||||
|
||||
|
@ -55,25 +47,19 @@ async fn hashtag_timeline(
|
|||
Some(auth) => Some(get_current_user(db_client, auth.token()).await?),
|
||||
None => None,
|
||||
};
|
||||
let mut posts = get_posts_by_tag(
|
||||
let posts = get_posts_by_tag(
|
||||
db_client,
|
||||
&hashtag,
|
||||
maybe_current_user.as_ref().map(|user| &user.id),
|
||||
query_params.max_id,
|
||||
query_params.limit,
|
||||
).await?;
|
||||
get_reposted_posts(db_client, posts.iter_mut().collect()).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();
|
||||
let statuses = build_status_list(
|
||||
db_client,
|
||||
&config.instance_url(),
|
||||
maybe_current_user.as_ref(),
|
||||
posts,
|
||||
).await?;
|
||||
Ok(HttpResponse::Ok().json(statuses))
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +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::helpers::add_user_actions;
|
||||
use crate::models::posts::queries::{
|
||||
RELATED_ATTACHMENTS,
|
||||
RELATED_MENTIONS,
|
||||
|
@ -133,6 +133,6 @@ pub async fn get_notifications(
|
|||
let posts = notifications.iter_mut()
|
||||
.filter_map(|item| item.post.as_mut())
|
||||
.collect();
|
||||
get_actions_for_posts(db_client, recipient_id, posts).await?;
|
||||
add_user_actions(db_client, recipient_id, posts).await?;
|
||||
Ok(notifications)
|
||||
}
|
||||
|
|
|
@ -9,13 +9,16 @@ use crate::models::users::types::User;
|
|||
use super::queries::{get_posts, find_reposted_by_user};
|
||||
use super::types::{Post, PostActions, Visibility};
|
||||
|
||||
pub async fn get_reposted_posts(
|
||||
pub async fn add_reposted_posts(
|
||||
db_client: &impl GenericClient,
|
||||
posts: Vec<&mut Post>,
|
||||
) -> Result<(), DatabaseError> {
|
||||
let reposted_ids: Vec<Uuid> = posts.iter()
|
||||
.filter_map(|post| post.repost_of_id)
|
||||
.collect();
|
||||
if reposted_ids.is_empty() {
|
||||
return Ok(());
|
||||
};
|
||||
let reposted = get_posts(db_client, reposted_ids).await?;
|
||||
for post in posts {
|
||||
if let Some(ref repost_of_id) = post.repost_of_id {
|
||||
|
@ -29,7 +32,7 @@ pub async fn get_reposted_posts(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_actions_for_posts(
|
||||
pub async fn add_user_actions(
|
||||
db_client: &impl GenericClient,
|
||||
user_id: &Uuid,
|
||||
posts: Vec<&mut Post>,
|
||||
|
|
|
@ -134,7 +134,7 @@ pub async fn get_profile_by_actor_id(
|
|||
|
||||
pub async fn get_profile_by_acct(
|
||||
db_client: &impl GenericClient,
|
||||
account_uri: &str,
|
||||
acct: &str,
|
||||
) -> Result<DbActorProfile, DatabaseError> {
|
||||
let result = db_client.query_opt(
|
||||
"
|
||||
|
@ -142,7 +142,7 @@ pub async fn get_profile_by_acct(
|
|||
FROM actor_profile
|
||||
WHERE actor_profile.acct = $1
|
||||
",
|
||||
&[&account_uri],
|
||||
&[&acct],
|
||||
).await?;
|
||||
let profile = match result {
|
||||
Some(row) => row.try_get("actor_profile")?,
|
||||
|
|
Loading…
Reference in a new issue