mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-03-13 06:52:41 +00:00
Create actions structs (#5482)
* migration * update code * tests * triggers * fix * fmt * clippy * post aggregate migration * changes for post aggregate code * wip: update tests for post aggregate * format * fix partialeq * trigger fix * fix post insert trigger * wip * reorder * fixes * community aggregate migration * update code * triggers * person aggregate migration * person aggregate code * person triggers * test fixes * fix scheduled task * update api tests * site_aggregates to local_site migration * site_aggregates code changes * triggers, tests * more fixes * Rename PersonPostAggregates to PostActions * Merge local_user_vote_display_mode into local_user * fix schema * remove duplicate fields * remove "aggregates" from index names * uncomment indices * if count = 0 * remove commentaggregates * Fix triggers in remove aggregates tables pr (#5451) * prevent all db_schema test errors * fix the delete_comments_before_post problem in a way that doesn't affect the returned number of affected rows * remove unnecessary recursion checks and add comment to remaining check * clean up * Fixing SQL format. * Update triggers.sql * Update triggers.sql * Update triggers.sql * Update triggers.sql * remove update of deleted column --------- Co-authored-by: Dessalines <tyhou13@gmx.com> * rename migration * Fix migration errors * Move community.hidden to visibility (fixes #5458) * Fixing person_saved_combined. (#5481) * Remove comment and post specific action structs. #5473 * Doing reports * fix up migration by dropping index * also add enum variant `LocalOnlyPublic`, rename `LocalOnly` to `LocalOnlyPrivate` fixes #5351 * fix column order in down.sql * wip * Moving blocks. * Adding a few more views. * more wip * fixes * migration for modlog * fix migration * Working views and schema. * Fix ts_optionals. * wip * db_schema compiling * make the code compile * Merging from main. * lint * Fixing SQL format. * fix down migration * Fixing api tests. * Adding field comments for the actions tables. * Refactoring CommunityFollower to include follow_state * fix test * make hidden status federate * ts attr * fix * fix api test * Update crates/api/src/reports/post_report/resolve.rs Co-authored-by: Nutomic <me@nutomic.com> * Addressing PR comments * Fix ts export. * update api client * review * Extracting filter_not_hidden_or_is_subscribed (#5497) * Extracting filter_not_hidden_or_is_subscribed * Cleanup. * Cleanup 2. * Remove follower_state_helper function. * Cleaning up some utils functions. * rename hidden to unlisted --------- Co-authored-by: Felix Ableitner <me@nutomic.com> Co-authored-by: dullbananas <dull.bananas0@gmail.com>
This commit is contained in:
parent
8ffeeca52d
commit
5fa6a490d5
109 changed files with 2420 additions and 3344 deletions
|
@ -95,6 +95,16 @@ steps:
|
|||
when:
|
||||
- event: pull_request
|
||||
|
||||
no_empty_files:
|
||||
image: alpine:3
|
||||
commands:
|
||||
# Makes sure there are no files smaller than 2 bytes
|
||||
# Don't use completely empty, as some editors use newlines
|
||||
- EMPTY_FILES=$(find crates migrations api_tests/src config -type f -size -2c)
|
||||
- if [[ "$EMPTY_FILES" ]]; then echo "Empty files present:\n$EMPTY_FILES\n"; exit 1; fi
|
||||
when:
|
||||
- event: pull_request
|
||||
|
||||
cargo_clippy:
|
||||
image: *rust_image
|
||||
environment:
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
"eslint": "^9.20.0",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"jest": "^29.5.0",
|
||||
"lemmy-js-client": "0.20.0-move-community-hidden.3",
|
||||
"lemmy-js-client": "1.0.0-action-structs.1",
|
||||
"prettier": "^3.5.0",
|
||||
"ts-jest": "^29.1.0",
|
||||
"tsoa": "^6.6.0",
|
||||
|
|
|
@ -33,8 +33,8 @@ importers:
|
|||
specifier: ^29.5.0
|
||||
version: 29.7.0(@types/node@22.13.1)
|
||||
lemmy-js-client:
|
||||
specifier: 0.20.0-move-community-hidden.3
|
||||
version: 0.20.0-move-community-hidden.3
|
||||
specifier: 1.0.0-action-structs.1
|
||||
version: 1.0.0-action-structs.1
|
||||
prettier:
|
||||
specifier: ^3.5.0
|
||||
version: 3.5.0
|
||||
|
@ -1528,8 +1528,8 @@ packages:
|
|||
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
lemmy-js-client@0.20.0-move-community-hidden.3:
|
||||
resolution: {integrity: sha512-X7bbSrnGGgupr//Qk2M1Z9nvFawNU4T116X+4/j912GO6KbQdWN7+10obbQJuoEYr15oCXwSaK8DLusofLxIig==}
|
||||
lemmy-js-client@1.0.0-action-structs.1:
|
||||
resolution: {integrity: sha512-Th/7TAjBQ7jcxJHpSMeHF50Y8GwK2YbCBVbLZ9AEPYmOyll0yK+bwTwhCEyvy/SIgbNQTd1OaIYv3F8iAvjvuw==}
|
||||
|
||||
leven@3.1.0:
|
||||
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
|
||||
|
@ -4169,7 +4169,7 @@ snapshots:
|
|||
|
||||
kleur@3.0.3: {}
|
||||
|
||||
lemmy-js-client@0.20.0-move-community-hidden.3: {}
|
||||
lemmy-js-client@1.0.0-action-structs.1: {}
|
||||
|
||||
leven@3.1.0: {}
|
||||
|
||||
|
|
|
@ -653,11 +653,11 @@ test("Check that activity from another instance is sent to third instance", asyn
|
|||
expect(gammaFollow.community_view.community.name).toBe("main");
|
||||
await waitUntil(
|
||||
() => resolveBetaCommunity(alpha),
|
||||
c => c.community?.subscribed === "Subscribed",
|
||||
c => c.community?.community_actions?.follow_state === "Accepted",
|
||||
);
|
||||
await waitUntil(
|
||||
() => resolveBetaCommunity(gamma),
|
||||
c => c.community?.subscribed === "Subscribed",
|
||||
c => c.community?.community_actions?.follow_state === "Accepted",
|
||||
);
|
||||
|
||||
// Create a post on beta
|
||||
|
|
|
@ -205,17 +205,17 @@ test("Admin actions in remote community are not federated to origin", async () =
|
|||
gammaCommunity = (
|
||||
await waitUntil(
|
||||
() => resolveCommunity(gamma, communityRes.community.ap_id),
|
||||
g => g.community?.subscribed === "Subscribed",
|
||||
g => g.community?.community_actions?.follow_state == "Accepted",
|
||||
)
|
||||
).community;
|
||||
if (!gammaCommunity) {
|
||||
throw "Missing gamma community";
|
||||
}
|
||||
expect(gammaCommunity.subscribed).toBe("Subscribed");
|
||||
expect(gammaCommunity.community_actions?.follow_state).toBe("Accepted");
|
||||
let gammaPost = (await createPost(gamma, gammaCommunity.community.id))
|
||||
.post_view;
|
||||
expect(gammaPost.post.id).toBeDefined();
|
||||
expect(gammaPost.creator_banned_from_community).toBe(false);
|
||||
expect(gammaPost.creator_community_actions?.received_ban).toBeUndefined();
|
||||
|
||||
// admin of beta decides to ban gamma from community
|
||||
let betaCommunity = (
|
||||
|
@ -244,11 +244,13 @@ test("Admin actions in remote community are not federated to origin", async () =
|
|||
|
||||
// ban doesn't federate to community's origin instance alpha
|
||||
let alphaPost = (await resolvePost(alpha, gammaPost.post)).post;
|
||||
expect(alphaPost?.creator_banned_from_community).toBe(false);
|
||||
expect(alphaPost?.creator_community_actions?.received_ban).toBeUndefined();
|
||||
|
||||
// and neither to gamma
|
||||
let gammaPost2 = await getPost(gamma, gammaPost.post.id);
|
||||
expect(gammaPost2.post_view.creator_banned_from_community).toBe(false);
|
||||
expect(
|
||||
gammaPost2.post_view.creator_community_actions?.received_ban,
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
test("moderator view", async () => {
|
||||
|
@ -391,7 +393,7 @@ test.skip("Community follower count is federated", async () => {
|
|||
let followed = (
|
||||
await waitUntil(
|
||||
() => resolveCommunity(alpha, communityActorId),
|
||||
c => c.community?.subscribed === "Subscribed",
|
||||
c => c.community?.community_actions?.follow_state == "Accepted",
|
||||
)
|
||||
).community;
|
||||
|
||||
|
@ -408,7 +410,7 @@ test.skip("Community follower count is federated", async () => {
|
|||
followed = (
|
||||
await waitUntil(
|
||||
() => resolveCommunity(gamma, communityActorId),
|
||||
c => c.community?.subscribed === "Subscribed",
|
||||
c => c.community?.community_actions?.follow_state == "Accepted",
|
||||
)
|
||||
).community;
|
||||
|
||||
|
@ -425,7 +427,7 @@ test.skip("Community follower count is federated", async () => {
|
|||
followed = (
|
||||
await waitUntil(
|
||||
() => resolveCommunity(delta, communityActorId),
|
||||
c => c.community?.subscribed === "Subscribed",
|
||||
c => c.community?.community_actions?.follow_state == "Accepted",
|
||||
)
|
||||
).community;
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@ test("Follow local community", async () => {
|
|||
|
||||
// Make sure the follow response went through
|
||||
expect(follow.community_view.community.local).toBe(true);
|
||||
expect(follow.community_view.subscribed).toBe("Subscribed");
|
||||
expect(follow.community_view.community_actions?.follow_state).toBe(
|
||||
"Accepted",
|
||||
);
|
||||
expect(follow.community_view.community.subscribers).toBe(
|
||||
community.community.subscribers + 1,
|
||||
);
|
||||
|
@ -36,7 +38,9 @@ test("Follow local community", async () => {
|
|||
|
||||
// Test an unfollow
|
||||
let unfollow = await followCommunity(user, false, community.community.id);
|
||||
expect(unfollow.community_view.subscribed).toBe("NotSubscribed");
|
||||
expect(
|
||||
unfollow.community_view.community_actions?.follow_state,
|
||||
).toBeUndefined();
|
||||
expect(unfollow.community_view.community.subscribers).toBe(
|
||||
community.community.subscribers,
|
||||
);
|
||||
|
@ -62,18 +66,18 @@ test("Follow federated community", async () => {
|
|||
true,
|
||||
betaCommunityInitial.community.id,
|
||||
);
|
||||
expect(follow.community_view.subscribed).toBe("Pending");
|
||||
expect(follow.community_view.community_actions?.follow_state).toBe("Pending");
|
||||
const betaCommunity = (
|
||||
await waitUntil(
|
||||
() => resolveBetaCommunity(alpha),
|
||||
c => c.community?.subscribed === "Subscribed",
|
||||
c => c.community?.community_actions?.follow_state === "Accepted",
|
||||
)
|
||||
).community;
|
||||
|
||||
// Make sure the follow response went through
|
||||
expect(betaCommunity?.community.local).toBe(false);
|
||||
expect(betaCommunity?.community.name).toBe("main");
|
||||
expect(betaCommunity?.subscribed).toBe("Subscribed");
|
||||
expect(betaCommunity?.community_actions?.follow_state).toBe("Accepted");
|
||||
expect(betaCommunity?.community.subscribers_local).toBe(
|
||||
betaCommunityInitial.community.subscribers_local + 1,
|
||||
);
|
||||
|
@ -99,7 +103,9 @@ test("Follow federated community", async () => {
|
|||
|
||||
// Test an unfollow
|
||||
let unfollow = await followCommunity(alpha, false, remoteCommunityId);
|
||||
expect(unfollow.community_view.subscribed).toBe("NotSubscribed");
|
||||
expect(
|
||||
unfollow.community_view.community_actions?.follow_state,
|
||||
).toBeUndefined();
|
||||
|
||||
// Make sure you are unsubbed locally
|
||||
let siteUnfollowCheck = await getMyUser(alpha);
|
||||
|
|
|
@ -281,7 +281,7 @@ test("Lock a post", async () => {
|
|||
await followCommunity(alpha, true, betaCommunity.community.id);
|
||||
await waitUntil(
|
||||
() => resolveBetaCommunity(alpha),
|
||||
c => c.community?.subscribed === "Subscribed",
|
||||
c => c.community?.community_actions?.follow_state == "Accepted",
|
||||
);
|
||||
|
||||
let postRes = await createPost(alpha, betaCommunity.community.id);
|
||||
|
@ -596,8 +596,9 @@ test("Enforce site ban federation for federated user", async () => {
|
|||
expect(betaBanRes.post_view.post.removed).toBe(true);
|
||||
expect(alphaPostAfterRemoveOnBeta.post_view.post.removed).toBe(true);
|
||||
expect(
|
||||
alphaPostAfterRemoveOnBeta.post_view.creator_banned_from_community,
|
||||
).toBe(true);
|
||||
alphaPostAfterRemoveOnBeta.post_view.creator_community_actions
|
||||
?.received_ban,
|
||||
).toBeDefined();
|
||||
|
||||
await unfollowRemotes(alpha);
|
||||
});
|
||||
|
@ -635,8 +636,12 @@ test("Enforce community ban for federated user", async () => {
|
|||
s => s.post_view.post.removed,
|
||||
);
|
||||
expect(removePostRes.post_view.post.removed).toBe(true);
|
||||
expect(removePostRes.post_view.creator_banned_from_community).toBe(true);
|
||||
expect(removePostRes.community_view.banned_from_community).toBe(true);
|
||||
expect(
|
||||
removePostRes.post_view.creator_community_actions?.received_ban,
|
||||
).toBeDefined();
|
||||
expect(
|
||||
removePostRes.community_view.community_actions?.received_ban,
|
||||
).toBeDefined();
|
||||
|
||||
// Alpha tries to make post on beta, but it fails because of ban
|
||||
await expect(
|
||||
|
@ -670,7 +675,7 @@ test("Enforce community ban for federated user", async () => {
|
|||
// Make sure that post makes it to beta community
|
||||
let postRes4 = await waitForPost(beta, postRes3.post_view.post);
|
||||
expect(postRes4.post).toBeDefined();
|
||||
expect(postRes4.creator_banned_from_community).toBe(false);
|
||||
expect(postRes4.creator_community_actions?.received_ban).toBeUndefined();
|
||||
|
||||
await unfollowRemotes(alpha);
|
||||
});
|
||||
|
|
|
@ -60,7 +60,9 @@ test("Follow a private community", async () => {
|
|||
|
||||
// Follow listed as pending
|
||||
const follow1 = await getCommunity(user, betaCommunityId);
|
||||
expect(follow1.community_view.subscribed).toBe("ApprovalRequired");
|
||||
expect(follow1.community_view.community_actions?.follow_state).toBe(
|
||||
"ApprovalRequired",
|
||||
);
|
||||
|
||||
// Wait for follow to federate, shown as pending
|
||||
let pendingFollows1 = await waitUntil(
|
||||
|
@ -76,7 +78,9 @@ test("Follow a private community", async () => {
|
|||
|
||||
// user still sees approval required at this point
|
||||
const betaCommunity2 = await getCommunity(user, betaCommunityId);
|
||||
expect(betaCommunity2.community_view.subscribed).toBe("ApprovalRequired");
|
||||
expect(betaCommunity2.community_view.community_actions?.follow_state).toBe(
|
||||
"ApprovalRequired",
|
||||
);
|
||||
|
||||
// Approve the follow
|
||||
const approve = await approveCommunityPendingFollow(
|
||||
|
@ -89,7 +93,7 @@ test("Follow a private community", async () => {
|
|||
// Follow is confirmed
|
||||
await waitUntil(
|
||||
() => getCommunity(user, betaCommunityId),
|
||||
c => c.community_view.subscribed == "Subscribed",
|
||||
c => c.community_view.community_actions?.follow_state == "Accepted",
|
||||
);
|
||||
const pendingFollows2 = await listCommunityPendingFollows(alpha);
|
||||
expect(pendingFollows2.items.length).toBe(0);
|
||||
|
@ -167,7 +171,7 @@ test("Only followers can view and interact with private community content", asyn
|
|||
const post1 = await createPost(user, betaCommunity.id);
|
||||
expect(post1.post_view).toBeDefined();
|
||||
const like = await likeComment(user, 1, resolvedComment!.comment);
|
||||
expect(like.comment_view.my_vote).toBe(1);
|
||||
expect(like.comment_view.comment_actions?.like_score).toBe(1);
|
||||
});
|
||||
|
||||
test("Reject follower", async () => {
|
||||
|
@ -188,7 +192,9 @@ test("Reject follower", async () => {
|
|||
follow: true,
|
||||
};
|
||||
const follow = await user.followCommunity(follow_form);
|
||||
expect(follow.community_view.subscribed).toBe("ApprovalRequired");
|
||||
expect(follow.community_view.community_actions?.follow_state).toBe(
|
||||
"ApprovalRequired",
|
||||
);
|
||||
|
||||
const pendingFollows1 = await waitUntil(
|
||||
() => listCommunityPendingFollows(alpha),
|
||||
|
@ -204,7 +210,7 @@ test("Reject follower", async () => {
|
|||
|
||||
await waitUntil(
|
||||
() => getCommunity(user, betaCommunity1.id),
|
||||
c => c.community_view.subscribed == "NotSubscribed",
|
||||
c => c.community_view.community_actions?.follow_state === undefined,
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -240,11 +246,11 @@ test("Follow a private community and receive activities", async () => {
|
|||
// Follow is confirmed
|
||||
await waitUntil(
|
||||
() => getCommunity(beta, betaCommunityId),
|
||||
c => c.community_view.subscribed == "Subscribed",
|
||||
c => c.community_view.community_actions?.follow_state == "Accepted",
|
||||
);
|
||||
await waitUntil(
|
||||
() => getCommunity(gamma, gammaCommunityId),
|
||||
c => c.community_view.subscribed == "Subscribed",
|
||||
c => c.community_view.community_actions?.follow_state == "Accepted",
|
||||
);
|
||||
|
||||
// create a post and comment from gamma
|
||||
|
@ -293,7 +299,7 @@ test("Fetch remote content in private community", async () => {
|
|||
// Follow is confirmed
|
||||
await waitUntil(
|
||||
() => getCommunity(beta, betaCommunityId),
|
||||
c => c.community_view.subscribed == "Subscribed",
|
||||
c => c.community_view.community_actions?.follow_state == "Accepted",
|
||||
);
|
||||
|
||||
// beta creates post and comment
|
||||
|
|
|
@ -471,8 +471,10 @@ export async function followCommunity(
|
|||
const res = await api.followCommunity(form);
|
||||
await waitUntil(
|
||||
() => getCommunity(api, res.community_view.community.id),
|
||||
g =>
|
||||
g.community_view.subscribed === (follow ? "Subscribed" : "NotSubscribed"),
|
||||
g => {
|
||||
let followState = g.community_view.community_actions?.follow_state;
|
||||
return follow ? followState === "Accepted" : followState === undefined;
|
||||
},
|
||||
);
|
||||
// wait FOLLOW_ADDITIONS_RECHECK_DELAY (there's no API to wait for this currently)
|
||||
await delay(2000);
|
||||
|
|
|
@ -10,14 +10,14 @@ use lemmy_api_common::{
|
|||
use lemmy_db_schema::{
|
||||
newtypes::{LocalUserId, PostOrCommentId},
|
||||
source::{
|
||||
comment::{CommentLike, CommentLikeForm},
|
||||
comment::{CommentActions, CommentLikeForm},
|
||||
comment_reply::CommentReply,
|
||||
local_site::LocalSite,
|
||||
},
|
||||
traits::Likeable,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommentView, LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use std::ops::Deref;
|
||||
|
||||
pub async fn like_comment(
|
||||
|
@ -64,23 +64,18 @@ pub async fn like_comment(
|
|||
}
|
||||
}
|
||||
|
||||
let like_form = CommentLikeForm {
|
||||
comment_id: data.comment_id,
|
||||
person_id: local_user_view.person.id,
|
||||
score: data.score,
|
||||
};
|
||||
let like_form = CommentLikeForm::new(local_user_view.person.id, data.comment_id, data.score);
|
||||
|
||||
// Remove any likes first
|
||||
let person_id = local_user_view.person.id;
|
||||
|
||||
CommentLike::remove(&mut context.pool(), person_id, comment_id).await?;
|
||||
CommentActions::remove_like(&mut context.pool(), person_id, comment_id).await?;
|
||||
|
||||
// Only add the like if the score isnt 0
|
||||
let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
|
||||
let do_add =
|
||||
like_form.like_score != 0 && (like_form.like_score == 1 || like_form.like_score == -1);
|
||||
if do_add {
|
||||
CommentLike::like(&mut context.pool(), &like_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikeComment)?;
|
||||
CommentActions::like(&mut context.pool(), &like_form).await?;
|
||||
}
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
|
|
|
@ -4,27 +4,23 @@ use lemmy_api_common::{
|
|||
context::LemmyContext,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::comment::{CommentSaved, CommentSavedForm},
|
||||
source::comment::{CommentActions, CommentSavedForm},
|
||||
traits::Saveable,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommentView, LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn save_comment(
|
||||
data: Json<SaveComment>,
|
||||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<CommentResponse>> {
|
||||
let comment_saved_form = CommentSavedForm::new(data.comment_id, local_user_view.person.id);
|
||||
let comment_saved_form = CommentSavedForm::new(local_user_view.person.id, data.comment_id);
|
||||
|
||||
if data.save {
|
||||
CommentSaved::save(&mut context.pool(), &comment_saved_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntSaveComment)?;
|
||||
CommentActions::save(&mut context.pool(), &comment_saved_form).await?;
|
||||
} else {
|
||||
CommentSaved::unsave(&mut context.pool(), &comment_saved_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntSaveComment)?;
|
||||
CommentActions::unsave(&mut context.pool(), &comment_saved_form).await?;
|
||||
}
|
||||
|
||||
let comment_id = data.comment_id;
|
||||
|
|
|
@ -8,14 +8,14 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||
community::{Community, CommunityActions, CommunityModeratorForm},
|
||||
local_user::LocalUser,
|
||||
mod_log::moderator::{ModAddCommunity, ModAddCommunityForm},
|
||||
},
|
||||
traits::{Crud, Joinable},
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityModeratorView, LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn add_mod_to_community(
|
||||
data: Json<AddModToCommunity>,
|
||||
|
@ -56,18 +56,11 @@ pub async fn add_mod_to_community(
|
|||
}
|
||||
|
||||
// Update in local database
|
||||
let community_moderator_form = CommunityModeratorForm {
|
||||
community_id: data.community_id,
|
||||
person_id: data.person_id,
|
||||
};
|
||||
let community_moderator_form = CommunityModeratorForm::new(data.community_id, data.person_id);
|
||||
if data.added {
|
||||
CommunityModerator::join(&mut context.pool(), &community_moderator_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)?;
|
||||
CommunityActions::join(&mut context.pool(), &community_moderator_form).await?;
|
||||
} else {
|
||||
CommunityModerator::leave(&mut context.pool(), &community_moderator_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)?;
|
||||
CommunityActions::leave(&mut context.pool(), &community_moderator_form).await?;
|
||||
}
|
||||
|
||||
// Mod tables
|
||||
|
|
|
@ -12,23 +12,14 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::{
|
||||
Community,
|
||||
CommunityFollower,
|
||||
CommunityFollowerForm,
|
||||
CommunityPersonBan,
|
||||
CommunityPersonBanForm,
|
||||
},
|
||||
community::{Community, CommunityActions, CommunityPersonBanForm},
|
||||
local_user::LocalUser,
|
||||
mod_log::moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
|
||||
},
|
||||
traits::{Bannable, Crud, Followable},
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PersonView};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
utils::validation::is_valid_body_field,
|
||||
};
|
||||
use lemmy_utils::{error::LemmyResult, utils::validation::is_valid_body_field};
|
||||
|
||||
pub async fn ban_from_community(
|
||||
data: Json<BanFromCommunity>,
|
||||
|
@ -61,25 +52,19 @@ pub async fn ban_from_community(
|
|||
}
|
||||
|
||||
let community_user_ban_form = CommunityPersonBanForm {
|
||||
community_id: data.community_id,
|
||||
person_id: data.person_id,
|
||||
expires: Some(expires),
|
||||
ban_expires: Some(expires),
|
||||
..CommunityPersonBanForm::new(data.community_id, data.person_id)
|
||||
};
|
||||
|
||||
if data.ban {
|
||||
CommunityPersonBan::ban(&mut context.pool(), &community_user_ban_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityUserAlreadyBanned)?;
|
||||
CommunityActions::ban(&mut context.pool(), &community_user_ban_form).await?;
|
||||
|
||||
// Also unsubscribe them from the community, if they are subscribed
|
||||
let community_follower_form = CommunityFollowerForm::new(data.community_id, banned_person_id);
|
||||
CommunityFollower::unfollow(&mut context.pool(), &community_follower_form)
|
||||
CommunityActions::unfollow(&mut context.pool(), banned_person_id, data.community_id)
|
||||
.await
|
||||
.ok();
|
||||
} else {
|
||||
CommunityPersonBan::unban(&mut context.pool(), &community_user_ban_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityUserAlreadyBanned)?;
|
||||
CommunityActions::unban(&mut context.pool(), &community_user_ban_form).await?;
|
||||
}
|
||||
|
||||
// Remove/Restore their data if that's desired
|
||||
|
|
|
@ -6,14 +6,11 @@ use lemmy_api_common::{
|
|||
send_activity::{ActivityChannel, SendActivityData},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::{CommunityFollower, CommunityFollowerForm},
|
||||
community_block::{CommunityBlock, CommunityBlockForm},
|
||||
},
|
||||
source::community::{CommunityActions, CommunityBlockForm},
|
||||
traits::{Blockable, Followable},
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityView, LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn user_block_community(
|
||||
data: Json<BlockCommunity>,
|
||||
|
@ -22,25 +19,17 @@ pub async fn user_block_community(
|
|||
) -> LemmyResult<Json<BlockCommunityResponse>> {
|
||||
let community_id = data.community_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
let community_block_form = CommunityBlockForm {
|
||||
person_id,
|
||||
community_id,
|
||||
};
|
||||
let community_block_form = CommunityBlockForm::new(community_id, person_id);
|
||||
|
||||
if data.block {
|
||||
CommunityBlock::block(&mut context.pool(), &community_block_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityBlockAlreadyExists)?;
|
||||
CommunityActions::block(&mut context.pool(), &community_block_form).await?;
|
||||
|
||||
// Also, unfollow the community, and send a federated unfollow
|
||||
let community_follower_form = CommunityFollowerForm::new(data.community_id, person_id);
|
||||
CommunityFollower::unfollow(&mut context.pool(), &community_follower_form)
|
||||
CommunityActions::unfollow(&mut context.pool(), person_id, data.community_id)
|
||||
.await
|
||||
.ok();
|
||||
} else {
|
||||
CommunityBlock::unblock(&mut context.pool(), &community_block_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityBlockAlreadyExists)?;
|
||||
CommunityActions::unblock(&mut context.pool(), &community_block_form).await?;
|
||||
}
|
||||
|
||||
let community_view = CommunityView::read(
|
||||
|
|
|
@ -9,13 +9,13 @@ use lemmy_api_common::{
|
|||
use lemmy_db_schema::{
|
||||
source::{
|
||||
actor_language::CommunityLanguage,
|
||||
community::{Community, CommunityFollower, CommunityFollowerForm, CommunityFollowerState},
|
||||
community::{Community, CommunityActions, CommunityFollowerForm, CommunityFollowerState},
|
||||
},
|
||||
traits::{Crud, Followable},
|
||||
CommunityVisibility,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityPersonBanView, CommunityView, LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn follow_community(
|
||||
data: Json<FollowCommunity>,
|
||||
|
@ -24,7 +24,7 @@ pub async fn follow_community(
|
|||
) -> LemmyResult<Json<CommunityResponse>> {
|
||||
check_user_valid(&local_user_view.person)?;
|
||||
let community = Community::read(&mut context.pool(), data.community_id).await?;
|
||||
let form = CommunityFollowerForm::new(community.id, local_user_view.person.id);
|
||||
let person_id = local_user_view.person.id;
|
||||
|
||||
if data.follow {
|
||||
// Only run these checks for local community, in case of remote community the local
|
||||
|
@ -32,34 +32,26 @@ pub async fn follow_community(
|
|||
// actions from existing followers for private community (so following would be impossible).
|
||||
if community.local {
|
||||
check_community_deleted_removed(&community)?;
|
||||
CommunityPersonBanView::check(&mut context.pool(), local_user_view.person.id, community.id)
|
||||
.await?;
|
||||
CommunityPersonBanView::check(&mut context.pool(), person_id, community.id).await?;
|
||||
}
|
||||
|
||||
let state = if community.local {
|
||||
let follow_state = if community.local {
|
||||
// Local follow is accepted immediately
|
||||
Some(CommunityFollowerState::Accepted)
|
||||
CommunityFollowerState::Accepted
|
||||
} else if community.visibility == CommunityVisibility::Private {
|
||||
// Private communities require manual approval
|
||||
Some(CommunityFollowerState::ApprovalRequired)
|
||||
CommunityFollowerState::ApprovalRequired
|
||||
} else {
|
||||
// remote follow needs to be federated first
|
||||
Some(CommunityFollowerState::Pending)
|
||||
CommunityFollowerState::Pending
|
||||
};
|
||||
|
||||
let form = CommunityFollowerForm {
|
||||
state,
|
||||
..CommunityFollowerForm::new(community.id, local_user_view.person.id)
|
||||
};
|
||||
let form = CommunityFollowerForm::new(community.id, person_id, follow_state);
|
||||
|
||||
// Write to db
|
||||
CommunityFollower::follow(&mut context.pool(), &form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityFollowerAlreadyExists)?;
|
||||
CommunityActions::follow(&mut context.pool(), &form).await?;
|
||||
} else {
|
||||
CommunityFollower::unfollow(&mut context.pool(), &form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityFollowerAlreadyExists)?;
|
||||
CommunityActions::unfollow(&mut context.pool(), person_id, community.id).await?;
|
||||
}
|
||||
|
||||
// Send the federated follow
|
||||
|
|
|
@ -7,10 +7,7 @@ use lemmy_api_common::{
|
|||
utils::is_mod_or_admin,
|
||||
SuccessResponse,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::community::{CommunityFollower, CommunityFollowerForm},
|
||||
traits::Followable,
|
||||
};
|
||||
use lemmy_db_schema::{source::community::CommunityActions, traits::Followable};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
|
@ -27,7 +24,7 @@ pub async fn post_pending_follows_approve(
|
|||
.await?;
|
||||
|
||||
let activity_data = if data.approve {
|
||||
CommunityFollower::approve(
|
||||
CommunityActions::approve_follower(
|
||||
&mut context.pool(),
|
||||
data.community_id,
|
||||
data.follower_id,
|
||||
|
@ -36,8 +33,7 @@ pub async fn post_pending_follows_approve(
|
|||
.await?;
|
||||
SendActivityData::AcceptFollower(data.community_id, data.follower_id)
|
||||
} else {
|
||||
let form = CommunityFollowerForm::new(data.community_id, data.follower_id);
|
||||
CommunityFollower::unfollow(&mut context.pool(), &form).await?;
|
||||
CommunityActions::unfollow(&mut context.pool(), data.follower_id, data.community_id).await?;
|
||||
SendActivityData::RejectFollower(data.community_id, data.follower_id)
|
||||
};
|
||||
ActivityChannel::submit_activity(activity_data, &context)?;
|
||||
|
|
|
@ -7,14 +7,14 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||
community::{Community, CommunityActions, CommunityModeratorForm},
|
||||
mod_log::moderator::{ModTransferCommunity, ModTransferCommunityForm},
|
||||
},
|
||||
traits::{Crud, Joinable},
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityModeratorView, CommunityView, LocalUserView};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
error::{LemmyErrorType, LemmyResult},
|
||||
location_info,
|
||||
};
|
||||
|
||||
|
@ -50,19 +50,15 @@ pub async fn transfer_community(
|
|||
// Delete all the mods
|
||||
let community_id = data.community_id;
|
||||
|
||||
CommunityModerator::delete_for_community(&mut context.pool(), community_id).await?;
|
||||
CommunityActions::delete_mods_for_community(&mut context.pool(), community_id).await?;
|
||||
|
||||
// TODO: this should probably be a bulk operation
|
||||
// Re-add the mods, in the new order
|
||||
for cmod in &community_mods {
|
||||
let community_moderator_form = CommunityModeratorForm {
|
||||
community_id: cmod.community.id,
|
||||
person_id: cmod.moderator.id,
|
||||
};
|
||||
let community_moderator_form =
|
||||
CommunityModeratorForm::new(cmod.community.id, cmod.moderator.id);
|
||||
|
||||
CommunityModerator::join(&mut context.pool(), &community_moderator_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)?;
|
||||
CommunityActions::join(&mut context.pool(), &community_moderator_form).await?;
|
||||
}
|
||||
|
||||
// Mod tables
|
||||
|
|
|
@ -9,12 +9,7 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::{
|
||||
CommunityFollower,
|
||||
CommunityFollowerForm,
|
||||
CommunityPersonBan,
|
||||
CommunityPersonBanForm,
|
||||
},
|
||||
community::{CommunityActions, CommunityPersonBanForm},
|
||||
mod_log::moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
|
||||
person::Person,
|
||||
},
|
||||
|
@ -162,25 +157,23 @@ pub(crate) async fn ban_nonlocal_user_from_local_communities(
|
|||
|
||||
// Ban / unban them from our local communities
|
||||
let community_user_ban_form = CommunityPersonBanForm {
|
||||
community_id,
|
||||
person_id: target.id,
|
||||
expires: Some(expires_dt),
|
||||
ban_expires: Some(expires_dt),
|
||||
..CommunityPersonBanForm::new(community_id, target.id)
|
||||
};
|
||||
|
||||
if ban {
|
||||
// Ignore all errors for these
|
||||
CommunityPersonBan::ban(&mut context.pool(), &community_user_ban_form)
|
||||
CommunityActions::ban(&mut context.pool(), &community_user_ban_form)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
// Also unsubscribe them from the community, if they are subscribed
|
||||
let community_follower_form = CommunityFollowerForm::new(community_id, target.id);
|
||||
|
||||
CommunityFollower::unfollow(&mut context.pool(), &community_follower_form)
|
||||
CommunityActions::unfollow(&mut context.pool(), target.id, community_id)
|
||||
.await
|
||||
.ok();
|
||||
} else {
|
||||
CommunityPersonBan::unban(&mut context.pool(), &community_user_ban_form)
|
||||
CommunityActions::unban(&mut context.pool(), &community_user_ban_form)
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ use lemmy_api_common::{
|
|||
person::{BlockPerson, BlockPersonResponse},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::person_block::{PersonBlock, PersonBlockForm},
|
||||
source::person::{PersonActions, PersonBlockForm},
|
||||
traits::Blockable,
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PersonView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
||||
pub async fn user_block_person(
|
||||
data: Json<BlockPerson>,
|
||||
|
@ -23,10 +23,7 @@ pub async fn user_block_person(
|
|||
Err(LemmyErrorType::CantBlockYourself)?
|
||||
}
|
||||
|
||||
let person_block_form = PersonBlockForm {
|
||||
person_id,
|
||||
target_id,
|
||||
};
|
||||
let person_block_form = PersonBlockForm::new(person_id, target_id);
|
||||
|
||||
let target_user = LocalUserView::read_person(&mut context.pool(), target_id)
|
||||
.await
|
||||
|
@ -37,13 +34,9 @@ pub async fn user_block_person(
|
|||
}
|
||||
|
||||
if data.block {
|
||||
PersonBlock::block(&mut context.pool(), &person_block_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::PersonBlockAlreadyExists)?;
|
||||
PersonActions::block(&mut context.pool(), &person_block_form).await?;
|
||||
} else {
|
||||
PersonBlock::unblock(&mut context.pool(), &person_block_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::PersonBlockAlreadyExists)?;
|
||||
PersonActions::unblock(&mut context.pool(), &person_block_form).await?;
|
||||
}
|
||||
|
||||
let person_view = PersonView::read(&mut context.pool(), target_id, false).await?;
|
||||
|
|
|
@ -2,11 +2,11 @@ use activitypub_federation::config::Data;
|
|||
use actix_web::web::Json;
|
||||
use lemmy_api_common::{context::LemmyContext, site::UserBlockInstanceParams, SuccessResponse};
|
||||
use lemmy_db_schema::{
|
||||
source::instance_block::{InstanceBlock, InstanceBlockForm},
|
||||
source::instance::{InstanceActions, InstanceBlockForm},
|
||||
traits::Blockable,
|
||||
};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
||||
pub async fn user_block_instance(
|
||||
data: Json<UserBlockInstanceParams>,
|
||||
|
@ -19,19 +19,12 @@ pub async fn user_block_instance(
|
|||
return Err(LemmyErrorType::CantBlockLocalInstance)?;
|
||||
}
|
||||
|
||||
let instance_block_form = InstanceBlockForm {
|
||||
person_id,
|
||||
instance_id,
|
||||
};
|
||||
let instance_block_form = InstanceBlockForm::new(person_id, instance_id);
|
||||
|
||||
if data.block {
|
||||
InstanceBlock::block(&mut context.pool(), &instance_block_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::InstanceBlockAlreadyExists)?;
|
||||
InstanceActions::block(&mut context.pool(), &instance_block_form).await?;
|
||||
} else {
|
||||
InstanceBlock::unblock(&mut context.pool(), &instance_block_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::InstanceBlockAlreadyExists)?;
|
||||
InstanceActions::unblock(&mut context.pool(), &instance_block_form).await?;
|
||||
}
|
||||
|
||||
Ok(Json(SuccessResponse::default()))
|
||||
|
|
|
@ -3,9 +3,12 @@ use lemmy_api_common::{
|
|||
context::LemmyContext,
|
||||
post::{HidePost, PostResponse},
|
||||
};
|
||||
use lemmy_db_schema::source::post::PostHide;
|
||||
use lemmy_db_schema::{
|
||||
source::post::{PostActions, PostHideForm},
|
||||
traits::Hideable,
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn hide_post(
|
||||
data: Json<HidePost>,
|
||||
|
@ -15,15 +18,13 @@ pub async fn hide_post(
|
|||
let person_id = local_user_view.person.id;
|
||||
let post_id = data.post_id;
|
||||
|
||||
let hide_form = PostHideForm::new(post_id, person_id);
|
||||
|
||||
// Mark the post as hidden / unhidden
|
||||
if data.hide {
|
||||
PostHide::hide(&mut context.pool(), post_id, person_id)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntHidePost)?;
|
||||
PostActions::hide(&mut context.pool(), &hide_form).await?;
|
||||
} else {
|
||||
PostHide::unhide(&mut context.pool(), post_id, person_id)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntHidePost)?;
|
||||
PostActions::unhide(&mut context.pool(), &hide_form).await?;
|
||||
}
|
||||
|
||||
let post_view = PostView::read(
|
||||
|
|
|
@ -11,12 +11,12 @@ use lemmy_db_schema::{
|
|||
newtypes::PostOrCommentId,
|
||||
source::{
|
||||
local_site::LocalSite,
|
||||
post::{PostLike, PostLikeForm, PostRead, PostReadForm},
|
||||
post::{PostActions, PostLikeForm, PostReadForm},
|
||||
},
|
||||
traits::Likeable,
|
||||
traits::{Likeable, Readable},
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use std::ops::Deref;
|
||||
|
||||
pub async fn like_post(
|
||||
|
@ -52,19 +52,18 @@ pub async fn like_post(
|
|||
// Remove any likes first
|
||||
let person_id = local_user_view.person.id;
|
||||
|
||||
PostLike::remove(&mut context.pool(), person_id, post_id).await?;
|
||||
PostActions::remove_like(&mut context.pool(), person_id, post_id).await?;
|
||||
|
||||
// Only add the like if the score isnt 0
|
||||
let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
|
||||
let do_add =
|
||||
like_form.like_score != 0 && (like_form.like_score == 1 || like_form.like_score == -1);
|
||||
if do_add {
|
||||
PostLike::like(&mut context.pool(), &like_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikePost)?;
|
||||
PostActions::like(&mut context.pool(), &like_form).await?;
|
||||
}
|
||||
|
||||
// Mark Post Read
|
||||
let read_form = PostReadForm::new(post_id, person_id);
|
||||
PostRead::mark_as_read(&mut context.pool(), &read_form).await?;
|
||||
PostActions::mark_as_read(&mut context.pool(), &read_form).await?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::LikePostOrComment {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use actix_web::web::{Data, Json};
|
||||
use lemmy_api_common::{context::LemmyContext, post::MarkManyPostsAsRead, SuccessResponse};
|
||||
use lemmy_db_schema::source::post::PostRead;
|
||||
use lemmy_db_schema::{source::post::PostActions, traits::Readable};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult, MAX_API_PARAM_ELEMENTS};
|
||||
|
||||
|
@ -16,8 +16,10 @@ pub async fn mark_posts_as_read(
|
|||
|
||||
let person_id = local_user_view.person.id;
|
||||
|
||||
let forms = PostActions::build_many_read_forms(post_ids, person_id);
|
||||
|
||||
// Mark the posts as read
|
||||
PostRead::mark_many_as_read(&mut context.pool(), post_ids, person_id).await?;
|
||||
PostActions::mark_many_as_read(&mut context.pool(), &forms).await?;
|
||||
|
||||
Ok(Json(SuccessResponse::default()))
|
||||
}
|
||||
|
|
|
@ -3,7 +3,10 @@ use lemmy_api_common::{
|
|||
context::LemmyContext,
|
||||
post::{MarkPostAsRead, PostResponse},
|
||||
};
|
||||
use lemmy_db_schema::source::post::{PostRead, PostReadForm};
|
||||
use lemmy_db_schema::{
|
||||
source::post::{PostActions, PostReadForm},
|
||||
traits::Readable,
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostView};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
|
@ -18,9 +21,9 @@ pub async fn mark_post_as_read(
|
|||
// Mark the post as read / unread
|
||||
let form = PostReadForm::new(post_id, person_id);
|
||||
if data.read {
|
||||
PostRead::mark_as_read(&mut context.pool(), &form).await?;
|
||||
PostActions::mark_as_read(&mut context.pool(), &form).await?;
|
||||
} else {
|
||||
PostRead::mark_as_unread(&mut context.pool(), &form).await?;
|
||||
PostActions::mark_as_unread(&mut context.pool(), &form).await?;
|
||||
}
|
||||
let post_view = PostView::read(
|
||||
&mut context.pool(),
|
||||
|
|
|
@ -4,11 +4,11 @@ use lemmy_api_common::{
|
|||
post::{PostResponse, SavePost},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::post::{PostRead, PostReadForm, PostSaved, PostSavedForm},
|
||||
traits::Saveable,
|
||||
source::post::{PostActions, PostReadForm, PostSavedForm},
|
||||
traits::{Readable, Saveable},
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn save_post(
|
||||
data: Json<SavePost>,
|
||||
|
@ -18,13 +18,9 @@ pub async fn save_post(
|
|||
let post_saved_form = PostSavedForm::new(data.post_id, local_user_view.person.id);
|
||||
|
||||
if data.save {
|
||||
PostSaved::save(&mut context.pool(), &post_saved_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntSavePost)?;
|
||||
PostActions::save(&mut context.pool(), &post_saved_form).await?;
|
||||
} else {
|
||||
PostSaved::unsave(&mut context.pool(), &post_saved_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntSavePost)?;
|
||||
PostActions::unsave(&mut context.pool(), &post_saved_form).await?;
|
||||
}
|
||||
|
||||
let post_id = data.post_id;
|
||||
|
@ -38,7 +34,7 @@ pub async fn save_post(
|
|||
.await?;
|
||||
|
||||
let read_form = PostReadForm::new(post_id, person_id);
|
||||
PostRead::mark_as_read(&mut context.pool(), &read_form).await?;
|
||||
PostActions::mark_as_read(&mut context.pool(), &read_form).await?;
|
||||
|
||||
Ok(Json(PostResponse { post_view }))
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ use lemmy_db_schema::{
|
|||
traits::Reportable,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommentReportView, CommentView, LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
/// Creates a comment report and notifies the moderators of the community
|
||||
pub async fn create_comment_report(
|
||||
|
@ -59,9 +59,7 @@ pub async fn create_comment_report(
|
|||
violates_instance_rules: data.violates_instance_rules.unwrap_or_default(),
|
||||
};
|
||||
|
||||
let report = CommentReport::report(&mut context.pool(), &report_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreateReport)?;
|
||||
let report = CommentReport::report(&mut context.pool(), &report_form).await?;
|
||||
|
||||
let comment_report_view =
|
||||
CommentReportView::read(&mut context.pool(), report.id, person_id).await?;
|
||||
|
|
|
@ -8,7 +8,7 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{source::comment_report::CommentReport, traits::Reportable};
|
||||
use lemmy_db_views::structs::{CommentReportView, LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
/// Resolves or unresolves a comment report and notifies the moderators of the community
|
||||
pub async fn resolve_comment_report(
|
||||
|
@ -30,13 +30,9 @@ pub async fn resolve_comment_report(
|
|||
.await?;
|
||||
|
||||
if data.resolved {
|
||||
CommentReport::resolve(&mut context.pool(), report_id, person_id)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
|
||||
CommentReport::resolve(&mut context.pool(), report_id, person_id).await?;
|
||||
} else {
|
||||
CommentReport::unresolve(&mut context.pool(), report_id, person_id)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
|
||||
CommentReport::unresolve(&mut context.pool(), report_id, person_id).await?;
|
||||
}
|
||||
|
||||
let report_id = data.report_id;
|
||||
|
|
|
@ -14,7 +14,7 @@ use lemmy_db_schema::{
|
|||
traits::{Crud, Reportable},
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityReportView, LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn create_community_report(
|
||||
data: Json<CreateCommunityReport>,
|
||||
|
@ -41,9 +41,7 @@ pub async fn create_community_report(
|
|||
reason,
|
||||
};
|
||||
|
||||
let report = CommunityReport::report(&mut context.pool(), &report_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreateReport)?;
|
||||
let report = CommunityReport::report(&mut context.pool(), &report_form).await?;
|
||||
|
||||
let community_report_view =
|
||||
CommunityReportView::read(&mut context.pool(), report.id, person_id).await?;
|
||||
|
|
|
@ -6,7 +6,7 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{source::community_report::CommunityReport, traits::Reportable};
|
||||
use lemmy_db_views::structs::{CommunityReportView, LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn resolve_community_report(
|
||||
data: Json<ResolveCommunityReport>,
|
||||
|
@ -18,13 +18,9 @@ pub async fn resolve_community_report(
|
|||
let report_id = data.report_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
if data.resolved {
|
||||
CommunityReport::resolve(&mut context.pool(), report_id, person_id)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
|
||||
CommunityReport::resolve(&mut context.pool(), report_id, person_id).await?;
|
||||
} else {
|
||||
CommunityReport::unresolve(&mut context.pool(), report_id, person_id)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
|
||||
CommunityReport::unresolve(&mut context.pool(), report_id, person_id).await?;
|
||||
}
|
||||
|
||||
let community_report_view =
|
||||
|
|
|
@ -20,7 +20,7 @@ use lemmy_db_schema::{
|
|||
traits::Reportable,
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostReportView, PostView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
/// Creates a post report and notifies the moderators of the community
|
||||
pub async fn create_post_report(
|
||||
|
@ -55,9 +55,7 @@ pub async fn create_post_report(
|
|||
violates_instance_rules: data.violates_instance_rules.unwrap_or_default(),
|
||||
};
|
||||
|
||||
let report = PostReport::report(&mut context.pool(), &report_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreateReport)?;
|
||||
let report = PostReport::report(&mut context.pool(), &report_form).await?;
|
||||
|
||||
let post_report_view = PostReportView::read(&mut context.pool(), report.id, person_id).await?;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{source::post_report::PostReport, traits::Reportable};
|
||||
use lemmy_db_views::structs::{LocalUserView, PostReportView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
/// Resolves or unresolves a post report and notifies the moderators of the community
|
||||
pub async fn resolve_post_report(
|
||||
|
@ -30,14 +30,9 @@ pub async fn resolve_post_report(
|
|||
.await?;
|
||||
|
||||
if data.resolved {
|
||||
PostReport::resolve(&mut context.pool(), report_id, person_id)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
|
||||
PostReport::resolve(&mut context.pool(), report_id, person_id).await?;
|
||||
} else {
|
||||
// TODO: not federated
|
||||
PostReport::unresolve(&mut context.pool(), report_id, person_id)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
|
||||
PostReport::unresolve(&mut context.pool(), report_id, person_id).await?;
|
||||
}
|
||||
|
||||
let post_report_view = PostReportView::read(&mut context.pool(), report_id, person_id).await?;
|
||||
|
|
|
@ -14,7 +14,7 @@ use lemmy_db_schema::{
|
|||
traits::{Crud, Reportable},
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PrivateMessageReportView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
||||
pub async fn create_pm_report(
|
||||
data: Json<CreatePrivateMessageReport>,
|
||||
|
@ -41,9 +41,7 @@ pub async fn create_pm_report(
|
|||
reason,
|
||||
};
|
||||
|
||||
let report = PrivateMessageReport::report(&mut context.pool(), &report_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreateReport)?;
|
||||
let report = PrivateMessageReport::report(&mut context.pool(), &report_form).await?;
|
||||
|
||||
let private_message_report_view =
|
||||
PrivateMessageReportView::read(&mut context.pool(), report.id).await?;
|
||||
|
|
|
@ -6,7 +6,7 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{source::private_message_report::PrivateMessageReport, traits::Reportable};
|
||||
use lemmy_db_views::structs::{LocalUserView, PrivateMessageReportView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn resolve_pm_report(
|
||||
data: Json<ResolvePrivateMessageReport>,
|
||||
|
@ -18,13 +18,9 @@ pub async fn resolve_pm_report(
|
|||
let report_id = data.report_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
if data.resolved {
|
||||
PrivateMessageReport::resolve(&mut context.pool(), report_id, person_id)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
|
||||
PrivateMessageReport::resolve(&mut context.pool(), report_id, person_id).await?;
|
||||
} else {
|
||||
PrivateMessageReport::unresolve(&mut context.pool(), report_id, person_id)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)?;
|
||||
PrivateMessageReport::unresolve(&mut context.pool(), report_id, person_id).await?;
|
||||
}
|
||||
|
||||
let private_message_report_view =
|
||||
|
|
|
@ -15,13 +15,11 @@ use enum_map::{enum_map, EnumMap};
|
|||
use lemmy_db_schema::{
|
||||
newtypes::{CommentId, CommunityId, DbUrl, InstanceId, PersonId, PostId, PostOrCommentId},
|
||||
source::{
|
||||
comment::{Comment, CommentLike, CommentUpdateForm},
|
||||
community::{Community, CommunityModerator, CommunityUpdateForm},
|
||||
community_block::CommunityBlock,
|
||||
comment::{Comment, CommentActions, CommentUpdateForm},
|
||||
community::{Community, CommunityActions, CommunityUpdateForm},
|
||||
email_verification::{EmailVerification, EmailVerificationForm},
|
||||
images::{ImageDetails, RemoteImage},
|
||||
instance::Instance,
|
||||
instance_block::InstanceBlock,
|
||||
instance::{Instance, InstanceActions},
|
||||
local_site::LocalSite,
|
||||
local_site_rate_limit::LocalSiteRateLimit,
|
||||
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
||||
|
@ -34,15 +32,13 @@ use lemmy_db_schema::{
|
|||
},
|
||||
oauth_account::OAuthAccount,
|
||||
password_reset_request::PasswordResetRequest,
|
||||
person::{Person, PersonUpdateForm},
|
||||
person_block::PersonBlock,
|
||||
post::{Post, PostLike},
|
||||
post_actions::{PostActions, PostActionsForm},
|
||||
person::{Person, PersonActions, PersonUpdateForm},
|
||||
post::{Post, PostActions, PostReadCommentsForm},
|
||||
private_message::PrivateMessage,
|
||||
registration_application::RegistrationApplication,
|
||||
site::Site,
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
traits::{Blockable, Crud, Likeable, ReadComments},
|
||||
utils::DbPool,
|
||||
FederationMode,
|
||||
RegistrationMode,
|
||||
|
@ -157,13 +153,8 @@ pub async fn update_read_comments(
|
|||
read_comments: i64,
|
||||
pool: &mut DbPool<'_>,
|
||||
) -> LemmyResult<()> {
|
||||
let person_post_agg_form = PostActionsForm {
|
||||
person_id,
|
||||
post_id,
|
||||
read_comments,
|
||||
};
|
||||
|
||||
PostActions::upsert(pool, &person_post_agg_form).await?;
|
||||
let person_post_agg_form = PostReadCommentsForm::new(post_id, person_id, read_comments);
|
||||
PostActions::update_read_comments(pool, &person_post_agg_form).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -288,9 +279,9 @@ pub async fn check_person_instance_community_block(
|
|||
community_id: CommunityId,
|
||||
pool: &mut DbPool<'_>,
|
||||
) -> LemmyResult<()> {
|
||||
PersonBlock::read(pool, potential_blocker_id, my_id).await?;
|
||||
InstanceBlock::read(pool, potential_blocker_id, community_instance_id).await?;
|
||||
CommunityBlock::read(pool, potential_blocker_id, community_id).await?;
|
||||
PersonActions::read_block(pool, potential_blocker_id, my_id).await?;
|
||||
InstanceActions::read_block(pool, potential_blocker_id, community_instance_id).await?;
|
||||
CommunityActions::read_block(pool, potential_blocker_id, community_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -312,9 +303,9 @@ pub async fn check_local_vote_mode(
|
|||
// Undo previous vote for item if new vote fails
|
||||
if downvote_fail || upvote_fail {
|
||||
match post_or_comment_id {
|
||||
PostOrCommentId::Post(post_id) => PostLike::remove(pool, person_id, post_id).await?,
|
||||
PostOrCommentId::Post(post_id) => PostActions::remove_like(pool, person_id, post_id).await?,
|
||||
PostOrCommentId::Comment(comment_id) => {
|
||||
CommentLike::remove(pool, person_id, comment_id).await?
|
||||
CommentActions::remove_like(pool, person_id, comment_id).await?
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -984,7 +975,7 @@ pub async fn purge_user_account(person_id: PersonId, context: &LemmyContext) ->
|
|||
.with_lemmy_type(LemmyErrorType::CouldntUpdatePost)?;
|
||||
|
||||
// Leave communities they mod
|
||||
CommunityModerator::leave_all_communities(pool, person_id).await?;
|
||||
CommunityActions::leave_mod_team_for_all_communities(pool, person_id).await?;
|
||||
|
||||
// Delete the oauth accounts linked to the local user
|
||||
if let Ok(local_user) = LocalUserView::read_person(pool, person_id).await {
|
||||
|
|
|
@ -19,7 +19,7 @@ use lemmy_db_schema::{
|
|||
impls::actor_language::validate_post_language,
|
||||
newtypes::PostOrCommentId,
|
||||
source::{
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm},
|
||||
comment::{Comment, CommentActions, CommentInsertForm, CommentLikeForm},
|
||||
comment_reply::{CommentReply, CommentReplyUpdateForm},
|
||||
person_comment_mention::{PersonCommentMention, PersonCommentMentionUpdateForm},
|
||||
},
|
||||
|
@ -123,15 +123,9 @@ pub async fn create_comment(
|
|||
.await?;
|
||||
|
||||
// You like your own comment by default
|
||||
let like_form = CommentLikeForm {
|
||||
comment_id: inserted_comment.id,
|
||||
person_id: local_user_view.person.id,
|
||||
score: 1,
|
||||
};
|
||||
let like_form = CommentLikeForm::new(local_user_view.person.id, inserted_comment.id, 1);
|
||||
|
||||
CommentLike::like(&mut context.pool(), &like_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikeComment)?;
|
||||
CommentActions::like(&mut context.pool(), &like_form).await?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::CreateComment(inserted_comment.clone()),
|
||||
|
|
|
@ -20,11 +20,10 @@ use lemmy_db_schema::{
|
|||
actor_language::{CommunityLanguage, LocalUserLanguage, SiteLanguage},
|
||||
community::{
|
||||
Community,
|
||||
CommunityFollower,
|
||||
CommunityActions,
|
||||
CommunityFollowerForm,
|
||||
CommunityFollowerState,
|
||||
CommunityInsertForm,
|
||||
CommunityModerator,
|
||||
CommunityModeratorForm,
|
||||
},
|
||||
},
|
||||
|
@ -115,26 +114,19 @@ pub async fn create_community(
|
|||
let community_id = inserted_community.id;
|
||||
|
||||
// The community creator becomes a moderator
|
||||
let community_moderator_form = CommunityModeratorForm {
|
||||
community_id,
|
||||
person_id: local_user_view.person.id,
|
||||
};
|
||||
let community_moderator_form =
|
||||
CommunityModeratorForm::new(community_id, local_user_view.person.id);
|
||||
|
||||
CommunityModerator::join(&mut context.pool(), &community_moderator_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)?;
|
||||
CommunityActions::join(&mut context.pool(), &community_moderator_form).await?;
|
||||
|
||||
// Follow your own community
|
||||
let community_follower_form = CommunityFollowerForm {
|
||||
let community_follower_form = CommunityFollowerForm::new(
|
||||
community_id,
|
||||
person_id: local_user_view.person.id,
|
||||
state: Some(CommunityFollowerState::Accepted),
|
||||
approver_id: None,
|
||||
};
|
||||
local_user_view.person.id,
|
||||
CommunityFollowerState::Accepted,
|
||||
);
|
||||
|
||||
CommunityFollower::follow(&mut context.pool(), &community_follower_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityFollowerAlreadyExists)?;
|
||||
CommunityActions::follow(&mut context.pool(), &community_follower_form).await?;
|
||||
|
||||
// Update the discussion_languages if that's provided
|
||||
let site_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
|
||||
|
|
|
@ -23,9 +23,9 @@ use lemmy_db_schema::{
|
|||
source::{
|
||||
community::Community,
|
||||
local_site::LocalSite,
|
||||
post::{Post, PostInsertForm, PostLike, PostLikeForm, PostRead, PostReadForm},
|
||||
post::{Post, PostActions, PostInsertForm, PostLikeForm, PostReadForm},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
traits::{Crud, Likeable, Readable},
|
||||
utils::diesel_url_create,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityModeratorView, LocalUserView};
|
||||
|
@ -144,9 +144,7 @@ pub async fn create_post(
|
|||
let post_id = inserted_post.id;
|
||||
let like_form = PostLikeForm::new(post_id, person_id, 1);
|
||||
|
||||
PostLike::like(&mut context.pool(), &like_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikePost)?;
|
||||
PostActions::like(&mut context.pool(), &like_form).await?;
|
||||
|
||||
// Scan the post body for user mentions, add those rows
|
||||
let mentions = scrape_text_for_mentions(&inserted_post.body.clone().unwrap_or_default());
|
||||
|
@ -161,7 +159,7 @@ pub async fn create_post(
|
|||
.await?;
|
||||
|
||||
let read_form = PostReadForm::new(post_id, person_id);
|
||||
PostRead::mark_as_read(&mut context.pool(), &read_form).await?;
|
||||
PostActions::mark_as_read(&mut context.pool(), &read_form).await?;
|
||||
|
||||
build_post_response(&context, community_id, local_user_view, post_id).await
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ use lemmy_api_common::{
|
|||
use lemmy_db_schema::{
|
||||
source::{
|
||||
comment::Comment,
|
||||
post::{Post, PostRead, PostReadForm},
|
||||
post::{Post, PostActions, PostReadForm},
|
||||
},
|
||||
traits::Crud,
|
||||
traits::{Crud, Readable},
|
||||
};
|
||||
use lemmy_db_views::{
|
||||
post::post_view::PostQuery,
|
||||
|
@ -64,7 +64,7 @@ pub async fn get_post(
|
|||
let post_id = post_view.post.id;
|
||||
if let Some(person_id) = person_id {
|
||||
let read_form = PostReadForm::new(post_id, person_id);
|
||||
PostRead::mark_as_read(&mut context.pool(), &read_form).await?;
|
||||
PostActions::mark_as_read(&mut context.pool(), &read_form).await?;
|
||||
|
||||
update_read_comments(
|
||||
person_id,
|
||||
|
|
|
@ -14,10 +14,10 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
person_block::PersonBlock,
|
||||
person::PersonActions,
|
||||
private_message::{PrivateMessage, PrivateMessageInsertForm},
|
||||
},
|
||||
traits::Crud,
|
||||
traits::{Blockable, Crud},
|
||||
};
|
||||
use lemmy_db_views::structs::{LocalUserView, PrivateMessageView};
|
||||
use lemmy_utils::{
|
||||
|
@ -35,7 +35,7 @@ pub async fn create_private_message(
|
|||
let content = process_markdown(&data.content, &slur_regex, &url_blocklist, &context).await?;
|
||||
is_valid_body_field(&content, false)?;
|
||||
|
||||
PersonBlock::read(
|
||||
PersonActions::read_block(
|
||||
&mut context.pool(),
|
||||
data.recipient_id,
|
||||
local_user_view.person.id,
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
use actix_web::web::{Data, Json};
|
||||
use lemmy_api_common::{context::LemmyContext, site::MyUserInfo, utils::check_user_valid};
|
||||
use lemmy_db_schema::source::{
|
||||
actor_language::LocalUserLanguage,
|
||||
community_block::CommunityBlock,
|
||||
instance_block::InstanceBlock,
|
||||
person_block::PersonBlock,
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
actor_language::LocalUserLanguage,
|
||||
community::CommunityActions,
|
||||
instance::InstanceActions,
|
||||
person::PersonActions,
|
||||
},
|
||||
traits::Blockable,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommunityFollowerView, CommunityModeratorView, LocalUserView};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
|
@ -23,9 +26,9 @@ pub async fn get_my_user(
|
|||
let (follows, community_blocks, instance_blocks, person_blocks, moderates, discussion_languages) =
|
||||
lemmy_db_schema::try_join_with_pool!(pool => (
|
||||
|pool| CommunityFollowerView::for_person(pool, person_id),
|
||||
|pool| CommunityBlock::for_person(pool, person_id),
|
||||
|pool| InstanceBlock::for_person(pool, person_id),
|
||||
|pool| PersonBlock::for_person(pool, person_id),
|
||||
|pool| CommunityActions::read_blocks_for_person(pool, person_id),
|
||||
|pool| InstanceActions::read_blocks_for_person(pool, person_id),
|
||||
|pool| PersonActions::read_blocks_for_person(pool, person_id),
|
||||
|pool| CommunityModeratorView::for_person(pool, person_id, Some(&local_user_view.local_user)),
|
||||
|pool| LocalUserLanguage::read(pool, local_user_id)
|
||||
))
|
||||
|
|
|
@ -30,7 +30,7 @@ use lemmy_api_common::{
|
|||
use lemmy_db_schema::{
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
community::{CommunityPersonBan, CommunityPersonBanForm},
|
||||
community::{CommunityActions, CommunityPersonBanForm},
|
||||
mod_log::moderator::{ModBan, ModBanForm, ModBanFromCommunity, ModBanFromCommunityForm},
|
||||
person::{Person, PersonUpdateForm},
|
||||
},
|
||||
|
@ -177,11 +177,10 @@ impl ActivityHandler for BlockUser {
|
|||
}
|
||||
SiteOrCommunity::Community(community) => {
|
||||
let community_user_ban_form = CommunityPersonBanForm {
|
||||
community_id: community.id,
|
||||
person_id: blocked_person.id,
|
||||
expires: Some(expires),
|
||||
ban_expires: Some(expires),
|
||||
..CommunityPersonBanForm::new(community.id, blocked_person.id)
|
||||
};
|
||||
CommunityPersonBan::ban(&mut context.pool(), &community_user_ban_form).await?;
|
||||
CommunityActions::ban(&mut context.pool(), &community_user_ban_form).await?;
|
||||
|
||||
// Dont unsubscribe the user so that we can receive a potential unban activity.
|
||||
// If we unfollowed the community here, activities from the community would be rejected
|
||||
|
|
|
@ -26,7 +26,7 @@ use lemmy_api_common::{
|
|||
use lemmy_db_schema::{
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
community::{CommunityPersonBan, CommunityPersonBanForm},
|
||||
community::{CommunityActions, CommunityPersonBanForm},
|
||||
mod_log::moderator::{ModBan, ModBanForm, ModBanFromCommunity, ModBanFromCommunityForm},
|
||||
person::{Person, PersonUpdateForm},
|
||||
},
|
||||
|
@ -130,12 +130,8 @@ impl ActivityHandler for UndoBlockUser {
|
|||
}
|
||||
SiteOrCommunity::Community(community) => {
|
||||
verify_visibility(&self.to, &self.cc, &community)?;
|
||||
let community_user_ban_form = CommunityPersonBanForm {
|
||||
community_id: community.id,
|
||||
person_id: blocked_person.id,
|
||||
expires: None,
|
||||
};
|
||||
CommunityPersonBan::unban(&mut context.pool(), &community_user_ban_form).await?;
|
||||
let community_user_ban_form = CommunityPersonBanForm::new(community.id, blocked_person.id);
|
||||
CommunityActions::unban(&mut context.pool(), &community_user_ban_form).await?;
|
||||
|
||||
if self.restore_data.unwrap_or(false) {
|
||||
remove_or_restore_user_data_in_community(
|
||||
|
|
|
@ -23,7 +23,7 @@ use activitypub_federation::{
|
|||
traits::{ActivityHandler, Actor},
|
||||
};
|
||||
use lemmy_api_common::context::LemmyContext;
|
||||
use lemmy_db_schema::source::{activity::ActivitySendTargets, community::CommunityFollower};
|
||||
use lemmy_db_schema::source::{activity::ActivitySendTargets, community::CommunityActions};
|
||||
use lemmy_utils::error::{FederationError, LemmyError, LemmyErrorType, LemmyResult};
|
||||
use serde_json::Value;
|
||||
use url::Url;
|
||||
|
@ -212,7 +212,7 @@ async fn can_accept_activity_in_community(
|
|||
return Err(LemmyErrorType::NotFound.into());
|
||||
}
|
||||
if !community.local {
|
||||
CommunityFollower::check_has_local_followers(&mut context.pool(), community.id).await?
|
||||
CommunityActions::check_has_local_followers(&mut context.pool(), community.id).await?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -30,7 +30,7 @@ use lemmy_db_schema::{
|
|||
newtypes::{CommunityId, PersonId},
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||
community::{Community, CommunityActions, CommunityModeratorForm},
|
||||
mod_log::moderator::{ModAddCommunity, ModAddCommunityForm},
|
||||
person::Person,
|
||||
post::{Post, PostUpdateForm},
|
||||
|
@ -133,14 +133,11 @@ impl ActivityHandler for CollectionAdd {
|
|||
// already been added. Skip it here as it would result in a duplicate key error.
|
||||
let new_mod_id = new_mod.id;
|
||||
let moderated_communities =
|
||||
CommunityModerator::get_person_moderated_communities(&mut context.pool(), new_mod_id)
|
||||
CommunityActions::get_person_moderated_communities(&mut context.pool(), new_mod_id)
|
||||
.await?;
|
||||
if !moderated_communities.contains(&community.id) {
|
||||
let form = CommunityModeratorForm {
|
||||
community_id: community.id,
|
||||
person_id: new_mod.id,
|
||||
};
|
||||
CommunityModerator::join(&mut context.pool(), &form).await?;
|
||||
let form = CommunityModeratorForm::new(community.id, new_mod.id);
|
||||
CommunityActions::join(&mut context.pool(), &form).await?;
|
||||
|
||||
// write mod log
|
||||
let actor = self.actor.dereference(context).await?;
|
||||
|
|
|
@ -26,7 +26,7 @@ use lemmy_db_schema::{
|
|||
impls::community::CollectionType,
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||
community::{Community, CommunityActions, CommunityModeratorForm},
|
||||
mod_log::moderator::{ModAddCommunity, ModAddCommunityForm},
|
||||
post::{Post, PostUpdateForm},
|
||||
},
|
||||
|
@ -124,11 +124,8 @@ impl ActivityHandler for CollectionRemove {
|
|||
.dereference(context)
|
||||
.await?;
|
||||
|
||||
let form = CommunityModeratorForm {
|
||||
community_id: community.id,
|
||||
person_id: remove_mod.id,
|
||||
};
|
||||
CommunityModerator::leave(&mut context.pool(), &form).await?;
|
||||
let form = CommunityModeratorForm::new(community.id, remove_mod.id);
|
||||
CommunityActions::leave(&mut context.pool(), &form).await?;
|
||||
|
||||
// write mod log
|
||||
let actor = self.actor.dereference(context).await?;
|
||||
|
|
|
@ -10,7 +10,7 @@ use lemmy_api_common::context::LemmyContext;
|
|||
use lemmy_db_schema::{
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
person::{Person, PersonFollower},
|
||||
person::{Person, PersonActions},
|
||||
site::Site,
|
||||
},
|
||||
traits::Crud,
|
||||
|
@ -59,7 +59,7 @@ pub(crate) async fn send_activity_in_community(
|
|||
// send to user followers
|
||||
if !is_mod_action {
|
||||
inboxes.add_inboxes(
|
||||
PersonFollower::list_followers(&mut context.pool(), actor.id)
|
||||
PersonActions::list_followers(&mut context.pool(), actor.id)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|p| ApubPerson(p).shared_inbox_or_inbox()),
|
||||
|
|
|
@ -31,7 +31,7 @@ use lemmy_db_schema::{
|
|||
newtypes::{PersonId, PostOrCommentId},
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
comment::{Comment, CommentLike, CommentLikeForm},
|
||||
comment::{Comment, CommentActions, CommentLikeForm},
|
||||
community::Community,
|
||||
person::Person,
|
||||
post::Post,
|
||||
|
@ -151,12 +151,8 @@ impl ActivityHandler for CreateOrUpdateNote {
|
|||
let comment = ApubComment::from_json(self.object, context).await?;
|
||||
|
||||
// author likes their own comment by default
|
||||
let like_form = CommentLikeForm {
|
||||
comment_id: comment.id,
|
||||
person_id: comment.creator_id,
|
||||
score: 1,
|
||||
};
|
||||
CommentLike::like(&mut context.pool(), &like_form).await?;
|
||||
let like_form = CommentLikeForm::new(comment.creator_id, comment.id, 1);
|
||||
CommentActions::like(&mut context.pool(), &like_form).await?;
|
||||
|
||||
// Calculate initial hot_rank
|
||||
Comment::update_hot_rank(&mut context.pool(), comment.id).await?;
|
||||
|
|
|
@ -27,7 +27,7 @@ use lemmy_db_schema::{
|
|||
activity::ActivitySendTargets,
|
||||
community::Community,
|
||||
person::Person,
|
||||
post::{Post, PostLike, PostLikeForm},
|
||||
post::{Post, PostActions, PostLikeForm},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
};
|
||||
|
@ -117,7 +117,7 @@ impl ActivityHandler for CreateOrUpdatePage {
|
|||
|
||||
// author likes their own post by default
|
||||
let like_form = PostLikeForm::new(post.id, post.creator_id, 1);
|
||||
PostLike::like(&mut context.pool(), &like_form).await?;
|
||||
PostActions::like(&mut context.pool(), &like_form).await?;
|
||||
|
||||
// Calculate initial hot_rank for post
|
||||
Post::update_ranks(&mut context.pool(), post.id).await?;
|
||||
|
|
|
@ -11,7 +11,7 @@ use activitypub_federation::{
|
|||
};
|
||||
use lemmy_api_common::context::LemmyContext;
|
||||
use lemmy_db_schema::{
|
||||
source::{activity::ActivitySendTargets, community::CommunityFollower},
|
||||
source::{activity::ActivitySendTargets, community::CommunityActions},
|
||||
traits::Followable,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyError, LemmyResult};
|
||||
|
@ -66,7 +66,7 @@ impl ActivityHandler for AcceptFollow {
|
|||
// This will throw an error if no follow was requested
|
||||
let community_id = community.id;
|
||||
let person_id = person.id;
|
||||
CommunityFollower::follow_accepted(&mut context.pool(), community_id, person_id).await?;
|
||||
CommunityActions::follow_accepted(&mut context.pool(), community_id, person_id).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ use lemmy_api_common::context::LemmyContext;
|
|||
use lemmy_db_schema::{
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
community::{CommunityFollower, CommunityFollowerForm, CommunityFollowerState},
|
||||
community::{CommunityActions, CommunityFollowerForm, CommunityFollowerState},
|
||||
instance::Instance,
|
||||
person::{PersonFollower, PersonFollowerForm},
|
||||
person::{PersonActions, PersonFollowerForm},
|
||||
},
|
||||
traits::Followable,
|
||||
CommunityVisibility,
|
||||
|
@ -95,12 +95,8 @@ impl ActivityHandler for Follow {
|
|||
let object = self.object.dereference(context).await?;
|
||||
match object {
|
||||
UserOrCommunity::User(u) => {
|
||||
let form = PersonFollowerForm {
|
||||
person_id: u.id,
|
||||
follower_id: actor.id,
|
||||
pending: false,
|
||||
};
|
||||
PersonFollower::follow(&mut context.pool(), &form).await?;
|
||||
let form = PersonFollowerForm::new(u.id, actor.id, false);
|
||||
PersonActions::follow(&mut context.pool(), &form).await?;
|
||||
AcceptFollow::send(self, context).await?;
|
||||
}
|
||||
UserOrCommunity::Community(c) => {
|
||||
|
@ -111,17 +107,14 @@ impl ActivityHandler for Follow {
|
|||
return Err(FederationError::PlatformLackingPrivateCommunitySupport.into());
|
||||
}
|
||||
}
|
||||
let state = Some(match c.visibility {
|
||||
let follow_state = match c.visibility {
|
||||
Public | Unlisted => CommunityFollowerState::Accepted,
|
||||
Private => CommunityFollowerState::ApprovalRequired,
|
||||
// Dont allow following local-only community via federation.
|
||||
LocalOnlyPrivate | LocalOnlyPublic => return Err(LemmyErrorType::NotFound.into()),
|
||||
});
|
||||
let form = CommunityFollowerForm {
|
||||
state,
|
||||
..CommunityFollowerForm::new(c.id, actor.id)
|
||||
};
|
||||
CommunityFollower::follow(&mut context.pool(), &form).await?;
|
||||
let form = CommunityFollowerForm::new(c.id, actor.id, follow_state);
|
||||
CommunityActions::follow(&mut context.pool(), &form).await?;
|
||||
if c.visibility == CommunityVisibility::Public {
|
||||
AcceptFollow::send(self, context).await?;
|
||||
}
|
||||
|
|
|
@ -11,10 +11,7 @@ use activitypub_federation::{
|
|||
};
|
||||
use lemmy_api_common::context::LemmyContext;
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
community::{CommunityFollower, CommunityFollowerForm},
|
||||
},
|
||||
source::{activity::ActivitySendTargets, community::CommunityActions},
|
||||
traits::Followable,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyError, LemmyResult};
|
||||
|
@ -68,8 +65,7 @@ impl ActivityHandler for RejectFollow {
|
|||
let person = self.object.actor.dereference(context).await?;
|
||||
|
||||
// remove the follow
|
||||
let form = CommunityFollowerForm::new(community.id, person.id);
|
||||
CommunityFollower::unfollow(&mut context.pool(), &form).await?;
|
||||
CommunityActions::unfollow(&mut context.pool(), person.id, community.id).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -13,11 +13,7 @@ use activitypub_federation::{
|
|||
};
|
||||
use lemmy_api_common::context::LemmyContext;
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
community::{CommunityFollower, CommunityFollowerForm},
|
||||
person::{PersonFollower, PersonFollowerForm},
|
||||
},
|
||||
source::{activity::ActivitySendTargets, community::CommunityActions, person::PersonActions},
|
||||
traits::Followable,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyError, LemmyResult};
|
||||
|
@ -79,16 +75,10 @@ impl ActivityHandler for UndoFollow {
|
|||
|
||||
match object {
|
||||
UserOrCommunity::User(u) => {
|
||||
let form = PersonFollowerForm {
|
||||
person_id: u.id,
|
||||
follower_id: person.id,
|
||||
pending: false,
|
||||
};
|
||||
PersonFollower::unfollow(&mut context.pool(), &form).await?;
|
||||
PersonActions::unfollow(&mut context.pool(), person.id, u.id).await?;
|
||||
}
|
||||
UserOrCommunity::Community(c) => {
|
||||
let form = CommunityFollowerForm::new(c.id, person.id);
|
||||
CommunityFollower::unfollow(&mut context.pool(), &form).await?;
|
||||
CommunityActions::unfollow(&mut context.pool(), person.id, c.id).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ use lemmy_db_schema::{
|
|||
newtypes::DbUrl,
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
comment::{CommentLike, CommentLikeForm},
|
||||
comment::{CommentActions, CommentLikeForm},
|
||||
community::Community,
|
||||
person::Person,
|
||||
post::{PostLike, PostLikeForm},
|
||||
post::{PostActions, PostLikeForm},
|
||||
},
|
||||
traits::Likeable,
|
||||
};
|
||||
|
@ -59,14 +59,10 @@ async fn vote_comment(
|
|||
context: &Data<LemmyContext>,
|
||||
) -> LemmyResult<()> {
|
||||
let comment_id = comment.id;
|
||||
let like_form = CommentLikeForm {
|
||||
comment_id,
|
||||
person_id: actor.id,
|
||||
score: vote_type.into(),
|
||||
};
|
||||
let like_form = CommentLikeForm::new(actor.id, comment_id, vote_type.into());
|
||||
let person_id = actor.id;
|
||||
CommentLike::remove(&mut context.pool(), person_id, comment_id).await?;
|
||||
CommentLike::like(&mut context.pool(), &like_form).await?;
|
||||
CommentActions::remove_like(&mut context.pool(), person_id, comment_id).await?;
|
||||
CommentActions::like(&mut context.pool(), &like_form).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -79,8 +75,8 @@ async fn vote_post(
|
|||
let post_id = post.id;
|
||||
let like_form = PostLikeForm::new(post.id, actor.id, vote_type.into());
|
||||
let person_id = actor.id;
|
||||
PostLike::remove(&mut context.pool(), person_id, post_id).await?;
|
||||
PostLike::like(&mut context.pool(), &like_form).await?;
|
||||
PostActions::remove_like(&mut context.pool(), person_id, post_id).await?;
|
||||
PostActions::like(&mut context.pool(), &like_form).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -91,7 +87,7 @@ async fn undo_vote_comment(
|
|||
) -> LemmyResult<()> {
|
||||
let comment_id = comment.id;
|
||||
let person_id = actor.id;
|
||||
CommentLike::remove(&mut context.pool(), person_id, comment_id).await?;
|
||||
CommentActions::remove_like(&mut context.pool(), person_id, comment_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -102,6 +98,6 @@ async fn undo_vote_post(
|
|||
) -> LemmyResult<()> {
|
||||
let post_id = post.id;
|
||||
let person_id = actor.id;
|
||||
PostLike::remove(&mut context.pool(), person_id, post_id).await?;
|
||||
PostActions::remove_like(&mut context.pool(), person_id, post_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::PostId,
|
||||
source::{community::Community, post::PostRead},
|
||||
source::{community::Community, post::PostActions},
|
||||
traits::Readable,
|
||||
};
|
||||
use lemmy_db_views::{
|
||||
post::post_view::PostQuery,
|
||||
|
@ -111,7 +112,8 @@ pub async fn list_posts(
|
|||
.unwrap_or(local_user.auto_mark_fetched_posts_as_read)
|
||||
{
|
||||
let post_ids = posts.iter().map(|p| p.post.id).collect::<Vec<PostId>>();
|
||||
PostRead::mark_many_as_read(&mut context.pool(), &post_ids, local_user.person_id).await?;
|
||||
let forms = PostActions::build_many_read_forms(&post_ids, local_user.person_id);
|
||||
PostActions::mark_many_as_read(&mut context.pool(), &forms).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,15 +12,17 @@ use lemmy_api_common::{context::LemmyContext, SuccessResponse};
|
|||
use lemmy_db_schema::{
|
||||
newtypes::DbUrl,
|
||||
source::{
|
||||
comment::{CommentSaved, CommentSavedForm},
|
||||
community::{CommunityFollower, CommunityFollowerForm, CommunityFollowerState},
|
||||
community_block::{CommunityBlock, CommunityBlockForm},
|
||||
instance::Instance,
|
||||
instance_block::{InstanceBlock, InstanceBlockForm},
|
||||
comment::{CommentActions, CommentSavedForm},
|
||||
community::{
|
||||
CommunityActions,
|
||||
CommunityBlockForm,
|
||||
CommunityFollowerForm,
|
||||
CommunityFollowerState,
|
||||
},
|
||||
instance::{Instance, InstanceActions, InstanceBlockForm},
|
||||
local_user::{LocalUser, LocalUserUpdateForm},
|
||||
person::{Person, PersonUpdateForm},
|
||||
person_block::{PersonBlock, PersonBlockForm},
|
||||
post::{PostSaved, PostSavedForm},
|
||||
person::{Person, PersonActions, PersonBlockForm, PersonUpdateForm},
|
||||
post::{PostActions, PostSavedForm},
|
||||
},
|
||||
traits::{Blockable, Crud, Followable, Saveable},
|
||||
};
|
||||
|
@ -163,11 +165,9 @@ pub async fn import_settings(
|
|||
&context,
|
||||
|(followed, context)| async move {
|
||||
let community = followed.dereference(&context).await?;
|
||||
let form = CommunityFollowerForm {
|
||||
state: Some(CommunityFollowerState::Pending),
|
||||
..CommunityFollowerForm::new(community.id, person_id)
|
||||
};
|
||||
CommunityFollower::follow(&mut context.pool(), &form).await?;
|
||||
let form =
|
||||
CommunityFollowerForm::new(community.id, person_id, CommunityFollowerState::Pending);
|
||||
CommunityActions::follow(&mut context.pool(), &form).await?;
|
||||
LemmyResult::Ok(())
|
||||
},
|
||||
)
|
||||
|
@ -179,7 +179,7 @@ pub async fn import_settings(
|
|||
|(saved, context)| async move {
|
||||
let post = saved.dereference(&context).await?;
|
||||
let form = PostSavedForm::new(post.id, person_id);
|
||||
PostSaved::save(&mut context.pool(), &form).await?;
|
||||
PostActions::save(&mut context.pool(), &form).await?;
|
||||
LemmyResult::Ok(())
|
||||
},
|
||||
)
|
||||
|
@ -190,8 +190,8 @@ pub async fn import_settings(
|
|||
&context,
|
||||
|(saved, context)| async move {
|
||||
let comment = saved.dereference(&context).await?;
|
||||
let form = CommentSavedForm::new(comment.id, person_id);
|
||||
CommentSaved::save(&mut context.pool(), &form).await?;
|
||||
let form = CommentSavedForm::new(person_id, comment.id);
|
||||
CommentActions::save(&mut context.pool(), &form).await?;
|
||||
LemmyResult::Ok(())
|
||||
},
|
||||
)
|
||||
|
@ -202,11 +202,8 @@ pub async fn import_settings(
|
|||
&context,
|
||||
|(blocked, context)| async move {
|
||||
let community = blocked.dereference(&context).await?;
|
||||
let form = CommunityBlockForm {
|
||||
person_id,
|
||||
community_id: community.id,
|
||||
};
|
||||
CommunityBlock::block(&mut context.pool(), &form).await?;
|
||||
let form = CommunityBlockForm::new(community.id, person_id);
|
||||
CommunityActions::block(&mut context.pool(), &form).await?;
|
||||
LemmyResult::Ok(())
|
||||
},
|
||||
)
|
||||
|
@ -218,11 +215,8 @@ pub async fn import_settings(
|
|||
|(blocked, context)| async move {
|
||||
let context = context.reset_request_count();
|
||||
let target = blocked.dereference(&context).await?;
|
||||
let form = PersonBlockForm {
|
||||
person_id,
|
||||
target_id: target.id,
|
||||
};
|
||||
PersonBlock::block(&mut context.pool(), &form).await?;
|
||||
let form = PersonBlockForm::new(person_id, target.id);
|
||||
PersonActions::block(&mut context.pool(), &form).await?;
|
||||
LemmyResult::Ok(())
|
||||
},
|
||||
)
|
||||
|
@ -230,11 +224,8 @@ pub async fn import_settings(
|
|||
|
||||
try_join_all(data.blocked_instances.iter().map(|domain| async {
|
||||
let instance = Instance::read_or_create(&mut context.pool(), domain.clone()).await?;
|
||||
let form = InstanceBlockForm {
|
||||
person_id,
|
||||
instance_id: instance.id,
|
||||
};
|
||||
InstanceBlock::block(&mut context.pool(), &form).await?;
|
||||
let form = InstanceBlockForm::new(person_id, instance.id);
|
||||
InstanceActions::block(&mut context.pool(), &form).await?;
|
||||
LemmyResult::Ok(())
|
||||
}))
|
||||
.await?;
|
||||
|
@ -292,7 +283,7 @@ pub(crate) mod tests {
|
|||
source::{
|
||||
community::{
|
||||
Community,
|
||||
CommunityFollower,
|
||||
CommunityActions,
|
||||
CommunityFollowerForm,
|
||||
CommunityFollowerState,
|
||||
CommunityInsertForm,
|
||||
|
@ -322,11 +313,12 @@ pub(crate) mod tests {
|
|||
"pubkey".to_string(),
|
||||
);
|
||||
let community = Community::create(pool, &community_form).await?;
|
||||
let follower_form = CommunityFollowerForm {
|
||||
state: Some(CommunityFollowerState::Accepted),
|
||||
..CommunityFollowerForm::new(community.id, export_user.person.id)
|
||||
};
|
||||
CommunityFollower::follow(pool, &follower_form).await?;
|
||||
let follower_form = CommunityFollowerForm::new(
|
||||
community.id,
|
||||
export_user.person.id,
|
||||
CommunityFollowerState::Accepted,
|
||||
);
|
||||
CommunityActions::follow(pool, &follower_form).await?;
|
||||
|
||||
let backup = export_settings(export_user.clone(), context.reset_request_count()).await?;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use activitypub_federation::{
|
|||
};
|
||||
use lemmy_api_common::{context::LemmyContext, utils::generate_moderators_url};
|
||||
use lemmy_db_schema::{
|
||||
source::community::{CommunityModerator, CommunityModeratorForm},
|
||||
source::community::{CommunityActions, CommunityModeratorForm},
|
||||
traits::Joinable,
|
||||
};
|
||||
use lemmy_db_views::structs::CommunityModeratorView;
|
||||
|
@ -62,11 +62,9 @@ impl Collection for ApubCommunityModerators {
|
|||
for mod_user in ¤t_moderators {
|
||||
let mod_id = ObjectId::from(mod_user.moderator.ap_id.clone());
|
||||
if !apub.ordered_items.contains(&mod_id) {
|
||||
let community_moderator_form = CommunityModeratorForm {
|
||||
community_id: mod_user.community.id,
|
||||
person_id: mod_user.moderator.id,
|
||||
};
|
||||
CommunityModerator::leave(&mut data.pool(), &community_moderator_form).await?;
|
||||
let community_moderator_form =
|
||||
CommunityModeratorForm::new(mod_user.community.id, mod_user.moderator.id);
|
||||
CommunityActions::leave(&mut data.pool(), &community_moderator_form).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,11 +78,8 @@ impl Collection for ApubCommunityModerators {
|
|||
.map(|c| c.moderator.ap_id.clone())
|
||||
.any(|x| x == mod_user.ap_id)
|
||||
{
|
||||
let community_moderator_form = CommunityModeratorForm {
|
||||
community_id: owner.id,
|
||||
person_id: mod_user.id,
|
||||
};
|
||||
CommunityModerator::join(&mut data.pool(), &community_moderator_form).await?;
|
||||
let community_moderator_form = CommunityModeratorForm::new(owner.id, mod_user.id);
|
||||
CommunityActions::join(&mut data.pool(), &community_moderator_form).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,12 +124,9 @@ mod tests {
|
|||
let old_mod = PersonInsertForm::test_form(inserted_instance.id, "holly");
|
||||
|
||||
let old_mod = Person::create(&mut context.pool(), &old_mod).await?;
|
||||
let community_moderator_form = CommunityModeratorForm {
|
||||
community_id: community.id,
|
||||
person_id: old_mod.id,
|
||||
};
|
||||
let community_moderator_form = CommunityModeratorForm::new(community.id, old_mod.id);
|
||||
|
||||
CommunityModerator::join(&mut context.pool(), &community_moderator_form).await?;
|
||||
CommunityActions::join(&mut context.pool(), &community_moderator_form).await?;
|
||||
|
||||
assert_eq!(site.ap_id.to_string(), "https://enterprise.lemmy.ml/");
|
||||
|
||||
|
|
|
@ -23,11 +23,10 @@ use lemmy_api_common::{
|
|||
use lemmy_db_schema::{
|
||||
source::{
|
||||
instance::Instance,
|
||||
person::Person,
|
||||
person_block::PersonBlock,
|
||||
person::{Person, PersonActions},
|
||||
private_message::{PrivateMessage as DbPrivateMessage, PrivateMessageInsertForm},
|
||||
},
|
||||
traits::Crud,
|
||||
traits::{Blockable, Crud},
|
||||
};
|
||||
use lemmy_db_views::structs::LocalUserView;
|
||||
use lemmy_utils::{
|
||||
|
@ -138,7 +137,7 @@ impl Object for ApubPrivateMessage {
|
|||
) -> LemmyResult<ApubPrivateMessage> {
|
||||
let creator = note.attributed_to.dereference(context).await?;
|
||||
let recipient = note.to[0].dereference(context).await?;
|
||||
PersonBlock::read(&mut context.pool(), recipient.id, creator.id).await?;
|
||||
PersonActions::read_block(&mut context.pool(), recipient.id, creator.id).await?;
|
||||
|
||||
// Check that they can receive private messages
|
||||
if let Ok(recipient_local_user) =
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
use crate::{
|
||||
diesel::{DecoratableTarget, OptionalExtension},
|
||||
impls::local_user::local_user_can_mod,
|
||||
newtypes::{CommentId, DbUrl, PersonId},
|
||||
schema::{comment, comment_actions},
|
||||
source::comment::{
|
||||
Comment,
|
||||
CommentActions,
|
||||
CommentInsertForm,
|
||||
CommentLike,
|
||||
CommentLikeForm,
|
||||
CommentSaved,
|
||||
CommentSavedForm,
|
||||
CommentUpdateForm,
|
||||
},
|
||||
|
@ -16,7 +14,6 @@ use crate::{
|
|||
utils::{
|
||||
functions::{coalesce, hot_rank},
|
||||
get_conn,
|
||||
now,
|
||||
uplete,
|
||||
DbPool,
|
||||
DELETED_REPLACEMENT_TEXT,
|
||||
|
@ -24,17 +21,18 @@ use crate::{
|
|||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::{
|
||||
dsl::{case_when, insert_into, not},
|
||||
dsl::insert_into,
|
||||
expression::SelectableHelper,
|
||||
result::Error,
|
||||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use diesel_ltree::Ltree;
|
||||
use lemmy_utils::{error::LemmyResult, settings::structs::Settings};
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
settings::structs::Settings,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
impl Comment {
|
||||
|
@ -143,41 +141,6 @@ impl Comment {
|
|||
}
|
||||
}
|
||||
|
||||
/// Selects the comment columns, but gives an empty string for content when
|
||||
/// deleted or removed, and you're not a mod/admin.
|
||||
#[diesel::dsl::auto_type]
|
||||
pub fn comment_select_remove_deletes() -> _ {
|
||||
let deleted_or_removed = comment::deleted.or(comment::removed);
|
||||
|
||||
// You can only view the content if it hasn't been removed, or you can mod.
|
||||
let can_view_content = not(deleted_or_removed).or(local_user_can_mod());
|
||||
let content = case_when(can_view_content, comment::content).otherwise("");
|
||||
|
||||
(
|
||||
comment::id,
|
||||
comment::creator_id,
|
||||
comment::post_id,
|
||||
content,
|
||||
comment::removed,
|
||||
comment::published,
|
||||
comment::updated,
|
||||
comment::deleted,
|
||||
comment::ap_id,
|
||||
comment::local,
|
||||
comment::path,
|
||||
comment::distinguished,
|
||||
comment::language_id,
|
||||
comment::score,
|
||||
comment::upvotes,
|
||||
comment::downvotes,
|
||||
comment::child_count,
|
||||
comment::hot_rank,
|
||||
comment::controversy_rank,
|
||||
comment::report_count,
|
||||
comment::unresolved_report_count,
|
||||
)
|
||||
}
|
||||
|
||||
impl Crud for Comment {
|
||||
type InsertForm = CommentInsertForm;
|
||||
type UpdateForm = CommentUpdateForm;
|
||||
|
@ -202,65 +165,58 @@ impl Crud for Comment {
|
|||
}
|
||||
}
|
||||
|
||||
impl Likeable for CommentLike {
|
||||
impl Likeable for CommentActions {
|
||||
type Form = CommentLikeForm;
|
||||
type IdType = CommentId;
|
||||
async fn like(pool: &mut DbPool<'_>, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
|
||||
|
||||
async fn like(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let comment_like_form = (
|
||||
comment_like_form,
|
||||
comment_actions::liked.eq(now().nullable()),
|
||||
);
|
||||
insert_into(comment_actions::table)
|
||||
.values(comment_like_form)
|
||||
.values(form)
|
||||
.on_conflict((comment_actions::comment_id, comment_actions::person_id))
|
||||
.do_update()
|
||||
.set(comment_like_form)
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikeComment)
|
||||
}
|
||||
async fn remove(
|
||||
async fn remove_like(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
comment_id: CommentId,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
comment_id: Self::IdType,
|
||||
) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(comment_actions::table.find((person_id, comment_id)))
|
||||
.set_null(comment_actions::like_score)
|
||||
.set_null(comment_actions::liked)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikeComment)
|
||||
}
|
||||
}
|
||||
|
||||
impl Saveable for CommentSaved {
|
||||
impl Saveable for CommentActions {
|
||||
type Form = CommentSavedForm;
|
||||
async fn save(
|
||||
pool: &mut DbPool<'_>,
|
||||
comment_saved_form: &CommentSavedForm,
|
||||
) -> Result<Self, Error> {
|
||||
async fn save(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(comment_actions::table)
|
||||
.values(comment_saved_form)
|
||||
.values(form)
|
||||
.on_conflict((comment_actions::comment_id, comment_actions::person_id))
|
||||
.do_update()
|
||||
.set(comment_saved_form)
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntSaveComment)
|
||||
}
|
||||
async fn unsave(
|
||||
pool: &mut DbPool<'_>,
|
||||
comment_saved_form: &CommentSavedForm,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
async fn unsave(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(
|
||||
comment_actions::table.find((comment_saved_form.person_id, comment_saved_form.comment_id)),
|
||||
)
|
||||
.set_null(comment_actions::saved)
|
||||
.get_result(conn)
|
||||
.await
|
||||
uplete::new(comment_actions::table.find((form.person_id, form.comment_id)))
|
||||
.set_null(comment_actions::saved)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntSaveComment)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,30 +312,15 @@ mod tests {
|
|||
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path)).await?;
|
||||
|
||||
// Comment Like
|
||||
let comment_like_form = CommentLikeForm {
|
||||
comment_id: inserted_comment.id,
|
||||
person_id: inserted_person.id,
|
||||
score: 1,
|
||||
};
|
||||
let comment_like_form = CommentLikeForm::new(inserted_person.id, inserted_comment.id, 1);
|
||||
|
||||
let inserted_comment_like = CommentLike::like(pool, &comment_like_form).await?;
|
||||
|
||||
let expected_comment_like = CommentLike {
|
||||
comment_id: inserted_comment.id,
|
||||
person_id: inserted_person.id,
|
||||
published: inserted_comment_like.published,
|
||||
score: 1,
|
||||
};
|
||||
let inserted_comment_like = CommentActions::like(pool, &comment_like_form).await?;
|
||||
assert_eq!(Some(1), inserted_comment_like.like_score);
|
||||
|
||||
// Comment Saved
|
||||
let comment_saved_form = CommentSavedForm::new(inserted_comment.id, inserted_person.id);
|
||||
let inserted_comment_saved = CommentSaved::save(pool, &comment_saved_form).await?;
|
||||
|
||||
let expected_comment_saved = CommentSaved {
|
||||
comment_id: inserted_comment.id,
|
||||
person_id: inserted_person.id,
|
||||
published: inserted_comment_saved.published,
|
||||
};
|
||||
let comment_saved_form = CommentSavedForm::new(inserted_person.id, inserted_comment.id);
|
||||
let inserted_comment_saved = CommentActions::save(pool, &comment_saved_form).await?;
|
||||
assert!(inserted_comment_saved.saved.is_some());
|
||||
|
||||
let comment_update_form = CommentUpdateForm {
|
||||
content: Some("A test comment".into()),
|
||||
|
@ -389,8 +330,9 @@ mod tests {
|
|||
let updated_comment = Comment::update(pool, inserted_comment.id, &comment_update_form).await?;
|
||||
|
||||
let read_comment = Comment::read(pool, inserted_comment.id).await?;
|
||||
let like_removed = CommentLike::remove(pool, inserted_person.id, inserted_comment.id).await?;
|
||||
let saved_removed = CommentSaved::unsave(pool, &comment_saved_form).await?;
|
||||
let like_removed =
|
||||
CommentActions::remove_like(pool, inserted_person.id, inserted_comment.id).await?;
|
||||
let saved_removed = CommentActions::unsave(pool, &comment_saved_form).await?;
|
||||
let num_deleted = Comment::delete(pool, inserted_comment.id).await?;
|
||||
Comment::delete(pool, inserted_child_comment.id).await?;
|
||||
Post::delete(pool, inserted_post.id).await?;
|
||||
|
@ -400,8 +342,6 @@ mod tests {
|
|||
|
||||
assert_eq!(expected_comment, read_comment);
|
||||
assert_eq!(expected_comment, updated_comment);
|
||||
assert_eq!(expected_comment_like, inserted_comment_like);
|
||||
assert_eq!(expected_comment_saved, inserted_comment_saved);
|
||||
assert_eq!(
|
||||
format!("0.{}.{}", expected_comment.id, inserted_child_comment.id),
|
||||
inserted_child_comment.path.0,
|
||||
|
@ -415,7 +355,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_aggregates() -> Result<(), Error> {
|
||||
async fn test_aggregates() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests();
|
||||
let pool = &mut pool.into();
|
||||
|
||||
|
@ -459,13 +399,9 @@ mod tests {
|
|||
let _inserted_child_comment =
|
||||
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path)).await?;
|
||||
|
||||
let comment_like = CommentLikeForm {
|
||||
comment_id: inserted_comment.id,
|
||||
person_id: inserted_person.id,
|
||||
score: 1,
|
||||
};
|
||||
let comment_like = CommentLikeForm::new(inserted_person.id, inserted_comment.id, 1);
|
||||
|
||||
CommentLike::like(pool, &comment_like).await?;
|
||||
CommentActions::like(pool, &comment_like).await?;
|
||||
|
||||
let comment_aggs_before_delete = Comment::read(pool, inserted_comment.id).await?;
|
||||
|
||||
|
@ -474,13 +410,9 @@ mod tests {
|
|||
assert_eq!(0, comment_aggs_before_delete.downvotes);
|
||||
|
||||
// Add a post dislike from the other person
|
||||
let comment_dislike = CommentLikeForm {
|
||||
comment_id: inserted_comment.id,
|
||||
person_id: another_inserted_person.id,
|
||||
score: -1,
|
||||
};
|
||||
let comment_dislike = CommentLikeForm::new(another_inserted_person.id, inserted_comment.id, -1);
|
||||
|
||||
CommentLike::like(pool, &comment_dislike).await?;
|
||||
CommentActions::like(pool, &comment_dislike).await?;
|
||||
|
||||
let comment_aggs_after_dislike = Comment::read(pool, inserted_comment.id).await?;
|
||||
|
||||
|
@ -489,7 +421,7 @@ mod tests {
|
|||
assert_eq!(1, comment_aggs_after_dislike.downvotes);
|
||||
|
||||
// Remove the first comment like
|
||||
CommentLike::remove(pool, inserted_person.id, inserted_comment.id).await?;
|
||||
CommentActions::remove_like(pool, inserted_person.id, inserted_comment.id).await?;
|
||||
let after_like_remove = Comment::read(pool, inserted_comment.id).await?;
|
||||
assert_eq!(-1, after_like_remove.score);
|
||||
assert_eq!(0, after_like_remove.upvotes);
|
||||
|
|
|
@ -8,13 +8,12 @@ use crate::{
|
|||
use chrono::Utc;
|
||||
use diesel::{
|
||||
dsl::{insert_into, update},
|
||||
result::Error,
|
||||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
|
||||
impl Reportable for CommentReport {
|
||||
type Form = CommentReportForm;
|
||||
|
@ -24,15 +23,13 @@ impl Reportable for CommentReport {
|
|||
///
|
||||
/// * `conn` - the postgres connection
|
||||
/// * `comment_report_form` - the filled CommentReportForm to insert
|
||||
async fn report(
|
||||
pool: &mut DbPool<'_>,
|
||||
comment_report_form: &CommentReportForm,
|
||||
) -> Result<Self, Error> {
|
||||
async fn report(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(comment_report::table)
|
||||
.values(comment_report_form)
|
||||
.values(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreateReport)
|
||||
}
|
||||
|
||||
/// resolve a comment report
|
||||
|
@ -44,7 +41,7 @@ impl Reportable for CommentReport {
|
|||
pool: &mut DbPool<'_>,
|
||||
report_id_: Self::IdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(comment_report::table.find(report_id_))
|
||||
.set((
|
||||
|
@ -54,6 +51,7 @@ impl Reportable for CommentReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
|
||||
async fn resolve_apub(
|
||||
|
@ -63,29 +61,28 @@ impl Reportable for CommentReport {
|
|||
resolver_id: PersonId,
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Ok(
|
||||
update(
|
||||
comment_report::table.filter(
|
||||
comment_report::comment_id
|
||||
.eq(object_id)
|
||||
.and(comment_report::creator_id.eq(report_creator_id)),
|
||||
),
|
||||
)
|
||||
.set((
|
||||
comment_report::resolved.eq(true),
|
||||
comment_report::resolver_id.eq(resolver_id),
|
||||
comment_report::updated.eq(Utc::now()),
|
||||
))
|
||||
.execute(conn)
|
||||
.await?,
|
||||
update(
|
||||
comment_report::table.filter(
|
||||
comment_report::comment_id
|
||||
.eq(object_id)
|
||||
.and(comment_report::creator_id.eq(report_creator_id)),
|
||||
),
|
||||
)
|
||||
.set((
|
||||
comment_report::resolved.eq(true),
|
||||
comment_report::resolver_id.eq(resolver_id),
|
||||
comment_report::updated.eq(Utc::now()),
|
||||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
|
||||
async fn resolve_all_for_object(
|
||||
pool: &mut DbPool<'_>,
|
||||
comment_id_: CommentId,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(comment_report::table.filter(comment_report::comment_id.eq(comment_id_)))
|
||||
.set((
|
||||
|
@ -95,6 +92,7 @@ impl Reportable for CommentReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
|
||||
/// unresolve a comment report
|
||||
|
@ -106,7 +104,7 @@ impl Reportable for CommentReport {
|
|||
pool: &mut DbPool<'_>,
|
||||
report_id_: Self::IdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(comment_report::table.find(report_id_))
|
||||
.set((
|
||||
|
@ -116,5 +114,6 @@ impl Reportable for CommentReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,49 +6,42 @@ use crate::{
|
|||
actor_language::CommunityLanguage,
|
||||
community::{
|
||||
Community,
|
||||
CommunityFollower,
|
||||
CommunityActions,
|
||||
CommunityBlockForm,
|
||||
CommunityFollowerForm,
|
||||
CommunityFollowerState,
|
||||
CommunityInsertForm,
|
||||
CommunityModerator,
|
||||
CommunityModeratorForm,
|
||||
CommunityPersonBan,
|
||||
CommunityPersonBanForm,
|
||||
CommunityUpdateForm,
|
||||
},
|
||||
post::Post,
|
||||
},
|
||||
traits::{ApubActor, Bannable, Crud, Followable, Joinable},
|
||||
traits::{ApubActor, Bannable, Blockable, Crud, Followable, Joinable},
|
||||
utils::{
|
||||
functions::{coalesce, coalesce_2_nullable, lower, random_smallint},
|
||||
get_conn,
|
||||
now,
|
||||
uplete,
|
||||
DbPool,
|
||||
},
|
||||
CommunityVisibility,
|
||||
ListingType,
|
||||
SubscribedType,
|
||||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::{
|
||||
deserialize,
|
||||
dsl::{exists, insert_into, not},
|
||||
expression::SelectableHelper,
|
||||
pg::Pg,
|
||||
result::Error,
|
||||
select,
|
||||
sql_types,
|
||||
update,
|
||||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
Queryable,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorType, LemmyResult},
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
settings::structs::Settings,
|
||||
};
|
||||
use url::Url;
|
||||
|
@ -85,42 +78,31 @@ impl Crud for Community {
|
|||
}
|
||||
}
|
||||
|
||||
impl Joinable for CommunityModerator {
|
||||
impl Joinable for CommunityActions {
|
||||
type Form = CommunityModeratorForm;
|
||||
async fn join(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_moderator_form: &CommunityModeratorForm,
|
||||
) -> Result<Self, Error> {
|
||||
async fn join(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let community_moderator_form = (
|
||||
community_moderator_form,
|
||||
community_actions::became_moderator.eq(now().nullable()),
|
||||
);
|
||||
insert_into(community_actions::table)
|
||||
.values(community_moderator_form)
|
||||
.values(form)
|
||||
.on_conflict((
|
||||
community_actions::person_id,
|
||||
community_actions::community_id,
|
||||
))
|
||||
.do_update()
|
||||
.set(community_moderator_form)
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)
|
||||
}
|
||||
|
||||
async fn leave(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_moderator_form: &CommunityModeratorForm,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
async fn leave(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(community_actions::table.find((
|
||||
community_moderator_form.person_id,
|
||||
community_moderator_form.community_id,
|
||||
)))
|
||||
.set_null(community_actions::became_moderator)
|
||||
.get_result(conn)
|
||||
.await
|
||||
uplete::new(community_actions::table.find((form.person_id, form.community_id)))
|
||||
.set_null(community_actions::became_moderator)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,8 +277,8 @@ impl Community {
|
|||
}
|
||||
}
|
||||
|
||||
impl CommunityModerator {
|
||||
pub async fn delete_for_community(
|
||||
impl CommunityActions {
|
||||
pub async fn delete_mods_for_community(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_community_id: CommunityId,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
|
@ -310,7 +292,7 @@ impl CommunityModerator {
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn leave_all_communities(
|
||||
pub async fn leave_mod_team_for_all_communities(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_person_id: PersonId,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
|
@ -365,49 +347,7 @@ impl CommunityModerator {
|
|||
Err(LemmyErrorType::NotHigherMod)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Bannable for CommunityPersonBan {
|
||||
type Form = CommunityPersonBanForm;
|
||||
async fn ban(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_person_ban_form: &CommunityPersonBanForm,
|
||||
) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let community_person_ban_form = (
|
||||
community_person_ban_form,
|
||||
community_actions::received_ban.eq(now().nullable()),
|
||||
);
|
||||
insert_into(community_actions::table)
|
||||
.values(community_person_ban_form)
|
||||
.on_conflict((
|
||||
community_actions::community_id,
|
||||
community_actions::person_id,
|
||||
))
|
||||
.do_update()
|
||||
.set(community_person_ban_form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn unban(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_person_ban_form: &CommunityPersonBanForm,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(community_actions::table.find((
|
||||
community_person_ban_form.person_id,
|
||||
community_person_ban_form.community_id,
|
||||
)))
|
||||
.set_null(community_actions::received_ban)
|
||||
.set_null(community_actions::ban_expires)
|
||||
.get_result(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl CommunityFollower {
|
||||
/// Check if a remote instance has any followers on local instance. For this it is enough to check
|
||||
/// if any follow relation is stored. Dont use this for local community.
|
||||
pub async fn check_has_local_followers(
|
||||
|
@ -425,7 +365,7 @@ impl CommunityFollower {
|
|||
.ok_or(LemmyErrorType::CommunityHasNoFollowers.into())
|
||||
}
|
||||
|
||||
pub async fn approve(
|
||||
pub async fn approve_follower(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_id: CommunityId,
|
||||
follower_id: PersonId,
|
||||
|
@ -446,33 +386,10 @@ impl CommunityFollower {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
// I'd really like to have these on the impl, but unfortunately they have to be top level,
|
||||
// according to https://diesel.rs/guides/composing-applications.html
|
||||
#[diesel::dsl::auto_type]
|
||||
pub fn community_follower_select_subscribed_type() -> _ {
|
||||
community_actions::follow_state.nullable()
|
||||
}
|
||||
|
||||
impl Queryable<sql_types::Nullable<crate::schema::sql_types::CommunityFollowerState>, Pg>
|
||||
for SubscribedType
|
||||
{
|
||||
type Row = Option<CommunityFollowerState>;
|
||||
fn build(row: Self::Row) -> deserialize::Result<Self> {
|
||||
Ok(match row {
|
||||
Some(CommunityFollowerState::Pending) => SubscribedType::Pending,
|
||||
Some(CommunityFollowerState::Accepted) => SubscribedType::Subscribed,
|
||||
Some(CommunityFollowerState::ApprovalRequired) => SubscribedType::ApprovalRequired,
|
||||
None => SubscribedType::NotSubscribed,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Followable for CommunityFollower {
|
||||
type Form = CommunityFollowerForm;
|
||||
async fn follow(pool: &mut DbPool<'_>, form: &CommunityFollowerForm) -> Result<Self, Error> {
|
||||
impl Bannable for CommunityActions {
|
||||
type Form = CommunityPersonBanForm;
|
||||
async fn ban(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let form = (form, community_actions::followed.eq(now().nullable()));
|
||||
insert_into(community_actions::table)
|
||||
.values(form)
|
||||
.on_conflict((
|
||||
|
@ -484,12 +401,44 @@ impl Followable for CommunityFollower {
|
|||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityUserAlreadyBanned)
|
||||
}
|
||||
|
||||
async fn unban(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(community_actions::table.find((form.person_id, form.community_id)))
|
||||
.set_null(community_actions::received_ban)
|
||||
.set_null(community_actions::ban_expires)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityUserAlreadyBanned)
|
||||
}
|
||||
}
|
||||
|
||||
impl Followable for CommunityActions {
|
||||
type Form = CommunityFollowerForm;
|
||||
type IdType = CommunityId;
|
||||
|
||||
async fn follow(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(community_actions::table)
|
||||
.values(form)
|
||||
.on_conflict((
|
||||
community_actions::community_id,
|
||||
community_actions::person_id,
|
||||
))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityFollowerAlreadyExists)
|
||||
}
|
||||
async fn follow_accepted(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_id: CommunityId,
|
||||
person_id: PersonId,
|
||||
) -> Result<Self, Error> {
|
||||
) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let find_action = community_actions::table
|
||||
.find((person_id, community_id))
|
||||
|
@ -499,18 +448,92 @@ impl Followable for CommunityFollower {
|
|||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityFollowerAlreadyExists)
|
||||
}
|
||||
|
||||
async fn unfollow(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &CommunityFollowerForm,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
person_id: PersonId,
|
||||
community_id: Self::IdType,
|
||||
) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(community_actions::table.find((form.person_id, form.community_id)))
|
||||
uplete::new(community_actions::table.find((person_id, community_id)))
|
||||
.set_null(community_actions::followed)
|
||||
.set_null(community_actions::follow_state)
|
||||
.set_null(community_actions::follow_approver_id)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityFollowerAlreadyExists)
|
||||
}
|
||||
}
|
||||
|
||||
impl Blockable for CommunityActions {
|
||||
type Form = CommunityBlockForm;
|
||||
type ObjectIdType = CommunityId;
|
||||
type ObjectType = Community;
|
||||
|
||||
async fn block(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(community_actions::table)
|
||||
.values(form)
|
||||
.on_conflict((
|
||||
community_actions::person_id,
|
||||
community_actions::community_id,
|
||||
))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityBlockAlreadyExists)
|
||||
}
|
||||
async fn unblock(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_block_form: &Self::Form,
|
||||
) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(community_actions::table.find((
|
||||
community_block_form.person_id,
|
||||
community_block_form.community_id,
|
||||
)))
|
||||
.set_null(community_actions::blocked)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityBlockAlreadyExists)
|
||||
}
|
||||
|
||||
async fn read_block(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
community_id: Self::ObjectIdType,
|
||||
) -> LemmyResult<()> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let find_action = community_actions::table
|
||||
.find((person_id, community_id))
|
||||
.filter(community_actions::blocked.is_not_null());
|
||||
|
||||
select(not(exists(find_action)))
|
||||
.get_result::<bool>(conn)
|
||||
.await?
|
||||
.then_some(())
|
||||
.ok_or(LemmyErrorType::CommunityIsBlocked.into())
|
||||
}
|
||||
|
||||
async fn read_blocks_for_person(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
) -> Result<Vec<Self::ObjectType>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
community_actions::table
|
||||
.filter(community_actions::blocked.is_not_null())
|
||||
.inner_join(community::table)
|
||||
.select(community::all_columns)
|
||||
.filter(community_actions::person_id.eq(person_id))
|
||||
.filter(community::deleted.eq(false))
|
||||
.filter(community::removed.eq(false))
|
||||
.order_by(community_actions::blocked)
|
||||
.load::<Community>(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,13 +590,11 @@ mod tests {
|
|||
comment::{Comment, CommentInsertForm},
|
||||
community::{
|
||||
Community,
|
||||
CommunityFollower,
|
||||
CommunityActions,
|
||||
CommunityFollowerForm,
|
||||
CommunityFollowerState,
|
||||
CommunityInsertForm,
|
||||
CommunityModerator,
|
||||
CommunityModeratorForm,
|
||||
CommunityPersonBan,
|
||||
CommunityPersonBanForm,
|
||||
CommunityUpdateForm,
|
||||
},
|
||||
|
@ -652,49 +673,35 @@ mod tests {
|
|||
interactions_month: 0,
|
||||
};
|
||||
|
||||
let community_follower_form = CommunityFollowerForm {
|
||||
community_id: inserted_community.id,
|
||||
person_id: inserted_bobby.id,
|
||||
state: Some(CommunityFollowerState::Accepted),
|
||||
approver_id: None,
|
||||
};
|
||||
let community_follower_form = CommunityFollowerForm::new(
|
||||
inserted_community.id,
|
||||
inserted_bobby.id,
|
||||
CommunityFollowerState::Accepted,
|
||||
);
|
||||
|
||||
let inserted_community_follower =
|
||||
CommunityFollower::follow(pool, &community_follower_form).await?;
|
||||
CommunityActions::follow(pool, &community_follower_form).await?;
|
||||
|
||||
let expected_community_follower = CommunityFollower {
|
||||
community_id: inserted_community.id,
|
||||
person_id: inserted_bobby.id,
|
||||
state: CommunityFollowerState::Accepted,
|
||||
published: inserted_community_follower.published,
|
||||
approver_id: None,
|
||||
};
|
||||
assert_eq!(
|
||||
Some(CommunityFollowerState::Accepted),
|
||||
inserted_community_follower.follow_state
|
||||
);
|
||||
|
||||
let bobby_moderator_form = CommunityModeratorForm {
|
||||
community_id: inserted_community.id,
|
||||
person_id: inserted_bobby.id,
|
||||
};
|
||||
let bobby_moderator_form =
|
||||
CommunityModeratorForm::new(inserted_community.id, inserted_bobby.id);
|
||||
|
||||
let inserted_bobby_moderator = CommunityModerator::join(pool, &bobby_moderator_form).await?;
|
||||
let inserted_bobby_moderator = CommunityActions::join(pool, &bobby_moderator_form).await?;
|
||||
assert!(inserted_bobby_moderator.became_moderator.is_some());
|
||||
|
||||
let artemis_moderator_form = CommunityModeratorForm {
|
||||
community_id: inserted_community.id,
|
||||
person_id: inserted_artemis.id,
|
||||
};
|
||||
let artemis_moderator_form =
|
||||
CommunityModeratorForm::new(inserted_community.id, inserted_artemis.id);
|
||||
|
||||
let _inserted_artemis_moderator =
|
||||
CommunityModerator::join(pool, &artemis_moderator_form).await?;
|
||||
|
||||
let expected_community_moderator = CommunityModerator {
|
||||
community_id: inserted_community.id,
|
||||
person_id: inserted_bobby.id,
|
||||
published: inserted_bobby_moderator.published,
|
||||
};
|
||||
let _inserted_artemis_moderator = CommunityActions::join(pool, &artemis_moderator_form).await?;
|
||||
|
||||
let moderator_person_ids = vec![inserted_bobby.id, inserted_artemis.id];
|
||||
|
||||
// Make sure bobby is marked as a higher mod than artemis, and vice versa
|
||||
let bobby_higher_check = CommunityModerator::is_higher_mod_check(
|
||||
let bobby_higher_check = CommunityActions::is_higher_mod_check(
|
||||
pool,
|
||||
inserted_community.id,
|
||||
inserted_bobby.id,
|
||||
|
@ -714,7 +721,7 @@ mod tests {
|
|||
assert!(bobby_higher_check_2.is_ok());
|
||||
|
||||
// This should throw an error, since artemis was added later
|
||||
let artemis_higher_check = CommunityModerator::is_higher_mod_check(
|
||||
let artemis_higher_check = CommunityActions::is_higher_mod_check(
|
||||
pool,
|
||||
inserted_community.id,
|
||||
inserted_artemis.id,
|
||||
|
@ -723,22 +730,14 @@ mod tests {
|
|||
.await;
|
||||
assert!(artemis_higher_check.is_err());
|
||||
|
||||
let community_person_ban_form = CommunityPersonBanForm {
|
||||
community_id: inserted_community.id,
|
||||
person_id: inserted_bobby.id,
|
||||
expires: None,
|
||||
};
|
||||
let community_person_ban_form =
|
||||
CommunityPersonBanForm::new(inserted_community.id, inserted_bobby.id);
|
||||
|
||||
let inserted_community_person_ban =
|
||||
CommunityPersonBan::ban(pool, &community_person_ban_form).await?;
|
||||
|
||||
let expected_community_person_ban = CommunityPersonBan {
|
||||
community_id: inserted_community.id,
|
||||
person_id: inserted_bobby.id,
|
||||
published: inserted_community_person_ban.published,
|
||||
expires: None,
|
||||
};
|
||||
CommunityActions::ban(pool, &community_person_ban_form).await?;
|
||||
|
||||
assert!(inserted_community_person_ban.received_ban.is_some());
|
||||
assert!(inserted_community_person_ban.ban_expires.is_none());
|
||||
let read_community = Community::read(pool, inserted_community.id).await?;
|
||||
|
||||
let update_community_form = CommunityUpdateForm {
|
||||
|
@ -748,9 +747,14 @@ mod tests {
|
|||
let updated_community =
|
||||
Community::update(pool, inserted_community.id, &update_community_form).await?;
|
||||
|
||||
let ignored_community = CommunityFollower::unfollow(pool, &community_follower_form).await?;
|
||||
let left_community = CommunityModerator::leave(pool, &bobby_moderator_form).await?;
|
||||
let unban = CommunityPersonBan::unban(pool, &community_person_ban_form).await?;
|
||||
let ignored_community = CommunityActions::unfollow(
|
||||
pool,
|
||||
community_follower_form.person_id,
|
||||
community_follower_form.community_id,
|
||||
)
|
||||
.await?;
|
||||
let left_community = CommunityActions::leave(pool, &bobby_moderator_form).await?;
|
||||
let unban = CommunityActions::unban(pool, &community_person_ban_form).await?;
|
||||
let num_deleted = Community::delete(pool, inserted_community.id).await?;
|
||||
Person::delete(pool, inserted_bobby.id).await?;
|
||||
Person::delete(pool, inserted_artemis.id).await?;
|
||||
|
@ -758,9 +762,6 @@ mod tests {
|
|||
|
||||
assert_eq!(expected_community, read_community);
|
||||
assert_eq!(expected_community, updated_community);
|
||||
assert_eq!(expected_community_follower, inserted_community_follower);
|
||||
assert_eq!(expected_community_moderator, inserted_bobby_moderator);
|
||||
assert_eq!(expected_community_person_ban, inserted_community_person_ban);
|
||||
assert_eq!(uplete::Count::only_updated(1), ignored_community);
|
||||
assert_eq!(uplete::Count::only_updated(1), left_community);
|
||||
assert_eq!(uplete::Count::only_deleted(1), unban);
|
||||
|
@ -802,32 +803,29 @@ mod tests {
|
|||
);
|
||||
let another_inserted_community = Community::create(pool, &another_community).await?;
|
||||
|
||||
let first_person_follow = CommunityFollowerForm {
|
||||
community_id: inserted_community.id,
|
||||
person_id: inserted_person.id,
|
||||
state: Some(CommunityFollowerState::Accepted),
|
||||
approver_id: None,
|
||||
};
|
||||
let first_person_follow = CommunityFollowerForm::new(
|
||||
inserted_community.id,
|
||||
inserted_person.id,
|
||||
CommunityFollowerState::Accepted,
|
||||
);
|
||||
|
||||
CommunityFollower::follow(pool, &first_person_follow).await?;
|
||||
CommunityActions::follow(pool, &first_person_follow).await?;
|
||||
|
||||
let second_person_follow = CommunityFollowerForm {
|
||||
community_id: inserted_community.id,
|
||||
person_id: another_inserted_person.id,
|
||||
state: Some(CommunityFollowerState::Accepted),
|
||||
approver_id: None,
|
||||
};
|
||||
let second_person_follow = CommunityFollowerForm::new(
|
||||
inserted_community.id,
|
||||
another_inserted_person.id,
|
||||
CommunityFollowerState::Accepted,
|
||||
);
|
||||
|
||||
CommunityFollower::follow(pool, &second_person_follow).await?;
|
||||
CommunityActions::follow(pool, &second_person_follow).await?;
|
||||
|
||||
let another_community_follow = CommunityFollowerForm {
|
||||
community_id: another_inserted_community.id,
|
||||
person_id: inserted_person.id,
|
||||
state: Some(CommunityFollowerState::Accepted),
|
||||
approver_id: None,
|
||||
};
|
||||
let another_community_follow = CommunityFollowerForm::new(
|
||||
another_inserted_community.id,
|
||||
inserted_person.id,
|
||||
CommunityFollowerState::Accepted,
|
||||
);
|
||||
|
||||
CommunityFollower::follow(pool, &another_community_follow).await?;
|
||||
CommunityActions::follow(pool, &another_community_follow).await?;
|
||||
|
||||
let new_post = PostInsertForm::new(
|
||||
"A test post".into(),
|
||||
|
@ -866,13 +864,18 @@ mod tests {
|
|||
assert_eq!(0, another_community_aggs.comments);
|
||||
|
||||
// Unfollow test
|
||||
CommunityFollower::unfollow(pool, &second_person_follow).await?;
|
||||
CommunityActions::unfollow(
|
||||
pool,
|
||||
second_person_follow.person_id,
|
||||
second_person_follow.community_id,
|
||||
)
|
||||
.await?;
|
||||
let after_unfollow = Community::read(pool, inserted_community.id).await?;
|
||||
assert_eq!(1, after_unfollow.subscribers);
|
||||
assert_eq!(1, after_unfollow.subscribers_local);
|
||||
|
||||
// Follow again just for the later tests
|
||||
CommunityFollower::follow(pool, &second_person_follow).await?;
|
||||
CommunityActions::follow(pool, &second_person_follow).await?;
|
||||
let after_follow_again = Community::read(pool, inserted_community.id).await?;
|
||||
assert_eq!(2, after_follow_again.subscribers);
|
||||
assert_eq!(2, after_follow_again.subscribers_local);
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
use crate::{
|
||||
newtypes::{CommunityId, PersonId},
|
||||
schema::{community, community_actions},
|
||||
source::{
|
||||
community::Community,
|
||||
community_block::{CommunityBlock, CommunityBlockForm},
|
||||
},
|
||||
traits::Blockable,
|
||||
utils::{get_conn, now, uplete, DbPool},
|
||||
};
|
||||
use diesel::{
|
||||
dsl::{exists, insert_into, not},
|
||||
expression::SelectableHelper,
|
||||
result::Error,
|
||||
select,
|
||||
ExpressionMethods,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
||||
impl CommunityBlock {
|
||||
pub async fn read(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_person_id: PersonId,
|
||||
for_community_id: CommunityId,
|
||||
) -> LemmyResult<()> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let find_action = community_actions::table
|
||||
.find((for_person_id, for_community_id))
|
||||
.filter(community_actions::blocked.is_not_null());
|
||||
select(not(exists(find_action)))
|
||||
.get_result::<bool>(conn)
|
||||
.await?
|
||||
.then_some(())
|
||||
.ok_or(LemmyErrorType::CommunityIsBlocked.into())
|
||||
}
|
||||
|
||||
pub async fn for_person(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
) -> Result<Vec<Community>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
community_actions::table
|
||||
.filter(community_actions::blocked.is_not_null())
|
||||
.inner_join(community::table)
|
||||
.select(community::all_columns)
|
||||
.filter(community_actions::person_id.eq(person_id))
|
||||
.filter(community::deleted.eq(false))
|
||||
.filter(community::removed.eq(false))
|
||||
.order_by(community_actions::blocked)
|
||||
.load::<Community>(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl Blockable for CommunityBlock {
|
||||
type Form = CommunityBlockForm;
|
||||
async fn block(pool: &mut DbPool<'_>, community_block_form: &Self::Form) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let community_block_form = (
|
||||
community_block_form,
|
||||
community_actions::blocked.eq(now().nullable()),
|
||||
);
|
||||
insert_into(community_actions::table)
|
||||
.values(community_block_form)
|
||||
.on_conflict((
|
||||
community_actions::person_id,
|
||||
community_actions::community_id,
|
||||
))
|
||||
.do_update()
|
||||
.set(community_block_form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
async fn unblock(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_block_form: &Self::Form,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(community_actions::table.find((
|
||||
community_block_form.person_id,
|
||||
community_block_form.community_id,
|
||||
)))
|
||||
.set_null(community_actions::blocked)
|
||||
.get_result(conn)
|
||||
.await
|
||||
}
|
||||
}
|
|
@ -8,13 +8,12 @@ use crate::{
|
|||
use chrono::Utc;
|
||||
use diesel::{
|
||||
dsl::{insert_into, update},
|
||||
result::Error,
|
||||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
|
||||
impl Reportable for CommunityReport {
|
||||
type Form = CommunityReportForm;
|
||||
|
@ -24,15 +23,13 @@ impl Reportable for CommunityReport {
|
|||
///
|
||||
/// * `conn` - the postgres connection
|
||||
/// * `community_report_form` - the filled CommunityReportForm to insert
|
||||
async fn report(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_report_form: &CommunityReportForm,
|
||||
) -> Result<Self, Error> {
|
||||
async fn report(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(community_report::table)
|
||||
.values(community_report_form)
|
||||
.values(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreateReport)
|
||||
}
|
||||
|
||||
/// resolve a community report
|
||||
|
@ -44,7 +41,7 @@ impl Reportable for CommunityReport {
|
|||
pool: &mut DbPool<'_>,
|
||||
report_id_: Self::IdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(community_report::table.find(report_id_))
|
||||
.set((
|
||||
|
@ -54,6 +51,7 @@ impl Reportable for CommunityReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
|
||||
async fn resolve_apub(
|
||||
|
@ -63,29 +61,28 @@ impl Reportable for CommunityReport {
|
|||
resolver_id: PersonId,
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Ok(
|
||||
update(
|
||||
community_report::table.filter(
|
||||
community_report::community_id
|
||||
.eq(object_id)
|
||||
.and(community_report::creator_id.eq(report_creator_id)),
|
||||
),
|
||||
)
|
||||
.set((
|
||||
community_report::resolved.eq(true),
|
||||
community_report::resolver_id.eq(resolver_id),
|
||||
community_report::updated.eq(Utc::now()),
|
||||
))
|
||||
.execute(conn)
|
||||
.await?,
|
||||
update(
|
||||
community_report::table.filter(
|
||||
community_report::community_id
|
||||
.eq(object_id)
|
||||
.and(community_report::creator_id.eq(report_creator_id)),
|
||||
),
|
||||
)
|
||||
.set((
|
||||
community_report::resolved.eq(true),
|
||||
community_report::resolver_id.eq(resolver_id),
|
||||
community_report::updated.eq(Utc::now()),
|
||||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
|
||||
async fn resolve_all_for_object(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_id_: CommunityId,
|
||||
community_id_: Self::ObjectIdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(community_report::table.filter(community_report::community_id.eq(community_id_)))
|
||||
.set((
|
||||
|
@ -95,6 +92,7 @@ impl Reportable for CommunityReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
|
||||
/// unresolve a community report
|
||||
|
@ -106,7 +104,7 @@ impl Reportable for CommunityReport {
|
|||
pool: &mut DbPool<'_>,
|
||||
report_id_: Self::IdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(community_report::table.find(report_id_))
|
||||
.set((
|
||||
|
@ -116,5 +114,6 @@ impl Reportable for CommunityReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,31 @@
|
|||
use crate::{
|
||||
diesel::dsl::IntervalDsl,
|
||||
newtypes::InstanceId,
|
||||
newtypes::{InstanceId, PersonId},
|
||||
schema::{
|
||||
federation_allowlist,
|
||||
federation_blocklist,
|
||||
federation_queue_state,
|
||||
instance,
|
||||
instance_actions,
|
||||
local_site,
|
||||
site,
|
||||
},
|
||||
source::{
|
||||
federation_queue_state::FederationQueueState,
|
||||
instance::{Instance, InstanceForm},
|
||||
instance::{Instance, InstanceActions, InstanceBlockForm, InstanceForm},
|
||||
},
|
||||
traits::Blockable,
|
||||
utils::{
|
||||
functions::{coalesce, lower},
|
||||
get_conn,
|
||||
now,
|
||||
uplete,
|
||||
DbPool,
|
||||
},
|
||||
};
|
||||
use chrono::Utc;
|
||||
use diesel::{
|
||||
dsl::{count_star, insert_into},
|
||||
dsl::{count_star, exists, insert_into, not, select},
|
||||
result::Error,
|
||||
ExpressionMethods,
|
||||
NullableExpressionMethods,
|
||||
|
@ -31,6 +34,7 @@ use diesel::{
|
|||
SelectableHelper,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
|
||||
impl Instance {
|
||||
/// Attempt to read Instance column for the given domain. If it doesn't exist, insert a new one.
|
||||
|
@ -186,3 +190,62 @@ impl Instance {
|
|||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl Blockable for InstanceActions {
|
||||
type Form = InstanceBlockForm;
|
||||
type ObjectIdType = InstanceId;
|
||||
type ObjectType = Instance;
|
||||
|
||||
async fn block(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(instance_actions::table)
|
||||
.values(form)
|
||||
.on_conflict((instance_actions::person_id, instance_actions::instance_id))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::InstanceBlockAlreadyExists)
|
||||
}
|
||||
|
||||
async fn unblock(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(instance_actions::table.find((form.person_id, form.instance_id)))
|
||||
.set_null(instance_actions::blocked)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::InstanceBlockAlreadyExists)
|
||||
}
|
||||
|
||||
async fn read_block(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
instance_id: Self::ObjectIdType,
|
||||
) -> LemmyResult<()> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let find_action = instance_actions::table
|
||||
.find((person_id, instance_id))
|
||||
.filter(instance_actions::blocked.is_not_null());
|
||||
select(not(exists(find_action)))
|
||||
.get_result::<bool>(conn)
|
||||
.await?
|
||||
.then_some(())
|
||||
.ok_or(LemmyErrorType::InstanceIsBlocked.into())
|
||||
}
|
||||
|
||||
async fn read_blocks_for_person(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
) -> Result<Vec<Self::ObjectType>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
instance_actions::table
|
||||
.filter(instance_actions::blocked.is_not_null())
|
||||
.inner_join(instance::table)
|
||||
.select(instance::all_columns)
|
||||
.filter(instance_actions::person_id.eq(person_id))
|
||||
.order_by(instance_actions::blocked)
|
||||
.load::<Instance>(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
use crate::{
|
||||
newtypes::{InstanceId, PersonId},
|
||||
schema::{instance, instance_actions},
|
||||
source::{
|
||||
instance::Instance,
|
||||
instance_block::{InstanceBlock, InstanceBlockForm},
|
||||
},
|
||||
traits::Blockable,
|
||||
utils::{get_conn, now, uplete, DbPool},
|
||||
};
|
||||
use diesel::{
|
||||
dsl::{exists, insert_into, not},
|
||||
expression::SelectableHelper,
|
||||
result::Error,
|
||||
select,
|
||||
ExpressionMethods,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
||||
impl InstanceBlock {
|
||||
pub async fn read(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_person_id: PersonId,
|
||||
for_instance_id: InstanceId,
|
||||
) -> LemmyResult<()> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let find_action = instance_actions::table
|
||||
.find((for_person_id, for_instance_id))
|
||||
.filter(instance_actions::blocked.is_not_null());
|
||||
select(not(exists(find_action)))
|
||||
.get_result::<bool>(conn)
|
||||
.await?
|
||||
.then_some(())
|
||||
.ok_or(LemmyErrorType::InstanceIsBlocked.into())
|
||||
}
|
||||
|
||||
pub async fn for_person(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
) -> Result<Vec<Instance>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
instance_actions::table
|
||||
.filter(instance_actions::blocked.is_not_null())
|
||||
.inner_join(instance::table)
|
||||
.select(instance::all_columns)
|
||||
.filter(instance_actions::person_id.eq(person_id))
|
||||
.order_by(instance_actions::blocked)
|
||||
.load::<Instance>(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl Blockable for InstanceBlock {
|
||||
type Form = InstanceBlockForm;
|
||||
async fn block(pool: &mut DbPool<'_>, instance_block_form: &Self::Form) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let instance_block_form = (
|
||||
instance_block_form,
|
||||
instance_actions::blocked.eq(now().nullable()),
|
||||
);
|
||||
insert_into(instance_actions::table)
|
||||
.values(instance_block_form)
|
||||
.on_conflict((instance_actions::person_id, instance_actions::instance_id))
|
||||
.do_update()
|
||||
.set(instance_block_form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
async fn unblock(
|
||||
pool: &mut DbPool<'_>,
|
||||
instance_block_form: &Self::Form,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(instance_actions::table.find((
|
||||
instance_block_form.person_id,
|
||||
instance_block_form.instance_id,
|
||||
)))
|
||||
.set_null(instance_actions::blocked)
|
||||
.get_result(conn)
|
||||
.await
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
use crate::{
|
||||
aliases::creator_community_actions,
|
||||
newtypes::{CommunityId, DbUrl, LanguageId, LocalUserId, PersonId},
|
||||
schema::{community, community_actions, local_user, person, registration_application},
|
||||
source::{
|
||||
|
@ -19,12 +18,9 @@ use bcrypt::{hash, DEFAULT_COST};
|
|||
use diesel::{
|
||||
dsl::{insert_into, not, IntervalDsl},
|
||||
result::Error,
|
||||
BoolExpressionMethods,
|
||||
CombineDsl,
|
||||
ExpressionMethods,
|
||||
JoinOnDsl,
|
||||
NullableExpressionMethods,
|
||||
PgExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
|
@ -301,29 +297,6 @@ impl LocalUser {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
// I'd really like to have these on the impl, but unfortunately they have to be top level,
|
||||
// according to https://diesel.rs/guides/composing-applications.html
|
||||
/// Checks to see if you can mod an item.
|
||||
///
|
||||
/// Caveat: Since admin status isn't federated or ordered, it can't know whether
|
||||
/// item creator is a federated admin, or a higher admin.
|
||||
/// The back-end will reject an action for admin that is higher via
|
||||
/// LocalUser::is_higher_mod_or_admin_check
|
||||
#[diesel::dsl::auto_type]
|
||||
pub fn local_user_can_mod() -> _ {
|
||||
let am_admin = local_user::admin.nullable();
|
||||
let creator_became_moderator = creator_community_actions
|
||||
.field(community_actions::became_moderator)
|
||||
.nullable();
|
||||
|
||||
let am_higher_mod = community_actions::became_moderator
|
||||
.nullable()
|
||||
.le(creator_became_moderator);
|
||||
|
||||
am_admin.or(am_higher_mod).is_not_distinct_from(true)
|
||||
}
|
||||
|
||||
/// Adds some helper functions for an optional LocalUser
|
||||
pub trait LocalUserOptionHelper {
|
||||
fn person_id(&self) -> Option<PersonId>;
|
||||
|
|
|
@ -5,7 +5,6 @@ pub mod comment;
|
|||
pub mod comment_reply;
|
||||
pub mod comment_report;
|
||||
pub mod community;
|
||||
pub mod community_block;
|
||||
pub mod community_report;
|
||||
pub mod custom_emoji;
|
||||
pub mod email_verification;
|
||||
|
@ -14,7 +13,6 @@ pub mod federation_blocklist;
|
|||
pub mod federation_queue_state;
|
||||
pub mod images;
|
||||
pub mod instance;
|
||||
pub mod instance_block;
|
||||
pub mod language;
|
||||
pub mod local_site;
|
||||
pub mod local_site_rate_limit;
|
||||
|
@ -26,11 +24,9 @@ pub mod oauth_account;
|
|||
pub mod oauth_provider;
|
||||
pub mod password_reset_request;
|
||||
pub mod person;
|
||||
pub mod person_block;
|
||||
pub mod person_comment_mention;
|
||||
pub mod person_post_mention;
|
||||
pub mod post;
|
||||
pub mod post_actions;
|
||||
pub mod post_report;
|
||||
pub mod private_message;
|
||||
pub mod private_message_report;
|
||||
|
|
|
@ -4,28 +4,28 @@ use crate::{
|
|||
schema::{comment, community, instance, local_user, person, person_actions, post},
|
||||
source::person::{
|
||||
Person,
|
||||
PersonFollower,
|
||||
PersonActions,
|
||||
PersonBlockForm,
|
||||
PersonFollowerForm,
|
||||
PersonInsertForm,
|
||||
PersonUpdateForm,
|
||||
},
|
||||
traits::{ApubActor, Crud, Followable},
|
||||
utils::{functions::lower, get_conn, now, uplete, DbPool},
|
||||
traits::{ApubActor, Blockable, Crud, Followable},
|
||||
utils::{functions::lower, get_conn, uplete, DbPool},
|
||||
};
|
||||
use chrono::Utc;
|
||||
use diesel::{
|
||||
dsl::{insert_into, not},
|
||||
dsl::{exists, insert_into, not, select},
|
||||
expression::SelectableHelper,
|
||||
result::Error,
|
||||
CombineDsl,
|
||||
ExpressionMethods,
|
||||
JoinOnDsl,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::{
|
||||
error::{LemmyErrorType, LemmyResult},
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
settings::structs::Settings,
|
||||
};
|
||||
use url::Url;
|
||||
|
@ -202,11 +202,12 @@ impl ApubActor for Person {
|
|||
}
|
||||
}
|
||||
|
||||
impl Followable for PersonFollower {
|
||||
impl Followable for PersonActions {
|
||||
type Form = PersonFollowerForm;
|
||||
async fn follow(pool: &mut DbPool<'_>, form: &PersonFollowerForm) -> Result<Self, Error> {
|
||||
type IdType = PersonId;
|
||||
|
||||
async fn follow(pool: &mut DbPool<'_>, form: &PersonFollowerForm) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let form = (form, person_actions::followed.eq(now().nullable()));
|
||||
insert_into(person_actions::table)
|
||||
.values(form)
|
||||
.on_conflict((person_actions::person_id, person_actions::target_id))
|
||||
|
@ -215,27 +216,96 @@ impl Followable for PersonFollower {
|
|||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityFollowerAlreadyExists)
|
||||
}
|
||||
|
||||
/// Currently no user following
|
||||
async fn follow_accepted(_: &mut DbPool<'_>, _: CommunityId, _: PersonId) -> Result<Self, Error> {
|
||||
Err(Error::NotFound)
|
||||
async fn follow_accepted(_: &mut DbPool<'_>, _: CommunityId, _: PersonId) -> LemmyResult<Self> {
|
||||
Err(LemmyErrorType::NotFound.into())
|
||||
}
|
||||
|
||||
async fn unfollow(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &PersonFollowerForm,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
person_id: PersonId,
|
||||
target_id: Self::IdType,
|
||||
) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(person_actions::table.find((form.follower_id, form.person_id)))
|
||||
uplete::new(person_actions::table.find((person_id, target_id)))
|
||||
.set_null(person_actions::followed)
|
||||
.set_null(person_actions::follow_pending)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CommunityFollowerAlreadyExists)
|
||||
}
|
||||
}
|
||||
|
||||
impl PersonFollower {
|
||||
impl Blockable for PersonActions {
|
||||
type Form = PersonBlockForm;
|
||||
type ObjectIdType = PersonId;
|
||||
type ObjectType = Person;
|
||||
|
||||
async fn block(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(person_actions::table)
|
||||
.values(form)
|
||||
.on_conflict((person_actions::person_id, person_actions::target_id))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::PersonBlockAlreadyExists)
|
||||
}
|
||||
|
||||
async fn unblock(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(person_actions::table.find((form.person_id, form.target_id)))
|
||||
.set_null(person_actions::blocked)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::PersonBlockAlreadyExists)
|
||||
}
|
||||
|
||||
async fn read_block(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
recipient_id: Self::ObjectIdType,
|
||||
) -> LemmyResult<()> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let find_action = person_actions::table
|
||||
.find((person_id, recipient_id))
|
||||
.filter(person_actions::blocked.is_not_null());
|
||||
|
||||
select(not(exists(find_action)))
|
||||
.get_result::<bool>(conn)
|
||||
.await?
|
||||
.then_some(())
|
||||
.ok_or(LemmyErrorType::PersonIsBlocked.into())
|
||||
}
|
||||
|
||||
async fn read_blocks_for_person(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
) -> Result<Vec<Self::ObjectType>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let target_person_alias = diesel::alias!(person as person1);
|
||||
|
||||
person_actions::table
|
||||
.filter(person_actions::blocked.is_not_null())
|
||||
.inner_join(person::table.on(person_actions::person_id.eq(person::id)))
|
||||
.inner_join(
|
||||
target_person_alias.on(person_actions::target_id.eq(target_person_alias.field(person::id))),
|
||||
)
|
||||
.select(target_person_alias.fields(person::all_columns))
|
||||
.filter(person_actions::person_id.eq(person_id))
|
||||
.filter(target_person_alias.field(person::deleted).eq(false))
|
||||
.order_by(person_actions::blocked)
|
||||
.load::<Person>(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl PersonActions {
|
||||
pub async fn list_followers(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_person_id: PersonId,
|
||||
|
@ -256,16 +326,15 @@ mod tests {
|
|||
|
||||
use crate::{
|
||||
source::{
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm, CommentUpdateForm},
|
||||
comment::{Comment, CommentActions, CommentInsertForm, CommentLikeForm, CommentUpdateForm},
|
||||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
person::{Person, PersonFollower, PersonFollowerForm, PersonInsertForm, PersonUpdateForm},
|
||||
post::{Post, PostInsertForm, PostLike, PostLikeForm},
|
||||
person::{Person, PersonActions, PersonFollowerForm, PersonInsertForm, PersonUpdateForm},
|
||||
post::{Post, PostActions, PostInsertForm, PostLikeForm},
|
||||
},
|
||||
traits::{Crud, Followable, Likeable},
|
||||
utils::{build_db_pool_for_tests, uplete},
|
||||
};
|
||||
use diesel::result::Error;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
@ -340,20 +409,17 @@ mod tests {
|
|||
let person_form_2 = PersonInsertForm::test_form(inserted_instance.id, "michele");
|
||||
let person_2 = Person::create(pool, &person_form_2).await?;
|
||||
|
||||
let follow_form = PersonFollowerForm {
|
||||
person_id: person_1.id,
|
||||
follower_id: person_2.id,
|
||||
pending: false,
|
||||
};
|
||||
let person_follower = PersonFollower::follow(pool, &follow_form).await?;
|
||||
assert_eq!(person_1.id, person_follower.person_id);
|
||||
assert_eq!(person_2.id, person_follower.follower_id);
|
||||
assert!(!person_follower.pending);
|
||||
let follow_form = PersonFollowerForm::new(person_1.id, person_2.id, false);
|
||||
let person_follower = PersonActions::follow(pool, &follow_form).await?;
|
||||
assert_eq!(person_1.id, person_follower.target_id);
|
||||
assert_eq!(person_2.id, person_follower.person_id);
|
||||
assert!(person_follower.follow_pending.is_some_and(|x| !x));
|
||||
|
||||
let followers = PersonFollower::list_followers(pool, person_1.id).await?;
|
||||
let followers = PersonActions::list_followers(pool, person_1.id).await?;
|
||||
assert_eq!(vec![person_2], followers);
|
||||
|
||||
let unfollow = PersonFollower::unfollow(pool, &follow_form).await?;
|
||||
let unfollow =
|
||||
PersonActions::unfollow(pool, follow_form.person_id, follow_form.target_id).await?;
|
||||
assert_eq!(uplete::Count::only_deleted(1), unfollow);
|
||||
|
||||
Ok(())
|
||||
|
@ -361,7 +427,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_aggregates() -> Result<(), Error> {
|
||||
async fn test_aggregates() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests();
|
||||
let pool = &mut pool.into();
|
||||
|
||||
|
@ -392,7 +458,7 @@ mod tests {
|
|||
let inserted_post = Post::create(pool, &new_post).await?;
|
||||
|
||||
let post_like = PostLikeForm::new(inserted_post.id, inserted_person.id, 1);
|
||||
let _inserted_post_like = PostLike::like(pool, &post_like).await?;
|
||||
let _inserted_post_like = PostActions::like(pool, &post_like).await?;
|
||||
|
||||
let comment_form = CommentInsertForm::new(
|
||||
inserted_person.id,
|
||||
|
@ -401,13 +467,9 @@ mod tests {
|
|||
);
|
||||
let inserted_comment = Comment::create(pool, &comment_form, None).await?;
|
||||
|
||||
let mut comment_like = CommentLikeForm {
|
||||
comment_id: inserted_comment.id,
|
||||
person_id: inserted_person.id,
|
||||
score: 1,
|
||||
};
|
||||
let mut comment_like = CommentLikeForm::new(inserted_person.id, inserted_comment.id, 1);
|
||||
|
||||
let _inserted_comment_like = CommentLike::like(pool, &comment_like).await?;
|
||||
let _inserted_comment_like = CommentActions::like(pool, &comment_like).await?;
|
||||
|
||||
let child_comment_form = CommentInsertForm::new(
|
||||
inserted_person.id,
|
||||
|
@ -417,13 +479,10 @@ mod tests {
|
|||
let inserted_child_comment =
|
||||
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path)).await?;
|
||||
|
||||
let child_comment_like = CommentLikeForm {
|
||||
comment_id: inserted_child_comment.id,
|
||||
person_id: another_inserted_person.id,
|
||||
score: 1,
|
||||
};
|
||||
let child_comment_like =
|
||||
CommentLikeForm::new(another_inserted_person.id, inserted_child_comment.id, 1);
|
||||
|
||||
let _inserted_child_comment_like = CommentLike::like(pool, &child_comment_like).await?;
|
||||
let _inserted_child_comment_like = CommentActions::like(pool, &child_comment_like).await?;
|
||||
|
||||
let person_aggregates_before_delete = Person::read(pool, inserted_person.id).await?;
|
||||
|
||||
|
@ -433,7 +492,7 @@ mod tests {
|
|||
assert_eq!(2, person_aggregates_before_delete.comment_score);
|
||||
|
||||
// Remove a post like
|
||||
PostLike::remove(pool, inserted_person.id, inserted_post.id).await?;
|
||||
PostActions::remove_like(pool, inserted_person.id, inserted_post.id).await?;
|
||||
let after_post_like_remove = Person::read(pool, inserted_person.id).await?;
|
||||
assert_eq!(0, after_post_like_remove.post_score);
|
||||
|
||||
|
@ -474,7 +533,7 @@ mod tests {
|
|||
let _new_child_comment =
|
||||
Comment::create(pool, &child_comment_form, Some(&new_parent_comment.path)).await?;
|
||||
comment_like.comment_id = new_parent_comment.id;
|
||||
CommentLike::like(pool, &comment_like).await?;
|
||||
CommentActions::like(pool, &comment_like).await?;
|
||||
let after_comment_add = Person::read(pool, inserted_person.id).await?;
|
||||
assert_eq!(2, after_comment_add.comment_count);
|
||||
// TODO: fix person aggregate comment score calculation
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
use crate::{
|
||||
newtypes::PersonId,
|
||||
schema::{person, person_actions},
|
||||
source::{
|
||||
person::Person,
|
||||
person_block::{PersonBlock, PersonBlockForm},
|
||||
},
|
||||
traits::Blockable,
|
||||
utils::{get_conn, now, uplete, DbPool},
|
||||
};
|
||||
use diesel::{
|
||||
dsl::{exists, insert_into, not},
|
||||
expression::SelectableHelper,
|
||||
result::Error,
|
||||
select,
|
||||
ExpressionMethods,
|
||||
JoinOnDsl,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
||||
impl PersonBlock {
|
||||
pub async fn read(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_person_id: PersonId,
|
||||
for_recipient_id: PersonId,
|
||||
) -> LemmyResult<()> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let find_action = person_actions::table
|
||||
.find((for_person_id, for_recipient_id))
|
||||
.filter(person_actions::blocked.is_not_null());
|
||||
select(not(exists(find_action)))
|
||||
.get_result::<bool>(conn)
|
||||
.await?
|
||||
.then_some(())
|
||||
.ok_or(LemmyErrorType::PersonIsBlocked.into())
|
||||
}
|
||||
|
||||
pub async fn for_person(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
) -> Result<Vec<Person>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let target_person_alias = diesel::alias!(person as person1);
|
||||
|
||||
person_actions::table
|
||||
.filter(person_actions::blocked.is_not_null())
|
||||
.inner_join(person::table.on(person_actions::person_id.eq(person::id)))
|
||||
.inner_join(
|
||||
target_person_alias.on(person_actions::target_id.eq(target_person_alias.field(person::id))),
|
||||
)
|
||||
.select(target_person_alias.fields(person::all_columns))
|
||||
.filter(person_actions::person_id.eq(person_id))
|
||||
.filter(target_person_alias.field(person::deleted).eq(false))
|
||||
.order_by(person_actions::blocked)
|
||||
.load::<Person>(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl Blockable for PersonBlock {
|
||||
type Form = PersonBlockForm;
|
||||
async fn block(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_block_form: &PersonBlockForm,
|
||||
) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let person_block_form = (
|
||||
person_block_form,
|
||||
person_actions::blocked.eq(now().nullable()),
|
||||
);
|
||||
insert_into(person_actions::table)
|
||||
.values(person_block_form)
|
||||
.on_conflict((person_actions::person_id, person_actions::target_id))
|
||||
.do_update()
|
||||
.set(person_block_form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
async fn unblock(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_block_form: &Self::Form,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(
|
||||
person_actions::table.find((person_block_form.person_id, person_block_form.target_id)),
|
||||
)
|
||||
.set_null(person_actions::blocked)
|
||||
.get_result(conn)
|
||||
.await
|
||||
}
|
||||
}
|
|
@ -3,19 +3,17 @@ use crate::{
|
|||
schema::{community, person, post, post_actions},
|
||||
source::post::{
|
||||
Post,
|
||||
PostActions,
|
||||
PostActionsCursor,
|
||||
PostHide,
|
||||
PostHideForm,
|
||||
PostInsertForm,
|
||||
PostLike,
|
||||
PostLikeForm,
|
||||
PostRead,
|
||||
PostReadCommentsForm,
|
||||
PostReadForm,
|
||||
PostSaved,
|
||||
PostSavedForm,
|
||||
PostUpdateForm,
|
||||
},
|
||||
traits::{Crud, Likeable, Saveable},
|
||||
traits::{Crud, Hideable, Likeable, ReadComments, Readable, Saveable},
|
||||
utils::{
|
||||
functions::{coalesce, hot_rank, scaled_rank},
|
||||
get_conn,
|
||||
|
@ -323,95 +321,85 @@ impl Post {
|
|||
}
|
||||
}
|
||||
|
||||
impl Likeable for PostLike {
|
||||
impl Likeable for PostActions {
|
||||
type Form = PostLikeForm;
|
||||
type IdType = PostId;
|
||||
async fn like(pool: &mut DbPool<'_>, post_like_form: &PostLikeForm) -> Result<Self, Error> {
|
||||
|
||||
async fn like(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(post_actions::table)
|
||||
.values(post_like_form)
|
||||
.values(form)
|
||||
.on_conflict((post_actions::post_id, post_actions::person_id))
|
||||
.do_update()
|
||||
.set(post_like_form)
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikePost)
|
||||
}
|
||||
async fn remove(
|
||||
async fn remove_like(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
post_id: PostId,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
post_id: Self::IdType,
|
||||
) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(post_actions::table.find((person_id, post_id)))
|
||||
.set_null(post_actions::like_score)
|
||||
.set_null(post_actions::liked)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikePost)
|
||||
}
|
||||
}
|
||||
|
||||
impl Saveable for PostSaved {
|
||||
impl Saveable for PostActions {
|
||||
type Form = PostSavedForm;
|
||||
async fn save(pool: &mut DbPool<'_>, post_saved_form: &PostSavedForm) -> Result<Self, Error> {
|
||||
async fn save(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(post_actions::table)
|
||||
.values(post_saved_form)
|
||||
.values(form)
|
||||
.on_conflict((post_actions::post_id, post_actions::person_id))
|
||||
.do_update()
|
||||
.set(post_saved_form)
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntSavePost)
|
||||
}
|
||||
async fn unsave(
|
||||
pool: &mut DbPool<'_>,
|
||||
post_saved_form: &PostSavedForm,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
async fn unsave(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
uplete::new(post_actions::table.find((post_saved_form.person_id, post_saved_form.post_id)))
|
||||
uplete::new(post_actions::table.find((form.person_id, form.post_id)))
|
||||
.set_null(post_actions::saved)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntSavePost)
|
||||
}
|
||||
}
|
||||
|
||||
impl PostRead {
|
||||
pub async fn mark_as_read(
|
||||
pool: &mut DbPool<'_>,
|
||||
post_read_form: &PostReadForm,
|
||||
) -> LemmyResult<usize> {
|
||||
Self::mark_many_as_read(pool, &[post_read_form.post_id], post_read_form.person_id).await
|
||||
impl Readable for PostActions {
|
||||
type Form = PostReadForm;
|
||||
|
||||
async fn mark_as_read(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<usize> {
|
||||
Self::mark_many_as_read(pool, &[form.clone()]).await
|
||||
}
|
||||
|
||||
pub async fn mark_as_unread(
|
||||
pool: &mut DbPool<'_>,
|
||||
post_read_form: &PostReadForm,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
async fn mark_as_unread(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
uplete::new(
|
||||
post_actions::table
|
||||
.filter(post_actions::post_id.eq(post_read_form.post_id))
|
||||
.filter(post_actions::person_id.eq(post_read_form.person_id)),
|
||||
.filter(post_actions::post_id.eq(form.post_id))
|
||||
.filter(post_actions::person_id.eq(form.person_id)),
|
||||
)
|
||||
.set_null(post_actions::read)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntMarkPostAsRead)
|
||||
}
|
||||
|
||||
pub async fn mark_many_as_read(
|
||||
pool: &mut DbPool<'_>,
|
||||
post_ids: &[PostId],
|
||||
person_id: PersonId,
|
||||
) -> LemmyResult<usize> {
|
||||
async fn mark_many_as_read(pool: &mut DbPool<'_>, forms: &[Self::Form]) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
let forms = post_ids
|
||||
.iter()
|
||||
.map(|post_id| (PostReadForm::new(*post_id, person_id)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
insert_into(post_actions::table)
|
||||
.values(forms)
|
||||
.on_conflict((post_actions::person_id, post_actions::post_id))
|
||||
|
@ -423,39 +411,79 @@ impl PostRead {
|
|||
}
|
||||
}
|
||||
|
||||
impl PostHide {
|
||||
pub async fn hide(
|
||||
pool: &mut DbPool<'_>,
|
||||
post_id: PostId,
|
||||
person_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
impl Hideable for PostActions {
|
||||
type Form = PostHideForm;
|
||||
async fn hide(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
let form = &PostHideForm::new(post_id, person_id);
|
||||
insert_into(post_actions::table)
|
||||
.values(form)
|
||||
.on_conflict((post_actions::person_id, post_actions::post_id))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.execute(conn)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntHidePost)
|
||||
}
|
||||
|
||||
pub async fn unhide(
|
||||
pool: &mut DbPool<'_>,
|
||||
post_id_: PostId,
|
||||
person_id_: PersonId,
|
||||
) -> Result<uplete::Count, Error> {
|
||||
async fn unhide(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
uplete::new(
|
||||
post_actions::table
|
||||
.filter(post_actions::post_id.eq(post_id_))
|
||||
.filter(post_actions::person_id.eq(person_id_)),
|
||||
.filter(post_actions::post_id.eq(form.post_id))
|
||||
.filter(post_actions::person_id.eq(form.person_id)),
|
||||
)
|
||||
.set_null(post_actions::hidden)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntHidePost)
|
||||
}
|
||||
}
|
||||
|
||||
impl ReadComments for PostActions {
|
||||
type Form = PostReadCommentsForm;
|
||||
type IdType = PostId;
|
||||
|
||||
async fn update_read_comments(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
insert_into(post_actions::table)
|
||||
.values(form)
|
||||
.on_conflict((post_actions::person_id, post_actions::post_id))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateReadComments)
|
||||
}
|
||||
|
||||
async fn remove_read_comments(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
post_id: Self::IdType,
|
||||
) -> LemmyResult<uplete::Count> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
uplete::new(
|
||||
post_actions::table
|
||||
.filter(post_actions::post_id.eq(post_id))
|
||||
.filter(post_actions::person_id.eq(person_id)),
|
||||
)
|
||||
.set_null(post_actions::read_comments_amount)
|
||||
.set_null(post_actions::read_comments)
|
||||
.get_result(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateReadComments)
|
||||
}
|
||||
}
|
||||
|
||||
impl PostActions {
|
||||
pub fn build_many_read_forms(post_ids: &[PostId], person_id: PersonId) -> Vec<PostReadForm> {
|
||||
post_ids
|
||||
.iter()
|
||||
.map(|post_id| (PostReadForm::new(*post_id, person_id)))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -499,17 +527,15 @@ mod tests {
|
|||
person::{Person, PersonInsertForm},
|
||||
post::{
|
||||
Post,
|
||||
PostActions,
|
||||
PostInsertForm,
|
||||
PostLike,
|
||||
PostLikeForm,
|
||||
PostRead,
|
||||
PostReadForm,
|
||||
PostSaved,
|
||||
PostSavedForm,
|
||||
PostUpdateForm,
|
||||
},
|
||||
},
|
||||
traits::{Crud, Likeable, Saveable},
|
||||
traits::{Crud, Likeable, Readable, Saveable},
|
||||
utils::{build_db_pool_for_tests, uplete, RANK_DEFAULT},
|
||||
};
|
||||
use chrono::DateTime;
|
||||
|
@ -603,31 +629,20 @@ mod tests {
|
|||
// Post Like
|
||||
let post_like_form = PostLikeForm::new(inserted_post.id, inserted_person.id, 1);
|
||||
|
||||
let inserted_post_like = PostLike::like(pool, &post_like_form).await?;
|
||||
|
||||
let expected_post_like = PostLike {
|
||||
post_id: inserted_post.id,
|
||||
person_id: inserted_person.id,
|
||||
published: inserted_post_like.published,
|
||||
score: 1,
|
||||
};
|
||||
let inserted_post_like = PostActions::like(pool, &post_like_form).await?;
|
||||
assert_eq!(Some(1), inserted_post_like.like_score);
|
||||
|
||||
// Post Save
|
||||
let post_saved_form = PostSavedForm::new(inserted_post.id, inserted_person.id);
|
||||
|
||||
let inserted_post_saved = PostSaved::save(pool, &post_saved_form).await?;
|
||||
|
||||
let expected_post_saved = PostSaved {
|
||||
post_id: inserted_post.id,
|
||||
person_id: inserted_person.id,
|
||||
published: inserted_post_saved.published,
|
||||
};
|
||||
let inserted_post_saved = PostActions::save(pool, &post_saved_form).await?;
|
||||
assert!(inserted_post_saved.saved.is_some());
|
||||
|
||||
// Mark 2 posts as read
|
||||
let post_read_form_1 = PostReadForm::new(inserted_post.id, inserted_person.id);
|
||||
PostRead::mark_as_read(pool, &post_read_form_1).await?;
|
||||
PostActions::mark_as_read(pool, &post_read_form_1).await?;
|
||||
let post_read_form_2 = PostReadForm::new(inserted_post2.id, inserted_person.id);
|
||||
PostRead::mark_as_read(pool, &post_read_form_2).await?;
|
||||
PostActions::mark_as_read(pool, &post_read_form_2).await?;
|
||||
|
||||
let read_post = Post::read(pool, inserted_post.id).await?;
|
||||
|
||||
|
@ -641,17 +656,17 @@ mod tests {
|
|||
let scheduled_post_count = Post::user_scheduled_post_count(inserted_person.id, pool).await?;
|
||||
assert_eq!(1, scheduled_post_count);
|
||||
|
||||
let like_removed = PostLike::remove(pool, inserted_person.id, inserted_post.id).await?;
|
||||
let like_removed = PostActions::remove_like(pool, inserted_person.id, inserted_post.id).await?;
|
||||
assert_eq!(uplete::Count::only_updated(1), like_removed);
|
||||
let saved_removed = PostSaved::unsave(pool, &post_saved_form).await?;
|
||||
let saved_removed = PostActions::unsave(pool, &post_saved_form).await?;
|
||||
assert_eq!(uplete::Count::only_updated(1), saved_removed);
|
||||
|
||||
let read_remove_form_1 = PostReadForm::new(inserted_post.id, inserted_person.id);
|
||||
let read_removed_1 = PostRead::mark_as_unread(pool, &read_remove_form_1).await?;
|
||||
let read_removed_1 = PostActions::mark_as_unread(pool, &read_remove_form_1).await?;
|
||||
assert_eq!(uplete::Count::only_deleted(1), read_removed_1);
|
||||
|
||||
let read_remove_form_2 = PostReadForm::new(inserted_post2.id, inserted_person.id);
|
||||
let read_removed_2 = PostRead::mark_as_unread(pool, &read_remove_form_2).await?;
|
||||
let read_removed_2 = PostActions::mark_as_unread(pool, &read_remove_form_2).await?;
|
||||
assert_eq!(uplete::Count::only_deleted(1), read_removed_2);
|
||||
|
||||
let num_deleted = Post::delete(pool, inserted_post.id).await?
|
||||
|
@ -665,15 +680,13 @@ mod tests {
|
|||
|
||||
assert_eq!(expected_post, read_post);
|
||||
assert_eq!(expected_post, updated_post);
|
||||
assert_eq!(expected_post_like, inserted_post_like);
|
||||
assert_eq!(expected_post_saved, inserted_post_saved);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_aggregates() -> Result<(), Error> {
|
||||
async fn test_aggregates() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests();
|
||||
let pool = &mut pool.into();
|
||||
|
||||
|
@ -719,7 +732,7 @@ mod tests {
|
|||
|
||||
let post_like = PostLikeForm::new(inserted_post.id, inserted_person.id, 1);
|
||||
|
||||
PostLike::like(pool, &post_like).await?;
|
||||
PostActions::like(pool, &post_like).await?;
|
||||
|
||||
let post_aggs_before_delete = Post::read(pool, inserted_post.id).await?;
|
||||
|
||||
|
@ -731,7 +744,7 @@ mod tests {
|
|||
// Add a post dislike from the other person
|
||||
let post_dislike = PostLikeForm::new(inserted_post.id, another_inserted_person.id, -1);
|
||||
|
||||
PostLike::like(pool, &post_dislike).await?;
|
||||
PostActions::like(pool, &post_dislike).await?;
|
||||
|
||||
let post_aggs_after_dislike = Post::read(pool, inserted_post.id).await?;
|
||||
|
||||
|
@ -750,7 +763,7 @@ mod tests {
|
|||
assert_eq!(1, after_comment_delete.downvotes);
|
||||
|
||||
// Remove the first post like
|
||||
PostLike::remove(pool, inserted_person.id, inserted_post.id).await?;
|
||||
PostActions::remove_like(pool, inserted_person.id, inserted_post.id).await?;
|
||||
let after_like_remove = Post::read(pool, inserted_post.id).await?;
|
||||
assert_eq!(0, after_like_remove.comments);
|
||||
assert_eq!(-1, after_like_remove.score);
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
use crate::{
|
||||
diesel::OptionalExtension,
|
||||
newtypes::{PersonId, PostId},
|
||||
schema::post_actions,
|
||||
source::post_actions::{PostActions, PostActionsForm},
|
||||
utils::{get_conn, now, DbPool},
|
||||
};
|
||||
use diesel::{
|
||||
expression::SelectableHelper,
|
||||
insert_into,
|
||||
result::Error,
|
||||
ExpressionMethods,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
|
||||
impl PostActions {
|
||||
pub async fn upsert(pool: &mut DbPool<'_>, form: &PostActionsForm) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let form = (form, post_actions::read_comments.eq(now().nullable()));
|
||||
insert_into(post_actions::table)
|
||||
.values(form)
|
||||
.on_conflict((post_actions::person_id, post_actions::post_id))
|
||||
.do_update()
|
||||
.set(form)
|
||||
.returning(Self::as_select())
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
pub async fn read(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id_: PersonId,
|
||||
post_id_: PostId,
|
||||
) -> Result<Option<Self>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
post_actions::table
|
||||
.find((person_id_, post_id_))
|
||||
.filter(post_actions::read_comments.is_not_null())
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await
|
||||
.optional()
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
use crate::{
|
||||
diesel::BoolExpressionMethods,
|
||||
newtypes::{PersonId, PostId, PostReportId},
|
||||
schema::post_report,
|
||||
source::post_report::{PostReport, PostReportForm},
|
||||
|
@ -9,31 +8,32 @@ use crate::{
|
|||
use chrono::Utc;
|
||||
use diesel::{
|
||||
dsl::{insert_into, update},
|
||||
result::Error,
|
||||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
|
||||
impl Reportable for PostReport {
|
||||
type Form = PostReportForm;
|
||||
type IdType = PostReportId;
|
||||
type ObjectIdType = PostId;
|
||||
|
||||
async fn report(pool: &mut DbPool<'_>, post_report_form: &PostReportForm) -> Result<Self, Error> {
|
||||
async fn report(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(post_report::table)
|
||||
.values(post_report_form)
|
||||
.values(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreateReport)
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
pool: &mut DbPool<'_>,
|
||||
report_id: Self::IdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(post_report::table.find(report_id))
|
||||
.set((
|
||||
|
@ -43,6 +43,7 @@ impl Reportable for PostReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
|
||||
async fn resolve_apub(
|
||||
|
@ -52,29 +53,28 @@ impl Reportable for PostReport {
|
|||
resolver_id: PersonId,
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
Ok(
|
||||
update(
|
||||
post_report::table.filter(
|
||||
post_report::post_id
|
||||
.eq(object_id)
|
||||
.and(post_report::creator_id.eq(report_creator_id)),
|
||||
),
|
||||
)
|
||||
.set((
|
||||
post_report::resolved.eq(true),
|
||||
post_report::resolver_id.eq(resolver_id),
|
||||
post_report::updated.eq(Utc::now()),
|
||||
))
|
||||
.execute(conn)
|
||||
.await?,
|
||||
update(
|
||||
post_report::table.filter(
|
||||
post_report::post_id
|
||||
.eq(object_id)
|
||||
.and(post_report::creator_id.eq(report_creator_id)),
|
||||
),
|
||||
)
|
||||
.set((
|
||||
post_report::resolved.eq(true),
|
||||
post_report::resolver_id.eq(resolver_id),
|
||||
post_report::updated.eq(Utc::now()),
|
||||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
|
||||
async fn resolve_all_for_object(
|
||||
pool: &mut DbPool<'_>,
|
||||
post_id_: PostId,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(post_report::table.filter(post_report::post_id.eq(post_id_)))
|
||||
.set((
|
||||
|
@ -84,13 +84,14 @@ impl Reportable for PostReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
|
||||
async fn unresolve(
|
||||
pool: &mut DbPool<'_>,
|
||||
report_id: Self::IdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(post_report::table.find(report_id))
|
||||
.set((
|
||||
|
@ -100,6 +101,7 @@ impl Reportable for PostReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,10 +119,9 @@ mod tests {
|
|||
traits::Crud,
|
||||
utils::build_db_pool_for_tests,
|
||||
};
|
||||
use diesel::result::Error;
|
||||
use serial_test::serial;
|
||||
|
||||
async fn init(pool: &mut DbPool<'_>) -> Result<(Person, PostReport), Error> {
|
||||
async fn init(pool: &mut DbPool<'_>) -> LemmyResult<(Person, PostReport)> {
|
||||
let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?;
|
||||
let person_form = PersonInsertForm::test_form(inserted_instance.id, "jim");
|
||||
let person = Person::create(pool, &person_form).await?;
|
||||
|
@ -149,7 +150,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_resolve_post_report() -> Result<(), Error> {
|
||||
async fn test_resolve_post_report() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests();
|
||||
let pool = &mut pool.into();
|
||||
|
||||
|
@ -169,7 +170,7 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_resolve_all_post_reports() -> Result<(), Error> {
|
||||
async fn test_resolve_all_post_reports() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests();
|
||||
let pool = &mut pool.into();
|
||||
|
||||
|
|
|
@ -8,34 +8,31 @@ use crate::{
|
|||
use chrono::Utc;
|
||||
use diesel::{
|
||||
dsl::{insert_into, update},
|
||||
result::Error,
|
||||
ExpressionMethods,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::error::{FederationError, LemmyResult};
|
||||
use lemmy_utils::error::{FederationError, LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
|
||||
impl Reportable for PrivateMessageReport {
|
||||
type Form = PrivateMessageReportForm;
|
||||
type IdType = PrivateMessageReportId;
|
||||
type ObjectIdType = PrivateMessageId;
|
||||
|
||||
async fn report(
|
||||
pool: &mut DbPool<'_>,
|
||||
pm_report_form: &PrivateMessageReportForm,
|
||||
) -> Result<Self, Error> {
|
||||
async fn report(pool: &mut DbPool<'_>, form: &Self::Form) -> LemmyResult<Self> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(private_message_report)
|
||||
.values(pm_report_form)
|
||||
.values(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreateReport)
|
||||
}
|
||||
|
||||
async fn resolve(
|
||||
pool: &mut DbPool<'_>,
|
||||
report_id: Self::IdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(private_message_report.find(report_id))
|
||||
.set((
|
||||
|
@ -45,6 +42,7 @@ impl Reportable for PrivateMessageReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
async fn resolve_apub(
|
||||
_pool: &mut DbPool<'_>,
|
||||
|
@ -60,15 +58,15 @@ impl Reportable for PrivateMessageReport {
|
|||
_pool: &mut DbPool<'_>,
|
||||
_pm_id_: PrivateMessageId,
|
||||
_by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
Err(Error::NotFound)
|
||||
) -> LemmyResult<usize> {
|
||||
Err(LemmyErrorType::NotFound.into())
|
||||
}
|
||||
|
||||
async fn unresolve(
|
||||
pool: &mut DbPool<'_>,
|
||||
report_id: Self::IdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
) -> LemmyResult<usize> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
update(private_message_report.find(report_id))
|
||||
.set((
|
||||
|
@ -78,5 +76,6 @@ impl Reportable for PrivateMessageReport {
|
|||
))
|
||||
.execute(conn)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntResolveReport)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,11 @@ pub mod schema_setup;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumString};
|
||||
#[cfg(feature = "full")]
|
||||
use {diesel::query_source::AliasedField, schema::person, ts_rs::TS};
|
||||
use {
|
||||
diesel::query_source::AliasedField,
|
||||
schema::{community_actions, person},
|
||||
ts_rs::TS,
|
||||
};
|
||||
|
||||
#[derive(
|
||||
EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default, Hash,
|
||||
|
@ -178,17 +182,6 @@ pub enum SearchType {
|
|||
Users,
|
||||
}
|
||||
|
||||
#[derive(EnumString, Display, Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Copy, Hash)]
|
||||
#[cfg_attr(feature = "full", derive(TS))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
/// A type / status for a community subscribe.
|
||||
pub enum SubscribedType {
|
||||
Subscribed,
|
||||
NotSubscribed,
|
||||
Pending,
|
||||
ApprovalRequired,
|
||||
}
|
||||
|
||||
#[derive(EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "full", derive(TS))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
|
@ -277,7 +270,7 @@ pub enum CommunityVisibility {
|
|||
/// Public community, any local or federated user can interact.
|
||||
#[default]
|
||||
Public,
|
||||
/// Community is hidden and doesn't appear in community list. Post from the community
|
||||
/// Community is unlisted/hidden and doesn't appear in community list. Posts from the community
|
||||
/// are not shown in Local and All feeds, except for subscribed users.
|
||||
Unlisted,
|
||||
/// Unfederated community, only local users can interact (with or without login).
|
||||
|
@ -330,7 +323,7 @@ macro_rules! assert_length {
|
|||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
/// A helper tuple for person alias columns
|
||||
/// A helper tuple for person 1 alias columns
|
||||
pub type Person1AliasAllColumnsTuple = (
|
||||
AliasedField<aliases::Person1, person::id>,
|
||||
AliasedField<aliases::Person1, person::name>,
|
||||
|
@ -357,3 +350,46 @@ pub type Person1AliasAllColumnsTuple = (
|
|||
AliasedField<aliases::Person1, person::comment_count>,
|
||||
AliasedField<aliases::Person1, person::comment_score>,
|
||||
);
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
/// A helper tuple for person 2 alias columns
|
||||
pub type Person2AliasAllColumnsTuple = (
|
||||
AliasedField<aliases::Person2, person::id>,
|
||||
AliasedField<aliases::Person2, person::name>,
|
||||
AliasedField<aliases::Person2, person::display_name>,
|
||||
AliasedField<aliases::Person2, person::avatar>,
|
||||
AliasedField<aliases::Person2, person::banned>,
|
||||
AliasedField<aliases::Person2, person::published>,
|
||||
AliasedField<aliases::Person2, person::updated>,
|
||||
AliasedField<aliases::Person2, person::ap_id>,
|
||||
AliasedField<aliases::Person2, person::bio>,
|
||||
AliasedField<aliases::Person2, person::local>,
|
||||
AliasedField<aliases::Person2, person::private_key>,
|
||||
AliasedField<aliases::Person2, person::public_key>,
|
||||
AliasedField<aliases::Person2, person::last_refreshed_at>,
|
||||
AliasedField<aliases::Person2, person::banner>,
|
||||
AliasedField<aliases::Person2, person::deleted>,
|
||||
AliasedField<aliases::Person2, person::inbox_url>,
|
||||
AliasedField<aliases::Person2, person::matrix_user_id>,
|
||||
AliasedField<aliases::Person2, person::bot_account>,
|
||||
AliasedField<aliases::Person2, person::ban_expires>,
|
||||
AliasedField<aliases::Person2, person::instance_id>,
|
||||
AliasedField<aliases::Person2, person::post_count>,
|
||||
AliasedField<aliases::Person2, person::post_score>,
|
||||
AliasedField<aliases::Person2, person::comment_count>,
|
||||
AliasedField<aliases::Person2, person::comment_score>,
|
||||
);
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
/// A helper tuple for creator community actions
|
||||
pub type CreatorCommunityActionsAllColumnsTuple = (
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::community_id>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::person_id>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::followed>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::follow_state>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::follow_approver_id>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::blocked>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::became_moderator>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::received_ban>,
|
||||
AliasedField<aliases::CreatorCommunityActions, community_actions::ban_expires>,
|
||||
);
|
||||
|
|
|
@ -198,17 +198,17 @@ pub struct LtreeDef(pub String);
|
|||
#[cfg_attr(feature = "full", ts(export))]
|
||||
pub struct DbUrl(pub(crate) Box<Url>);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Default)]
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
/// The report combined id
|
||||
pub struct ReportCombinedId(i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Default)]
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
/// The person content combined id
|
||||
pub struct PersonContentCombinedId(i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Default)]
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
/// The person saved combined id
|
||||
pub struct PersonSavedCombinedId(i32);
|
||||
|
|
|
@ -4,8 +4,11 @@ use crate::schema::person_content_combined;
|
|||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use i_love_jesus::CursorKeysModule;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
#[skip_serializing_none]
|
||||
#[derive(PartialEq, Eq, Serialize, Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, CursorKeysModule)
|
||||
|
|
|
@ -4,8 +4,11 @@ use crate::schema::person_saved_combined;
|
|||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use i_love_jesus::CursorKeysModule;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
#[skip_serializing_none]
|
||||
#[derive(PartialEq, Eq, Serialize, Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, CursorKeysModule)
|
||||
|
|
|
@ -10,8 +10,11 @@ use crate::schema::report_combined;
|
|||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use i_love_jesus::CursorKeysModule;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
#[skip_serializing_none]
|
||||
#[derive(PartialEq, Eq, Serialize, Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, CursorKeysModule)
|
||||
|
|
|
@ -5,8 +5,6 @@ use crate::newtypes::{CommentId, DbUrl, LanguageId, PersonId, PostId};
|
|||
use crate::schema::{comment, comment_actions};
|
||||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use diesel::{dsl, expression_methods::NullableExpressionMethods};
|
||||
#[cfg(feature = "full")]
|
||||
use diesel_ltree::Ltree;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
|
@ -104,59 +102,48 @@ pub struct CommentUpdateForm {
|
|||
pub language_id: Option<LanguageId>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
#[skip_serializing_none]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, Associations)
|
||||
derive(Identifiable, Queryable, Selectable, Associations, TS)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::comment::Comment)))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = comment_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, comment_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct CommentLike {
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
pub struct CommentActions {
|
||||
pub person_id: PersonId,
|
||||
pub comment_id: CommentId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = comment_actions::like_score.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<comment_actions::like_score>))]
|
||||
pub score: i16,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = comment_actions::liked.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<comment_actions::liked>))]
|
||||
pub published: DateTime<Utc>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// The like / score for the comment.
|
||||
pub like_score: Option<i16>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the comment was liked.
|
||||
pub liked: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the comment was saved.
|
||||
pub saved: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = comment_actions))]
|
||||
pub struct CommentLikeForm {
|
||||
pub person_id: PersonId,
|
||||
pub comment_id: CommentId,
|
||||
#[cfg_attr(feature = "full", diesel(column_name = like_score))]
|
||||
pub score: i16,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, Associations)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::comment::Comment)))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = comment_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, comment_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct CommentSaved {
|
||||
pub comment_id: CommentId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = comment_actions::saved.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<comment_actions::saved>))]
|
||||
pub published: DateTime<Utc>,
|
||||
pub like_score: i16,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub liked: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = comment_actions))]
|
||||
#[derive(derive_new::new)]
|
||||
pub struct CommentSavedForm {
|
||||
pub comment_id: CommentId,
|
||||
pub person_id: PersonId,
|
||||
pub comment_id: CommentId,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub saved: DateTime<Utc>,
|
||||
}
|
||||
|
|
|
@ -7,8 +7,6 @@ use crate::{
|
|||
CommunityVisibility,
|
||||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use diesel::{dsl, expression_methods::NullableExpressionMethods};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
use strum::{Display, EnumString};
|
||||
|
@ -172,10 +170,11 @@ pub struct CommunityUpdateForm {
|
|||
pub description: Option<Option<String>>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[skip_serializing_none]
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, Associations)
|
||||
derive(Identifiable, Queryable, Selectable, Associations, TS)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
|
@ -184,52 +183,53 @@ pub struct CommunityUpdateForm {
|
|||
#[cfg_attr(feature = "full", diesel(table_name = community_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, community_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct CommunityModerator {
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
pub struct CommunityActions {
|
||||
pub community_id: CommunityId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = community_actions::became_moderator.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<community_actions::became_moderator>))]
|
||||
pub published: DateTime<Utc>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the community was followed.
|
||||
pub followed: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// The state of the community follow.
|
||||
pub follow_state: Option<CommunityFollowerState>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// The approver of the community follow.
|
||||
pub follow_approver_id: Option<PersonId>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the community was blocked.
|
||||
pub blocked: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When this user became a moderator.
|
||||
pub became_moderator: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When this user received a ban.
|
||||
pub received_ban: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When their ban expires.
|
||||
pub ban_expires: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = community_actions))]
|
||||
pub struct CommunityModeratorForm {
|
||||
pub community_id: CommunityId,
|
||||
pub person_id: PersonId,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub became_moderator: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, Associations)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
diesel(belongs_to(crate::source::community::Community))
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = community_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, community_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct CommunityPersonBan {
|
||||
pub community_id: CommunityId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = community_actions::received_ban.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<community_actions::received_ban>))]
|
||||
pub published: DateTime<Utc>,
|
||||
#[cfg_attr(feature = "full", diesel(column_name = ban_expires))]
|
||||
pub expires: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = community_actions))]
|
||||
pub struct CommunityPersonBanForm {
|
||||
pub community_id: CommunityId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(column_name = ban_expires))]
|
||||
pub expires: Option<Option<DateTime<Utc>>>,
|
||||
#[new(default)]
|
||||
pub ban_expires: Option<Option<DateTime<Utc>>>,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub received_ban: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -246,41 +246,25 @@ pub enum CommunityFollowerState {
|
|||
ApprovalRequired,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, Associations)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
diesel(belongs_to(crate::source::community::Community))
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = community_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, community_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct CommunityFollower {
|
||||
pub community_id: CommunityId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = community_actions::followed.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<community_actions::followed>))]
|
||||
pub published: DateTime<Utc>,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = community_actions::follow_state.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<community_actions::follow_state>))]
|
||||
pub state: CommunityFollowerState,
|
||||
#[cfg_attr(feature = "full", diesel(column_name = follow_approver_id))]
|
||||
pub approver_id: Option<PersonId>,
|
||||
}
|
||||
|
||||
#[derive(Clone, derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = community_actions))]
|
||||
pub struct CommunityFollowerForm {
|
||||
pub community_id: CommunityId,
|
||||
pub person_id: PersonId,
|
||||
pub follow_state: CommunityFollowerState,
|
||||
#[new(default)]
|
||||
#[cfg_attr(feature = "full", diesel(column_name = follow_state))]
|
||||
pub state: Option<CommunityFollowerState>,
|
||||
#[new(default)]
|
||||
#[cfg_attr(feature = "full", diesel(column_name = follow_approver_id))]
|
||||
pub approver_id: Option<PersonId>,
|
||||
pub follow_approver_id: Option<PersonId>,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub followed: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = community_actions))]
|
||||
pub struct CommunityBlockForm {
|
||||
pub community_id: CommunityId,
|
||||
pub person_id: PersonId,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub blocked: DateTime<Utc>,
|
||||
}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
use crate::newtypes::{CommunityId, PersonId};
|
||||
#[cfg(feature = "full")]
|
||||
use crate::schema::community_actions;
|
||||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use diesel::{dsl, expression_methods::NullableExpressionMethods};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Queryable, Selectable, Associations, Identifiable)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
diesel(belongs_to(crate::source::community::Community))
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = community_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, community_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct CommunityBlock {
|
||||
pub person_id: PersonId,
|
||||
pub community_id: CommunityId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = community_actions::blocked.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<community_actions::blocked>))]
|
||||
pub published: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = community_actions))]
|
||||
pub struct CommunityBlockForm {
|
||||
pub person_id: PersonId,
|
||||
pub community_id: CommunityId,
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use crate::newtypes::InstanceId;
|
||||
use crate::newtypes::{InstanceId, PersonId};
|
||||
#[cfg(feature = "full")]
|
||||
use crate::schema::instance;
|
||||
use crate::schema::{instance, instance_actions};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
|
@ -20,10 +20,13 @@ pub struct Instance {
|
|||
pub domain: String,
|
||||
pub published: DateTime<Utc>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the instance was updated.
|
||||
pub updated: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// The software of the instance.
|
||||
pub software: Option<String>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// The version of the instance's software.
|
||||
pub version: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -39,3 +42,34 @@ pub struct InstanceForm {
|
|||
#[new(default)]
|
||||
pub updated: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Queryable, Selectable, Associations, Identifiable, TS)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
diesel(belongs_to(crate::source::instance::Instance))
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = instance_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, instance_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
pub struct InstanceActions {
|
||||
pub person_id: PersonId,
|
||||
pub instance_id: InstanceId,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the instance was blocked.
|
||||
pub blocked: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = instance_actions))]
|
||||
pub struct InstanceBlockForm {
|
||||
pub person_id: PersonId,
|
||||
pub instance_id: InstanceId,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub blocked: DateTime<Utc>,
|
||||
}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
use crate::newtypes::{InstanceId, PersonId};
|
||||
#[cfg(feature = "full")]
|
||||
use crate::schema::instance_actions;
|
||||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use diesel::{dsl, expression_methods::NullableExpressionMethods};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Queryable, Selectable, Associations, Identifiable)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
diesel(belongs_to(crate::source::instance::Instance))
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = instance_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, instance_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct InstanceBlock {
|
||||
pub person_id: PersonId,
|
||||
pub instance_id: InstanceId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = instance_actions::blocked.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<instance_actions::blocked>))]
|
||||
pub published: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = instance_actions))]
|
||||
pub struct InstanceBlockForm {
|
||||
pub person_id: PersonId,
|
||||
pub instance_id: InstanceId,
|
||||
}
|
|
@ -10,7 +10,6 @@ pub mod comment;
|
|||
pub mod comment_reply;
|
||||
pub mod comment_report;
|
||||
pub mod community;
|
||||
pub mod community_block;
|
||||
pub mod community_report;
|
||||
pub mod custom_emoji;
|
||||
pub mod custom_emoji_keyword;
|
||||
|
@ -20,7 +19,6 @@ pub mod federation_blocklist;
|
|||
pub mod federation_queue_state;
|
||||
pub mod images;
|
||||
pub mod instance;
|
||||
pub mod instance_block;
|
||||
pub mod language;
|
||||
pub mod local_site;
|
||||
pub mod local_site_rate_limit;
|
||||
|
@ -32,11 +30,9 @@ pub mod oauth_account;
|
|||
pub mod oauth_provider;
|
||||
pub mod password_reset_request;
|
||||
pub mod person;
|
||||
pub mod person_block;
|
||||
pub mod person_comment_mention;
|
||||
pub mod person_post_mention;
|
||||
pub mod post;
|
||||
pub mod post_actions;
|
||||
pub mod post_report;
|
||||
pub mod private_message;
|
||||
pub mod private_message_report;
|
||||
|
|
|
@ -7,8 +7,6 @@ use crate::{
|
|||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use diesel::{dsl, expression_methods::NullableExpressionMethods};
|
||||
#[cfg(feature = "full")]
|
||||
use i_love_jesus::CursorKeysModule;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
|
@ -141,36 +139,47 @@ pub struct PersonUpdateForm {
|
|||
pub ban_expires: Option<Option<DateTime<Utc>>>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[skip_serializing_none]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, Associations)
|
||||
derive(Identifiable, Queryable, Selectable, Associations, TS)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = person_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, target_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct PersonFollower {
|
||||
#[cfg_attr(feature = "full", diesel(column_name = target_id))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
pub struct PersonActions {
|
||||
pub target_id: PersonId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(column_name = person_id))]
|
||||
pub follower_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = person_actions::followed.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<person_actions::followed>))]
|
||||
pub published: DateTime<Utc>,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = person_actions::follow_pending.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<person_actions::follow_pending>))]
|
||||
pub pending: bool,
|
||||
#[serde(skip)]
|
||||
pub followed: Option<DateTime<Utc>>,
|
||||
#[serde(skip)]
|
||||
pub follow_pending: Option<bool>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the person was blocked.
|
||||
pub blocked: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = person_actions))]
|
||||
pub struct PersonFollowerForm {
|
||||
#[cfg_attr(feature = "full", diesel(column_name = target_id))]
|
||||
pub target_id: PersonId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(column_name = person_id))]
|
||||
pub follower_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(column_name = follow_pending))]
|
||||
pub pending: bool,
|
||||
pub follow_pending: bool,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub followed: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = person_actions))]
|
||||
pub struct PersonBlockForm {
|
||||
// This order is switched so blocks can work the same.
|
||||
pub person_id: PersonId,
|
||||
pub target_id: PersonId,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub blocked: DateTime<Utc>,
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
use crate::newtypes::PersonId;
|
||||
#[cfg(feature = "full")]
|
||||
use crate::schema::person_actions;
|
||||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use diesel::{dsl, expression_methods::NullableExpressionMethods};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Queryable, Selectable, Associations, Identifiable)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = person_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, target_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct PersonBlock {
|
||||
pub person_id: PersonId,
|
||||
pub target_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = person_actions::blocked.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<person_actions::blocked>))]
|
||||
pub published: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = person_actions))]
|
||||
pub struct PersonBlockForm {
|
||||
pub person_id: PersonId,
|
||||
pub target_id: PersonId,
|
||||
}
|
|
@ -5,7 +5,6 @@ use serde_with::skip_serializing_none;
|
|||
#[cfg(feature = "full")]
|
||||
use {
|
||||
crate::schema::{post, post_actions},
|
||||
diesel::{dsl, expression_methods::NullableExpressionMethods},
|
||||
i_love_jesus::CursorKeysModule,
|
||||
ts_rs::TS,
|
||||
};
|
||||
|
@ -16,8 +15,8 @@ use {
|
|||
feature = "full",
|
||||
derive(Queryable, Selectable, Identifiable, TS, CursorKeysModule)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
#[cfg_attr(feature = "full", cursor_keys_module(name = post_keys))]
|
||||
/// A post.
|
||||
|
@ -172,24 +171,42 @@ pub struct PostUpdateForm {
|
|||
pub scheduled_publish_time: Option<Option<DateTime<Utc>>>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[skip_serializing_none]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, Associations)
|
||||
derive(Identifiable, Queryable, Selectable, Associations, TS)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct PostLike {
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
pub struct PostActions {
|
||||
pub post_id: PostId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = post_actions::like_score.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<post_actions::like_score>))]
|
||||
pub score: i16,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = post_actions::liked.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<post_actions::liked>))]
|
||||
pub published: DateTime<Utc>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the post was read.
|
||||
pub read: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When was the last time you read the comments.
|
||||
pub read_comments: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// The number of comments you read last. Subtract this from total comments to get an unread
|
||||
/// count.
|
||||
pub read_comments_amount: Option<i64>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the post was saved.
|
||||
pub saved: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the post was liked.
|
||||
pub liked: Option<DateTime<Utc>>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// The like / score of the post.
|
||||
pub like_score: Option<i16>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
/// When the post was hidden.
|
||||
pub hidden: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, derive_new::new)]
|
||||
|
@ -198,29 +215,11 @@ pub struct PostLike {
|
|||
pub struct PostLikeForm {
|
||||
pub post_id: PostId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(column_name = like_score))]
|
||||
pub score: i16,
|
||||
pub like_score: i16,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub liked: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, Associations)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct PostSaved {
|
||||
pub post_id: PostId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = post_actions::saved.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<post_actions::saved>))]
|
||||
pub published: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post_actions))]
|
||||
|
@ -231,24 +230,7 @@ pub struct PostSavedForm {
|
|||
pub saved: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, Associations)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct PostRead {
|
||||
pub post_id: PostId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = post_actions::read.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<post_actions::read>))]
|
||||
pub published: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(derive_new::new)]
|
||||
#[derive(derive_new::new, Clone)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post_actions))]
|
||||
pub struct PostReadForm {
|
||||
|
@ -258,21 +240,15 @@ pub struct PostReadForm {
|
|||
pub read: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, Associations)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::post::Post)))]
|
||||
#[derive(derive_new::new)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
pub struct PostHide {
|
||||
pub struct PostReadCommentsForm {
|
||||
pub post_id: PostId,
|
||||
pub person_id: PersonId,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = post_actions::hidden.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<post_actions::hidden>))]
|
||||
pub published: DateTime<Utc>,
|
||||
pub read_comments_amount: i64,
|
||||
#[new(value = "Utc::now()")]
|
||||
pub read_comments: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(derive_new::new)]
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
use crate::newtypes::{PersonId, PostId};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[cfg(feature = "full")]
|
||||
use {
|
||||
crate::schema::post_actions,
|
||||
diesel::{dsl, expression_methods::NullableExpressionMethods},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Queryable, Selectable, Associations, Identifiable)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post_actions))]
|
||||
#[cfg_attr(feature = "full", diesel(primary_key(person_id, post_id)))]
|
||||
#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
/// Aggregate data for a person's post.
|
||||
pub struct PostActions {
|
||||
pub person_id: PersonId,
|
||||
pub post_id: PostId,
|
||||
/// The number of comments they've read on that post.
|
||||
///
|
||||
/// This is updated to the current post comment count every time they view a post.
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = post_actions::read_comments_amount.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<post_actions::read_comments_amount>))]
|
||||
pub read_comments: i64,
|
||||
#[cfg_attr(feature = "full", diesel(select_expression = post_actions::read_comments.assume_not_null()))]
|
||||
#[cfg_attr(feature = "full", diesel(select_expression_type = dsl::AssumeNotNull<post_actions::read_comments>))]
|
||||
pub published: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post_actions))]
|
||||
pub struct PostActionsForm {
|
||||
pub person_id: PersonId,
|
||||
pub post_id: PostId,
|
||||
#[cfg_attr(feature = "full", diesel(column_name = read_comments_amount))]
|
||||
pub read_comments: i64,
|
||||
}
|
|
@ -82,23 +82,25 @@ where
|
|||
|
||||
pub trait Followable {
|
||||
type Form;
|
||||
type IdType;
|
||||
fn follow(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<Self, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn follow_accepted(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_id: CommunityId,
|
||||
person_id: PersonId,
|
||||
) -> impl Future<Output = Result<Self, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn unfollow(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<uplete::Count, Error>> + Send
|
||||
person_id: PersonId,
|
||||
item_id: Self::IdType,
|
||||
) -> impl Future<Output = LemmyResult<uplete::Count>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
@ -108,13 +110,13 @@ pub trait Joinable {
|
|||
fn join(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<Self, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn leave(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<uplete::Count, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<uplete::Count>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
@ -125,14 +127,14 @@ pub trait Likeable {
|
|||
fn like(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<Self, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn remove(
|
||||
fn remove_like(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
item_id: Self::IdType,
|
||||
) -> impl Future<Output = Result<uplete::Count, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<uplete::Count>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
@ -142,13 +144,13 @@ pub trait Bannable {
|
|||
fn ban(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<Self, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn unban(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<uplete::Count, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<uplete::Count>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
@ -158,29 +160,102 @@ pub trait Saveable {
|
|||
fn save(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<Self, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn unsave(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<uplete::Count, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<uplete::Count>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub trait Readable {
|
||||
type Form;
|
||||
fn mark_as_read(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = LemmyResult<usize>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn mark_many_as_read(
|
||||
pool: &mut DbPool<'_>,
|
||||
forms: &[Self::Form],
|
||||
) -> impl Future<Output = LemmyResult<usize>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn mark_as_unread(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = LemmyResult<uplete::Count>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub trait ReadComments {
|
||||
type Form;
|
||||
type IdType;
|
||||
fn update_read_comments(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = LemmyResult<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn remove_read_comments(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
item_id: Self::IdType,
|
||||
) -> impl Future<Output = LemmyResult<uplete::Count>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub trait Hideable {
|
||||
type Form;
|
||||
fn hide(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = LemmyResult<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn unhide(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = LemmyResult<uplete::Count>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub trait Blockable {
|
||||
type Form;
|
||||
type ObjectIdType;
|
||||
type ObjectType;
|
||||
fn block(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<Self, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn unblock(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<uplete::Count, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<uplete::Count>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn read_block(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_person_id: PersonId,
|
||||
for_item_id: Self::ObjectIdType,
|
||||
) -> impl Future<Output = LemmyResult<()>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
fn read_blocks_for_person(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
// Note: cant use lemmyresult because of try_pool
|
||||
) -> impl Future<Output = Result<Vec<Self::ObjectType>, diesel::result::Error>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
@ -192,14 +267,14 @@ pub trait Reportable {
|
|||
fn report(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &Self::Form,
|
||||
) -> impl Future<Output = Result<Self, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<Self>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn resolve(
|
||||
pool: &mut DbPool<'_>,
|
||||
report_id: Self::IdType,
|
||||
resolver_id: PersonId,
|
||||
) -> impl Future<Output = Result<usize, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<usize>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn resolve_apub(
|
||||
|
@ -214,14 +289,14 @@ pub trait Reportable {
|
|||
pool: &mut DbPool<'_>,
|
||||
comment_id_: Self::ObjectIdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> impl Future<Output = Result<usize, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<usize>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
fn unresolve(
|
||||
pool: &mut DbPool<'_>,
|
||||
report_id: Self::IdType,
|
||||
resolver_id: PersonId,
|
||||
) -> impl Future<Output = Result<usize, Error>> + Send
|
||||
) -> impl Future<Output = LemmyResult<usize>> + Send
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ use diesel_async::RunQueryDsl;
|
|||
use i_love_jesus::PaginatedQueryBuilder;
|
||||
use lemmy_db_schema::{
|
||||
aliases::{self, creator_community_actions, creator_local_user},
|
||||
impls::{community::community_follower_select_subscribed_type, local_user::local_user_can_mod},
|
||||
newtypes::{PaginationCursor, PersonId},
|
||||
schema::{
|
||||
comment,
|
||||
|
@ -38,13 +37,11 @@ use lemmy_db_schema::{
|
|||
person_post_mention,
|
||||
post,
|
||||
post_actions,
|
||||
post_tag,
|
||||
private_message,
|
||||
tag,
|
||||
},
|
||||
source::combined::inbox::{inbox_combined_keys as key, InboxCombined},
|
||||
traits::{InternalToCombinedView, PaginationCursorBuilder},
|
||||
utils::{functions::coalesce, get_conn, DbPool},
|
||||
utils::{get_conn, DbPool},
|
||||
InboxDataType,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
@ -55,14 +52,16 @@ impl InboxCombinedViewInternal {
|
|||
let item_creator = person::id;
|
||||
let recipient_person = aliases::person1.field(person::id);
|
||||
|
||||
let item_creator_join = comment::creator_id
|
||||
.eq(item_creator)
|
||||
.or(
|
||||
inbox_combined::person_post_mention_id
|
||||
.is_not_null()
|
||||
.and(post::creator_id.eq(item_creator)),
|
||||
)
|
||||
.or(private_message::creator_id.eq(item_creator));
|
||||
let item_creator_join = person::table.on(
|
||||
comment::creator_id
|
||||
.eq(item_creator)
|
||||
.or(
|
||||
inbox_combined::person_post_mention_id
|
||||
.is_not_null()
|
||||
.and(post::creator_id.eq(item_creator)),
|
||||
)
|
||||
.or(private_message::creator_id.eq(item_creator)),
|
||||
);
|
||||
|
||||
let recipient_join = aliases::person1.on(
|
||||
comment_reply::recipient_id
|
||||
|
@ -72,27 +71,33 @@ impl InboxCombinedViewInternal {
|
|||
.or(private_message::recipient_id.eq(recipient_person)),
|
||||
);
|
||||
|
||||
let comment_join = comment_reply::comment_id
|
||||
.eq(comment::id)
|
||||
.or(person_comment_mention::comment_id.eq(comment::id))
|
||||
// Filter out the deleted / removed
|
||||
.and(not(comment::deleted))
|
||||
.and(not(comment::removed));
|
||||
let comment_join = comment::table.on(
|
||||
comment_reply::comment_id
|
||||
.eq(comment::id)
|
||||
.or(person_comment_mention::comment_id.eq(comment::id))
|
||||
// Filter out the deleted / removed
|
||||
.and(not(comment::deleted))
|
||||
.and(not(comment::removed)),
|
||||
);
|
||||
|
||||
let post_join = person_post_mention::post_id
|
||||
.eq(post::id)
|
||||
.or(comment::post_id.eq(post::id))
|
||||
// Filter out the deleted / removed
|
||||
.and(not(post::deleted))
|
||||
.and(not(post::removed));
|
||||
let post_join = post::table.on(
|
||||
person_post_mention::post_id
|
||||
.eq(post::id)
|
||||
.or(comment::post_id.eq(post::id))
|
||||
// Filter out the deleted / removed
|
||||
.and(not(post::deleted))
|
||||
.and(not(post::removed)),
|
||||
);
|
||||
|
||||
// This could be a simple join, but you need to check for deleted here
|
||||
let private_message_join = inbox_combined::private_message_id
|
||||
.eq(private_message::id.nullable())
|
||||
.and(not(private_message::deleted))
|
||||
.and(not(private_message::removed));
|
||||
let private_message_join = private_message::table.on(
|
||||
inbox_combined::private_message_id
|
||||
.eq(private_message::id.nullable())
|
||||
.and(not(private_message::deleted))
|
||||
.and(not(private_message::removed)),
|
||||
);
|
||||
|
||||
let community_join = post::community_id.eq(community::id);
|
||||
let community_join = community::table.on(post::community_id.eq(community::id));
|
||||
|
||||
let local_user_join = local_user::table.on(local_user::person_id.nullable().eq(my_person_id));
|
||||
|
||||
|
@ -150,11 +155,11 @@ impl InboxCombinedViewInternal {
|
|||
.left_join(comment_reply::table)
|
||||
.left_join(person_comment_mention::table)
|
||||
.left_join(person_post_mention::table)
|
||||
.left_join(private_message::table.on(private_message_join))
|
||||
.left_join(comment::table.on(comment_join))
|
||||
.left_join(post::table.on(post_join))
|
||||
.left_join(community::table.on(community_join))
|
||||
.inner_join(person::table.on(item_creator_join))
|
||||
.left_join(private_message_join)
|
||||
.left_join(comment_join)
|
||||
.left_join(post_join)
|
||||
.left_join(community_join)
|
||||
.inner_join(item_creator_join)
|
||||
.inner_join(recipient_join)
|
||||
.left_join(image_details_join)
|
||||
.left_join(creator_community_actions_join)
|
||||
|
@ -266,58 +271,8 @@ impl InboxCombinedQuery {
|
|||
let item_creator = person::id;
|
||||
let recipient_person = aliases::person1.field(person::id);
|
||||
|
||||
let post_tags = post_tag::table
|
||||
.inner_join(tag::table)
|
||||
.select(diesel::dsl::sql::<diesel::sql_types::Json>(
|
||||
"json_agg(tag.*)",
|
||||
))
|
||||
.filter(post_tag::post_id.eq(post::id))
|
||||
.filter(tag::deleted.eq(false))
|
||||
.single_value();
|
||||
|
||||
let mut query = InboxCombinedViewInternal::joins(my_person_id)
|
||||
.select((
|
||||
// Specific
|
||||
comment_reply::all_columns.nullable(),
|
||||
person_comment_mention::all_columns.nullable(),
|
||||
person_post_mention::all_columns.nullable(),
|
||||
coalesce(
|
||||
post::comments.nullable() - post_actions::read_comments_amount.nullable(),
|
||||
post::comments,
|
||||
)
|
||||
.nullable(),
|
||||
post_actions::saved.nullable(),
|
||||
post_actions::read.nullable().is_not_null(),
|
||||
post_actions::hidden.nullable().is_not_null(),
|
||||
post_actions::like_score.nullable(),
|
||||
image_details::all_columns.nullable(),
|
||||
post_tags,
|
||||
private_message::all_columns.nullable(),
|
||||
// Shared
|
||||
post::all_columns.nullable(),
|
||||
community::all_columns.nullable(),
|
||||
comment::all_columns.nullable(),
|
||||
comment_actions::saved.nullable(),
|
||||
comment_actions::like_score.nullable(),
|
||||
community_follower_select_subscribed_type(),
|
||||
person::all_columns,
|
||||
aliases::person1.fields(person::all_columns),
|
||||
creator_local_user
|
||||
.field(local_user::admin)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::became_moderator)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::received_ban)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
person_actions::blocked.nullable().is_not_null(),
|
||||
community_actions::received_ban.nullable().is_not_null(),
|
||||
local_user_can_mod(),
|
||||
))
|
||||
.select(InboxCombinedViewInternal::as_select())
|
||||
.into_boxed();
|
||||
|
||||
// Filters
|
||||
|
@ -431,14 +386,12 @@ impl InternalToCombinedView for InboxCombinedViewInternal {
|
|||
post,
|
||||
community,
|
||||
creator: v.item_creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
community_actions: v.community_actions,
|
||||
comment_actions: v.comment_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.comment_saved,
|
||||
my_vote: v.my_comment_vote,
|
||||
banned_from_community: v.banned_from_community,
|
||||
can_mod: v.can_mod,
|
||||
}))
|
||||
} else if let (Some(person_comment_mention), Some(comment), Some(post), Some(community)) = (
|
||||
|
@ -455,42 +408,31 @@ impl InternalToCombinedView for InboxCombinedViewInternal {
|
|||
post,
|
||||
community,
|
||||
creator: v.item_creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
community_actions: v.community_actions,
|
||||
comment_actions: v.comment_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.comment_saved,
|
||||
my_vote: v.my_comment_vote,
|
||||
banned_from_community: v.banned_from_community,
|
||||
can_mod: v.can_mod,
|
||||
},
|
||||
))
|
||||
} else if let (Some(person_post_mention), Some(post), Some(unread_comments), Some(community)) = (
|
||||
v.person_post_mention,
|
||||
v.post,
|
||||
v.post_unread_comments,
|
||||
v.community,
|
||||
) {
|
||||
} else if let (Some(person_post_mention), Some(post), Some(community)) =
|
||||
(v.person_post_mention, v.post, v.community)
|
||||
{
|
||||
Some(InboxCombinedView::PostMention(PersonPostMentionView {
|
||||
person_post_mention,
|
||||
post,
|
||||
community,
|
||||
recipient: v.item_recipient,
|
||||
unread_comments,
|
||||
creator: v.item_creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.post_saved,
|
||||
read: v.post_read,
|
||||
hidden: v.post_hidden,
|
||||
my_vote: v.my_post_vote,
|
||||
recipient: v.item_recipient,
|
||||
community_actions: v.community_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
post_actions: v.post_actions,
|
||||
image_details: v.image_details,
|
||||
post_tags: v.post_tags,
|
||||
banned_from_community: v.banned_from_community,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
can_mod: v.can_mod,
|
||||
}))
|
||||
} else if let Some(private_message) = v.private_message {
|
||||
|
@ -518,10 +460,8 @@ mod tests {
|
|||
comment::{Comment, CommentInsertForm},
|
||||
comment_reply::{CommentReply, CommentReplyInsertForm, CommentReplyUpdateForm},
|
||||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
instance_block::{InstanceBlock, InstanceBlockForm},
|
||||
person::{Person, PersonInsertForm, PersonUpdateForm},
|
||||
person_block::{PersonBlock, PersonBlockForm},
|
||||
instance::{Instance, InstanceActions, InstanceBlockForm},
|
||||
person::{Person, PersonActions, PersonBlockForm, PersonInsertForm, PersonUpdateForm},
|
||||
person_comment_mention::{PersonCommentMention, PersonCommentMentionInsertForm},
|
||||
person_post_mention::{PersonPostMention, PersonPostMentionInsertForm},
|
||||
post::{Post, PostInsertForm},
|
||||
|
@ -727,11 +667,8 @@ mod tests {
|
|||
}
|
||||
|
||||
// Sara blocks timmy, and make sure these counts are now empty
|
||||
let sara_blocks_timmy_form = PersonBlockForm {
|
||||
person_id: data.sara.id,
|
||||
target_id: data.timmy.id,
|
||||
};
|
||||
PersonBlock::block(pool, &sara_blocks_timmy_form).await?;
|
||||
let sara_blocks_timmy_form = PersonBlockForm::new(data.sara.id, data.timmy.id);
|
||||
PersonActions::block(pool, &sara_blocks_timmy_form).await?;
|
||||
|
||||
let sara_unread_mentions_after_block =
|
||||
InboxCombinedViewInternal::get_unread_count(pool, data.sara.id, true).await?;
|
||||
|
@ -749,7 +686,7 @@ mod tests {
|
|||
));
|
||||
|
||||
// Unblock user so we can reuse the same person
|
||||
PersonBlock::unblock(pool, &sara_blocks_timmy_form).await?;
|
||||
PersonActions::unblock(pool, &sara_blocks_timmy_form).await?;
|
||||
|
||||
// Test the type filter
|
||||
let sara_inbox_post_mentions_only = InboxCombinedQuery {
|
||||
|
@ -883,19 +820,18 @@ mod tests {
|
|||
setup_private_messages(&data, pool).await?;
|
||||
|
||||
// Make sure blocks are working
|
||||
let timmy_blocks_sara_form = PersonBlockForm {
|
||||
person_id: data.timmy.id,
|
||||
target_id: data.sara.id,
|
||||
};
|
||||
let timmy_blocks_sara_form = PersonBlockForm::new(data.timmy.id, data.sara.id);
|
||||
|
||||
let inserted_block = PersonBlock::block(pool, &timmy_blocks_sara_form).await?;
|
||||
let inserted_block = PersonActions::block(pool, &timmy_blocks_sara_form).await?;
|
||||
|
||||
let expected_block = PersonBlock {
|
||||
person_id: data.timmy.id,
|
||||
target_id: data.sara.id,
|
||||
published: inserted_block.published,
|
||||
};
|
||||
assert_eq!(expected_block, inserted_block);
|
||||
assert_eq!(
|
||||
(data.timmy.id, data.sara.id, true),
|
||||
(
|
||||
inserted_block.person_id,
|
||||
inserted_block.target_id,
|
||||
inserted_block.blocked.is_some()
|
||||
)
|
||||
);
|
||||
|
||||
let timmy_messages = map_to_pm(
|
||||
&InboxCombinedQuery {
|
||||
|
@ -926,19 +862,18 @@ mod tests {
|
|||
setup_private_messages(&data, pool).await?;
|
||||
|
||||
// Make sure instance_blocks are working
|
||||
let timmy_blocks_instance_form = InstanceBlockForm {
|
||||
person_id: data.timmy.id,
|
||||
instance_id: data.sara.instance_id,
|
||||
};
|
||||
let timmy_blocks_instance_form = InstanceBlockForm::new(data.timmy.id, data.sara.instance_id);
|
||||
|
||||
let inserted_instance_block = InstanceBlock::block(pool, &timmy_blocks_instance_form).await?;
|
||||
let inserted_instance_block = InstanceActions::block(pool, &timmy_blocks_instance_form).await?;
|
||||
|
||||
let expected_instance_block = InstanceBlock {
|
||||
person_id: data.timmy.id,
|
||||
instance_id: data.sara.instance_id,
|
||||
published: inserted_instance_block.published,
|
||||
};
|
||||
assert_eq!(expected_instance_block, inserted_instance_block);
|
||||
assert_eq!(
|
||||
(data.timmy.id, data.sara.instance_id, true),
|
||||
(
|
||||
inserted_instance_block.person_id,
|
||||
inserted_instance_block.instance_id,
|
||||
inserted_instance_block.blocked.is_some()
|
||||
)
|
||||
);
|
||||
|
||||
let timmy_messages = map_to_pm(
|
||||
&InboxCombinedQuery {
|
||||
|
|
|
@ -20,7 +20,7 @@ use crate::{
|
|||
ModlogCombinedView,
|
||||
ModlogCombinedViewInternal,
|
||||
},
|
||||
utils::{filter_is_subscribed, filter_not_hidden_or_is_subscribed},
|
||||
utils::{filter_is_subscribed, filter_not_unlisted_or_is_subscribed},
|
||||
};
|
||||
use diesel::{
|
||||
BoolExpressionMethods,
|
||||
|
@ -378,7 +378,7 @@ impl ModlogCombinedQuery<'_> {
|
|||
ListingType::Subscribed => query.filter(filter_is_subscribed()),
|
||||
ListingType::Local => query
|
||||
.filter(community::local.eq(true))
|
||||
.filter(filter_not_hidden_or_is_subscribed()),
|
||||
.filter(filter_not_unlisted_or_is_subscribed()),
|
||||
ListingType::ModeratorView => query.filter(community_actions::became_moderator.is_not_null()),
|
||||
};
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ use diesel::{
|
|||
use diesel_async::RunQueryDsl;
|
||||
use i_love_jesus::PaginatedQueryBuilder;
|
||||
use lemmy_db_schema::{
|
||||
self,
|
||||
aliases::{creator_community_actions, creator_local_user},
|
||||
impls::{community::community_follower_select_subscribed_type, local_user::local_user_can_mod},
|
||||
newtypes::{PaginationCursor, PersonId},
|
||||
schema::{
|
||||
comment,
|
||||
|
@ -25,18 +25,17 @@ use lemmy_db_schema::{
|
|||
community,
|
||||
community_actions,
|
||||
image_details,
|
||||
instance_actions,
|
||||
local_user,
|
||||
person,
|
||||
person_actions,
|
||||
person_content_combined,
|
||||
post,
|
||||
post_actions,
|
||||
post_tag,
|
||||
tag,
|
||||
},
|
||||
source::combined::person_content::{person_content_combined_keys as key, PersonContentCombined},
|
||||
traits::{InternalToCombinedView, PaginationCursorBuilder},
|
||||
utils::{functions::coalesce, get_conn, DbPool},
|
||||
utils::{get_conn, DbPool},
|
||||
PersonContentType,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
@ -93,6 +92,12 @@ impl PersonContentCombinedViewInternal {
|
|||
.and(community_actions::person_id.nullable().eq(my_person_id)),
|
||||
);
|
||||
|
||||
let instance_actions_join = instance_actions::table.on(
|
||||
instance_actions::instance_id
|
||||
.eq(person::instance_id)
|
||||
.and(instance_actions::person_id.nullable().eq(my_person_id)),
|
||||
);
|
||||
|
||||
let post_actions_join = post_actions::table.on(
|
||||
post_actions::post_id
|
||||
.eq(post::id)
|
||||
|
@ -123,6 +128,7 @@ impl PersonContentCombinedViewInternal {
|
|||
.left_join(local_user_join)
|
||||
.left_join(creator_local_user_join)
|
||||
.left_join(community_actions_join)
|
||||
.left_join(instance_actions_join)
|
||||
.left_join(post_actions_join)
|
||||
.left_join(person_actions_join)
|
||||
.left_join(comment_actions_join)
|
||||
|
@ -185,15 +191,6 @@ impl PersonContentCombinedQuery {
|
|||
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
let post_tags = post_tag::table
|
||||
.inner_join(tag::table)
|
||||
.select(diesel::dsl::sql::<diesel::sql_types::Json>(
|
||||
"json_agg(tag.*)",
|
||||
))
|
||||
.filter(post_tag::post_id.eq(post::id))
|
||||
.filter(tag::deleted.eq(false))
|
||||
.single_value();
|
||||
|
||||
// Notes: since the post_id and comment_id are optional columns,
|
||||
// many joins must use an OR condition.
|
||||
// For example, the creator must be the person table joined to either:
|
||||
|
@ -202,43 +199,7 @@ impl PersonContentCombinedQuery {
|
|||
let mut query = PersonContentCombinedViewInternal::joins(my_person_id)
|
||||
// The creator id filter
|
||||
.filter(item_creator.eq(self.creator_id))
|
||||
.select((
|
||||
// Post-specific
|
||||
coalesce(
|
||||
post::comments.nullable() - post_actions::read_comments_amount.nullable(),
|
||||
post::comments,
|
||||
),
|
||||
post_actions::saved.nullable(),
|
||||
post_actions::read.nullable().is_not_null(),
|
||||
post_actions::hidden.nullable().is_not_null(),
|
||||
post_actions::like_score.nullable(),
|
||||
image_details::all_columns.nullable(),
|
||||
post_tags,
|
||||
// Comment-specific
|
||||
comment::all_columns.nullable(),
|
||||
comment_actions::saved.nullable(),
|
||||
comment_actions::like_score.nullable(),
|
||||
// Shared
|
||||
post::all_columns,
|
||||
community::all_columns,
|
||||
person::all_columns,
|
||||
community_follower_select_subscribed_type(),
|
||||
creator_local_user
|
||||
.field(local_user::admin)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::became_moderator)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::received_ban)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
person_actions::blocked.nullable().is_not_null(),
|
||||
community_actions::received_ban.nullable().is_not_null(),
|
||||
local_user_can_mod(),
|
||||
))
|
||||
.select(PersonContentCombinedViewInternal::as_select())
|
||||
.into_boxed();
|
||||
|
||||
if let Some(type_) = self.type_ {
|
||||
|
@ -292,34 +253,26 @@ impl InternalToCombinedView for PersonContentCombinedViewInternal {
|
|||
post: v.post,
|
||||
community: v.community,
|
||||
creator: v.item_creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
community_actions: v.community_actions,
|
||||
comment_actions: v.comment_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.comment_saved,
|
||||
my_vote: v.my_comment_vote,
|
||||
banned_from_community: v.banned_from_community,
|
||||
can_mod: v.can_mod,
|
||||
}))
|
||||
} else {
|
||||
Some(PersonContentCombinedView::Post(PostView {
|
||||
post: v.post,
|
||||
community: v.community,
|
||||
unread_comments: v.post_unread_comments,
|
||||
creator: v.item_creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.post_saved,
|
||||
read: v.post_read,
|
||||
hidden: v.post_hidden,
|
||||
my_vote: v.my_post_vote,
|
||||
image_details: v.image_details,
|
||||
banned_from_community: v.banned_from_community,
|
||||
tags: v.post_tags,
|
||||
community_actions: v.community_actions,
|
||||
post_actions: v.post_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
can_mod: v.can_mod,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ use diesel_async::RunQueryDsl;
|
|||
use i_love_jesus::PaginatedQueryBuilder;
|
||||
use lemmy_db_schema::{
|
||||
aliases::{creator_community_actions, creator_local_user},
|
||||
impls::{community::community_follower_select_subscribed_type, local_user::local_user_can_mod},
|
||||
newtypes::{PaginationCursor, PersonId},
|
||||
schema::{
|
||||
comment,
|
||||
|
@ -25,18 +24,17 @@ use lemmy_db_schema::{
|
|||
community,
|
||||
community_actions,
|
||||
image_details,
|
||||
instance_actions,
|
||||
local_user,
|
||||
person,
|
||||
person_actions,
|
||||
person_saved_combined,
|
||||
post,
|
||||
post_actions,
|
||||
post_tag,
|
||||
tag,
|
||||
},
|
||||
source::combined::person_saved::{person_saved_combined_keys as key, PersonSavedCombined},
|
||||
traits::{InternalToCombinedView, PaginationCursorBuilder},
|
||||
utils::{functions::coalesce, get_conn, DbPool},
|
||||
utils::{get_conn, DbPool},
|
||||
PersonContentType,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
@ -134,6 +132,12 @@ impl PersonSavedCombinedViewInternal {
|
|||
.and(community_actions::person_id.eq(my_person_id)),
|
||||
);
|
||||
|
||||
let instance_actions_join = instance_actions::table.on(
|
||||
instance_actions::instance_id
|
||||
.eq(person::instance_id)
|
||||
.and(instance_actions::person_id.eq(my_person_id)),
|
||||
);
|
||||
|
||||
let post_actions_join = post_actions::table.on(
|
||||
post_actions::post_id
|
||||
.eq(post::id)
|
||||
|
@ -164,6 +168,7 @@ impl PersonSavedCombinedViewInternal {
|
|||
.left_join(local_user_join)
|
||||
.left_join(creator_local_user_join)
|
||||
.left_join(community_actions_join)
|
||||
.left_join(instance_actions_join)
|
||||
.left_join(post_actions_join)
|
||||
.left_join(person_actions_join)
|
||||
.left_join(comment_actions_join)
|
||||
|
@ -181,54 +186,9 @@ impl PersonSavedCombinedQuery {
|
|||
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
let post_tags = post_tag::table
|
||||
.inner_join(tag::table)
|
||||
.select(diesel::dsl::sql::<diesel::sql_types::Json>(
|
||||
"json_agg(tag.*)",
|
||||
))
|
||||
.filter(post_tag::post_id.eq(post::id))
|
||||
.filter(tag::deleted.eq(false))
|
||||
.single_value();
|
||||
|
||||
let mut query = PersonSavedCombinedViewInternal::joins(my_person_id)
|
||||
.filter(person_saved_combined::person_id.eq(my_person_id))
|
||||
.select((
|
||||
// Post-specific
|
||||
coalesce(
|
||||
post::comments.nullable() - post_actions::read_comments_amount.nullable(),
|
||||
post::comments,
|
||||
),
|
||||
post_actions::saved.nullable(),
|
||||
post_actions::read.nullable().is_not_null(),
|
||||
post_actions::hidden.nullable().is_not_null(),
|
||||
post_actions::like_score.nullable(),
|
||||
image_details::all_columns.nullable(),
|
||||
post_tags,
|
||||
// Comment-specific
|
||||
comment::all_columns.nullable(),
|
||||
comment_actions::saved.nullable(),
|
||||
comment_actions::like_score.nullable(),
|
||||
// Shared
|
||||
post::all_columns,
|
||||
community::all_columns,
|
||||
person::all_columns,
|
||||
community_follower_select_subscribed_type(),
|
||||
creator_local_user
|
||||
.field(local_user::admin)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::became_moderator)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::received_ban)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
person_actions::blocked.nullable().is_not_null(),
|
||||
community_actions::received_ban.nullable().is_not_null(),
|
||||
local_user_can_mod(),
|
||||
))
|
||||
.select(PersonSavedCombinedViewInternal::as_select())
|
||||
.into_boxed();
|
||||
|
||||
if let Some(type_) = self.type_ {
|
||||
|
@ -280,34 +240,26 @@ impl InternalToCombinedView for PersonSavedCombinedViewInternal {
|
|||
post: v.post,
|
||||
community: v.community,
|
||||
creator: v.item_creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
community_actions: v.community_actions,
|
||||
comment_actions: v.comment_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.comment_saved,
|
||||
my_vote: v.my_comment_vote,
|
||||
banned_from_community: v.banned_from_community,
|
||||
can_mod: v.can_mod,
|
||||
}))
|
||||
} else {
|
||||
Some(PersonSavedCombinedView::Post(PostView {
|
||||
post: v.post,
|
||||
community: v.community,
|
||||
unread_comments: v.post_unread_comments,
|
||||
creator: v.item_creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.post_saved,
|
||||
read: v.post_read,
|
||||
hidden: v.post_hidden,
|
||||
my_vote: v.my_post_vote,
|
||||
image_details: v.image_details,
|
||||
banned_from_community: v.banned_from_community,
|
||||
tags: v.post_tags,
|
||||
community_actions: v.community_actions,
|
||||
post_actions: v.post_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
can_mod: v.can_mod,
|
||||
}))
|
||||
}
|
||||
|
@ -324,12 +276,12 @@ mod tests {
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
comment::{Comment, CommentInsertForm, CommentSaved, CommentSavedForm},
|
||||
comment::{Comment, CommentActions, CommentInsertForm, CommentSavedForm},
|
||||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
local_user::{LocalUser, LocalUserInsertForm},
|
||||
person::{Person, PersonInsertForm},
|
||||
post::{Post, PostInsertForm, PostSaved, PostSavedForm},
|
||||
post::{Post, PostActions, PostInsertForm, PostSavedForm},
|
||||
},
|
||||
traits::{Crud, Saveable},
|
||||
utils::{build_db_pool_for_tests, DbPool},
|
||||
|
@ -424,14 +376,14 @@ mod tests {
|
|||
|
||||
// Save a few things
|
||||
let save_sara_comment_2 =
|
||||
CommentSavedForm::new(data.sara_comment_2.id, data.timmy_view.person.id);
|
||||
CommentSaved::save(pool, &save_sara_comment_2).await?;
|
||||
CommentSavedForm::new(data.timmy_view.person.id, data.sara_comment_2.id);
|
||||
CommentActions::save(pool, &save_sara_comment_2).await?;
|
||||
|
||||
let save_sara_comment = CommentSavedForm::new(data.sara_comment.id, data.timmy_view.person.id);
|
||||
CommentSaved::save(pool, &save_sara_comment).await?;
|
||||
let save_sara_comment = CommentSavedForm::new(data.timmy_view.person.id, data.sara_comment.id);
|
||||
CommentActions::save(pool, &save_sara_comment).await?;
|
||||
|
||||
let post_save_form = PostSavedForm::new(data.timmy_post.id, data.timmy.id);
|
||||
PostSaved::save(pool, &post_save_form).await?;
|
||||
PostActions::save(pool, &post_save_form).await?;
|
||||
|
||||
let timmy_saved = PersonSavedCombinedQuery::default()
|
||||
.list(pool, &data.timmy_view)
|
||||
|
@ -459,8 +411,8 @@ mod tests {
|
|||
}
|
||||
|
||||
// Try unsaving 2 things
|
||||
CommentSaved::unsave(pool, &save_sara_comment).await?;
|
||||
PostSaved::unsave(pool, &post_save_form).await?;
|
||||
CommentActions::unsave(pool, &save_sara_comment).await?;
|
||||
PostActions::unsave(pool, &post_save_form).await?;
|
||||
|
||||
let timmy_saved = PersonSavedCombinedQuery::default()
|
||||
.list(pool, &data.timmy_view)
|
||||
|
|
|
@ -22,7 +22,6 @@ use diesel_async::RunQueryDsl;
|
|||
use i_love_jesus::PaginatedQueryBuilder;
|
||||
use lemmy_db_schema::{
|
||||
aliases::{self, creator_community_actions},
|
||||
impls::community::community_follower_select_subscribed_type,
|
||||
newtypes::{CommunityId, PaginationCursor, PersonId, PostId},
|
||||
schema::{
|
||||
comment,
|
||||
|
@ -43,7 +42,7 @@ use lemmy_db_schema::{
|
|||
},
|
||||
source::combined::report::{report_combined_keys as key, ReportCombined},
|
||||
traits::{InternalToCombinedView, PaginationCursorBuilder},
|
||||
utils::{functions::coalesce, get_conn, DbPool, ReverseTimestampKey},
|
||||
utils::{get_conn, DbPool, ReverseTimestampKey},
|
||||
ReportType,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
@ -255,46 +254,7 @@ impl ReportCombinedQuery {
|
|||
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let mut query = ReportCombinedViewInternal::joins(my_person_id)
|
||||
.select((
|
||||
// Post-specific
|
||||
post_report::all_columns.nullable(),
|
||||
post::all_columns.nullable(),
|
||||
coalesce(
|
||||
post::comments.nullable() - post_actions::read_comments_amount.nullable(),
|
||||
post::comments,
|
||||
)
|
||||
.nullable(),
|
||||
post_actions::saved.nullable(),
|
||||
post_actions::read.nullable().is_not_null(),
|
||||
post_actions::hidden.nullable().is_not_null(),
|
||||
post_actions::like_score.nullable(),
|
||||
// Comment-specific
|
||||
comment_report::all_columns.nullable(),
|
||||
comment::all_columns.nullable(),
|
||||
comment_actions::saved.nullable(),
|
||||
comment_actions::like_score.nullable(),
|
||||
// Private-message-specific
|
||||
private_message_report::all_columns.nullable(),
|
||||
private_message::all_columns.nullable(),
|
||||
// Community-specific
|
||||
community_report::all_columns.nullable(),
|
||||
// Shared
|
||||
person::all_columns,
|
||||
aliases::person1.fields(person::all_columns.nullable()),
|
||||
community::all_columns.nullable(),
|
||||
community_follower_select_subscribed_type(),
|
||||
aliases::person2.fields(person::all_columns.nullable()),
|
||||
local_user::admin.nullable().is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::received_ban)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::became_moderator)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
person_actions::blocked.nullable().is_not_null(),
|
||||
))
|
||||
.select(ReportCombinedViewInternal::as_select())
|
||||
.into_boxed();
|
||||
|
||||
if let Some(community_id) = self.community_id {
|
||||
|
@ -414,36 +374,24 @@ impl InternalToCombinedView for ReportCombinedViewInternal {
|
|||
// Use for a short alias
|
||||
let v = self;
|
||||
|
||||
if let (
|
||||
Some(post_report),
|
||||
Some(post),
|
||||
Some(community),
|
||||
Some(unread_comments),
|
||||
Some(post_creator),
|
||||
) = (
|
||||
if let (Some(post_report), Some(post), Some(community), Some(post_creator)) = (
|
||||
v.post_report,
|
||||
v.post.clone(),
|
||||
v.community.clone(),
|
||||
v.post_unread_comments,
|
||||
v.item_creator.clone(),
|
||||
) {
|
||||
Some(ReportCombinedView::Post(PostReportView {
|
||||
post_report,
|
||||
post,
|
||||
community,
|
||||
unread_comments,
|
||||
creator: v.report_creator,
|
||||
post_creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.post_saved,
|
||||
read: v.post_read,
|
||||
hidden: v.post_hidden,
|
||||
my_vote: v.my_post_vote,
|
||||
creator: v.report_creator,
|
||||
resolver: v.resolver,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
community_actions: v.community_actions,
|
||||
post_actions: v.post_actions,
|
||||
person_actions: v.person_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
}))
|
||||
} else if let (
|
||||
Some(comment_report),
|
||||
|
@ -465,14 +413,12 @@ impl InternalToCombinedView for ReportCombinedViewInternal {
|
|||
community,
|
||||
creator: v.report_creator,
|
||||
comment_creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.comment_saved,
|
||||
my_vote: v.my_comment_vote,
|
||||
resolver: v.resolver,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
community_actions: v.community_actions,
|
||||
comment_actions: v.comment_actions,
|
||||
person_actions: v.person_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
}))
|
||||
} else if let (
|
||||
Some(private_message_report),
|
||||
|
@ -494,7 +440,6 @@ impl InternalToCombinedView for ReportCombinedViewInternal {
|
|||
community_report,
|
||||
community,
|
||||
creator: v.report_creator,
|
||||
subscribed: v.subscribed,
|
||||
resolver: v.resolver,
|
||||
}))
|
||||
} else {
|
||||
|
@ -527,7 +472,7 @@ mod tests {
|
|||
source::{
|
||||
comment::{Comment, CommentInsertForm},
|
||||
comment_report::{CommentReport, CommentReportForm},
|
||||
community::{Community, CommunityInsertForm, CommunityModerator, CommunityModeratorForm},
|
||||
community::{Community, CommunityActions, CommunityInsertForm, CommunityModeratorForm},
|
||||
community_report::{CommunityReport, CommunityReportForm},
|
||||
instance::Instance,
|
||||
local_user::{LocalUser, LocalUserInsertForm},
|
||||
|
@ -595,11 +540,9 @@ mod tests {
|
|||
let inserted_community = Community::create(pool, &community_form).await?;
|
||||
|
||||
// Make timmy a mod
|
||||
let timmy_moderator_form = CommunityModeratorForm {
|
||||
community_id: inserted_community.id,
|
||||
person_id: inserted_timmy.id,
|
||||
};
|
||||
CommunityModerator::join(pool, &timmy_moderator_form).await?;
|
||||
let timmy_moderator_form =
|
||||
CommunityModeratorForm::new(inserted_community.id, inserted_timmy.id);
|
||||
CommunityActions::join(pool, &timmy_moderator_form).await?;
|
||||
|
||||
let post_form = PostInsertForm::new(
|
||||
"A test post crv".into(),
|
||||
|
@ -926,7 +869,6 @@ mod tests {
|
|||
assert_eq!(read_jessica_report_view.community.id, data.community.id);
|
||||
assert_eq!(read_jessica_report_view.creator.id, data.jessica.id);
|
||||
assert_eq!(read_jessica_report_view.post_creator.id, data.timmy.id);
|
||||
assert_eq!(read_jessica_report_view.my_vote, None);
|
||||
assert_eq!(read_jessica_report_view.resolver, None);
|
||||
assert_eq!(agg_1.report_count, 1);
|
||||
assert_eq!(agg_1.unresolved_report_count, 1);
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
SearchCombinedView,
|
||||
SearchCombinedViewInternal,
|
||||
},
|
||||
utils::{filter_is_subscribed, filter_not_hidden_or_is_subscribed},
|
||||
utils::{filter_is_subscribed, filter_not_unlisted_or_is_subscribed},
|
||||
};
|
||||
use diesel::{
|
||||
dsl::not,
|
||||
|
@ -24,7 +24,6 @@ use diesel_async::RunQueryDsl;
|
|||
use i_love_jesus::PaginatedQueryBuilder;
|
||||
use lemmy_db_schema::{
|
||||
aliases::{creator_community_actions, creator_local_user},
|
||||
impls::{community::community_follower_select_subscribed_type, local_user::local_user_can_mod},
|
||||
newtypes::{CommunityId, PaginationCursor, PersonId},
|
||||
schema::{
|
||||
comment,
|
||||
|
@ -32,26 +31,17 @@ use lemmy_db_schema::{
|
|||
community,
|
||||
community_actions,
|
||||
image_details,
|
||||
instance_actions,
|
||||
local_user,
|
||||
person,
|
||||
person_actions,
|
||||
post,
|
||||
post_actions,
|
||||
post_tag,
|
||||
search_combined,
|
||||
tag,
|
||||
},
|
||||
source::combined::search::{search_combined_keys as key, SearchCombined},
|
||||
traits::{InternalToCombinedView, PaginationCursorBuilder},
|
||||
utils::{
|
||||
functions::coalesce,
|
||||
fuzzy_search,
|
||||
get_conn,
|
||||
now,
|
||||
seconds_to_pg_interval,
|
||||
DbPool,
|
||||
ReverseTimestampKey,
|
||||
},
|
||||
utils::{fuzzy_search, get_conn, now, seconds_to_pg_interval, DbPool, ReverseTimestampKey},
|
||||
ListingType,
|
||||
SearchSortType,
|
||||
SearchType,
|
||||
|
@ -128,6 +118,12 @@ impl SearchCombinedViewInternal {
|
|||
.and(community_actions::person_id.nullable().eq(my_person_id)),
|
||||
);
|
||||
|
||||
let instance_actions_join = instance_actions::table.on(
|
||||
instance_actions::instance_id
|
||||
.eq(person::instance_id)
|
||||
.and(instance_actions::person_id.nullable().eq(my_person_id)),
|
||||
);
|
||||
|
||||
let post_actions_join = post_actions::table.on(
|
||||
post_actions::post_id
|
||||
.eq(post::id)
|
||||
|
@ -158,6 +154,7 @@ impl SearchCombinedViewInternal {
|
|||
.left_join(local_user_join)
|
||||
.left_join(creator_local_user_join)
|
||||
.left_join(community_actions_join)
|
||||
.left_join(instance_actions_join)
|
||||
.left_join(post_actions_join)
|
||||
.left_join(person_actions_join)
|
||||
.left_join(comment_actions_join)
|
||||
|
@ -230,53 +227,8 @@ impl SearchCombinedQuery {
|
|||
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
let post_tags = post_tag::table
|
||||
.inner_join(tag::table)
|
||||
.select(diesel::dsl::sql::<diesel::sql_types::Json>(
|
||||
"json_agg(tag.*)",
|
||||
))
|
||||
.filter(post_tag::post_id.eq(post::id))
|
||||
.filter(tag::deleted.eq(false))
|
||||
.single_value();
|
||||
|
||||
let mut query = SearchCombinedViewInternal::joins(my_person_id)
|
||||
.select((
|
||||
// Post-specific
|
||||
post::all_columns.nullable(),
|
||||
coalesce(
|
||||
post::comments.nullable() - post_actions::read_comments_amount.nullable(),
|
||||
post::comments,
|
||||
)
|
||||
.nullable(),
|
||||
post_actions::saved.nullable(),
|
||||
post_actions::read.nullable().is_not_null(),
|
||||
post_actions::hidden.nullable().is_not_null(),
|
||||
post_actions::like_score.nullable(),
|
||||
image_details::all_columns.nullable(),
|
||||
post_tags,
|
||||
// Comment-specific
|
||||
comment::all_columns.nullable(),
|
||||
comment_actions::saved.nullable(),
|
||||
comment_actions::like_score.nullable(),
|
||||
// Community-specific
|
||||
community::all_columns.nullable(),
|
||||
community_actions::blocked.nullable().is_not_null(),
|
||||
community_follower_select_subscribed_type(),
|
||||
// // Shared
|
||||
person::all_columns.nullable(),
|
||||
local_user::admin.nullable().is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::became_moderator)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::received_ban)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
person_actions::blocked.nullable().is_not_null(),
|
||||
community_actions::received_ban.nullable().is_not_null(),
|
||||
local_user_can_mod(),
|
||||
))
|
||||
.select(SearchCombinedViewInternal::as_select())
|
||||
.into_boxed();
|
||||
|
||||
// The filters
|
||||
|
@ -359,13 +311,14 @@ impl SearchCombinedQuery {
|
|||
query = query.filter(
|
||||
community::local
|
||||
.eq(true)
|
||||
.and(filter_not_hidden_or_is_subscribed())
|
||||
.and(filter_not_unlisted_or_is_subscribed())
|
||||
.or(search_combined::person_id.is_not_null().and(person::local)),
|
||||
);
|
||||
}
|
||||
ListingType::All => {
|
||||
query = query
|
||||
.filter(filter_not_hidden_or_is_subscribed().or(search_combined::person_id.is_not_null()))
|
||||
query = query.filter(
|
||||
filter_not_unlisted_or_is_subscribed().or(search_combined::person_id.is_not_null()),
|
||||
)
|
||||
}
|
||||
ListingType::ModeratorView => {
|
||||
query = query.filter(community_actions::became_moderator.is_not_null());
|
||||
|
@ -425,47 +378,35 @@ impl InternalToCombinedView for SearchCombinedViewInternal {
|
|||
post,
|
||||
community,
|
||||
creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
community_actions: v.community_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
person_actions: v.person_actions,
|
||||
comment_actions: v.comment_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.comment_saved,
|
||||
my_vote: v.my_comment_vote,
|
||||
banned_from_community: v.banned_from_community,
|
||||
can_mod: v.can_mod,
|
||||
}))
|
||||
} else if let (Some(post), Some(creator), Some(community), Some(unread_comments)) = (
|
||||
v.post,
|
||||
v.item_creator.clone(),
|
||||
v.community.clone(),
|
||||
v.post_unread_comments,
|
||||
) {
|
||||
} else if let (Some(post), Some(creator), Some(community)) =
|
||||
(v.post, v.item_creator.clone(), v.community.clone())
|
||||
{
|
||||
Some(SearchCombinedView::Post(PostView {
|
||||
post,
|
||||
community,
|
||||
unread_comments,
|
||||
creator,
|
||||
creator_banned_from_community: v.item_creator_banned_from_community,
|
||||
creator_is_moderator: v.item_creator_is_moderator,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
creator_blocked: v.item_creator_blocked,
|
||||
subscribed: v.subscribed,
|
||||
saved: v.post_saved,
|
||||
read: v.post_read,
|
||||
hidden: v.post_hidden,
|
||||
my_vote: v.my_post_vote,
|
||||
image_details: v.image_details,
|
||||
banned_from_community: v.banned_from_community,
|
||||
tags: v.post_tags,
|
||||
community_actions: v.community_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
person_actions: v.person_actions,
|
||||
post_actions: v.post_actions,
|
||||
can_mod: v.can_mod,
|
||||
}))
|
||||
} else if let Some(community) = v.community {
|
||||
Some(SearchCombinedView::Community(CommunityView {
|
||||
community,
|
||||
subscribed: v.subscribed,
|
||||
blocked: v.community_blocked,
|
||||
banned_from_community: v.banned_from_community,
|
||||
community_actions: v.community_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
can_mod: v.can_mod,
|
||||
}))
|
||||
} else if let Some(person) = v.item_creator {
|
||||
|
@ -490,12 +431,12 @@ mod tests {
|
|||
use lemmy_db_schema::{
|
||||
assert_length,
|
||||
source::{
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm, CommentUpdateForm},
|
||||
comment::{Comment, CommentActions, CommentInsertForm, CommentLikeForm, CommentUpdateForm},
|
||||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
local_user::{LocalUser, LocalUserInsertForm},
|
||||
person::{Person, PersonInsertForm},
|
||||
post::{Post, PostInsertForm, PostLike, PostLikeForm, PostUpdateForm},
|
||||
post::{Post, PostActions, PostInsertForm, PostLikeForm, PostUpdateForm},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
utils::{build_db_pool_for_tests, DbPool},
|
||||
|
@ -583,34 +524,22 @@ mod tests {
|
|||
|
||||
// Timmy likes and dislikes a few things
|
||||
let timmy_like_post_form = PostLikeForm::new(timmy_post.id, timmy.id, 1);
|
||||
PostLike::like(pool, &timmy_like_post_form).await?;
|
||||
PostActions::like(pool, &timmy_like_post_form).await?;
|
||||
|
||||
let timmy_like_sara_post_form = PostLikeForm::new(sara_post.id, timmy.id, 1);
|
||||
PostLike::like(pool, &timmy_like_sara_post_form).await?;
|
||||
PostActions::like(pool, &timmy_like_sara_post_form).await?;
|
||||
|
||||
let timmy_dislike_post_form = PostLikeForm::new(timmy_post_2.id, timmy.id, -1);
|
||||
PostLike::like(pool, &timmy_dislike_post_form).await?;
|
||||
PostActions::like(pool, &timmy_dislike_post_form).await?;
|
||||
|
||||
let timmy_like_comment_form = CommentLikeForm {
|
||||
person_id: timmy.id,
|
||||
comment_id: timmy_comment.id,
|
||||
score: 1,
|
||||
};
|
||||
CommentLike::like(pool, &timmy_like_comment_form).await?;
|
||||
let timmy_like_comment_form = CommentLikeForm::new(timmy.id, timmy_comment.id, 1);
|
||||
CommentActions::like(pool, &timmy_like_comment_form).await?;
|
||||
|
||||
let timmy_like_sara_comment_form = CommentLikeForm {
|
||||
person_id: timmy.id,
|
||||
comment_id: sara_comment.id,
|
||||
score: 1,
|
||||
};
|
||||
CommentLike::like(pool, &timmy_like_sara_comment_form).await?;
|
||||
let timmy_like_sara_comment_form = CommentLikeForm::new(timmy.id, sara_comment.id, 1);
|
||||
CommentActions::like(pool, &timmy_like_sara_comment_form).await?;
|
||||
|
||||
let timmy_dislike_sara_comment_form = CommentLikeForm {
|
||||
person_id: timmy.id,
|
||||
comment_id: sara_comment_2.id,
|
||||
score: -1,
|
||||
};
|
||||
CommentLike::like(pool, &timmy_dislike_sara_comment_form).await?;
|
||||
let timmy_dislike_sara_comment_form = CommentLikeForm::new(timmy.id, sara_comment_2.id, -1);
|
||||
CommentActions::like(pool, &timmy_dislike_sara_comment_form).await?;
|
||||
|
||||
Ok(Data {
|
||||
instance,
|
||||
|
|
|
@ -117,29 +117,18 @@ impl CommentView {
|
|||
);
|
||||
}
|
||||
|
||||
let mut res = query.first::<Self>(conn).await?;
|
||||
|
||||
// If a person is given, then my_vote (res.9), if None, should be 0, not null
|
||||
// Necessary to differentiate between other person's votes
|
||||
if my_local_user.is_some() && res.my_vote.is_none() {
|
||||
res.my_vote = Some(0);
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
query.first::<Self>(conn).await
|
||||
}
|
||||
|
||||
pub fn map_to_slim(self) -> CommentSlimView {
|
||||
CommentSlimView {
|
||||
comment: self.comment,
|
||||
creator: self.creator,
|
||||
creator_banned_from_community: self.creator_banned_from_community,
|
||||
banned_from_community: self.banned_from_community,
|
||||
creator_is_moderator: self.creator_is_moderator,
|
||||
comment_actions: self.comment_actions,
|
||||
creator_community_actions: self.creator_community_actions,
|
||||
person_actions: self.person_actions,
|
||||
instance_actions: self.instance_actions,
|
||||
creator_is_admin: self.creator_is_admin,
|
||||
subscribed: self.subscribed,
|
||||
saved: self.saved,
|
||||
creator_blocked: self.creator_blocked,
|
||||
my_vote: self.my_vote,
|
||||
can_mod: self.can_mod,
|
||||
}
|
||||
}
|
||||
|
@ -328,34 +317,30 @@ mod tests {
|
|||
use lemmy_db_schema::{
|
||||
assert_length,
|
||||
impls::actor_language::UNDETERMINED_ID,
|
||||
newtypes::{CommentId, LanguageId},
|
||||
newtypes::CommentId,
|
||||
source::{
|
||||
actor_language::LocalUserLanguage,
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm, CommentUpdateForm},
|
||||
comment::{Comment, CommentActions, CommentInsertForm, CommentLikeForm, CommentUpdateForm},
|
||||
community::{
|
||||
Community,
|
||||
CommunityFollower,
|
||||
CommunityActions,
|
||||
CommunityFollowerForm,
|
||||
CommunityFollowerState,
|
||||
CommunityInsertForm,
|
||||
CommunityModerator,
|
||||
CommunityModeratorForm,
|
||||
CommunityPersonBan,
|
||||
CommunityPersonBanForm,
|
||||
CommunityUpdateForm,
|
||||
},
|
||||
instance::Instance,
|
||||
language::Language,
|
||||
local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm},
|
||||
person::{Person, PersonInsertForm},
|
||||
person_block::{PersonBlock, PersonBlockForm},
|
||||
person::{Person, PersonActions, PersonBlockForm, PersonInsertForm},
|
||||
post::{Post, PostInsertForm, PostUpdateForm},
|
||||
site::{Site, SiteInsertForm},
|
||||
},
|
||||
traits::{Bannable, Blockable, Crud, Followable, Joinable, Likeable},
|
||||
utils::{build_db_pool_for_tests, RANK_DEFAULT},
|
||||
utils::build_db_pool_for_tests,
|
||||
CommunityVisibility,
|
||||
SubscribedType,
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
@ -366,7 +351,7 @@ mod tests {
|
|||
inserted_comment_0: Comment,
|
||||
inserted_comment_1: Comment,
|
||||
inserted_comment_2: Comment,
|
||||
inserted_comment_5: Comment,
|
||||
_inserted_comment_5: Comment,
|
||||
inserted_post: Post,
|
||||
timmy_local_user_view: LocalUserView,
|
||||
inserted_sara_person: Person,
|
||||
|
@ -474,30 +459,26 @@ mod tests {
|
|||
inserted_post.id,
|
||||
"Comment 5".into(),
|
||||
);
|
||||
let inserted_comment_5 =
|
||||
let _inserted_comment_5 =
|
||||
Comment::create(pool, &comment_form_5, Some(&inserted_comment_4.path)).await?;
|
||||
|
||||
let timmy_blocks_sara_form = PersonBlockForm {
|
||||
person_id: inserted_timmy_person.id,
|
||||
target_id: inserted_sara_person.id,
|
||||
};
|
||||
let timmy_blocks_sara_form =
|
||||
PersonBlockForm::new(inserted_timmy_person.id, inserted_sara_person.id);
|
||||
let inserted_block = PersonActions::block(pool, &timmy_blocks_sara_form).await?;
|
||||
|
||||
let inserted_block = PersonBlock::block(pool, &timmy_blocks_sara_form).await?;
|
||||
assert_eq!(
|
||||
(inserted_timmy_person.id, inserted_sara_person.id, true),
|
||||
(
|
||||
inserted_block.person_id,
|
||||
inserted_block.target_id,
|
||||
inserted_block.blocked.is_some()
|
||||
)
|
||||
);
|
||||
|
||||
let expected_block = PersonBlock {
|
||||
person_id: inserted_timmy_person.id,
|
||||
target_id: inserted_sara_person.id,
|
||||
published: inserted_block.published,
|
||||
};
|
||||
assert_eq!(expected_block, inserted_block);
|
||||
let comment_like_form =
|
||||
CommentLikeForm::new(inserted_timmy_person.id, inserted_comment_0.id, 1);
|
||||
|
||||
let comment_like_form = CommentLikeForm {
|
||||
comment_id: inserted_comment_0.id,
|
||||
person_id: inserted_timmy_person.id,
|
||||
score: 1,
|
||||
};
|
||||
|
||||
let _inserted_comment_like = CommentLike::like(pool, &comment_like_form).await?;
|
||||
CommentActions::like(pool, &comment_like_form).await?;
|
||||
|
||||
let timmy_local_user_view = LocalUserView {
|
||||
local_user: inserted_timmy_local_user.clone(),
|
||||
|
@ -510,7 +491,7 @@ mod tests {
|
|||
inserted_comment_0,
|
||||
inserted_comment_1,
|
||||
inserted_comment_2,
|
||||
inserted_comment_5,
|
||||
_inserted_comment_5,
|
||||
inserted_post,
|
||||
timmy_local_user_view,
|
||||
inserted_sara_person,
|
||||
|
@ -526,12 +507,6 @@ mod tests {
|
|||
let pool = &mut pool.into();
|
||||
let data = init_data(pool).await?;
|
||||
|
||||
let expected_comment_view_no_person = expected_comment_view(&data);
|
||||
|
||||
let mut expected_comment_view_with_person = expected_comment_view_no_person.clone();
|
||||
expected_comment_view_with_person.my_vote = Some(1);
|
||||
expected_comment_view_with_person.can_mod = true;
|
||||
|
||||
let read_comment_views_no_person = CommentQuery {
|
||||
sort: (Some(CommentSortType::Old)),
|
||||
post_id: (Some(data.inserted_post.id)),
|
||||
|
@ -540,10 +515,8 @@ mod tests {
|
|||
.list(&data.site, pool)
|
||||
.await?;
|
||||
|
||||
assert_eq!(
|
||||
Some(&expected_comment_view_no_person),
|
||||
read_comment_views_no_person.first()
|
||||
);
|
||||
assert!(read_comment_views_no_person[0].comment_actions.is_none());
|
||||
assert!(!read_comment_views_no_person[0].can_mod);
|
||||
|
||||
let read_comment_views_with_person = CommentQuery {
|
||||
sort: (Some(CommentSortType::Old)),
|
||||
|
@ -554,10 +527,11 @@ mod tests {
|
|||
.list(&data.site, pool)
|
||||
.await?;
|
||||
|
||||
assert_eq!(
|
||||
expected_comment_view_with_person,
|
||||
read_comment_views_with_person[0]
|
||||
);
|
||||
assert!(read_comment_views_with_person[0]
|
||||
.comment_actions
|
||||
.as_ref()
|
||||
.is_some_and(|x| x.like_score == Some(1)));
|
||||
assert!(read_comment_views_with_person[0].can_mod);
|
||||
|
||||
// Make sure its 1, not showing the blocked comment
|
||||
assert_length!(5, read_comment_views_with_person);
|
||||
|
@ -570,7 +544,9 @@ mod tests {
|
|||
.await?;
|
||||
|
||||
// Make sure block set the creator blocked
|
||||
assert!(read_comment_from_blocked_person.creator_blocked);
|
||||
assert!(read_comment_from_blocked_person
|
||||
.person_actions
|
||||
.is_some_and(|x| x.blocked.is_some()));
|
||||
|
||||
cleanup(data, pool).await
|
||||
}
|
||||
|
@ -583,19 +559,19 @@ mod tests {
|
|||
let data = init_data(pool).await?;
|
||||
|
||||
// Unblock sara first
|
||||
let timmy_unblocks_sara_form = PersonBlockForm {
|
||||
person_id: data.timmy_local_user_view.person.id,
|
||||
target_id: data.inserted_sara_person.id,
|
||||
};
|
||||
PersonBlock::unblock(pool, &timmy_unblocks_sara_form).await?;
|
||||
let timmy_unblocks_sara_form = PersonBlockForm::new(
|
||||
data.timmy_local_user_view.person.id,
|
||||
data.inserted_sara_person.id,
|
||||
);
|
||||
PersonActions::unblock(pool, &timmy_unblocks_sara_form).await?;
|
||||
|
||||
// Like a new comment
|
||||
let comment_like_form = CommentLikeForm {
|
||||
comment_id: data.inserted_comment_1.id,
|
||||
person_id: data.timmy_local_user_view.person.id,
|
||||
score: 1,
|
||||
};
|
||||
CommentLike::like(pool, &comment_like_form).await?;
|
||||
let comment_like_form = CommentLikeForm::new(
|
||||
data.timmy_local_user_view.person.id,
|
||||
data.inserted_comment_1.id,
|
||||
1,
|
||||
);
|
||||
CommentActions::like(pool, &comment_like_form).await?;
|
||||
|
||||
let read_liked_comment_views = CommentQuery {
|
||||
local_user: Some(&data.timmy_local_user_view.local_user),
|
||||
|
@ -672,10 +648,6 @@ mod tests {
|
|||
.await?;
|
||||
|
||||
// Make sure a depth limited one only has the top comment
|
||||
assert_eq!(
|
||||
expected_comment_view(&data),
|
||||
read_comment_views_top_max_depth[0]
|
||||
);
|
||||
assert_length!(1, read_comment_views_top_max_depth);
|
||||
|
||||
let child_path = data.inserted_comment_1.path.clone();
|
||||
|
@ -793,11 +765,8 @@ mod tests {
|
|||
// Make one of the inserted persons a moderator
|
||||
let person_id = data.inserted_sara_person.id;
|
||||
let community_id = data.inserted_community.id;
|
||||
let form = CommunityModeratorForm {
|
||||
community_id,
|
||||
person_id,
|
||||
};
|
||||
CommunityModerator::join(pool, &form).await?;
|
||||
let form = CommunityModeratorForm::new(community_id, person_id);
|
||||
CommunityActions::join(pool, &form).await?;
|
||||
|
||||
// Make sure that they come back as a mod in the list
|
||||
let comments = CommentQuery {
|
||||
|
@ -808,8 +777,12 @@ mod tests {
|
|||
.await?;
|
||||
|
||||
assert_eq!(comments[1].creator.name, "sara");
|
||||
assert!(comments[1].creator_is_moderator);
|
||||
assert!(!comments[0].creator_is_moderator);
|
||||
assert!(comments[1]
|
||||
.creator_community_actions
|
||||
.as_ref()
|
||||
.is_some_and(|x| x.became_moderator.is_some()));
|
||||
|
||||
assert!(comments[0].creator_community_actions.is_none());
|
||||
|
||||
cleanup(data, pool).await
|
||||
}
|
||||
|
@ -840,7 +813,7 @@ mod tests {
|
|||
}
|
||||
|
||||
async fn cleanup(data: Data, pool: &mut DbPool<'_>) -> LemmyResult<()> {
|
||||
CommentLike::remove(
|
||||
CommentActions::remove_like(
|
||||
pool,
|
||||
data.timmy_local_user_view.person.id,
|
||||
data.inserted_comment_0.id,
|
||||
|
@ -859,147 +832,6 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn expected_comment_view(data: &Data) -> CommentView {
|
||||
CommentView {
|
||||
creator_banned_from_community: false,
|
||||
banned_from_community: false,
|
||||
creator_is_moderator: false,
|
||||
creator_is_admin: true,
|
||||
my_vote: None,
|
||||
subscribed: SubscribedType::NotSubscribed,
|
||||
saved: None,
|
||||
creator_blocked: false,
|
||||
can_mod: false,
|
||||
comment: Comment {
|
||||
id: data.inserted_comment_0.id,
|
||||
content: "Comment 0".into(),
|
||||
creator_id: data.timmy_local_user_view.person.id,
|
||||
post_id: data.inserted_post.id,
|
||||
removed: false,
|
||||
deleted: false,
|
||||
published: data.inserted_comment_0.published,
|
||||
ap_id: data.inserted_comment_0.ap_id.clone(),
|
||||
updated: None,
|
||||
local: true,
|
||||
distinguished: false,
|
||||
path: data.inserted_comment_0.clone().path,
|
||||
language_id: LanguageId(37),
|
||||
score: 1,
|
||||
upvotes: 1,
|
||||
downvotes: 0,
|
||||
child_count: 5,
|
||||
hot_rank: RANK_DEFAULT,
|
||||
controversy_rank: 0.0,
|
||||
report_count: 0,
|
||||
unresolved_report_count: 0,
|
||||
},
|
||||
creator: Person {
|
||||
id: data.timmy_local_user_view.person.id,
|
||||
name: "timmy".into(),
|
||||
display_name: None,
|
||||
published: data.timmy_local_user_view.person.published,
|
||||
avatar: None,
|
||||
ap_id: data.timmy_local_user_view.person.ap_id.clone(),
|
||||
local: true,
|
||||
banned: false,
|
||||
deleted: false,
|
||||
bot_account: false,
|
||||
bio: None,
|
||||
banner: None,
|
||||
updated: None,
|
||||
inbox_url: data.timmy_local_user_view.person.inbox_url.clone(),
|
||||
matrix_user_id: None,
|
||||
ban_expires: None,
|
||||
instance_id: data.inserted_instance.id,
|
||||
private_key: data.timmy_local_user_view.person.private_key.clone(),
|
||||
public_key: data.timmy_local_user_view.person.public_key.clone(),
|
||||
last_refreshed_at: data.timmy_local_user_view.person.last_refreshed_at,
|
||||
post_count: 1,
|
||||
post_score: 0,
|
||||
comment_count: 5,
|
||||
comment_score: 1,
|
||||
},
|
||||
post: Post {
|
||||
id: data.inserted_post.id,
|
||||
name: data.inserted_post.name.clone(),
|
||||
creator_id: data.timmy_local_user_view.person.id,
|
||||
url: None,
|
||||
body: None,
|
||||
alt_text: None,
|
||||
published: data.inserted_post.published,
|
||||
updated: None,
|
||||
community_id: data.inserted_community.id,
|
||||
removed: false,
|
||||
deleted: false,
|
||||
locked: false,
|
||||
nsfw: false,
|
||||
embed_title: None,
|
||||
embed_description: None,
|
||||
embed_video_url: None,
|
||||
thumbnail_url: None,
|
||||
ap_id: data.inserted_post.ap_id.clone(),
|
||||
local: true,
|
||||
language_id: Default::default(),
|
||||
featured_community: false,
|
||||
featured_local: false,
|
||||
url_content_type: None,
|
||||
scheduled_publish_time: None,
|
||||
comments: 6,
|
||||
score: 0,
|
||||
upvotes: 0,
|
||||
downvotes: 0,
|
||||
newest_comment_time_necro: data.inserted_comment_1.published,
|
||||
newest_comment_time: data.inserted_comment_5.published,
|
||||
hot_rank: RANK_DEFAULT,
|
||||
hot_rank_active: RANK_DEFAULT,
|
||||
controversy_rank: 0.0,
|
||||
scaled_rank: RANK_DEFAULT,
|
||||
instance_id: data.inserted_instance.id,
|
||||
report_count: 0,
|
||||
unresolved_report_count: 0,
|
||||
},
|
||||
community: Community {
|
||||
id: data.inserted_community.id,
|
||||
name: "test community 5".to_string(),
|
||||
icon: None,
|
||||
removed: false,
|
||||
deleted: false,
|
||||
nsfw: false,
|
||||
ap_id: data.inserted_community.ap_id.clone(),
|
||||
local: true,
|
||||
title: "nada".to_owned(),
|
||||
sidebar: None,
|
||||
description: None,
|
||||
updated: None,
|
||||
banner: None,
|
||||
posting_restricted_to_mods: false,
|
||||
published: data.inserted_community.published,
|
||||
instance_id: data.inserted_instance.id,
|
||||
private_key: data.inserted_community.private_key.clone(),
|
||||
public_key: data.inserted_community.public_key.clone(),
|
||||
last_refreshed_at: data.inserted_community.last_refreshed_at,
|
||||
followers_url: data.inserted_community.followers_url.clone(),
|
||||
inbox_url: data.inserted_community.inbox_url.clone(),
|
||||
moderators_url: data.inserted_community.moderators_url.clone(),
|
||||
featured_url: data.inserted_community.featured_url.clone(),
|
||||
visibility: CommunityVisibility::Public,
|
||||
random_number: data.inserted_community.random_number,
|
||||
subscribers: 0,
|
||||
posts: 1,
|
||||
comments: 6,
|
||||
users_active_day: 0,
|
||||
users_active_week: 0,
|
||||
users_active_month: 0,
|
||||
users_active_half_year: 0,
|
||||
hot_rank: RANK_DEFAULT,
|
||||
subscribers_local: 0,
|
||||
report_count: 0,
|
||||
unresolved_report_count: 0,
|
||||
interactions_month: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn local_only_instance() -> LemmyResult<()> {
|
||||
|
@ -1065,13 +897,12 @@ mod tests {
|
|||
)
|
||||
.await?;
|
||||
|
||||
CommunityPersonBan::ban(
|
||||
CommunityActions::ban(
|
||||
pool,
|
||||
&CommunityPersonBanForm {
|
||||
community_id: data.inserted_community.id,
|
||||
person_id: inserted_banned_from_comm_person.id,
|
||||
expires: None,
|
||||
},
|
||||
&CommunityPersonBanForm::new(
|
||||
data.inserted_community.id,
|
||||
inserted_banned_from_comm_person.id,
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -1082,7 +913,9 @@ mod tests {
|
|||
)
|
||||
.await?;
|
||||
|
||||
assert!(comment_view.banned_from_community);
|
||||
assert!(comment_view
|
||||
.community_actions
|
||||
.is_some_and(|x| x.received_ban.is_some()));
|
||||
|
||||
Person::delete(pool, inserted_banned_from_comm_person.id).await?;
|
||||
cleanup(data, pool).await
|
||||
|
@ -1102,7 +935,7 @@ mod tests {
|
|||
)
|
||||
.await?;
|
||||
|
||||
assert!(!comment_view.banned_from_community);
|
||||
assert!(comment_view.community_actions.is_none());
|
||||
|
||||
cleanup(data, pool).await
|
||||
}
|
||||
|
@ -1198,15 +1031,13 @@ mod tests {
|
|||
data.timmy_local_user_view.local_user.admin = false;
|
||||
|
||||
// User can view after following
|
||||
CommunityFollower::follow(
|
||||
CommunityActions::follow(
|
||||
pool,
|
||||
&CommunityFollowerForm {
|
||||
state: Some(CommunityFollowerState::Accepted),
|
||||
..CommunityFollowerForm::new(
|
||||
data.inserted_community.id,
|
||||
data.timmy_local_user_view.person.id,
|
||||
)
|
||||
},
|
||||
&CommunityFollowerForm::new(
|
||||
data.inserted_community.id,
|
||||
data.timmy_local_user_view.person.id,
|
||||
CommunityFollowerState::Accepted,
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
let read_comment_listing = CommentQuery {
|
||||
|
|
|
@ -7,12 +7,12 @@ use diesel::{
|
|||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
JoinOnDsl,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
SelectableHelper,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_db_schema::{
|
||||
impls::community::community_follower_select_subscribed_type,
|
||||
newtypes::{CommunityId, DbUrl, InstanceId, PersonId},
|
||||
schema::{community, community_actions, person},
|
||||
source::{
|
||||
|
@ -21,7 +21,6 @@ use lemmy_db_schema::{
|
|||
},
|
||||
utils::{get_conn, limit_and_offset, DbPool},
|
||||
CommunityVisibility,
|
||||
SubscribedType,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
|
||||
|
@ -151,7 +150,7 @@ impl CommunityFollowerView {
|
|||
person::all_columns,
|
||||
community::all_columns,
|
||||
is_new_instance,
|
||||
community_follower_select_subscribed_type(),
|
||||
community_actions::follow_state.nullable(),
|
||||
))
|
||||
.into_boxed();
|
||||
if all_communities {
|
||||
|
@ -168,17 +167,17 @@ impl CommunityFollowerView {
|
|||
.order_by(community_actions::followed.asc())
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load::<(Person, Community, bool, SubscribedType)>(conn)
|
||||
.load::<(Person, Community, bool, Option<CommunityFollowerState>)>(conn)
|
||||
.await?;
|
||||
Ok(
|
||||
res
|
||||
.into_iter()
|
||||
.map(
|
||||
|(person, community, is_new_instance, subscribed)| PendingFollow {
|
||||
|(person, community, is_new_instance, follow_state)| PendingFollow {
|
||||
person,
|
||||
community,
|
||||
is_new_instance,
|
||||
subscribed,
|
||||
follow_state,
|
||||
},
|
||||
)
|
||||
.collect(),
|
||||
|
@ -259,7 +258,7 @@ mod tests {
|
|||
use super::*;
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::{CommunityFollower, CommunityFollowerForm, CommunityInsertForm},
|
||||
community::{CommunityActions, CommunityFollowerForm, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
person::PersonInsertForm,
|
||||
},
|
||||
|
@ -300,11 +299,12 @@ mod tests {
|
|||
assert!(has_followers.is_err());
|
||||
|
||||
// insert unapproved follower
|
||||
let mut follower_form = CommunityFollowerForm {
|
||||
state: Some(CommunityFollowerState::ApprovalRequired),
|
||||
..CommunityFollowerForm::new(community.id, person.id)
|
||||
};
|
||||
CommunityFollower::follow(pool, &follower_form).await?;
|
||||
let mut follower_form = CommunityFollowerForm::new(
|
||||
community.id,
|
||||
person.id,
|
||||
CommunityFollowerState::ApprovalRequired,
|
||||
);
|
||||
CommunityActions::follow(pool, &follower_form).await?;
|
||||
|
||||
// still returns error
|
||||
let has_followers = CommunityFollowerView::check_has_followers_from_instance(
|
||||
|
@ -316,8 +316,8 @@ mod tests {
|
|||
assert!(has_followers.is_err());
|
||||
|
||||
// mark follower as accepted
|
||||
follower_form.state = Some(CommunityFollowerState::Accepted);
|
||||
CommunityFollower::follow(pool, &follower_form).await?;
|
||||
follower_form.follow_state = CommunityFollowerState::Accepted;
|
||||
CommunityActions::follow(pool, &follower_form).await?;
|
||||
|
||||
// now returns ok
|
||||
let has_followers = CommunityFollowerView::check_has_followers_from_instance(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
structs::{CommunityModeratorView, CommunitySortType, CommunityView, PersonView},
|
||||
utils::{filter_is_subscribed, filter_not_hidden_or_is_subscribed},
|
||||
utils::{filter_is_subscribed, filter_not_unlisted_or_is_subscribed},
|
||||
};
|
||||
use diesel::{
|
||||
result::Error,
|
||||
|
@ -131,16 +131,16 @@ impl CommunityQuery<'_> {
|
|||
if !o.is_mod_or_admin {
|
||||
query = query
|
||||
.filter(Community::hide_removed_and_deleted())
|
||||
.filter(filter_not_hidden_or_is_subscribed());
|
||||
.filter(filter_not_unlisted_or_is_subscribed());
|
||||
}
|
||||
|
||||
if let Some(listing_type) = o.listing_type {
|
||||
query = match listing_type {
|
||||
ListingType::All => query.filter(filter_not_hidden_or_is_subscribed()),
|
||||
ListingType::All => query.filter(filter_not_unlisted_or_is_subscribed()),
|
||||
ListingType::Subscribed => query.filter(filter_is_subscribed()),
|
||||
ListingType::Local => query
|
||||
.filter(community::local.eq(true))
|
||||
.filter(filter_not_hidden_or_is_subscribed()),
|
||||
.filter(filter_not_unlisted_or_is_subscribed()),
|
||||
ListingType::ModeratorView => {
|
||||
query.filter(community_actions::became_moderator.is_not_null())
|
||||
}
|
||||
|
@ -199,11 +199,10 @@ mod tests {
|
|||
source::{
|
||||
community::{
|
||||
Community,
|
||||
CommunityFollower,
|
||||
CommunityActions,
|
||||
CommunityFollowerForm,
|
||||
CommunityFollowerState,
|
||||
CommunityInsertForm,
|
||||
CommunityModerator,
|
||||
CommunityModeratorForm,
|
||||
CommunityUpdateForm,
|
||||
},
|
||||
|
@ -215,7 +214,6 @@ mod tests {
|
|||
traits::{Crud, Followable, Joinable},
|
||||
utils::{build_db_pool_for_tests, DbPool},
|
||||
CommunityVisibility,
|
||||
SubscribedType,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
use serial_test::serial;
|
||||
|
@ -312,28 +310,31 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn subscribe_state() -> LemmyResult<()> {
|
||||
async fn follow_state() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests();
|
||||
let pool = &mut pool.into();
|
||||
let data = init_data(pool).await?;
|
||||
let community = &data.communities[0];
|
||||
|
||||
let unauthenticated = CommunityView::read(pool, community.id, None, false).await?;
|
||||
assert_eq!(SubscribedType::NotSubscribed, unauthenticated.subscribed);
|
||||
assert!(unauthenticated.community_actions.is_none());
|
||||
|
||||
let authenticated =
|
||||
CommunityView::read(pool, community.id, Some(&data.local_user), false).await?;
|
||||
assert_eq!(SubscribedType::NotSubscribed, authenticated.subscribed);
|
||||
assert!(authenticated.community_actions.is_none());
|
||||
|
||||
let form = CommunityFollowerForm {
|
||||
state: Some(CommunityFollowerState::Pending),
|
||||
..CommunityFollowerForm::new(community.id, data.local_user.person_id)
|
||||
};
|
||||
CommunityFollower::follow(pool, &form).await?;
|
||||
let form = CommunityFollowerForm::new(
|
||||
community.id,
|
||||
data.local_user.person_id,
|
||||
CommunityFollowerState::Pending,
|
||||
);
|
||||
CommunityActions::follow(pool, &form).await?;
|
||||
|
||||
let with_pending_follow =
|
||||
CommunityView::read(pool, community.id, Some(&data.local_user), false).await?;
|
||||
assert_eq!(SubscribedType::Pending, with_pending_follow.subscribed);
|
||||
assert!(with_pending_follow
|
||||
.community_actions
|
||||
.is_some_and(|x| x.follow_state == Some(CommunityFollowerState::Pending)));
|
||||
|
||||
// mark community private and set follow as approval required
|
||||
Community::update(
|
||||
|
@ -345,27 +346,30 @@ mod tests {
|
|||
},
|
||||
)
|
||||
.await?;
|
||||
let form = CommunityFollowerForm {
|
||||
state: Some(CommunityFollowerState::ApprovalRequired),
|
||||
..CommunityFollowerForm::new(community.id, data.local_user.person_id)
|
||||
};
|
||||
CommunityFollower::follow(pool, &form).await?;
|
||||
let form = CommunityFollowerForm::new(
|
||||
community.id,
|
||||
data.local_user.person_id,
|
||||
CommunityFollowerState::ApprovalRequired,
|
||||
);
|
||||
CommunityActions::follow(pool, &form).await?;
|
||||
|
||||
let with_approval_required_follow =
|
||||
CommunityView::read(pool, community.id, Some(&data.local_user), false).await?;
|
||||
assert_eq!(
|
||||
SubscribedType::ApprovalRequired,
|
||||
with_approval_required_follow.subscribed
|
||||
);
|
||||
assert!(with_approval_required_follow
|
||||
.community_actions
|
||||
.is_some_and(|x| x.follow_state == Some(CommunityFollowerState::ApprovalRequired)));
|
||||
|
||||
let form = CommunityFollowerForm {
|
||||
state: Some(CommunityFollowerState::Accepted),
|
||||
..CommunityFollowerForm::new(community.id, data.local_user.person_id)
|
||||
};
|
||||
CommunityFollower::follow(pool, &form).await?;
|
||||
let form = CommunityFollowerForm::new(
|
||||
community.id,
|
||||
data.local_user.person_id,
|
||||
CommunityFollowerState::Accepted,
|
||||
);
|
||||
CommunityActions::follow(pool, &form).await?;
|
||||
let with_accepted_follow =
|
||||
CommunityView::read(pool, community.id, Some(&data.local_user), false).await?;
|
||||
assert_eq!(SubscribedType::Subscribed, with_accepted_follow.subscribed);
|
||||
assert!(with_accepted_follow
|
||||
.community_actions
|
||||
.is_some_and(|x| x.follow_state == Some(CommunityFollowerState::Accepted)));
|
||||
|
||||
cleanup(data, pool).await
|
||||
}
|
||||
|
@ -463,17 +467,11 @@ mod tests {
|
|||
let person_id = data.local_user.person_id;
|
||||
|
||||
// Now join the mod team of test community 1 and 2
|
||||
let mod_form_1 = CommunityModeratorForm {
|
||||
community_id: data.communities[0].id,
|
||||
person_id,
|
||||
};
|
||||
CommunityModerator::join(pool, &mod_form_1).await?;
|
||||
let mod_form_1 = CommunityModeratorForm::new(data.communities[0].id, person_id);
|
||||
CommunityActions::join(pool, &mod_form_1).await?;
|
||||
|
||||
let mod_form_2 = CommunityModeratorForm {
|
||||
community_id: data.communities[1].id,
|
||||
person_id,
|
||||
};
|
||||
CommunityModerator::join(pool, &mod_form_2).await?;
|
||||
let mod_form_2 = CommunityModeratorForm::new(data.communities[1].id, person_id);
|
||||
CommunityActions::join(pool, &mod_form_2).await?;
|
||||
|
||||
let mod_query = CommunityQuery {
|
||||
local_user: Some(&data.local_user),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
structs::{PostPaginationCursor, PostView},
|
||||
utils::{filter_blocked, filter_is_subscribed, filter_not_hidden_or_is_subscribed},
|
||||
utils::{filter_blocked, filter_is_subscribed, filter_not_unlisted_or_is_subscribed},
|
||||
};
|
||||
use diesel::{
|
||||
debug_query,
|
||||
|
@ -15,15 +15,13 @@ use diesel::{
|
|||
OptionalExtension,
|
||||
PgTextExpressionMethods,
|
||||
QueryDsl,
|
||||
SelectableHelper,
|
||||
TextExpressionMethods,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_db_schema::{
|
||||
aliases::{creator_community_actions, creator_local_user},
|
||||
impls::{
|
||||
community::community_follower_select_subscribed_type,
|
||||
local_user::{local_user_can_mod, LocalUserOptionHelper},
|
||||
},
|
||||
aliases::creator_community_actions,
|
||||
impls::local_user::LocalUserOptionHelper,
|
||||
newtypes::{CommunityId, PersonId, PostId},
|
||||
schema::{
|
||||
community,
|
||||
|
@ -36,8 +34,6 @@ use lemmy_db_schema::{
|
|||
person_actions,
|
||||
post,
|
||||
post_actions,
|
||||
post_tag,
|
||||
tag,
|
||||
},
|
||||
source::{
|
||||
community::CommunityFollowerState,
|
||||
|
@ -47,7 +43,6 @@ use lemmy_db_schema::{
|
|||
},
|
||||
traits::Crud,
|
||||
utils::{
|
||||
functions::coalesce,
|
||||
fuzzy_search,
|
||||
get_conn,
|
||||
limit_and_offset,
|
||||
|
@ -124,17 +119,6 @@ impl PostView {
|
|||
.left_join(local_user_join)
|
||||
}
|
||||
|
||||
#[diesel::dsl::auto_type(no_type_alias)]
|
||||
fn creator_is_admin() -> _ {
|
||||
exists(
|
||||
creator_local_user.filter(
|
||||
post::creator_id
|
||||
.eq(creator_local_user.field(local_user::person_id))
|
||||
.and(creator_local_user.field(local_user::admin).eq(true)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn read(
|
||||
pool: &mut DbPool<'_>,
|
||||
post_id: PostId,
|
||||
|
@ -144,45 +128,9 @@ impl PostView {
|
|||
let conn = &mut get_conn(pool).await?;
|
||||
let my_person_id = my_local_user.person_id();
|
||||
|
||||
let post_tags = post_tag::table
|
||||
.inner_join(tag::table)
|
||||
.select(diesel::dsl::sql::<diesel::sql_types::Json>(
|
||||
"json_agg(tag.*)",
|
||||
))
|
||||
.filter(post_tag::post_id.eq(post::id))
|
||||
.filter(tag::deleted.eq(false))
|
||||
.single_value();
|
||||
|
||||
let mut query = Self::joins(my_person_id)
|
||||
.filter(post::id.eq(post_id))
|
||||
.select((
|
||||
post::all_columns,
|
||||
person::all_columns,
|
||||
community::all_columns,
|
||||
image_details::all_columns.nullable(),
|
||||
creator_community_actions
|
||||
.field(community_actions::received_ban)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
community_actions::received_ban.nullable().is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::became_moderator)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
Self::creator_is_admin(),
|
||||
community_follower_select_subscribed_type(),
|
||||
post_actions::saved.nullable(),
|
||||
post_actions::read.nullable().is_not_null(),
|
||||
post_actions::hidden.nullable().is_not_null(),
|
||||
person_actions::blocked.nullable().is_not_null(),
|
||||
post_actions::like_score.nullable(),
|
||||
coalesce(
|
||||
post::comments.nullable() - post_actions::read_comments_amount.nullable(),
|
||||
post::comments,
|
||||
),
|
||||
post_tags,
|
||||
local_user_can_mod(),
|
||||
))
|
||||
.select(Self::as_select())
|
||||
.into_boxed();
|
||||
|
||||
// Hide deleted and removed for non-admins or mods
|
||||
|
@ -389,44 +337,8 @@ impl<'a> PostQuery<'a> {
|
|||
let my_person_id = o.local_user.person_id();
|
||||
let my_local_user_id = o.local_user.local_user_id();
|
||||
|
||||
let post_tags = post_tag::table
|
||||
.inner_join(tag::table)
|
||||
.select(diesel::dsl::sql::<diesel::sql_types::Json>(
|
||||
"json_agg(tag.*)",
|
||||
))
|
||||
.filter(post_tag::post_id.eq(post::id))
|
||||
.filter(tag::deleted.eq(false))
|
||||
.single_value();
|
||||
|
||||
let mut query = PostView::joins(my_person_id)
|
||||
.select((
|
||||
post::all_columns,
|
||||
person::all_columns,
|
||||
community::all_columns,
|
||||
image_details::all_columns.nullable(),
|
||||
creator_community_actions
|
||||
.field(community_actions::received_ban)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
community_actions::received_ban.nullable().is_not_null(),
|
||||
creator_community_actions
|
||||
.field(community_actions::became_moderator)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
PostView::creator_is_admin(),
|
||||
community_follower_select_subscribed_type(),
|
||||
post_actions::saved.nullable(),
|
||||
post_actions::read.nullable().is_not_null(),
|
||||
post_actions::hidden.nullable().is_not_null(),
|
||||
person_actions::blocked.nullable().is_not_null(),
|
||||
post_actions::like_score.nullable(),
|
||||
coalesce(
|
||||
post::comments.nullable() - post_actions::read_comments_amount.nullable(),
|
||||
post::comments,
|
||||
),
|
||||
post_tags,
|
||||
local_user_can_mod(),
|
||||
))
|
||||
.select(PostView::as_select())
|
||||
.into_boxed();
|
||||
|
||||
// hide posts from deleted communities
|
||||
|
@ -465,9 +377,9 @@ impl<'a> PostQuery<'a> {
|
|||
ListingType::Local => {
|
||||
query = query
|
||||
.filter(community::local.eq(true))
|
||||
.filter(filter_not_hidden_or_is_subscribed());
|
||||
.filter(filter_not_unlisted_or_is_subscribed());
|
||||
}
|
||||
ListingType::All => query = query.filter(filter_not_hidden_or_is_subscribed()),
|
||||
ListingType::All => query = query.filter(filter_not_unlisted_or_is_subscribed()),
|
||||
ListingType::ModeratorView => {
|
||||
query = query.filter(community_actions::became_moderator.is_not_null());
|
||||
}
|
||||
|
@ -655,7 +567,7 @@ impl<'a> PostQuery<'a> {
|
|||
mod tests {
|
||||
use crate::{
|
||||
post::post_view::{PaginationCursorData, PostQuery, PostView},
|
||||
structs::{LocalUserView, PostTags},
|
||||
structs::LocalUserView,
|
||||
};
|
||||
use chrono::Utc;
|
||||
use diesel_async::SimpleAsyncConnection;
|
||||
|
@ -667,41 +579,35 @@ mod tests {
|
|||
comment::{Comment, CommentInsertForm},
|
||||
community::{
|
||||
Community,
|
||||
CommunityFollower,
|
||||
CommunityActions,
|
||||
CommunityBlockForm,
|
||||
CommunityFollowerForm,
|
||||
CommunityFollowerState,
|
||||
CommunityInsertForm,
|
||||
CommunityModerator,
|
||||
CommunityModeratorForm,
|
||||
CommunityPersonBan,
|
||||
CommunityPersonBanForm,
|
||||
CommunityUpdateForm,
|
||||
},
|
||||
community_block::{CommunityBlock, CommunityBlockForm},
|
||||
instance::Instance,
|
||||
instance_block::{InstanceBlock, InstanceBlockForm},
|
||||
instance::{Instance, InstanceActions, InstanceBlockForm},
|
||||
language::Language,
|
||||
local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm},
|
||||
person::{Person, PersonInsertForm},
|
||||
person_block::{PersonBlock, PersonBlockForm},
|
||||
person::{Person, PersonActions, PersonBlockForm, PersonInsertForm},
|
||||
post::{
|
||||
Post,
|
||||
PostHide,
|
||||
PostActions,
|
||||
PostHideForm,
|
||||
PostInsertForm,
|
||||
PostLike,
|
||||
PostLikeForm,
|
||||
PostRead,
|
||||
PostReadForm,
|
||||
PostUpdateForm,
|
||||
},
|
||||
site::Site,
|
||||
tag::{PostTagInsertForm, Tag, TagInsertForm},
|
||||
},
|
||||
traits::{Bannable, Blockable, Crud, Followable, Joinable, Likeable},
|
||||
utils::{build_db_pool, get_conn, uplete, ActualDbPool, DbPool, RANK_DEFAULT},
|
||||
traits::{Bannable, Blockable, Crud, Followable, Hideable, Joinable, Likeable, Readable},
|
||||
utils::{build_db_pool, get_conn, uplete, ActualDbPool, DbPool},
|
||||
CommunityVisibility,
|
||||
PostSortType,
|
||||
SubscribedType,
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
@ -730,8 +636,8 @@ mod tests {
|
|||
post: Post,
|
||||
bot_post: Post,
|
||||
post_with_tags: Post,
|
||||
tag_1: Tag,
|
||||
tag_2: Tag,
|
||||
_tag_1: Tag,
|
||||
_tag_2: Tag,
|
||||
site: Site,
|
||||
}
|
||||
|
||||
|
@ -805,12 +711,8 @@ mod tests {
|
|||
Post::create(pool, &post_from_blocked_person).await?;
|
||||
|
||||
// block that person
|
||||
let person_block = PersonBlockForm {
|
||||
person_id: inserted_tegan_person.id,
|
||||
target_id: inserted_john_person.id,
|
||||
};
|
||||
|
||||
PersonBlock::block(pool, &person_block).await?;
|
||||
let person_block = PersonBlockForm::new(inserted_tegan_person.id, inserted_john_person.id);
|
||||
PersonActions::block(pool, &person_block).await?;
|
||||
|
||||
// Two community post tags
|
||||
let tag_1 = Tag::create(
|
||||
|
@ -918,8 +820,8 @@ mod tests {
|
|||
post,
|
||||
bot_post,
|
||||
post_with_tags,
|
||||
tag_1,
|
||||
tag_2,
|
||||
_tag_1: tag_1,
|
||||
_tag_2: tag_2,
|
||||
site,
|
||||
})
|
||||
}
|
||||
|
@ -982,17 +884,11 @@ mod tests {
|
|||
)
|
||||
.await?;
|
||||
|
||||
let expected_post_listing_with_user = expected_post_view(data)?;
|
||||
|
||||
// Should be only one person, IE the bot post, and blocked should be missing
|
||||
assert_eq!(
|
||||
vec![post_listing_single_with_person.clone()],
|
||||
read_post_listing
|
||||
);
|
||||
assert_eq!(
|
||||
expected_post_listing_with_user,
|
||||
post_listing_single_with_person
|
||||
);
|
||||
assert_eq!(data.post.id, post_listing_single_with_person.post.id);
|
||||
|
||||
let local_user_form = LocalUserUpdateForm {
|
||||
show_bot_accounts: Some(true),
|
||||
|
@ -1038,23 +934,16 @@ mod tests {
|
|||
let read_post_listing_single_no_person =
|
||||
PostView::read(pool, data.post.id, None, false).await?;
|
||||
|
||||
let mut expected_post_listing_no_person = expected_post_view(data)?;
|
||||
expected_post_listing_no_person.can_mod = false;
|
||||
|
||||
// Should be 2 posts, with the bot post, and the blocked
|
||||
assert_eq!(
|
||||
vec![POST_WITH_TAGS, POST_BY_BOT, POST, POST_BY_BLOCKED_PERSON],
|
||||
names(&read_post_listing_multiple_no_person)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Some(&expected_post_listing_no_person),
|
||||
read_post_listing_multiple_no_person.get(2)
|
||||
);
|
||||
assert_eq!(
|
||||
expected_post_listing_no_person,
|
||||
read_post_listing_single_no_person
|
||||
);
|
||||
assert!(read_post_listing_multiple_no_person
|
||||
.get(2)
|
||||
.is_some_and(|x| x.post.id == data.post.id));
|
||||
assert_eq!(false, read_post_listing_single_no_person.can_mod);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1125,11 +1014,9 @@ mod tests {
|
|||
let pool = &data.pool();
|
||||
let pool = &mut pool.into();
|
||||
|
||||
let community_block = CommunityBlockForm {
|
||||
person_id: data.tegan_local_user_view.person.id,
|
||||
community_id: data.community.id,
|
||||
};
|
||||
CommunityBlock::block(pool, &community_block).await?;
|
||||
let community_block =
|
||||
CommunityBlockForm::new(data.community.id, data.tegan_local_user_view.person.id);
|
||||
CommunityActions::block(pool, &community_block).await?;
|
||||
|
||||
let read_post_listings_with_person_after_block = PostQuery {
|
||||
community_id: Some(data.community.id),
|
||||
|
@ -1140,7 +1027,7 @@ mod tests {
|
|||
// Should be 0 posts after the community block
|
||||
assert_eq!(read_post_listings_with_person_after_block, vec![]);
|
||||
|
||||
CommunityBlock::unblock(pool, &community_block).await?;
|
||||
CommunityActions::unblock(pool, &community_block).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1153,15 +1040,16 @@ mod tests {
|
|||
|
||||
let post_like_form = PostLikeForm::new(data.post.id, data.tegan_local_user_view.person.id, 1);
|
||||
|
||||
let inserted_post_like = PostLike::like(pool, &post_like_form).await?;
|
||||
let inserted_post_like = PostActions::like(pool, &post_like_form).await?;
|
||||
|
||||
let expected_post_like = PostLike {
|
||||
post_id: data.post.id,
|
||||
person_id: data.tegan_local_user_view.person.id,
|
||||
published: inserted_post_like.published,
|
||||
score: 1,
|
||||
};
|
||||
assert_eq!(expected_post_like, inserted_post_like);
|
||||
assert_eq!(
|
||||
(data.post.id, data.tegan_local_user_view.person.id, Some(1)),
|
||||
(
|
||||
inserted_post_like.post_id,
|
||||
inserted_post_like.person_id,
|
||||
inserted_post_like.like_score,
|
||||
)
|
||||
);
|
||||
|
||||
let post_listing_single_with_person = PostView::read(
|
||||
pool,
|
||||
|
@ -1171,12 +1059,17 @@ mod tests {
|
|||
)
|
||||
.await?;
|
||||
|
||||
let mut expected_post_with_upvote = expected_post_view(data)?;
|
||||
expected_post_with_upvote.my_vote = Some(1);
|
||||
expected_post_with_upvote.post.score = 1;
|
||||
expected_post_with_upvote.post.upvotes = 1;
|
||||
expected_post_with_upvote.creator.post_score = 1;
|
||||
assert_eq!(expected_post_with_upvote, post_listing_single_with_person);
|
||||
assert_eq!(
|
||||
(true, 1, 1, 1),
|
||||
(
|
||||
post_listing_single_with_person
|
||||
.post_actions
|
||||
.is_some_and(|t| t.like_score == Some(1)),
|
||||
post_listing_single_with_person.post.score,
|
||||
post_listing_single_with_person.post.upvotes,
|
||||
post_listing_single_with_person.creator.post_score,
|
||||
)
|
||||
);
|
||||
|
||||
let local_user_form = LocalUserUpdateForm {
|
||||
show_bot_accounts: Some(false),
|
||||
|
@ -1197,10 +1090,13 @@ mod tests {
|
|||
.list(&data.site, pool)
|
||||
.await?;
|
||||
read_post_listing.remove(0);
|
||||
assert_eq!(vec![expected_post_with_upvote], read_post_listing);
|
||||
assert_eq!(
|
||||
post_listing_single_with_person.post.id,
|
||||
read_post_listing[0].post.id
|
||||
);
|
||||
|
||||
let like_removed =
|
||||
PostLike::remove(pool, data.tegan_local_user_view.person.id, data.post.id).await?;
|
||||
PostActions::remove_like(pool, data.tegan_local_user_view.person.id, data.post.id).await?;
|
||||
assert_eq!(uplete::Count::only_deleted(1), like_removed);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1215,11 +1111,11 @@ mod tests {
|
|||
// Like both the bot post, and your own
|
||||
// The liked_only should not show your own post
|
||||
let post_like_form = PostLikeForm::new(data.post.id, data.tegan_local_user_view.person.id, 1);
|
||||
PostLike::like(pool, &post_like_form).await?;
|
||||
PostActions::like(pool, &post_like_form).await?;
|
||||
|
||||
let bot_post_like_form =
|
||||
PostLikeForm::new(data.bot_post.id, data.tegan_local_user_view.person.id, 1);
|
||||
PostLike::like(pool, &bot_post_like_form).await?;
|
||||
PostActions::like(pool, &bot_post_like_form).await?;
|
||||
|
||||
// Read the liked only
|
||||
let read_liked_post_listing = PostQuery {
|
||||
|
@ -1257,7 +1153,7 @@ mod tests {
|
|||
// Only mark the bot post as read
|
||||
// The read_only should only show the bot post
|
||||
let post_read_form = PostReadForm::new(data.bot_post.id, data.tegan_local_user_view.person.id);
|
||||
PostRead::mark_as_read(pool, &post_read_form).await?;
|
||||
PostActions::mark_as_read(pool, &post_read_form).await?;
|
||||
|
||||
// Only read the post marked as read
|
||||
let read_read_post_listing = PostQuery {
|
||||
|
@ -1292,8 +1188,9 @@ mod tests {
|
|||
.map(|p| {
|
||||
(
|
||||
p.creator.name,
|
||||
p.creator_is_moderator,
|
||||
p.creator_is_admin,
|
||||
p.creator_community_actions
|
||||
.map(|x| x.became_moderator.is_some())
|
||||
.unwrap_or(false),
|
||||
p.can_mod,
|
||||
)
|
||||
})
|
||||
|
@ -1301,24 +1198,20 @@ mod tests {
|
|||
|
||||
// Tegan is an admin, so can_mod should be always true
|
||||
let expected_post_listing = vec![
|
||||
("tegan".to_owned(), false, true, true),
|
||||
("mybot".to_owned(), false, false, true),
|
||||
("tegan".to_owned(), false, true, true),
|
||||
("tegan".to_owned(), false, true),
|
||||
("mybot".to_owned(), false, true),
|
||||
("tegan".to_owned(), false, true),
|
||||
];
|
||||
assert_eq!(expected_post_listing, tegan_listings);
|
||||
|
||||
// Have john become a moderator, then the bot
|
||||
let john_mod_form = CommunityModeratorForm {
|
||||
community_id,
|
||||
person_id: data.john_local_user_view.person.id,
|
||||
};
|
||||
CommunityModerator::join(pool, &john_mod_form).await?;
|
||||
let john_mod_form =
|
||||
CommunityModeratorForm::new(community_id, data.john_local_user_view.person.id);
|
||||
CommunityActions::join(pool, &john_mod_form).await?;
|
||||
|
||||
let bot_mod_form = CommunityModeratorForm {
|
||||
community_id,
|
||||
person_id: data.bot_local_user_view.person.id,
|
||||
};
|
||||
CommunityModerator::join(pool, &bot_mod_form).await?;
|
||||
let bot_mod_form =
|
||||
CommunityModeratorForm::new(community_id, data.bot_local_user_view.person.id);
|
||||
CommunityActions::join(pool, &bot_mod_form).await?;
|
||||
|
||||
let john_listings = PostQuery {
|
||||
sort: Some(PostSortType::New),
|
||||
|
@ -1331,8 +1224,9 @@ mod tests {
|
|||
.map(|p| {
|
||||
(
|
||||
p.creator.name,
|
||||
p.creator_is_moderator,
|
||||
p.creator_is_admin,
|
||||
p.creator_community_actions
|
||||
.map(|x| x.became_moderator.is_some())
|
||||
.unwrap_or(false),
|
||||
p.can_mod,
|
||||
)
|
||||
})
|
||||
|
@ -1340,10 +1234,10 @@ mod tests {
|
|||
|
||||
// John is a mod, so he can_mod the bots (and his own) posts, but not tegans.
|
||||
let expected_post_listing = vec![
|
||||
("tegan".to_owned(), false, true, false),
|
||||
("mybot".to_owned(), true, false, true),
|
||||
("tegan".to_owned(), false, true, false),
|
||||
("john".to_owned(), true, false, true),
|
||||
("tegan".to_owned(), false, false),
|
||||
("mybot".to_owned(), true, true),
|
||||
("tegan".to_owned(), false, false),
|
||||
("john".to_owned(), true, true),
|
||||
];
|
||||
assert_eq!(expected_post_listing, john_listings);
|
||||
|
||||
|
@ -1359,23 +1253,24 @@ mod tests {
|
|||
.map(|p| {
|
||||
(
|
||||
p.creator.name,
|
||||
p.creator_is_moderator,
|
||||
p.creator_is_admin,
|
||||
p.creator_community_actions
|
||||
.map(|x| x.became_moderator.is_some())
|
||||
.unwrap_or(false),
|
||||
p.can_mod,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let expected_post_listing = vec![
|
||||
("tegan".to_owned(), false, true, false),
|
||||
("mybot".to_owned(), true, false, true),
|
||||
("tegan".to_owned(), false, true, false),
|
||||
("john".to_owned(), true, false, false),
|
||||
("tegan".to_owned(), false, false),
|
||||
("mybot".to_owned(), true, true),
|
||||
("tegan".to_owned(), false, false),
|
||||
("john".to_owned(), true, false),
|
||||
];
|
||||
assert_eq!(expected_post_listing, bot_listings);
|
||||
|
||||
// Make the bot leave the mod team, and make sure it can_mod is false.
|
||||
CommunityModerator::leave(pool, &bot_mod_form).await?;
|
||||
CommunityActions::leave(pool, &bot_mod_form).await?;
|
||||
|
||||
let bot_listings = PostQuery {
|
||||
sort: Some(PostSortType::New),
|
||||
|
@ -1388,18 +1283,19 @@ mod tests {
|
|||
.map(|p| {
|
||||
(
|
||||
p.creator.name,
|
||||
p.creator_is_moderator,
|
||||
p.creator_is_admin,
|
||||
p.creator_community_actions
|
||||
.map(|x| x.became_moderator.is_some())
|
||||
.unwrap_or(false),
|
||||
p.can_mod,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let expected_post_listing = vec![
|
||||
("tegan".to_owned(), false, true, false),
|
||||
("mybot".to_owned(), false, false, false),
|
||||
("tegan".to_owned(), false, true, false),
|
||||
("john".to_owned(), true, false, false),
|
||||
("tegan".to_owned(), false, false),
|
||||
("mybot".to_owned(), false, false),
|
||||
("tegan".to_owned(), false, false),
|
||||
("john".to_owned(), true, false),
|
||||
];
|
||||
assert_eq!(expected_post_listing, bot_listings);
|
||||
|
||||
|
@ -1576,11 +1472,12 @@ mod tests {
|
|||
assert!(posts.is_empty());
|
||||
|
||||
// Follow the community
|
||||
let form = CommunityFollowerForm {
|
||||
state: Some(CommunityFollowerState::Accepted),
|
||||
..CommunityFollowerForm::new(data.community.id, data.tegan_local_user_view.person.id)
|
||||
};
|
||||
CommunityFollower::follow(pool, &form).await?;
|
||||
let form = CommunityFollowerForm::new(
|
||||
data.community.id,
|
||||
data.tegan_local_user_view.person.id,
|
||||
CommunityFollowerState::Accepted,
|
||||
);
|
||||
CommunityActions::follow(pool, &form).await?;
|
||||
|
||||
let posts = data.default_post_query().list(&data.site, pool).await?;
|
||||
assert!(!posts.is_empty());
|
||||
|
@ -1628,11 +1525,9 @@ mod tests {
|
|||
assert_eq!(POST_LISTING_WITH_BLOCKED, *names(&post_listings_all));
|
||||
|
||||
// block the instance
|
||||
let block_form = InstanceBlockForm {
|
||||
person_id: data.tegan_local_user_view.person.id,
|
||||
instance_id: blocked_instance.id,
|
||||
};
|
||||
InstanceBlock::block(pool, &block_form).await?;
|
||||
let block_form =
|
||||
InstanceBlockForm::new(data.tegan_local_user_view.person.id, blocked_instance.id);
|
||||
InstanceActions::block(pool, &block_form).await?;
|
||||
|
||||
// now posts from communities on that instance should be hidden
|
||||
let post_listings_blocked = data.default_post_query().list(&data.site, pool).await?;
|
||||
|
@ -1645,16 +1540,23 @@ mod tests {
|
|||
.all(|p| p.post.id != post_from_blocked_instance.id));
|
||||
|
||||
// Follow community from the blocked instance to see posts anyway
|
||||
let mut follow_form =
|
||||
CommunityFollowerForm::new(inserted_community.id, data.tegan_local_user_view.person.id);
|
||||
follow_form.state = Some(CommunityFollowerState::Accepted);
|
||||
CommunityFollower::follow(pool, &follow_form).await?;
|
||||
let follow_form = CommunityFollowerForm::new(
|
||||
inserted_community.id,
|
||||
data.tegan_local_user_view.person.id,
|
||||
CommunityFollowerState::Accepted,
|
||||
);
|
||||
CommunityActions::follow(pool, &follow_form).await?;
|
||||
let post_listings_bypass = data.default_post_query().list(&data.site, pool).await?;
|
||||
assert_eq!(POST_LISTING_WITH_BLOCKED, *names(&post_listings_bypass));
|
||||
CommunityFollower::unfollow(pool, &follow_form).await?;
|
||||
CommunityActions::unfollow(
|
||||
pool,
|
||||
data.tegan_local_user_view.person.id,
|
||||
inserted_community.id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// after unblocking it should return all posts again
|
||||
InstanceBlock::unblock(pool, &block_form).await?;
|
||||
InstanceActions::unblock(pool, &block_form).await?;
|
||||
let post_listings_blocked = data.default_post_query().list(&data.site, pool).await?;
|
||||
assert_eq!(POST_LISTING_WITH_BLOCKED, *names(&post_listings_blocked));
|
||||
|
||||
|
@ -1800,7 +1702,7 @@ mod tests {
|
|||
|
||||
// Mark a post as read
|
||||
let read_form = PostReadForm::new(data.bot_post.id, data.tegan_local_user_view.person.id);
|
||||
PostRead::mark_as_read(pool, &read_form).await?;
|
||||
PostActions::mark_as_read(pool, &read_form).await?;
|
||||
|
||||
// Make sure you don't see the read post in the results
|
||||
let post_listings_hide_read = data.default_post_query().list(&data.site, pool).await?;
|
||||
|
@ -1840,7 +1742,8 @@ mod tests {
|
|||
let pool = &mut pool.into();
|
||||
|
||||
// Mark a post as hidden
|
||||
PostHide::hide(pool, data.bot_post.id, data.tegan_local_user_view.person.id).await?;
|
||||
let hide_form = PostHideForm::new(data.bot_post.id, data.tegan_local_user_view.person.id);
|
||||
PostActions::hide(pool, &hide_form).await?;
|
||||
|
||||
// Make sure you don't see the hidden post in the results
|
||||
let post_listings_hide_hidden = data.default_post_query().list(&data.site, pool).await?;
|
||||
|
@ -1864,7 +1767,9 @@ mod tests {
|
|||
);
|
||||
|
||||
// Make sure that hidden field is true.
|
||||
assert!(&post_listings_show_hidden.get(1).is_some_and(|p| p.hidden));
|
||||
assert!(&post_listings_show_hidden
|
||||
.get(1)
|
||||
.is_some_and(|p| p.post_actions.as_ref().is_some_and(|a| a.hidden.is_some())));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1914,135 +1819,6 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn expected_post_view(data: &Data) -> LemmyResult<PostView> {
|
||||
let (inserted_person, inserted_community, inserted_post) = (
|
||||
&data.tegan_local_user_view.person,
|
||||
&data.community,
|
||||
&data.post,
|
||||
);
|
||||
|
||||
Ok(PostView {
|
||||
post: Post {
|
||||
id: inserted_post.id,
|
||||
name: inserted_post.name.clone(),
|
||||
creator_id: inserted_person.id,
|
||||
url: None,
|
||||
body: None,
|
||||
alt_text: None,
|
||||
published: inserted_post.published,
|
||||
updated: None,
|
||||
community_id: inserted_community.id,
|
||||
removed: false,
|
||||
deleted: false,
|
||||
locked: false,
|
||||
nsfw: false,
|
||||
embed_title: None,
|
||||
embed_description: None,
|
||||
embed_video_url: None,
|
||||
thumbnail_url: None,
|
||||
ap_id: inserted_post.ap_id.clone(),
|
||||
local: true,
|
||||
language_id: LanguageId(47),
|
||||
featured_community: false,
|
||||
featured_local: false,
|
||||
url_content_type: None,
|
||||
scheduled_publish_time: None,
|
||||
comments: 0,
|
||||
score: 0,
|
||||
upvotes: 0,
|
||||
downvotes: 0,
|
||||
newest_comment_time_necro: inserted_post.published,
|
||||
newest_comment_time: inserted_post.published,
|
||||
hot_rank: RANK_DEFAULT,
|
||||
hot_rank_active: RANK_DEFAULT,
|
||||
controversy_rank: 0.0,
|
||||
scaled_rank: RANK_DEFAULT,
|
||||
instance_id: data.instance.id,
|
||||
report_count: 0,
|
||||
unresolved_report_count: 0,
|
||||
},
|
||||
my_vote: None,
|
||||
unread_comments: 0,
|
||||
creator: Person {
|
||||
id: inserted_person.id,
|
||||
name: inserted_person.name.clone(),
|
||||
display_name: None,
|
||||
published: inserted_person.published,
|
||||
avatar: None,
|
||||
ap_id: inserted_person.ap_id.clone(),
|
||||
local: true,
|
||||
bot_account: false,
|
||||
banned: false,
|
||||
deleted: false,
|
||||
bio: None,
|
||||
banner: None,
|
||||
updated: None,
|
||||
inbox_url: inserted_person.inbox_url.clone(),
|
||||
matrix_user_id: None,
|
||||
ban_expires: None,
|
||||
instance_id: data.instance.id,
|
||||
private_key: inserted_person.private_key.clone(),
|
||||
public_key: inserted_person.public_key.clone(),
|
||||
last_refreshed_at: inserted_person.last_refreshed_at,
|
||||
post_count: 2,
|
||||
post_score: 0,
|
||||
comment_count: 0,
|
||||
comment_score: 0,
|
||||
},
|
||||
image_details: None,
|
||||
creator_banned_from_community: false,
|
||||
banned_from_community: false,
|
||||
creator_is_moderator: false,
|
||||
creator_is_admin: true,
|
||||
can_mod: true,
|
||||
community: Community {
|
||||
id: inserted_community.id,
|
||||
name: inserted_community.name.clone(),
|
||||
icon: None,
|
||||
removed: false,
|
||||
deleted: false,
|
||||
nsfw: false,
|
||||
ap_id: inserted_community.ap_id.clone(),
|
||||
local: true,
|
||||
title: "nada".to_owned(),
|
||||
sidebar: None,
|
||||
description: None,
|
||||
updated: None,
|
||||
banner: None,
|
||||
posting_restricted_to_mods: false,
|
||||
published: inserted_community.published,
|
||||
instance_id: data.instance.id,
|
||||
private_key: inserted_community.private_key.clone(),
|
||||
public_key: inserted_community.public_key.clone(),
|
||||
last_refreshed_at: inserted_community.last_refreshed_at,
|
||||
followers_url: inserted_community.followers_url.clone(),
|
||||
inbox_url: inserted_community.inbox_url.clone(),
|
||||
moderators_url: inserted_community.moderators_url.clone(),
|
||||
featured_url: inserted_community.featured_url.clone(),
|
||||
visibility: CommunityVisibility::Public,
|
||||
random_number: inserted_community.random_number,
|
||||
subscribers: 0,
|
||||
posts: 4,
|
||||
comments: 0,
|
||||
users_active_day: 0,
|
||||
users_active_week: 0,
|
||||
users_active_month: 0,
|
||||
users_active_half_year: 0,
|
||||
hot_rank: RANK_DEFAULT,
|
||||
subscribers_local: 0,
|
||||
report_count: 0,
|
||||
unresolved_report_count: 0,
|
||||
interactions_month: 0,
|
||||
},
|
||||
subscribed: SubscribedType::NotSubscribed,
|
||||
read: false,
|
||||
hidden: false,
|
||||
saved: None,
|
||||
creator_blocked: false,
|
||||
tags: PostTags::default(),
|
||||
})
|
||||
}
|
||||
|
||||
#[test_context(Data)]
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
|
@ -2109,13 +1885,9 @@ mod tests {
|
|||
)
|
||||
.await?;
|
||||
|
||||
CommunityPersonBan::ban(
|
||||
CommunityActions::ban(
|
||||
pool,
|
||||
&CommunityPersonBanForm {
|
||||
community_id: data.community.id,
|
||||
person_id: inserted_banned_from_comm_person.id,
|
||||
expires: None,
|
||||
},
|
||||
&CommunityPersonBanForm::new(data.community.id, inserted_banned_from_comm_person.id),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -2127,7 +1899,9 @@ mod tests {
|
|||
)
|
||||
.await?;
|
||||
|
||||
assert!(post_view.banned_from_community);
|
||||
assert!(post_view
|
||||
.community_actions
|
||||
.is_some_and(|x| x.received_ban.is_some()));
|
||||
|
||||
Person::delete(pool, inserted_banned_from_comm_person.id).await?;
|
||||
Ok(())
|
||||
|
@ -2148,7 +1922,7 @@ mod tests {
|
|||
)
|
||||
.await?;
|
||||
|
||||
assert!(!post_view.banned_from_community);
|
||||
assert!(post_view.community_actions.is_none());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -2311,14 +2085,13 @@ mod tests {
|
|||
data.tegan_local_user_view.local_user.admin = false;
|
||||
|
||||
// User can view after following
|
||||
CommunityFollower::follow(
|
||||
pool,
|
||||
&CommunityFollowerForm {
|
||||
state: Some(CommunityFollowerState::Accepted),
|
||||
..CommunityFollowerForm::new(data.community.id, data.tegan_local_user_view.person.id)
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
let follow_form = CommunityFollowerForm::new(
|
||||
data.community.id,
|
||||
data.tegan_local_user_view.person.id,
|
||||
CommunityFollowerState::Accepted,
|
||||
);
|
||||
CommunityActions::follow(pool, &follow_form).await?;
|
||||
|
||||
let read_post_listing = PostQuery {
|
||||
community_id: Some(data.community.id),
|
||||
local_user: Some(&data.tegan_local_user_view.local_user),
|
||||
|
@ -2404,30 +2177,31 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test_context(Data)]
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn post_tags_present(data: &mut Data) -> LemmyResult<()> {
|
||||
let pool = &data.pool();
|
||||
let pool = &mut pool.into();
|
||||
// TODO add these back in later
|
||||
// #[test_context(Data)]
|
||||
// #[tokio::test]
|
||||
// #[serial]
|
||||
// async fn post_tags_present(data: &mut Data) -> LemmyResult<()> {
|
||||
// let pool = &data.pool();
|
||||
// let pool = &mut pool.into();
|
||||
|
||||
let post_view = PostView::read(
|
||||
pool,
|
||||
data.post_with_tags.id,
|
||||
Some(&data.tegan_local_user_view.local_user),
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
// let post_view = PostView::read(
|
||||
// pool,
|
||||
// data.post_with_tags.id,
|
||||
// Some(&data.tegan_local_user_view.local_user),
|
||||
// false,
|
||||
// )
|
||||
// .await?;
|
||||
|
||||
assert_eq!(2, post_view.tags.tags.len());
|
||||
assert_eq!(data.tag_1.name, post_view.tags.tags[0].name);
|
||||
assert_eq!(data.tag_2.name, post_view.tags.tags[1].name);
|
||||
// assert_eq!(2, post_view.tags.tags.len());
|
||||
// assert_eq!(data.tag_1.name, post_view.tags.tags[0].name);
|
||||
// assert_eq!(data.tag_2.name, post_view.tags.tags[1].name);
|
||||
|
||||
let all_posts = data.default_post_query().list(&data.site, pool).await?;
|
||||
assert_eq!(2, all_posts[0].tags.tags.len()); // post with tags
|
||||
assert_eq!(0, all_posts[1].tags.tags.len()); // bot post
|
||||
assert_eq!(0, all_posts[2].tags.tags.len()); // normal post
|
||||
// let all_posts = data.default_post_query().list(&data.site, pool).await?;
|
||||
// assert_eq!(2, all_posts[0].tags.tags.len()); // post with tags
|
||||
// assert_eq!(0, all_posts[1].tags.tags.len()); // bot post
|
||||
// assert_eq!(0, all_posts[2].tags.tags.len()); // normal post
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// Ok(())
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -20,13 +20,17 @@ use lemmy_db_schema::{
|
|||
impl RegistrationApplicationView {
|
||||
#[diesel::dsl::auto_type(no_type_alias)]
|
||||
fn joins() -> _ {
|
||||
let local_user_join =
|
||||
local_user::table.on(registration_application::local_user_id.eq(local_user::id));
|
||||
|
||||
let creator_join = person::table.on(local_user::person_id.eq(person::id));
|
||||
let admin_join = aliases::person1
|
||||
.on(registration_application::admin_id.eq(aliases::person1.field(person::id).nullable()));
|
||||
|
||||
registration_application::table
|
||||
.inner_join(local_user::table.on(registration_application::local_user_id.eq(local_user::id)))
|
||||
.inner_join(person::table.on(local_user::person_id.eq(person::id)))
|
||||
.left_join(
|
||||
aliases::person1
|
||||
.on(registration_application::admin_id.eq(aliases::person1.field(person::id).nullable())),
|
||||
)
|
||||
.inner_join(local_user_join)
|
||||
.inner_join(creator_join)
|
||||
.left_join(admin_join)
|
||||
}
|
||||
|
||||
pub async fn read(pool: &mut DbPool<'_>, id: RegistrationApplicationId) -> Result<Self, Error> {
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
use crate::structs::CommentReportView;
|
||||
use diesel::{
|
||||
dsl::now,
|
||||
result::Error,
|
||||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
JoinOnDsl,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
SelectableHelper,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_db_schema::{
|
||||
aliases::{self, creator_community_actions},
|
||||
impls::community::community_follower_select_subscribed_type,
|
||||
newtypes::{CommentReportId, PersonId},
|
||||
schema::{
|
||||
comment,
|
||||
|
@ -24,7 +23,7 @@ use lemmy_db_schema::{
|
|||
person_actions,
|
||||
post,
|
||||
},
|
||||
utils::{functions::coalesce, get_conn, DbPool},
|
||||
utils::{get_conn, DbPool},
|
||||
};
|
||||
|
||||
impl CommentReportView {
|
||||
|
@ -103,37 +102,7 @@ impl CommentReportView {
|
|||
let conn = &mut get_conn(pool).await?;
|
||||
Self::joins(my_person_id)
|
||||
.filter(comment_report::id.eq(report_id))
|
||||
.select((
|
||||
comment_report::all_columns,
|
||||
comment::all_columns,
|
||||
post::all_columns,
|
||||
community::all_columns,
|
||||
person::all_columns,
|
||||
aliases::person1.fields(person::all_columns),
|
||||
coalesce(
|
||||
creator_community_actions
|
||||
.field(community_actions::received_ban)
|
||||
.nullable()
|
||||
.is_not_null()
|
||||
.or(
|
||||
creator_community_actions
|
||||
.field(community_actions::ban_expires)
|
||||
.nullable()
|
||||
.gt(now),
|
||||
),
|
||||
false,
|
||||
),
|
||||
creator_community_actions
|
||||
.field(community_actions::became_moderator)
|
||||
.nullable()
|
||||
.is_not_null(),
|
||||
local_user::admin.nullable().is_not_null(),
|
||||
person_actions::blocked.nullable().is_not_null(),
|
||||
community_follower_select_subscribed_type(),
|
||||
comment_actions::saved.nullable(),
|
||||
comment_actions::like_score.nullable(),
|
||||
aliases::person2.fields(person::all_columns).nullable(),
|
||||
))
|
||||
.select(Self::as_select())
|
||||
.first(conn)
|
||||
.await
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue