feat: set and user custom title
This commit is contained in:
@@ -16,7 +16,7 @@ use std::collections::HashMap;
|
||||
#[derive(FromForm)]
|
||||
pub struct CommentInput {
|
||||
pid: i32,
|
||||
#[field(validate = len(1..4097))]
|
||||
#[field(validate = len(1..12289))]
|
||||
text: String,
|
||||
use_title: Option<i8>,
|
||||
}
|
||||
@@ -118,7 +118,12 @@ pub async fn add_comment(
|
||||
NewComment {
|
||||
content: ci.text.to_string(),
|
||||
author_hash: user.namehash.to_string(),
|
||||
author_title: "".to_string(),
|
||||
author_title: (if ci.use_title.is_some() {
|
||||
CustomTitle::get(&rconn, &user.namehash).await?
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
is_tmp: user.id.is_none(),
|
||||
post_id: ci.pid,
|
||||
},
|
||||
|
||||
@@ -84,6 +84,7 @@ pub enum PolicyError {
|
||||
IsReported,
|
||||
IsDeleted,
|
||||
NotAllowed,
|
||||
TitleUsed,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -112,6 +113,7 @@ impl<'r> Responder<'r, 'static> for APIError {
|
||||
PolicyError::IsReported => "内容被举报,处理中",
|
||||
PolicyError::IsDeleted => "内容被删除",
|
||||
PolicyError::NotAllowed => "不允许的操作",
|
||||
PolicyError::TitleUsed => "头衔已被使用",
|
||||
}
|
||||
})
|
||||
.respond_to(req),
|
||||
|
||||
@@ -47,7 +47,7 @@ pub async fn delete(di: Form<DeleteInput>, user: CurrentUser, db: Db, rconn: Rds
|
||||
|
||||
(p.author_hash.clone(), p)
|
||||
}
|
||||
_ => { Err(NotAllowed) }?,
|
||||
_ => Err(NotAllowed)?,
|
||||
};
|
||||
|
||||
if user.is_admin && !user.namehash.eq(&author_hash) {
|
||||
@@ -128,11 +128,11 @@ pub async fn block(bi: Form<BlockInput>, user: CurrentUser, db: Db, rconn: RdsCo
|
||||
let nh_to_block = match bi.content_type.as_str() {
|
||||
"post" => Post::get(&db, &rconn, bi.id).await?.author_hash,
|
||||
"comment" => Comment::get(&db, bi.id).await?.author_hash,
|
||||
_ => { Err(NotAllowed) }?,
|
||||
_ => Err(NotAllowed)?,
|
||||
};
|
||||
|
||||
if nh_to_block.eq(&user.namehash) {
|
||||
{ Err(NotAllowed) }?;
|
||||
Err(NotAllowed)?;
|
||||
}
|
||||
|
||||
blk.add(&nh_to_block).await?;
|
||||
@@ -150,3 +150,18 @@ pub async fn block(bi: Form<BlockInput>, user: CurrentUser, db: Db, rconn: RdsCo
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(FromForm)]
|
||||
pub struct TitleInput {
|
||||
#[field(validate = len(1..31))]
|
||||
title: String,
|
||||
}
|
||||
|
||||
#[post("/title", data = "<ti>")]
|
||||
pub async fn set_title(ti: Form<TitleInput>, user: CurrentUser, rconn: RdsConn) -> JsonAPI {
|
||||
if CustomTitle::set(&rconn, &user.namehash, &ti.title).await? {
|
||||
code0!()
|
||||
} else {
|
||||
Err(TitleUsed)?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ use rocket::serde::{json::json, Serialize};
|
||||
|
||||
#[derive(FromForm)]
|
||||
pub struct PostInput {
|
||||
#[field(validate = len(1..4097))]
|
||||
#[field(validate = len(1..12289))]
|
||||
text: String,
|
||||
#[field(validate = len(0..33))]
|
||||
#[field(validate = len(0..97))]
|
||||
cw: String,
|
||||
allow_search: Option<i8>,
|
||||
use_title: Option<i8>,
|
||||
@@ -52,7 +52,7 @@ pub struct PostOutput {
|
||||
#[derive(FromForm)]
|
||||
pub struct CwInput {
|
||||
pid: i32,
|
||||
#[field(validate = len(0..33))]
|
||||
#[field(validate = len(0..97))]
|
||||
cw: String,
|
||||
}
|
||||
|
||||
@@ -145,6 +145,7 @@ pub async fn get_list(
|
||||
Ok(json!({
|
||||
"data": ps_data,
|
||||
"count": ps_data.len(),
|
||||
"custom_title": CustomTitle::get(&rconn, &user.namehash).await?,
|
||||
"code": 0
|
||||
}))
|
||||
}
|
||||
@@ -162,7 +163,12 @@ pub async fn publish_post(
|
||||
content: poi.text.to_string(),
|
||||
cw: poi.cw.to_string(),
|
||||
author_hash: user.namehash.to_string(),
|
||||
author_title: "".to_string(),
|
||||
author_title: (if poi.use_title.is_some() {
|
||||
CustomTitle::get(&rconn, &user.namehash).await?
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
is_tmp: user.id.is_none(),
|
||||
n_attentions: 1,
|
||||
allow_search: poi.allow_search.is_some(),
|
||||
|
||||
@@ -66,6 +66,7 @@ async fn main() -> Result<(), rocket::Error> {
|
||||
api::systemlog::get_systemlog,
|
||||
api::operation::delete,
|
||||
api::operation::report,
|
||||
api::operation::set_title,
|
||||
api::operation::block,
|
||||
],
|
||||
)
|
||||
@@ -96,4 +97,5 @@ fn init_database() {
|
||||
|
||||
async fn clear_outdate_redis_data(rconn: &RdsConn) {
|
||||
rds_models::BannedUsers::clear(&rconn).await.unwrap();
|
||||
rds_models::CustomTitle::clear(&rconn).await.unwrap();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ const KEY_SYSTEMLOG: &str = "hole_v2:systemlog_list";
|
||||
const KEY_BANNED_USERS: &str = "hole_v2:banned_user_hash_list";
|
||||
const KEY_BLOCKED_COUNTER: &str = "hole_v2:blocked_counter";
|
||||
const KEY_DANGEROUS_USERS: &str = "hole_thu:dangerous_users"; //兼容一下旧版
|
||||
const KEY_CUSTOM_TITLE: &str = "hole_v2:title";
|
||||
|
||||
const SYSTEMLOG_MAX_LEN: isize = 1000;
|
||||
pub const BLOCK_THRESHOLD: i32 = 10;
|
||||
@@ -183,4 +184,29 @@ impl DangerousUser {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CustomTitle;
|
||||
|
||||
impl CustomTitle {
|
||||
// return false if title exits
|
||||
pub async fn set(rconn: &RdsConn, namehash: &str, title: &str) -> RedisResult<bool> {
|
||||
let mut rconn = rconn.clone();
|
||||
if rconn.hexists(KEY_CUSTOM_TITLE, title).await? {
|
||||
Ok(false)
|
||||
} else {
|
||||
rconn.hset(KEY_CUSTOM_TITLE, namehash, title).await?;
|
||||
rconn.hset(KEY_CUSTOM_TITLE, title, namehash).await?;
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get(rconn: &RdsConn, namehash: &str) -> RedisResult<Option<String>> {
|
||||
rconn.clone().hget(KEY_CUSTOM_TITLE, namehash).await
|
||||
}
|
||||
|
||||
pub async fn clear(rconn: &RdsConn) -> RedisResult<()> {
|
||||
rconn.clone().del(KEY_CUSTOM_TITLE).await
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub(crate) use init;
|
||||
|
||||
Reference in New Issue
Block a user