add: ability to generate invite codes in bulk add: better mark as nsfw
ui
This commit is contained in:
parent
2a77c61bf2
commit
4843688fcf
13 changed files with 126 additions and 90 deletions
|
@ -168,7 +168,7 @@ version = "1.0.0"
|
||||||
"settings:label.export" = "Export"
|
"settings:label.export" = "Export"
|
||||||
"settings:label.manage_blocks" = "Manage blocks"
|
"settings:label.manage_blocks" = "Manage blocks"
|
||||||
"settings:label.users" = "Users"
|
"settings:label.users" = "Users"
|
||||||
"settings:label.generate_invite" = "Generate invite"
|
"settings:label.generate_invites" = "Generate invites"
|
||||||
"settings:label.add_to_stack" = "Add to stack"
|
"settings:label.add_to_stack" = "Add to stack"
|
||||||
"settings:tab.security" = "Security"
|
"settings:tab.security" = "Security"
|
||||||
"settings:tab.blocks" = "Blocks"
|
"settings:tab.blocks" = "Blocks"
|
||||||
|
|
|
@ -218,7 +218,7 @@ pre {
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
padding: var(--pad-1);
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre,
|
pre,
|
||||||
|
|
|
@ -139,7 +139,7 @@
|
||||||
("id" "files_list")
|
("id" "files_list")
|
||||||
("class" "flex gap-2 flex-wrap"))
|
("class" "flex gap-2 flex-wrap"))
|
||||||
(div
|
(div
|
||||||
("class" "flex justify-between gap-2")
|
("class" "flex justify-between flex-collapse gap-2")
|
||||||
(text "{{ components::create_post_options() }}")
|
(text "{{ components::create_post_options() }}")
|
||||||
(div
|
(div
|
||||||
("class" "flex gap-2")
|
("class" "flex gap-2")
|
||||||
|
|
|
@ -1399,7 +1399,7 @@
|
||||||
|
|
||||||
(text "{%- endif %} {%- endmacro %} {% macro create_post_options() -%}")
|
(text "{%- endif %} {%- endmacro %} {% macro create_post_options() -%}")
|
||||||
(div
|
(div
|
||||||
("class" "flex gap-2")
|
("class" "flex gap-2 flex-wrap")
|
||||||
(text "{{ components::emoji_picker(element_id=\"content\", render_dialog=true) }} {% if not quoting -%} {% if is_supporter -%} {{ components::file_picker(files_list_id=\"files_list\") }} {%- endif %} {%- endif %}")
|
(text "{{ components::emoji_picker(element_id=\"content\", render_dialog=true) }} {% if not quoting -%} {% if is_supporter -%} {{ components::file_picker(files_list_id=\"files_list\") }} {%- endif %} {%- endif %}")
|
||||||
|
|
||||||
(button
|
(button
|
||||||
|
@ -1414,7 +1414,20 @@
|
||||||
("title" "More options")
|
("title" "More options")
|
||||||
("onclick" "document.getElementById('post_options_dialog').showModal()")
|
("onclick" "document.getElementById('post_options_dialog').showModal()")
|
||||||
("type" "button")
|
("type" "button")
|
||||||
(text "{{ icon \"ellipsis\" }}")))
|
(text "{{ icon \"ellipsis\" }}"))
|
||||||
|
|
||||||
|
(label
|
||||||
|
("class" "flex items-center gap-1 button lowered")
|
||||||
|
("title" "Mark as NSFW/hide from public timelines")
|
||||||
|
("for" "is_nsfw")
|
||||||
|
(input
|
||||||
|
("type" "checkbox")
|
||||||
|
("name" "is_nsfw")
|
||||||
|
("id" "is_nsfw")
|
||||||
|
("checked" "{{ user.settings.auto_unlist }}")
|
||||||
|
("onchange" "POST_INITIAL_SETTINGS['is_nsfw'] = event.target.checked"))
|
||||||
|
|
||||||
|
(span (icon (text "eye-closed")))))
|
||||||
|
|
||||||
(dialog
|
(dialog
|
||||||
("id" "post_options_dialog")
|
("id" "post_options_dialog")
|
||||||
|
@ -1474,11 +1487,11 @@
|
||||||
window.POST_INITIAL_SETTINGS.reactions_enabled.toString(),
|
window.POST_INITIAL_SETTINGS.reactions_enabled.toString(),
|
||||||
\"checkbox\",
|
\"checkbox\",
|
||||||
],
|
],
|
||||||
[
|
// [
|
||||||
[\"is_nsfw\", \"Hide from public timelines\"],
|
// [\"is_nsfw\", \"Hide from public timelines\"],
|
||||||
window.POST_INITIAL_SETTINGS.is_nsfw.toString(),
|
// window.POST_INITIAL_SETTINGS.is_nsfw.toString(),
|
||||||
\"checkbox\",
|
// \"checkbox\",
|
||||||
],
|
// ],
|
||||||
[
|
[
|
||||||
[\"content_warning\", \"Content warning\"],
|
[\"content_warning\", \"Content warning\"],
|
||||||
window.POST_INITIAL_SETTINGS.content_warning,
|
window.POST_INITIAL_SETTINGS.content_warning,
|
||||||
|
|
|
@ -113,21 +113,24 @@
|
||||||
("id" "files_list")
|
("id" "files_list")
|
||||||
("class" "flex gap-2 flex-wrap"))
|
("class" "flex gap-2 flex-wrap"))
|
||||||
(div
|
(div
|
||||||
("class" "flex flex-wrap w-full gap-2")
|
("class" "flex w-full justify-between flex-collapse gap-2")
|
||||||
(text "{{ components::create_post_options() }}")
|
(div
|
||||||
|
("class" "flex flex-wrap w-full gap-2")
|
||||||
|
(text "{{ components::create_post_options() }}")
|
||||||
|
(button
|
||||||
|
("type" "button")
|
||||||
|
("class" "red lowered")
|
||||||
|
("onclick" "trigger('me::remove_question', ['{{ question[0].id }}'])")
|
||||||
|
(text "{{ text \"general:action.delete\" }}"))
|
||||||
|
(button
|
||||||
|
("type" "button")
|
||||||
|
("class" "red lowered")
|
||||||
|
("onclick" "trigger('me::ip_block_question', ['{{ question[0].id }}'])")
|
||||||
|
(text "{{ text \"auth:action.ip_block\" }}")))
|
||||||
|
|
||||||
(button
|
(button
|
||||||
("class" "primary")
|
("class" "primary")
|
||||||
(text "{{ text \"requests:label.answer\" }}"))
|
(text "{{ text \"requests:label.answer\" }}")))))
|
||||||
(button
|
|
||||||
("type" "button")
|
|
||||||
("class" "red lowered")
|
|
||||||
("onclick" "trigger('me::remove_question', ['{{ question[0].id }}'])")
|
|
||||||
(text "{{ text \"general:action.delete\" }}"))
|
|
||||||
(button
|
|
||||||
("type" "button")
|
|
||||||
("class" "red lowered")
|
|
||||||
("onclick" "trigger('me::ip_block_question', ['{{ question[0].id }}'])")
|
|
||||||
(text "{{ text \"auth:action.ip_block\" }}")))))
|
|
||||||
(text "{% endfor %}")))
|
(text "{% endfor %}")))
|
||||||
|
|
||||||
(text "{{ components::pagination(page=page, items=requests|length, key=\"&id=\", value=profile.id) }}"))
|
(text "{{ components::pagination(page=page, items=requests|length, key=\"&id=\", value=profile.id) }}"))
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
(text "{% if config.security.enable_invite_codes -%}")
|
(text "{% if config.security.enable_invite_codes -%}")
|
||||||
(a
|
(a
|
||||||
("data-tab-button" "account/invites")
|
("data-tab-button" "account/invites")
|
||||||
("href" "#/account/invites")
|
("href" "?page=0#/account/invites")
|
||||||
(text "{{ icon \"ticket\" }}")
|
(text "{{ icon \"ticket\" }}")
|
||||||
(span
|
(span
|
||||||
(text "{{ text \"settings:tab.invites\" }}")))
|
(text "{{ text \"settings:tab.invites\" }}")))
|
||||||
|
@ -538,10 +538,12 @@
|
||||||
(text "{{ text \"settings:tab.invites\" }}")))
|
(text "{{ text \"settings:tab.invites\" }}")))
|
||||||
(div
|
(div
|
||||||
("class" "card flex flex-col gap-2 secondary")
|
("class" "card flex flex-col gap-2 secondary")
|
||||||
|
(pre ("id" "invite_codes_output") ("class" "hidden") (code))
|
||||||
|
|
||||||
(button
|
(button
|
||||||
("onclick" "generate_invite_code()")
|
("onclick" "generate_invite_codes()")
|
||||||
(icon (text "plus"))
|
(icon (text "plus"))
|
||||||
(str (text "settings:label.generate_invite")))
|
(str (text "settings:label.generate_invites")))
|
||||||
|
|
||||||
(text "{{ components::supporter_ad(body=\"Become a supporter to generate up to 48 invite codes! You can currently have 2 maximum.\") }} {% for code in invites %}")
|
(text "{{ components::supporter_ad(body=\"Become a supporter to generate up to 48 invite codes! You can currently have 2 maximum.\") }} {% for code in invites %}")
|
||||||
(div
|
(div
|
||||||
|
@ -555,8 +557,10 @@
|
||||||
(b (text "{{ code[1].code }}"))
|
(b (text "{{ code[1].code }}"))
|
||||||
(text "{%- endif %}"))
|
(text "{%- endif %}"))
|
||||||
(text "{% endfor %}")
|
(text "{% endfor %}")
|
||||||
|
(text "{{ components::pagination(page=page, items=invites|length, key=\"#/account/invites\") }}")
|
||||||
(script
|
(script
|
||||||
(text "globalThis.generate_invite_code = async () => {
|
(text "globalThis.generate_invite_codes = async () => {
|
||||||
|
await trigger(\"atto::debounce\", [\"invites::create\"]);
|
||||||
if (
|
if (
|
||||||
!(await trigger(\"atto::confirm\", [
|
!(await trigger(\"atto::confirm\", [
|
||||||
\"Are you sure you would like to do this? This action is permanent.\",
|
\"Are you sure you would like to do this? This action is permanent.\",
|
||||||
|
@ -565,7 +569,16 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(`/api/v1/invite`, {
|
const count = Number.parseInt(await trigger(\"atto::prompt\", [\"Count (1-48):\"]));
|
||||||
|
|
||||||
|
if (!count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById(\"invite_codes_output\").classList.remove(\"hidden\");
|
||||||
|
document.getElementById(\"invite_codes_output\").children[0].innerText = \"Working...\";
|
||||||
|
|
||||||
|
fetch(`/api/v1/invites/${count}`, {
|
||||||
method: \"POST\",
|
method: \"POST\",
|
||||||
})
|
})
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
|
@ -576,7 +589,7 @@
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
alert(res.payload);
|
document.getElementById(\"invite_codes_output\").children[0].innerText = res.payload;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};"))))))
|
};"))))))
|
||||||
|
|
|
@ -832,8 +832,9 @@ pub async fn refresh_grant_request(
|
||||||
/// Generate an invite code.
|
/// Generate an invite code.
|
||||||
///
|
///
|
||||||
/// Does not support third-party grants.
|
/// Does not support third-party grants.
|
||||||
pub async fn generate_invite_code_request(
|
pub async fn generate_invite_codes_request(
|
||||||
jar: CookieJar,
|
jar: CookieJar,
|
||||||
|
Path(count): Path<usize>,
|
||||||
Extension(data): Extension<State>,
|
Extension(data): Extension<State>,
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
let data = &(data.read().await).0;
|
let data = &(data.read().await).0;
|
||||||
|
@ -846,15 +847,25 @@ pub async fn generate_invite_code_request(
|
||||||
return Json(Error::NotAllowed.into());
|
return Json(Error::NotAllowed.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
match data
|
if count > 48 {
|
||||||
.create_invite_code(InviteCode::new(user.id), &user)
|
return Json(Error::DataTooLong("count".to_string()).into());
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(x) => Json(ApiReturn {
|
|
||||||
ok: true,
|
|
||||||
message: "Code generated".to_string(),
|
|
||||||
payload: Some(x.code),
|
|
||||||
}),
|
|
||||||
Err(e) => Json(e.into()),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut out_string = String::new();
|
||||||
|
|
||||||
|
for _ in 0..count {
|
||||||
|
match data
|
||||||
|
.create_invite_code(InviteCode::new(user.id), &user)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(x) => out_string += &(x.code + "\n"),
|
||||||
|
Err(_) => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Json(ApiReturn {
|
||||||
|
ok: true,
|
||||||
|
message: "Success".to_string(),
|
||||||
|
payload: Some(out_string),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -441,10 +441,7 @@ pub async fn posts_request(
|
||||||
};
|
};
|
||||||
|
|
||||||
check_user_blocked_or_private!(Some(&user), other_user, data, @api);
|
check_user_blocked_or_private!(Some(&user), other_user, data, @api);
|
||||||
match data
|
match data.get_posts_by_user(id, 12, props.page).await {
|
||||||
.get_posts_by_user(id, 12, props.page, &Some(user.clone()))
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(posts) => {
|
Ok(posts) => {
|
||||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||||
Json(ApiReturn {
|
Json(ApiReturn {
|
||||||
|
|
|
@ -37,7 +37,10 @@ pub fn routes() -> Router {
|
||||||
.route("/util/proxy", get(util::proxy_request))
|
.route("/util/proxy", get(util::proxy_request))
|
||||||
.route("/util/lang", get(util::set_langfile_request))
|
.route("/util/lang", get(util::set_langfile_request))
|
||||||
.route("/util/ip", get(util::ip_test_request))
|
.route("/util/ip", get(util::ip_test_request))
|
||||||
.route("/invite", post(auth::profile::generate_invite_code_request))
|
.route(
|
||||||
|
"/invites/{count}",
|
||||||
|
post(auth::profile::generate_invite_codes_request),
|
||||||
|
)
|
||||||
// reactions
|
// reactions
|
||||||
.route("/reactions", post(reactions::create_request))
|
.route("/reactions", post(reactions::create_request))
|
||||||
.route("/reactions/{id}", get(reactions::get_request))
|
.route("/reactions/{id}", get(reactions::get_request))
|
||||||
|
|
|
@ -625,12 +625,10 @@ pub async fn swiss_army_timeline_request(
|
||||||
check_user_blocked_or_private!(user, other_user, data, jar);
|
check_user_blocked_or_private!(user, other_user, data, jar);
|
||||||
|
|
||||||
if req.tag.is_empty() {
|
if req.tag.is_empty() {
|
||||||
data.0
|
data.0.get_posts_by_user(req.user_id, 12, req.page).await
|
||||||
.get_posts_by_user(req.user_id, 12, req.page, &user)
|
|
||||||
.await
|
|
||||||
} else {
|
} else {
|
||||||
data.0
|
data.0
|
||||||
.get_posts_by_user_tag(req.user_id, &req.tag, 12, req.page, &user)
|
.get_posts_by_user_tag(req.user_id, &req.tag, 12, req.page)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -101,7 +101,11 @@ pub async fn settings_request(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let invites = match data.0.get_invite_codes_by_owner(profile.id).await {
|
let invites = match data
|
||||||
|
.0
|
||||||
|
.get_invite_codes_by_owner(profile.id, 12, req.page)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(l) => match data.0.fill_invite_codes(l).await {
|
Ok(l) => match data.0.fill_invite_codes(l).await {
|
||||||
Ok(l) => l,
|
Ok(l) => l,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use oiseau::{cache::Cache, query_rows};
|
use oiseau::{cache::Cache, query_row, query_rows};
|
||||||
use tetratto_shared::unix_epoch_timestamp;
|
use tetratto_shared::unix_epoch_timestamp;
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
Error, Result,
|
Error, Result,
|
||||||
|
@ -24,7 +24,12 @@ impl DataManager {
|
||||||
auto_method!(get_invite_code_by_code(&str)@get_invite_code_from_row -> "SELECT * FROM invite_codes WHERE code = $1" --name="invite_code" --returns=InviteCode);
|
auto_method!(get_invite_code_by_code(&str)@get_invite_code_from_row -> "SELECT * FROM invite_codes WHERE code = $1" --name="invite_code" --returns=InviteCode);
|
||||||
|
|
||||||
/// Get invite_codes by `owner`.
|
/// Get invite_codes by `owner`.
|
||||||
pub async fn get_invite_codes_by_owner(&self, owner: usize) -> Result<Vec<InviteCode>> {
|
pub async fn get_invite_codes_by_owner(
|
||||||
|
&self,
|
||||||
|
owner: usize,
|
||||||
|
batch: usize,
|
||||||
|
page: usize,
|
||||||
|
) -> Result<Vec<InviteCode>> {
|
||||||
let conn = match self.0.connect().await {
|
let conn = match self.0.connect().await {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
|
Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
|
||||||
|
@ -32,8 +37,8 @@ impl DataManager {
|
||||||
|
|
||||||
let res = query_rows!(
|
let res = query_rows!(
|
||||||
&conn,
|
&conn,
|
||||||
"SELECT * FROM invite_codes WHERE owner = $1",
|
"SELECT * FROM invite_codes WHERE owner = $1 ORDER BY created DESC LIMIT $2 OFFSET $3",
|
||||||
&[&(owner as i64)],
|
&[&(owner as i64), &(batch as i64), &((page * batch) as i64)],
|
||||||
|x| { Self::get_invite_code_from_row(x) }
|
|x| { Self::get_invite_code_from_row(x) }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -44,6 +49,27 @@ impl DataManager {
|
||||||
Ok(res.unwrap())
|
Ok(res.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get invite_codes by `owner`.
|
||||||
|
pub async fn get_invite_codes_by_owner_count(&self, owner: usize) -> Result<i32> {
|
||||||
|
let conn = match self.0.connect().await {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
|
||||||
|
};
|
||||||
|
|
||||||
|
let res = query_row!(
|
||||||
|
&conn,
|
||||||
|
"SELECT COUNT(*)::int FROM invite_codes WHERE owner = $1",
|
||||||
|
&[&(owner as i64)],
|
||||||
|
|x| Ok(x.get::<usize, i32>(0))
|
||||||
|
);
|
||||||
|
|
||||||
|
if res.is_err() {
|
||||||
|
return Err(Error::GeneralNotFound("invite_code".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res.unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
/// Fill a vector of invite codes with the user that used them.
|
/// Fill a vector of invite codes with the user that used them.
|
||||||
pub async fn fill_invite_codes(
|
pub async fn fill_invite_codes(
|
||||||
&self,
|
&self,
|
||||||
|
@ -89,7 +115,7 @@ impl DataManager {
|
||||||
|
|
||||||
// our account is old enough, but we need to make sure we don't already have
|
// our account is old enough, but we need to make sure we don't already have
|
||||||
// 2 invite codes
|
// 2 invite codes
|
||||||
if self.get_invite_codes_by_owner(user.id).await?.len()
|
if (self.get_invite_codes_by_owner_count(user.id).await? as usize)
|
||||||
>= Self::MAXIMUM_FREE_INVITE_CODES
|
>= Self::MAXIMUM_FREE_INVITE_CODES
|
||||||
{
|
{
|
||||||
return Err(Error::MiscError(
|
return Err(Error::MiscError(
|
||||||
|
@ -99,7 +125,7 @@ impl DataManager {
|
||||||
}
|
}
|
||||||
} else if !user.permissions.check(FinePermission::MANAGE_USERS) {
|
} else if !user.permissions.check(FinePermission::MANAGE_USERS) {
|
||||||
// check count since we're also not a moderator with MANAGE_USERS
|
// check count since we're also not a moderator with MANAGE_USERS
|
||||||
if self.get_invite_codes_by_owner(user.id).await?.len()
|
if (self.get_invite_codes_by_owner_count(user.id).await? as usize)
|
||||||
>= Self::MAXIMUM_SUPPORTER_INVITE_CODES
|
>= Self::MAXIMUM_SUPPORTER_INVITE_CODES
|
||||||
{
|
{
|
||||||
return Err(Error::MiscError(
|
return Err(Error::MiscError(
|
||||||
|
|
|
@ -689,31 +689,15 @@ impl DataManager {
|
||||||
id: usize,
|
id: usize,
|
||||||
batch: usize,
|
batch: usize,
|
||||||
page: usize,
|
page: usize,
|
||||||
user: &Option<User>,
|
|
||||||
) -> Result<Vec<Post>> {
|
) -> Result<Vec<Post>> {
|
||||||
let conn = match self.0.connect().await {
|
let conn = match self.0.connect().await {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
|
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 {
|
|
||||||
hide_nsfw = !ua.settings.show_nsfw;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...
|
|
||||||
let res = query_rows!(
|
let res = query_rows!(
|
||||||
&conn,
|
&conn,
|
||||||
&format!(
|
"SELECT * FROM posts WHERE owner = $1 AND replying_to = 0 AND NOT (context::json->>'is_profile_pinned')::boolean AND is_deleted = 0 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 AND is_deleted = 0 {} ORDER BY created DESC LIMIT $2 OFFSET $3",
|
|
||||||
if hide_nsfw {
|
|
||||||
"AND NOT (context::json->>'is_nsfw')::boolean"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
),
|
|
||||||
&[&(id as i64), &(batch as i64), &((page * batch) as i64)],
|
&[&(id as i64), &(batch as i64), &((page * batch) as i64)],
|
||||||
|x| { Self::get_post_from_row(x) }
|
|x| { Self::get_post_from_row(x) }
|
||||||
);
|
);
|
||||||
|
@ -1008,31 +992,15 @@ impl DataManager {
|
||||||
tag: &str,
|
tag: &str,
|
||||||
batch: usize,
|
batch: usize,
|
||||||
page: usize,
|
page: usize,
|
||||||
user: &Option<User>,
|
|
||||||
) -> Result<Vec<Post>> {
|
) -> Result<Vec<Post>> {
|
||||||
let conn = match self.0.connect().await {
|
let conn = match self.0.connect().await {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
|
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 {
|
|
||||||
hide_nsfw = !ua.settings.show_nsfw;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...
|
|
||||||
let res = query_rows!(
|
let res = query_rows!(
|
||||||
&conn,
|
&conn,
|
||||||
&format!(
|
"SELECT * FROM posts WHERE owner = $1 AND context::json->>'tags' LIKE $2 AND is_deleted = 0 ORDER BY created DESC LIMIT $3 OFFSET $4",
|
||||||
"SELECT * FROM posts WHERE owner = $1 AND context::json->>'tags' LIKE $2 AND is_deleted = 0 {} ORDER BY created DESC LIMIT $3 OFFSET $4",
|
|
||||||
if hide_nsfw {
|
|
||||||
"AND NOT (context::json->>'is_nsfw')::boolean"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
),
|
|
||||||
params![
|
params![
|
||||||
&(id as i64),
|
&(id as i64),
|
||||||
&format!("%\"{tag}\"%"),
|
&format!("%\"{tag}\"%"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue