Use typed-builder crate for queries (#2379)

* Use typed-builder crate for PrivateMessageQuery

* derive builder for all queries

* remove unnecessary clones

* fix tests
This commit is contained in:
Nutomic 2022-08-04 21:30:17 +02:00 committed by GitHub
parent 7094a0c0a4
commit 8a4d9cc1ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 469 additions and 796 deletions

View file

@ -41,7 +41,7 @@ steps:
commands: commands:
- apt-get update - apt-get update
- apt-get -y install --no-install-recommends postgresql-client - apt-get -y install --no-install-recommends postgresql-client
- cargo test --workspace --no-fail-fast - cargo test --workspace --no-fail-fast --all-features
- name: check defaults.hjson updated - name: check defaults.hjson updated
image: clux/muslrust:1.57.0 image: clux/muslrust:1.57.0

13
Cargo.lock generated
View file

@ -2020,6 +2020,7 @@ dependencies = [
"serde", "serde",
"serial_test", "serial_test",
"tracing", "tracing",
"typed-builder",
] ]
[[package]] [[package]]
@ -2029,6 +2030,7 @@ dependencies = [
"diesel", "diesel",
"lemmy_db_schema", "lemmy_db_schema",
"serde", "serde",
"typed-builder",
] ]
[[package]] [[package]]
@ -4201,6 +4203,17 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d" checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d"
[[package]]
name = "typed-builder"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c"
dependencies = [
"proc-macro2 1.0.39",
"quote 1.0.18",
"syn 1.0.96",
]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.15.0" version = "1.15.0"

View file

@ -4,7 +4,7 @@ use lemmy_api_common::{
comment::{ListCommentReports, ListCommentReportsResponse}, comment::{ListCommentReports, ListCommentReportsResponse},
utils::{blocking, get_local_user_view_from_jwt}, utils::{blocking, get_local_user_view_from_jwt},
}; };
use lemmy_db_views::comment_report_view::CommentReportQueryBuilder; use lemmy_db_views::comment_report_view::CommentReportQuery;
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -32,11 +32,15 @@ impl Perform for ListCommentReports {
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let comment_reports = blocking(context.pool(), move |conn| { let comment_reports = blocking(context.pool(), move |conn| {
CommentReportQueryBuilder::create(conn, person_id, admin) CommentReportQuery::builder()
.conn(conn)
.my_person_id(person_id)
.admin(admin)
.community_id(community_id) .community_id(community_id)
.unresolved_only(unresolved_only) .unresolved_only(unresolved_only)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;

View file

@ -4,7 +4,7 @@ use lemmy_api_common::{
person::{GetPersonMentions, GetPersonMentionsResponse}, person::{GetPersonMentions, GetPersonMentionsResponse},
utils::{blocking, get_local_user_view_from_jwt}, utils::{blocking, get_local_user_view_from_jwt},
}; };
use lemmy_db_views_actor::person_mention_view::PersonMentionQueryBuilder; use lemmy_db_views_actor::person_mention_view::PersonMentionQuery;
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -26,11 +26,12 @@ impl Perform for GetPersonMentions {
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let unread_only = data.unread_only; let unread_only = data.unread_only;
let person_id = local_user_view.person.id; let person_id = Some(local_user_view.person.id);
let show_bot_accounts = local_user_view.local_user.show_bot_accounts; let show_bot_accounts = Some(local_user_view.local_user.show_bot_accounts);
let mentions = blocking(context.pool(), move |conn| { let mentions = blocking(context.pool(), move |conn| {
PersonMentionQueryBuilder::create(conn) PersonMentionQuery::builder()
.conn(conn)
.recipient_id(person_id) .recipient_id(person_id)
.my_person_id(person_id) .my_person_id(person_id)
.sort(sort) .sort(sort)
@ -38,6 +39,7 @@ impl Perform for GetPersonMentions {
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;

View file

@ -4,7 +4,7 @@ use lemmy_api_common::{
person::{GetReplies, GetRepliesResponse}, person::{GetReplies, GetRepliesResponse},
utils::{blocking, get_local_user_view_from_jwt}, utils::{blocking, get_local_user_view_from_jwt},
}; };
use lemmy_db_views_actor::comment_reply_view::CommentReplyQueryBuilder; use lemmy_db_views_actor::comment_reply_view::CommentReplyQuery;
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -26,11 +26,12 @@ impl Perform for GetReplies {
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let unread_only = data.unread_only; let unread_only = data.unread_only;
let person_id = local_user_view.person.id; let person_id = Some(local_user_view.person.id);
let show_bot_accounts = local_user_view.local_user.show_bot_accounts; let show_bot_accounts = Some(local_user_view.local_user.show_bot_accounts);
let replies = blocking(context.pool(), move |conn| { let replies = blocking(context.pool(), move |conn| {
CommentReplyQueryBuilder::create(conn) CommentReplyQuery::builder()
.conn(conn)
.recipient_id(person_id) .recipient_id(person_id)
.my_person_id(person_id) .my_person_id(person_id)
.sort(sort) .sort(sort)
@ -38,6 +39,7 @@ impl Perform for GetReplies {
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;

View file

@ -4,7 +4,7 @@ use lemmy_api_common::{
post::{ListPostReports, ListPostReportsResponse}, post::{ListPostReports, ListPostReportsResponse},
utils::{blocking, get_local_user_view_from_jwt}, utils::{blocking, get_local_user_view_from_jwt},
}; };
use lemmy_db_views::post_report_view::PostReportQueryBuilder; use lemmy_db_views::post_report_view::PostReportQuery;
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -32,11 +32,15 @@ impl Perform for ListPostReports {
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let post_reports = blocking(context.pool(), move |conn| { let post_reports = blocking(context.pool(), move |conn| {
PostReportQueryBuilder::create(conn, person_id, admin) PostReportQuery::builder()
.conn(conn)
.my_person_id(person_id)
.admin(admin)
.community_id(community_id) .community_id(community_id)
.unresolved_only(unresolved_only) .unresolved_only(unresolved_only)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
utils::{blocking, get_local_user_view_from_jwt, is_admin}, utils::{blocking, get_local_user_view_from_jwt, is_admin},
}; };
use lemmy_db_schema::source::site::Site; use lemmy_db_schema::source::site::Site;
use lemmy_db_views::registration_application_view::RegistrationApplicationQueryBuilder; use lemmy_db_views::registration_application_view::RegistrationApplicationQuery;
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -34,11 +34,13 @@ impl Perform for ListRegistrationApplications {
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let registration_applications = blocking(context.pool(), move |conn| { let registration_applications = blocking(context.pool(), move |conn| {
RegistrationApplicationQueryBuilder::create(conn) RegistrationApplicationQuery::builder()
.conn(conn)
.unread_only(unread_only) .unread_only(unread_only)
.verified_email_only(verified_email_only) .verified_email_only(Some(verified_email_only))
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;

View file

@ -11,11 +11,8 @@ use lemmy_db_schema::{
utils::post_to_comment_sort_type, utils::post_to_comment_sort_type,
SearchType, SearchType,
}; };
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder}; use lemmy_db_views::{comment_view::CommentQuery, post_view::PostQuery};
use lemmy_db_views_actor::{ use lemmy_db_views_actor::{community_view::CommunityQuery, person_view::PersonQuery};
community_view::CommunityQueryBuilder,
person_view::PersonQueryBuilder,
};
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -73,7 +70,8 @@ impl Perform for Search {
match search_type { match search_type {
SearchType::Posts => { SearchType::Posts => {
posts = blocking(context.pool(), move |conn| { posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn) PostQuery::builder()
.conn(conn)
.sort(sort) .sort(sort)
.show_nsfw(show_nsfw) .show_nsfw(show_nsfw)
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
@ -83,19 +81,21 @@ impl Perform for Search {
.community_actor_id(community_actor_id) .community_actor_id(community_actor_id)
.creator_id(creator_id) .creator_id(creator_id)
.my_person_id(person_id) .my_person_id(person_id)
.search_term(q) .search_term(Some(q))
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;
} }
SearchType::Comments => { SearchType::Comments => {
comments = blocking(context.pool(), move |conn| { comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn) CommentQuery::builder()
.conn(conn)
.sort(sort.map(post_to_comment_sort_type)) .sort(sort.map(post_to_comment_sort_type))
.listing_type(listing_type) .listing_type(listing_type)
.search_term(q) .search_term(Some(q))
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
.community_id(community_id) .community_id(community_id)
.community_actor_id(community_actor_id) .community_actor_id(community_actor_id)
@ -103,30 +103,35 @@ impl Perform for Search {
.my_person_id(person_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;
} }
SearchType::Communities => { SearchType::Communities => {
communities = blocking(context.pool(), move |conn| { communities = blocking(context.pool(), move |conn| {
CommunityQueryBuilder::create(conn) CommunityQuery::builder()
.conn(conn)
.sort(sort) .sort(sort)
.listing_type(listing_type) .listing_type(listing_type)
.search_term(q) .search_term(Some(q))
.my_person_id(person_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;
} }
SearchType::Users => { SearchType::Users => {
users = blocking(context.pool(), move |conn| { users = blocking(context.pool(), move |conn| {
PersonQueryBuilder::create(conn) PersonQuery::builder()
.conn(conn)
.sort(sort) .sort(sort)
.search_term(q) .search_term(Some(q))
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;
@ -138,7 +143,8 @@ impl Perform for Search {
let community_actor_id_2 = community_actor_id.to_owned(); let community_actor_id_2 = community_actor_id.to_owned();
posts = blocking(context.pool(), move |conn| { posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn) PostQuery::builder()
.conn(conn)
.sort(sort) .sort(sort)
.show_nsfw(show_nsfw) .show_nsfw(show_nsfw)
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
@ -148,9 +154,10 @@ impl Perform for Search {
.community_actor_id(community_actor_id_2) .community_actor_id(community_actor_id_2)
.creator_id(creator_id) .creator_id(creator_id)
.my_person_id(person_id) .my_person_id(person_id)
.search_term(q) .search_term(Some(q))
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;
@ -159,10 +166,11 @@ impl Perform for Search {
let community_actor_id = community_actor_id.to_owned(); let community_actor_id = community_actor_id.to_owned();
comments = blocking(context.pool(), move |conn| { comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn) CommentQuery::builder()
.conn(conn)
.sort(sort.map(post_to_comment_sort_type)) .sort(sort.map(post_to_comment_sort_type))
.listing_type(listing_type) .listing_type(listing_type)
.search_term(q) .search_term(Some(q))
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
.community_id(community_id) .community_id(community_id)
.community_actor_id(community_actor_id) .community_actor_id(community_actor_id)
@ -170,6 +178,7 @@ impl Perform for Search {
.my_person_id(person_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;
@ -180,13 +189,15 @@ impl Perform for Search {
vec![] vec![]
} else { } else {
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
CommunityQueryBuilder::create(conn) CommunityQuery::builder()
.conn(conn)
.sort(sort) .sort(sort)
.listing_type(listing_type) .listing_type(listing_type)
.search_term(q) .search_term(Some(q))
.my_person_id(person_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await?? .await??
@ -198,11 +209,13 @@ impl Perform for Search {
vec![] vec![]
} else { } else {
blocking(context.pool(), move |conn| { blocking(context.pool(), move |conn| {
PersonQueryBuilder::create(conn) PersonQuery::builder()
.conn(conn)
.sort(sort) .sort(sort)
.search_term(q) .search_term(Some(q))
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await?? .await??
@ -210,7 +223,8 @@ impl Perform for Search {
} }
SearchType::Url => { SearchType::Url => {
posts = blocking(context.pool(), move |conn| { posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn) PostQuery::builder()
.conn(conn)
.sort(sort) .sort(sort)
.show_nsfw(show_nsfw) .show_nsfw(show_nsfw)
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
@ -220,9 +234,10 @@ impl Perform for Search {
.community_id(community_id) .community_id(community_id)
.community_actor_id(community_actor_id) .community_actor_id(community_actor_id)
.creator_id(creator_id) .creator_id(creator_id)
.url_search(q) .url_search(Some(q))
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;

View file

@ -20,7 +20,7 @@ use lemmy_db_schema::{
ListingType, ListingType,
}; };
use lemmy_db_views::{ use lemmy_db_views::{
comment_view::CommentQueryBuilder, comment_view::CommentQuery,
structs::{LocalUserSettingsView, LocalUserView}, structs::{LocalUserSettingsView, LocalUserView},
}; };
use lemmy_db_views_actor::structs::{ use lemmy_db_views_actor::structs::{
@ -667,10 +667,12 @@ pub async fn remove_user_data_in_community(
// Comments // Comments
// TODO Diesel doesn't allow updates with joins, so this has to be a loop // TODO Diesel doesn't allow updates with joins, so this has to be a loop
let comments = blocking(pool, move |conn| { let comments = blocking(pool, move |conn| {
CommentQueryBuilder::create(conn) CommentQuery::builder()
.creator_id(banned_person_id) .conn(conn)
.community_id(community_id) .creator_id(Some(banned_person_id))
.limit(std::i64::MAX) .community_id(Some(community_id))
.limit(Some(i64::MAX))
.build()
.list() .list()
}) })
.await??; .await??;

View file

@ -14,7 +14,7 @@ use lemmy_db_schema::{
source::{comment::Comment, community::Community}, source::{comment::Comment, community::Community},
traits::{Crud, DeleteableOrRemoveable}, traits::{Crud, DeleteableOrRemoveable},
}; };
use lemmy_db_views::comment_view::CommentQueryBuilder; use lemmy_db_views::comment_view::CommentQuery;
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -71,8 +71,9 @@ impl PerformCrud for GetComments {
let post_id = data.post_id; let post_id = data.post_id;
let mut comments = blocking(context.pool(), move |conn| { let mut comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn) CommentQuery::builder()
.listing_type(listing_type) .conn(conn)
.listing_type(Some(listing_type))
.sort(sort) .sort(sort)
.max_depth(max_depth) .max_depth(max_depth)
.saved_only(saved_only) .saved_only(saved_only)
@ -84,6 +85,7 @@ impl PerformCrud for GetComments {
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await? .await?

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt}, utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
}; };
use lemmy_db_schema::traits::DeleteableOrRemoveable; use lemmy_db_schema::traits::DeleteableOrRemoveable;
use lemmy_db_views_actor::community_view::CommunityQueryBuilder; use lemmy_db_views_actor::community_view::CommunityQuery;
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -39,13 +39,15 @@ impl PerformCrud for ListCommunities {
let page = data.page; let page = data.page;
let limit = data.limit; let limit = data.limit;
let mut communities = blocking(context.pool(), move |conn| { let mut communities = blocking(context.pool(), move |conn| {
CommunityQueryBuilder::create(conn) CommunityQuery::builder()
.conn(conn)
.listing_type(listing_type) .listing_type(listing_type)
.sort(sort) .sort(sort)
.show_nsfw(show_nsfw) .show_nsfw(Some(show_nsfw))
.my_person_id(person_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await??; .await??;

View file

@ -11,7 +11,7 @@ use lemmy_api_common::{
}; };
use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity}; use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
use lemmy_db_schema::{source::community::Community, traits::DeleteableOrRemoveable}; use lemmy_db_schema::{source::community::Community, traits::DeleteableOrRemoveable};
use lemmy_db_views::post_view::PostQueryBuilder; use lemmy_db_views::post_view::PostQuery;
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -59,8 +59,9 @@ impl PerformCrud for GetPosts {
let saved_only = data.saved_only; let saved_only = data.saved_only;
let mut posts = blocking(context.pool(), move |conn| { let mut posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn) PostQuery::builder()
.listing_type(listing_type) .conn(conn)
.listing_type(Some(listing_type))
.sort(sort) .sort(sort)
.show_nsfw(show_nsfw) .show_nsfw(show_nsfw)
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
@ -71,6 +72,7 @@ impl PerformCrud for GetPosts {
.my_person_id(person_id) .my_person_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.build()
.list() .list()
}) })
.await? .await?

View file

@ -5,7 +5,7 @@ use lemmy_api_common::{
utils::{blocking, get_local_user_view_from_jwt}, utils::{blocking, get_local_user_view_from_jwt},
}; };
use lemmy_db_schema::traits::DeleteableOrRemoveable; use lemmy_db_schema::traits::DeleteableOrRemoveable;
use lemmy_db_views::private_message_view::PrivateMessageQueryBuilder; use lemmy_db_views::private_message_view::PrivateMessageQuery;
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -28,10 +28,13 @@ impl PerformCrud for GetPrivateMessages {
let limit = data.limit; let limit = data.limit;
let unread_only = data.unread_only; let unread_only = data.unread_only;
let mut messages = blocking(context.pool(), move |conn| { let mut messages = blocking(context.pool(), move |conn| {
PrivateMessageQueryBuilder::create(conn, person_id) PrivateMessageQuery::builder()
.conn(conn)
.recipient_id(person_id)
.page(page) .page(page)
.limit(limit) .limit(limit)
.unread_only(unread_only) .unread_only(unread_only)
.build()
.list() .list()
}) })
.await??; .await??;

View file

@ -6,7 +6,7 @@ use lemmy_api_common::{
}; };
use lemmy_apub::{fetcher::resolve_actor_identifier, objects::person::ApubPerson}; use lemmy_apub::{fetcher::resolve_actor_identifier, objects::person::ApubPerson};
use lemmy_db_schema::{source::person::Person, utils::post_to_comment_sort_type}; use lemmy_db_schema::{source::person::Person, utils::post_to_comment_sort_type};
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder}; use lemmy_db_views::{comment_view::CommentQuery, post_view::PostQuery};
use lemmy_db_views_actor::structs::{CommunityModeratorView, PersonViewSafe}; use lemmy_db_views_actor::structs::{CommunityModeratorView, PersonViewSafe};
use lemmy_utils::{error::LemmyError, ConnectionId}; use lemmy_utils::{error::LemmyError, ConnectionId};
use lemmy_websocket::LemmyContext; use lemmy_websocket::LemmyContext;
@ -74,7 +74,8 @@ impl PerformCrud for GetPersonDetails {
let community_id = data.community_id; let community_id = data.community_id;
let (posts, comments) = blocking(context.pool(), move |conn| { let (posts, comments) = blocking(context.pool(), move |conn| {
let mut posts_query = PostQueryBuilder::create(conn) let posts_query = PostQuery::builder()
.conn(conn)
.sort(sort) .sort(sort)
.show_nsfw(show_nsfw) .show_nsfw(show_nsfw)
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
@ -85,7 +86,8 @@ impl PerformCrud for GetPersonDetails {
.page(page) .page(page)
.limit(limit); .limit(limit);
let mut comments_query = CommentQueryBuilder::create(conn) let comments_query = CommentQuery::builder()
.conn(conn)
.my_person_id(person_id) .my_person_id(person_id)
.show_bot_accounts(show_bot_accounts) .show_bot_accounts(show_bot_accounts)
.sort(sort.map(post_to_comment_sort_type)) .sort(sort.map(post_to_comment_sort_type))
@ -96,13 +98,20 @@ impl PerformCrud for GetPersonDetails {
// If its saved only, you don't care what creator it was // If its saved only, you don't care what creator it was
// Or, if its not saved, then you only want it for that specific creator // Or, if its not saved, then you only want it for that specific creator
if !saved_only.unwrap_or(false) { let (posts, comments) = if !saved_only.unwrap_or(false) {
posts_query = posts_query.creator_id(person_details_id); (
comments_query = comments_query.creator_id(person_details_id); posts_query
} .creator_id(Some(person_details_id))
.build()
let posts = posts_query.list()?; .list()?,
let comments = comments_query.list()?; comments_query
.creator_id(Some(person_details_id))
.build()
.list()?,
)
} else {
(posts_query.build().list()?, comments_query.build().list()?)
};
Ok((posts, comments)) as Result<_, LemmyError> Ok((posts, comments)) as Result<_, LemmyError>
}) })

View file

@ -130,22 +130,6 @@ pub trait DeleteableOrRemoveable {
fn blank_out_deleted_or_removed_info(self) -> Self; fn blank_out_deleted_or_removed_info(self) -> Self;
} }
pub trait MaybeOptional<T> {
fn get_optional(self) -> Option<T>;
}
impl<T> MaybeOptional<T> for T {
fn get_optional(self) -> Option<T> {
Some(self)
}
}
impl<T> MaybeOptional<T> for Option<T> {
fn get_optional(self) -> Option<T> {
self
}
}
pub trait ToSafe { pub trait ToSafe {
type SafeColumns; type SafeColumns;
fn safe_columns_tuple() -> Self::SafeColumns; fn safe_columns_tuple() -> Self::SafeColumns;

View file

@ -20,6 +20,7 @@ diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json
serde = { version = "1.0.136", features = ["derive"] } serde = { version = "1.0.136", features = ["derive"] }
tracing = { version = "0.1.32", optional = true } tracing = { version = "0.1.32", optional = true }
diesel_ltree = "0.2.7" diesel_ltree = "0.2.7"
typed-builder = "0.10.0"
[dev-dependencies] [dev-dependencies]
serial_test = "0.6.0" serial_test = "0.6.0"

View file

@ -23,9 +23,10 @@ use lemmy_db_schema::{
person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2}, person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
post::Post, post::Post,
}, },
traits::{MaybeOptional, ToSafe, ViewToVec}, traits::{ToSafe, ViewToVec},
utils::limit_and_offset, utils::limit_and_offset,
}; };
use typed_builder::TypedBuilder;
type CommentReportViewTuple = ( type CommentReportViewTuple = (
CommentReport, CommentReport,
@ -159,9 +160,14 @@ impl CommentReportView {
} }
} }
pub struct CommentReportQueryBuilder<'a> { #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct CommentReportQuery<'a> {
#[builder(!default)]
conn: &'a PgConnection, conn: &'a PgConnection,
#[builder(!default)]
my_person_id: PersonId, my_person_id: PersonId,
#[builder(!default)]
admin: bool, admin: bool,
community_id: Option<CommunityId>, community_id: Option<CommunityId>,
page: Option<i64>, page: Option<i64>,
@ -169,39 +175,7 @@ pub struct CommentReportQueryBuilder<'a> {
unresolved_only: Option<bool>, unresolved_only: Option<bool>,
} }
impl<'a> CommentReportQueryBuilder<'a> { impl<'a> CommentReportQuery<'a> {
pub fn create(conn: &'a PgConnection, my_person_id: PersonId, admin: bool) -> Self {
CommentReportQueryBuilder {
conn,
my_person_id,
admin,
community_id: None,
page: None,
limit: None,
unresolved_only: Some(true),
}
}
pub fn community_id<T: MaybeOptional<CommunityId>>(mut self, community_id: T) -> Self {
self.community_id = community_id.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn unresolved_only<T: MaybeOptional<bool>>(mut self, unresolved_only: T) -> Self {
self.unresolved_only = unresolved_only.get_optional();
self
}
pub fn list(self) -> Result<Vec<CommentReportView>, Error> { pub fn list(self) -> Result<Vec<CommentReportView>, Error> {
let mut query = comment_report::table let mut query = comment_report::table
.inner_join(comment::table) .inner_join(comment::table)
@ -252,7 +226,7 @@ impl<'a> CommentReportQueryBuilder<'a> {
query = query.filter(post::community_id.eq(community_id)); query = query.filter(post::community_id.eq(community_id));
} }
if self.unresolved_only.unwrap_or(false) { if self.unresolved_only.unwrap_or(true) {
query = query.filter(comment_report::resolved.eq(false)); query = query.filter(comment_report::resolved.eq(false));
} }
@ -286,18 +260,18 @@ impl ViewToVec for CommentReportView {
type DbTuple = CommentReportViewTuple; type DbTuple = CommentReportViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
comment_report: a.0.to_owned(), comment_report: a.0,
comment: a.1.to_owned(), comment: a.1,
post: a.2.to_owned(), post: a.2,
community: a.3.to_owned(), community: a.3,
creator: a.4.to_owned(), creator: a.4,
comment_creator: a.5.to_owned(), comment_creator: a.5,
counts: a.6.to_owned(), counts: a.6,
creator_banned_from_community: a.7.is_some(), creator_banned_from_community: a.7.is_some(),
my_vote: a.8, my_vote: a.8,
resolver: a.9.to_owned(), resolver: a.9,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }
@ -305,7 +279,7 @@ impl ViewToVec for CommentReportView {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::comment_report_view::{CommentReportQueryBuilder, CommentReportView}; use crate::comment_report_view::{CommentReportQuery, CommentReportView};
use lemmy_db_schema::{ use lemmy_db_schema::{
aggregates::structs::CommentAggregates, aggregates::structs::CommentAggregates,
source::{comment::*, comment_report::*, community::*, person::*, post::*}, source::{comment::*, comment_report::*, community::*, person::*, post::*},
@ -504,7 +478,11 @@ mod tests {
}; };
// Do a batch read of timmys reports // Do a batch read of timmys reports
let reports = CommentReportQueryBuilder::create(&conn, inserted_timmy.id, false) let reports = CommentReportQuery::builder()
.conn(&conn)
.my_person_id(inserted_timmy.id)
.admin(false)
.build()
.list() .list()
.unwrap(); .unwrap();
@ -566,10 +544,15 @@ mod tests {
// Do a batch read of timmys reports // Do a batch read of timmys reports
// It should only show saras, which is unresolved // It should only show saras, which is unresolved
let reports_after_resolve = CommentReportQueryBuilder::create(&conn, inserted_timmy.id, false) let reports_after_resolve = CommentReportQuery::builder()
.conn(&conn)
.my_person_id(inserted_timmy.id)
.admin(false)
.build()
.list() .list()
.unwrap(); .unwrap();
assert_eq!(reports_after_resolve[0], expected_sara_report_view); assert_eq!(reports_after_resolve[0], expected_sara_report_view);
assert_eq!(reports_after_resolve.len(), 1);
// Make sure the counts are correct // Make sure the counts are correct
let report_count_after_resolved = let report_count_after_resolved =

View file

@ -24,11 +24,12 @@ use lemmy_db_schema::{
person_block::PersonBlock, person_block::PersonBlock,
post::Post, post::Post,
}, },
traits::{MaybeOptional, ToSafe, ViewToVec}, traits::{ToSafe, ViewToVec},
utils::{functions::hot_rank, fuzzy_search, limit_and_offset_unlimited}, utils::{functions::hot_rank, fuzzy_search, limit_and_offset_unlimited},
CommentSortType, CommentSortType,
ListingType, ListingType,
}; };
use typed_builder::TypedBuilder;
type CommentViewTuple = ( type CommentViewTuple = (
Comment, Comment,
@ -146,7 +147,10 @@ impl CommentView {
} }
} }
pub struct CommentQueryBuilder<'a> { #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct CommentQuery<'a> {
#[builder(!default)]
conn: &'a PgConnection, conn: &'a PgConnection,
listing_type: Option<ListingType>, listing_type: Option<ListingType>,
sort: Option<CommentSortType>, sort: Option<CommentSortType>,
@ -164,97 +168,7 @@ pub struct CommentQueryBuilder<'a> {
max_depth: Option<i32>, max_depth: Option<i32>,
} }
impl<'a> CommentQueryBuilder<'a> { impl<'a> CommentQuery<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
CommentQueryBuilder {
conn,
listing_type: Some(ListingType::All),
sort: None,
community_id: None,
community_actor_id: None,
post_id: None,
parent_path: None,
creator_id: None,
my_person_id: None,
search_term: None,
saved_only: None,
show_bot_accounts: None,
page: None,
limit: None,
max_depth: None,
}
}
pub fn listing_type<T: MaybeOptional<ListingType>>(mut self, listing_type: T) -> Self {
self.listing_type = listing_type.get_optional();
self
}
pub fn sort<T: MaybeOptional<CommentSortType>>(mut self, sort: T) -> Self {
self.sort = sort.get_optional();
self
}
pub fn post_id<T: MaybeOptional<PostId>>(mut self, post_id: T) -> Self {
self.post_id = post_id.get_optional();
self
}
pub fn creator_id<T: MaybeOptional<PersonId>>(mut self, creator_id: T) -> Self {
self.creator_id = creator_id.get_optional();
self
}
pub fn community_id<T: MaybeOptional<CommunityId>>(mut self, community_id: T) -> Self {
self.community_id = community_id.get_optional();
self
}
pub fn my_person_id<T: MaybeOptional<PersonId>>(mut self, my_person_id: T) -> Self {
self.my_person_id = my_person_id.get_optional();
self
}
pub fn community_actor_id<T: MaybeOptional<DbUrl>>(mut self, community_actor_id: T) -> Self {
self.community_actor_id = community_actor_id.get_optional();
self
}
pub fn search_term<T: MaybeOptional<String>>(mut self, search_term: T) -> Self {
self.search_term = search_term.get_optional();
self
}
pub fn saved_only<T: MaybeOptional<bool>>(mut self, saved_only: T) -> Self {
self.saved_only = saved_only.get_optional();
self
}
pub fn show_bot_accounts<T: MaybeOptional<bool>>(mut self, show_bot_accounts: T) -> Self {
self.show_bot_accounts = show_bot_accounts.get_optional();
self
}
pub fn parent_path<T: MaybeOptional<Ltree>>(mut self, parent_path: T) -> Self {
self.parent_path = parent_path.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn max_depth<T: MaybeOptional<i32>>(mut self, max_depth: T) -> Self {
self.max_depth = max_depth.get_optional();
self
}
pub fn list(self) -> Result<Vec<CommentView>, Error> { pub fn list(self) -> Result<Vec<CommentView>, Error> {
use diesel::dsl::*; use diesel::dsl::*;
@ -437,13 +351,13 @@ impl ViewToVec for CommentView {
type DbTuple = CommentViewTuple; type DbTuple = CommentViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
comment: a.0.to_owned(), comment: a.0,
creator: a.1.to_owned(), creator: a.1,
post: a.2.to_owned(), post: a.2,
community: a.3.to_owned(), community: a.3,
counts: a.4.to_owned(), counts: a.4,
creator_banned_from_community: a.5.is_some(), creator_banned_from_community: a.5.is_some(),
subscribed: CommunityFollower::to_subscribed_type(&a.6), subscribed: CommunityFollower::to_subscribed_type(&a.6),
saved: a.7.is_some(), saved: a.7.is_some(),
@ -691,8 +605,10 @@ mod tests {
let mut expected_comment_view_with_person = expected_comment_view_no_person.to_owned(); let mut expected_comment_view_with_person = expected_comment_view_no_person.to_owned();
expected_comment_view_with_person.my_vote = Some(1); expected_comment_view_with_person.my_vote = Some(1);
let read_comment_views_no_person = CommentQueryBuilder::create(&conn) let read_comment_views_no_person = CommentQuery::builder()
.post_id(inserted_post.id) .conn(&conn)
.post_id(Some(inserted_post.id))
.build()
.list() .list()
.unwrap(); .unwrap();
@ -701,9 +617,11 @@ mod tests {
read_comment_views_no_person[0] read_comment_views_no_person[0]
); );
let read_comment_views_with_person = CommentQueryBuilder::create(&conn) let read_comment_views_with_person = CommentQuery::builder()
.post_id(inserted_post.id) .conn(&conn)
.my_person_id(inserted_person.id) .post_id(Some(inserted_post.id))
.my_person_id(Some(inserted_person.id))
.build()
.list() .list()
.unwrap(); .unwrap();
@ -722,16 +640,20 @@ mod tests {
assert!(read_comment_from_blocked_person.creator_blocked); assert!(read_comment_from_blocked_person.creator_blocked);
let top_path = inserted_comment_0.path; let top_path = inserted_comment_0.path;
let read_comment_views_top_path = CommentQueryBuilder::create(&conn) let read_comment_views_top_path = CommentQuery::builder()
.post_id(inserted_post.id) .conn(&conn)
.parent_path(top_path) .post_id(Some(inserted_post.id))
.parent_path(Some(top_path))
.build()
.list() .list()
.unwrap(); .unwrap();
let child_path = inserted_comment_1.to_owned().path; let child_path = inserted_comment_1.to_owned().path;
let read_comment_views_child_path = CommentQueryBuilder::create(&conn) let read_comment_views_child_path = CommentQuery::builder()
.post_id(inserted_post.id) .conn(&conn)
.parent_path(child_path) .post_id(Some(inserted_post.id))
.parent_path(Some(child_path))
.build()
.list() .list()
.unwrap(); .unwrap();
@ -747,9 +669,11 @@ mod tests {
assert!(child_comments.contains(&inserted_comment_1)); assert!(child_comments.contains(&inserted_comment_1));
assert!(!child_comments.contains(&inserted_comment_2)); assert!(!child_comments.contains(&inserted_comment_2));
let read_comment_views_top_max_depth = CommentQueryBuilder::create(&conn) let read_comment_views_top_max_depth = CommentQuery::builder()
.post_id(inserted_post.id) .conn(&conn)
.max_depth(1) .post_id(Some(inserted_post.id))
.max_depth(Some(1))
.build()
.list() .list()
.unwrap(); .unwrap();
@ -761,11 +685,13 @@ mod tests {
assert_eq!(1, read_comment_views_top_max_depth.len()); assert_eq!(1, read_comment_views_top_max_depth.len());
let child_path = inserted_comment_1.path; let child_path = inserted_comment_1.path;
let read_comment_views_parent_max_depth = CommentQueryBuilder::create(&conn) let read_comment_views_parent_max_depth = CommentQuery::builder()
.post_id(inserted_post.id) .conn(&conn)
.parent_path(child_path) .post_id(Some(inserted_post.id))
.max_depth(1) .parent_path(Some(child_path))
.sort(CommentSortType::New) .max_depth(Some(1))
.sort(Some(CommentSortType::New))
.build()
.list() .list()
.unwrap(); .unwrap();

View file

@ -21,9 +21,10 @@ use lemmy_db_schema::{
post::Post, post::Post,
post_report::PostReport, post_report::PostReport,
}, },
traits::{MaybeOptional, ToSafe, ViewToVec}, traits::{ToSafe, ViewToVec},
utils::limit_and_offset, utils::limit_and_offset,
}; };
use typed_builder::TypedBuilder;
type PostReportViewTuple = ( type PostReportViewTuple = (
PostReport, PostReport,
@ -148,9 +149,14 @@ impl PostReportView {
} }
} }
pub struct PostReportQueryBuilder<'a> { #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct PostReportQuery<'a> {
#[builder(!default)]
conn: &'a PgConnection, conn: &'a PgConnection,
#[builder(!default)]
my_person_id: PersonId, my_person_id: PersonId,
#[builder(!default)]
admin: bool, admin: bool,
community_id: Option<CommunityId>, community_id: Option<CommunityId>,
page: Option<i64>, page: Option<i64>,
@ -158,39 +164,7 @@ pub struct PostReportQueryBuilder<'a> {
unresolved_only: Option<bool>, unresolved_only: Option<bool>,
} }
impl<'a> PostReportQueryBuilder<'a> { impl<'a> PostReportQuery<'a> {
pub fn create(conn: &'a PgConnection, my_person_id: PersonId, admin: bool) -> Self {
PostReportQueryBuilder {
conn,
my_person_id,
admin,
community_id: None,
page: None,
limit: None,
unresolved_only: Some(true),
}
}
pub fn community_id<T: MaybeOptional<CommunityId>>(mut self, community_id: T) -> Self {
self.community_id = community_id.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn unresolved_only<T: MaybeOptional<bool>>(mut self, unresolved_only: T) -> Self {
self.unresolved_only = unresolved_only.get_optional();
self
}
pub fn list(self) -> Result<Vec<PostReportView>, Error> { pub fn list(self) -> Result<Vec<PostReportView>, Error> {
let mut query = post_report::table let mut query = post_report::table
.inner_join(post::table) .inner_join(post::table)
@ -237,7 +211,7 @@ impl<'a> PostReportQueryBuilder<'a> {
query = query.filter(post::community_id.eq(community_id)); query = query.filter(post::community_id.eq(community_id));
} }
if self.unresolved_only.unwrap_or(false) { if self.unresolved_only.unwrap_or(true) {
query = query.filter(post_report::resolved.eq(false)); query = query.filter(post_report::resolved.eq(false));
} }
@ -271,17 +245,17 @@ impl ViewToVec for PostReportView {
type DbTuple = PostReportViewTuple; type DbTuple = PostReportViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
post_report: a.0.to_owned(), post_report: a.0,
post: a.1.to_owned(), post: a.1,
community: a.2.to_owned(), community: a.2,
creator: a.3.to_owned(), creator: a.3,
post_creator: a.4.to_owned(), post_creator: a.4,
creator_banned_from_community: a.5.is_some(), creator_banned_from_community: a.5.is_some(),
my_vote: a.6, my_vote: a.6,
counts: a.7.to_owned(), counts: a.7,
resolver: a.8.to_owned(), resolver: a.8,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }
@ -289,7 +263,7 @@ impl ViewToVec for PostReportView {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::post_report_view::{PostReportQueryBuilder, PostReportView}; use crate::post_report_view::{PostReportQuery, PostReportView};
use lemmy_db_schema::{ use lemmy_db_schema::{
aggregates::structs::PostAggregates, aggregates::structs::PostAggregates,
source::{ source::{
@ -491,7 +465,11 @@ mod tests {
}; };
// Do a batch read of timmys reports // Do a batch read of timmys reports
let reports = PostReportQueryBuilder::create(&conn, inserted_timmy.id, false) let reports = PostReportQuery::builder()
.conn(&conn)
.my_person_id(inserted_timmy.id)
.admin(false)
.build()
.list() .list()
.unwrap(); .unwrap();
@ -551,7 +529,11 @@ mod tests {
// Do a batch read of timmys reports // Do a batch read of timmys reports
// It should only show saras, which is unresolved // It should only show saras, which is unresolved
let reports_after_resolve = PostReportQueryBuilder::create(&conn, inserted_timmy.id, false) let reports_after_resolve = PostReportQuery::builder()
.conn(&conn)
.my_person_id(inserted_timmy.id)
.admin(false)
.build()
.list() .list()
.unwrap(); .unwrap();
assert_eq!(reports_after_resolve[0], expected_sara_report_view); assert_eq!(reports_after_resolve[0], expected_sara_report_view);

View file

@ -22,12 +22,13 @@ use lemmy_db_schema::{
person_block::PersonBlock, person_block::PersonBlock,
post::{Post, PostRead, PostSaved}, post::{Post, PostRead, PostSaved},
}, },
traits::{MaybeOptional, ToSafe, ViewToVec}, traits::{ToSafe, ViewToVec},
utils::{functions::hot_rank, fuzzy_search, limit_and_offset}, utils::{functions::hot_rank, fuzzy_search, limit_and_offset},
ListingType, ListingType,
SortType, SortType,
}; };
use tracing::debug; use tracing::debug;
use typed_builder::TypedBuilder;
type PostViewTuple = ( type PostViewTuple = (
Post, Post,
@ -151,7 +152,10 @@ impl PostView {
} }
} }
pub struct PostQueryBuilder<'a> { #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct PostQuery<'a> {
#[builder(!default)]
conn: &'a PgConnection, conn: &'a PgConnection,
listing_type: Option<ListingType>, listing_type: Option<ListingType>,
sort: Option<SortType>, sort: Option<SortType>,
@ -169,97 +173,7 @@ pub struct PostQueryBuilder<'a> {
limit: Option<i64>, limit: Option<i64>,
} }
impl<'a> PostQueryBuilder<'a> { impl<'a> PostQuery<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
PostQueryBuilder {
conn,
listing_type: Some(ListingType::All),
sort: None,
creator_id: None,
community_id: None,
community_actor_id: None,
my_person_id: None,
search_term: None,
url_search: None,
show_nsfw: None,
show_bot_accounts: None,
show_read_posts: None,
saved_only: None,
page: None,
limit: None,
}
}
pub fn listing_type<T: MaybeOptional<ListingType>>(mut self, listing_type: T) -> Self {
self.listing_type = listing_type.get_optional();
self
}
pub fn sort<T: MaybeOptional<SortType>>(mut self, sort: T) -> Self {
self.sort = sort.get_optional();
self
}
pub fn community_id<T: MaybeOptional<CommunityId>>(mut self, community_id: T) -> Self {
self.community_id = community_id.get_optional();
self
}
pub fn my_person_id<T: MaybeOptional<PersonId>>(mut self, my_person_id: T) -> Self {
self.my_person_id = my_person_id.get_optional();
self
}
pub fn community_actor_id<T: MaybeOptional<DbUrl>>(mut self, community_actor_id: T) -> Self {
self.community_actor_id = community_actor_id.get_optional();
self
}
pub fn creator_id<T: MaybeOptional<PersonId>>(mut self, creator_id: T) -> Self {
self.creator_id = creator_id.get_optional();
self
}
pub fn search_term<T: MaybeOptional<String>>(mut self, search_term: T) -> Self {
self.search_term = search_term.get_optional();
self
}
pub fn url_search<T: MaybeOptional<String>>(mut self, url_search: T) -> Self {
self.url_search = url_search.get_optional();
self
}
pub fn show_nsfw<T: MaybeOptional<bool>>(mut self, show_nsfw: T) -> Self {
self.show_nsfw = show_nsfw.get_optional();
self
}
pub fn show_bot_accounts<T: MaybeOptional<bool>>(mut self, show_bot_accounts: T) -> Self {
self.show_bot_accounts = show_bot_accounts.get_optional();
self
}
pub fn show_read_posts<T: MaybeOptional<bool>>(mut self, show_read_posts: T) -> Self {
self.show_read_posts = show_read_posts.get_optional();
self
}
pub fn saved_only<T: MaybeOptional<bool>>(mut self, saved_only: T) -> Self {
self.saved_only = saved_only.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn list(self) -> Result<Vec<PostView>, Error> { pub fn list(self) -> Result<Vec<PostView>, Error> {
use diesel::dsl::*; use diesel::dsl::*;
@ -477,13 +391,13 @@ impl ViewToVec for PostView {
type DbTuple = PostViewTuple; type DbTuple = PostViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
post: a.0.to_owned(), post: a.0,
creator: a.1.to_owned(), creator: a.1,
community: a.2.to_owned(), community: a.2,
creator_banned_from_community: a.3.is_some(), creator_banned_from_community: a.3.is_some(),
counts: a.4.to_owned(), counts: a.4,
subscribed: CommunityFollower::to_subscribed_type(&a.5), subscribed: CommunityFollower::to_subscribed_type(&a.5),
saved: a.6.is_some(), saved: a.6.is_some(),
read: a.7.is_some(), read: a.7.is_some(),
@ -496,7 +410,7 @@ impl ViewToVec for PostView {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::post_view::{PostQueryBuilder, PostView}; use crate::post_view::{PostQuery, PostView};
use lemmy_db_schema::{ use lemmy_db_schema::{
aggregates::structs::PostAggregates, aggregates::structs::PostAggregates,
source::{ source::{
@ -610,17 +524,21 @@ mod tests {
score: 1, score: 1,
}; };
let read_post_listings_with_person = PostQueryBuilder::create(&conn) let read_post_listings_with_person = PostQuery::builder()
.sort(SortType::New) .conn(&conn)
.show_bot_accounts(false) .sort(Some(SortType::New))
.community_id(inserted_community.id) .show_bot_accounts(Some(false))
.my_person_id(inserted_person.id) .community_id(Some(inserted_community.id))
.my_person_id(Some(inserted_person.id))
.build()
.list() .list()
.unwrap(); .unwrap();
let read_post_listings_no_person = PostQueryBuilder::create(&conn) let read_post_listings_no_person = PostQuery::builder()
.sort(SortType::New) .conn(&conn)
.community_id(inserted_community.id) .sort(Some(SortType::New))
.community_id(Some(inserted_community.id))
.build()
.list() .list()
.unwrap(); .unwrap();
@ -717,11 +635,13 @@ mod tests {
}; };
CommunityBlock::block(&conn, &community_block).unwrap(); CommunityBlock::block(&conn, &community_block).unwrap();
let read_post_listings_with_person_after_block = PostQueryBuilder::create(&conn) let read_post_listings_with_person_after_block = PostQuery::builder()
.sort(SortType::New) .conn(&conn)
.show_bot_accounts(false) .sort(Some(SortType::New))
.community_id(inserted_community.id) .show_bot_accounts(Some(false))
.my_person_id(inserted_person.id) .community_id(Some(inserted_community.id))
.my_person_id(Some(inserted_person.id))
.build()
.list() .list()
.unwrap(); .unwrap();

View file

@ -7,10 +7,11 @@ use lemmy_db_schema::{
person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
private_message::PrivateMessage, private_message::PrivateMessage,
}, },
traits::{MaybeOptional, ToSafe, ViewToVec}, traits::{ToSafe, ViewToVec},
utils::limit_and_offset, utils::limit_and_offset,
}; };
use tracing::debug; use tracing::debug;
use typed_builder::TypedBuilder;
type PrivateMessageViewTuple = (PrivateMessage, PersonSafe, PersonSafeAlias1); type PrivateMessageViewTuple = (PrivateMessage, PersonSafe, PersonSafeAlias1);
@ -47,40 +48,19 @@ impl PrivateMessageView {
} }
} }
pub struct PrivateMessageQueryBuilder<'a> { #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct PrivateMessageQuery<'a> {
#[builder(!default)]
conn: &'a PgConnection, conn: &'a PgConnection,
#[builder(!default)]
recipient_id: PersonId, recipient_id: PersonId,
unread_only: Option<bool>, unread_only: Option<bool>,
page: Option<i64>, page: Option<i64>,
limit: Option<i64>, limit: Option<i64>,
} }
impl<'a> PrivateMessageQueryBuilder<'a> { impl<'a> PrivateMessageQuery<'a> {
pub fn create(conn: &'a PgConnection, recipient_id: PersonId) -> Self {
PrivateMessageQueryBuilder {
conn,
recipient_id,
unread_only: None,
page: None,
limit: None,
}
}
pub fn unread_only<T: MaybeOptional<bool>>(mut self, unread_only: T) -> Self {
self.unread_only = unread_only.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn list(self) -> Result<Vec<PrivateMessageView>, Error> { pub fn list(self) -> Result<Vec<PrivateMessageView>, Error> {
let mut query = private_message::table let mut query = private_message::table
.inner_join(person::table.on(private_message::creator_id.eq(person::id))) .inner_join(person::table.on(private_message::creator_id.eq(person::id)))
@ -130,11 +110,11 @@ impl ViewToVec for PrivateMessageView {
type DbTuple = PrivateMessageViewTuple; type DbTuple = PrivateMessageViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
private_message: a.0.to_owned(), private_message: a.0,
creator: a.1.to_owned(), creator: a.1,
recipient: a.2.to_owned(), recipient: a.2,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -7,9 +7,10 @@ use lemmy_db_schema::{
person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
registration_application::RegistrationApplication, registration_application::RegistrationApplication,
}, },
traits::{MaybeOptional, ToSafe, ToSafeSettings, ViewToVec}, traits::{ToSafe, ToSafeSettings, ViewToVec},
utils::limit_and_offset, utils::limit_and_offset,
}; };
use typed_builder::TypedBuilder;
type RegistrationApplicationViewTuple = ( type RegistrationApplicationViewTuple = (
RegistrationApplication, RegistrationApplication,
@ -70,7 +71,10 @@ impl RegistrationApplicationView {
} }
} }
pub struct RegistrationApplicationQueryBuilder<'a> { #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct RegistrationApplicationQuery<'a> {
#[builder(!default)]
conn: &'a PgConnection, conn: &'a PgConnection,
unread_only: Option<bool>, unread_only: Option<bool>,
verified_email_only: Option<bool>, verified_email_only: Option<bool>,
@ -78,37 +82,7 @@ pub struct RegistrationApplicationQueryBuilder<'a> {
limit: Option<i64>, limit: Option<i64>,
} }
impl<'a> RegistrationApplicationQueryBuilder<'a> { impl<'a> RegistrationApplicationQuery<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
RegistrationApplicationQueryBuilder {
conn,
unread_only: None,
verified_email_only: None,
page: None,
limit: None,
}
}
pub fn unread_only<T: MaybeOptional<bool>>(mut self, unread_only: T) -> Self {
self.unread_only = unread_only.get_optional();
self
}
pub fn verified_email_only<T: MaybeOptional<bool>>(mut self, verified_email_only: T) -> Self {
self.verified_email_only = verified_email_only.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn list(self) -> Result<Vec<RegistrationApplicationView>, Error> { pub fn list(self) -> Result<Vec<RegistrationApplicationView>, Error> {
let mut query = registration_application::table let mut query = registration_application::table
.inner_join(local_user::table.on(registration_application::local_user_id.eq(local_user::id))) .inner_join(local_user::table.on(registration_application::local_user_id.eq(local_user::id)))
@ -151,12 +125,12 @@ impl ViewToVec for RegistrationApplicationView {
type DbTuple = RegistrationApplicationViewTuple; type DbTuple = RegistrationApplicationViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
registration_application: a.0.to_owned(), registration_application: a.0,
creator_local_user: a.1.to_owned(), creator_local_user: a.1,
creator: a.2.to_owned(), creator: a.2,
admin: a.3.to_owned(), admin: a.3,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }
@ -165,7 +139,7 @@ impl ViewToVec for RegistrationApplicationView {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::registration_application_view::{ use crate::registration_application_view::{
RegistrationApplicationQueryBuilder, RegistrationApplicationQuery,
RegistrationApplicationView, RegistrationApplicationView,
}; };
use lemmy_db_schema::{ use lemmy_db_schema::{
@ -302,8 +276,10 @@ mod tests {
assert_eq!(read_sara_app_view, expected_sara_app_view); assert_eq!(read_sara_app_view, expected_sara_app_view);
// Do a batch read of the applications // Do a batch read of the applications
let apps = RegistrationApplicationQueryBuilder::create(&conn) let apps = RegistrationApplicationQuery::builder()
.unread_only(true) .conn(&conn)
.unread_only(Some(true))
.build()
.list() .list()
.unwrap(); .unwrap();
@ -369,8 +345,10 @@ mod tests {
// Do a batch read of apps again // Do a batch read of apps again
// It should show only jessicas which is unresolved // It should show only jessicas which is unresolved
let apps_after_resolve = RegistrationApplicationQueryBuilder::create(&conn) let apps_after_resolve = RegistrationApplicationQuery::builder()
.unread_only(true) .conn(&conn)
.unread_only(Some(true))
.build()
.list() .list()
.unwrap(); .unwrap();
assert_eq!(apps_after_resolve, vec![read_jess_app_view]); assert_eq!(apps_after_resolve, vec![read_jess_app_view]);
@ -381,7 +359,9 @@ mod tests {
assert_eq!(unread_count_after_approve, 1); assert_eq!(unread_count_after_approve, 1);
// Make sure the not undenied_only has all the apps // Make sure the not undenied_only has all the apps
let all_apps = RegistrationApplicationQueryBuilder::create(&conn) let all_apps = RegistrationApplicationQuery::builder()
.conn(&conn)
.build()
.list() .list()
.unwrap(); .unwrap();
assert_eq!(all_apps.len(), 2); assert_eq!(all_apps.len(), 2);

View file

@ -18,3 +18,4 @@ full = ["lemmy_db_schema/full", "diesel"]
lemmy_db_schema = { version = "=0.16.5", path = "../db_schema" } lemmy_db_schema = { version = "=0.16.5", path = "../db_schema" }
diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"], optional = true } diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"], optional = true }
serde = { version = "1.0.136", features = ["derive"] } serde = { version = "1.0.136", features = ["derive"] }
typed-builder = "0.10.0"

View file

@ -25,10 +25,11 @@ use lemmy_db_schema::{
person_block::PersonBlock, person_block::PersonBlock,
post::Post, post::Post,
}, },
traits::{MaybeOptional, ToSafe, ViewToVec}, traits::{ToSafe, ViewToVec},
utils::{functions::hot_rank, limit_and_offset}, utils::{functions::hot_rank, limit_and_offset},
CommentSortType, CommentSortType,
}; };
use typed_builder::TypedBuilder;
type CommentReplyViewTuple = ( type CommentReplyViewTuple = (
CommentReply, CommentReply,
@ -159,7 +160,10 @@ impl CommentReplyView {
} }
} }
pub struct CommentReplyQueryBuilder<'a> { #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct CommentReplyQuery<'a> {
#[builder(!default)]
conn: &'a PgConnection, conn: &'a PgConnection,
my_person_id: Option<PersonId>, my_person_id: Option<PersonId>,
recipient_id: Option<PersonId>, recipient_id: Option<PersonId>,
@ -170,55 +174,7 @@ pub struct CommentReplyQueryBuilder<'a> {
limit: Option<i64>, limit: Option<i64>,
} }
impl<'a> CommentReplyQueryBuilder<'a> { impl<'a> CommentReplyQuery<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
CommentReplyQueryBuilder {
conn,
my_person_id: None,
recipient_id: None,
sort: None,
unread_only: None,
show_bot_accounts: None,
page: None,
limit: None,
}
}
pub fn sort<T: MaybeOptional<CommentSortType>>(mut self, sort: T) -> Self {
self.sort = sort.get_optional();
self
}
pub fn unread_only<T: MaybeOptional<bool>>(mut self, unread_only: T) -> Self {
self.unread_only = unread_only.get_optional();
self
}
pub fn show_bot_accounts<T: MaybeOptional<bool>>(mut self, show_bot_accounts: T) -> Self {
self.show_bot_accounts = show_bot_accounts.get_optional();
self
}
pub fn recipient_id<T: MaybeOptional<PersonId>>(mut self, recipient_id: T) -> Self {
self.recipient_id = recipient_id.get_optional();
self
}
pub fn my_person_id<T: MaybeOptional<PersonId>>(mut self, my_person_id: T) -> Self {
self.my_person_id = my_person_id.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn list(self) -> Result<Vec<CommentReplyView>, Error> { pub fn list(self) -> Result<Vec<CommentReplyView>, Error> {
use diesel::dsl::*; use diesel::dsl::*;

View file

@ -33,10 +33,10 @@ impl ViewToVec for CommunityBlockView {
type DbTuple = CommunityBlockViewTuple; type DbTuple = CommunityBlockViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
person: a.0.to_owned(), person: a.0,
community: a.1.to_owned(), community: a.1,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -48,10 +48,10 @@ impl ViewToVec for CommunityFollowerView {
type DbTuple = CommunityFollowerViewTuple; type DbTuple = CommunityFollowerViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
community: a.0.to_owned(), community: a.0,
follower: a.1.to_owned(), follower: a.1,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -70,10 +70,10 @@ impl ViewToVec for CommunityModeratorView {
type DbTuple = CommunityModeratorViewTuple; type DbTuple = CommunityModeratorViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
community: a.0.to_owned(), community: a.0,
moderator: a.1.to_owned(), moderator: a.1,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -8,11 +8,12 @@ use lemmy_db_schema::{
community::{Community, CommunityFollower, CommunitySafe}, community::{Community, CommunityFollower, CommunitySafe},
community_block::CommunityBlock, community_block::CommunityBlock,
}, },
traits::{MaybeOptional, ToSafe, ViewToVec}, traits::{ToSafe, ViewToVec},
utils::{functions::hot_rank, fuzzy_search, limit_and_offset}, utils::{functions::hot_rank, fuzzy_search, limit_and_offset},
ListingType, ListingType,
SortType, SortType,
}; };
use typed_builder::TypedBuilder;
type CommunityViewTuple = ( type CommunityViewTuple = (
CommunitySafe, CommunitySafe,
@ -91,7 +92,10 @@ impl CommunityView {
} }
} }
pub struct CommunityQueryBuilder<'a> { #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct CommunityQuery<'a> {
#[builder(!default)]
conn: &'a PgConnection, conn: &'a PgConnection,
listing_type: Option<ListingType>, listing_type: Option<ListingType>,
sort: Option<SortType>, sort: Option<SortType>,
@ -102,55 +106,7 @@ pub struct CommunityQueryBuilder<'a> {
limit: Option<i64>, limit: Option<i64>,
} }
impl<'a> CommunityQueryBuilder<'a> { impl<'a> CommunityQuery<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
CommunityQueryBuilder {
conn,
my_person_id: None,
listing_type: Some(ListingType::All),
sort: None,
show_nsfw: None,
search_term: None,
page: None,
limit: None,
}
}
pub fn listing_type<T: MaybeOptional<ListingType>>(mut self, listing_type: T) -> Self {
self.listing_type = listing_type.get_optional();
self
}
pub fn sort<T: MaybeOptional<SortType>>(mut self, sort: T) -> Self {
self.sort = sort.get_optional();
self
}
pub fn show_nsfw<T: MaybeOptional<bool>>(mut self, show_nsfw: T) -> Self {
self.show_nsfw = show_nsfw.get_optional();
self
}
pub fn search_term<T: MaybeOptional<String>>(mut self, search_term: T) -> Self {
self.search_term = search_term.get_optional();
self
}
pub fn my_person_id<T: MaybeOptional<PersonId>>(mut self, my_person_id: T) -> Self {
self.my_person_id = my_person_id.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn list(self) -> Result<Vec<CommunityView>, Error> { pub fn list(self) -> Result<Vec<CommunityView>, Error> {
// The left join below will return None in this case // The left join below will return None in this case
let person_id_join = self.my_person_id.unwrap_or(PersonId(-1)); let person_id_join = self.my_person_id.unwrap_or(PersonId(-1));
@ -258,10 +214,10 @@ impl ViewToVec for CommunityView {
type DbTuple = CommunityViewTuple; type DbTuple = CommunityViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
community: a.0.to_owned(), community: a.0,
counts: a.1.to_owned(), counts: a.1,
subscribed: CommunityFollower::to_subscribed_type(&a.2), subscribed: CommunityFollower::to_subscribed_type(&a.2),
blocked: a.3.is_some(), blocked: a.3.is_some(),
}) })

View file

@ -30,10 +30,10 @@ impl ViewToVec for PersonBlockView {
type DbTuple = PersonBlockViewTuple; type DbTuple = PersonBlockViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
person: a.0.to_owned(), person: a.0,
target: a.1.to_owned(), target: a.1,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -25,10 +25,11 @@ use lemmy_db_schema::{
person_mention::PersonMention, person_mention::PersonMention,
post::Post, post::Post,
}, },
traits::{MaybeOptional, ToSafe, ViewToVec}, traits::{ToSafe, ViewToVec},
utils::{functions::hot_rank, limit_and_offset}, utils::{functions::hot_rank, limit_and_offset},
CommentSortType, CommentSortType,
}; };
use typed_builder::TypedBuilder;
type PersonMentionViewTuple = ( type PersonMentionViewTuple = (
PersonMention, PersonMention,
@ -159,7 +160,10 @@ impl PersonMentionView {
} }
} }
pub struct PersonMentionQueryBuilder<'a> { #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct PersonMentionQuery<'a> {
#[builder(!default)]
conn: &'a PgConnection, conn: &'a PgConnection,
my_person_id: Option<PersonId>, my_person_id: Option<PersonId>,
recipient_id: Option<PersonId>, recipient_id: Option<PersonId>,
@ -170,55 +174,7 @@ pub struct PersonMentionQueryBuilder<'a> {
limit: Option<i64>, limit: Option<i64>,
} }
impl<'a> PersonMentionQueryBuilder<'a> { impl<'a> PersonMentionQuery<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
PersonMentionQueryBuilder {
conn,
my_person_id: None,
recipient_id: None,
sort: None,
unread_only: None,
show_bot_accounts: None,
page: None,
limit: None,
}
}
pub fn sort<T: MaybeOptional<CommentSortType>>(mut self, sort: T) -> Self {
self.sort = sort.get_optional();
self
}
pub fn unread_only<T: MaybeOptional<bool>>(mut self, unread_only: T) -> Self {
self.unread_only = unread_only.get_optional();
self
}
pub fn show_bot_accounts<T: MaybeOptional<bool>>(mut self, show_bot_accounts: T) -> Self {
self.show_bot_accounts = show_bot_accounts.get_optional();
self
}
pub fn recipient_id<T: MaybeOptional<PersonId>>(mut self, recipient_id: T) -> Self {
self.recipient_id = recipient_id.get_optional();
self
}
pub fn my_person_id<T: MaybeOptional<PersonId>>(mut self, my_person_id: T) -> Self {
self.my_person_id = my_person_id.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn list(self) -> Result<Vec<PersonMentionView>, Error> { pub fn list(self) -> Result<Vec<PersonMentionView>, Error> {
use diesel::dsl::*; use diesel::dsl::*;
@ -324,15 +280,15 @@ impl ViewToVec for PersonMentionView {
type DbTuple = PersonMentionViewTuple; type DbTuple = PersonMentionViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
person_mention: a.0.to_owned(), person_mention: a.0,
comment: a.1.to_owned(), comment: a.1,
creator: a.2.to_owned(), creator: a.2,
post: a.3.to_owned(), post: a.3,
community: a.4.to_owned(), community: a.4,
recipient: a.5.to_owned(), recipient: a.5,
counts: a.6.to_owned(), counts: a.6,
creator_banned_from_community: a.7.is_some(), creator_banned_from_community: a.7.is_some(),
subscribed: CommunityFollower::to_subscribed_type(&a.8), subscribed: CommunityFollower::to_subscribed_type(&a.8),
saved: a.9.is_some(), saved: a.9.is_some(),

View file

@ -5,10 +5,11 @@ use lemmy_db_schema::{
newtypes::PersonId, newtypes::PersonId,
schema::{person, person_aggregates}, schema::{person, person_aggregates},
source::person::{Person, PersonSafe}, source::person::{Person, PersonSafe},
traits::{MaybeOptional, ToSafe, ViewToVec}, traits::{ToSafe, ViewToVec},
utils::{fuzzy_search, limit_and_offset}, utils::{fuzzy_search, limit_and_offset},
SortType, SortType,
}; };
use typed_builder::TypedBuilder;
type PersonViewSafeTuple = (PersonSafe, PersonAggregates); type PersonViewSafeTuple = (PersonSafe, PersonAggregates);
@ -50,7 +51,10 @@ impl PersonViewSafe {
} }
} }
pub struct PersonQueryBuilder<'a> { #[derive(TypedBuilder)]
#[builder(field_defaults(default))]
pub struct PersonQuery<'a> {
#[builder(!default)]
conn: &'a PgConnection, conn: &'a PgConnection,
sort: Option<SortType>, sort: Option<SortType>,
search_term: Option<String>, search_term: Option<String>,
@ -58,37 +62,7 @@ pub struct PersonQueryBuilder<'a> {
limit: Option<i64>, limit: Option<i64>,
} }
impl<'a> PersonQueryBuilder<'a> { impl<'a> PersonQuery<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
PersonQueryBuilder {
conn,
search_term: None,
sort: None,
page: None,
limit: None,
}
}
pub fn sort<T: MaybeOptional<SortType>>(mut self, sort: T) -> Self {
self.sort = sort.get_optional();
self
}
pub fn search_term<T: MaybeOptional<String>>(mut self, search_term: T) -> Self {
self.search_term = search_term.get_optional();
self
}
pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
self.page = page.get_optional();
self
}
pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
self.limit = limit.get_optional();
self
}
pub fn list(self) -> Result<Vec<PersonViewSafe>, Error> { pub fn list(self) -> Result<Vec<PersonViewSafe>, Error> {
let mut query = person::table let mut query = person::table
.inner_join(person_aggregates::table) .inner_join(person_aggregates::table)
@ -138,10 +112,10 @@ impl ViewToVec for PersonViewSafe {
type DbTuple = PersonViewSafeTuple; type DbTuple = PersonViewSafeTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
person: a.0.to_owned(), person: a.0,
counts: a.1.to_owned(), counts: a.1,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -51,11 +51,11 @@ impl ViewToVec for AdminPurgeCommentView {
type DbTuple = AdminPurgeCommentViewTuple; type DbTuple = AdminPurgeCommentViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
admin_purge_comment: a.0.to_owned(), admin_purge_comment: a.0,
admin: a.1.to_owned(), admin: a.1,
post: a.2.to_owned(), post: a.2,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -48,10 +48,10 @@ impl ViewToVec for AdminPurgeCommunityView {
type DbTuple = AdminPurgeCommunityViewTuple; type DbTuple = AdminPurgeCommunityViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
admin_purge_community: a.0.to_owned(), admin_purge_community: a.0,
admin: a.1.to_owned(), admin: a.1,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -48,10 +48,10 @@ impl ViewToVec for AdminPurgePersonView {
type DbTuple = AdminPurgePersonViewTuple; type DbTuple = AdminPurgePersonViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
admin_purge_person: a.0.to_owned(), admin_purge_person: a.0,
admin: a.1.to_owned(), admin: a.1,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -51,11 +51,11 @@ impl ViewToVec for AdminPurgePostView {
type DbTuple = AdminPurgePostViewTuple; type DbTuple = AdminPurgePostViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
admin_purge_post: a.0.to_owned(), admin_purge_post: a.0,
admin: a.1.to_owned(), admin: a.1,
community: a.2.to_owned(), community: a.2,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -60,12 +60,12 @@ impl ViewToVec for ModAddCommunityView {
type DbTuple = ModAddCommunityViewTuple; type DbTuple = ModAddCommunityViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_add_community: a.0.to_owned(), mod_add_community: a.0,
moderator: a.1.to_owned(), moderator: a.1,
community: a.2.to_owned(), community: a.2,
modded_person: a.3.to_owned(), modded_person: a.3,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -50,11 +50,11 @@ impl ViewToVec for ModAddView {
type DbTuple = ModAddViewTuple; type DbTuple = ModAddViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_add: a.0.to_owned(), mod_add: a.0,
moderator: a.1.to_owned(), moderator: a.1,
modded_person: a.2.to_owned(), modded_person: a.2,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -65,12 +65,12 @@ impl ViewToVec for ModBanFromCommunityView {
type DbTuple = ModBanFromCommunityViewTuple; type DbTuple = ModBanFromCommunityViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_ban_from_community: a.0.to_owned(), mod_ban_from_community: a.0,
moderator: a.1.to_owned(), moderator: a.1,
community: a.2.to_owned(), community: a.2,
banned_person: a.3.to_owned(), banned_person: a.3,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -50,11 +50,11 @@ impl ViewToVec for ModBanView {
type DbTuple = ModBanViewTuple; type DbTuple = ModBanViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_ban: a.0.to_owned(), mod_ban: a.0,
moderator: a.1.to_owned(), moderator: a.1,
banned_person: a.2.to_owned(), banned_person: a.2,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -57,11 +57,11 @@ impl ViewToVec for ModHideCommunityView {
type DbTuple = ModHideCommunityViewTuple; type DbTuple = ModHideCommunityViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_hide_community: a.0.to_owned(), mod_hide_community: a.0,
admin: a.1.to_owned(), admin: a.1,
community: a.2.to_owned(), community: a.2,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -59,12 +59,12 @@ impl ViewToVec for ModLockPostView {
type DbTuple = ModLockPostViewTuple; type DbTuple = ModLockPostViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_lock_post: a.0.to_owned(), mod_lock_post: a.0,
moderator: a.1.to_owned(), moderator: a.1,
post: a.2.to_owned(), post: a.2,
community: a.3.to_owned(), community: a.3,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -71,14 +71,14 @@ impl ViewToVec for ModRemoveCommentView {
type DbTuple = ModRemoveCommentViewTuple; type DbTuple = ModRemoveCommentViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_remove_comment: a.0.to_owned(), mod_remove_comment: a.0,
moderator: a.1.to_owned(), moderator: a.1,
comment: a.2.to_owned(), comment: a.2,
commenter: a.3.to_owned(), commenter: a.3,
post: a.4.to_owned(), post: a.4,
community: a.5.to_owned(), community: a.5,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -51,11 +51,11 @@ impl ViewToVec for ModRemoveCommunityView {
type DbTuple = ModRemoveCommunityTuple; type DbTuple = ModRemoveCommunityTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_remove_community: a.0.to_owned(), mod_remove_community: a.0,
moderator: a.1.to_owned(), moderator: a.1,
community: a.2.to_owned(), community: a.2,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -59,12 +59,12 @@ impl ViewToVec for ModRemovePostView {
type DbTuple = ModRemovePostViewTuple; type DbTuple = ModRemovePostViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_remove_post: a.0.to_owned(), mod_remove_post: a.0,
moderator: a.1.to_owned(), moderator: a.1,
post: a.2.to_owned(), post: a.2,
community: a.3.to_owned(), community: a.3,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -59,12 +59,12 @@ impl ViewToVec for ModStickyPostView {
type DbTuple = ModStickyPostViewTuple; type DbTuple = ModStickyPostViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_sticky_post: a.0.to_owned(), mod_sticky_post: a.0,
moderator: a.1.to_owned(), moderator: a.1,
post: a.2.to_owned(), post: a.2,
community: a.3.to_owned(), community: a.3,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -65,12 +65,12 @@ impl ViewToVec for ModTransferCommunityView {
type DbTuple = ModTransferCommunityViewTuple; type DbTuple = ModTransferCommunityViewTuple;
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> { fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
items items
.iter() .into_iter()
.map(|a| Self { .map(|a| Self {
mod_transfer_community: a.0.to_owned(), mod_transfer_community: a.0,
moderator: a.1.to_owned(), moderator: a.1,
community: a.2.to_owned(), community: a.2,
modded_person: a.3.to_owned(), modded_person: a.3,
}) })
.collect::<Vec<Self>>() .collect::<Vec<Self>>()
} }

View file

@ -12,12 +12,12 @@ use lemmy_db_schema::{
SortType, SortType,
}; };
use lemmy_db_views::{ use lemmy_db_views::{
post_view::PostQueryBuilder, post_view::PostQuery,
structs::{PostView, SiteView}, structs::{PostView, SiteView},
}; };
use lemmy_db_views_actor::{ use lemmy_db_views_actor::{
comment_reply_view::CommentReplyQueryBuilder, comment_reply_view::CommentReplyQuery,
person_mention_view::PersonMentionQueryBuilder, person_mention_view::PersonMentionQuery,
structs::{CommentReplyView, PersonMentionView}, structs::{CommentReplyView, PersonMentionView},
}; };
use lemmy_utils::{claims::Claims, error::LemmyError, utils::markdown_to_html}; use lemmy_utils::{claims::Claims, error::LemmyError, utils::markdown_to_html};
@ -91,10 +91,12 @@ async fn get_feed_data(
let site_view = blocking(context.pool(), SiteView::read_local).await??; let site_view = blocking(context.pool(), SiteView::read_local).await??;
let posts = blocking(context.pool(), move |conn| { let posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn) PostQuery::builder()
.listing_type(listing_type) .conn(conn)
.sort(sort_type) .listing_type(Some(listing_type))
.limit(RSS_FETCH_LIMIT) .sort(Some(sort_type))
.limit(Some(RSS_FETCH_LIMIT))
.build()
.list() .list()
}) })
.await??; .await??;
@ -184,11 +186,13 @@ fn get_feed_user(
let site_view = SiteView::read_local(conn)?; let site_view = SiteView::read_local(conn)?;
let person = Person::read_from_name(conn, user_name, false)?; let person = Person::read_from_name(conn, user_name, false)?;
let posts = PostQueryBuilder::create(conn) let posts = PostQuery::builder()
.listing_type(ListingType::All) .conn(conn)
.sort(*sort_type) .listing_type(Some(ListingType::All))
.creator_id(person.id) .sort(Some(*sort_type))
.limit(RSS_FETCH_LIMIT) .creator_id(Some(person.id))
.limit(Some(RSS_FETCH_LIMIT))
.build()
.list()?; .list()?;
let items = create_post_items(posts, protocol_and_hostname)?; let items = create_post_items(posts, protocol_and_hostname)?;
@ -213,10 +217,12 @@ fn get_feed_community(
let site_view = SiteView::read_local(conn)?; let site_view = SiteView::read_local(conn)?;
let community = Community::read_from_name(conn, community_name, false)?; let community = Community::read_from_name(conn, community_name, false)?;
let posts = PostQueryBuilder::create(conn) let posts = PostQuery::builder()
.sort(*sort_type) .conn(conn)
.community_id(community.id) .sort(Some(*sort_type))
.limit(RSS_FETCH_LIMIT) .community_id(Some(community.id))
.limit(Some(RSS_FETCH_LIMIT))
.build()
.list()?; .list()?;
let items = create_post_items(posts, protocol_and_hostname)?; let items = create_post_items(posts, protocol_and_hostname)?;
@ -247,13 +253,15 @@ fn get_feed_front(
let local_user_id = LocalUserId(Claims::decode(jwt, jwt_secret)?.claims.sub); let local_user_id = LocalUserId(Claims::decode(jwt, jwt_secret)?.claims.sub);
let local_user = LocalUser::read(conn, local_user_id)?; let local_user = LocalUser::read(conn, local_user_id)?;
let posts = PostQueryBuilder::create(conn) let posts = PostQuery::builder()
.listing_type(ListingType::Subscribed) .conn(conn)
.my_person_id(local_user.person_id) .listing_type(Some(ListingType::Subscribed))
.show_bot_accounts(local_user.show_bot_accounts) .my_person_id(Some(local_user.person_id))
.show_read_posts(local_user.show_read_posts) .show_bot_accounts(Some(local_user.show_bot_accounts))
.sort(*sort_type) .show_read_posts(Some(local_user.show_read_posts))
.limit(RSS_FETCH_LIMIT) .sort(Some(*sort_type))
.limit(Some(RSS_FETCH_LIMIT))
.build()
.list()?; .list()?;
let items = create_post_items(posts, protocol_and_hostname)?; let items = create_post_items(posts, protocol_and_hostname)?;
@ -287,20 +295,24 @@ fn get_feed_inbox(
let sort = CommentSortType::New; let sort = CommentSortType::New;
let replies = CommentReplyQueryBuilder::create(conn) let replies = CommentReplyQuery::builder()
.recipient_id(person_id) .conn(conn)
.my_person_id(person_id) .recipient_id(Some(person_id))
.show_bot_accounts(show_bot_accounts) .my_person_id(Some(person_id))
.sort(sort) .show_bot_accounts(Some(show_bot_accounts))
.limit(RSS_FETCH_LIMIT) .sort(Some(sort))
.limit(Some(RSS_FETCH_LIMIT))
.build()
.list()?; .list()?;
let mentions = PersonMentionQueryBuilder::create(conn) let mentions = PersonMentionQuery::builder()
.recipient_id(person_id) .conn(conn)
.my_person_id(person_id) .recipient_id(Some(person_id))
.show_bot_accounts(show_bot_accounts) .my_person_id(Some(person_id))
.sort(sort) .show_bot_accounts(Some(show_bot_accounts))
.limit(RSS_FETCH_LIMIT) .sort(Some(sort))
.limit(Some(RSS_FETCH_LIMIT))
.build()
.list()?; .list()?;
let items = create_reply_and_mention_items(replies, mentions, protocol_and_hostname)?; let items = create_reply_and_mention_items(replies, mentions, protocol_and_hostname)?;