steps:
- - name: chown repo
+ - name: prepare repo
image: ekidd/rust-musl-builder:1.50.0
user: root
commands:
- chown 1000:1000 . -R
+ - git fetch --tags
- name: check formatting
image: rustdocker/rust:nightly
RUST_TEST_THREADS: 1
commands:
- sudo apt-get update
- - sudo apt-get -y install --no-install-recommends espeak postgresql-client
+ - sudo apt-get -y install --no-install-recommends postgresql-client
- cargo test --workspace --no-fail-fast
- name: cargo build
steps:
+ - name: prepare repo
+ image: rust:1.50-slim-buster
+ user: root
+ commands:
+ - chown 1000:1000 . -R
+ - apt update
+ - apt install --no-install-recommends --yes git
+ - git fetch --tags
+
- name: cargo test
image: rust:1.50-slim-buster
environment:
RUST_TEST_THREADS: 1
commands:
- apt-get update
- - apt-get -y install --no-install-recommends espeak postgresql-client libssl-dev pkg-config libpq-dev
+ - apt-get -y install --no-install-recommends postgresql-client libssl-dev pkg-config libpq-dev
- cargo test --workspace --no-fail-fast
- cargo build
}
// Remove/Restore their data if that's desired
- if data.remove_data {
+ if data.remove_data.unwrap_or(false) {
// Posts
blocking(context.pool(), move |conn: &'_ _| {
Post::update_removed_for_creator(conn, banned_person_id, Some(community_id), true)
use lemmy_db_queries::{
diesel_option_overwrite,
diesel_option_overwrite_to_url,
+ from_opt_str_to_opt_enum,
source::{
comment::Comment_,
local_user::LocalUser_,
LemmyContext,
UserOperation,
};
-use std::str::FromStr;
#[async_trait::async_trait(?Send)]
impl Perform for Login {
}
// Remove their data if that's desired
- if data.remove_data {
+ if data.remove_data.unwrap_or(false) {
// Posts
blocking(context.pool(), move |conn: &'_ _| {
Post::update_removed_for_creator(conn, banned_person_id, None, true)
let data: &GetReplies = &self;
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
- let sort = SortType::from_str(&data.sort)?;
+ let sort: Option<SortType> = from_opt_str_to_opt_enum(&data.sort);
let page = data.page;
let limit = data.limit;
let replies = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn)
- .sort(&sort)
+ .sort(sort)
.unread_only(unread_only)
.recipient_id(person_id)
.show_bot_accounts(show_bot_accounts)
let data: &GetPersonMentions = &self;
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
- let sort = SortType::from_str(&data.sort)?;
+ let sort: Option<SortType> = from_opt_str_to_opt_enum(&data.sort);
let page = data.page;
let limit = data.limit;
PersonMentionQueryBuilder::create(conn)
.recipient_id(person_id)
.my_person_id(person_id)
- .sort(&sort)
+ .sort(sort)
.unread_only(unread_only)
.page(page)
.limit(limit)
get_local_user_view_from_jwt_opt,
is_admin,
site::*,
- user_show_bot_accounts,
- user_show_nsfw,
- user_show_read_posts,
};
use lemmy_apub::fetcher::search::search_by_apub_id;
-use lemmy_db_queries::{source::site::Site_, Crud, SearchType, SortType};
+use lemmy_db_queries::{
+ from_opt_str_to_opt_enum,
+ source::site::Site_,
+ Crud,
+ ListingType,
+ SearchType,
+ SortType,
+};
use lemmy_db_schema::source::{moderator::*, site::Site};
use lemmy_db_views::{
comment_view::CommentQueryBuilder,
};
use lemmy_websocket::LemmyContext;
use log::debug;
-use std::str::FromStr;
#[async_trait::async_trait(?Send)]
impl Perform for GetModlog {
let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
- let show_nsfw = user_show_nsfw(&local_user_view);
- let show_bot_accounts = user_show_bot_accounts(&local_user_view);
- let show_read_posts = user_show_read_posts(&local_user_view);
+ let show_nsfw = local_user_view.as_ref().map(|t| t.local_user.show_nsfw);
+ let show_bot_accounts = local_user_view
+ .as_ref()
+ .map(|t| t.local_user.show_bot_accounts);
+ let show_read_posts = local_user_view
+ .as_ref()
+ .map(|t| t.local_user.show_read_posts);
let person_id = local_user_view.map(|u| u.person.id);
- let type_ = SearchType::from_str(&data.type_)?;
-
let mut posts = Vec::new();
let mut comments = Vec::new();
let mut communities = Vec::new();
let q = data.q.to_owned();
let page = data.page;
let limit = data.limit;
- let sort = SortType::from_str(&data.sort)?;
+ let sort: Option<SortType> = from_opt_str_to_opt_enum(&data.sort);
+ let listing_type: Option<ListingType> = from_opt_str_to_opt_enum(&data.listing_type);
+ let search_type: SearchType = from_opt_str_to_opt_enum(&data.type_).unwrap_or(SearchType::All);
let community_id = data.community_id;
let community_name = data.community_name.to_owned();
- match type_ {
+ let creator_id = data.creator_id;
+ match search_type {
SearchType::Posts => {
posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn)
- .sort(&sort)
+ .sort(sort)
.show_nsfw(show_nsfw)
.show_bot_accounts(show_bot_accounts)
.show_read_posts(show_read_posts)
+ .listing_type(listing_type)
.community_id(community_id)
.community_name(community_name)
+ .creator_id(creator_id)
.my_person_id(person_id)
.search_term(q)
.page(page)
SearchType::Comments => {
comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(&conn)
- .sort(&sort)
+ .sort(sort)
+ .listing_type(listing_type)
.search_term(q)
.show_bot_accounts(show_bot_accounts)
+ .community_id(community_id)
+ .community_name(community_name)
+ .creator_id(creator_id)
.my_person_id(person_id)
.page(page)
.limit(limit)
SearchType::Communities => {
communities = blocking(context.pool(), move |conn| {
CommunityQueryBuilder::create(conn)
- .sort(&sort)
+ .sort(sort)
+ .listing_type(listing_type)
.search_term(q)
.my_person_id(person_id)
.page(page)
SearchType::Users => {
users = blocking(context.pool(), move |conn| {
PersonQueryBuilder::create(conn)
- .sort(&sort)
+ .sort(sort)
.search_term(q)
.page(page)
.limit(limit)
.await??;
}
SearchType::All => {
+ // If the community or creator is included, dont search communities or users
+ let community_or_creator_included =
+ data.community_id.is_some() || data.community_name.is_some() || data.creator_id.is_some();
+
posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn)
- .sort(&sort)
+ .sort(sort)
.show_nsfw(show_nsfw)
.show_bot_accounts(show_bot_accounts)
.show_read_posts(show_read_posts)
+ .listing_type(listing_type)
.community_id(community_id)
.community_name(community_name)
+ .creator_id(creator_id)
.my_person_id(person_id)
.search_term(q)
.page(page)
.await??;
let q = data.q.to_owned();
- let sort = SortType::from_str(&data.sort)?;
+ let community_name = data.community_name.to_owned();
comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn)
- .sort(&sort)
+ .sort(sort)
+ .listing_type(listing_type)
.search_term(q)
.show_bot_accounts(show_bot_accounts)
+ .community_id(community_id)
+ .community_name(community_name)
+ .creator_id(creator_id)
.my_person_id(person_id)
.page(page)
.limit(limit)
.await??;
let q = data.q.to_owned();
- let sort = SortType::from_str(&data.sort)?;
- communities = blocking(context.pool(), move |conn| {
- CommunityQueryBuilder::create(conn)
- .sort(&sort)
- .search_term(q)
- .my_person_id(person_id)
- .page(page)
- .limit(limit)
- .list()
- })
- .await??;
+ communities = if community_or_creator_included {
+ vec![]
+ } else {
+ blocking(context.pool(), move |conn| {
+ CommunityQueryBuilder::create(conn)
+ .sort(sort)
+ .listing_type(listing_type)
+ .search_term(q)
+ .my_person_id(person_id)
+ .page(page)
+ .limit(limit)
+ .list()
+ })
+ .await??
+ };
let q = data.q.to_owned();
- let sort = SortType::from_str(&data.sort)?;
- users = blocking(context.pool(), move |conn| {
- PersonQueryBuilder::create(conn)
- .sort(&sort)
- .search_term(q)
- .page(page)
- .limit(limit)
- .list()
- })
- .await??;
+ users = if community_or_creator_included {
+ vec![]
+ } else {
+ blocking(context.pool(), move |conn| {
+ PersonQueryBuilder::create(conn)
+ .sort(sort)
+ .search_term(q)
+ .page(page)
+ .limit(limit)
+ .list()
+ })
+ .await??
+ };
}
SearchType::Url => {
posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn)
- .sort(&sort)
+ .sort(sort)
.show_nsfw(show_nsfw)
.show_bot_accounts(show_bot_accounts)
.show_read_posts(show_read_posts)
+ .listing_type(listing_type)
.my_person_id(person_id)
.community_id(community_id)
.community_name(community_name)
+ .creator_id(creator_id)
.url_search(q)
.page(page)
.limit(limit)
// Return the jwt
Ok(SearchResponse {
- type_: data.type_.to_owned(),
+ type_: search_type.to_string(),
comments,
posts,
communities,
#[derive(Deserialize)]
pub struct CreateComment {
pub content: String,
- pub parent_id: Option<CommentId>,
pub post_id: PostId,
+ pub parent_id: Option<CommentId>,
pub form_id: Option<String>,
pub auth: String,
}
#[derive(Deserialize)]
pub struct GetComments {
- pub type_: String,
- pub sort: String,
+ pub type_: Option<String>,
+ pub sort: Option<String>,
pub page: Option<i64>,
pub limit: Option<i64>,
pub community_id: Option<CommunityId>,
pub community_name: Option<String>,
- pub saved_only: bool,
+ pub saved_only: Option<bool>,
pub auth: Option<String>,
}
#[derive(Deserialize, Debug)]
pub struct ListCommunities {
- pub type_: String,
- pub sort: String,
+ pub type_: Option<String>,
+ pub sort: Option<String>,
pub page: Option<i64>,
pub limit: Option<i64>,
pub auth: Option<String>,
pub community_id: CommunityId,
pub person_id: PersonId,
pub ban: bool,
- pub remove_data: bool,
+ pub remove_data: Option<bool>,
pub reason: Option<String>,
pub expires: Option<i64>,
pub auth: String,
#[derive(Deserialize)]
pub struct EditCommunity {
pub community_id: CommunityId,
- pub title: String,
+ pub title: Option<String>,
pub description: Option<String>,
pub icon: Option<String>,
pub banner: Option<String>,
Ok(())
}
-/// A helper method for showing the bot account
-pub fn user_show_bot_accounts(local_user_view: &Option<LocalUserView>) -> bool {
- match local_user_view {
- Some(uv) => uv.to_owned().local_user.show_bot_accounts,
- None => true,
- }
-}
-
-/// A helper method for showing nsfw
-pub fn user_show_nsfw(local_user_view: &Option<LocalUserView>) -> bool {
- match &local_user_view {
- Some(uv) => uv.local_user.show_nsfw,
- None => false,
- }
-}
-
-/// A helper method for showing read posts
-pub fn user_show_read_posts(local_user_view: &Option<LocalUserView>) -> bool {
- match local_user_view {
- Some(uv) => uv.to_owned().local_user.show_read_posts,
- None => true,
- }
-}
-
pub async fn get_post(post_id: PostId, pool: &DbPool) -> Result<Post, LemmyError> {
blocking(pool, move |conn| Post::read(conn, post_id))
.await?
#[derive(Deserialize)]
pub struct Register {
pub username: String,
- pub email: Option<String>,
pub password: String,
pub password_verify: String,
pub show_nsfw: bool,
+ pub email: Option<String>,
pub captcha_uuid: Option<String>,
pub captcha_answer: Option<String>,
}
#[derive(Deserialize)]
pub struct GetPersonDetails {
- pub person_id: Option<PersonId>,
+ pub person_id: Option<PersonId>, // One of these two are required
pub username: Option<String>,
- pub sort: String,
+ pub sort: Option<String>,
pub page: Option<i64>,
pub limit: Option<i64>,
pub community_id: Option<CommunityId>,
- pub saved_only: bool,
+ pub saved_only: Option<bool>,
pub auth: Option<String>,
}
pub struct BanPerson {
pub person_id: PersonId,
pub ban: bool,
- pub remove_data: bool,
+ pub remove_data: Option<bool>,
pub reason: Option<String>,
pub expires: Option<i64>,
pub auth: String,
#[derive(Deserialize)]
pub struct GetReplies {
- pub sort: String,
+ pub sort: Option<String>,
pub page: Option<i64>,
pub limit: Option<i64>,
- pub unread_only: bool,
+ pub unread_only: Option<bool>,
pub auth: String,
}
#[derive(Deserialize)]
pub struct GetPersonMentions {
- pub sort: String,
+ pub sort: Option<String>,
pub page: Option<i64>,
pub limit: Option<i64>,
- pub unread_only: bool,
+ pub unread_only: Option<bool>,
pub auth: String,
}
#[derive(Deserialize)]
pub struct GetPrivateMessages {
- pub unread_only: bool,
+ pub unread_only: Option<bool>,
pub page: Option<i64>,
pub limit: Option<i64>,
pub auth: String,
#[derive(Deserialize, Debug)]
pub struct CreatePost {
pub name: String,
+ pub community_id: CommunityId,
pub url: Option<Url>,
pub body: Option<String>,
- pub nsfw: bool,
- pub community_id: CommunityId,
+ pub nsfw: Option<bool>,
pub auth: String,
}
#[derive(Deserialize, Debug)]
pub struct GetPosts {
- pub type_: String,
- pub sort: String,
+ pub type_: Option<String>,
+ pub sort: Option<String>,
pub page: Option<i64>,
pub limit: Option<i64>,
pub community_id: Option<CommunityId>,
pub community_name: Option<String>,
- pub saved_only: bool,
+ pub saved_only: Option<bool>,
pub auth: Option<String>,
}
#[derive(Deserialize)]
pub struct EditPost {
pub post_id: PostId,
- pub name: String,
+ pub name: Option<String>,
pub url: Option<Url>,
pub body: Option<String>,
- pub nsfw: bool,
+ pub nsfw: Option<bool>,
pub auth: String,
}
#[derive(Deserialize, Debug)]
pub struct Search {
pub q: String,
- pub type_: String,
pub community_id: Option<CommunityId>,
pub community_name: Option<String>,
- pub sort: String,
+ pub creator_id: Option<PersonId>,
+ pub type_: Option<String>,
+ pub sort: Option<String>,
+ pub listing_type: Option<String>,
pub page: Option<i64>,
pub limit: Option<i64>,
pub auth: Option<String>,
pub description: Option<String>,
pub icon: Option<String>,
pub banner: Option<String>,
- pub enable_downvotes: bool,
- pub open_registration: bool,
- pub enable_nsfw: bool,
- pub community_creation_admin_only: bool,
+ pub enable_downvotes: Option<bool>,
+ pub open_registration: Option<bool>,
+ pub enable_nsfw: Option<bool>,
+ pub community_creation_admin_only: Option<bool>,
pub auth: String,
}
#[derive(Deserialize)]
pub struct EditSite {
- pub name: String,
+ pub name: Option<String>,
pub sidebar: Option<String>,
pub description: Option<String>,
pub icon: Option<String>,
pub banner: Option<String>,
- pub enable_downvotes: bool,
- pub open_registration: bool,
- pub enable_nsfw: bool,
+ pub enable_downvotes: Option<bool>,
+ pub open_registration: Option<bool>,
+ pub enable_nsfw: Option<bool>,
pub community_creation_admin_only: Option<bool>,
pub auth: String,
}
use crate::PerformCrud;
use actix_web::web::Data;
-use lemmy_api_common::{
- blocking,
- comment::*,
- get_local_user_view_from_jwt_opt,
- user_show_bot_accounts,
-};
-use lemmy_db_queries::{ListingType, SortType};
+use lemmy_api_common::{blocking, comment::*, get_local_user_view_from_jwt_opt};
+use lemmy_db_queries::{from_opt_str_to_opt_enum, ListingType, SortType};
use lemmy_db_views::comment_view::CommentQueryBuilder;
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;
-use std::str::FromStr;
#[async_trait::async_trait(?Send)]
impl PerformCrud for GetComments {
let data: &GetComments = &self;
let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
- let show_bot_accounts = user_show_bot_accounts(&local_user_view);
+ let show_bot_accounts = local_user_view
+ .as_ref()
+ .map(|t| t.local_user.show_bot_accounts);
let person_id = local_user_view.map(|u| u.person.id);
- let type_ = ListingType::from_str(&data.type_)?;
- let sort = SortType::from_str(&data.sort)?;
+ let sort: Option<SortType> = from_opt_str_to_opt_enum(&data.sort);
+ let listing_type: Option<ListingType> = from_opt_str_to_opt_enum(&data.type_);
let community_id = data.community_id;
let community_name = data.community_name.to_owned();
let limit = data.limit;
let comments = blocking(context.pool(), move |conn| {
CommentQueryBuilder::create(conn)
- .listing_type(type_)
- .sort(&sort)
+ .listing_type(listing_type)
+ .sort(sort)
.saved_only(saved_only)
.community_id(community_id)
.community_name(community_name)
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt_opt};
-use lemmy_db_queries::{source::community::Community_, ListingType, SortType};
+use lemmy_db_queries::{
+ from_opt_str_to_opt_enum,
+ source::community::Community_,
+ ListingType,
+ SortType,
+};
use lemmy_db_schema::source::community::*;
use lemmy_db_views_actor::{
community_moderator_view::CommunityModeratorView,
};
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
use lemmy_websocket::{messages::GetCommunityUsersOnline, LemmyContext};
-use std::str::FromStr;
#[async_trait::async_trait(?Send)]
impl PerformCrud for GetCommunity {
None => false,
};
- let type_ = ListingType::from_str(&data.type_)?;
- let sort = SortType::from_str(&data.sort)?;
+ let sort: Option<SortType> = from_opt_str_to_opt_enum(&data.sort);
+ let listing_type: Option<ListingType> = from_opt_str_to_opt_enum(&data.type_);
let page = data.page;
let limit = data.limit;
let communities = blocking(context.pool(), move |conn| {
CommunityQueryBuilder::create(conn)
- .listing_type(&type_)
- .sort(&sort)
+ .listing_type(listing_type)
+ .sort(sort)
.show_nsfw(show_nsfw)
.my_person_id(person_id)
.page(page)
community_moderator_view::CommunityModeratorView,
community_view::CommunityView,
};
-use lemmy_utils::{
- utils::{check_slurs, check_slurs_opt},
- ApiError,
- ConnectionId,
- LemmyError,
-};
+use lemmy_utils::{utils::check_slurs_opt, ApiError, ConnectionId, LemmyError};
use lemmy_websocket::{LemmyContext, UserOperationCrud};
#[async_trait::async_trait(?Send)]
let data: &EditCommunity = &self;
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
- check_slurs(&data.title)?;
+ check_slurs_opt(&data.title)?;
check_slurs_opt(&data.description)?;
// Verify its a mod (only mods can edit it)
let community_form = CommunityForm {
name: read_community.name,
- title: data.title.to_owned(),
+ title: data.title.to_owned().unwrap_or(read_community.title),
description: data.description.to_owned(),
icon,
banner,
use crate::PerformCrud;
use actix_web::web::Data;
-use lemmy_api_common::{
- blocking,
- get_local_user_view_from_jwt_opt,
- mark_post_as_read,
- post::*,
- user_show_bot_accounts,
- user_show_nsfw,
- user_show_read_posts,
-};
-use lemmy_db_queries::{ListingType, SortType};
+use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, mark_post_as_read, post::*};
+use lemmy_db_queries::{from_opt_str_to_opt_enum, ListingType, SortType};
use lemmy_db_views::{
comment_view::CommentQueryBuilder,
post_view::{PostQueryBuilder, PostView},
};
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
use lemmy_websocket::{messages::GetPostUsersOnline, LemmyContext};
-use std::str::FromStr;
#[async_trait::async_trait(?Send)]
impl PerformCrud for GetPost {
let data: &GetPost = &self;
let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
- let show_bot_accounts = user_show_bot_accounts(&local_user_view);
-
+ let show_bot_accounts = local_user_view
+ .as_ref()
+ .map(|t| t.local_user.show_bot_accounts);
let person_id = local_user_view.map(|u| u.person.id);
let id = data.id;
let person_id = local_user_view.to_owned().map(|l| l.person.id);
- let show_nsfw = user_show_nsfw(&local_user_view);
- let show_bot_accounts = user_show_bot_accounts(&local_user_view);
- let show_read_posts = user_show_read_posts(&local_user_view);
+ let show_nsfw = local_user_view.as_ref().map(|t| t.local_user.show_nsfw);
+ let show_bot_accounts = local_user_view
+ .as_ref()
+ .map(|t| t.local_user.show_bot_accounts);
+ let show_read_posts = local_user_view
+ .as_ref()
+ .map(|t| t.local_user.show_read_posts);
- let type_ = ListingType::from_str(&data.type_)?;
- let sort = SortType::from_str(&data.sort)?;
+ let sort: Option<SortType> = from_opt_str_to_opt_enum(&data.sort);
+ let listing_type: Option<ListingType> = from_opt_str_to_opt_enum(&data.type_);
let page = data.page;
let limit = data.limit;
let posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(conn)
- .listing_type(&type_)
- .sort(&sort)
+ .listing_type(listing_type)
+ .sort(sort)
.show_nsfw(show_nsfw)
.show_bot_accounts(show_bot_accounts)
.show_read_posts(show_read_posts)
use lemmy_db_views::post_view::PostView;
use lemmy_utils::{
request::fetch_iframely_and_pictrs_data,
- utils::{check_slurs, check_slurs_opt, is_valid_post_title},
+ utils::{check_slurs_opt, is_valid_post_title},
ApiError,
ConnectionId,
LemmyError,
let data: &EditPost = &self;
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
- check_slurs(&data.name)?;
+ check_slurs_opt(&data.name)?;
check_slurs_opt(&data.body)?;
- if !is_valid_post_title(&data.name) {
- return Err(ApiError::err("invalid_post_title").into());
+ if let Some(name) = &data.name {
+ if !is_valid_post_title(name) {
+ return Err(ApiError::err("invalid_post_title").into());
+ }
}
let post_id = data.post_id;
let post_form = PostForm {
creator_id: orig_post.creator_id.to_owned(),
community_id: orig_post.community_id,
- name: data.name.trim().to_owned(),
+ name: data.name.to_owned().unwrap_or(orig_post.name),
url: data_url.map(|u| u.to_owned().into()),
body: data.body.to_owned(),
nsfw: data.nsfw,
open_registration: data.open_registration,
enable_nsfw: data.enable_nsfw,
updated: None,
- community_creation_admin_only: Some(data.community_creation_admin_only),
+ community_creation_admin_only: data.community_creation_admin_only,
};
let create_site = move |conn: &'_ _| Site::create(conn, &site_form);
description: None,
icon: None,
banner: None,
- enable_downvotes: true,
- open_registration: true,
- enable_nsfw: true,
+ enable_downvotes: None,
+ open_registration: None,
+ enable_nsfw: None,
auth: login_response.jwt,
- community_creation_admin_only: false,
+ community_creation_admin_only: None,
};
create_site.perform(context, websocket_id).await?;
info!("Site {} created", setup.site_name);
source::site::{Site, SiteForm},
};
use lemmy_db_views::site_view::SiteView;
-use lemmy_utils::{
- utils::{check_slurs, check_slurs_opt},
- ApiError,
- ConnectionId,
- LemmyError,
-};
+use lemmy_utils::{utils::check_slurs_opt, ApiError, ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendAllMessage, LemmyContext, UserOperationCrud};
#[async_trait::async_trait(?Send)]
let data: &EditSite = &self;
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
- check_slurs(&data.name)?;
+ check_slurs_opt(&data.name)?;
check_slurs_opt(&data.description)?;
// Make sure user is an admin
}
let site_form = SiteForm {
- name: data.name.to_owned(),
+ creator_id: found_site.creator_id,
+ name: data.name.to_owned().unwrap_or(found_site.name),
sidebar,
description,
icon,
banner,
- creator_id: found_site.creator_id,
updated: Some(naive_now()),
enable_downvotes: data.enable_downvotes,
open_registration: data.open_registration,
use crate::PerformCrud;
use actix_web::web::Data;
-use lemmy_api_common::{
- blocking,
- get_local_user_view_from_jwt_opt,
- person::*,
- user_show_bot_accounts,
- user_show_nsfw,
- user_show_read_posts,
-};
-use lemmy_db_queries::{source::person::Person_, SortType};
+use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, person::*};
+use lemmy_db_queries::{from_opt_str_to_opt_enum, source::person::Person_, SortType};
use lemmy_db_schema::source::person::*;
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder};
use lemmy_db_views_actor::{
};
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;
-use std::str::FromStr;
#[async_trait::async_trait(?Send)]
impl PerformCrud for GetPersonDetails {
let data: &GetPersonDetails = &self;
let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
- let show_nsfw = user_show_nsfw(&local_user_view);
- let show_bot_accounts = user_show_bot_accounts(&local_user_view);
- let show_read_posts = user_show_read_posts(&local_user_view);
+ let show_nsfw = local_user_view.as_ref().map(|t| t.local_user.show_nsfw);
+ let show_bot_accounts = local_user_view
+ .as_ref()
+ .map(|t| t.local_user.show_bot_accounts);
+ let show_read_posts = local_user_view
+ .as_ref()
+ .map(|t| t.local_user.show_read_posts);
- let sort = SortType::from_str(&data.sort)?;
+ let sort: Option<SortType> = from_opt_str_to_opt_enum(&data.sort);
let username = data
.username
let (posts, comments) = blocking(context.pool(), move |conn| {
let mut posts_query = PostQueryBuilder::create(conn)
- .sort(&sort)
+ .sort(sort)
.show_nsfw(show_nsfw)
.show_bot_accounts(show_bot_accounts)
.show_read_posts(show_read_posts)
let mut comments_query = CommentQueryBuilder::create(conn)
.my_person_id(person_id)
.show_bot_accounts(show_bot_accounts)
- .sort(&sort)
+ .sort(sort)
.saved_only(saved_only)
.community_id(community_id)
.page(page)
// If its saved only, you don't care what creator it was
// Or, if its not saved, then you only want it for that specific creator
- if !saved_only {
+ if !saved_only.unwrap_or(false) {
posts_query = posts_query.creator_id(person_details_id);
comments_query = comments_query.creator_id(person_details_id);
}
.as_ref()
.map(|u| u.to_owned().naive_local()),
deleted: None,
- nsfw: ext.sensitive.unwrap_or(false),
- stickied: ext.stickied.or(Some(false)),
+ nsfw: ext.sensitive,
+ stickied: ext.stickied,
embed_title: iframely_title,
embed_description: iframely_description,
embed_html: iframely_html,
let site_form = SiteForm {
name: "test_site".into(),
+ creator_id: inserted_person.id,
sidebar: None,
description: None,
icon: None,
banner: None,
- creator_id: inserted_person.id,
- enable_downvotes: true,
- open_registration: true,
- enable_nsfw: true,
+ enable_downvotes: None,
+ open_registration: None,
+ enable_nsfw: None,
updated: None,
community_creation_admin_only: Some(false),
};
env::var("LEMMY_DATABASE_URL")
}
-#[derive(EnumString, ToString, Debug, Serialize, Deserialize)]
+#[derive(EnumString, ToString, Debug, Serialize, Deserialize, Clone, Copy)]
pub enum SortType {
Active,
Hot,
NewComments,
}
-#[derive(EnumString, ToString, Debug, Serialize, Deserialize, Clone)]
+#[derive(EnumString, ToString, Debug, Serialize, Deserialize, Clone, Copy)]
pub enum ListingType {
All,
Local,
Community,
}
-#[derive(EnumString, ToString, Debug, Serialize, Deserialize)]
+#[derive(EnumString, ToString, Debug, Serialize, Deserialize, Clone, Copy)]
pub enum SearchType {
All,
Comments,
Url,
}
+pub fn from_opt_str_to_opt_enum<T: std::str::FromStr>(opt: &Option<String>) -> Option<T> {
+ opt.as_ref().map(|t| T::from_str(t).ok()).flatten()
+}
+
pub fn fuzzy_search(q: &str) -> String {
let replaced = q.replace(" ", "%");
format!("%{}%", replaced)
pub name: String,
pub creator_id: PersonId,
pub community_id: CommunityId,
- pub nsfw: bool,
+ pub nsfw: Option<bool>,
pub url: Option<DbUrl>,
pub body: Option<String>,
pub removed: Option<bool>,
#[table_name = "site"]
pub struct SiteForm {
pub name: String,
- pub sidebar: Option<Option<String>>,
pub creator_id: PersonId,
+ pub sidebar: Option<Option<String>>,
pub updated: Option<chrono::NaiveDateTime>,
- pub enable_downvotes: bool,
- pub open_registration: bool,
- pub enable_nsfw: bool,
+ pub enable_downvotes: Option<bool>,
+ pub open_registration: Option<bool>,
+ pub enable_nsfw: Option<bool>,
// when you want to null out a column, you have to send Some(None)), since sending None means you just don't want to update that column.
pub icon: Option<Option<DbUrl>>,
pub banner: Option<Option<DbUrl>>,
pub struct CommentQueryBuilder<'a> {
conn: &'a PgConnection,
- listing_type: ListingType,
- sort: &'a SortType,
+ listing_type: Option<ListingType>,
+ sort: Option<SortType>,
community_id: Option<CommunityId>,
community_name: Option<String>,
post_id: Option<PostId>,
recipient_id: Option<PersonId>,
my_person_id: Option<PersonId>,
search_term: Option<String>,
- saved_only: bool,
- unread_only: bool,
- show_bot_accounts: bool,
+ saved_only: Option<bool>,
+ unread_only: Option<bool>,
+ show_bot_accounts: Option<bool>,
page: Option<i64>,
limit: Option<i64>,
}
pub fn create(conn: &'a PgConnection) -> Self {
CommentQueryBuilder {
conn,
- listing_type: ListingType::All,
- sort: &SortType::New,
+ listing_type: None,
+ sort: None,
community_id: None,
community_name: None,
post_id: None,
recipient_id: None,
my_person_id: None,
search_term: None,
- saved_only: false,
- unread_only: false,
- show_bot_accounts: true,
+ saved_only: None,
+ unread_only: None,
+ show_bot_accounts: None,
page: None,
limit: None,
}
}
- pub fn listing_type(mut self, listing_type: ListingType) -> Self {
- self.listing_type = listing_type;
+ pub fn listing_type<T: MaybeOptional<ListingType>>(mut self, listing_type: T) -> Self {
+ self.listing_type = listing_type.get_optional();
self
}
- pub fn sort(mut self, sort: &'a SortType) -> Self {
- self.sort = sort;
+ pub fn sort<T: MaybeOptional<SortType>>(mut self, sort: T) -> Self {
+ self.sort = sort.get_optional();
self
}
self
}
- pub fn saved_only(mut self, saved_only: bool) -> Self {
- self.saved_only = saved_only;
+ pub fn saved_only<T: MaybeOptional<bool>>(mut self, saved_only: T) -> Self {
+ self.saved_only = saved_only.get_optional();
self
}
- pub fn unread_only(mut self, unread_only: bool) -> Self {
- self.unread_only = unread_only;
+ pub fn unread_only<T: MaybeOptional<bool>>(mut self, unread_only: T) -> Self {
+ self.unread_only = unread_only.get_optional();
self
}
- pub fn show_bot_accounts(mut self, show_bot_accounts: bool) -> Self {
- self.show_bot_accounts = show_bot_accounts;
+ pub fn show_bot_accounts<T: MaybeOptional<bool>>(mut self, show_bot_accounts: T) -> Self {
+ self.show_bot_accounts = show_bot_accounts.get_optional();
self
}
.filter(comment::removed.eq(false));
}
- if self.unread_only {
+ if self.unread_only.unwrap_or(false) {
query = query.filter(comment::read.eq(false));
}
query = query.filter(comment::content.ilike(fuzzy_search(&search_term)));
};
- query = match self.listing_type {
- // ListingType::Subscribed => query.filter(community_follower::subscribed.eq(true)),
- ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)),
- ListingType::Local => query.filter(community::local.eq(true)),
- _ => query,
- };
+ if let Some(listing_type) = self.listing_type {
+ query = match listing_type {
+ ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)),
+ ListingType::Local => query.filter(community::local.eq(true)),
+ _ => query,
+ };
+ }
- if self.saved_only {
+ if self.saved_only.unwrap_or(false) {
query = query.filter(comment_saved::id.is_not_null());
}
- if !self.show_bot_accounts {
+ if !self.show_bot_accounts.unwrap_or(true) {
query = query.filter(person::bot_account.eq(false));
};
- query = match self.sort {
+ query = match self.sort.unwrap_or(SortType::New) {
SortType::Hot | SortType::Active => query
.order_by(hot_rank(comment_aggregates::score, comment_aggregates::published).desc())
.then_order_by(comment_aggregates::published.desc()),
pub struct PostQueryBuilder<'a> {
conn: &'a PgConnection,
- listing_type: &'a ListingType,
- sort: &'a SortType,
+ listing_type: Option<ListingType>,
+ sort: Option<SortType>,
creator_id: Option<PersonId>,
community_id: Option<CommunityId>,
community_name: Option<String>,
my_person_id: Option<PersonId>,
search_term: Option<String>,
url_search: Option<String>,
- show_nsfw: bool,
- show_bot_accounts: bool,
- show_read_posts: bool,
- saved_only: bool,
+ show_nsfw: Option<bool>,
+ show_bot_accounts: Option<bool>,
+ show_read_posts: Option<bool>,
+ saved_only: Option<bool>,
page: Option<i64>,
limit: Option<i64>,
}
pub fn create(conn: &'a PgConnection) -> Self {
PostQueryBuilder {
conn,
- listing_type: &ListingType::All,
- sort: &SortType::Hot,
+ listing_type: None,
+ sort: None,
creator_id: None,
community_id: None,
community_name: None,
my_person_id: None,
search_term: None,
url_search: None,
- show_nsfw: true,
- show_bot_accounts: true,
- show_read_posts: true,
- saved_only: false,
+ show_nsfw: None,
+ show_bot_accounts: None,
+ show_read_posts: None,
+ saved_only: None,
page: None,
limit: None,
}
}
- pub fn listing_type(mut self, listing_type: &'a ListingType) -> Self {
- self.listing_type = listing_type;
+ pub fn listing_type<T: MaybeOptional<ListingType>>(mut self, listing_type: T) -> Self {
+ self.listing_type = listing_type.get_optional();
self
}
- pub fn sort(mut self, sort: &'a SortType) -> Self {
- self.sort = sort;
+ pub fn sort<T: MaybeOptional<SortType>>(mut self, sort: T) -> Self {
+ self.sort = sort.get_optional();
self
}
self
}
- pub fn show_nsfw(mut self, show_nsfw: bool) -> Self {
- self.show_nsfw = show_nsfw;
+ pub fn show_nsfw<T: MaybeOptional<bool>>(mut self, show_nsfw: T) -> Self {
+ self.show_nsfw = show_nsfw.get_optional();
self
}
- pub fn show_bot_accounts(mut self, show_bot_accounts: bool) -> Self {
- self.show_bot_accounts = show_bot_accounts;
+ pub fn show_bot_accounts<T: MaybeOptional<bool>>(mut self, show_bot_accounts: T) -> Self {
+ self.show_bot_accounts = show_bot_accounts.get_optional();
self
}
- pub fn show_read_posts(mut self, show_read_posts: bool) -> Self {
- self.show_read_posts = show_read_posts;
+ pub fn show_read_posts<T: MaybeOptional<bool>>(mut self, show_read_posts: T) -> Self {
+ self.show_read_posts = show_read_posts.get_optional();
self
}
- pub fn saved_only(mut self, saved_only: bool) -> Self {
- self.saved_only = saved_only;
+ pub fn saved_only<T: MaybeOptional<bool>>(mut self, saved_only: T) -> Self {
+ self.saved_only = saved_only.get_optional();
self
}
))
.into_boxed();
- query = match self.listing_type {
- ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)),
- ListingType::Local => query.filter(community::local.eq(true)),
- _ => query,
- };
+ if let Some(listing_type) = self.listing_type {
+ query = match listing_type {
+ ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()),
+ ListingType::Local => query.filter(community::local.eq(true)),
+ _ => query,
+ };
+ }
if let Some(community_id) = self.community_id {
query = query
query = query.filter(post::creator_id.eq(creator_id));
}
- if !self.show_nsfw {
+ if !self.show_nsfw.unwrap_or(true) {
query = query
.filter(post::nsfw.eq(false))
.filter(community::nsfw.eq(false));
};
- if !self.show_bot_accounts {
+ if !self.show_bot_accounts.unwrap_or(true) {
query = query.filter(person::bot_account.eq(false));
};
- if self.saved_only {
- query = query.filter(post_saved::id.is_not_null());
+ if !self.show_read_posts.unwrap_or(true) {
+ query = query.filter(post_read::id.is_null());
};
- if !self.show_read_posts {
- query = query.filter(post_read::id.is_null());
+ if self.saved_only.unwrap_or(false) {
+ query = query.filter(post_saved::id.is_not_null());
};
- query = match self.sort {
+ query = match self.sort.unwrap_or(SortType::Hot) {
SortType::Active => query
.then_order_by(
hot_rank(
};
let read_post_listings_with_person = PostQueryBuilder::create(&conn)
- .listing_type(&ListingType::Community)
- .sort(&SortType::New)
+ .listing_type(ListingType::Community)
+ .sort(SortType::New)
.show_bot_accounts(false)
.community_id(inserted_community.id)
.my_person_id(inserted_person.id)
.unwrap();
let read_post_listings_no_person = PostQueryBuilder::create(&conn)
- .listing_type(&ListingType::Community)
- .sort(&SortType::New)
+ .listing_type(ListingType::Community)
+ .sort(SortType::New)
.community_id(inserted_community.id)
.list()
.unwrap();
pub struct PrivateMessageQueryBuilder<'a> {
conn: &'a PgConnection,
recipient_id: PersonId,
- unread_only: bool,
+ unread_only: Option<bool>,
page: Option<i64>,
limit: Option<i64>,
}
PrivateMessageQueryBuilder {
conn,
recipient_id,
- unread_only: false,
+ unread_only: None,
page: None,
limit: None,
}
}
- pub fn unread_only(mut self, unread_only: bool) -> Self {
- self.unread_only = unread_only;
+ pub fn unread_only<T: MaybeOptional<bool>>(mut self, unread_only: T) -> Self {
+ self.unread_only = unread_only.get_optional();
self
}
.into_boxed();
// If its unread, I only want the ones to me
- if self.unread_only {
+ if self.unread_only.unwrap_or(false) {
query = query
.filter(private_message::read.eq(false))
.filter(private_message::recipient_id.eq(self.recipient_id));
pub struct CommunityQueryBuilder<'a> {
conn: &'a PgConnection,
- listing_type: &'a ListingType,
- sort: &'a SortType,
+ listing_type: Option<ListingType>,
+ sort: Option<SortType>,
my_person_id: Option<PersonId>,
- show_nsfw: bool,
+ show_nsfw: Option<bool>,
search_term: Option<String>,
page: Option<i64>,
limit: Option<i64>,
CommunityQueryBuilder {
conn,
my_person_id: None,
- listing_type: &ListingType::All,
- sort: &SortType::Hot,
- show_nsfw: true,
+ listing_type: None,
+ sort: None,
+ show_nsfw: None,
search_term: None,
page: None,
limit: None,
}
}
- pub fn listing_type(mut self, listing_type: &'a ListingType) -> Self {
- self.listing_type = listing_type;
+ pub fn listing_type<T: MaybeOptional<ListingType>>(mut self, listing_type: T) -> Self {
+ self.listing_type = listing_type.get_optional();
self
}
- pub fn sort(mut self, sort: &'a SortType) -> Self {
- self.sort = sort;
+ pub fn sort<T: MaybeOptional<SortType>>(mut self, sort: T) -> Self {
+ self.sort = sort.get_optional();
self
}
- pub fn show_nsfw(mut self, show_nsfw: bool) -> Self {
- self.show_nsfw = show_nsfw;
+ pub fn show_nsfw<T: MaybeOptional<bool>>(mut self, show_nsfw: T) -> Self {
+ self.show_nsfw = show_nsfw.get_optional();
self
}
.or_filter(community::description.ilike(searcher));
};
- match self.sort {
+ match self.sort.unwrap_or(SortType::Hot) {
SortType::New => query = query.order_by(community::published.desc()),
SortType::TopAll => query = query.order_by(community_aggregates::subscribers.desc()),
SortType::TopMonth => query = query.order_by(community_aggregates::users_active_month.desc()),
}
};
- if !self.show_nsfw {
+ if !self.show_nsfw.unwrap_or(true) {
query = query.filter(community::nsfw.eq(false));
};
- query = match self.listing_type {
- ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)),
- ListingType::Local => query.filter(community::local.eq(true)),
- _ => query,
- };
+ if let Some(listing_type) = self.listing_type {
+ query = match listing_type {
+ ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)),
+ ListingType::Local => query.filter(community::local.eq(true)),
+ _ => query,
+ };
+ }
let (limit, offset) = limit_and_offset(self.page, self.limit);
let res = query
conn: &'a PgConnection,
my_person_id: Option<PersonId>,
recipient_id: Option<PersonId>,
- sort: &'a SortType,
- unread_only: bool,
+ sort: Option<SortType>,
+ unread_only: Option<bool>,
page: Option<i64>,
limit: Option<i64>,
}
conn,
my_person_id: None,
recipient_id: None,
- sort: &SortType::New,
- unread_only: false,
+ sort: None,
+ unread_only: None,
page: None,
limit: None,
}
}
- pub fn sort(mut self, sort: &'a SortType) -> Self {
- self.sort = sort;
+ pub fn sort<T: MaybeOptional<SortType>>(mut self, sort: T) -> Self {
+ self.sort = sort.get_optional();
self
}
- pub fn unread_only(mut self, unread_only: bool) -> Self {
- self.unread_only = unread_only;
+ pub fn unread_only<T: MaybeOptional<bool>>(mut self, unread_only: T) -> Self {
+ self.unread_only = unread_only.get_optional();
self
}
query = query.filter(person_mention::recipient_id.eq(recipient_id));
}
- if self.unread_only {
+ if self.unread_only.unwrap_or(false) {
query = query.filter(person_mention::read.eq(false));
}
- query = match self.sort {
+ query = match self.sort.unwrap_or(SortType::Hot) {
SortType::Hot | SortType::Active => query
.order_by(hot_rank(comment_aggregates::score, comment_aggregates::published).desc())
.then_order_by(comment_aggregates::published.desc()),
pub struct PersonQueryBuilder<'a> {
conn: &'a PgConnection,
- sort: &'a SortType,
+ sort: Option<SortType>,
search_term: Option<String>,
page: Option<i64>,
limit: Option<i64>,
PersonQueryBuilder {
conn,
search_term: None,
- sort: &SortType::Hot,
+ sort: None,
page: None,
limit: None,
}
}
- pub fn sort(mut self, sort: &'a SortType) -> Self {
- self.sort = sort;
+ pub fn sort<T: MaybeOptional<SortType>>(mut self, sort: T) -> Self {
+ self.sort = sort.get_optional();
self
}
query = query.filter(person::name.ilike(fuzzy_search(&search_term)));
}
- query = match self.sort {
+ query = match self.sort.unwrap_or(SortType::Hot) {
SortType::Hot => query
.order_by(person_aggregates::comment_score.desc())
.then_order_by(person::published.desc()),
) -> Result<HttpResponse, LemmyError> {
let site_view = blocking(context.pool(), move |conn| SiteView::read(&conn)).await??;
- let listing_type_ = listing_type.clone();
let posts = blocking(context.pool(), move |conn| {
PostQueryBuilder::create(&conn)
- .listing_type(&listing_type_)
- .sort(&sort_type)
+ .listing_type(listing_type)
+ .sort(sort_type)
.list()
})
.await??;
let person = Person::find_by_name(&conn, &user_name)?;
let posts = PostQueryBuilder::create(&conn)
- .listing_type(&ListingType::All)
- .sort(sort_type)
+ .listing_type(ListingType::All)
+ .sort(*sort_type)
.creator_id(person.id)
.list()?;
let community = Community::read_from_name(&conn, &community_name)?;
let posts = PostQueryBuilder::create(&conn)
- .listing_type(&ListingType::All)
- .sort(sort_type)
+ .listing_type(ListingType::All)
+ .sort(*sort_type)
.community_id(community.id)
.list()?;
let show_read_posts = local_user.show_read_posts;
let posts = PostQueryBuilder::create(&conn)
- .listing_type(&ListingType::Subscribed)
+ .listing_type(ListingType::Subscribed)
.my_person_id(person_id)
.show_bot_accounts(show_bot_accounts)
.show_read_posts(show_read_posts)
- .sort(sort_type)
+ .sort(*sort_type)
.list()?;
let items = create_post_items(posts)?;
.recipient_id(person_id)
.my_person_id(person_id)
.show_bot_accounts(show_bot_accounts)
- .sort(&sort)
+ .sort(sort)
.list()?;
let mentions = PersonMentionQueryBuilder::create(&conn)
.recipient_id(person_id)
.my_person_id(person_id)
- .sort(&sort)
+ .sort(sort)
.list()?;
let items = create_reply_and_mention_items(replies, mentions)?;