add: profile and full search
This commit is contained in:
parent
b8b0ef7f21
commit
3e4ee8126a
52 changed files with 897 additions and 484 deletions
|
@ -196,6 +196,21 @@ pub struct StripeConfig {
|
|||
pub billing_portal_url: String,
|
||||
}
|
||||
|
||||
/// Manuals config (search help, etc)
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct ManualsConfig {
|
||||
/// The page shown for help with search syntax.
|
||||
pub search_help: String,
|
||||
}
|
||||
|
||||
impl Default for ManualsConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
search_help: "".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration file
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct Config {
|
||||
|
@ -259,6 +274,9 @@ pub struct Config {
|
|||
pub html_footer_path: String,
|
||||
#[serde(default)]
|
||||
pub stripe: Option<StripeConfig>,
|
||||
/// The relative paths to manuals.
|
||||
#[serde(default)]
|
||||
pub manuals: ManualsConfig,
|
||||
}
|
||||
|
||||
fn default_name() -> String {
|
||||
|
@ -307,12 +325,15 @@ fn default_banned_usernames() -> Vec<String> {
|
|||
"moderator".to_string(),
|
||||
"api".to_string(),
|
||||
"communities".to_string(),
|
||||
"community".to_string(),
|
||||
"notifs".to_string(),
|
||||
"notification".to_string(),
|
||||
"post".to_string(),
|
||||
"void".to_string(),
|
||||
"anonymous".to_string(),
|
||||
"stacks".to_string(),
|
||||
"stack".to_string(),
|
||||
"search".to_string(),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -328,6 +349,10 @@ fn default_connections() -> ConnectionsConfig {
|
|||
ConnectionsConfig::default()
|
||||
}
|
||||
|
||||
fn default_manuals() -> ManualsConfig {
|
||||
ManualsConfig::default()
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
@ -348,6 +373,7 @@ impl Default for Config {
|
|||
connections: default_connections(),
|
||||
html_footer_path: String::new(),
|
||||
stripe: None,
|
||||
manuals: default_manuals(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,5 +13,6 @@ CREATE TABLE IF NOT EXISTS posts (
|
|||
comment_count INT NOT NULL,
|
||||
-- ...
|
||||
uploads TEXT NOT NULL,
|
||||
is_deleted INT NOT NULL
|
||||
is_deleted INT NOT NULL,
|
||||
tsvector_content tsvector GENERATED ALWAYS AS (to_tsvector ('english', coalesce(content, ''))) STORED
|
||||
)
|
||||
|
|
|
@ -52,6 +52,37 @@ macro_rules! private_post_replying {
|
|||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
($post:ident, $replying_posts:ident, id=$user_id:ident, $data:ident) => {
|
||||
// post owner is not following us
|
||||
// check if we're the owner of the post the post is replying to
|
||||
// all routes but 1 must lead to continue
|
||||
if let Some(replying) = $post.replying_to {
|
||||
if replying != 0 {
|
||||
if let Some(post) = $replying_posts.get(&replying) {
|
||||
// we've seen this post before
|
||||
if post.owner != $user_id {
|
||||
// we aren't the owner of this post,
|
||||
// so we can't see their comment
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// we haven't seen this post before
|
||||
let post = $data.get_post_by_id(replying).await?;
|
||||
|
||||
if post.owner != $user_id {
|
||||
continue;
|
||||
}
|
||||
|
||||
$replying_posts.insert(post.id, post);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl DataManager {
|
||||
|
@ -317,6 +348,7 @@ impl DataManager {
|
|||
|
||||
let mut seen_before: HashMap<(usize, usize), (User, Community)> = HashMap::new();
|
||||
let mut seen_user_follow_statuses: HashMap<(usize, usize), bool> = HashMap::new();
|
||||
let mut replying_posts: HashMap<usize, Post> = HashMap::new();
|
||||
|
||||
for post in posts {
|
||||
if post.is_deleted {
|
||||
|
@ -355,9 +387,8 @@ impl DataManager {
|
|||
if user_id != ua.id {
|
||||
if let Some(is_following) = seen_user_follow_statuses.get(&(ua.id, user_id))
|
||||
{
|
||||
if !is_following && (ua.id != user_id) {
|
||||
// post owner is not following us
|
||||
continue;
|
||||
if !is_following {
|
||||
private_post_replying!(post, replying_posts, id = user_id, self);
|
||||
}
|
||||
} else {
|
||||
if self
|
||||
|
@ -367,7 +398,7 @@ impl DataManager {
|
|||
{
|
||||
// post owner is not following us
|
||||
seen_user_follow_statuses.insert((ua.id, user_id), false);
|
||||
continue;
|
||||
private_post_replying!(post, replying_posts, id = user_id, self);
|
||||
}
|
||||
|
||||
seen_user_follow_statuses.insert((ua.id, user_id), true);
|
||||
|
@ -428,9 +459,9 @@ impl DataManager {
|
|||
let res = query_rows!(
|
||||
&conn,
|
||||
&format!(
|
||||
"SELECT * FROM posts WHERE owner = $1 AND replying_to = 0 AND NOT context LIKE '%\"is_profile_pinned\":true%' {} ORDER BY created DESC LIMIT $2 OFFSET $3",
|
||||
"SELECT * FROM posts WHERE owner = $1 AND replying_to = 0 AND NOT (context::json->>'is_profile_pinned')::boolean {} ORDER BY created DESC LIMIT $2 OFFSET $3",
|
||||
if hide_nsfw {
|
||||
"AND NOT context LIKE '%\"is_nsfw\":true%'"
|
||||
"AND NOT (context::json->>'is_nsfw')::boolean"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
@ -446,6 +477,101 @@ impl DataManager {
|
|||
Ok(res.unwrap())
|
||||
}
|
||||
|
||||
/// Get all posts from the given user (searched).
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `id` - the ID of the user the requested posts belong to
|
||||
/// * `batch` - the limit of posts in each page
|
||||
/// * `page` - the page number
|
||||
/// * `text_query` - the search query
|
||||
/// * `user` - the user who is viewing the posts
|
||||
pub async fn get_posts_by_user_searched(
|
||||
&self,
|
||||
id: usize,
|
||||
batch: usize,
|
||||
page: usize,
|
||||
text_query: &str,
|
||||
user: &Option<&User>,
|
||||
) -> Result<Vec<Post>> {
|
||||
let other_user = self.get_user_by_id(id).await?;
|
||||
|
||||
let conn = match self.connect().await {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
|
||||
};
|
||||
|
||||
// check if we should hide nsfw posts
|
||||
let mut hide_nsfw: bool = true;
|
||||
|
||||
if let Some(ua) = user {
|
||||
if ua.id == other_user.id {
|
||||
hide_nsfw = false
|
||||
}
|
||||
}
|
||||
|
||||
if other_user.settings.private_profile {
|
||||
hide_nsfw = false;
|
||||
}
|
||||
|
||||
// ...
|
||||
let res = query_rows!(
|
||||
&conn,
|
||||
&format!(
|
||||
"SELECT * FROM posts WHERE owner = $1 AND tsvector_content @@ to_tsquery($2) AND replying_to = 0 AND NOT (context::json->>'is_profile_pinned')::boolean {} ORDER BY created DESC LIMIT $3 OFFSET $4",
|
||||
if hide_nsfw {
|
||||
"AND NOT (context::json->>'is_nsfw')::boolean"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
),
|
||||
params![
|
||||
&(id as i64),
|
||||
&text_query,
|
||||
&(batch as i64),
|
||||
&((page * batch) as i64)
|
||||
],
|
||||
|x| { Self::get_post_from_row(x) }
|
||||
);
|
||||
|
||||
if res.is_err() {
|
||||
return Err(Error::GeneralNotFound("post".to_string()));
|
||||
}
|
||||
|
||||
Ok(res.unwrap())
|
||||
}
|
||||
|
||||
/// Get all post (searched).
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `batch` - the limit of posts in each page
|
||||
/// * `page` - the page number
|
||||
/// * `text_query` - the search query
|
||||
pub async fn get_posts_searched(
|
||||
&self,
|
||||
batch: usize,
|
||||
page: usize,
|
||||
text_query: &str,
|
||||
) -> Result<Vec<Post>> {
|
||||
let conn = match self.connect().await {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
|
||||
};
|
||||
|
||||
// ...
|
||||
let res = query_rows!(
|
||||
&conn,
|
||||
"SELECT * FROM posts WHERE tsvector_content @@ to_tsquery($1) AND replying_to = 0 AND NOT (context::json->>'is_profile_pinned')::boolean ORDER BY created DESC LIMIT $2 OFFSET $3",
|
||||
params![&text_query, &(batch as i64), &((page * batch) as i64)],
|
||||
|x| { Self::get_post_from_row(x) }
|
||||
);
|
||||
|
||||
if res.is_err() {
|
||||
return Err(Error::GeneralNotFound("post".to_string()));
|
||||
}
|
||||
|
||||
Ok(res.unwrap())
|
||||
}
|
||||
|
||||
/// Get all posts from the given user with the given tag (from most recent).
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -487,7 +613,7 @@ impl DataManager {
|
|||
&format!(
|
||||
"SELECT * FROM posts WHERE owner = $1 AND context::json->>'tags' LIKE $2 {} ORDER BY created DESC LIMIT $3 OFFSET $4",
|
||||
if hide_nsfw {
|
||||
"AND NOT context LIKE '%\"is_nsfw\":true%'"
|
||||
"AND NOT (context::json->>'is_nsfw')::boolean"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue