mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-09-04 20:23:56 +00:00
Add endpoint to get Liked / Disliked comments and posts. (#5616)
* 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
* Extracting pagination cursor utils into a trait.
- Fixes #5275
* Refactoring to avoid stack overflows.
* Fixing api_common feature.
* Adding pagination for GetBannedPersons.
- Must come after #5424
- Fixes #2847
* Starting to work on removing rest of page / limit.
* Issues with community pagination.
* Rename the traits and paginationcursor::new
* remove duplicate fields
* remove "aggregates" from index names
* uncomment indices
* if count = 0
* Using combined trait.
* 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)
* Removing empty files.
* 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
* Updating lemmy-js-client.
* Fixing a few cases.
* Fixing list_banned.
* Starting to convert to lemmy results.
* Fixing vote_view.
* Close to finishing up errors.
* Got compiling.
* Remove tracing for CI.
* Removing unused errors.
* Fixing merge from main.
* lower_name community_view sort.
* Syntax errors.
* Removing rest of Result from db_schema, db_views.
* Finally compiling again.
* fmt.
* Subpath tries again.
* Adding some more indexes./
* Fixing shear.
* Fix keyword_blocks test.
* @dullbananas fixes to Subpath, fixing comment tests.
* sql fmt
* Fixing unused error.
* API test fixing
* Moving read_only_posts to its own endpoint, sorted by read date.
- Fixes #5505
* Adding endpoint to list hidden posts.
- Fixes #5607
* Adding a first_id helper function.
* Fixing api_common
* Adding a person/liked endpoint for posts and comments.
- Fixes #4499
* Get rid of old liked_only filters.
* Formatting sql.
* Clippy
* Fixing view tests.
* SQL fmt
* Addressing PR comments
* Addressing PR comments 1.
* Using id desc.
* Addressing PR comments 2.
* Removing the reverse_timestamp keys for the post table.
* Make community_title and community_lower_name indexes desc
* Remove featured_community from post sort
* Forgot to drop index.
* Addressing PR comments
* Fixing clippy.
* Adding person_local column to post_actions and comment_actions
* Fixing pg_format
* Fixing pg_format 2
* Revert "Adding person_local column to post_actions and comment_actions"
This reverts commit e5145d8b07
.
* Adding local person check to liked and saved combined.
* Formatting sql.
* Adding local check to migration.
* Addressing PR comments
* Try to add versioned pg_formatter 1
* Try to add versioned pg_formatter 2
* Try to add versioned pg_formatter 3
* Try to add versioned pg_formatter 4
* Moving back to correct location.
---------
Co-authored-by: Felix Ableitner <me@nutomic.com>
Co-authored-by: dullbananas <dull.bananas0@gmail.com>
This commit is contained in:
parent
7504738de0
commit
9250460b11
71 changed files with 999 additions and 343 deletions
|
@ -61,10 +61,10 @@ steps:
|
|||
- event: pull_request
|
||||
|
||||
sql_fmt:
|
||||
image: debian:bookworm
|
||||
image: alpine:3
|
||||
commands:
|
||||
- apt-get update
|
||||
- apt-get --yes --no-install-recommends --no-install-suggests install pgformatter
|
||||
- apk add perl make bash
|
||||
- ./scripts/alpine_install_pg_formatter.sh
|
||||
- ./scripts/sql_format_check.sh
|
||||
when:
|
||||
- event: pull_request
|
||||
|
|
22
Cargo.lock
generated
22
Cargo.lock
generated
|
@ -3131,6 +3131,7 @@ dependencies = [
|
|||
"lemmy_db_views_local_user",
|
||||
"lemmy_db_views_modlog_combined",
|
||||
"lemmy_db_views_person",
|
||||
"lemmy_db_views_person_liked_combined",
|
||||
"lemmy_db_views_person_saved_combined",
|
||||
"lemmy_db_views_post",
|
||||
"lemmy_db_views_registration_applications",
|
||||
|
@ -3599,6 +3600,27 @@ dependencies = [
|
|||
"ts-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lemmy_db_views_person_liked_combined"
|
||||
version = "1.0.0-alpha.5"
|
||||
dependencies = [
|
||||
"diesel",
|
||||
"diesel-async",
|
||||
"i-love-jesus",
|
||||
"lemmy_db_schema",
|
||||
"lemmy_db_schema_file",
|
||||
"lemmy_db_views_comment",
|
||||
"lemmy_db_views_local_user",
|
||||
"lemmy_db_views_post",
|
||||
"lemmy_utils",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"serde_with",
|
||||
"serial_test",
|
||||
"tokio",
|
||||
"ts-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lemmy_db_views_person_saved_combined"
|
||||
version = "1.0.0-alpha.5"
|
||||
|
|
|
@ -67,6 +67,7 @@ members = [
|
|||
"crates/db_views/modlog_combined",
|
||||
"crates/db_views/person_content_combined",
|
||||
"crates/db_views/person_saved_combined",
|
||||
"crates/db_views/person_liked_combined",
|
||||
"crates/db_views/report_combined",
|
||||
"crates/db_views/search_combined",
|
||||
"crates/db_views/site",
|
||||
|
@ -132,6 +133,7 @@ lemmy_db_views_inbox_combined = { version = "=1.0.0-alpha.5", path = "./crates/d
|
|||
lemmy_db_views_modlog_combined = { version = "=1.0.0-alpha.5", path = "./crates/db_views/modlog_combined" }
|
||||
lemmy_db_views_person_content_combined = { version = "=1.0.0-alpha.5", path = "./crates/db_views/person_content_combined" }
|
||||
lemmy_db_views_person_saved_combined = { version = "=1.0.0-alpha.5", path = "./crates/db_views/person_saved_combined" }
|
||||
lemmy_db_views_person_liked_combined = { version = "=1.0.0-alpha.5", path = "./crates/db_views/person_liked_combined" }
|
||||
lemmy_db_views_report_combined = { version = "=1.0.0-alpha.5", path = "./crates/db_views/report_combined" }
|
||||
lemmy_db_views_search_combined = { version = "=1.0.0-alpha.5", path = "./crates/db_views/search_combined" }
|
||||
lemmy_db_views_site = { version = "=1.0.0-alpha.5", path = "./crates/db_views/site" }
|
||||
|
|
|
@ -32,6 +32,7 @@ lemmy_db_views_local_image = { workspace = true, features = ["full"] }
|
|||
lemmy_db_views_inbox_combined = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_modlog_combined = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_person_saved_combined = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_person_liked_combined = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_report_combined = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_site = { workspace = true, features = ["full"] }
|
||||
lemmy_db_views_registration_applications = { workspace = true, features = [
|
||||
|
|
43
crates/api/src/local_user/list_liked.rs
Normal file
43
crates/api/src/local_user/list_liked.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use activitypub_federation::config::Data;
|
||||
use actix_web::web::{Json, Query};
|
||||
use lemmy_api_common::context::LemmyContext;
|
||||
use lemmy_db_schema::traits::PaginationCursorBuilder;
|
||||
use lemmy_db_views_local_user::LocalUserView;
|
||||
use lemmy_db_views_person_liked_combined::{
|
||||
impls::PersonLikedCombinedQuery,
|
||||
ListPersonLiked,
|
||||
ListPersonLikedResponse,
|
||||
PersonLikedCombinedView,
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
|
||||
pub async fn list_person_liked(
|
||||
data: Query<ListPersonLiked>,
|
||||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<ListPersonLikedResponse>> {
|
||||
let cursor_data = if let Some(cursor) = &data.page_cursor {
|
||||
Some(PersonLikedCombinedView::from_cursor(cursor, &mut context.pool()).await?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let liked = PersonLikedCombinedQuery {
|
||||
type_: data.type_,
|
||||
like_type: data.like_type,
|
||||
cursor_data,
|
||||
page_back: data.page_back,
|
||||
limit: data.limit,
|
||||
}
|
||||
.list(&mut context.pool(), &local_user_view)
|
||||
.await?;
|
||||
|
||||
let next_page = liked.last().map(PaginationCursorBuilder::to_cursor);
|
||||
let prev_page = liked.first().map(PaginationCursorBuilder::to_cursor);
|
||||
|
||||
Ok(Json(ListPersonLikedResponse {
|
||||
liked,
|
||||
next_page,
|
||||
prev_page,
|
||||
}))
|
||||
}
|
|
@ -7,6 +7,7 @@ pub mod donation_dialog_shown;
|
|||
pub mod generate_totp_secret;
|
||||
pub mod get_captcha;
|
||||
pub mod list_hidden;
|
||||
pub mod list_liked;
|
||||
pub mod list_logins;
|
||||
pub mod list_media;
|
||||
pub mod list_read;
|
||||
|
|
|
@ -141,10 +141,6 @@ pub struct GetComments {
|
|||
pub post_id: Option<PostId>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub parent_id: Option<CommentId>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub liked_only: Option<bool>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub disliked_only: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
|
|
|
@ -96,10 +96,6 @@ pub struct GetPosts {
|
|||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub community_name: Option<String>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub liked_only: Option<bool>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub disliked_only: Option<bool>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub show_hidden: Option<bool>,
|
||||
/// If true, then show the read posts (even if your user setting is to hide them)
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
|
|
|
@ -5,7 +5,7 @@ use actix_web::web::{Json, Query};
|
|||
use lemmy_api_common::{
|
||||
comment::{GetComments, GetCommentsResponse, GetCommentsSlimResponse},
|
||||
context::LemmyContext,
|
||||
utils::{check_conflicting_like_filters, check_private_instance},
|
||||
utils::check_private_instance,
|
||||
};
|
||||
use lemmy_apub_objects::objects::community::ApubCommunity;
|
||||
use lemmy_db_schema::{
|
||||
|
@ -50,11 +50,6 @@ async fn list_comments_common(
|
|||
));
|
||||
let time_range_seconds = data.time_range_seconds;
|
||||
let max_depth = data.max_depth;
|
||||
|
||||
let liked_only = data.liked_only;
|
||||
let disliked_only = data.disliked_only;
|
||||
check_conflicting_like_filters(liked_only, disliked_only)?;
|
||||
|
||||
let limit = data.limit;
|
||||
let parent_id = data.parent_id;
|
||||
|
||||
|
@ -88,8 +83,6 @@ async fn list_comments_common(
|
|||
sort,
|
||||
time_range_seconds,
|
||||
max_depth,
|
||||
liked_only,
|
||||
disliked_only,
|
||||
community_id,
|
||||
parent_path,
|
||||
post_id,
|
||||
|
|
|
@ -11,7 +11,7 @@ use actix_web::web::{Json, Query};
|
|||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
post::{GetPosts, GetPostsResponse},
|
||||
utils::{check_conflicting_like_filters, check_private_instance},
|
||||
utils::check_private_instance,
|
||||
};
|
||||
use lemmy_apub_objects::objects::community::ApubCommunity;
|
||||
use lemmy_db_schema::{
|
||||
|
@ -50,10 +50,6 @@ pub async fn list_posts(
|
|||
let hide_media = data.hide_media;
|
||||
let no_comments_only = data.no_comments_only;
|
||||
|
||||
let liked_only = data.liked_only;
|
||||
let disliked_only = data.disliked_only;
|
||||
check_conflicting_like_filters(liked_only, disliked_only)?;
|
||||
|
||||
let local_user = local_user_view.as_ref().map(|u| &u.local_user);
|
||||
let listing_type = Some(listing_type_with_default(
|
||||
data.type_,
|
||||
|
@ -91,8 +87,6 @@ pub async fn list_posts(
|
|||
sort,
|
||||
time_range_seconds,
|
||||
community_id,
|
||||
liked_only,
|
||||
disliked_only,
|
||||
limit,
|
||||
show_hidden,
|
||||
show_read,
|
||||
|
|
|
@ -158,6 +158,19 @@ pub enum PostFeatureType {
|
|||
Community,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, Eq, Hash,
|
||||
)]
|
||||
#[cfg_attr(feature = "full", derive(TS))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
/// The like_type for a persons liked content.
|
||||
pub enum LikeType {
|
||||
#[default]
|
||||
All,
|
||||
LikedOnly,
|
||||
DislikedOnly,
|
||||
}
|
||||
|
||||
/// Wrapper for assert_eq! macro. Checks that vec matches the given length, and prints the
|
||||
/// vec on failure.
|
||||
#[macro_export]
|
||||
|
|
|
@ -211,6 +211,11 @@ pub struct PersonContentCombinedId(i32);
|
|||
/// The person saved combined id
|
||||
pub struct PersonSavedCombinedId(i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
/// The person liked combined id
|
||||
pub struct PersonLikedCombinedId(i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
pub struct ModlogCombinedId(i32);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod inbox;
|
||||
pub mod modlog;
|
||||
pub mod person_content;
|
||||
pub mod person_liked;
|
||||
pub mod person_saved;
|
||||
pub mod report;
|
||||
pub mod search;
|
||||
|
|
27
crates/db_schema/src/source/combined/person_liked.rs
Normal file
27
crates/db_schema/src/source/combined/person_liked.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use crate::newtypes::{CommentId, PersonId, PersonLikedCombinedId, PostId};
|
||||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use i_love_jesus::CursorKeysModule;
|
||||
#[cfg(feature = "full")]
|
||||
use lemmy_db_schema_file::schema::person_liked_combined;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
|
||||
#[skip_serializing_none]
|
||||
#[derive(PartialEq, Eq, Serialize, Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
derive(Identifiable, Queryable, Selectable, CursorKeysModule)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = person_liked_combined))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
#[cfg_attr(feature = "full", cursor_keys_module(name = person_liked_combined_keys))]
|
||||
/// A combined person_liked table.
|
||||
pub struct PersonLikedCombined {
|
||||
pub id: PersonLikedCombinedId,
|
||||
pub liked: DateTime<Utc>,
|
||||
pub like_score: i16,
|
||||
pub person_id: PersonId,
|
||||
pub post_id: Option<PostId>,
|
||||
pub comment_id: Option<CommentId>,
|
||||
}
|
|
@ -67,17 +67,14 @@ CREATE FUNCTION r.parent_comment_ids (path ltree)
|
|||
RETURNS SETOF int
|
||||
LANGUAGE sql
|
||||
IMMUTABLE parallel safe
|
||||
BEGIN
|
||||
ATOMIC
|
||||
BEGIN ATOMIC
|
||||
SELECT
|
||||
comment_id::int
|
||||
FROM
|
||||
string_to_table (ltree2text (path), '.') AS comment_id
|
||||
-- Skip first and last
|
||||
LIMIT (nlevel (path) - 2) OFFSET 1;
|
||||
|
||||
END;
|
||||
|
||||
CALL r.create_triggers ('comment', $$
|
||||
BEGIN
|
||||
-- Prevent infinite recursion
|
||||
|
@ -86,9 +83,7 @@ BEGIN
|
|||
count(*)
|
||||
FROM select_old_and_new_rows AS old_and_new_rows) = 0 THEN
|
||||
RETURN NULL;
|
||||
|
||||
END IF;
|
||||
|
||||
UPDATE
|
||||
person AS a
|
||||
SET
|
||||
|
@ -106,7 +101,6 @@ FROM (
|
|||
WHERE
|
||||
a.id = diff.creator_id
|
||||
AND diff.comment_count != 0;
|
||||
|
||||
UPDATE
|
||||
comment AS a
|
||||
SET
|
||||
|
@ -144,7 +138,6 @@ FROM (
|
|||
WHERE
|
||||
a.id = diff.parent_id
|
||||
AND diff.child_count != 0;
|
||||
|
||||
UPDATE
|
||||
post AS a
|
||||
SET
|
||||
|
@ -176,7 +169,6 @@ WHERE
|
|||
GREATEST (a.newest_comment_time_necro, diff.newest_comment_time_necro)) != (0,
|
||||
a.newest_comment_time,
|
||||
a.newest_comment_time_necro);
|
||||
|
||||
UPDATE
|
||||
local_site AS a
|
||||
SET
|
||||
|
@ -191,13 +183,9 @@ FROM (
|
|||
AND (comment).local) AS diff
|
||||
WHERE
|
||||
diff.comments != 0;
|
||||
|
||||
RETURN NULL;
|
||||
|
||||
END;
|
||||
|
||||
$$);
|
||||
|
||||
CALL r.create_triggers ('post', $$
|
||||
BEGIN
|
||||
UPDATE
|
||||
|
@ -214,7 +202,6 @@ BEGIN
|
|||
WHERE
|
||||
a.id = diff.creator_id
|
||||
AND diff.post_count != 0;
|
||||
|
||||
UPDATE
|
||||
community AS a
|
||||
SET
|
||||
|
@ -236,7 +223,6 @@ WHERE
|
|||
AND (diff.posts,
|
||||
diff.comments) != (0,
|
||||
0);
|
||||
|
||||
UPDATE
|
||||
local_site AS a
|
||||
SET
|
||||
|
@ -251,13 +237,9 @@ FROM (
|
|||
AND (post).local) AS diff
|
||||
WHERE
|
||||
diff.posts != 0;
|
||||
|
||||
RETURN NULL;
|
||||
|
||||
END;
|
||||
|
||||
$$);
|
||||
|
||||
CALL r.create_triggers ('community', $$
|
||||
BEGIN
|
||||
UPDATE
|
||||
|
@ -273,13 +255,9 @@ BEGIN
|
|||
AND (community).local) AS diff
|
||||
WHERE
|
||||
diff.communities != 0;
|
||||
|
||||
RETURN NULL;
|
||||
|
||||
END;
|
||||
|
||||
$$);
|
||||
|
||||
CALL r.create_triggers ('local_user', $$
|
||||
BEGIN
|
||||
UPDATE
|
||||
|
@ -293,13 +271,9 @@ BEGIN
|
|||
WHERE (local_user).accepted_application) AS diff
|
||||
WHERE
|
||||
diff.users != 0;
|
||||
|
||||
RETURN NULL;
|
||||
|
||||
END;
|
||||
|
||||
$$);
|
||||
|
||||
-- Count subscribers for communities.
|
||||
-- subscribers should be updated only when a local community is followed by a local or remote person.
|
||||
-- subscribers_local should be updated only when a local person follows a local or remote community.
|
||||
|
@ -319,13 +293,9 @@ BEGIN
|
|||
WHERE
|
||||
a.id = diff.community_id
|
||||
AND (diff.subscribers, diff.subscribers_local) != (0, 0);
|
||||
|
||||
RETURN NULL;
|
||||
|
||||
END;
|
||||
|
||||
$$);
|
||||
|
||||
CALL r.create_triggers ('post_report', $$
|
||||
BEGIN
|
||||
UPDATE
|
||||
|
@ -339,13 +309,9 @@ BEGIN
|
|||
FROM select_old_and_new_rows AS old_and_new_rows GROUP BY (post_report).post_id) AS diff
|
||||
WHERE (diff.report_count, diff.unresolved_report_count) != (0, 0)
|
||||
AND a.id = diff.post_id;
|
||||
|
||||
RETURN NULL;
|
||||
|
||||
END;
|
||||
|
||||
$$);
|
||||
|
||||
CALL r.create_triggers ('comment_report', $$
|
||||
BEGIN
|
||||
UPDATE
|
||||
|
@ -359,13 +325,9 @@ BEGIN
|
|||
FROM select_old_and_new_rows AS old_and_new_rows GROUP BY (comment_report).comment_id) AS diff
|
||||
WHERE (diff.report_count, diff.unresolved_report_count) != (0, 0)
|
||||
AND a.id = diff.comment_id;
|
||||
|
||||
RETURN NULL;
|
||||
|
||||
END;
|
||||
|
||||
$$);
|
||||
|
||||
CALL r.create_triggers ('community_report', $$
|
||||
BEGIN
|
||||
UPDATE
|
||||
|
@ -378,13 +340,9 @@ BEGIN
|
|||
FROM select_old_and_new_rows AS old_and_new_rows GROUP BY (community_report).community_id) AS diff
|
||||
WHERE (diff.report_count, diff.unresolved_report_count) != (0, 0)
|
||||
AND a.id = diff.community_id;
|
||||
|
||||
RETURN NULL;
|
||||
|
||||
END;
|
||||
|
||||
$$);
|
||||
|
||||
-- Change the order of some cascading deletions to make deletion triggers run before the deletion of rows that the triggers need to read
|
||||
CREATE FUNCTION r.delete_follow_before_person ()
|
||||
RETURNS TRIGGER
|
||||
|
@ -396,12 +354,10 @@ BEGIN
|
|||
RETURN OLD;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER delete_follow
|
||||
BEFORE DELETE ON person
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.delete_follow_before_person ();
|
||||
|
||||
-- Triggers that change values before insert or update
|
||||
CREATE FUNCTION r.comment_change_values ()
|
||||
RETURNS TRIGGER
|
||||
|
@ -421,12 +377,10 @@ BEGIN
|
|||
RETURN NEW;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER change_values
|
||||
BEFORE INSERT OR UPDATE ON comment
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.comment_change_values ();
|
||||
|
||||
CREATE FUNCTION r.post_change_values ()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql
|
||||
|
@ -442,12 +396,10 @@ BEGIN
|
|||
RETURN NEW;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER change_values
|
||||
BEFORE INSERT ON post
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.post_change_values ();
|
||||
|
||||
CREATE FUNCTION r.private_message_change_values ()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql
|
||||
|
@ -460,12 +412,10 @@ BEGIN
|
|||
RETURN NEW;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER change_values
|
||||
BEFORE INSERT ON private_message
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.private_message_change_values ();
|
||||
|
||||
-- Combined tables triggers
|
||||
-- These insert (published, item_id) into X_combined tables
|
||||
-- Reports (comment_report, post_report, private_message_report)
|
||||
|
@ -491,15 +441,10 @@ BEGIN
|
|||
table_name);
|
||||
END;
|
||||
$a$;
|
||||
|
||||
CALL r.create_report_combined_trigger ('post_report');
|
||||
|
||||
CALL r.create_report_combined_trigger ('comment_report');
|
||||
|
||||
CALL r.create_report_combined_trigger ('private_message_report');
|
||||
|
||||
CALL r.create_report_combined_trigger ('community_report');
|
||||
|
||||
-- person_content (comment, post)
|
||||
CREATE PROCEDURE r.create_person_content_combined_trigger (table_name text)
|
||||
LANGUAGE plpgsql
|
||||
|
@ -523,14 +468,13 @@ BEGIN
|
|||
table_name);
|
||||
END;
|
||||
$a$;
|
||||
|
||||
CALL r.create_person_content_combined_trigger ('post');
|
||||
|
||||
CALL r.create_person_content_combined_trigger ('comment');
|
||||
|
||||
-- person_saved (comment, post)
|
||||
-- This one is a little different, because it triggers using x_actions.saved,
|
||||
-- Rather than any row insert
|
||||
-- TODO a hack because local is not currently on the post_view table
|
||||
-- https://github.com/LemmyNet/lemmy/pull/5616#discussion_r2064219628
|
||||
CREATE PROCEDURE r.create_person_saved_combined_trigger (table_name text)
|
||||
LANGUAGE plpgsql
|
||||
AS $a$
|
||||
|
@ -571,11 +515,67 @@ BEGIN
|
|||
table_name);
|
||||
END;
|
||||
$a$;
|
||||
|
||||
CALL r.create_person_saved_combined_trigger ('post');
|
||||
|
||||
CALL r.create_person_saved_combined_trigger ('comment');
|
||||
|
||||
-- person_liked (comment, post)
|
||||
-- This one is a little different, because it triggers using x_actions.liked,
|
||||
-- Rather than any row insert
|
||||
-- TODO a hack because local is not currently on the post_view table
|
||||
-- https://github.com/LemmyNet/lemmy/pull/5616#discussion_r2064219628
|
||||
CREATE PROCEDURE r.create_person_liked_combined_trigger (table_name text)
|
||||
LANGUAGE plpgsql
|
||||
AS $a$
|
||||
BEGIN
|
||||
EXECUTE replace($b$ CREATE FUNCTION r.person_liked_combined_change_values_thing ( )
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
IF (TG_OP = 'DELETE') THEN
|
||||
DELETE FROM person_liked_combined AS p
|
||||
WHERE p.person_id = OLD.person_id
|
||||
AND p.thing_id = OLD.thing_id;
|
||||
ELSIF (TG_OP = 'INSERT') THEN
|
||||
IF NEW.liked IS NOT NULL AND (
|
||||
SELECT
|
||||
local
|
||||
FROM
|
||||
person
|
||||
WHERE
|
||||
id = NEW.person_id) = TRUE THEN
|
||||
INSERT INTO person_liked_combined (liked, like_score, person_id, thing_id)
|
||||
VALUES (NEW.liked, NEW.like_score, NEW.person_id, NEW.thing_id);
|
||||
END IF;
|
||||
ELSIF (TG_OP = 'UPDATE') THEN
|
||||
IF NEW.liked IS NOT NULL AND (
|
||||
SELECT
|
||||
local
|
||||
FROM
|
||||
person
|
||||
WHERE
|
||||
id = NEW.person_id) = TRUE THEN
|
||||
INSERT INTO person_liked_combined (liked, like_score, person_id, thing_id)
|
||||
VALUES (NEW.liked, NEW.like_score, NEW.person_id, NEW.thing_id);
|
||||
-- If liked gets set as null, delete the row
|
||||
ELSE
|
||||
DELETE FROM person_liked_combined AS p
|
||||
WHERE p.person_id = NEW.person_id
|
||||
AND p.thing_id = NEW.thing_id;
|
||||
END IF;
|
||||
END IF;
|
||||
RETURN NULL;
|
||||
END $$;
|
||||
CREATE TRIGGER person_liked_combined
|
||||
AFTER INSERT OR DELETE OR UPDATE OF liked ON thing_actions
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.person_liked_combined_change_values_thing ( );
|
||||
$b$,
|
||||
'thing',
|
||||
table_name);
|
||||
END;
|
||||
$a$;
|
||||
CALL r.create_person_liked_combined_trigger ('post');
|
||||
CALL r.create_person_liked_combined_trigger ('comment');
|
||||
-- modlog: (17 tables)
|
||||
-- admin_allow_instance
|
||||
-- admin_block_instance
|
||||
|
@ -616,41 +616,23 @@ BEGIN
|
|||
table_name);
|
||||
END;
|
||||
$a$;
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('admin_allow_instance');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('admin_block_instance');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('admin_purge_comment');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('admin_purge_community');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('admin_purge_person');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('admin_purge_post');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_add');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_add_community');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_ban');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_ban_from_community');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_feature_post');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_change_community_visibility');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_lock_post');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_remove_comment');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_remove_community');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_remove_post');
|
||||
|
||||
CALL r.create_modlog_combined_trigger ('mod_transfer_community');
|
||||
|
||||
-- Inbox: (replies, comment mentions, post mentions, and private_messages)
|
||||
CREATE PROCEDURE r.create_inbox_combined_trigger (table_name text)
|
||||
LANGUAGE plpgsql
|
||||
|
@ -674,15 +656,10 @@ BEGIN
|
|||
table_name);
|
||||
END;
|
||||
$a$;
|
||||
|
||||
CALL r.create_inbox_combined_trigger ('comment_reply');
|
||||
|
||||
CALL r.create_inbox_combined_trigger ('person_comment_mention');
|
||||
|
||||
CALL r.create_inbox_combined_trigger ('person_post_mention');
|
||||
|
||||
CALL r.create_inbox_combined_trigger ('private_message');
|
||||
|
||||
-- Prevent using delete instead of uplete on action tables
|
||||
CREATE FUNCTION r.require_uplete ()
|
||||
RETURNS TRIGGER
|
||||
|
@ -695,32 +672,26 @@ BEGIN
|
|||
RETURN NULL;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER require_uplete
|
||||
BEFORE DELETE ON comment_actions
|
||||
FOR EACH STATEMENT
|
||||
EXECUTE FUNCTION r.require_uplete ();
|
||||
|
||||
CREATE TRIGGER require_uplete
|
||||
BEFORE DELETE ON community_actions
|
||||
FOR EACH STATEMENT
|
||||
EXECUTE FUNCTION r.require_uplete ();
|
||||
|
||||
CREATE TRIGGER require_uplete
|
||||
BEFORE DELETE ON instance_actions
|
||||
FOR EACH STATEMENT
|
||||
EXECUTE FUNCTION r.require_uplete ();
|
||||
|
||||
CREATE TRIGGER require_uplete
|
||||
BEFORE DELETE ON person_actions
|
||||
FOR EACH STATEMENT
|
||||
EXECUTE FUNCTION r.require_uplete ();
|
||||
|
||||
CREATE TRIGGER require_uplete
|
||||
BEFORE DELETE ON post_actions
|
||||
FOR EACH STATEMENT
|
||||
EXECUTE FUNCTION r.require_uplete ();
|
||||
|
||||
-- search: (post, comment, community, person)
|
||||
CREATE PROCEDURE r.create_search_combined_trigger (table_name text)
|
||||
LANGUAGE plpgsql
|
||||
|
@ -745,15 +716,10 @@ BEGIN
|
|||
table_name);
|
||||
END;
|
||||
$a$;
|
||||
|
||||
CALL r.create_search_combined_trigger ('post');
|
||||
|
||||
CALL r.create_search_combined_trigger ('comment');
|
||||
|
||||
CALL r.create_search_combined_trigger ('community');
|
||||
|
||||
CALL r.create_search_combined_trigger ('person');
|
||||
|
||||
-- You also need to triggers to update the `score` column.
|
||||
-- post | post::score
|
||||
-- comment | comment_aggregates::score
|
||||
|
@ -775,12 +741,10 @@ BEGIN
|
|||
RETURN NULL;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER search_combined_post_score
|
||||
AFTER UPDATE OF score ON post
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.search_combined_post_score_update ();
|
||||
|
||||
-- Comment score
|
||||
CREATE FUNCTION r.search_combined_comment_score_update ()
|
||||
RETURNS TRIGGER
|
||||
|
@ -796,12 +760,10 @@ BEGIN
|
|||
RETURN NULL;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER search_combined_comment_score
|
||||
AFTER UPDATE OF score ON comment
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.search_combined_comment_score_update ();
|
||||
|
||||
-- Person score
|
||||
CREATE FUNCTION r.search_combined_person_score_update ()
|
||||
RETURNS TRIGGER
|
||||
|
@ -817,12 +779,10 @@ BEGIN
|
|||
RETURN NULL;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER search_combined_person_score
|
||||
AFTER UPDATE OF post_score ON person
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.search_combined_person_score_update ();
|
||||
|
||||
-- Community score
|
||||
CREATE FUNCTION r.search_combined_community_score_update ()
|
||||
RETURNS TRIGGER
|
||||
|
@ -838,9 +798,7 @@ BEGIN
|
|||
RETURN NULL;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER search_combined_community_score
|
||||
AFTER UPDATE OF users_active_month ON community
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.search_combined_community_score_update ();
|
||||
|
||||
|
|
|
@ -814,6 +814,17 @@ diesel::table! {
|
|||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
person_liked_combined (id) {
|
||||
id -> Int4,
|
||||
liked -> Timestamptz,
|
||||
like_score -> Int2,
|
||||
person_id -> Int4,
|
||||
post_id -> Nullable<Int4>,
|
||||
comment_id -> Nullable<Int4>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
person_post_mention (id) {
|
||||
id -> Int4,
|
||||
|
@ -1167,6 +1178,9 @@ diesel::joinable!(person_comment_mention -> comment (comment_id));
|
|||
diesel::joinable!(person_comment_mention -> person (recipient_id));
|
||||
diesel::joinable!(person_content_combined -> comment (comment_id));
|
||||
diesel::joinable!(person_content_combined -> post (post_id));
|
||||
diesel::joinable!(person_liked_combined -> comment (comment_id));
|
||||
diesel::joinable!(person_liked_combined -> person (person_id));
|
||||
diesel::joinable!(person_liked_combined -> post (post_id));
|
||||
diesel::joinable!(person_post_mention -> person (recipient_id));
|
||||
diesel::joinable!(person_post_mention -> post (post_id));
|
||||
diesel::joinable!(person_saved_combined -> comment (comment_id));
|
||||
|
@ -1251,6 +1265,7 @@ diesel::allow_tables_to_appear_in_same_query!(
|
|||
person_ban,
|
||||
person_comment_mention,
|
||||
person_content_combined,
|
||||
person_liked_combined,
|
||||
person_post_mention,
|
||||
person_saved_combined,
|
||||
post,
|
||||
|
|
|
@ -48,15 +48,7 @@ use lemmy_db_schema_file::{
|
|||
CommunityVisibility,
|
||||
ListingType,
|
||||
},
|
||||
schema::{
|
||||
comment,
|
||||
comment_actions,
|
||||
community,
|
||||
community_actions,
|
||||
local_user_language,
|
||||
person,
|
||||
post,
|
||||
},
|
||||
schema::{comment, community, community_actions, local_user_language, person, post},
|
||||
};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
|
||||
|
@ -163,9 +155,6 @@ pub struct CommentQuery<'a> {
|
|||
pub post_id: Option<PostId>,
|
||||
pub parent_path: Option<Ltree>,
|
||||
pub local_user: Option<&'a LocalUser>,
|
||||
// TODO get rid of liked / disliked_only
|
||||
pub liked_only: Option<bool>,
|
||||
pub disliked_only: Option<bool>,
|
||||
pub max_depth: Option<i32>,
|
||||
pub cursor_data: Option<Comment>,
|
||||
pub page_back: Option<bool>,
|
||||
|
@ -208,19 +197,6 @@ impl CommentQuery<'_> {
|
|||
ListingType::ModeratorView => query.filter(community_actions::became_moderator.is_not_null()),
|
||||
};
|
||||
|
||||
if let Some(my_id) = my_person_id {
|
||||
let not_creator_filter = comment::creator_id.ne(my_id);
|
||||
if o.liked_only.unwrap_or_default() {
|
||||
query = query
|
||||
.filter(not_creator_filter)
|
||||
.filter(comment_actions::like_score.eq(1));
|
||||
} else if o.disliked_only.unwrap_or_default() {
|
||||
query = query
|
||||
.filter(not_creator_filter)
|
||||
.filter(comment_actions::like_score.eq(-1));
|
||||
}
|
||||
}
|
||||
|
||||
if !o.local_user.show_bot_accounts() {
|
||||
query = query.filter(person::bot_account.eq(false));
|
||||
};
|
||||
|
@ -548,52 +524,6 @@ mod tests {
|
|||
cleanup(data, pool).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_liked_only() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests();
|
||||
let pool = &mut pool.into();
|
||||
let data = init_data(pool).await?;
|
||||
|
||||
// Unblock sara first
|
||||
let timmy_unblocks_sara_form =
|
||||
PersonBlockForm::new(data.timmy_local_user_view.person.id, data.sara_person.id);
|
||||
PersonActions::unblock(pool, &timmy_unblocks_sara_form).await?;
|
||||
|
||||
// Like a new comment
|
||||
let comment_like_form =
|
||||
CommentLikeForm::new(data.timmy_local_user_view.person.id, data.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),
|
||||
liked_only: Some(true),
|
||||
..Default::default()
|
||||
}
|
||||
.list(&data.site, pool)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|c| c.comment.content)
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
// Shouldn't include your own post, only other peoples
|
||||
assert_eq!(data.comment_1.content, read_liked_comment_views[0]);
|
||||
|
||||
assert_length!(1, read_liked_comment_views);
|
||||
|
||||
let read_disliked_comment_views: Vec<CommentView> = CommentQuery {
|
||||
local_user: Some(&data.timmy_local_user_view.local_user),
|
||||
disliked_only: Some(true),
|
||||
..Default::default()
|
||||
}
|
||||
.list(&data.site, pool)
|
||||
.await?;
|
||||
|
||||
assert!(read_disliked_comment_views.is_empty());
|
||||
|
||||
cleanup(data, pool).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_comment_tree() -> LemmyResult<()> {
|
||||
|
|
47
crates/db_views/person_liked_combined/Cargo.toml
Normal file
47
crates/db_views/person_liked_combined/Cargo.toml
Normal file
|
@ -0,0 +1,47 @@
|
|||
[package]
|
||||
name = "lemmy_db_views_person_liked_combined"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
description.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[features]
|
||||
full = [
|
||||
"lemmy_utils",
|
||||
"diesel",
|
||||
"diesel-async",
|
||||
"ts-rs",
|
||||
"i-love-jesus",
|
||||
"lemmy_db_schema/full",
|
||||
"lemmy_db_schema_file/full",
|
||||
"lemmy_db_views_comment/full",
|
||||
"lemmy_db_views_post/full",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
lemmy_db_views_post = { workspace = true }
|
||||
lemmy_db_views_comment = { workspace = true }
|
||||
lemmy_db_views_local_user = { workspace = true }
|
||||
lemmy_db_schema = { workspace = true }
|
||||
lemmy_utils = { workspace = true, optional = true }
|
||||
lemmy_db_schema_file = { workspace = true }
|
||||
diesel = { workspace = true, optional = true }
|
||||
diesel-async = { workspace = true, optional = true }
|
||||
serde = { workspace = true }
|
||||
serde_with = { workspace = true }
|
||||
ts-rs = { workspace = true, optional = true }
|
||||
i-love-jesus = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = { workspace = true }
|
||||
serial_test = { workspace = true }
|
||||
tokio = { workspace = true }
|
451
crates/db_views/person_liked_combined/src/impls.rs
Normal file
451
crates/db_views/person_liked_combined/src/impls.rs
Normal file
|
@ -0,0 +1,451 @@
|
|||
use crate::{
|
||||
CommentView,
|
||||
LocalUserView,
|
||||
PersonLikedCombinedView,
|
||||
PersonLikedCombinedViewInternal,
|
||||
PostView,
|
||||
};
|
||||
use diesel::{
|
||||
BoolExpressionMethods,
|
||||
ExpressionMethods,
|
||||
JoinOnDsl,
|
||||
NullableExpressionMethods,
|
||||
QueryDsl,
|
||||
SelectableHelper,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use i_love_jesus::SortDirection;
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{InstanceId, PaginationCursor, PersonId},
|
||||
source::combined::person_liked::{person_liked_combined_keys as key, PersonLikedCombined},
|
||||
traits::{InternalToCombinedView, PaginationCursorBuilder},
|
||||
utils::{
|
||||
get_conn,
|
||||
limit_fetch,
|
||||
paginate,
|
||||
queries::{
|
||||
community_join,
|
||||
creator_community_actions_join,
|
||||
creator_home_instance_actions_join,
|
||||
creator_local_instance_actions_join,
|
||||
creator_local_user_admin_join,
|
||||
image_details_join,
|
||||
my_comment_actions_join,
|
||||
my_community_actions_join,
|
||||
my_instance_actions_person_join,
|
||||
my_local_user_admin_join,
|
||||
my_person_actions_join,
|
||||
my_post_actions_join,
|
||||
},
|
||||
DbPool,
|
||||
},
|
||||
LikeType,
|
||||
PersonContentType,
|
||||
};
|
||||
use lemmy_db_schema_file::schema::{comment, person, person_liked_combined, post};
|
||||
use lemmy_utils::error::{LemmyErrorType, LemmyResult};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PersonLikedCombinedQuery {
|
||||
pub type_: Option<PersonContentType>,
|
||||
pub like_type: Option<LikeType>,
|
||||
pub cursor_data: Option<PersonLikedCombined>,
|
||||
pub page_back: Option<bool>,
|
||||
pub limit: Option<i64>,
|
||||
}
|
||||
|
||||
impl PaginationCursorBuilder for PersonLikedCombinedView {
|
||||
type CursorData = PersonLikedCombined;
|
||||
|
||||
fn to_cursor(&self) -> PaginationCursor {
|
||||
let (prefix, id) = match &self {
|
||||
PersonLikedCombinedView::Comment(v) => ('C', v.comment.id.0),
|
||||
PersonLikedCombinedView::Post(v) => ('P', v.post.id.0),
|
||||
};
|
||||
PaginationCursor::new_single(prefix, id)
|
||||
}
|
||||
|
||||
async fn from_cursor(
|
||||
cursor: &PaginationCursor,
|
||||
pool: &mut DbPool<'_>,
|
||||
) -> LemmyResult<Self::CursorData> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let pids = cursor.prefixes_and_ids();
|
||||
let (prefix, id) = pids
|
||||
.as_slice()
|
||||
.first()
|
||||
.ok_or(LemmyErrorType::CouldntParsePaginationToken)?;
|
||||
|
||||
let mut query = person_liked_combined::table
|
||||
.select(Self::CursorData::as_select())
|
||||
.into_boxed();
|
||||
|
||||
query = match prefix {
|
||||
'C' => query.filter(person_liked_combined::comment_id.eq(id)),
|
||||
'P' => query.filter(person_liked_combined::post_id.eq(id)),
|
||||
_ => return Err(LemmyErrorType::CouldntParsePaginationToken.into()),
|
||||
};
|
||||
let token = query.first(conn).await?;
|
||||
|
||||
Ok(token)
|
||||
}
|
||||
}
|
||||
|
||||
impl PersonLikedCombinedViewInternal {
|
||||
#[diesel::dsl::auto_type(no_type_alias)]
|
||||
pub(crate) fn joins(my_person_id: PersonId, local_instance_id: InstanceId) -> _ {
|
||||
let item_creator = person::id;
|
||||
|
||||
let comment_join =
|
||||
comment::table.on(person_liked_combined::comment_id.eq(comment::id.nullable()));
|
||||
|
||||
let post_join = post::table.on(
|
||||
person_liked_combined::post_id
|
||||
.eq(post::id.nullable())
|
||||
.or(comment::post_id.eq(post::id)),
|
||||
);
|
||||
|
||||
let item_creator_join = person::table.on(
|
||||
comment::creator_id
|
||||
.eq(item_creator)
|
||||
// Need to filter out the post rows where the post_id given is null
|
||||
// Otherwise you'll get duped post rows
|
||||
.or(
|
||||
post::creator_id
|
||||
.eq(item_creator)
|
||||
.and(person_liked_combined::post_id.is_not_null()),
|
||||
),
|
||||
);
|
||||
|
||||
let my_community_actions_join: my_community_actions_join =
|
||||
my_community_actions_join(Some(my_person_id));
|
||||
let my_post_actions_join: my_post_actions_join = my_post_actions_join(Some(my_person_id));
|
||||
let my_comment_actions_join: my_comment_actions_join =
|
||||
my_comment_actions_join(Some(my_person_id));
|
||||
let my_local_user_admin_join: my_local_user_admin_join =
|
||||
my_local_user_admin_join(Some(my_person_id));
|
||||
let my_instance_actions_person_join: my_instance_actions_person_join =
|
||||
my_instance_actions_person_join(Some(my_person_id));
|
||||
let my_person_actions_join: my_person_actions_join = my_person_actions_join(Some(my_person_id));
|
||||
let creator_local_instance_actions_join: creator_local_instance_actions_join =
|
||||
creator_local_instance_actions_join(local_instance_id);
|
||||
|
||||
person_liked_combined::table
|
||||
.left_join(comment_join)
|
||||
.inner_join(post_join)
|
||||
.inner_join(item_creator_join)
|
||||
.inner_join(community_join())
|
||||
.left_join(creator_community_actions_join())
|
||||
.left_join(my_local_user_admin_join)
|
||||
.left_join(creator_local_user_admin_join())
|
||||
.left_join(my_community_actions_join)
|
||||
.left_join(my_instance_actions_person_join)
|
||||
.left_join(creator_home_instance_actions_join())
|
||||
.left_join(creator_local_instance_actions_join)
|
||||
.left_join(my_post_actions_join)
|
||||
.left_join(my_person_actions_join)
|
||||
.left_join(my_comment_actions_join)
|
||||
.left_join(image_details_join())
|
||||
}
|
||||
}
|
||||
|
||||
impl PersonLikedCombinedQuery {
|
||||
pub async fn list(
|
||||
self,
|
||||
pool: &mut DbPool<'_>,
|
||||
user: &LocalUserView,
|
||||
) -> LemmyResult<Vec<PersonLikedCombinedView>> {
|
||||
let my_person_id = user.local_user.person_id;
|
||||
let local_instance_id = user.person.instance_id;
|
||||
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let limit = limit_fetch(self.limit)?;
|
||||
|
||||
let mut query = PersonLikedCombinedViewInternal::joins(my_person_id, local_instance_id)
|
||||
.filter(person_liked_combined::person_id.eq(my_person_id))
|
||||
.select(PersonLikedCombinedViewInternal::as_select())
|
||||
.limit(limit)
|
||||
.into_boxed();
|
||||
|
||||
if let Some(type_) = self.type_ {
|
||||
query = match type_ {
|
||||
PersonContentType::All => query,
|
||||
PersonContentType::Comments => {
|
||||
query.filter(person_liked_combined::comment_id.is_not_null())
|
||||
}
|
||||
PersonContentType::Posts => query.filter(person_liked_combined::post_id.is_not_null()),
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(like_type) = self.like_type {
|
||||
query = match like_type {
|
||||
LikeType::All => query,
|
||||
LikeType::LikedOnly => query.filter(person_liked_combined::like_score.eq(1)),
|
||||
LikeType::DislikedOnly => query.filter(person_liked_combined::like_score.eq(-1)),
|
||||
}
|
||||
}
|
||||
|
||||
// Sorting by liked desc
|
||||
let paginated_query = paginate(
|
||||
query,
|
||||
SortDirection::Desc,
|
||||
self.cursor_data,
|
||||
None,
|
||||
self.page_back,
|
||||
)
|
||||
.then_order_by(key::liked)
|
||||
// Tie breaker
|
||||
.then_order_by(key::id);
|
||||
|
||||
let res = paginated_query
|
||||
.load::<PersonLikedCombinedViewInternal>(conn)
|
||||
.await?;
|
||||
|
||||
// Map the query results to the enum
|
||||
let out = res
|
||||
.into_iter()
|
||||
.filter_map(InternalToCombinedView::map_to_enum)
|
||||
.collect();
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
}
|
||||
|
||||
impl InternalToCombinedView for PersonLikedCombinedViewInternal {
|
||||
type CombinedView = PersonLikedCombinedView;
|
||||
|
||||
fn map_to_enum(self) -> Option<Self::CombinedView> {
|
||||
// Use for a short alias
|
||||
let v = self;
|
||||
|
||||
if let Some(comment) = v.comment {
|
||||
Some(PersonLikedCombinedView::Comment(CommentView {
|
||||
comment,
|
||||
post: v.post,
|
||||
community: v.community,
|
||||
creator: v.item_creator,
|
||||
community_actions: v.community_actions,
|
||||
comment_actions: v.comment_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
creator_home_instance_actions: v.creator_home_instance_actions,
|
||||
creator_local_instance_actions: v.creator_local_instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
post_tags: v.post_tags,
|
||||
can_mod: v.can_mod,
|
||||
creator_banned: v.creator_banned,
|
||||
}))
|
||||
} else {
|
||||
Some(PersonLikedCombinedView::Post(PostView {
|
||||
post: v.post,
|
||||
community: v.community,
|
||||
creator: v.item_creator,
|
||||
image_details: v.image_details,
|
||||
community_actions: v.community_actions,
|
||||
post_actions: v.post_actions,
|
||||
person_actions: v.person_actions,
|
||||
instance_actions: v.instance_actions,
|
||||
creator_home_instance_actions: v.creator_home_instance_actions,
|
||||
creator_local_instance_actions: v.creator_local_instance_actions,
|
||||
creator_community_actions: v.creator_community_actions,
|
||||
creator_is_admin: v.item_creator_is_admin,
|
||||
tags: v.post_tags,
|
||||
can_mod: v.can_mod,
|
||||
creator_banned: v.creator_banned,
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[expect(clippy::indexing_slicing)]
|
||||
mod tests {
|
||||
|
||||
use crate::{impls::PersonLikedCombinedQuery, LocalUserView, PersonLikedCombinedView};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
comment::{Comment, CommentActions, CommentInsertForm, CommentLikeForm},
|
||||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
local_user::{LocalUser, LocalUserInsertForm},
|
||||
person::{Person, PersonInsertForm},
|
||||
post::{Post, PostActions, PostInsertForm, PostLikeForm},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
utils::{build_db_pool_for_tests, DbPool},
|
||||
LikeType,
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
struct Data {
|
||||
instance: Instance,
|
||||
timmy: Person,
|
||||
timmy_view: LocalUserView,
|
||||
sara: Person,
|
||||
timmy_post: Post,
|
||||
sara_comment: Comment,
|
||||
sara_comment_2: Comment,
|
||||
}
|
||||
|
||||
async fn init_data(pool: &mut DbPool<'_>) -> LemmyResult<Data> {
|
||||
let instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?;
|
||||
|
||||
let timmy_form = PersonInsertForm::test_form(instance.id, "timmy_pcv");
|
||||
let timmy = Person::create(pool, &timmy_form).await?;
|
||||
let timmy_local_user_form = LocalUserInsertForm::test_form(timmy.id);
|
||||
let timmy_local_user = LocalUser::create(pool, &timmy_local_user_form, vec![]).await?;
|
||||
let timmy_view = LocalUserView {
|
||||
local_user: timmy_local_user,
|
||||
person: timmy.clone(),
|
||||
instance_actions: None,
|
||||
};
|
||||
|
||||
let sara_form = PersonInsertForm::test_form(instance.id, "sara_pcv");
|
||||
let sara = Person::create(pool, &sara_form).await?;
|
||||
|
||||
let community_form = CommunityInsertForm::new(
|
||||
instance.id,
|
||||
"test community pcv".to_string(),
|
||||
"nada".to_owned(),
|
||||
"pubkey".to_string(),
|
||||
);
|
||||
let community = Community::create(pool, &community_form).await?;
|
||||
|
||||
let timmy_post_form = PostInsertForm::new("timmy post prv".into(), timmy.id, community.id);
|
||||
let timmy_post = Post::create(pool, &timmy_post_form).await?;
|
||||
|
||||
let timmy_post_form_2 = PostInsertForm::new("timmy post prv 2".into(), timmy.id, community.id);
|
||||
let timmy_post_2 = Post::create(pool, &timmy_post_form_2).await?;
|
||||
|
||||
let sara_post_form = PostInsertForm::new("sara post prv".into(), sara.id, community.id);
|
||||
let _sara_post = Post::create(pool, &sara_post_form).await?;
|
||||
|
||||
let timmy_comment_form =
|
||||
CommentInsertForm::new(timmy.id, timmy_post.id, "timmy comment prv".into());
|
||||
let _timmy_comment = Comment::create(pool, &timmy_comment_form, None).await?;
|
||||
|
||||
let sara_comment_form =
|
||||
CommentInsertForm::new(sara.id, timmy_post.id, "sara comment prv".into());
|
||||
let sara_comment = Comment::create(pool, &sara_comment_form, None).await?;
|
||||
|
||||
let sara_comment_form_2 =
|
||||
CommentInsertForm::new(sara.id, timmy_post_2.id, "sara comment prv 2".into());
|
||||
let sara_comment_2 = Comment::create(pool, &sara_comment_form_2, None).await?;
|
||||
|
||||
Ok(Data {
|
||||
instance,
|
||||
timmy,
|
||||
timmy_view,
|
||||
sara,
|
||||
timmy_post,
|
||||
sara_comment,
|
||||
sara_comment_2,
|
||||
})
|
||||
}
|
||||
|
||||
async fn cleanup(data: Data, pool: &mut DbPool<'_>) -> LemmyResult<()> {
|
||||
Instance::delete(pool, data.instance.id).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_combined() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests();
|
||||
let pool = &mut pool.into();
|
||||
let data = init_data(pool).await?;
|
||||
|
||||
// Do a batch read of timmy liked
|
||||
let timmy_liked = PersonLikedCombinedQuery::default()
|
||||
.list(pool, &data.timmy_view)
|
||||
.await?;
|
||||
assert_eq!(0, timmy_liked.len());
|
||||
|
||||
// Like a few things
|
||||
let like_sara_comment_2 = CommentLikeForm::new(data.timmy.id, data.sara_comment_2.id, 1);
|
||||
CommentActions::like(pool, &like_sara_comment_2).await?;
|
||||
|
||||
let dislike_sara_comment = CommentLikeForm::new(data.timmy.id, data.sara_comment.id, -1);
|
||||
CommentActions::like(pool, &dislike_sara_comment).await?;
|
||||
|
||||
let post_like_form = PostLikeForm::new(data.timmy_post.id, data.timmy.id, 1);
|
||||
PostActions::like(pool, &post_like_form).await?;
|
||||
|
||||
let timmy_liked_all = PersonLikedCombinedQuery::default()
|
||||
.list(pool, &data.timmy_view)
|
||||
.await?;
|
||||
assert_eq!(3, timmy_liked_all.len());
|
||||
|
||||
// Make sure the types and order are correct
|
||||
if let PersonLikedCombinedView::Post(v) = &timmy_liked_all[0] {
|
||||
assert_eq!(data.timmy_post.id, v.post.id);
|
||||
assert_eq!(data.timmy.id, v.post.creator_id);
|
||||
assert_eq!(Some(1), v.post_actions.as_ref().and_then(|l| l.like_score));
|
||||
} else {
|
||||
panic!("wrong type");
|
||||
}
|
||||
if let PersonLikedCombinedView::Comment(v) = &timmy_liked_all[1] {
|
||||
assert_eq!(data.sara_comment.id, v.comment.id);
|
||||
assert_eq!(data.sara.id, v.comment.creator_id);
|
||||
assert_eq!(
|
||||
Some(-1),
|
||||
v.comment_actions.as_ref().and_then(|l| l.like_score)
|
||||
);
|
||||
} else {
|
||||
panic!("wrong type");
|
||||
}
|
||||
if let PersonLikedCombinedView::Comment(v) = &timmy_liked_all[2] {
|
||||
assert_eq!(data.sara_comment_2.id, v.comment.id);
|
||||
assert_eq!(data.sara.id, v.comment.creator_id);
|
||||
assert_eq!(
|
||||
Some(1),
|
||||
v.comment_actions.as_ref().and_then(|l| l.like_score)
|
||||
);
|
||||
} else {
|
||||
panic!("wrong type");
|
||||
}
|
||||
|
||||
let timmy_disliked = PersonLikedCombinedQuery {
|
||||
like_type: Some(LikeType::DislikedOnly),
|
||||
..PersonLikedCombinedQuery::default()
|
||||
}
|
||||
.list(pool, &data.timmy_view)
|
||||
.await?;
|
||||
assert_eq!(1, timmy_disliked.len());
|
||||
|
||||
if let PersonLikedCombinedView::Comment(v) = &timmy_disliked[0] {
|
||||
assert_eq!(data.sara_comment.id, v.comment.id);
|
||||
assert_eq!(data.sara.id, v.comment.creator_id);
|
||||
assert_eq!(
|
||||
Some(-1),
|
||||
v.comment_actions.as_ref().and_then(|l| l.like_score)
|
||||
);
|
||||
} else {
|
||||
panic!("wrong type");
|
||||
}
|
||||
|
||||
// Try unliking 2 things
|
||||
CommentActions::remove_like(pool, data.timmy.id, data.sara_comment.id).await?;
|
||||
PostActions::remove_like(pool, data.timmy.id, data.timmy_post.id).await?;
|
||||
|
||||
let timmy_likes_removed = PersonLikedCombinedQuery::default()
|
||||
.list(pool, &data.timmy_view)
|
||||
.await?;
|
||||
assert_eq!(1, timmy_likes_removed.len());
|
||||
|
||||
if let PersonLikedCombinedView::Comment(v) = &timmy_likes_removed[0] {
|
||||
assert_eq!(data.sara_comment_2.id, v.comment.id);
|
||||
assert_eq!(data.sara.id, v.comment.creator_id);
|
||||
} else {
|
||||
panic!("wrong type");
|
||||
}
|
||||
|
||||
cleanup(data, pool).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
152
crates/db_views/person_liked_combined/src/lib.rs
Normal file
152
crates/db_views/person_liked_combined/src/lib.rs
Normal file
|
@ -0,0 +1,152 @@
|
|||
use lemmy_db_schema::{
|
||||
newtypes::PaginationCursor,
|
||||
source::{
|
||||
combined::person_liked::PersonLikedCombined,
|
||||
comment::{Comment, CommentActions},
|
||||
community::{Community, CommunityActions},
|
||||
images::ImageDetails,
|
||||
instance::InstanceActions,
|
||||
person::{Person, PersonActions},
|
||||
post::{Post, PostActions},
|
||||
tag::TagsView,
|
||||
},
|
||||
LikeType,
|
||||
PersonContentType,
|
||||
};
|
||||
use lemmy_db_views_comment::CommentView;
|
||||
use lemmy_db_views_post::PostView;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::skip_serializing_none;
|
||||
#[cfg(feature = "full")]
|
||||
use {
|
||||
diesel::{dsl::Nullable, NullableExpressionMethods, Queryable, Selectable},
|
||||
lemmy_db_schema::{
|
||||
utils::queries::{
|
||||
creator_banned,
|
||||
creator_community_actions_select,
|
||||
creator_home_instance_actions_select,
|
||||
creator_is_admin,
|
||||
creator_local_instance_actions_select,
|
||||
local_user_can_mod,
|
||||
post_tags_fragment,
|
||||
},
|
||||
CreatorCommunityActionsAllColumnsTuple,
|
||||
CreatorHomeInstanceActionsAllColumnsTuple,
|
||||
CreatorLocalInstanceActionsAllColumnsTuple,
|
||||
},
|
||||
lemmy_db_views_local_user::LocalUserView,
|
||||
ts_rs::TS,
|
||||
};
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
pub mod impls;
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
#[cfg_attr(feature = "full", derive(Queryable, Selectable))]
|
||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||
/// A combined person_saved view
|
||||
pub(crate) struct PersonLikedCombinedViewInternal {
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub person_liked_combined: PersonLikedCombined,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub comment: Option<Comment>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub post: Post,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub item_creator: Person,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub community: Community,
|
||||
#[cfg_attr(feature = "full",
|
||||
diesel(
|
||||
select_expression_type = Nullable<CreatorCommunityActionsAllColumnsTuple>,
|
||||
select_expression = creator_community_actions_select().nullable()
|
||||
)
|
||||
)]
|
||||
pub creator_community_actions: Option<CommunityActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub community_actions: Option<CommunityActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<CreatorHomeInstanceActionsAllColumnsTuple>,
|
||||
select_expression = creator_home_instance_actions_select()))]
|
||||
pub creator_home_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(
|
||||
select_expression_type = Nullable<CreatorLocalInstanceActionsAllColumnsTuple>,
|
||||
select_expression = creator_local_instance_actions_select()))]
|
||||
pub creator_local_instance_actions: Option<InstanceActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub post_actions: Option<PostActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub person_actions: Option<PersonActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub comment_actions: Option<CommentActions>,
|
||||
#[cfg_attr(feature = "full", diesel(embed))]
|
||||
pub image_details: Option<ImageDetails>,
|
||||
#[cfg_attr(feature = "full",
|
||||
diesel(
|
||||
select_expression = creator_is_admin()
|
||||
)
|
||||
)]
|
||||
pub item_creator_is_admin: bool,
|
||||
#[cfg_attr(feature = "full",
|
||||
diesel(
|
||||
select_expression = post_tags_fragment()
|
||||
)
|
||||
)]
|
||||
pub post_tags: TagsView,
|
||||
#[cfg_attr(feature = "full",
|
||||
diesel(
|
||||
select_expression = local_user_can_mod()
|
||||
)
|
||||
)]
|
||||
pub can_mod: bool,
|
||||
#[cfg_attr(feature = "full",
|
||||
diesel(
|
||||
select_expression = creator_banned()
|
||||
)
|
||||
)]
|
||||
pub creator_banned: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
#[cfg_attr(feature = "full", derive(TS))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
// Use serde's internal tagging, to work easier with javascript libraries
|
||||
#[serde(tag = "type_")]
|
||||
pub enum PersonLikedCombinedView {
|
||||
Post(PostView),
|
||||
Comment(CommentView),
|
||||
}
|
||||
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "full", derive(TS))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
/// Gets your liked / disliked posts
|
||||
pub struct ListPersonLiked {
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub type_: Option<PersonContentType>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub like_type: Option<LikeType>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub page_cursor: Option<PaginationCursor>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub page_back: Option<bool>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub limit: Option<i64>,
|
||||
}
|
||||
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[cfg_attr(feature = "full", derive(TS))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
/// Your liked posts response.
|
||||
pub struct ListPersonLikedResponse {
|
||||
pub liked: Vec<PersonLikedCombinedView>,
|
||||
/// the pagination cursor to use to fetch the next page
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub next_page: Option<PaginationCursor>,
|
||||
#[cfg_attr(feature = "full", ts(optional))]
|
||||
pub prev_page: Option<PaginationCursor>,
|
||||
}
|
|
@ -23,6 +23,8 @@ full = [
|
|||
"i-love-jesus",
|
||||
"lemmy_db_schema/full",
|
||||
"lemmy_db_schema_file/full",
|
||||
"lemmy_db_views_post/full",
|
||||
"lemmy_db_views_comment/full",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -241,8 +241,6 @@ pub struct PostQuery<'a> {
|
|||
pub time_range_seconds: Option<i32>,
|
||||
pub community_id: Option<CommunityId>,
|
||||
pub local_user: Option<&'a LocalUser>,
|
||||
pub liked_only: Option<bool>,
|
||||
pub disliked_only: Option<bool>,
|
||||
pub show_hidden: Option<bool>,
|
||||
pub show_read: Option<bool>,
|
||||
pub show_nsfw: Option<bool>,
|
||||
|
@ -396,20 +394,6 @@ impl PostQuery<'_> {
|
|||
));
|
||||
}
|
||||
|
||||
// TODO move liked only elsewhere
|
||||
if let Some(my_id) = my_person_id {
|
||||
let not_creator_filter = post::creator_id.ne(my_id);
|
||||
if o.liked_only.unwrap_or_default() {
|
||||
query = query
|
||||
.filter(not_creator_filter)
|
||||
.filter(post_actions::like_score.eq(1));
|
||||
} else if o.disliked_only.unwrap_or_default() {
|
||||
query = query
|
||||
.filter(not_creator_filter)
|
||||
.filter(post_actions::like_score.eq(-1));
|
||||
}
|
||||
};
|
||||
|
||||
query = o.local_user.visible_communities_only(query);
|
||||
query = query.filter(
|
||||
post::federation_pending
|
||||
|
@ -1019,48 +1003,6 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test_context(Data)]
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn post_listing_liked_only(data: &mut Data) -> LemmyResult<()> {
|
||||
let pool = &data.pool();
|
||||
let pool = &mut pool.into();
|
||||
|
||||
// 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);
|
||||
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);
|
||||
PostActions::like(pool, &bot_post_like_form).await?;
|
||||
|
||||
// Read the liked only
|
||||
let read_liked_post_listing = PostQuery {
|
||||
community_id: Some(data.community.id),
|
||||
liked_only: Some(true),
|
||||
..data.default_post_query()
|
||||
}
|
||||
.list(&data.site, pool)
|
||||
.await?;
|
||||
|
||||
// This should only include the bot post, not the one you created
|
||||
assert_eq!(vec![POST_BY_BOT], names(&read_liked_post_listing));
|
||||
|
||||
let read_disliked_post_listing = PostQuery {
|
||||
community_id: Some(data.community.id),
|
||||
disliked_only: Some(true),
|
||||
..data.default_post_query()
|
||||
}
|
||||
.list(&data.site, pool)
|
||||
.await?;
|
||||
|
||||
// Should be no posts
|
||||
assert_eq!(read_disliked_post_listing, vec![]);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_context(Data)]
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
|
|
|
@ -49,7 +49,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -41,7 +41,7 @@ with all_comment AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -121,7 +121,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -220,7 +220,7 @@ with all_comment AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -125,7 +125,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -228,7 +228,7 @@ with all_comment AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -132,7 +132,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -139,7 +139,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -55,7 +55,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -70,7 +70,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -76,7 +76,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -122,7 +122,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -124,7 +124,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -299,7 +299,7 @@ with all_comment AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -132,7 +132,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -327,7 +327,7 @@ with all_comment AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -111,7 +111,7 @@ with all_post AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -376,7 +376,7 @@ with all_comment AS (
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -74,7 +74,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -430,7 +430,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -94,7 +94,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -95,7 +95,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -61,7 +61,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -72,7 +72,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -82,7 +82,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -83,7 +83,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -96,7 +96,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -97,7 +97,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -351,7 +351,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -566,7 +566,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -494,7 +494,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -741,7 +741,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -405,7 +405,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN pl.score = - 1 THEN
|
||||
CASE WHEN pl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -662,7 +662,7 @@ SELECT
|
|||
NULL
|
||||
END) AS upvotes,
|
||||
count(
|
||||
CASE WHEN cl.score = - 1 THEN
|
||||
CASE WHEN cl.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -198,7 +198,7 @@ FROM
|
|||
post_id,
|
||||
sum(score) AS score,
|
||||
sum(score) FILTER (WHERE score = 1) AS upvotes,
|
||||
- sum(score) FILTER (WHERE score = - 1) AS downvotes
|
||||
- sum(score) FILTER (WHERE score = -1) AS downvotes
|
||||
FROM
|
||||
post_like
|
||||
GROUP BY
|
||||
|
@ -658,7 +658,7 @@ FROM
|
|||
NULL
|
||||
END) AS up,
|
||||
count(
|
||||
CASE WHEN l.score = - 1 THEN
|
||||
CASE WHEN l.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -1062,7 +1062,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN (OLD.score = - 1) THEN
|
||||
downvotes = CASE WHEN (OLD.score = -1) THEN
|
||||
downvotes - 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -1083,7 +1083,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN (NEW.score = - 1) THEN
|
||||
downvotes = CASE WHEN (NEW.score = -1) THEN
|
||||
downvotes + 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -1130,7 +1130,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN (OLD.score = - 1) THEN
|
||||
downvotes = CASE WHEN (OLD.score = -1) THEN
|
||||
downvotes - 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -1151,7 +1151,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN (NEW.score = - 1) THEN
|
||||
downvotes = CASE WHEN (NEW.score = -1) THEN
|
||||
downvotes + 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
|
|
@ -51,7 +51,7 @@ FROM
|
|||
NULL
|
||||
END) AS up,
|
||||
count(
|
||||
CASE WHEN l.score = - 1 THEN
|
||||
CASE WHEN l.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -396,7 +396,7 @@ FROM
|
|||
post_id,
|
||||
sum(score) AS score,
|
||||
sum(score) FILTER (WHERE score = 1) AS upvotes,
|
||||
- sum(score) FILTER (WHERE score = - 1) AS downvotes
|
||||
- sum(score) FILTER (WHERE score = -1) AS downvotes
|
||||
FROM
|
||||
post_like
|
||||
GROUP BY
|
||||
|
|
|
@ -52,7 +52,7 @@ FROM
|
|||
NULL
|
||||
END) AS up,
|
||||
count(
|
||||
CASE WHEN l.score = - 1 THEN
|
||||
CASE WHEN l.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
@ -398,7 +398,7 @@ FROM
|
|||
post_id,
|
||||
sum(score) AS score,
|
||||
sum(score) FILTER (WHERE score = 1) AS upvotes,
|
||||
- sum(score) FILTER (WHERE score = - 1) AS downvotes
|
||||
- sum(score) FILTER (WHERE score = -1) AS downvotes
|
||||
FROM
|
||||
post_like
|
||||
GROUP BY
|
||||
|
|
|
@ -52,7 +52,7 @@ FROM
|
|||
NULL
|
||||
END) AS up,
|
||||
count(
|
||||
CASE WHEN l.score = - 1 THEN
|
||||
CASE WHEN l.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -54,7 +54,7 @@ FROM
|
|||
NULL
|
||||
END) AS up,
|
||||
count(
|
||||
CASE WHEN l.score = - 1 THEN
|
||||
CASE WHEN l.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -203,7 +203,7 @@ FROM
|
|||
post_id,
|
||||
sum(score) AS score,
|
||||
sum(score) FILTER (WHERE score = 1) AS upvotes,
|
||||
- sum(score) FILTER (WHERE score = - 1) AS downvotes
|
||||
- sum(score) FILTER (WHERE score = -1) AS downvotes
|
||||
FROM
|
||||
post_like
|
||||
GROUP BY
|
||||
|
@ -514,7 +514,7 @@ FROM
|
|||
NULL
|
||||
END) AS up,
|
||||
count(
|
||||
CASE WHEN l.score = - 1 THEN
|
||||
CASE WHEN l.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -185,7 +185,7 @@ FROM
|
|||
post_id,
|
||||
sum(score) AS score,
|
||||
sum(score) FILTER (WHERE score = 1) AS upvotes,
|
||||
- sum(score) FILTER (WHERE score = - 1) AS downvotes
|
||||
- sum(score) FILTER (WHERE score = -1) AS downvotes
|
||||
FROM
|
||||
post_like
|
||||
GROUP BY
|
||||
|
@ -524,7 +524,7 @@ FROM
|
|||
NULL
|
||||
END) AS up,
|
||||
count(
|
||||
CASE WHEN l.score = - 1 THEN
|
||||
CASE WHEN l.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
NULL
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
ALTER TABLE activity
|
||||
ADD COLUMN ap_id TEXT;
|
||||
ADD COLUMN ap_id text;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
ALTER TABLE activity
|
||||
ADD COLUMN user_id INTEGER;
|
||||
ADD COLUMN user_id integer;
|
||||
|
||||
ALTER TABLE activity
|
||||
DROP COLUMN sensitive;
|
||||
|
|
|
@ -2,5 +2,5 @@ ALTER TABLE activity
|
|||
DROP COLUMN user_id;
|
||||
|
||||
ALTER TABLE activity
|
||||
ADD COLUMN sensitive BOOLEAN DEFAULT TRUE;
|
||||
ADD COLUMN sensitive boolean DEFAULT TRUE;
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
ALTER TABLE community_follower
|
||||
ADD COLUMN pending BOOLEAN DEFAULT FALSE;
|
||||
ADD COLUMN pending boolean DEFAULT FALSE;
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
ALTER TABLE user_
|
||||
ADD COLUMN deleted BOOLEAN DEFAULT FALSE NOT NULL;
|
||||
ADD COLUMN deleted boolean DEFAULT FALSE NOT NULL;
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN NEW.score = - 1 THEN
|
||||
downvotes = CASE WHEN NEW.score = -1 THEN
|
||||
downvotes + 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -143,7 +143,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN OLD.score = - 1 THEN
|
||||
downvotes = CASE WHEN OLD.score = -1 THEN
|
||||
downvotes - 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
|
|
@ -78,7 +78,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN NEW.score = - 1 THEN
|
||||
downvotes = CASE WHEN NEW.score = -1 THEN
|
||||
downvotes + 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -96,7 +96,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN OLD.score = - 1 THEN
|
||||
downvotes = CASE WHEN OLD.score = -1 THEN
|
||||
downvotes - 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
ALTER TABLE site
|
||||
ADD COLUMN actor_id varchar(255) NOT NULL UNIQUE DEFAULT generate_unique_changeme (),
|
||||
ADD COLUMN last_refreshed_at Timestamp NOT NULL DEFAULT now(),
|
||||
ADD COLUMN last_refreshed_at timestamp NOT NULL DEFAULT now(),
|
||||
ADD COLUMN inbox_url varchar(255) NOT NULL DEFAULT generate_unique_changeme (),
|
||||
ADD COLUMN private_key text,
|
||||
ADD COLUMN public_key text NOT NULL DEFAULT generate_unique_changeme ();
|
||||
|
|
|
@ -14,7 +14,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN NEW.score = - 1 THEN
|
||||
downvotes = CASE WHEN NEW.score = -1 THEN
|
||||
downvotes + 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -32,7 +32,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN OLD.score = - 1 THEN
|
||||
downvotes = CASE WHEN OLD.score = -1 THEN
|
||||
downvotes - 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -63,7 +63,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN NEW.score = - 1 THEN
|
||||
downvotes = CASE WHEN NEW.score = -1 THEN
|
||||
downvotes + 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -81,7 +81,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN OLD.score = - 1 THEN
|
||||
downvotes = CASE WHEN OLD.score = -1 THEN
|
||||
downvotes - 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
|
|
@ -64,7 +64,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN NEW.score = - 1 THEN
|
||||
downvotes = CASE WHEN NEW.score = -1 THEN
|
||||
downvotes + 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -73,7 +73,7 @@ BEGIN
|
|||
1
|
||||
ELSE
|
||||
0
|
||||
END::numeric, pa.downvotes + CASE WHEN NEW.score = - 1 THEN
|
||||
END::numeric, pa.downvotes + CASE WHEN NEW.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
|
@ -91,7 +91,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN OLD.score = - 1 THEN
|
||||
downvotes = CASE WHEN OLD.score = -1 THEN
|
||||
downvotes - 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -100,7 +100,7 @@ BEGIN
|
|||
1
|
||||
ELSE
|
||||
0
|
||||
END::numeric, pa.downvotes + CASE WHEN NEW.score = - 1 THEN
|
||||
END::numeric, pa.downvotes + CASE WHEN NEW.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
|
@ -131,7 +131,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN NEW.score = - 1 THEN
|
||||
downvotes = CASE WHEN NEW.score = -1 THEN
|
||||
downvotes + 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -140,7 +140,7 @@ BEGIN
|
|||
1
|
||||
ELSE
|
||||
0
|
||||
END::numeric, ca.downvotes + CASE WHEN NEW.score = - 1 THEN
|
||||
END::numeric, ca.downvotes + CASE WHEN NEW.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
|
@ -158,7 +158,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN OLD.score = - 1 THEN
|
||||
downvotes = CASE WHEN OLD.score = -1 THEN
|
||||
downvotes - 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -167,7 +167,7 @@ BEGIN
|
|||
1
|
||||
ELSE
|
||||
0
|
||||
END::numeric, ca.downvotes + CASE WHEN NEW.score = - 1 THEN
|
||||
END::numeric, ca.downvotes + CASE WHEN NEW.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
|
|
|
@ -33,7 +33,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN NEW.score = - 1 THEN
|
||||
downvotes = CASE WHEN NEW.score = -1 THEN
|
||||
downvotes + 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -42,7 +42,7 @@ BEGIN
|
|||
1
|
||||
ELSE
|
||||
0
|
||||
END::numeric, ca.downvotes + CASE WHEN NEW.score = - 1 THEN
|
||||
END::numeric, ca.downvotes + CASE WHEN NEW.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
|
@ -60,7 +60,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN OLD.score = - 1 THEN
|
||||
downvotes = CASE WHEN OLD.score = -1 THEN
|
||||
downvotes - 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -69,7 +69,7 @@ BEGIN
|
|||
1
|
||||
ELSE
|
||||
0
|
||||
END::numeric, ca.downvotes + CASE WHEN NEW.score = - 1 THEN
|
||||
END::numeric, ca.downvotes + CASE WHEN NEW.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
|
@ -551,7 +551,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN NEW.score = - 1 THEN
|
||||
downvotes = CASE WHEN NEW.score = -1 THEN
|
||||
downvotes + 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -560,7 +560,7 @@ BEGIN
|
|||
1
|
||||
ELSE
|
||||
0
|
||||
END::numeric, pa.downvotes + CASE WHEN NEW.score = - 1 THEN
|
||||
END::numeric, pa.downvotes + CASE WHEN NEW.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
|
@ -578,7 +578,7 @@ BEGIN
|
|||
ELSE
|
||||
upvotes
|
||||
END,
|
||||
downvotes = CASE WHEN OLD.score = - 1 THEN
|
||||
downvotes = CASE WHEN OLD.score = -1 THEN
|
||||
downvotes - 1
|
||||
ELSE
|
||||
downvotes
|
||||
|
@ -587,7 +587,7 @@ BEGIN
|
|||
1
|
||||
ELSE
|
||||
0
|
||||
END::numeric, pa.downvotes + CASE WHEN NEW.score = - 1 THEN
|
||||
END::numeric, pa.downvotes + CASE WHEN NEW.score = -1 THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
|
|
|
@ -33,8 +33,10 @@ CREATE TABLE person_saved_combined (
|
|||
id serial PRIMARY KEY,
|
||||
saved timestamptz NOT NULL,
|
||||
person_id int NOT NULL REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
post_id int UNIQUE REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
comment_id int UNIQUE REFERENCES COMMENT ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
comment_id int REFERENCES COMMENT ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
UNIQUE (person_id, post_id),
|
||||
UNIQUE (person_id, comment_id),
|
||||
-- Make sure only one of the columns is not null
|
||||
CHECK (num_nonnulls (post_id, comment_id) = 1)
|
||||
);
|
||||
|
|
|
@ -62,8 +62,8 @@ ALTER TABLE local_site
|
|||
|
||||
-- Add the new column to both tables (null means no limit)
|
||||
ALTER TABLE local_user
|
||||
ADD COLUMN default_post_time_range_seconds INTEGER;
|
||||
ADD COLUMN default_post_time_range_seconds integer;
|
||||
|
||||
ALTER TABLE local_site
|
||||
ADD COLUMN default_post_time_range_seconds INTEGER;
|
||||
ADD COLUMN default_post_time_range_seconds integer;
|
||||
|
||||
|
|
2
migrations/2025-04-10-234244_add_liked_combined/down.sql
Normal file
2
migrations/2025-04-10-234244_add_liked_combined/down.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
DROP TABLE person_liked_combined;
|
||||
|
49
migrations/2025-04-10-234244_add_liked_combined/up.sql
Normal file
49
migrations/2025-04-10-234244_add_liked_combined/up.sql
Normal file
|
@ -0,0 +1,49 @@
|
|||
-- Creates combined tables for
|
||||
-- person_liked: (comment, post)
|
||||
--
|
||||
-- This one is special, because you use the liked date, not the ordinary published
|
||||
CREATE TABLE person_liked_combined (
|
||||
id serial PRIMARY KEY,
|
||||
liked timestamptz NOT NULL,
|
||||
like_score smallint NOT NULL,
|
||||
person_id int NOT NULL REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
comment_id int REFERENCES COMMENT ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
UNIQUE (person_id, post_id),
|
||||
UNIQUE (person_id, comment_id),
|
||||
-- Make sure only one of the columns is not null
|
||||
CHECK (num_nonnulls (post_id, comment_id) = 1)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_person_liked_combined_published ON person_liked_combined (liked DESC, id DESC);
|
||||
|
||||
CREATE INDEX idx_person_liked_combined ON person_liked_combined (person_id);
|
||||
|
||||
-- Updating the history
|
||||
INSERT INTO person_liked_combined (liked, like_score, person_id, post_id, comment_id)
|
||||
SELECT
|
||||
pa.liked,
|
||||
pa.like_score,
|
||||
pa.person_id,
|
||||
pa.post_id,
|
||||
NULL::int
|
||||
FROM
|
||||
post_actions pa
|
||||
INNER JOIN person p ON pa.person_id = p.id
|
||||
WHERE
|
||||
pa.liked IS NOT NULL
|
||||
AND p.local = TRUE
|
||||
UNION ALL
|
||||
SELECT
|
||||
ca.liked,
|
||||
ca.like_score,
|
||||
ca.person_id,
|
||||
NULL::int,
|
||||
ca.comment_id
|
||||
FROM
|
||||
comment_actions ca
|
||||
INNER JOIN person p ON ca.person_id = p.id
|
||||
WHERE
|
||||
liked IS NOT NULL
|
||||
AND p.local = TRUE;
|
||||
|
10
scripts/alpine_install_pg_formatter.sh
Executable file
10
scripts/alpine_install_pg_formatter.sh
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
version=5.6
|
||||
wget https://github.com/darold/pgFormatter/archive/refs/tags/v${version}.tar.gz
|
||||
tar xzf v${version}.tar.gz
|
||||
cd pgFormatter-${version}/
|
||||
perl Makefile.PL
|
||||
make && make install
|
||||
cd ../ && rm -rf v${version}.tar.gz && rm -rf pgFormatter-${version} #clean up
|
|
@ -30,6 +30,7 @@ use lemmy_api::{
|
|||
generate_totp_secret::generate_totp_secret,
|
||||
get_captcha::get_captcha,
|
||||
list_hidden::list_person_hidden,
|
||||
list_liked::list_person_liked,
|
||||
list_logins::list_logins,
|
||||
list_media::list_media,
|
||||
list_read::list_person_read,
|
||||
|
@ -371,6 +372,7 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
.route("/saved", get().to(list_person_saved))
|
||||
.route("/read", get().to(list_person_read))
|
||||
.route("/hidden", get().to(list_person_hidden))
|
||||
.route("/liked", get().to(list_person_liked))
|
||||
.route("/settings/save", put().to(save_user_settings))
|
||||
// Account settings import / export have a strict rate limit
|
||||
.service(
|
||||
|
|
Loading…
Reference in a new issue