kovi_plugin_napcat_quick/
lib.rs

1use std::sync::Arc;
2use kovi::{MsgEvent, RuntimeBot};
3use kovi::serde_json::{json, Value};
4
5/**
6发送文件, 私聊直接发送, 群聊则上传到群文件根目录
7*/
8pub fn send_file(e: Arc<MsgEvent>, bot: Arc<RuntimeBot>, url: String, filename: String) {
9    if e.is_private(){
10        bot.send_api("upload_private_file", json!({
11      "user_id": e.user_id,
12      "file": url,
13      "name": filename,
14    }));
15    } else {
16        bot.send_api("upload_group_file", json!({
17      "group_id": e.group_id,
18      "file": url,
19      "name": filename,
20      "folder_id": "/"
21    }));
22    }
23}
24
25/**
26发送戳一戳
27*/
28pub fn send_poke(bot: Arc<RuntimeBot>, user_id: i64){
29    bot.send_api("send_poke", json!({
30            "user_id": user_id,
31          }))
32}
33
34/**
35设置消息表情, 仅限群可以使用, 表情参考: https://docs-v1.zhamao.xin/face_list.html
36*/
37pub fn set_msg_emoji_like(bot: Arc<RuntimeBot>, message_id: i32, emoji_id: u8) {
38    bot.send_api("set_msg_emoji_like", json!({
39            "message_id": message_id,
40            "emoji_id": emoji_id
41          }))
42}
43
44
45/**
46从引用或者当前 event 中提取图片, 优先级: 引用 > 当前 event
47*/
48pub async fn get_pic_from_reply_or_current(e: Arc<MsgEvent>, bot: Arc<RuntimeBot>) -> Option<String> {
49    if e.human_text.contains("reply") {
50        get_image_from_reply(&e, &bot).await
51    } else {
52        get_image_from_current(&e)
53    }
54}
55
56async fn get_image_from_reply(e: &MsgEvent, bot: &RuntimeBot) -> Option<String> {
57    let msg_id = e.original_json
58        .get("message")?
59        .as_array()?
60        .first()?
61        .get("data")?
62        .get("id")?
63        .as_str()?;
64
65    let sid = if e.is_group() {
66        e.group_id?.to_string()
67    } else {
68        e.user_id.to_string()
69    };
70
71    get_img_from_reply(bot, msg_id, e.is_group(), &sid).await
72}
73
74fn get_image_from_current(e: &MsgEvent) -> Option<String> {
75    e.message.iter()
76        .find(|msg| msg.type_ == "image")
77        .and_then(|msg| msg.data.get("url"))
78        .and_then(Value::as_str)
79        .map(|s| s.trim_matches('"').to_string())
80}
81
82async fn get_img_from_reply(bot: &RuntimeBot, msg_id: &str, is_group: bool, sid: &str) -> Option<String> {
83    let (api_name, param_key) = if is_group {
84        ("get_group_msg_history", "group_id")
85    } else {
86        ("get_friend_msg_history", "user_id")
87    };
88
89    let params = json!({ param_key: sid, "message_seq": msg_id });
90    let history_msg = bot.send_api_return(api_name, params).await.ok()?;
91
92    history_msg.data
93        .get("messages")?
94        .as_array()?
95        .first()?
96        .get("message")?
97        .as_array()?
98        .iter()
99        .find(|msg| msg.get("type").and_then(Value::as_str) == Some("image"))
100        .and_then(|msg| msg.get("data")?.get("url")?.as_str())
101        .map(|url| url.trim_matches('"').to_string())
102}