lemmy/crates/api_crud/src/post/read.rs
Dessalines a9d6d4e6e0
Add user setting to auto-mark fetched posts as read. (#5160)
* Add user setting to auto-mark fetched posts as read.

- Rather than apps collecting up viewed posts ids, and sending many
  mark as read requests, users can now turn this setting on, and any
  results from /post/list will be auto-marked as read.
- Fixes #5144

* Adding list_post request option to auto-mark as read.

* Moving db_perf to before federation tests.

* Fixing lemmyerrortype import.

* Fixing ts_option.

* Fix clippy.

* Fix override logic.

* Revert "Fix override logic."

This reverts commit 923d7f0eca.

* Changing name to mark_as_read
2024-11-13 10:05:16 -05:00

115 lines
2.9 KiB
Rust

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, update_read_comments},
};
use lemmy_db_schema::{
source::{
comment::Comment,
post::{Post, PostRead},
},
traits::Crud,
};
use lemmy_db_views::{
post_view::PostQuery,
structs::{LocalUserView, PostView, SiteView},
};
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
#[tracing::instrument(skip(context))]
pub async fn get_post(
data: Query<GetPost>,
context: Data<LemmyContext>,
local_user_view: Option<LocalUserView>,
) -> LemmyResult<Json<GetPostResponse>> {
let local_site = SiteView::read_local(&mut context.pool()).await?;
check_private_instance(&local_user_view, &local_site.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?
.post_id
} else {
Err(LemmyErrorType::NotFound)?
};
// Check to see if the person is a mod or admin, to show deleted / removed
let community_id = Post::read_xx(&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 local_user = local_user_view.map(|l| l.local_user);
let post_view = PostView::read(
&mut context.pool(),
post_id,
local_user.as_ref(),
is_mod_or_admin,
)
.await?;
let post_id = post_view.post.id;
if let Some(person_id) = person_id {
PostRead::mark_as_read(&mut context.pool(), post_id, person_id).await?;
update_read_comments(
person_id,
post_id,
post_view.counts.comments,
&mut context.pool(),
)
.await?;
}
// Necessary for the sidebar subscribed
let community_view = CommunityView::read(
&mut context.pool(),
community_id,
local_user.as_ref(),
is_mod_or_admin,
)
.await?;
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_only: Some(true),
search_term: Some(url.inner().as_str().into()),
local_user: local_user.as_ref(),
..Default::default()
}
.list(&local_site.site, &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,
}))
}