lemmynsfw-changes
Felix Ableitner 2024-01-23 13:02:11 +01:00
parent d18ac067c5
commit c537cf298a
14 changed files with 168 additions and 174 deletions

2
Cargo.lock generated
View File

@ -2708,6 +2708,7 @@ dependencies = [
"tokio", "tokio",
"tracing", "tracing",
"ts-rs", "ts-rs",
"typed-builder",
] ]
[[package]] [[package]]
@ -2726,6 +2727,7 @@ dependencies = [
"strum_macros", "strum_macros",
"tokio", "tokio",
"ts-rs", "ts-rs",
"typed-builder",
] ]
[[package]] [[package]]

View File

@ -31,7 +31,8 @@ pub async fn like_post(
let post_id = data.post_id; let post_id = data.post_id;
let post = Post::read(&mut context.pool(), post_id).await?; let post = Post::read(&mut context.pool(), post_id).await?;
// TODO: need to read community both here are for check_community_user_action() // TODO: need to read community both here are for check_community_user_action(), would be good to
// read it only once
let community = Community::read(&mut context.pool(), post.community_id).await?; let community = Community::read(&mut context.pool(), post.community_id).await?;
check_vote_permission( check_vote_permission(
data.score, data.score,

View File

@ -840,7 +840,6 @@ pub async fn check_vote_permission(
if community.only_followers_can_vote if community.only_followers_can_vote
&& !CommunityFollower::is_follower(&mut context.pool(), person.id, community.id).await? && !CommunityFollower::is_follower(&mut context.pool(), person.id, community.id).await?
{ {
// TODO: lemmynsfw code checks that follow was at least 10 minutes ago
Err(LemmyErrorType::DownvotesAreDisabled)? Err(LemmyErrorType::DownvotesAreDisabled)?
} }
Ok(()) Ok(())

View File

@ -29,18 +29,18 @@ pub async fn list_communities(
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let local_user = local_user_view.map(|l| l.local_user); let local_user = local_user_view.map(|l| l.local_user);
let communities = CommunityQuery { let communities = CommunityQuery::builder()
listing_type, .local_site(local_site)
show_nsfw, .listing_type(listing_type)
sort, .show_nsfw(show_nsfw)
local_user: local_user.as_ref(), .sort(sort)
page, .local_user(local_user.as_ref())
limit, .page(page)
is_mod_or_admin: is_admin, .limit(limit)
..Default::default() .is_mod_or_admin(is_admin)
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
// Return the jwt // Return the jwt
Ok(Json(ListCommunitiesResponse { communities })) Ok(Json(ListCommunitiesResponse { communities }))

View File

@ -89,12 +89,12 @@ pub async fn get_post(
// Fetch the cross_posts // Fetch the cross_posts
let cross_posts = if let Some(url) = &post_view.post.url { let cross_posts = if let Some(url) = &post_view.post.url {
let mut x_posts = PostQuery { let mut x_posts = PostQuery::builder()
url_search: Some(url.inner().as_str().into()), .local_site(local_site)
..Default::default() .url_search(Some(url.inner().as_str().into()))
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
// Don't return this post as one of the cross_posts // Don't return this post as one of the cross_posts
x_posts.retain(|x| x.post.id != post_id); x_posts.retain(|x| x.post.id != post_id);

View File

@ -67,11 +67,9 @@ async fn vote_comment(
person_id: actor.id, person_id: actor.id,
score: vote_type.into(), score: vote_type.into(),
}; };
let person_id = actor.id;
// TODO: inefficient
let post = Post::read(&mut context.pool(), comment.post_id).await?; let post = Post::read(&mut context.pool(), comment.post_id).await?;
check_vote_permission(Some(vote_type), &actor, post.community_id, context).await?; check_vote_permission(Some(vote_type), &actor, post.community_id, context).await?;
CommentLike::remove(&mut context.pool(), person_id, comment_id).await?; CommentLike::remove(&mut context.pool(), actor.id, comment_id).await?;
CommentLike::like(&mut context.pool(), &like_form).await?; CommentLike::like(&mut context.pool(), &like_form).await?;
Ok(()) Ok(())
} }
@ -102,12 +100,9 @@ async fn undo_vote_comment(
comment: &ApubComment, comment: &ApubComment,
context: &Data<LemmyContext>, context: &Data<LemmyContext>,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let comment_id = comment.id;
let person_id = actor.id;
// TODO: inefficient
let post = Post::read(&mut context.pool(), comment.post_id).await?; let post = Post::read(&mut context.pool(), comment.post_id).await?;
check_vote_permission(None, &actor, post.community_id, context).await?; check_vote_permission(None, &actor, post.community_id, context).await?;
CommentLike::remove(&mut context.pool(), person_id, comment_id).await?; CommentLike::remove(&mut context.pool(), actor.id, comment.id).await?;
Ok(()) Ok(())
} }
@ -117,10 +112,8 @@ async fn undo_vote_post(
post: &ApubPost, post: &ApubPost,
context: &Data<LemmyContext>, context: &Data<LemmyContext>,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let post_id = post.id;
let person_id = actor.id;
check_vote_permission(None, &actor, post.community_id, context).await?; check_vote_permission(None, &actor, post.community_id, context).await?;
PostLike::remove(&mut context.pool(), person_id, post_id).await?; PostLike::remove(&mut context.pool(), actor.id, post.id).await?;
Ok(()) Ok(())
} }

View File

@ -57,22 +57,22 @@ pub async fn list_posts(
None None
}; };
let posts = PostQuery { let posts = PostQuery::builder()
local_user: local_user_view.as_ref(), .local_site(local_site)
listing_type, .local_user(local_user_view.as_ref())
sort, .listing_type(listing_type)
community_id, .sort(sort)
saved_only, .community_id(community_id)
liked_only, .saved_only(saved_only)
disliked_only, .liked_only(liked_only)
page, .disliked_only(disliked_only)
page_after, .page(page)
limit, .page_after(page_after)
..Default::default() .limit(limit)
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await .await
.with_lemmy_type(LemmyErrorType::CouldntGetPosts)?; .with_lemmy_type(LemmyErrorType::CouldntGetPosts)?;
// if this page wasn't empty, then there is a next page after the last post on this page // if this page wasn't empty, then there is a next page after the last post on this page
let next_page = posts.last().map(PaginationCursor::after_post); let next_page = posts.last().map(PaginationCursor::after_post);

View File

@ -60,18 +60,18 @@ pub async fn read_person(
None None
}; };
let posts = PostQuery { let posts = PostQuery::builder()
sort, .local_site(local_site)
saved_only, .local_user(local_user_view.as_ref())
local_user: local_user_view.as_ref(), .sort(sort)
community_id, .community_id(community_id)
page, .saved_only(saved_only)
limit, .page(page)
creator_id, .limit(limit)
..Default::default() .creator_id(creator_id)
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
let comments = CommentQuery { let comments = CommentQuery {
local_user: local_user_view.as_ref(), local_user: local_user_view.as_ref(),

View File

@ -56,19 +56,19 @@ pub async fn search(
let local_user = local_user_view.as_ref().map(|l| l.local_user.clone()); let local_user = local_user_view.as_ref().map(|l| l.local_user.clone());
match search_type { match search_type {
SearchType::Posts => { SearchType::Posts => {
posts = PostQuery { PostQuery::builder()
sort: (sort), .local_site(local_site)
listing_type: (listing_type), .local_user(local_user_view.as_ref())
community_id: (community_id), .sort(sort)
creator_id: (creator_id), .community_id(community_id)
local_user: (local_user_view.as_ref()), .creator_id(creator_id)
search_term: (Some(q)), .listing_type(listing_type)
page: (page), .search_term(Some(q))
limit: (limit), .page(page)
..Default::default() .limit(limit)
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
} }
SearchType::Comments => { SearchType::Comments => {
comments = CommentQuery { comments = CommentQuery {
@ -86,18 +86,18 @@ pub async fn search(
.await?; .await?;
} }
SearchType::Communities => { SearchType::Communities => {
communities = CommunityQuery { communities = CommunityQuery::builder()
sort: (sort), .local_site(local_site)
listing_type: (listing_type), .listing_type(listing_type)
search_term: (Some(q)), .sort(sort)
local_user: (local_user.as_ref()), .local_user(local_user.as_ref())
is_mod_or_admin: (is_admin), .page(page)
page: (page), .limit(limit)
limit: (limit), .search_term(Some(q))
..Default::default() .is_mod_or_admin(is_admin)
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
} }
SearchType::Users => { SearchType::Users => {
users = PersonQuery { users = PersonQuery {
@ -116,19 +116,19 @@ pub async fn search(
let q = data.q.clone(); let q = data.q.clone();
posts = PostQuery { posts = PostQuery::builder()
sort: (sort), .local_site(local_site.clone())
listing_type: (listing_type), .local_user(local_user_view.as_ref())
community_id: (community_id), .sort(sort)
creator_id: (creator_id), .community_id(community_id)
local_user: (local_user_view.as_ref()), .creator_id(creator_id)
search_term: (Some(q)), .listing_type(listing_type)
page: (page), .search_term(Some(q))
limit: (limit), .page(page)
..Default::default() .limit(limit)
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
let q = data.q.clone(); let q = data.q.clone();
@ -151,18 +151,18 @@ pub async fn search(
communities = if community_or_creator_included { communities = if community_or_creator_included {
vec![] vec![]
} else { } else {
CommunityQuery { CommunityQuery::builder()
sort: (sort), .local_site(local_site)
listing_type: (listing_type), .listing_type(listing_type)
search_term: (Some(q)), .sort(sort)
local_user: (local_user.as_ref()), .local_user(local_user.as_ref())
is_mod_or_admin: (is_admin), .page(page)
page: (page), .limit(limit)
limit: (limit), .search_term(Some(q))
..Default::default() .is_mod_or_admin(is_admin)
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await? .await?
}; };
let q = data.q.clone(); let q = data.q.clone();
@ -181,18 +181,19 @@ pub async fn search(
}; };
} }
SearchType::Url => { SearchType::Url => {
posts = PostQuery { posts = PostQuery::builder()
sort: (sort), .local_site(local_site)
listing_type: (listing_type), .local_user(local_user_view.as_ref())
community_id: (community_id), .sort(sort)
creator_id: (creator_id), .community_id(community_id)
url_search: (Some(q)), .creator_id(creator_id)
page: (page), .listing_type(listing_type)
limit: (limit), .search_term(Some(q))
..Default::default() .page(page)
} .limit(limit)
.list(&mut context.pool()) .build()
.await?; .list(&mut context.pool())
.await?;
} }
}; };

View File

@ -37,6 +37,7 @@ serde_with = { workspace = true }
tracing = { workspace = true, optional = true } tracing = { workspace = true, optional = true }
ts-rs = { workspace = true, optional = true } ts-rs = { workspace = true, optional = true }
actix-web = { workspace = true, optional = true } actix-web = { workspace = true, optional = true }
typed-builder = { workspace = true }
[dev-dependencies] [dev-dependencies]
serial_test = { workspace = true } serial_test = { workspace = true }

View File

@ -26,7 +26,6 @@ use lemmy_db_schema::{
community_moderator, community_moderator,
community_person_ban, community_person_ban,
instance_block, instance_block,
local_site::dsl::local_site,
local_user, local_user,
local_user_language, local_user_language,
person, person,
@ -55,6 +54,7 @@ use lemmy_db_schema::{
SortType, SortType,
}; };
use tracing::debug; use tracing::debug;
use typed_builder::TypedBuilder;
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Ord { enum Ord {
@ -386,12 +386,7 @@ fn queries<'a>() -> Queries<
} }
// If there is a content warning, show nsfw content by default. // If there is a content warning, show nsfw content by default.
// TODO: inefficient let has_content_warning = options.local_site.content_warning.is_some();
let has_content_warning = local_site
.first::<LocalSite>(&mut conn)
.await?
.content_warning
.is_some();
if !options if !options
.local_user .local_user
.map(|l| l.local_user.show_nsfw) .map(|l| l.local_user.show_nsfw)
@ -616,8 +611,11 @@ impl PaginationCursor {
#[derive(Clone)] #[derive(Clone)]
pub struct PaginationCursorData(PostAggregates); pub struct PaginationCursorData(PostAggregates);
#[derive(Default, Clone)] #[derive(Clone, TypedBuilder)]
#[builder(field_defaults(default))]
pub struct PostQuery<'a> { pub struct PostQuery<'a> {
#[builder(!default)]
pub local_site: LocalSite,
pub listing_type: Option<ListingType>, pub listing_type: Option<ListingType>,
pub sort: Option<SortType>, pub sort: Option<SortType>,
pub creator_id: Option<PersonId>, pub creator_id: Option<PersonId>,

View File

@ -34,6 +34,7 @@ ts-rs = { workspace = true, optional = true }
chrono.workspace = true chrono.workspace = true
strum = { workspace = true } strum = { workspace = true }
strum_macros = { workspace = true } strum_macros = { workspace = true }
typed-builder = { workspace = true }
[dev-dependencies] [dev-dependencies]
serial_test = { workspace = true } serial_test = { workspace = true }

View File

@ -18,7 +18,6 @@ use lemmy_db_schema::{
community_block, community_block,
community_follower, community_follower,
instance_block, instance_block,
local_site::dsl::local_site,
local_user, local_user,
}, },
source::{community::CommunityFollower, local_site::LocalSite, local_user::LocalUser}, source::{community::CommunityFollower, local_site::LocalSite, local_user::LocalUser},
@ -26,6 +25,7 @@ use lemmy_db_schema::{
ListingType, ListingType,
SortType, SortType,
}; };
use typed_builder::TypedBuilder;
fn queries<'a>() -> Queries< fn queries<'a>() -> Queries<
impl ReadFn<'a, CommunityView, (CommunityId, Option<PersonId>, bool)>, impl ReadFn<'a, CommunityView, (CommunityId, Option<PersonId>, bool)>,
@ -155,12 +155,7 @@ fn queries<'a>() -> Queries<
} else { } else {
// No person in request, only show nsfw communities if show_nsfw is passed into request or if // No person in request, only show nsfw communities if show_nsfw is passed into request or if
// site has content warning. // site has content warning.
// TODO: inefficient let has_content_warning = options.local_site.content_warning.is_some();
let has_content_warning = local_site
.first::<LocalSite>(&mut conn)
.await?
.content_warning
.is_some();
if !options.show_nsfw && !has_content_warning { if !options.show_nsfw && !has_content_warning {
query = query.filter(community::nsfw.eq(false)); query = query.filter(community::nsfw.eq(false));
} }
@ -220,8 +215,11 @@ impl CommunityView {
} }
} }
#[derive(Default)] #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct CommunityQuery<'a> { pub struct CommunityQuery<'a> {
#[builder(!default)]
pub local_site: LocalSite,
pub listing_type: Option<ListingType>, pub listing_type: Option<ListingType>,
pub sort: Option<SortType>, pub sort: Option<SortType>,
pub local_user: Option<&'a LocalUser>, pub local_user: Option<&'a LocalUser>,

View File

@ -128,15 +128,15 @@ async fn get_feed_data(
check_private_instance(&None, &site_view.local_site)?; check_private_instance(&None, &site_view.local_site)?;
let posts = PostQuery { let posts = PostQuery::builder()
listing_type: (Some(listing_type)), .local_site(site_view.local_site)
sort: (Some(sort_type)), .listing_type(Some(listing_type))
limit: (Some(limit)), .sort(Some(sort_type))
page: (Some(page)), .limit(Some(limit))
..Default::default() .page(Some(page))
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?; let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?;
@ -234,16 +234,16 @@ async fn get_feed_user(
check_private_instance(&None, &site_view.local_site)?; check_private_instance(&None, &site_view.local_site)?;
let posts = PostQuery { let posts = PostQuery::builder()
listing_type: (Some(ListingType::All)), .local_site(site_view.local_site)
sort: (Some(*sort_type)), .listing_type(Some(ListingType::All))
creator_id: (Some(person.id)), .creator_id(Some(person.id))
limit: (Some(*limit)), .sort(Some(*sort_type))
page: (Some(*page)), .limit(Some(*limit))
..Default::default() .page(Some(*page))
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?; let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?;
@ -271,15 +271,15 @@ async fn get_feed_community(
check_private_instance(&None, &site_view.local_site)?; check_private_instance(&None, &site_view.local_site)?;
let posts = PostQuery { let posts = PostQuery::builder()
sort: (Some(*sort_type)), .local_site(site_view.local_site)
community_id: (Some(community.id)), .community_id(Some(community.id))
limit: (Some(*limit)), .sort(Some(*sort_type))
page: (Some(*page)), .limit(Some(*limit))
..Default::default() .page(Some(*page))
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?; let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?;
@ -311,16 +311,16 @@ async fn get_feed_front(
check_private_instance(&Some(local_user.clone()), &site_view.local_site)?; check_private_instance(&Some(local_user.clone()), &site_view.local_site)?;
let posts = PostQuery { let posts = PostQuery::builder()
listing_type: (Some(ListingType::Subscribed)), .local_site(site_view.local_site)
local_user: (Some(&local_user)), .listing_type(Some(ListingType::Subscribed))
sort: (Some(*sort_type)), .local_user(Some(&local_user))
limit: (Some(*limit)), .sort(Some(*sort_type))
page: (Some(*page)), .limit(Some(*limit))
..Default::default() .page(Some(*page))
} .build()
.list(&mut context.pool()) .list(&mut context.pool())
.await?; .await?;
let protocol_and_hostname = context.settings().get_protocol_and_hostname(); let protocol_and_hostname = context.settings().get_protocol_and_hostname();
let items = create_post_items(posts, &protocol_and_hostname)?; let items = create_post_items(posts, &protocol_and_hostname)?;