Skip to content

Commit

Permalink
add deny history mod
Browse files Browse the repository at this point in the history
  • Loading branch information
EluvK committed Mar 13, 2023
1 parent 4434d44 commit 84a40db
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/cqbot/bot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ impl Bot {
let user_id = message.user_id();
let ts = message.message_ts();

let pm = self
let pm_result = self
.chat_manager
.pre_handle_private_message(group_id, user_id, ts, message.message().clone());
match pm {
match pm_result {
Ok(true) => {
// legal request
let post_message = GPTPostMessage::new_with_history(
Expand Down
105 changes: 105 additions & 0 deletions src/history.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use std::{
collections::{HashMap, HashSet},
fs::File,
path::Path,
};

use serde::{Deserialize, Serialize};

/// deny lists for every group
#[derive(Default, Debug, Serialize, Deserialize)]
struct DenyLists(HashMap<String, HashSet<u64>>);

/// record running history for the bot, so the next run will automatically load these settings.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct BotHistory {
deny_lists: DenyLists,
}

static HISTORY_JSON_FILE: &str = "history.json";

pub enum BotHistoryOp {
AddDeny(u64),
RemoveDeny(u64),
}

impl BotHistory {
/// constructor
pub fn load() -> Self {
let path = Path::new(HISTORY_JSON_FILE);

if !path.exists() {
let new_empty_history = Self::default();
let mut _file = File::create(path).expect("Failed to create history file");
new_empty_history.write_to_file();
new_empty_history
} else {
Self::read_from_file()
}
}

pub fn load_group_deny_history(&self) -> HashMap<u64, HashSet<u64>> {
self.deny_lists
.0
.clone()
.into_iter()
.map(|(group_id_str, set)| (group_id_str.parse::<u64>().expect("error from string to u64"), set))
.collect()
}

pub fn sync_op(&mut self, group_id: Option<u64>, op: BotHistoryOp) {
let group_id_str = group_id.map_or(String::from("private"), |group_id| group_id.to_string());
match op {
BotHistoryOp::AddDeny(user_id) => {
self.deny_lists
.0
.entry(group_id_str)
.or_insert(HashSet::new())
.insert(user_id);
}
BotHistoryOp::RemoveDeny(user_id) => {
self.deny_lists
.0
.entry(group_id_str)
.or_insert(HashSet::new())
.remove(&user_id);
}
};
self.write_to_file();
}

fn write_to_file(&self) {
println!("[history] write_to_file: {:?}", self.deny_lists);
let contents = serde_json::to_string_pretty(&self).expect("History ser error");
std::fs::write(HISTORY_JSON_FILE, contents).expect("History file write error");
}
fn read_from_file() -> Self {
println!("[history] read_from_file");
let contents = std::fs::read(HISTORY_JSON_FILE).expect("History file read error");
serde_json::from_slice::<Self>(&contents).expect("History de error")
}
}

#[cfg(test)]
mod tests {

#[allow(unused_imports)]
use super::*;

#[test]
fn test_bot_history_serde() {
let raw_str = r#"
{
"deny_lists": {
"123": [
1,
222,
3
]
}
}
"#;
let history = serde_json::from_str::<BotHistory>(raw_str).unwrap();
println!("{:?}", history);
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod command;
mod config;
mod cqbot;
mod gpt;
mod history;
mod private_manager;
mod role;

Expand Down
36 changes: 30 additions & 6 deletions src/private_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ use std::{
rc::Rc,
};

use crate::{command, config::Config, gpt::GPTMessages, role::BotRole};
use crate::{
command,
config::Config,
gpt::GPTMessages,
history::{BotHistory, BotHistoryOp},
role::BotRole,
};

use self::error::PrivateManagerError;

Expand Down Expand Up @@ -83,6 +89,13 @@ impl PrivateManager {
deny_list: HashSet::new(),
}
}
fn new_with_history(interval: u64, deny_list: HashSet<u64>) -> Self {
PrivateManager {
contexts: HashMap::new(),
interval,
deny_list,
}
}

fn deny(&mut self, user_id: u64) {
self.deny_list.insert(user_id);
Expand All @@ -92,6 +105,10 @@ impl PrivateManager {
self.deny_list.remove(&user_id);
}

fn is_deny(&self, qq: u64) -> bool {
self.deny_list.contains(&qq)
}

fn reset(&mut self, user_id: Option<u64>) {
match user_id {
Some(user_id) => {
Expand All @@ -104,10 +121,6 @@ impl PrivateManager {
}
}

fn is_deny(&self, qq: u64) -> bool {
self.deny_list.contains(&qq)
}

fn get_histories(&self, user_id: u64) -> Option<&Vec<GPTMessages>> {
self.contexts.get(&user_id).map(|c| &c.histories)
}
Expand Down Expand Up @@ -192,14 +205,23 @@ pub struct ChatManager {
group_contexts: HashMap<u64, PrivateManager>,
private_context: PrivateManager,
config: Rc<Config>,
history: BotHistory,
}

impl ChatManager {
pub fn new(config: Rc<Config>) -> Self {
let history = BotHistory::load();
let group_historys = history.load_group_deny_history();
Self {
group_contexts: HashMap::new(),
group_contexts: group_historys
.into_iter()
.map(|(group_id, group_deny_history)| {
(group_id, PrivateManager::new_with_history(10, group_deny_history))
})
.collect(),
private_context: PrivateManager::new(1),
config,
history,
}
}

Expand Down Expand Up @@ -228,10 +250,12 @@ impl ChatManager {
command::RootOpcode::Invalid => PrivateManagerError::InvalidCommand,
command::RootOpcode::Deny(qq) => {
self.choose_pm(group_id).deny(qq);
self.history.sync_op(group_id, BotHistoryOp::AddDeny(qq));
PrivateManagerError::CommandSuccess(format!("Deny {}", qq))
}
command::RootOpcode::Allow(qq) => {
self.choose_pm(group_id).allow(qq);
self.history.sync_op(group_id, BotHistoryOp::RemoveDeny(qq));
PrivateManagerError::CommandSuccess(format!("Allow {}", qq))
}
command::RootOpcode::Reset(qq) => {
Expand Down

0 comments on commit 84a40db

Please sign in to comment.