You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
4.8 KiB
186 lines
4.8 KiB
use crate::rds_conn::RdsConn; |
|
use chrono::{offset::Local, DateTime}; |
|
use redis::{AsyncCommands, RedisResult}; |
|
use rocket::serde::json::serde_json; |
|
use rocket::serde::{Deserialize, Serialize}; |
|
|
|
macro_rules! init { |
|
($ktype:ty, $formatter:expr) => { |
|
pub fn init(k: $ktype, rconn: &RdsConn) -> Self { |
|
Self { |
|
key: format!($formatter, k), |
|
rconn: rconn.clone(), |
|
} |
|
} |
|
}; |
|
() => { |
|
pub fn init(rconn: &RdsConn) -> Self { |
|
Self { |
|
rconn: rconn.clone(), |
|
} |
|
} |
|
}; |
|
} |
|
|
|
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 SYSTEMLOG_MAX_LEN: isize = 1000; |
|
pub const BLOCK_THRESHOLD: i32 = 10; |
|
|
|
pub struct Attention { |
|
key: String, |
|
rconn: RdsConn, |
|
} |
|
|
|
impl Attention { |
|
init!(&str, "hole_v2:attention:{}"); |
|
|
|
pub async fn add(&mut self, pid: i32) -> RedisResult<()> { |
|
self.rconn.sadd(&self.key, pid).await |
|
} |
|
|
|
pub async fn remove(&mut self, pid: i32) -> RedisResult<()> { |
|
self.rconn.srem(&self.key, pid).await |
|
} |
|
|
|
pub async fn has(&mut self, pid: i32) -> RedisResult<bool> { |
|
self.rconn.sismember(&self.key, pid).await |
|
} |
|
|
|
pub async fn all(&mut self) -> RedisResult<Vec<i32>> { |
|
self.rconn.smembers(&self.key).await |
|
} |
|
|
|
// TODO: clear all |
|
} |
|
|
|
#[derive(Serialize, Deserialize, Debug)] |
|
#[serde(crate = "rocket::serde")] |
|
pub enum LogType { |
|
AdminDelete, |
|
Report, |
|
Ban, |
|
} |
|
|
|
impl LogType { |
|
pub fn contains_ugc(&self) -> bool { |
|
match self { |
|
Self::Report => true, |
|
_ => false, |
|
} |
|
} |
|
} |
|
|
|
#[derive(Serialize, Deserialize, Debug)] |
|
#[serde(crate = "rocket::serde")] |
|
pub struct Systemlog { |
|
pub user_hash: String, |
|
pub action_type: LogType, |
|
pub target: String, |
|
pub detail: String, |
|
pub time: DateTime<Local>, |
|
} |
|
|
|
impl Systemlog { |
|
pub async fn create(&self, rconn: &RdsConn) -> RedisResult<()> { |
|
let mut rconn = rconn.clone(); |
|
if rconn.llen::<&str, isize>(KEY_SYSTEMLOG).await? > SYSTEMLOG_MAX_LEN { |
|
rconn.ltrim(KEY_SYSTEMLOG, 0, SYSTEMLOG_MAX_LEN - 1).await?; |
|
} |
|
rconn |
|
.lpush(KEY_SYSTEMLOG, serde_json::to_string(&self).unwrap()) |
|
.await |
|
} |
|
|
|
pub async fn get_list(rconn: &RdsConn, limit: isize) -> RedisResult<Vec<Self>> { |
|
let rds_result = rconn |
|
.clone() |
|
.lrange::<&str, Vec<String>>(KEY_SYSTEMLOG, 0, limit) |
|
.await?; |
|
Ok(rds_result |
|
.iter() |
|
.map(|s| serde_json::from_str(s).unwrap()) |
|
.collect()) |
|
} |
|
} |
|
|
|
pub struct BannedUsers; |
|
|
|
impl BannedUsers { |
|
pub async fn add(rconn: &RdsConn, namehash: &str) -> RedisResult<()> { |
|
rconn |
|
.clone() |
|
.sadd::<&str, &str, ()>(KEY_BANNED_USERS, namehash) |
|
.await |
|
} |
|
|
|
pub async fn has(rconn: &RdsConn, namehash: &str) -> RedisResult<bool> { |
|
rconn.clone().sismember(KEY_BANNED_USERS, namehash).await |
|
} |
|
|
|
pub async fn clear(rconn: &RdsConn) -> RedisResult<()> { |
|
rconn.clone().del(KEY_BANNED_USERS).await |
|
} |
|
} |
|
|
|
pub struct BlockedUsers { |
|
pub key: String, |
|
rconn: RdsConn, |
|
} |
|
|
|
impl BlockedUsers { |
|
init!(i32, "hole_v2:blocked_users:{}"); |
|
|
|
pub async fn add(&mut self, namehash: &str) -> RedisResult<()> { |
|
self.rconn.sadd(&self.key, namehash).await |
|
} |
|
|
|
pub async fn has(&mut self, namehash: &str) -> RedisResult<bool> { |
|
self.rconn.sismember(&self.key, namehash).await |
|
} |
|
|
|
pub async fn check_blocked( |
|
rconn: &RdsConn, |
|
viewer_id: Option<i32>, |
|
viewer_hash: &str, |
|
author_hash: &str, |
|
) -> RedisResult<bool> { |
|
Ok(match viewer_id { |
|
Some(id) => Self::init(id, rconn).has(author_hash).await?, |
|
None => false, |
|
} || (DangerousUser::has(rconn, author_hash).await? |
|
&& !DangerousUser::has(rconn,viewer_hash).await?)) |
|
} |
|
} |
|
|
|
pub struct BlockCounter; |
|
|
|
impl BlockCounter { |
|
pub async fn count_incr(rconn: &RdsConn, namehash: &str) -> RedisResult<i32> { |
|
rconn.clone().hincr(KEY_BLOCKED_COUNTER, namehash, 1).await |
|
} |
|
|
|
pub async fn get_count(rconn: &RdsConn, namehash: &str) -> RedisResult<i32> { |
|
rconn.clone().hget(KEY_BLOCKED_COUNTER, namehash).await |
|
} |
|
} |
|
|
|
pub struct DangerousUser; |
|
|
|
impl DangerousUser { |
|
pub async fn add(rconn: &RdsConn, namehash: &str) -> RedisResult<()> { |
|
rconn |
|
.clone() |
|
.sadd::<&str, &str, ()>(KEY_DANGEROUS_USERS, namehash) |
|
.await |
|
} |
|
|
|
pub async fn has(rconn: &RdsConn, namehash: &str) -> RedisResult<bool> { |
|
rconn.clone().sismember(KEY_DANGEROUS_USERS, namehash).await |
|
} |
|
} |
|
|
|
pub(crate) use init;
|
|
|