kovi-plugin-copycat 0.1.4

基于 Kovi 框架的群消息自动复读插件
Documentation
mod config;

use kovi::{
    PluginBuilder as plugin, RuntimeBot, bot::runtimebot::kovi_api::SetAccessControlList,
    event::GroupMsgEvent, log::info, tokio::sync::Mutex,
};
use std::{collections::HashMap, sync::Arc};

use crate::config::CONFIG;

const PLUGIN_NAME: &str = "kovi-plugin-copycat";

struct State {
    text: String,
    count: u32,
    sender: i64,
}

#[kovi::plugin]
async fn init() {
    let bot = plugin::get_runtime_bot();
    let config = config::init(&bot).await.unwrap();

    let state: Arc<Mutex<HashMap<i64, State>>> = Arc::new(Mutex::new(HashMap::new()));

    if let Some(groups) = &config.allow_groups {
        bot.set_plugin_access_control(PLUGIN_NAME, true).unwrap();
        bot.set_plugin_access_control_list(
            PLUGIN_NAME,
            true,
            SetAccessControlList::Adds(groups.clone()),
        )
        .unwrap();
    } else {
        bot.set_plugin_access_control(PLUGIN_NAME, false).unwrap();
    }

    plugin::on_group_msg({
        let bot = bot.clone();
        let state = state.clone();
        move |e| on_group_msg(e, bot.clone(), state.clone())
    });

    info!("[copycat] Ready to reveal the essence of human beings.")
}

async fn on_group_msg(
    event: Arc<GroupMsgEvent>,
    bot: Arc<RuntimeBot>,
    state: Arc<Mutex<HashMap<i64, State>>>,
) {
    let config = CONFIG.get().unwrap();

    let msgs = event.message.get("text");
    if msgs.len() > 1
        || msgs.is_empty()
        || !event.message.clone().into_iter().all(|m| m.type_ == "text")
    {
        info!("[copycat] Not a plain text message, ignored.");
        return;
    }

    let msg = msgs[0].data["text"].as_str().unwrap().to_string();

    {
        let mut s = state.lock().await;
        let s = match s.get_mut(&event.group_id) {
            Some(s) => s,
            None => {
                s.insert(
                    event.group_id,
                    State {
                        text: String::new(),
                        count: 0,
                        sender: -1,
                    },
                );
                s.get_mut(&event.group_id).unwrap()
            }
        };

        if s.text == msg {
            if s.sender != event.sender.user_id {
                s.count += 1;
                info!(
                    "[copycat] Received repeated message, current count: {} / {}",
                    s.count, config.repeat_after
                );
            }
        } else {
            s.text = msg;
            s.count = 1;
            s.sender = event.sender.user_id;
        }

        if s.count == config.repeat_after {
            bot.send_group_msg(event.group_id, &s.text);
            s.count += 1;

            info!(
                "[copycat] Meow! Current count: {} / {}",
                s.count, config.repeat_after
            );
        }
    }
}