diff --git a/README.md b/README.md index b94db1f..25317ce 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ start cmd /K rikka-bot-wechat.exe ## 功能模块 -1. - [x] [管理权限](docs/plugin/README.md) -2. - [ ] 链接解析 +1. - [x] [管理权限](docs/plugin/admin/README.md) +2. - [x] [链接解析](docs/plugin/bilibili/README.md) 3. - [ ] 热更新 ## 如何开发插件 diff --git a/docs/img/bilibili/biliurlparse01.png b/docs/img/bilibili/biliurlparse01.png new file mode 100644 index 0000000..018e6d6 Binary files /dev/null and b/docs/img/bilibili/biliurlparse01.png differ diff --git a/docs/img/bilibili/biliurlparse02.png b/docs/img/bilibili/biliurlparse02.png new file mode 100644 index 0000000..d2cc704 Binary files /dev/null and b/docs/img/bilibili/biliurlparse02.png differ diff --git a/docs/img/bilibili/biliurlparse03.png b/docs/img/bilibili/biliurlparse03.png new file mode 100644 index 0000000..aa909c1 Binary files /dev/null and b/docs/img/bilibili/biliurlparse03.png differ diff --git a/docs/plugin/README.md b/docs/plugin/admin/README.md similarity index 93% rename from docs/plugin/README.md rename to docs/plugin/admin/README.md index 84d012a..b074799 100644 --- a/docs/plugin/README.md +++ b/docs/plugin/admin/README.md @@ -23,5 +23,5 @@ ## 图解 -![img.png](../img/admincall.png) +![img.png](../../img/admincall.png) diff --git a/docs/plugin/bilibili/README.md b/docs/plugin/bilibili/README.md new file mode 100644 index 0000000..9d5ca65 --- /dev/null +++ b/docs/plugin/bilibili/README.md @@ -0,0 +1,26 @@ +# bilibili链接解析模块 + +> [!TIP] +> 插件代码位置: [/rikkabot/plugins/admin/adminplugin.go](https://github.com/Clov614/rikka-bot-wechat/tree/main/rikkabot/plugins/biliUrlDecode/biliUrlDecode.go) + + +## 功能说明 + +以下三种消息可以触发链接解析: + +- bvid: BV1yi42127nN + +- 原始链接/分享短链: https://www.bilibili.com/video/BV1yi42127nN + +- 分享的app消息 + +## 立即使用 + +被动技能无需主动命令发起 + +## 图解 + +![biliurlparse01.png](../../img/bilibili/biliurlparse01.png) +![biliurlparse02.png](../../img/bilibili/biliurlparse02.png) +![biliurlparse03.png](../../img/bilibili/biliurlparse03.png) + diff --git a/go.mod b/go.mod index e70a3f4..1386966 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( replace github.com/eatmoreapple/openwechat => github.com/Clov614/openwechat v1.4.8 require ( + github.com/Clov614/bilibili v0.1.1 // indirect github.com/bytedance/sonic v1.11.9 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/cloudwego/base64x v0.1.4 // indirect diff --git a/go.sum b/go.sum index 72a3b06..6ab4ef3 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/Clov614/bilibili v0.1.1 h1:YsWcm8vYSwwksvUTZAjBPd37VTAcU2+BfArHQxJqKIY= +github.com/Clov614/bilibili v0.1.1/go.mod h1:th+qNf6jfSDH03oCM4s347a+i7IpCgZyNRIHY8AAXe8= github.com/Clov614/go-ai-sdk v0.3.3 h1:aNL3vQvh6TRX+NZ8HcW/SJsfSdP1cpX+bcWXkNMSLGw= github.com/Clov614/go-ai-sdk v0.3.3/go.mod h1:S/GDuJSLlnNU47uEpY2FrN1GdP+A4mDXBQZQ2i6sCzk= github.com/Clov614/openwechat v1.4.8 h1:8O8zeVAGw4W2PWy/gVGthPuM7Ua25ZSfaerwAs6JqIU= diff --git a/rikkabot/plugins/biliUrlDecode/biliUrlDecode.go b/rikkabot/plugins/biliUrlDecode/biliUrlDecode.go index 38518f2..e6b593e 100644 --- a/rikkabot/plugins/biliUrlDecode/biliUrlDecode.go +++ b/rikkabot/plugins/biliUrlDecode/biliUrlDecode.go @@ -1 +1,119 @@ package biliUrlDecode + +import ( + "bytes" + "encoding/xml" + "github.com/Clov614/bilibili" + "github.com/rs/zerolog/log" + "regexp" + "strconv" + "wechat-demo/rikkabot/message" + "wechat-demo/rikkabot/processor/control" + "wechat-demo/rikkabot/processor/control/dialog" + "wechat-demo/rikkabot/processor/register" + "wechat-demo/rikkabot/utils/imgutil" +) + +func init() { + biliDecodePlugin := biliPlugin{ + OnceDialog: &dialog.OnceDialog{}, + } + biliDecodePlugin.PluginName = "bilibili链接解析" + // 允许群组 白名单允许 + biliDecodePlugin.ProcessRules = &control.ProcessRules{EnableGroup: true, CostomTrigger: func(rikkaMsg message.Message) bool { + if rikkaMsg.Msgtype == message.MsgTypeApp { + var xmlMsg message.XMLMsg + err := xml.Unmarshal([]byte(rikkaMsg.Content), &xmlMsg) + if err != nil { + log.Err(err).Msg("xml.Unmarshal fail at biliPlugin") + return false + } + // 解析链接 + if xmlMsg.AppInfo.AppName == "哔哩哔哩" { + return true + } + } else if rikkaMsg.Msgtype == message.MsgTypeText { + regexBV := regexp.MustCompile(`(BV[\w\d]+)`) + regexBilibili := regexp.MustCompile(`https:\/\/www\.bilibili\.com\/video\/(BV[\w\d]+)\/?`) + regexShort := regexp.MustCompile(`https:\/\/b23\.tv\/([\w\d]+)`) + return regexBV.MatchString(rikkaMsg.Content) || regexBilibili.MatchString(rikkaMsg.Content) || regexShort.MatchString(rikkaMsg.Content) + } + return false + }} + biliDecodePlugin.Once = func(recvmsg message.Message, sendMsg chan<- *message.Message) { + switch recvmsg.Msgtype { + case message.MsgTypeApp: + var xmlMsg message.XMLMsg + err := xml.Unmarshal([]byte(recvmsg.Content), &xmlMsg) + if err != nil { + log.Err(err).Msg("xml.Unmarshal fail at biliPlugin") + return + } + // 解析链接 + if xmlMsg.AppInfo.AppName == "哔哩哔哩" { + videoInfo, err := bilibili.NewUrlDecoder().Parse(xmlMsg.AppMsg.URL) + if err != nil { + log.Err(err).Msg("bilibili.NewUrlDecoder fail at biliPlugin") + } + output := buildOutput(videoInfo) + biliDecodePlugin.SendText(recvmsg.MetaData, output) + return + } + case message.MsgTypeText: + regexBV := regexp.MustCompile(`(BV[\w\d]+)`) + regexBilibili := regexp.MustCompile(`https:\/\/www\.bilibili\.com\/video\/(BV[\w\d]+)\/?`) + regexShort := regexp.MustCompile(`https:\/\/b23\.tv\/([\w\d]+)`) + var videoInfo *bilibili.VideoInfo + var err error + urlParser := bilibili.NewUrlDecoder() + if match := regexBV.FindStringSubmatch(recvmsg.Content); len(match) > 0 { + videoInfo, err = urlParser.ParseByBvid(match[1]) + if err != nil { + log.Err(err).Msg("bilibili.urlParser.ParseByBvid fail at biliPlugin") + return + } + } else if match = regexBilibili.FindStringSubmatch(recvmsg.Content); len(match) > 0 { + videoInfo, err = urlParser.Parse(match[1]) + if err != nil { + log.Err(err).Msg("bilibili.urlParser.ParseByBvid fail at biliPlugin") + return + } + } else if match = regexShort.FindStringSubmatch(recvmsg.Content); len(match) > 0 { + videoInfo, err = urlParser.Parse(match[1]) + if err != nil { + log.Err(err).Msg("bilibili.urlParser.ParseByBvid fail at biliPlugin") + return + } + } + output := buildOutput(videoInfo) + imgFetch, err := imgutil.ImgFetch(videoInfo.Pic) + if err != nil { + log.Err(err).Msg("bilibili.videoInfo.pic.fetchimg fail at biliPlugin") + } else { + biliDecodePlugin.SendImage(recvmsg.MetaData, imgFetch) // 发送图片封面 + } + biliDecodePlugin.SendText(recvmsg.MetaData, output) + } + } + register.RegistPlugin("bili-url-parse", biliDecodePlugin.OnceDialog, 1) +} + +func buildOutput(videoInfo *bilibili.VideoInfo) string { + // 构建输出视频信息 + videoUrl := "https://www.bilibili.com/video/" + videoInfo.Bvid + "\n" + var buf bytes.Buffer + buf.WriteString(videoUrl) + buf.WriteString("标题: " + videoInfo.Title + "\n") + buf.WriteString("分区: " + videoInfo.Tname + "\n") + buf.WriteString("播放量: " + strconv.Itoa(videoInfo.View) + "\n") + buf.WriteString("点赞: " + strconv.Itoa(videoInfo.Like) + "\n") + buf.WriteString("投币: " + strconv.Itoa(videoInfo.Coin) + "\n") + buf.WriteString("收藏: " + strconv.Itoa(videoInfo.Favorite) + "\n") + buf.WriteString("分享: " + strconv.Itoa(videoInfo.Share) + "\n") + buf.WriteString("Bvid: \n\n " + videoInfo.Bvid + "\n") + return buf.String() +} + +type biliPlugin struct { + *dialog.OnceDialog +} diff --git a/rikkabot/plugins/defaultPlugin.go b/rikkabot/plugins/defaultPlugin.go index 7b776ea..6fb7144 100644 --- a/rikkabot/plugins/defaultPlugin.go +++ b/rikkabot/plugins/defaultPlugin.go @@ -13,9 +13,10 @@ import ( "wechat-demo/rikkabot/processor/control/dialog" "wechat-demo/rikkabot/processor/register" - _ "wechat-demo/rikkabot/plugins/admin" // 需要副作用 init注册方法 - _ "wechat-demo/rikkabot/plugins/ai" // 需要副作用 init注册方法 - _ "wechat-demo/rikkabot/plugins/game" // 需要副作用 init注册方法 + _ "wechat-demo/rikkabot/plugins/admin" // 需要副作用 init注册方法 + _ "wechat-demo/rikkabot/plugins/ai" // 需要副作用 init注册方法 + _ "wechat-demo/rikkabot/plugins/biliUrlDecode" // 需要副作用 init注册方法 + _ "wechat-demo/rikkabot/plugins/game" // 需要副作用 init注册方法 ) func init() {