mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-22 04:11:17 +00:00
add setting store_vote_timestamps
This commit is contained in:
parent
08055b9dfb
commit
fd8a6b46f7
24 changed files with 285 additions and 256 deletions
|
@ -35,6 +35,9 @@
|
|||
database: "string"
|
||||
# Maximum number of active sql connections
|
||||
pool_size: 30
|
||||
# Set true to store the time when votes were cast. Requires more storage space but can be
|
||||
# used to detect vote manipulation.
|
||||
store_vote_timestamps: false
|
||||
}
|
||||
# Pictrs image server configuration.
|
||||
pictrs: {
|
||||
|
|
|
@ -9,11 +9,7 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::LocalUserId,
|
||||
source::{
|
||||
comment::{CommentLike, CommentLikeForm},
|
||||
comment_reply::CommentReply,
|
||||
local_site::LocalSite,
|
||||
},
|
||||
source::{comment::CommentLike, comment_reply::CommentReply, local_site::LocalSite},
|
||||
traits::Likeable,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommentView, LocalUserView};
|
||||
|
@ -65,23 +61,23 @@ pub async fn like_comment(
|
|||
}
|
||||
}
|
||||
|
||||
let like_form = CommentLikeForm {
|
||||
comment_id: data.comment_id,
|
||||
person_id: local_user_view.person.id,
|
||||
score: data.score,
|
||||
};
|
||||
|
||||
// Remove any likes first
|
||||
let person_id = local_user_view.person.id;
|
||||
|
||||
CommentLike::remove(&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 = data.score != 0 && (data.score == 1 || data.score == -1);
|
||||
if do_add {
|
||||
CommentLike::like(&mut context.pool(), &like_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikeComment)?;
|
||||
CommentLike::like(
|
||||
&mut context.pool(),
|
||||
person_id,
|
||||
data.comment_id,
|
||||
data.score,
|
||||
context.settings(),
|
||||
)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikeComment)?;
|
||||
}
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
|
|
|
@ -17,7 +17,7 @@ use lemmy_db_schema::{
|
|||
source::{
|
||||
community::Community,
|
||||
local_site::LocalSite,
|
||||
post::{Post, PostLike, PostLikeForm},
|
||||
post::{Post, PostLike},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
};
|
||||
|
@ -54,23 +54,23 @@ pub async fn like_post(
|
|||
)
|
||||
.await?;
|
||||
|
||||
let like_form = PostLikeForm {
|
||||
post_id: data.post_id,
|
||||
person_id: local_user_view.person.id,
|
||||
score: data.score,
|
||||
};
|
||||
|
||||
// Remove any likes first
|
||||
let person_id = local_user_view.person.id;
|
||||
|
||||
PostLike::remove(&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 = data.score != 0 && (data.score == 1 || data.score == -1);
|
||||
if do_add {
|
||||
PostLike::like(&mut context.pool(), &like_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikePost)?;
|
||||
PostLike::like(
|
||||
&mut context.pool(),
|
||||
person_id,
|
||||
post_id,
|
||||
data.score,
|
||||
context.settings(),
|
||||
)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikePost)?;
|
||||
}
|
||||
|
||||
mark_post_as_read(person_id, post_id, &mut context.pool()).await?;
|
||||
|
|
|
@ -19,7 +19,7 @@ use lemmy_db_schema::{
|
|||
impls::actor_language::default_post_language,
|
||||
source::{
|
||||
actor_language::CommunityLanguage,
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm},
|
||||
comment::{Comment, CommentInsertForm, CommentLike},
|
||||
comment_reply::{CommentReply, CommentReplyUpdateForm},
|
||||
local_site::LocalSite,
|
||||
person_mention::{PersonMention, PersonMentionUpdateForm},
|
||||
|
@ -130,15 +130,15 @@ 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,
|
||||
};
|
||||
|
||||
CommentLike::like(&mut context.pool(), &like_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikeComment)?;
|
||||
CommentLike::like(
|
||||
&mut context.pool(),
|
||||
local_user_view.person.id,
|
||||
inserted_comment.id,
|
||||
1,
|
||||
context.settings(),
|
||||
)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikeComment)?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::CreateComment(inserted_comment.clone()),
|
||||
|
|
|
@ -22,7 +22,7 @@ use lemmy_db_schema::{
|
|||
actor_language::CommunityLanguage,
|
||||
community::Community,
|
||||
local_site::LocalSite,
|
||||
post::{Post, PostInsertForm, PostLike, PostLikeForm},
|
||||
post::{Post, PostInsertForm, PostLike},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
utils::diesel_url_create,
|
||||
|
@ -159,15 +159,15 @@ pub async fn create_post(
|
|||
// They like their own post by default
|
||||
let person_id = local_user_view.person.id;
|
||||
let post_id = inserted_post.id;
|
||||
let like_form = PostLikeForm {
|
||||
post_id,
|
||||
PostLike::like(
|
||||
&mut context.pool(),
|
||||
person_id,
|
||||
score: 1,
|
||||
};
|
||||
|
||||
PostLike::like(&mut context.pool(), &like_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikePost)?;
|
||||
post_id,
|
||||
1,
|
||||
context.settings(),
|
||||
)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikePost)?;
|
||||
|
||||
mark_post_as_read(person_id, post_id, &mut context.pool()).await?;
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ use lemmy_db_schema::{
|
|||
newtypes::PersonId,
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
comment::{Comment, CommentLike, CommentLikeForm},
|
||||
comment::{Comment, CommentLike},
|
||||
community::Community,
|
||||
person::Person,
|
||||
post::Post,
|
||||
|
@ -151,12 +151,14 @@ 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?;
|
||||
CommentLike::like(
|
||||
&mut context.pool(),
|
||||
comment.creator_id,
|
||||
comment.id,
|
||||
1,
|
||||
context.settings(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Calculate initial hot_rank
|
||||
CommentAggregates::update_hot_rank(&mut context.pool(), comment.id).await?;
|
||||
|
|
|
@ -28,7 +28,7 @@ use lemmy_db_schema::{
|
|||
activity::ActivitySendTargets,
|
||||
community::Community,
|
||||
person::Person,
|
||||
post::{Post, PostLike, PostLikeForm},
|
||||
post::{Post, PostLike},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
};
|
||||
|
@ -118,12 +118,14 @@ impl ActivityHandler for CreateOrUpdatePage {
|
|||
let post = ApubPost::from_json(self.object, context).await?;
|
||||
|
||||
// author likes their own post by default
|
||||
let like_form = PostLikeForm {
|
||||
post_id: post.id,
|
||||
person_id: post.creator_id,
|
||||
score: 1,
|
||||
};
|
||||
PostLike::like(&mut context.pool(), &like_form).await?;
|
||||
PostLike::like(
|
||||
&mut context.pool(),
|
||||
post.creator_id,
|
||||
post.id,
|
||||
1,
|
||||
context.settings(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Calculate initial hot_rank for post
|
||||
PostAggregates::update_ranks(&mut context.pool(), post.id).await?;
|
||||
|
|
|
@ -14,10 +14,10 @@ use lemmy_db_schema::{
|
|||
newtypes::DbUrl,
|
||||
source::{
|
||||
activity::ActivitySendTargets,
|
||||
comment::{CommentLike, CommentLikeForm},
|
||||
comment::CommentLike,
|
||||
community::Community,
|
||||
person::Person,
|
||||
post::{PostLike, PostLikeForm},
|
||||
post::PostLike,
|
||||
},
|
||||
traits::Likeable,
|
||||
};
|
||||
|
@ -59,15 +59,15 @@ async fn vote_comment(
|
|||
comment: &ApubComment,
|
||||
context: &Data<LemmyContext>,
|
||||
) -> LemmyResult<()> {
|
||||
let comment_id = comment.id;
|
||||
let like_form = CommentLikeForm {
|
||||
comment_id,
|
||||
person_id: actor.id,
|
||||
score: 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?;
|
||||
CommentLike::remove(&mut context.pool(), actor.id, comment.id).await?;
|
||||
CommentLike::like(
|
||||
&mut context.pool(),
|
||||
actor.id,
|
||||
comment.id,
|
||||
vote_type.into(),
|
||||
context.settings(),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -78,15 +78,15 @@ async fn vote_post(
|
|||
post: &ApubPost,
|
||||
context: &Data<LemmyContext>,
|
||||
) -> LemmyResult<()> {
|
||||
let post_id = post.id;
|
||||
let like_form = PostLikeForm {
|
||||
post_id: post.id,
|
||||
person_id: actor.id,
|
||||
score: 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?;
|
||||
PostLike::remove(&mut context.pool(), actor.id, post.id).await?;
|
||||
PostLike::like(
|
||||
&mut context.pool(),
|
||||
actor.id,
|
||||
post.id,
|
||||
vote_type.into(),
|
||||
context.settings(),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ mod tests {
|
|||
use crate::{
|
||||
aggregates::comment_aggregates::CommentAggregates,
|
||||
source::{
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm},
|
||||
comment::{Comment, CommentInsertForm, CommentLike},
|
||||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
person::{Person, PersonInsertForm},
|
||||
|
@ -45,6 +45,7 @@ mod tests {
|
|||
utils::build_db_pool_for_tests,
|
||||
};
|
||||
use diesel::result::Error;
|
||||
use lemmy_utils::settings::structs::Settings;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -94,13 +95,8 @@ 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,
|
||||
};
|
||||
|
||||
CommentLike::like(pool, &comment_like).await?;
|
||||
let settings = Settings::default();
|
||||
CommentLike::like(pool, inserted_person.id, inserted_comment.id, 1, &settings).await?;
|
||||
|
||||
let comment_aggs_before_delete = CommentAggregates::read(pool, inserted_comment.id).await?;
|
||||
|
||||
|
@ -109,13 +105,14 @@ 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,
|
||||
};
|
||||
|
||||
CommentLike::like(pool, &comment_dislike).await?;
|
||||
CommentLike::like(
|
||||
pool,
|
||||
another_inserted_person.id,
|
||||
inserted_comment.id,
|
||||
-1,
|
||||
&settings,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let comment_aggs_after_dislike = CommentAggregates::read(pool, inserted_comment.id).await?;
|
||||
|
||||
|
|
|
@ -20,16 +20,17 @@ mod tests {
|
|||
use crate::{
|
||||
aggregates::person_aggregates::PersonAggregates,
|
||||
source::{
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm, CommentUpdateForm},
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentUpdateForm},
|
||||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
person::{Person, PersonInsertForm},
|
||||
post::{Post, PostInsertForm, PostLike, PostLikeForm},
|
||||
post::{Post, PostInsertForm, PostLike},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
utils::build_db_pool_for_tests,
|
||||
};
|
||||
use diesel::result::Error;
|
||||
use lemmy_utils::settings::structs::Settings;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -65,12 +66,8 @@ mod tests {
|
|||
);
|
||||
let inserted_post = Post::create(pool, &new_post).await?;
|
||||
|
||||
let post_like = PostLikeForm {
|
||||
post_id: inserted_post.id,
|
||||
person_id: inserted_person.id,
|
||||
score: 1,
|
||||
};
|
||||
let _inserted_post_like = PostLike::like(pool, &post_like).await?;
|
||||
let settings = Settings::default();
|
||||
PostLike::like(pool, inserted_person.id, inserted_post.id, 1, &settings).await?;
|
||||
|
||||
let comment_form = CommentInsertForm::new(
|
||||
inserted_person.id,
|
||||
|
@ -79,13 +76,7 @@ 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 _inserted_comment_like = CommentLike::like(pool, &comment_like).await?;
|
||||
CommentLike::like(pool, inserted_person.id, inserted_comment.id, 1, &settings).await?;
|
||||
|
||||
let child_comment_form = CommentInsertForm::new(
|
||||
inserted_person.id,
|
||||
|
@ -95,13 +86,14 @@ 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 _inserted_child_comment_like = CommentLike::like(pool, &child_comment_like).await?;
|
||||
CommentLike::like(
|
||||
pool,
|
||||
another_inserted_person.id,
|
||||
inserted_child_comment.id,
|
||||
1,
|
||||
&settings,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let person_aggregates_before_delete = PersonAggregates::read(pool, inserted_person.id).await?;
|
||||
|
||||
|
@ -151,8 +143,14 @@ mod tests {
|
|||
let new_parent_comment = Comment::create(pool, &comment_form, None).await?;
|
||||
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?;
|
||||
CommentLike::like(
|
||||
pool,
|
||||
inserted_person.id,
|
||||
new_parent_comment.id,
|
||||
1,
|
||||
&settings,
|
||||
)
|
||||
.await?;
|
||||
let after_comment_add = PersonAggregates::read(pool, inserted_person.id).await?;
|
||||
assert_eq!(2, after_comment_add.comment_count);
|
||||
// TODO: fix person aggregate comment score calculation
|
||||
|
|
|
@ -58,12 +58,13 @@ mod tests {
|
|||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
person::{Person, PersonInsertForm},
|
||||
post::{Post, PostInsertForm, PostLike, PostLikeForm},
|
||||
post::{Post, PostInsertForm, PostLike},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
utils::build_db_pool_for_tests,
|
||||
};
|
||||
use diesel::result::Error;
|
||||
use lemmy_utils::settings::structs::Settings;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -113,13 +114,8 @@ mod tests {
|
|||
let inserted_child_comment =
|
||||
Comment::create(pool, &child_comment_form, Some(&inserted_comment.path)).await?;
|
||||
|
||||
let post_like = PostLikeForm {
|
||||
post_id: inserted_post.id,
|
||||
person_id: inserted_person.id,
|
||||
score: 1,
|
||||
};
|
||||
|
||||
PostLike::like(pool, &post_like).await?;
|
||||
let settings = Settings::default();
|
||||
PostLike::like(pool, inserted_person.id, inserted_post.id, 1, &settings).await?;
|
||||
|
||||
let post_aggs_before_delete = PostAggregates::read(pool, inserted_post.id).await?;
|
||||
|
||||
|
@ -129,13 +125,14 @@ mod tests {
|
|||
assert_eq!(0, post_aggs_before_delete.downvotes);
|
||||
|
||||
// Add a post dislike from the other person
|
||||
let post_dislike = PostLikeForm {
|
||||
post_id: inserted_post.id,
|
||||
person_id: another_inserted_person.id,
|
||||
score: -1,
|
||||
};
|
||||
|
||||
PostLike::like(pool, &post_dislike).await?;
|
||||
PostLike::like(
|
||||
pool,
|
||||
another_inserted_person.id,
|
||||
inserted_post.id,
|
||||
-1,
|
||||
&settings,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let post_aggs_after_dislike = PostAggregates::read(pool, inserted_post.id).await?;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ use chrono::{DateTime, Utc};
|
|||
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use diesel_ltree::Ltree;
|
||||
use lemmy_utils::settings::structs::Settings;
|
||||
use url::Url;
|
||||
|
||||
impl Comment {
|
||||
|
@ -138,16 +139,32 @@ impl Crud for Comment {
|
|||
|
||||
#[async_trait]
|
||||
impl Likeable for CommentLike {
|
||||
type Form = CommentLikeForm;
|
||||
type IdType = CommentId;
|
||||
async fn like(pool: &mut DbPool<'_>, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
|
||||
use crate::schema::comment_like::dsl::{comment_id, comment_like, person_id};
|
||||
async fn like(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
comment_id: Self::IdType,
|
||||
score: i16,
|
||||
settings: &Settings,
|
||||
) -> Result<Self, Error> {
|
||||
use crate::schema::comment_like;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(comment_like)
|
||||
.values(comment_like_form)
|
||||
.on_conflict((comment_id, person_id))
|
||||
let published = if settings.database.store_vote_timestamps {
|
||||
Some(Utc::now())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let form = CommentLikeForm {
|
||||
person_id,
|
||||
comment_id,
|
||||
score,
|
||||
published,
|
||||
};
|
||||
insert_into(comment_like::table)
|
||||
.values(&form)
|
||||
.on_conflict((comment_like::comment_id, comment_like::person_id))
|
||||
.do_update()
|
||||
.set(comment_like_form)
|
||||
.set(&form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
|
@ -205,7 +222,6 @@ mod tests {
|
|||
Comment,
|
||||
CommentInsertForm,
|
||||
CommentLike,
|
||||
CommentLikeForm,
|
||||
CommentSaved,
|
||||
CommentSavedForm,
|
||||
CommentUpdateForm,
|
||||
|
@ -219,7 +235,7 @@ mod tests {
|
|||
utils::build_db_pool_for_tests,
|
||||
};
|
||||
use diesel_ltree::Ltree;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use lemmy_utils::{error::LemmyResult, settings::structs::Settings};
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
use url::Url;
|
||||
|
@ -287,18 +303,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 inserted_comment_like = CommentLike::like(pool, &comment_like_form).await?;
|
||||
let settings = Settings::default();
|
||||
let inserted_comment_like =
|
||||
CommentLike::like(pool, inserted_person.id, inserted_comment.id, 1, &settings).await?;
|
||||
|
||||
let expected_comment_like = CommentLike {
|
||||
comment_id: inserted_comment.id,
|
||||
person_id: inserted_person.id,
|
||||
score: 1,
|
||||
published: None,
|
||||
};
|
||||
|
||||
// Comment Saved
|
||||
|
|
|
@ -39,6 +39,7 @@ use diesel::{
|
|||
TextExpressionMethods,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use lemmy_utils::settings::structs::Settings;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[async_trait]
|
||||
|
@ -274,15 +275,31 @@ impl Post {
|
|||
|
||||
#[async_trait]
|
||||
impl Likeable for PostLike {
|
||||
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<'_>,
|
||||
person_id: PersonId,
|
||||
post_id: Self::IdType,
|
||||
score: i16,
|
||||
settings: &Settings,
|
||||
) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let published = if settings.database.store_vote_timestamps {
|
||||
Some(Utc::now())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let form = PostLikeForm {
|
||||
person_id,
|
||||
post_id,
|
||||
score,
|
||||
published,
|
||||
};
|
||||
insert_into(post_like::table)
|
||||
.values(post_like_form)
|
||||
.values(&form)
|
||||
.on_conflict((post_like::post_id, post_like::person_id))
|
||||
.do_update()
|
||||
.set(post_like_form)
|
||||
.set(&form)
|
||||
.get_result::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
|
@ -399,22 +416,13 @@ mod tests {
|
|||
community::{Community, CommunityInsertForm},
|
||||
instance::Instance,
|
||||
person::{Person, PersonInsertForm},
|
||||
post::{
|
||||
Post,
|
||||
PostInsertForm,
|
||||
PostLike,
|
||||
PostLikeForm,
|
||||
PostRead,
|
||||
PostSaved,
|
||||
PostSavedForm,
|
||||
PostUpdateForm,
|
||||
},
|
||||
post::{Post, PostInsertForm, PostLike, PostRead, PostSaved, PostSavedForm, PostUpdateForm},
|
||||
},
|
||||
traits::{Crud, Likeable, Saveable},
|
||||
utils::build_db_pool_for_tests,
|
||||
};
|
||||
use chrono::DateTime;
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use lemmy_utils::{error::LemmyResult, settings::structs::Settings};
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
use std::collections::HashSet;
|
||||
|
@ -489,18 +497,15 @@ mod tests {
|
|||
};
|
||||
|
||||
// Post Like
|
||||
let post_like_form = PostLikeForm {
|
||||
post_id: inserted_post.id,
|
||||
person_id: inserted_person.id,
|
||||
score: 1,
|
||||
};
|
||||
|
||||
let inserted_post_like = PostLike::like(pool, &post_like_form).await?;
|
||||
let settings = Settings::default();
|
||||
let inserted_post_like =
|
||||
PostLike::like(pool, inserted_person.id, inserted_post.id, 1, &settings).await?;
|
||||
|
||||
let expected_post_like = PostLike {
|
||||
post_id: inserted_post.id,
|
||||
person_id: inserted_person.id,
|
||||
score: 1,
|
||||
published: None,
|
||||
};
|
||||
|
||||
// Post Save
|
||||
|
|
|
@ -124,6 +124,7 @@ diesel::table! {
|
|||
person_id -> Int4,
|
||||
comment_id -> Int4,
|
||||
score -> Int2,
|
||||
published -> Nullable<Timestamptz>,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -814,6 +815,7 @@ diesel::table! {
|
|||
post_id -> Int4,
|
||||
person_id -> Int4,
|
||||
score -> Int2,
|
||||
published -> Nullable<Timestamptz>,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,15 +103,17 @@ pub struct CommentLike {
|
|||
pub person_id: PersonId,
|
||||
pub comment_id: CommentId,
|
||||
pub score: i16,
|
||||
pub published: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = comment_like))]
|
||||
pub struct CommentLikeForm {
|
||||
pub(crate) struct CommentLikeForm {
|
||||
pub person_id: PersonId,
|
||||
pub comment_id: CommentId,
|
||||
pub score: i16,
|
||||
pub published: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
|
|
|
@ -150,15 +150,17 @@ pub struct PostLike {
|
|||
pub post_id: PostId,
|
||||
pub person_id: PersonId,
|
||||
pub score: i16,
|
||||
pub published: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", diesel(table_name = post_like))]
|
||||
pub struct PostLikeForm {
|
||||
pub(crate) struct PostLikeForm {
|
||||
pub post_id: PostId,
|
||||
pub person_id: PersonId,
|
||||
pub score: i16,
|
||||
pub published: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
|
|
|
@ -15,6 +15,7 @@ use diesel_async::{
|
|||
AsyncPgConnection,
|
||||
RunQueryDsl,
|
||||
};
|
||||
use lemmy_utils::settings::structs::Settings;
|
||||
|
||||
/// Returned by `diesel::delete`
|
||||
pub type Delete<T> = DeleteStatement<<T as HasTable>::Table, <T as IntoUpdateTarget>::WhereClause>;
|
||||
|
@ -94,9 +95,14 @@ pub trait Joinable {
|
|||
|
||||
#[async_trait]
|
||||
pub trait Likeable {
|
||||
type Form;
|
||||
type IdType;
|
||||
async fn like(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<Self, Error>
|
||||
async fn like(
|
||||
pool: &mut DbPool<'_>,
|
||||
person_id: PersonId,
|
||||
item_id: Self::IdType,
|
||||
score: i16,
|
||||
settings: &Settings,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
Self: Sized;
|
||||
async fn remove(
|
||||
|
|
|
@ -438,7 +438,6 @@ mod tests {
|
|||
Comment,
|
||||
CommentInsertForm,
|
||||
CommentLike,
|
||||
CommentLikeForm,
|
||||
CommentSaved,
|
||||
CommentSavedForm,
|
||||
CommentUpdateForm,
|
||||
|
@ -466,7 +465,7 @@ mod tests {
|
|||
CommunityVisibility,
|
||||
SubscribedType,
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use lemmy_utils::{error::LemmyResult, settings::structs::Settings};
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -599,13 +598,15 @@ mod tests {
|
|||
};
|
||||
assert_eq!(expected_block, inserted_block);
|
||||
|
||||
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?;
|
||||
let settings = Settings::default();
|
||||
CommentLike::like(
|
||||
pool,
|
||||
inserted_timmy_person.id,
|
||||
inserted_comment_0.id,
|
||||
1,
|
||||
&settings,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let timmy_local_user_view = LocalUserView {
|
||||
local_user: inserted_timmy_local_user.clone(),
|
||||
|
@ -698,12 +699,15 @@ mod tests {
|
|||
PersonBlock::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 settings = Settings::default();
|
||||
CommentLike::like(
|
||||
pool,
|
||||
data.timmy_local_user_view.person.id,
|
||||
data.inserted_comment_1.id,
|
||||
1,
|
||||
&settings,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let read_liked_comment_views = CommentQuery {
|
||||
local_user: Some(&data.timmy_local_user_view.local_user),
|
||||
|
|
|
@ -759,7 +759,6 @@ mod tests {
|
|||
PostHide,
|
||||
PostInsertForm,
|
||||
PostLike,
|
||||
PostLikeForm,
|
||||
PostRead,
|
||||
PostSaved,
|
||||
PostSavedForm,
|
||||
|
@ -773,7 +772,7 @@ mod tests {
|
|||
PostSortType,
|
||||
SubscribedType,
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use lemmy_utils::{error::LemmyResult, settings::structs::Settings};
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
use std::{collections::HashSet, time::Duration};
|
||||
|
@ -1114,18 +1113,21 @@ mod tests {
|
|||
let pool = &mut pool.into();
|
||||
let mut data = init_data(pool).await?;
|
||||
|
||||
let post_like_form = PostLikeForm {
|
||||
post_id: data.inserted_post.id,
|
||||
person_id: data.local_user_view.person.id,
|
||||
score: 1,
|
||||
};
|
||||
|
||||
let inserted_post_like = PostLike::like(pool, &post_like_form).await?;
|
||||
let settings = Settings::default();
|
||||
let inserted_post_like = PostLike::like(
|
||||
pool,
|
||||
data.local_user_view.person.id,
|
||||
data.inserted_post.id,
|
||||
1,
|
||||
&settings,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let expected_post_like = PostLike {
|
||||
post_id: data.inserted_post.id,
|
||||
person_id: data.local_user_view.person.id,
|
||||
score: 1,
|
||||
published: None,
|
||||
};
|
||||
assert_eq!(expected_post_like, inserted_post_like);
|
||||
|
||||
|
@ -1173,19 +1175,24 @@ mod tests {
|
|||
|
||||
// Like both the bot post, and your own
|
||||
// The liked_only should not show your own post
|
||||
let post_like_form = PostLikeForm {
|
||||
post_id: data.inserted_post.id,
|
||||
person_id: data.local_user_view.person.id,
|
||||
score: 1,
|
||||
};
|
||||
PostLike::like(pool, &post_like_form).await?;
|
||||
let settings = Settings::default();
|
||||
PostLike::like(
|
||||
pool,
|
||||
data.local_user_view.person.id,
|
||||
data.inserted_post.id,
|
||||
1,
|
||||
&settings,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let bot_post_like_form = PostLikeForm {
|
||||
post_id: data.inserted_bot_post.id,
|
||||
person_id: data.local_user_view.person.id,
|
||||
score: 1,
|
||||
};
|
||||
PostLike::like(pool, &bot_post_like_form).await?;
|
||||
PostLike::like(
|
||||
pool,
|
||||
data.local_user_view.person.id,
|
||||
data.inserted_bot_post.id,
|
||||
1,
|
||||
&settings,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Read the liked only
|
||||
let read_liked_post_listing = PostQuery {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
#[cfg(feature = "full")]
|
||||
use diesel::Queryable;
|
||||
use lemmy_db_schema::{
|
||||
|
@ -216,6 +217,7 @@ pub struct VoteView {
|
|||
pub creator: Person,
|
||||
pub creator_banned_from_community: bool,
|
||||
pub score: i16,
|
||||
pub published: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[skip_serializing_none]
|
||||
|
|
|
@ -40,6 +40,7 @@ impl VoteView {
|
|||
person::all_columns,
|
||||
community_person_ban::community_id.nullable().is_not_null(),
|
||||
post_like::score,
|
||||
post_like::published,
|
||||
))
|
||||
.order_by(post_like::score)
|
||||
.limit(limit)
|
||||
|
@ -74,6 +75,7 @@ impl VoteView {
|
|||
person::all_columns,
|
||||
community_person_ban::community_id.nullable().is_not_null(),
|
||||
comment_like::score,
|
||||
comment_like::published,
|
||||
))
|
||||
.order_by(comment_like::score)
|
||||
.limit(limit)
|
||||
|
@ -89,16 +91,16 @@ mod tests {
|
|||
use crate::structs::VoteView;
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm},
|
||||
comment::{Comment, CommentInsertForm, CommentLike},
|
||||
community::{Community, CommunityInsertForm, CommunityPersonBan, CommunityPersonBanForm},
|
||||
instance::Instance,
|
||||
person::{Person, PersonInsertForm},
|
||||
post::{Post, PostInsertForm, PostLike, PostLikeForm},
|
||||
post::{Post, PostInsertForm, PostLike},
|
||||
},
|
||||
traits::{Bannable, Crud, Likeable},
|
||||
utils::build_db_pool_for_tests,
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use lemmy_utils::{error::LemmyResult, settings::structs::Settings};
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -141,31 +143,24 @@ mod tests {
|
|||
let inserted_comment = Comment::create(pool, &comment_form, None).await?;
|
||||
|
||||
// Timmy upvotes his own post
|
||||
let timmy_post_vote_form = PostLikeForm {
|
||||
post_id: inserted_post.id,
|
||||
person_id: inserted_timmy.id,
|
||||
score: 1,
|
||||
};
|
||||
PostLike::like(pool, &timmy_post_vote_form).await?;
|
||||
let settings = Settings::default();
|
||||
PostLike::like(pool, inserted_timmy.id, inserted_post.id, 1, &settings).await?;
|
||||
|
||||
// Sara downvotes timmy's post
|
||||
let sara_post_vote_form = PostLikeForm {
|
||||
post_id: inserted_post.id,
|
||||
person_id: inserted_sara.id,
|
||||
score: -1,
|
||||
};
|
||||
PostLike::like(pool, &sara_post_vote_form).await?;
|
||||
PostLike::like(pool, inserted_sara.id, inserted_post.id, -1, &settings).await?;
|
||||
|
||||
let expected_post_vote_views = [
|
||||
VoteView {
|
||||
creator: inserted_sara.clone(),
|
||||
creator_banned_from_community: false,
|
||||
score: -1,
|
||||
published: None,
|
||||
},
|
||||
VoteView {
|
||||
creator: inserted_timmy.clone(),
|
||||
creator_banned_from_community: false,
|
||||
score: 1,
|
||||
published: None,
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -173,31 +168,23 @@ mod tests {
|
|||
assert_eq!(read_post_vote_views, expected_post_vote_views);
|
||||
|
||||
// Timothy votes down his own comment
|
||||
let timmy_comment_vote_form = CommentLikeForm {
|
||||
comment_id: inserted_comment.id,
|
||||
person_id: inserted_timmy.id,
|
||||
score: -1,
|
||||
};
|
||||
CommentLike::like(pool, &timmy_comment_vote_form).await?;
|
||||
CommentLike::like(pool, inserted_timmy.id, inserted_comment.id, -1, &settings).await?;
|
||||
|
||||
// Sara upvotes timmy's comment
|
||||
let sara_comment_vote_form = CommentLikeForm {
|
||||
comment_id: inserted_comment.id,
|
||||
person_id: inserted_sara.id,
|
||||
score: 1,
|
||||
};
|
||||
CommentLike::like(pool, &sara_comment_vote_form).await?;
|
||||
CommentLike::like(pool, inserted_sara.id, inserted_comment.id, 1, &settings).await?;
|
||||
|
||||
let expected_comment_vote_views = [
|
||||
VoteView {
|
||||
creator: inserted_timmy.clone(),
|
||||
creator_banned_from_community: false,
|
||||
score: -1,
|
||||
published: None,
|
||||
},
|
||||
VoteView {
|
||||
creator: inserted_sara.clone(),
|
||||
creator_banned_from_community: false,
|
||||
score: 1,
|
||||
published: None,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -128,6 +128,11 @@ pub struct DatabaseConfig {
|
|||
/// Maximum number of active sql connections
|
||||
#[default(30)]
|
||||
pub pool_size: usize,
|
||||
|
||||
/// Set true to store the time when votes were cast. Requires more storage space but can be
|
||||
/// used to detect vote manipulation.
|
||||
#[default(false)]
|
||||
pub store_vote_timestamps: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)]
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
-- make published not null again and add default
|
||||
ALTER TABLE post_like
|
||||
ADD COLUMN published timestamptz NOT NULL DEFAULT now();
|
||||
ALTER COLUMN published SET NOT NULL;
|
||||
|
||||
ALTER TABLE post_like
|
||||
ALTER COLUMN published SET DEFAULT now();
|
||||
|
||||
ALTER TABLE comment_like
|
||||
ADD COLUMN published timestamptz NOT NULL DEFAULT now();
|
||||
ALTER COLUMN published DROP NOT NULL;
|
||||
|
||||
ALTER TABLE comment_like
|
||||
ALTER COLUMN published SET DEFAULT now();
|
||||
|
||||
-- restore comment_like.post_id
|
||||
ALTER TABLE comment_like
|
||||
ADD COLUMN post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE;
|
||||
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
-- set all column values to null to reclaim disk space
|
||||
-- https://dba.stackexchange.com/a/117513
|
||||
-- make published columns nullable and remove default value
|
||||
ALTER TABLE post_like
|
||||
ALTER COLUMN published DROP NOT NULL;
|
||||
|
||||
UPDATE
|
||||
post_like
|
||||
SET
|
||||
published = NULL;
|
||||
ALTER TABLE post_like
|
||||
ALTER COLUMN published DROP DEFAULT;
|
||||
|
||||
ALTER TABLE comment_like
|
||||
ALTER COLUMN published DROP NOT NULL;
|
||||
|
||||
UPDATE
|
||||
comment_like
|
||||
SET
|
||||
published = NULL;
|
||||
ALTER TABLE comment_like
|
||||
ALTER COLUMN published DROP DEFAULT;
|
||||
|
||||
-- get rid of comment_like.post_id, setting null first to reclaim space
|
||||
-- https://dba.stackexchange.com/a/117513
|
||||
ALTER TABLE comment_like
|
||||
ALTER COLUMN post_id DROP NOT NULL;
|
||||
|
||||
|
@ -25,12 +22,6 @@ SET
|
|||
post_id = NULL;
|
||||
|
||||
-- drop the columns
|
||||
ALTER TABLE post_like
|
||||
DROP published;
|
||||
|
||||
ALTER TABLE comment_like
|
||||
DROP published;
|
||||
|
||||
ALTER TABLE comment_like
|
||||
DROP post_id;
|
||||
|
||||
|
|
Loading…
Reference in a new issue