Skip to content

Commit

Permalink
Add support for Featured Posts
Browse files Browse the repository at this point in the history
  • Loading branch information
makotech222 committed Dec 2, 2022
1 parent f02892b commit 8a337f8
Show file tree
Hide file tree
Showing 25 changed files with 258 additions and 129 deletions.
54 changes: 32 additions & 22 deletions crates/api/src/post/sticky.rs → crates/api/src/post/feature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,28 @@ use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{PostResponse, StickyPost},
post::{FeaturePost, PostResponse},
utils::{
check_community_ban,
check_community_deleted_or_removed,
get_local_user_view_from_jwt,
is_admin,
is_mod_or_admin,
},
websocket::{send::send_post_ws_message, UserOperation},
};
use lemmy_db_schema::{
source::{
moderator::{ModStickyPost, ModStickyPostForm},
moderator::{ModFeaturePost, ModFeaturePostForm},
post::{Post, PostUpdateForm},
},
traits::Crud,
PostFeatureType,
};
use lemmy_utils::{error::LemmyError, ConnectionId};

#[async_trait::async_trait(?Send)]
impl Perform for StickyPost {
impl Perform for FeaturePost {
type Response = PostResponse;

#[tracing::instrument(skip(context, websocket_id))]
Expand All @@ -30,7 +32,7 @@ impl Perform for StickyPost {
context: &Data<LemmyContext>,
websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> {
let data: &StickyPost = self;
let data: &FeaturePost = self;
let local_user_view =
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;

Expand All @@ -45,36 +47,44 @@ impl Perform for StickyPost {
.await?;
check_community_deleted_or_removed(orig_post.community_id, context.pool()).await?;

// Verify that only the mods can sticky
is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
if data.feature_type == PostFeatureType::Community {
// Verify that only the mods can feature in community
is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
} else {
is_admin(&local_user_view)?;
}

// Update the post
let post_id = data.post_id;
let stickied = data.stickied;
Post::update(
context.pool(),
post_id,
&PostUpdateForm::builder().stickied(Some(stickied)).build(),
)
.await?;
let new_post: PostUpdateForm;
if data.feature_type == PostFeatureType::Community {
new_post = PostUpdateForm::builder()
.featured_community(Some(featured))
.build();
} else {
new_post = PostUpdateForm::builder()
.featured_local(Some(featured))
.build();
}
Post::update(context.pool(), post_id, &new_post);

// Mod tables
let form = ModStickyPostForm {
let form = ModFeaturePostForm {
mod_person_id: local_user_view.person.id,
post_id: data.post_id,
stickied: Some(stickied),
featured: Some(featured),
};

ModStickyPost::create(context.pool(), &form).await?;
ModFeaturePost::create(context.pool(), &form).await?;

send_post_ws_message(
data.post_id,
UserOperation::StickyPost,
UserOperation::FeaturePost,
websocket_id,
Some(local_user_view.person.id),
context,
Expand Down
2 changes: 1 addition & 1 deletion crates/api/src/post/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod feature;
mod get_link_metadata;
mod like;
mod lock;
mod mark_read;
mod save;
mod sticky;
8 changes: 4 additions & 4 deletions crates/api/src/site/mod_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ use lemmy_db_views_moderator::structs::{
ModAddView,
ModBanFromCommunityView,
ModBanView,
ModFeaturePostView,
ModHideCommunityView,
ModLockPostView,
ModRemoveCommentView,
ModRemoveCommunityView,
ModRemovePostView,
ModStickyPostView,
ModTransferCommunityView,
ModlogListParams,
};
Expand Down Expand Up @@ -91,8 +91,8 @@ impl Perform for GetModlog {
_ => Default::default(),
};

let stickied_posts = match type_ {
All | ModStickyPost => ModStickyPostView::list(context.pool(), params).await?,
let featured_posts = match type_ {
All | ModFeaturePost => ModFeaturePostView::list(context.pool(), params).await?,
_ => Default::default(),
};

Expand Down Expand Up @@ -181,7 +181,7 @@ impl Perform for GetModlog {
Ok(GetModlogResponse {
removed_posts,
locked_posts,
stickied_posts,
featured_posts,
removed_comments,
removed_communities,
banned_from_community,
Expand Down
6 changes: 4 additions & 2 deletions crates/api_common/src/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::sensitive::Sensitive;
use lemmy_db_schema::{
newtypes::{CommentId, CommunityId, DbUrl, LanguageId, PostId, PostReportId},
ListingType,
PostFeatureType,
SortType,
};
use lemmy_db_views::structs::{PostReportView, PostView};
Expand Down Expand Up @@ -106,9 +107,10 @@ pub struct LockPost {
}

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct StickyPost {
pub struct FeaturePost {
pub post_id: PostId,
pub stickied: bool,
pub featured: bool,
pub feature_type: PostFeatureType,
pub auth: Sensitive<String>,
}

Expand Down
4 changes: 2 additions & 2 deletions crates/api_common/src/site.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ use lemmy_db_views_moderator::structs::{
ModAddView,
ModBanFromCommunityView,
ModBanView,
ModFeaturePostView,
ModHideCommunityView,
ModLockPostView,
ModRemoveCommentView,
ModRemoveCommunityView,
ModRemovePostView,
ModStickyPostView,
ModTransferCommunityView,
};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -93,7 +93,7 @@ pub struct GetModlog {
pub struct GetModlogResponse {
pub removed_posts: Vec<ModRemovePostView>,
pub locked_posts: Vec<ModLockPostView>,
pub stickied_posts: Vec<ModStickyPostView>,
pub featured_posts: Vec<ModFeaturePostView>,
pub removed_comments: Vec<ModRemoveCommentView>,
pub removed_communities: Vec<ModRemoveCommunityView>,
pub banned_from_community: Vec<ModBanFromCommunityView>,
Expand Down
2 changes: 1 addition & 1 deletion crates/api_common/src/websocket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub enum UserOperation {
ListCommentReports,
CreatePostLike,
LockPost,
StickyPost,
FeaturePost,
MarkPostAsRead,
SavePost,
CreatePostReport,
Expand Down
4 changes: 2 additions & 2 deletions crates/apub/src/activities/create_or_update/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,9 @@ impl ActivityHandler for CreateOrUpdatePage {
// However, when fetching a remote post we generate a new create activity with the current
// locked/stickied value, so this check may fail. So only check if its a local community,
// because then we will definitely receive all create and update activities separately.
let is_stickied_or_locked =
let is_featured_or_locked =
self.object.stickied == Some(true) || self.object.comments_enabled == Some(false);
if community.local && is_stickied_or_locked {
if community.local && is_featured_or_locked {
return Err(LemmyError::from_message(
"New post cannot be stickied or locked",
));
Expand Down
22 changes: 12 additions & 10 deletions crates/apub/src/objects/post.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use lemmy_db_schema::{
source::{
community::Community,
local_site::LocalSite,
moderator::{ModLockPost, ModLockPostForm, ModStickyPost, ModStickyPostForm},
moderator::{ModFeaturePost, ModFeaturePostForm, ModLockPost, ModLockPostForm},
person::Person,
post::{Post, PostInsertForm, PostUpdateForm},
},
Expand Down Expand Up @@ -117,7 +117,7 @@ impl ApubObject for ApubPost {
image: self.thumbnail_url.clone().map(ImageObject::new),
comments_enabled: Some(!self.locked),
sensitive: Some(self.nsfw),
stickied: Some(self.stickied),
stickied: Some(self.featured_community),
language,
published: Some(convert_datetime(self.published)),
updated: self.updated.map(convert_datetime),
Expand Down Expand Up @@ -210,14 +210,15 @@ impl ApubObject for ApubPost {
updated: page.updated.map(|u| u.naive_local()),
deleted: Some(false),
nsfw: page.sensitive,
stickied: page.stickied,
embed_title,
embed_description,
embed_video_url,
thumbnail_url,
ap_id: Some(page.id.clone().into()),
local: Some(false),
language_id,
featured_community: page.stickied,
featured_local: Some(false),
}
} else {
// if is mod action, only update locked/stickied fields, nothing else
Expand All @@ -227,7 +228,8 @@ impl ApubObject for ApubPost {
.community_id(community.id)
.ap_id(Some(page.id.clone().into()))
.locked(page.comments_enabled.map(|e| !e))
.stickied(page.stickied)
.featured_community(page.stickied)
.featured_local(Some(false))
.updated(page.updated.map(|u| u.naive_local()))
.build()
};
Expand All @@ -239,14 +241,14 @@ impl ApubObject for ApubPost {

let post = Post::create(context.pool(), &form).await?;

// write mod log entries for sticky/lock
if Page::is_stickied_changed(&old_post, &page.stickied) {
let form = ModStickyPostForm {
// write mod log entries for feature/lock
if Page::is_featured_changed(&old_post, &page.stickied) {
let form = ModFeaturePostForm {
mod_person_id: creator.id,
post_id: post.id,
stickied: Some(post.stickied),
featured: Some(post.featured_community),
};
ModStickyPost::create(context.pool(), &form).await?;
ModFeaturePost::create(context.pool(), &form).await?;
}
if Page::is_locked_changed(&old_post, &page.comments_enabled) {
let form = ModLockPostForm {
Expand Down Expand Up @@ -298,7 +300,7 @@ mod tests {
assert!(post.body.is_some());
assert_eq!(post.body.as_ref().unwrap().len(), 45);
assert!(!post.locked);
assert!(post.stickied);
assert!(post.featured_community);
assert_eq!(request_counter, 0);

Post::delete(context.pool(), post.id).await.unwrap();
Expand Down
12 changes: 6 additions & 6 deletions crates/apub/src/protocol/objects/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,18 @@ impl Page {
.dereference_local(context)
.await;

let stickied_changed = Page::is_stickied_changed(&old_post, &self.stickied);
let featured_changed = Page::is_featured_changed(&old_post, &self.stickied);
let locked_changed = Page::is_locked_changed(&old_post, &self.comments_enabled);
Ok(stickied_changed || locked_changed)
Ok(featured_changed || locked_changed)
}

pub(crate) fn is_stickied_changed<E>(
pub(crate) fn is_featured_changed<E>(
old_post: &Result<ApubPost, E>,
new_stickied: &Option<bool>,
new_featured_community: &Option<bool>,
) -> bool {
if let Some(new_stickied) = new_stickied {
if let Some(new_featured_community) = new_featured_community {
if let Ok(old_post) = old_post {
return new_stickied != &old_post.stickied;
return new_featured_community != &old_post.featured_community;
}
}

Expand Down
3 changes: 2 additions & 1 deletion crates/db_schema/src/aggregates/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ pub struct PostAggregates {
pub score: i64,
pub upvotes: i64,
pub downvotes: i64,
pub stickied: bool,
pub published: chrono::NaiveDateTime,
pub newest_comment_time_necro: chrono::NaiveDateTime, // A newest comment time, limited to 2 days, to prevent necrobumping
pub newest_comment_time: chrono::NaiveDateTime,
pub featured_community: bool,
pub featured_local: bool,
}

#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
Expand Down
Loading

0 comments on commit 8a337f8

Please sign in to comment.