X-Git-Url: http://these/git/?a=blobdiff_plain;f=crates%2Fapi_crud%2Fsrc%2Fpost%2Fread.rs;h=d37b1a5825819cb875325cbb9b6660fab312d72e;hb=c8063f3267cf2b3622f1fdc69128c6b55feefbbc;hp=1b173418b28c4eb471d5a59adadfd00d64f14665;hpb=249fcc5066c30158eb3a3094a21ff5e021534cd2;p=lemmy.git diff --git a/crates/api_crud/src/post/read.rs b/crates/api_crud/src/post/read.rs index 1b173418..d37b1a58 100644 --- a/crates/api_crud/src/post/read.rs +++ b/crates/api_crud/src/post/read.rs @@ -1,135 +1,115 @@ -use crate::PerformCrud; -use actix_web::web::Data; -use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, post::*}; -use lemmy_db_queries::{ListingType, SortType}; -use lemmy_db_views::{ - comment_view::CommentQueryBuilder, - post_view::{PostQueryBuilder, PostView}, +use actix_web::web::{Data, Json, Query}; +use lemmy_api_common::{ + context::LemmyContext, + post::{GetPost, GetPostResponse}, + utils::{ + check_private_instance, + is_mod_or_admin_opt, + local_user_view_from_jwt_opt, + mark_post_as_read, + }, }; -use lemmy_db_views_actor::{ - community_moderator_view::CommunityModeratorView, - community_view::CommunityView, +use lemmy_db_schema::{ + aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm}, + source::{comment::Comment, local_site::LocalSite, post::Post}, + traits::Crud, }; -use lemmy_utils::{ApiError, ConnectionId, LemmyError}; -use lemmy_websocket::{messages::GetPostUsersOnline, LemmyContext}; -use std::str::FromStr; - -#[async_trait::async_trait(?Send)] -impl PerformCrud for GetPost { - type Response = GetPostResponse; - - async fn perform( - &self, - context: &Data, - _websocket_id: Option, - ) -> Result { - let data: &GetPost = &self; - let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?; - let person_id = local_user_view.map(|u| u.person.id); - - let id = data.id; - let post_view = match blocking(context.pool(), move |conn| { - PostView::read(conn, id, person_id) - }) - .await? - { - Ok(post) => post, - Err(_e) => return Err(ApiError::err("couldnt_find_post").into()), - }; - - let id = data.id; - let comments = blocking(context.pool(), move |conn| { - CommentQueryBuilder::create(conn) - .my_person_id(person_id) - .post_id(id) - .limit(9999) - .list() - }) - .await??; - - let community_id = post_view.community.id; - let moderators = blocking(context.pool(), move |conn| { - CommunityModeratorView::for_community(conn, community_id) - }) - .await??; - - // Necessary for the sidebar - let community_view = match blocking(context.pool(), move |conn| { - CommunityView::read(conn, community_id, person_id) - }) - .await? - { - Ok(community) => community, - Err(_e) => return Err(ApiError::err("couldnt_find_community").into()), - }; - - let online = context - .chat_server() - .send(GetPostUsersOnline { post_id: data.id }) +use lemmy_db_views::{post_view::PostQuery, structs::PostView}; +use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView}; +use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; + +#[tracing::instrument(skip(context))] +pub async fn get_post( + data: Query, + context: Data, +) -> Result, LemmyError> { + let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await; + let local_site = LocalSite::read(&mut context.pool()).await?; + + check_private_instance(&local_user_view, &local_site)?; + + let person_id = local_user_view.as_ref().map(|u| u.person.id); + + // I'd prefer fetching the post_view by a comment join, but it adds a lot of boilerplate + let post_id = if let Some(id) = data.id { + id + } else if let Some(comment_id) = data.comment_id { + Comment::read(&mut context.pool(), comment_id) .await - .unwrap_or(1); - - // Return the jwt - Ok(GetPostResponse { - post_view, - community_view, - comments, - moderators, - online, - }) + .with_lemmy_type(LemmyErrorType::CouldntFindPost)? + .post_id + } else { + Err(LemmyErrorType::CouldntFindPost)? + }; + + // Check to see if the person is a mod or admin, to show deleted / removed + let community_id = Post::read(&mut context.pool(), post_id).await?.community_id; + let is_mod_or_admin = is_mod_or_admin_opt( + &mut context.pool(), + local_user_view.as_ref(), + Some(community_id), + ) + .await + .is_ok(); + + let post_view = PostView::read(&mut context.pool(), post_id, person_id, is_mod_or_admin) + .await + .with_lemmy_type(LemmyErrorType::CouldntFindPost)?; + + // Mark the post as read + let post_id = post_view.post.id; + if let Some(person_id) = person_id { + mark_post_as_read(person_id, post_id, &mut context.pool()).await?; } -} -#[async_trait::async_trait(?Send)] -impl PerformCrud for GetPosts { - type Response = GetPostsResponse; - - async fn perform( - &self, - context: &Data, - _websocket_id: Option, - ) -> Result { - let data: &GetPosts = &self; - let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?; - - let person_id = match &local_user_view { - Some(uv) => Some(uv.person.id), - None => None, - }; - - let show_nsfw = match &local_user_view { - Some(uv) => uv.local_user.show_nsfw, - None => false, + // Necessary for the sidebar subscribed + let community_view = CommunityView::read( + &mut context.pool(), + community_id, + person_id, + is_mod_or_admin, + ) + .await + .with_lemmy_type(LemmyErrorType::CouldntFindCommunity)?; + + // Insert into PersonPostAggregates + // to update the read_comments count + if let Some(person_id) = person_id { + let read_comments = post_view.counts.comments; + let person_post_agg_form = PersonPostAggregatesForm { + person_id, + post_id, + read_comments, + ..PersonPostAggregatesForm::default() }; - - let type_ = ListingType::from_str(&data.type_)?; - let sort = SortType::from_str(&data.sort)?; - - let page = data.page; - let limit = data.limit; - let community_id = data.community_id; - let community_name = data.community_name.to_owned(); - let saved_only = data.saved_only; - - let posts = match blocking(context.pool(), move |conn| { - PostQueryBuilder::create(conn) - .listing_type(&type_) - .sort(&sort) - .show_nsfw(show_nsfw) - .community_id(community_id) - .community_name(community_name) - .saved_only(saved_only) - .my_person_id(person_id) - .page(page) - .limit(limit) - .list() - }) - .await? - { - Ok(posts) => posts, - Err(_e) => return Err(ApiError::err("couldnt_get_posts").into()), - }; - - Ok(GetPostsResponse { posts }) + PersonPostAggregates::upsert(&mut context.pool(), &person_post_agg_form) + .await + .with_lemmy_type(LemmyErrorType::CouldntFindPost)?; } + + let moderators = CommunityModeratorView::for_community(&mut context.pool(), community_id).await?; + + // Fetch the cross_posts + let cross_posts = if let Some(url) = &post_view.post.url { + let mut x_posts = PostQuery { + url_search: Some(url.inner().as_str().into()), + ..Default::default() + } + .list(&mut context.pool()) + .await?; + + // Don't return this post as one of the cross_posts + x_posts.retain(|x| x.post.id != post_id); + x_posts + } else { + Vec::new() + }; + + // Return the jwt + Ok(Json(GetPostResponse { + post_view, + community_view, + moderators, + cross_posts, + })) }