kovi_plugin_copycat/
lib.rs

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