kovi_plugin_copycat/
lib.rs1mod config;
2
3use kovi::{
4 PluginBuilder as plugin, RuntimeBot, bot::runtimebot::kovi_api::SetAccessControlList,
5 event::GroupMsgEvent, log::info, tokio::sync::Mutex,
6};
7use std::{
8 collections::HashMap,
9 sync::{Arc, OnceLock},
10};
11
12use crate::config::CONFIG;
13
14static BOT: OnceLock<Arc<RuntimeBot>> = OnceLock::new();
15static STATE: OnceLock<Arc<Mutex<HashMap<i64, State>>>> = OnceLock::new();
16
17struct State {
18 text: String,
19 count: u32,
20 sender: i64,
21}
22
23#[kovi::plugin]
24async fn init() {
25 let bot = BOT.get_or_init(|| plugin::get_runtime_bot());
26 let config = config::init(bot).await.unwrap();
27
28 STATE.get_or_init(|| Arc::new(Mutex::new(HashMap::new())));
29
30 match &config.allow_groups {
31 Some(groups) => {
32 bot.set_plugin_access_control("copycat", true).unwrap();
33 bot.set_plugin_access_control_list(
34 "copycat",
35 true,
36 SetAccessControlList::Adds(groups.clone()),
37 )
38 .unwrap();
39 }
40 None => {
41 bot.set_plugin_access_control("copycat", false).unwrap();
42 }
43 }
44
45 plugin::on_group_msg(on_group_msg);
46}
47
48async fn on_group_msg(event: Arc<GroupMsgEvent>) {
49 let state = STATE.get().unwrap().clone();
50 let config = CONFIG.get().unwrap();
51
52 let msgs = event.message.get("text");
53 if msgs.len() > 1
54 || msgs.is_empty()
55 || !event.message.clone().into_iter().all(|m| m.type_ == "text")
56 {
57 info!("[copycat] Not a plain text message, ignored.");
58 return;
59 }
60
61 let msg = msgs[0].data["text"].as_str().unwrap().to_string();
62
63 {
64 let mut s = state.lock().await;
65 let s = match s.get_mut(&event.group_id) {
66 Some(s) => s,
67 None => {
68 s.insert(
69 event.group_id,
70 State {
71 text: String::new(),
72 count: 0,
73 sender: -1,
74 },
75 );
76 s.get_mut(&event.group_id).unwrap()
77 }
78 };
79
80 if s.text == msg {
81 if s.sender != event.sender.user_id {
82 s.count += 1;
83 info!(
84 "[copycat] Received repeated message, current count: {} / {}",
85 s.count, config.repeat_after
86 );
87 }
88 } else {
89 s.text = msg;
90 s.count = 1;
91 s.sender = event.sender.user_id;
92 }
93
94 if s.count == config.repeat_after {
95 BOT.get().unwrap().send_group_msg(event.group_id, &s.text);
96 s.count += 1;
97
98 info!(
99 "[copycat] Meow! Current count: {} / {}",
100 s.count, config.repeat_after
101 );
102 }
103 }
104}