nekrochan/src/web/actions/user_post_actions.rs

136 řádky
3.6 KiB
Rust

use actix_web::{post, web::Data, HttpRequest, HttpResponse};
use pwhash::bcrypt::verify;
use serde::Deserialize;
use std::fmt::Write;
use crate::{
ctx::Ctx,
db::models::{Ban, Board},
error::NekrochanError,
qsform::QsForm,
web::{
actions::{get_posts_from_ids, ActionTemplate},
ban_response,
tcx::{ip_from_req, TemplateCtx},
template_response,
},
};
#[derive(Deserialize)]
pub struct UserPostActionsForm {
#[serde(default)]
pub posts: Vec<String>,
pub remove_posts: Option<String>,
pub remove_files: Option<String>,
pub toggle_spoiler: Option<String>,
#[serde(rename = "post_password")]
pub password: String,
}
#[post("/actions/user-post-actions")]
pub async fn user_post_actions(
ctx: Data<Ctx>,
req: HttpRequest,
QsForm(form): QsForm<UserPostActionsForm>,
) -> Result<HttpResponse, NekrochanError> {
let tcx = TemplateCtx::new(&ctx, &req).await?;
let (ip, _) = ip_from_req(&req)?;
let bans = Ban::read_by_ip(&ctx, ip).await?;
if let Some(ban) = bans.get(&None) {
if !(tcx.perms.owner() || tcx.perms.bypass_bans()) {
return ban_response(&ctx, &req, ban.clone()).await;
}
}
let posts = get_posts_from_ids(&ctx, &form.posts).await;
let boards = Board::read_all_map(&ctx).await?;
let mut response = String::new();
let mut posts_removed = 0;
let mut files_removed = 0;
let mut spoilers_toggled = 0;
for post in &posts {
let board = &boards[&post.board];
if bans.contains_key(&Some(board.id.clone()))
&& !(tcx.perms.owner() || tcx.perms.bypass_bans())
{
writeln!(&mut response, "[Chyba] Jsi zabanován z /{}/.", board.id).ok();
continue;
}
if board.config.0.locked && !(tcx.perms.owner() || tcx.perms.bypass_board_lock()) {
writeln!(
&mut response,
"[Chyba] {}",
NekrochanError::BoardLockError(board.id.clone())
)
.ok();
continue;
}
if !verify(&form.password, &post.password) {
writeln!(
&mut response,
"[Chyba] {}",
NekrochanError::IncorrectPasswordError(post.id)
)
.ok();
continue;
}
if form.remove_posts.is_some() {
post.delete(&ctx).await?;
posts_removed += 1;
}
if form.remove_files.is_some() {
if (post.thread.is_none() && board.config.0.require_thread_file)
|| (post.thread.is_some() && board.config.0.require_reply_file)
{
writeln!(&mut response, "[Chyba] Soubor je na tomto místě potřebný.").ok();
} else {
post.delete_files(&ctx).await?;
files_removed += post.files.0.len();
}
}
if form.toggle_spoiler.is_some() {
post.update_spoiler(&ctx).await?;
spoilers_toggled += post.files.0.len();
}
}
if posts_removed != 0 {
writeln!(
&mut response,
"[Úspěch] Odstraněny příspěvky: {posts_removed}"
)
.ok();
}
if files_removed != 0 {
writeln!(
&mut response,
"[Úspěch] Odstraněny soubory: {files_removed}"
)
.ok();
}
if spoilers_toggled != 0 {
writeln!(
&mut response,
"[Úspěch] Přepnuty spoilery: {spoilers_toggled}"
)
.ok();
}
let template = ActionTemplate { tcx, response };
template_response(&template)
}