naive_now,
post::*,
post_report::*,
- post_view::*,
views::{
community_moderator_view::CommunityModeratorView,
community_view::CommunityView,
+ post_view::{PostQueryBuilder, PostView},
site_view::SiteView,
},
Crud,
Err(_e) => return Err(APIError::err("couldnt_find_post").into()),
};
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::CreatePost,
})
.await??;
- let community_id = post_view.community_id;
+ let community_id = post_view.community.id;
let community = blocking(context.pool(), move |conn| {
CommunityView::read(conn, community_id, user_id)
})
.await??;
- let community_id = post_view.community_id;
+ let community_id = post_view.community.id;
let moderators = blocking(context.pool(), move |conn| {
CommunityModeratorView::for_community(conn, community_id)
})
// Return the jwt
Ok(GetPostResponse {
- post: post_view,
+ post_view,
comments,
community,
moderators,
let community_id = data.community_id;
let community_name = data.community_name.to_owned();
let posts = match blocking(context.pool(), move |conn| {
- PostQueryBuilder::create(conn)
+ PostQueryBuilder::create(conn, user_id)
.listing_type(&type_)
.sort(&sort)
.show_nsfw(show_nsfw)
.for_community_id(community_id)
.for_community_name(community_name)
- .my_user_id(user_id)
.page(page)
.limit(limit)
.list()
Err(_e) => return Err(APIError::err("couldnt_find_post").into()),
};
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::CreatePostLike,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::EditPost,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::DeletePost,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::RemovePost,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::LockPost,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::StickyPost,
})
.await??;
- Ok(PostResponse { post: post_view })
+ Ok(PostResponse { post_view })
}
}
let user_id = user.id;
let post_id = data.post_id;
- let post = blocking(context.pool(), move |conn| {
+ let post_view = blocking(context.pool(), move |conn| {
PostView::read(&conn, post_id, None)
})
.await??;
- check_community_ban(user_id, post.community_id, context.pool()).await?;
+ check_community_ban(user_id, post_view.community.id, context.pool()).await?;
let report_form = PostReportForm {
creator_id: user_id,
post_id,
- original_post_name: post.name,
- original_post_url: post.url,
- original_post_body: post.body,
+ original_post_name: post_view.post.name,
+ original_post_url: post_view.post.url,
+ original_post_body: post_view.post.body,
reason: data.reason.to_owned(),
};
context.chat_server().do_send(SendModRoomMessage {
op: UserOperation::CreatePostReport,
response: report,
- community_id: post.community_id,
+ community_id: post_view.community.id,
websocket_id,
});
moderator::*,
moderator_views::*,
naive_now,
- post_view::*,
site::*,
views::{
community_view::CommunityQueryBuilder,
+ post_view::PostQueryBuilder,
site_view::SiteView,
user_view::{UserQueryBuilder, UserViewSafe},
},
match type_ {
SearchType::Posts => {
posts = blocking(context.pool(), move |conn| {
- PostQueryBuilder::create(conn)
+ PostQueryBuilder::create(conn, user_id)
.sort(&sort)
.show_nsfw(true)
.for_community_id(community_id)
.for_community_name(community_name)
.search_term(q)
- .my_user_id(user_id)
.page(page)
.limit(limit)
.list()
}
SearchType::All => {
posts = blocking(context.pool(), move |conn| {
- PostQueryBuilder::create(conn)
+ PostQueryBuilder::create(conn, user_id)
.sort(&sort)
.show_nsfw(true)
.for_community_id(community_id)
.for_community_name(community_name)
.search_term(q)
- .my_user_id(user_id)
.page(page)
.limit(limit)
.list()
}
SearchType::Url => {
posts = blocking(context.pool(), move |conn| {
- PostQueryBuilder::create(conn)
+ PostQueryBuilder::create(conn, None)
.sort(&sort)
.show_nsfw(true)
.for_community_id(community_id)
password_reset_request::*,
post::*,
post_report::PostReportView,
- post_view::*,
private_message::*,
private_message_view::*,
site::*,
views::{
community_follower_view::CommunityFollowerView,
community_moderator_view::CommunityModeratorView,
+ post_view::PostQueryBuilder,
site_view::SiteView,
user_view::{UserViewDangerous, UserViewSafe},
},
let community_id = data.community_id;
let (posts, comments) = blocking(context.pool(), move |conn| {
- let mut posts_query = PostQueryBuilder::create(conn)
+ let mut posts_query = PostQueryBuilder::create(conn, user_id)
.sort(&sort)
.show_nsfw(show_nsfw)
.saved_only(saved_only)
.for_community_id(community_id)
- .my_user_id(user_id)
.page(page)
.limit(limit);
use anyhow::Context;
use lemmy_db::{
post::{Post, PostLike, PostLikeForm},
- post_view::PostView,
+ views::post_view::PostView,
Likeable,
};
use lemmy_structs::{blocking, post::PostResponse};
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::CreatePost,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::EditPost,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::CreatePostLike,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::CreatePostLike,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::EditPost,
post: res,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::EditPost,
post: res,
use activitystreams::activity::{Dislike, Like};
use lemmy_db::{
post::{Post, PostLike},
- post_view::PostView,
+ views::post_view::PostView,
Likeable,
};
use lemmy_structs::{blocking, post::PostResponse};
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::CreatePostLike,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::CreatePostLike,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::EditPost,
post: res,
})
.await??;
- let res = PostResponse { post: post_view };
+ let res = PostResponse { post_view };
context.chat_server().do_send(SendPost {
op: UserOperation::EditPost,
community::{Community, CommunityModerator, CommunityModeratorForm},
naive_now,
post::Post,
- post_view::PostView,
user::User_,
- views::{community_view::CommunityView, user_view::UserViewSafe},
+ views::{community_view::CommunityView, post_view::PostView, user_view::UserViewSafe},
ApubObject,
Joinable,
SearchType,
pub mod password_reset_request;
pub mod post;
pub mod post_report;
-pub mod post_view;
pub mod private_message;
pub mod private_message_view;
pub mod schema;
+++ /dev/null
-use super::post_view::post_fast_view::BoxedQuery;
-use crate::{fuzzy_search, limit_and_offset, ListingType, MaybeOptional, SortType};
-use diesel::{dsl::*, pg::Pg, result::Error, *};
-use serde::Serialize;
-
-// The faked schema since diesel doesn't do views
-table! {
- post_view (id) {
- id -> Int4,
- name -> Varchar,
- url -> Nullable<Text>,
- body -> Nullable<Text>,
- creator_id -> Int4,
- community_id -> Int4,
- removed -> Bool,
- locked -> Bool,
- published -> Timestamp,
- updated -> Nullable<Timestamp>,
- deleted -> Bool,
- nsfw -> Bool,
- stickied -> Bool,
- embed_title -> Nullable<Text>,
- embed_description -> Nullable<Text>,
- embed_html -> Nullable<Text>,
- thumbnail_url -> Nullable<Text>,
- ap_id -> Text,
- local -> Bool,
- creator_actor_id -> Text,
- creator_local -> Bool,
- creator_name -> Varchar,
- creator_preferred_username -> Nullable<Varchar>,
- creator_published -> Timestamp,
- creator_avatar -> Nullable<Text>,
- banned -> Bool,
- banned_from_community -> Bool,
- community_actor_id -> Text,
- community_local -> Bool,
- community_name -> Varchar,
- community_icon -> Nullable<Text>,
- community_removed -> Bool,
- community_deleted -> Bool,
- community_nsfw -> Bool,
- number_of_comments -> BigInt,
- score -> BigInt,
- upvotes -> BigInt,
- downvotes -> BigInt,
- hot_rank -> Int4,
- hot_rank_active -> Int4,
- newest_activity_time -> Timestamp,
- user_id -> Nullable<Int4>,
- my_vote -> Nullable<Int4>,
- subscribed -> Nullable<Bool>,
- read -> Nullable<Bool>,
- saved -> Nullable<Bool>,
- }
-}
-
-table! {
- post_fast_view (id) {
- id -> Int4,
- name -> Varchar,
- url -> Nullable<Text>,
- body -> Nullable<Text>,
- creator_id -> Int4,
- community_id -> Int4,
- removed -> Bool,
- locked -> Bool,
- published -> Timestamp,
- updated -> Nullable<Timestamp>,
- deleted -> Bool,
- nsfw -> Bool,
- stickied -> Bool,
- embed_title -> Nullable<Text>,
- embed_description -> Nullable<Text>,
- embed_html -> Nullable<Text>,
- thumbnail_url -> Nullable<Text>,
- ap_id -> Text,
- local -> Bool,
- creator_actor_id -> Text,
- creator_local -> Bool,
- creator_name -> Varchar,
- creator_preferred_username -> Nullable<Varchar>,
- creator_published -> Timestamp,
- creator_avatar -> Nullable<Text>,
- banned -> Bool,
- banned_from_community -> Bool,
- community_actor_id -> Text,
- community_local -> Bool,
- community_name -> Varchar,
- community_icon -> Nullable<Text>,
- community_removed -> Bool,
- community_deleted -> Bool,
- community_nsfw -> Bool,
- number_of_comments -> BigInt,
- score -> BigInt,
- upvotes -> BigInt,
- downvotes -> BigInt,
- hot_rank -> Int4,
- hot_rank_active -> Int4,
- newest_activity_time -> Timestamp,
- user_id -> Nullable<Int4>,
- my_vote -> Nullable<Int4>,
- subscribed -> Nullable<Bool>,
- read -> Nullable<Bool>,
- saved -> Nullable<Bool>,
- }
-}
-
-#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, QueryableByName, Clone)]
-#[table_name = "post_fast_view"]
-pub struct PostView {
- pub id: i32,
- pub name: String,
- pub url: Option<String>,
- pub body: Option<String>,
- pub creator_id: i32,
- pub community_id: i32,
- pub removed: bool,
- pub locked: bool,
- pub published: chrono::NaiveDateTime,
- pub updated: Option<chrono::NaiveDateTime>,
- pub deleted: bool,
- pub nsfw: bool,
- pub stickied: bool,
- pub embed_title: Option<String>,
- pub embed_description: Option<String>,
- pub embed_html: Option<String>,
- pub thumbnail_url: Option<String>,
- pub ap_id: String,
- pub local: bool,
- pub creator_actor_id: String,
- pub creator_local: bool,
- pub creator_name: String,
- pub creator_preferred_username: Option<String>,
- pub creator_published: chrono::NaiveDateTime,
- pub creator_avatar: Option<String>,
- pub banned: bool,
- pub banned_from_community: bool,
- pub community_actor_id: String,
- pub community_local: bool,
- pub community_name: String,
- pub community_icon: Option<String>,
- pub community_removed: bool,
- pub community_deleted: bool,
- pub community_nsfw: bool,
- pub number_of_comments: i64,
- pub score: i64,
- pub upvotes: i64,
- pub downvotes: i64,
- pub hot_rank: i32,
- pub hot_rank_active: i32,
- pub newest_activity_time: chrono::NaiveDateTime,
- pub user_id: Option<i32>,
- pub my_vote: Option<i32>,
- pub subscribed: Option<bool>,
- pub read: Option<bool>,
- pub saved: Option<bool>,
-}
-
-pub struct PostQueryBuilder<'a> {
- conn: &'a PgConnection,
- query: BoxedQuery<'a, Pg>,
- listing_type: &'a ListingType,
- sort: &'a SortType,
- my_user_id: Option<i32>,
- for_creator_id: Option<i32>,
- for_community_id: Option<i32>,
- for_community_name: Option<String>,
- search_term: Option<String>,
- url_search: Option<String>,
- show_nsfw: bool,
- saved_only: bool,
- unread_only: bool,
- page: Option<i64>,
- limit: Option<i64>,
-}
-
-impl<'a> PostQueryBuilder<'a> {
- pub fn create(conn: &'a PgConnection) -> Self {
- use super::post_view::post_fast_view::dsl::*;
-
- let query = post_fast_view.into_boxed();
-
- PostQueryBuilder {
- conn,
- query,
- listing_type: &ListingType::All,
- sort: &SortType::Hot,
- my_user_id: None,
- for_creator_id: None,
- for_community_id: None,
- for_community_name: None,
- search_term: None,
- url_search: None,
- show_nsfw: true,
- saved_only: false,
- unread_only: false,
- page: None,
- limit: None,
- }
- }
-
- pub fn listing_type(mut self, listing_type: &'a ListingType) -> Self {
- self.listing_type = listing_type;
- self
- }
-
- pub fn sort(mut self, sort: &'a SortType) -> Self {
- self.sort = sort;
- self
- }
-
- pub fn for_community_id<T: MaybeOptional<i32>>(mut self, for_community_id: T) -> Self {
- self.for_community_id = for_community_id.get_optional();
- self
- }
-
- pub fn for_community_name<T: MaybeOptional<String>>(mut self, for_community_name: T) -> Self {
- self.for_community_name = for_community_name.get_optional();
- self
- }
-
- pub fn for_creator_id<T: MaybeOptional<i32>>(mut self, for_creator_id: T) -> Self {
- self.for_creator_id = for_creator_id.get_optional();
- self
- }
-
- pub fn search_term<T: MaybeOptional<String>>(mut self, search_term: T) -> Self {
- self.search_term = search_term.get_optional();
- self
- }
-
- pub fn url_search<T: MaybeOptional<String>>(mut self, url_search: T) -> Self {
- self.url_search = url_search.get_optional();
- self
- }
-
- pub fn my_user_id<T: MaybeOptional<i32>>(mut self, my_user_id: T) -> Self {
- self.my_user_id = my_user_id.get_optional();
- self
- }
-
- pub fn show_nsfw(mut self, show_nsfw: bool) -> Self {
- self.show_nsfw = show_nsfw;
- self
- }
-
- pub fn saved_only(mut self, saved_only: bool) -> Self {
- self.saved_only = saved_only;
- self
- }
-
- pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
- self.page = page.get_optional();
- self
- }
-
- pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
- self.limit = limit.get_optional();
- self
- }
-
- pub fn list(self) -> Result<Vec<PostView>, Error> {
- use super::post_view::post_fast_view::dsl::*;
-
- let mut query = self.query;
-
- query = match self.listing_type {
- ListingType::Subscribed => query.filter(subscribed.eq(true)),
- ListingType::Local => query.filter(community_local.eq(true)),
- _ => query,
- };
-
- if let Some(for_community_id) = self.for_community_id {
- query = query
- .filter(community_id.eq(for_community_id))
- .then_order_by(stickied.desc());
- }
-
- if let Some(for_community_name) = self.for_community_name {
- query = query
- .filter(community_name.eq(for_community_name))
- .filter(community_local.eq(true))
- .then_order_by(stickied.desc());
- }
-
- if let Some(url_search) = self.url_search {
- query = query.filter(url.eq(url_search));
- }
-
- if let Some(search_term) = self.search_term {
- let searcher = fuzzy_search(&search_term);
- query = query.filter(name.ilike(searcher.to_owned()).or(body.ilike(searcher)));
- }
-
- query = match self.sort {
- SortType::Active => query
- .then_order_by(hot_rank_active.desc())
- .then_order_by(published.desc()),
- SortType::Hot => query
- .then_order_by(hot_rank.desc())
- .then_order_by(published.desc()),
- SortType::New => query.then_order_by(published.desc()),
- SortType::TopAll => query.then_order_by(score.desc()),
- SortType::TopYear => query
- .filter(published.gt(now - 1.years()))
- .then_order_by(score.desc()),
- SortType::TopMonth => query
- .filter(published.gt(now - 1.months()))
- .then_order_by(score.desc()),
- SortType::TopWeek => query
- .filter(published.gt(now - 1.weeks()))
- .then_order_by(score.desc()),
- SortType::TopDay => query
- .filter(published.gt(now - 1.days()))
- .then_order_by(score.desc()),
- };
-
- // The view lets you pass a null user_id, if you're not logged in
- query = if let Some(my_user_id) = self.my_user_id {
- query.filter(user_id.eq(my_user_id))
- } else {
- query.filter(user_id.is_null())
- };
-
- // If its for a specific user, show the removed / deleted
- if let Some(for_creator_id) = self.for_creator_id {
- query = query.filter(creator_id.eq(for_creator_id));
- } else {
- query = query
- .filter(removed.eq(false))
- .filter(deleted.eq(false))
- .filter(community_removed.eq(false))
- .filter(community_deleted.eq(false));
- }
-
- if !self.show_nsfw {
- query = query
- .filter(nsfw.eq(false))
- .filter(community_nsfw.eq(false));
- };
-
- // TODO these are wrong, bc they'll only show saved for your logged in user, not theirs
- if self.saved_only {
- query = query.filter(saved.eq(true));
- };
-
- if self.unread_only {
- query = query.filter(read.eq(false));
- };
-
- let (limit, offset) = limit_and_offset(self.page, self.limit);
- query = query
- .limit(limit)
- .offset(offset)
- .filter(removed.eq(false))
- .filter(deleted.eq(false))
- .filter(community_removed.eq(false))
- .filter(community_deleted.eq(false));
-
- query.load::<PostView>(self.conn)
- }
-}
-
-impl PostView {
- pub fn read(
- conn: &PgConnection,
- from_post_id: i32,
- my_user_id: Option<i32>,
- ) -> Result<Self, Error> {
- use super::post_view::post_fast_view::dsl::*;
- use diesel::prelude::*;
-
- let mut query = post_fast_view.into_boxed();
-
- query = query.filter(id.eq(from_post_id));
-
- if let Some(my_user_id) = my_user_id {
- query = query.filter(user_id.eq(my_user_id));
- } else {
- query = query.filter(user_id.is_null());
- };
-
- query.first::<Self>(conn)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::{
- community::*,
- post::*,
- post_view::*,
- tests::establish_unpooled_connection,
- user::*,
- Crud,
- Likeable,
- *,
- };
-
- #[test]
- fn test_crud() {
- let conn = establish_unpooled_connection();
-
- let user_name = "tegan".to_string();
- let community_name = "test_community_3".to_string();
- let post_name = "test post 3".to_string();
-
- let new_user = UserForm {
- name: user_name.to_owned(),
- preferred_username: None,
- password_encrypted: "nope".into(),
- email: None,
- matrix_user_id: None,
- avatar: None,
- banner: None,
- published: None,
- updated: None,
- admin: false,
- banned: Some(false),
- show_nsfw: false,
- theme: "browser".into(),
- default_sort_type: SortType::Hot as i16,
- default_listing_type: ListingType::Subscribed as i16,
- lang: "browser".into(),
- show_avatars: true,
- send_notifications_to_email: false,
- actor_id: None,
- bio: None,
- local: true,
- private_key: None,
- public_key: None,
- last_refreshed_at: None,
- };
-
- let inserted_user = User_::create(&conn, &new_user).unwrap();
-
- let new_community = CommunityForm {
- name: community_name.to_owned(),
- title: "nada".to_owned(),
- description: None,
- creator_id: inserted_user.id,
- category_id: 1,
- removed: None,
- deleted: None,
- updated: None,
- nsfw: false,
- actor_id: None,
- local: true,
- private_key: None,
- public_key: None,
- last_refreshed_at: None,
- published: None,
- icon: None,
- banner: None,
- };
-
- let inserted_community = Community::create(&conn, &new_community).unwrap();
-
- let new_post = PostForm {
- name: post_name.to_owned(),
- url: None,
- body: None,
- creator_id: inserted_user.id,
- community_id: inserted_community.id,
- removed: None,
- deleted: None,
- locked: None,
- stickied: None,
- updated: None,
- nsfw: false,
- embed_title: None,
- embed_description: None,
- embed_html: None,
- thumbnail_url: None,
- ap_id: None,
- local: true,
- published: None,
- };
-
- let inserted_post = Post::create(&conn, &new_post).unwrap();
-
- let post_like_form = PostLikeForm {
- post_id: inserted_post.id,
- user_id: inserted_user.id,
- score: 1,
- };
-
- let inserted_post_like = PostLike::like(&conn, &post_like_form).unwrap();
-
- let expected_post_like = PostLike {
- id: inserted_post_like.id,
- post_id: inserted_post.id,
- user_id: inserted_user.id,
- published: inserted_post_like.published,
- score: 1,
- };
-
- let read_post_listings_with_user = PostQueryBuilder::create(&conn)
- .listing_type(&ListingType::Community)
- .sort(&SortType::New)
- .for_community_id(inserted_community.id)
- .my_user_id(inserted_user.id)
- .list()
- .unwrap();
-
- let read_post_listings_no_user = PostQueryBuilder::create(&conn)
- .listing_type(&ListingType::Community)
- .sort(&SortType::New)
- .for_community_id(inserted_community.id)
- .list()
- .unwrap();
-
- let read_post_listing_no_user = PostView::read(&conn, inserted_post.id, None).unwrap();
- let read_post_listing_with_user =
- PostView::read(&conn, inserted_post.id, Some(inserted_user.id)).unwrap();
-
- // the non user version
- let expected_post_listing_no_user = PostView {
- user_id: None,
- my_vote: None,
- id: inserted_post.id,
- name: post_name.to_owned(),
- url: None,
- body: None,
- creator_id: inserted_user.id,
- creator_name: user_name.to_owned(),
- creator_preferred_username: None,
- creator_published: inserted_user.published,
- creator_avatar: None,
- banned: false,
- banned_from_community: false,
- community_id: inserted_community.id,
- removed: false,
- deleted: false,
- locked: false,
- stickied: false,
- community_name: community_name.to_owned(),
- community_icon: None,
- community_removed: false,
- community_deleted: false,
- community_nsfw: false,
- number_of_comments: 0,
- score: 1,
- upvotes: 1,
- downvotes: 0,
- hot_rank: read_post_listing_no_user.hot_rank,
- hot_rank_active: read_post_listing_no_user.hot_rank_active,
- published: inserted_post.published,
- newest_activity_time: inserted_post.published,
- updated: None,
- subscribed: None,
- read: None,
- saved: None,
- nsfw: false,
- embed_title: None,
- embed_description: None,
- embed_html: None,
- thumbnail_url: None,
- ap_id: inserted_post.ap_id.to_owned(),
- local: true,
- creator_actor_id: inserted_user.actor_id.to_owned(),
- creator_local: true,
- community_actor_id: inserted_community.actor_id.to_owned(),
- community_local: true,
- };
-
- let expected_post_listing_with_user = PostView {
- user_id: Some(inserted_user.id),
- my_vote: Some(1),
- id: inserted_post.id,
- name: post_name,
- url: None,
- body: None,
- removed: false,
- deleted: false,
- locked: false,
- stickied: false,
- creator_id: inserted_user.id,
- creator_name: user_name,
- creator_preferred_username: None,
- creator_published: inserted_user.published,
- creator_avatar: None,
- banned: false,
- banned_from_community: false,
- community_id: inserted_community.id,
- community_name,
- community_icon: None,
- community_removed: false,
- community_deleted: false,
- community_nsfw: false,
- number_of_comments: 0,
- score: 1,
- upvotes: 1,
- downvotes: 0,
- hot_rank: read_post_listing_with_user.hot_rank,
- hot_rank_active: read_post_listing_with_user.hot_rank_active,
- published: inserted_post.published,
- newest_activity_time: inserted_post.published,
- updated: None,
- subscribed: Some(false),
- read: Some(false),
- saved: Some(false),
- nsfw: false,
- embed_title: None,
- embed_description: None,
- embed_html: None,
- thumbnail_url: None,
- ap_id: inserted_post.ap_id.to_owned(),
- local: true,
- creator_actor_id: inserted_user.actor_id.to_owned(),
- creator_local: true,
- community_actor_id: inserted_community.actor_id.to_owned(),
- community_local: true,
- };
-
- let like_removed = PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap();
- let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
- Community::delete(&conn, inserted_community.id).unwrap();
- User_::delete(&conn, inserted_user.id).unwrap();
-
- // The with user
- assert_eq!(
- expected_post_listing_with_user,
- read_post_listings_with_user[0]
- );
- assert_eq!(expected_post_listing_with_user, read_post_listing_with_user);
- assert_eq!(1, read_post_listings_with_user.len());
-
- // Without the user
- assert_eq!(expected_post_listing_no_user, read_post_listings_no_user[0]);
- assert_eq!(expected_post_listing_no_user, read_post_listing_no_user);
- assert_eq!(1, read_post_listings_no_user.len());
-
- // assert_eq!(expected_post, inserted_post);
- // assert_eq!(expected_post, updated_post);
- assert_eq!(expected_post_like, inserted_post_like);
- assert_eq!(1, like_removed);
- assert_eq!(1, num_deleted);
- }
-}
use diesel::{result::Error, *};
use serde::Serialize;
-#[derive(Debug, Serialize, Clone)]
+#[derive(Debug, PartialEq, Serialize, Clone)]
pub struct PostView {
pub post: Post,
pub creator: UserSafe,
pub community: CommunitySafe,
pub counts: PostAggregates,
- pub subscribed: bool, // Left join to CommunityFollower
- pub banned_from_community: bool, // Left Join to CommunityUserBan
- pub saved: bool, // Left join to PostSaved
- pub read: bool, // Left join to PostRead
- pub my_vote: Option<i16>, // Left join to PostLike
+ pub subscribed: bool, // Left join to CommunityFollower
+ pub creator_banned_from_community: bool, // Left Join to CommunityUserBan
+ pub saved: bool, // Left join to PostSaved
+ pub read: bool, // Left join to PostRead
+ pub my_vote: Option<i16>, // Left join to PostLike
}
type PostViewTuple = (
Post,
UserSafe,
CommunitySafe,
+ Option<CommunityUserBan>,
PostAggregates,
Option<CommunityFollower>,
- Option<CommunityUserBan>,
Option<PostSaved>,
Option<PostRead>,
Option<i16>,
// The left join below will return None in this case
let user_id_join = my_user_id.unwrap_or(-1);
- let (post, creator, community, counts, follower, banned_from_community, saved, read, my_vote) =
- post::table
- .find(post_id)
- .inner_join(user_::table)
- .inner_join(community::table)
- .inner_join(post_aggregates::table)
- .left_join(
- community_follower::table.on(
- post::community_id
- .eq(community_follower::community_id)
- .and(community_follower::user_id.eq(user_id_join)),
- ),
- )
- .left_join(
- community_user_ban::table.on(
- post::community_id
- .eq(community_user_ban::community_id)
- .and(community_user_ban::user_id.eq(user_id_join)),
- ),
- )
- .left_join(
- post_saved::table.on(
- post::id
- .eq(post_saved::post_id)
- .and(post_saved::user_id.eq(user_id_join)),
- ),
- )
- .left_join(
- post_read::table.on(
- post::id
- .eq(post_read::post_id)
- .and(post_read::user_id.eq(user_id_join)),
- ),
- )
- .left_join(
- post_like::table.on(
- post::id
- .eq(post_like::post_id)
- .and(post_like::user_id.eq(user_id_join)),
- ),
- )
- .select((
- post::all_columns,
- User_::safe_columns_tuple(),
- Community::safe_columns_tuple(),
- post_aggregates::all_columns,
- community_follower::all_columns.nullable(),
- community_user_ban::all_columns.nullable(),
- post_saved::all_columns.nullable(),
- post_read::all_columns.nullable(),
- post_like::score.nullable(),
- ))
- .first::<PostViewTuple>(conn)?;
+ let (
+ post,
+ creator,
+ community,
+ creator_banned_from_community,
+ counts,
+ follower,
+ saved,
+ read,
+ my_vote,
+ ) = post::table
+ .find(post_id)
+ .inner_join(user_::table)
+ .inner_join(community::table)
+ .left_join(
+ community_user_ban::table.on(
+ post::community_id
+ .eq(community_user_ban::community_id)
+ .and(community_user_ban::user_id.eq(community::creator_id)),
+ ),
+ )
+ .inner_join(post_aggregates::table)
+ .left_join(
+ community_follower::table.on(
+ post::community_id
+ .eq(community_follower::community_id)
+ .and(community_follower::user_id.eq(user_id_join)),
+ ),
+ )
+ .left_join(
+ post_saved::table.on(
+ post::id
+ .eq(post_saved::post_id)
+ .and(post_saved::user_id.eq(user_id_join)),
+ ),
+ )
+ .left_join(
+ post_read::table.on(
+ post::id
+ .eq(post_read::post_id)
+ .and(post_read::user_id.eq(user_id_join)),
+ ),
+ )
+ .left_join(
+ post_like::table.on(
+ post::id
+ .eq(post_like::post_id)
+ .and(post_like::user_id.eq(user_id_join)),
+ ),
+ )
+ .select((
+ post::all_columns,
+ User_::safe_columns_tuple(),
+ Community::safe_columns_tuple(),
+ community_user_ban::all_columns.nullable(),
+ post_aggregates::all_columns,
+ community_follower::all_columns.nullable(),
+ post_saved::all_columns.nullable(),
+ post_read::all_columns.nullable(),
+ post_like::score.nullable(),
+ ))
+ .first::<PostViewTuple>(conn)?;
Ok(PostView {
post,
creator,
community,
+ creator_banned_from_community: creator_banned_from_community.is_some(),
counts,
subscribed: follower.is_some(),
- banned_from_community: banned_from_community.is_some(),
saved: saved.is_some(),
read: read.is_some(),
my_vote,
sql_types::*,
};
- /// TODO awful, but necessary because of the boxed join
+ // /// TODO awful, but necessary because of the boxed join
pub(super) type BoxedPostJoin<'a> = BoxedSelectStatement<
'a,
(
Nullable<Text>,
Nullable<Text>,
),
+ Nullable<(Integer, Integer, Integer, Timestamp)>,
(Integer, Integer, BigInt, BigInt, BigInt, BigInt, Timestamp),
Nullable<(Integer, Integer, Integer, Timestamp, Nullable<Bool>)>,
Nullable<(Integer, Integer, Integer, Timestamp)>,
Nullable<(Integer, Integer, Integer, Timestamp)>,
- Nullable<(Integer, Integer, Integer, Timestamp)>,
Nullable<SmallInt>,
),
JoinOn<
diesel::expression::nullable::Nullable<community::columns::id>,
>,
>,
- post_aggregates::table,
- Inner,
+ community_user_ban::table,
+ LeftOuter,
>,
- diesel::expression::operators::Eq<
- diesel::expression::nullable::Nullable<
- post_aggregates::columns::post_id,
+ diesel::expression::operators::And<
+ diesel::expression::operators::Eq<
+ post::columns::community_id,
+ community_user_ban::columns::community_id,
+ >,
+ diesel::expression::operators::Eq<
+ community_user_ban::columns::user_id,
+ community::columns::creator_id,
>,
- diesel::expression::nullable::Nullable<post::columns::id>,
>,
>,
- community_follower::table,
- LeftOuter,
+ post_aggregates::table,
+ Inner,
>,
- diesel::expression::operators::And<
- diesel::expression::operators::Eq<
- post::columns::community_id,
- community_follower::columns::community_id,
- >,
- diesel::expression::operators::Eq<
- community_follower::columns::user_id,
- diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>,
- >,
+ diesel::expression::operators::Eq<
+ diesel::expression::nullable::Nullable<post_aggregates::columns::post_id>,
+ diesel::expression::nullable::Nullable<post::columns::id>,
>,
>,
- community_user_ban::table,
+ community_follower::table,
LeftOuter,
>,
diesel::expression::operators::And<
diesel::expression::operators::Eq<
post::columns::community_id,
- community_user_ban::columns::community_id,
+ community_follower::columns::community_id,
>,
diesel::expression::operators::Eq<
- community_user_ban::columns::user_id,
- diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>,
+ community_follower::columns::user_id,
+ diesel::expression::bound::Bound<Integer, i32>,
>,
>,
>,
diesel::expression::operators::Eq<post::columns::id, post_saved::columns::post_id>,
diesel::expression::operators::Eq<
post_saved::columns::user_id,
- diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>,
+ diesel::expression::bound::Bound<Integer, i32>,
>,
>,
>,
diesel::expression::operators::Eq<post::columns::id, post_read::columns::post_id>,
diesel::expression::operators::Eq<
post_read::columns::user_id,
- diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>,
+ diesel::expression::bound::Bound<Integer, i32>,
>,
>,
>,
diesel::expression::operators::Eq<post::columns::id, post_like::columns::post_id>,
diesel::expression::operators::Eq<
post_like::columns::user_id,
- diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>,
+ diesel::expression::bound::Bound<Integer, i32>,
>,
>,
>,
let query = post::table
.inner_join(user_::table)
.inner_join(community::table)
- .inner_join(post_aggregates::table)
.left_join(
- community_follower::table.on(
+ community_user_ban::table.on(
post::community_id
- .eq(community_follower::community_id)
- .and(community_follower::user_id.eq(user_id_join)),
+ .eq(community_user_ban::community_id)
+ .and(community_user_ban::user_id.eq(community::creator_id)),
),
)
+ .inner_join(post_aggregates::table)
.left_join(
- community_user_ban::table.on(
+ community_follower::table.on(
post::community_id
- .eq(community_user_ban::community_id)
- .and(community_user_ban::user_id.eq(user_id_join)),
+ .eq(community_follower::community_id)
+ .and(community_follower::user_id.eq(user_id_join)),
),
)
.left_join(
post::all_columns,
User_::safe_columns_tuple(),
Community::safe_columns_tuple(),
+ community_user_ban::all_columns.nullable(),
post_aggregates::all_columns,
community_follower::all_columns.nullable(),
- community_user_ban::all_columns.nullable(),
post_saved::all_columns.nullable(),
post_read::all_columns.nullable(),
post_like::score.nullable(),
post: a.0.to_owned(),
creator: a.1.to_owned(),
community: a.2.to_owned(),
- counts: a.3.to_owned(),
- subscribed: a.4.is_some(),
- banned_from_community: a.5.is_some(),
+ creator_banned_from_community: a.3.is_some(),
+ counts: a.4.to_owned(),
+ subscribed: a.5.is_some(),
saved: a.6.is_some(),
read: a.7.is_some(),
my_vote: a.8,
.collect::<Vec<Self>>()
}
}
+
+#[cfg(test)]
+mod tests {
+ use crate::{
+ aggregates::post_aggregates::PostAggregates,
+ community::*,
+ post::*,
+ tests::establish_unpooled_connection,
+ user::*,
+ views::post_view::{PostQueryBuilder, PostView},
+ Crud,
+ Likeable,
+ *,
+ };
+
+ #[test]
+ fn test_crud() {
+ let conn = establish_unpooled_connection();
+
+ let user_name = "tegan".to_string();
+ let community_name = "test_community_3".to_string();
+ let post_name = "test post 3".to_string();
+
+ let new_user = UserForm {
+ name: user_name.to_owned(),
+ preferred_username: None,
+ password_encrypted: "nope".into(),
+ email: None,
+ matrix_user_id: None,
+ avatar: None,
+ banner: None,
+ published: None,
+ updated: None,
+ admin: false,
+ banned: Some(false),
+ show_nsfw: false,
+ theme: "browser".into(),
+ default_sort_type: SortType::Hot as i16,
+ default_listing_type: ListingType::Subscribed as i16,
+ lang: "browser".into(),
+ show_avatars: true,
+ send_notifications_to_email: false,
+ actor_id: None,
+ bio: None,
+ local: true,
+ private_key: None,
+ public_key: None,
+ last_refreshed_at: None,
+ };
+
+ let inserted_user = User_::create(&conn, &new_user).unwrap();
+
+ let new_community = CommunityForm {
+ name: community_name.to_owned(),
+ title: "nada".to_owned(),
+ description: None,
+ creator_id: inserted_user.id,
+ category_id: 1,
+ removed: None,
+ deleted: None,
+ updated: None,
+ nsfw: false,
+ actor_id: None,
+ local: true,
+ private_key: None,
+ public_key: None,
+ last_refreshed_at: None,
+ published: None,
+ icon: None,
+ banner: None,
+ };
+
+ let inserted_community = Community::create(&conn, &new_community).unwrap();
+
+ let new_post = PostForm {
+ name: post_name.to_owned(),
+ url: None,
+ body: None,
+ creator_id: inserted_user.id,
+ community_id: inserted_community.id,
+ removed: None,
+ deleted: None,
+ locked: None,
+ stickied: None,
+ updated: None,
+ nsfw: false,
+ embed_title: None,
+ embed_description: None,
+ embed_html: None,
+ thumbnail_url: None,
+ ap_id: None,
+ local: true,
+ published: None,
+ };
+
+ let inserted_post = Post::create(&conn, &new_post).unwrap();
+
+ let post_like_form = PostLikeForm {
+ post_id: inserted_post.id,
+ user_id: inserted_user.id,
+ score: 1,
+ };
+
+ let inserted_post_like = PostLike::like(&conn, &post_like_form).unwrap();
+
+ let expected_post_like = PostLike {
+ id: inserted_post_like.id,
+ post_id: inserted_post.id,
+ user_id: inserted_user.id,
+ published: inserted_post_like.published,
+ score: 1,
+ };
+
+ let read_post_listings_with_user = PostQueryBuilder::create(&conn, Some(inserted_user.id))
+ .listing_type(&ListingType::Community)
+ .sort(&SortType::New)
+ .for_community_id(inserted_community.id)
+ .list()
+ .unwrap();
+
+ let read_post_listings_no_user = PostQueryBuilder::create(&conn, None)
+ .listing_type(&ListingType::Community)
+ .sort(&SortType::New)
+ .for_community_id(inserted_community.id)
+ .list()
+ .unwrap();
+
+ let read_post_listing_no_user = PostView::read(&conn, inserted_post.id, None).unwrap();
+ let read_post_listing_with_user =
+ PostView::read(&conn, inserted_post.id, Some(inserted_user.id)).unwrap();
+
+ // the non user version
+ let expected_post_listing_no_user = PostView {
+ post: Post {
+ id: inserted_post.id,
+ name: post_name.to_owned(),
+ creator_id: inserted_user.id,
+ url: None,
+ body: None,
+ published: inserted_post.published,
+ updated: None,
+ community_id: inserted_community.id,
+ removed: false,
+ deleted: false,
+ locked: false,
+ stickied: false,
+ nsfw: false,
+ embed_title: None,
+ embed_description: None,
+ embed_html: None,
+ thumbnail_url: None,
+ ap_id: inserted_post.ap_id.to_owned(),
+ local: true,
+ },
+ my_vote: None,
+ creator: UserSafe {
+ id: inserted_user.id,
+ name: user_name.to_owned(),
+ preferred_username: None,
+ published: inserted_user.published,
+ avatar: None,
+ actor_id: inserted_user.actor_id.to_owned(),
+ local: true,
+ banned: false,
+ deleted: false,
+ bio: None,
+ banner: None,
+ admin: false,
+ updated: None,
+ matrix_user_id: None,
+ },
+ creator_banned_from_community: false,
+ community: CommunitySafe {
+ id: inserted_community.id,
+ name: community_name.to_owned(),
+ icon: None,
+ removed: false,
+ deleted: false,
+ nsfw: false,
+ actor_id: inserted_community.actor_id.to_owned(),
+ local: true,
+ title: "nada".to_owned(),
+ description: None,
+ creator_id: inserted_user.id,
+ category_id: 1,
+ updated: None,
+ banner: None,
+ published: inserted_community.published,
+ },
+ counts: PostAggregates {
+ id: inserted_post.id, // TODO this might fail
+ post_id: inserted_post.id,
+ comments: 0,
+ score: 1,
+ upvotes: 1,
+ downvotes: 0,
+ newest_comment_time: inserted_post.published,
+ },
+ subscribed: false,
+ read: false,
+ saved: false,
+ };
+
+ // TODO More needs to be added here
+ let mut expected_post_listing_with_user = expected_post_listing_no_user.to_owned();
+ expected_post_listing_with_user.my_vote = Some(1);
+
+ let like_removed = PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap();
+ let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
+ Community::delete(&conn, inserted_community.id).unwrap();
+ User_::delete(&conn, inserted_user.id).unwrap();
+
+ // The with user
+ assert_eq!(
+ expected_post_listing_with_user,
+ read_post_listings_with_user[0]
+ );
+ assert_eq!(expected_post_listing_with_user, read_post_listing_with_user);
+ assert_eq!(1, read_post_listings_with_user.len());
+
+ // Without the user
+ assert_eq!(expected_post_listing_no_user, read_post_listings_no_user[0]);
+ assert_eq!(expected_post_listing_no_user, read_post_listing_no_user);
+ assert_eq!(1, read_post_listings_no_user.len());
+
+ // assert_eq!(expected_post, inserted_post);
+ // assert_eq!(expected_post, updated_post);
+ assert_eq!(expected_post_like, inserted_post_like);
+ assert_eq!(1, like_removed);
+ assert_eq!(1, num_deleted);
+ }
+}
use lemmy_db::{
comment_view::CommentView,
post_report::PostReportView,
- post_view::PostView,
- views::{community_moderator_view::CommunityModeratorView, community_view::CommunityView},
+ views::{
+ community_moderator_view::CommunityModeratorView,
+ community_view::CommunityView,
+ post_view::PostView,
+ },
};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Clone)]
pub struct PostResponse {
- pub post: PostView,
+ pub post_view: PostView,
}
#[derive(Deserialize)]
#[derive(Serialize)]
pub struct GetPostResponse {
- pub post: PostView,
+ pub post_view: PostView,
pub comments: Vec<CommentView>,
pub community: CommunityView,
pub moderators: Vec<CommunityModeratorView>,
category::*,
comment_view::*,
moderator_views::*,
- post_view::*,
user::*,
- views::{community_view::CommunityView, site_view::SiteView, user_view::UserViewSafe},
+ views::{
+ community_view::CommunityView,
+ post_view::PostView,
+ site_view::SiteView,
+ user_view::UserViewSafe,
+ },
};
use serde::{Deserialize, Serialize};
use lemmy_db::{
comment_view::{CommentView, ReplyView},
- post_view::PostView,
private_message_view::PrivateMessageView,
user_mention_view::UserMentionView,
views::{
community_follower_view::CommunityFollowerView,
community_moderator_view::CommunityModeratorView,
+ post_view::PostView,
user_view::{UserViewDangerous, UserViewSafe},
},
};
pub fn send_post(
&self,
user_operation: &UserOperation,
- post: &PostResponse,
+ post_res: &PostResponse,
websocket_id: Option<ConnectionId>,
) -> Result<(), LemmyError> {
- let community_id = post.post.community_id;
+ let community_id = post_res.post_view.community.id;
// Don't send my data with it
- let mut post_sent = post.clone();
- post_sent.post.my_vote = None;
- post_sent.post.user_id = None;
+ // TODO no idea what to do here
+ // let mut post_sent = post_res.clone();
+ // post_sent.post.my_vote = None;
+ // post_sent.post.user_id = None;
// Send it to /c/all and that community
- self.send_community_room_message(user_operation, &post_sent, 0, websocket_id)?;
- self.send_community_room_message(user_operation, &post_sent, community_id, websocket_id)?;
+ self.send_community_room_message(user_operation, &post_res, 0, websocket_id)?;
+ self.send_community_room_message(user_operation, &post_res, community_id, websocket_id)?;
// Send it to the post room
- self.send_post_room_message(user_operation, &post_sent, post.post.id, websocket_id)?;
+ self.send_post_room_message(
+ user_operation,
+ &post_res,
+ post_res.post_view.post.id,
+ websocket_id,
+ )?;
Ok(())
}
use lemmy_db::{
comment_view::{ReplyQueryBuilder, ReplyView},
community::Community,
- post_view::{PostQueryBuilder, PostView},
user::User_,
user_mention_view::{UserMentionQueryBuilder, UserMentionView},
- views::site_view::SiteView,
+ views::{
+ post_view::{PostQueryBuilder, PostView},
+ site_view::SiteView,
+ },
ListingType,
SortType,
};
let listing_type_ = listing_type.clone();
let posts = blocking(context.pool(), move |conn| {
- PostQueryBuilder::create(&conn)
+ PostQueryBuilder::create(&conn, None)
.listing_type(&listing_type_)
.sort(&sort_type)
.list()
let user = User_::find_by_username(&conn, &user_name)?;
let user_url = user.get_profile_url(&Settings::get().hostname);
- let posts = PostQueryBuilder::create(&conn)
+ let posts = PostQueryBuilder::create(&conn, None)
.listing_type(&ListingType::All)
.sort(sort_type)
.for_creator_id(user.id)
let site_view = SiteView::read(&conn)?;
let community = Community::read_from_name(&conn, &community_name)?;
- let posts = PostQueryBuilder::create(&conn)
+ let posts = PostQueryBuilder::create(&conn, None)
.listing_type(&ListingType::All)
.sort(sort_type)
.for_community_id(community.id)
let site_view = SiteView::read(&conn)?;
let user_id = Claims::decode(&jwt)?.claims.id;
- let posts = PostQueryBuilder::create(&conn)
+ let posts = PostQueryBuilder::create(&conn, Some(user_id))
.listing_type(&ListingType::Subscribed)
.sort(sort_type)
- .my_user_id(user_id)
.list()?;
let items = create_post_items(posts)?;
let mut i = ItemBuilder::default();
let mut dc_extension = DublinCoreExtensionBuilder::default();
- i.title(p.name);
+ i.title(p.post.name);
- dc_extension.creators(vec![p.creator_actor_id.to_owned()]);
+ dc_extension.creators(vec![p.creator.actor_id.to_owned()]);
- let dt = DateTime::<Utc>::from_utc(p.published, Utc);
+ let dt = DateTime::<Utc>::from_utc(p.post.published, Utc);
i.pub_date(dt.to_rfc2822());
let post_url = format!(
"{}/post/{}",
Settings::get().get_protocol_and_hostname(),
- p.id
+ p.post.id
);
i.comments(post_url.to_owned());
let guid = GuidBuilder::default()
let community_url = format!(
"{}/c/{}",
Settings::get().get_protocol_and_hostname(),
- p.community_name
+ p.community.name
);
// TODO: for category we should just put the name of the category, but then we would have
// to read each community from the db
- if let Some(url) = p.url {
+ if let Some(url) = p.post.url {
i.link(url);
}
// TODO add images
let mut description = format!("submitted by <a href=\"{}\">{}</a> to <a href=\"{}\">{}</a><br>{} points | <a href=\"{}\">{} comments</a>",
- p.creator_actor_id,
- p.creator_name,
+ p.creator.actor_id,
+ p.creator.name,
community_url,
- p.community_name,
- p.score,
+ p.community.name,
+ p.counts.score,
post_url,
- p.number_of_comments);
+ p.counts.comments);
- if let Some(body) = p.body {
+ if let Some(body) = p.post.body {
let html = markdown_to_html(&body);
description.push_str(&html);
}