Skip to main content

kovi_plugin_like/
lib.rs

1use kovi::event::MessageEventTrait;
2use kovi::event::id::ID;
3use kovi::log::info;
4pub use kovi::tokio;
5use kovi::utils::{load_json_data, save_json_data};
6use kovi::{PluginBuilder as P, RuntimeBot};
7use serde::{Deserialize, Serialize};
8use serde_json::json;
9use std::path::PathBuf;
10use std::sync::{Arc, Mutex};
11use std::time::{SystemTime, UNIX_EPOCH};
12
13#[cfg(not(any(feature = "onebot", feature = "milky")))]
14compile_error!("请至少启用一个协议 feature: \"onebot\" 或 \"milky\"");
15
16#[cfg(all(feature = "onebot", feature = "milky"))]
17compile_error!("不能同时启用 onebot 和 milky feature");
18
19#[cfg(feature = "onebot")]
20use kovi_onebot::*;
21
22#[cfg(feature = "milky")]
23use kovi_milky::*;
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26struct Config {
27    today: Vec<ID>,
28    /// 储存秒级别时间戳
29    data_time: u64,
30    like_times: usize,
31    msg: Msg,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
35struct Msg {
36    cmd: String,
37    like: String,
38    today: String,
39    do_not_like_you: String,
40}
41
42#[kovi::plugin]
43async fn main() {
44    let bot = P::get_runtime_bot();
45    let mut path = bot.get_data_path();
46    path.push("config.json");
47
48    let config: Config = {
49        let config: Config = serde_json::from_value(json!({
50            "today": [],
51            "data_time": 1,
52            "like_times": 10,
53            "msg": {
54                "cmd": "赞我",
55                "like": "已为你点赞10次",
56                "today": "今天赞过了,一边呆着去!",
57                "do_not_like_you": "就不给你点,略略略"
58            }
59        }))
60        .unwrap();
61
62        let mut config: Config = match load_json_data(config.clone(), &path) {
63            Ok(v) => v,
64            Err(e) => {
65                // 是json解析报错的话?
66                if let Some(_parse_error) = e.downcast_ref::<serde_json::Error>() {
67                    save_json_data(&config, &path).unwrap();
68                    config
69                } else {
70                    panic!("{e}")
71                }
72            }
73        };
74        let now = SystemTime::now()
75            .duration_since(UNIX_EPOCH)
76            .unwrap()
77            .as_secs();
78        if config.data_time / 86400 != now / 86400 {
79            config.today = Vec::new();
80            config.data_time = now;
81            save_json_data(&config, &path).unwrap();
82        }
83        config
84    };
85
86    let msg = Arc::new(config.msg.clone());
87    let path = Arc::new(path);
88    let config_arc = Arc::new(Mutex::new(config));
89
90    use kovi::async_move;
91
92    P::on(async_move!(e; msg, bot, config_arc, path;  {
93        on_msg_send_like(e, msg, bot, config_arc, path).await
94    }));
95
96    // P::on({
97    //     let msg = msg.clone();
98    //     let bot = bot.clone();
99    //     let config_arc = config_arc.clone();
100    //     let path = path.clone();
101    //     move |e: Arc<MsgEvent>| {
102    //         on_msg_send_like(
103    //             e,
104    //             msg.clone(),
105    //             bot.clone(),
106    //             config_arc.clone(),
107    //             path.clone(),
108    //         )
109    //     }
110    // });
111
112    P::cron("0 0 * * *", move || {
113        let config_clone_for_reset = config_arc.clone();
114        let path = path.clone();
115        async move {
116            // 清空 `today`
117            let mut config = config_clone_for_reset.lock().unwrap();
118            config.today.clear();
119            config.data_time = SystemTime::now()
120                .duration_since(UNIX_EPOCH)
121                .unwrap()
122                .as_secs();
123            info!("like插件正在清理");
124            save_json_data(&*config, &*path).unwrap();
125        }
126    })
127    .unwrap();
128}
129
130async fn on_msg_send_like(
131    e: Arc<MsgEvent>,
132    msg: Arc<Msg>,
133    bot: Arc<RuntimeBot>,
134    config_arc: Arc<Mutex<Config>>,
135    path: Arc<PathBuf>,
136) {
137    if e.borrow_text() != Some(&msg.cmd) {
138        return;
139    }
140
141    {
142        let config_lock = config_arc.lock().unwrap();
143
144        if config_lock.today.contains(&e.get_sender_id().to_id()) {
145            e.reply_and_quote(&msg.today);
146            return;
147        }
148    }
149
150    #[cfg(feature = "onebot")]
151    let res = bot
152        .send_like_return(*(e.get_sender_id().try_as_i64_or_panic()), 10)
153        .await;
154
155    #[cfg(feature = "milky")]
156    let res = {
157        use kovi::bot::runtimebot::CanSendApi as _;
158
159        bot.send_api_return(
160            "send_profile_like",
161            json!({
162                "user_id": e.get_sender_id().try_as_i64_or_panic(),
163                "count": 10
164            }),
165        )
166        .await
167    };
168
169    {
170        let mut config_lock = config_arc.lock().unwrap();
171
172        match res {
173            Ok(_) => {
174                e.reply_and_quote(&msg.like);
175                config_lock.today.push(e.get_sender_id().to_id());
176                save_json_data(&*config_lock, &*path).unwrap();
177            }
178            Err(_) => e.reply_and_quote(&msg.do_not_like_you),
179        };
180    }
181}