mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-07 23:50:25 +00:00
Compare commits
15 Commits
v1.3.1-bet
...
v1.3.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f181a4b9cd | ||
|
|
77e5d8b0c2 | ||
|
|
edd9feb8f8 | ||
|
|
81d6a06dbe | ||
|
|
8afbc67bf7 | ||
|
|
a27132f907 | ||
|
|
183be05d82 | ||
|
|
bccf789714 | ||
|
|
55944dddb3 | ||
|
|
f67932cc56 | ||
|
|
6d633fac6a | ||
|
|
86fc5c51c8 | ||
|
|
156e9f07ad | ||
|
|
1ba4722fc7 | ||
|
|
54c9857219 |
@@ -1,6 +1,6 @@
|
||||
linters-settings:
|
||||
errcheck:
|
||||
ignore: fmt:.*,io/ioutil:^Read.*
|
||||
ignore: fmt:.*
|
||||
ignoretests: true
|
||||
|
||||
goimports:
|
||||
|
||||
49
README.md
49
README.md
@@ -67,10 +67,57 @@ zerobot [-h] [-t token] [-u url] [-n nickname] [-p prefix] [-d|w] [-g 监听地
|
||||
- [x] /服务详情
|
||||
- [x] @Bot 插件冲突检测 (会在本群发送一条消息并在约 1s 后撤回以检测其它同类 bot 中已启用的插件并禁用)
|
||||
- **定时指令触发器** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/job"`
|
||||
- [x] 记录以"完全匹配关键词"触发的(代表我执行的)指令
|
||||
- [x] 取消以"完全匹配关键词"触发的(代表我执行的)指令
|
||||
- [x] 记录在"cron"触发的指令
|
||||
- [x] 取消在"cron"触发的指令
|
||||
- [x] 查看所有触发指令
|
||||
- [x] 查看在"cron"触发的指令
|
||||
- [x] 查看以"完全匹配关键词"触发的(代表我执行的)指令
|
||||
- [x] 注入指令结果:任意指令
|
||||
- [x] 执行指令:任意指令
|
||||
- 注:任意指令可以使用形如`?::参数1提示语::1!`,`?::参数2提示语::2!`,`?::?可选参数3提示语,不回答将填入空值::3!`,`!::从url获取的参数::4!`,`!::?可选的从url获取的参数,出错将填入空值::5!`的未定参数,在注入时一一匹配
|
||||
- 一些示例
|
||||
> 每日9:30推送摸鱼人日历
|
||||
```
|
||||
记录在"30 9 * * *"触发的指令
|
||||
run[CQ:image,file=https://api.vvhan.com/api/moyu]
|
||||
```
|
||||
> 每日12:00以1/2概率执行coser指令
|
||||
```python
|
||||
记录在"0 12 * * *"触发的指令
|
||||
注入指令结果:>runcoderaw py
|
||||
from random import random
|
||||
if random() > 0.5: print('coser')
|
||||
else: print('今天没有coser哦~')
|
||||
```
|
||||
> 每日15:00询问设置定时者否想看coser
|
||||
```python
|
||||
记录在"0 15 * * *"触发的指令
|
||||
注入指令结果:>runcoderaw py
|
||||
if '?::想看coser吗?::1!' == '想': print('coser')
|
||||
else: print('好吧')
|
||||
```
|
||||
> 自行编写简易的选择困难症助手小插件
|
||||
```python
|
||||
记录以"简易的选择困难症助手"触发的指令
|
||||
执行指令:>runcoderaw py
|
||||
from random import random
|
||||
if random() > 0.5: print('您最终会选?::请输入您的选择1::1!')
|
||||
else: print('您最终会选?::请输入您的选择2::2!')
|
||||
简易的选择困难症助手
|
||||
```
|
||||
> 自行编写随机b站404页趣图插件
|
||||
```python
|
||||
记录以"随机b站404页趣图"触发的代表我执行的指令
|
||||
注入指令结果:>runcoderaw py
|
||||
import json
|
||||
j = json.loads(r'''!::https://api.iyk0.com/bili_chart::1!''')
|
||||
print("run[CQ:image,file="+j["img"]+"]")
|
||||
随机b站404页趣图
|
||||
```
|
||||

|
||||
|
||||
- **聊天** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat"`
|
||||
- [x] [BOT名字]
|
||||
- [x] [戳一戳BOT]
|
||||
@@ -120,6 +167,7 @@ zerobot [-h] [-t token] [-u url] [-n nickname] [-p prefix] [-d|w] [-g 监听地
|
||||
- **在线代码运行** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode"`
|
||||
- [x] > runcode [language] help
|
||||
- [x] > runcode [language] [code block]
|
||||
- [x] > runcoderaw [language] [code block]
|
||||
- **点歌** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/music"`
|
||||
- [x] 点歌[xxx]
|
||||
- [x] 网易点歌[xxx]
|
||||
@@ -202,7 +250,6 @@ zerobot [-h] [-t token] [-u url] [-n nickname] [-p prefix] [-d|w] [-g 监听地
|
||||
- **bilibili** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili"`
|
||||
- [x] >vup info [名字 | uid]
|
||||
- [x] >user info [名字 | uid]
|
||||
- [x] /开启粉丝日报
|
||||
- **嘉然** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana"`
|
||||
- [x] 小作文
|
||||
- [x] 发大病
|
||||
|
||||
6
go.mod
6
go.mod
@@ -3,9 +3,9 @@ module github.com/FloatTech/ZeroBot-Plugin
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/FloatTech/AnimeAPI v1.3.1-0.20220307053346-aa76aec4b635
|
||||
github.com/FloatTech/AnimeAPI v1.3.1-0.20220311024222-ed58ddf6834e
|
||||
github.com/FloatTech/sqlite v0.2.1
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220307063102-42185420359d
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220311032316-df8ab8b3c180
|
||||
github.com/antchfx/htmlquery v1.2.4
|
||||
github.com/corona10/goimagehash v1.0.3
|
||||
github.com/fogleman/gg v1.3.0
|
||||
@@ -21,7 +21,7 @@ require (
|
||||
github.com/shirou/gopsutil/v3 v3.22.2
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/tidwall/gjson v1.14.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220304040741-8e53f210618c
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220307142419-a1b34e6da007
|
||||
golang.org/x/image v0.0.0-20220302094943-723b81ca9867
|
||||
)
|
||||
|
||||
|
||||
15
go.sum
15
go.sum
@@ -1,11 +1,11 @@
|
||||
github.com/FloatTech/AnimeAPI v1.3.1-0.20220307053346-aa76aec4b635 h1:T7J1wLvSqn8PvkM7X98dgbafW+zG1l0LdX664HbrG0U=
|
||||
github.com/FloatTech/AnimeAPI v1.3.1-0.20220307053346-aa76aec4b635/go.mod h1:ZNhcnGEchvEjd09WbpLMlmxlmYy4trtLYEAJHRAoKaw=
|
||||
github.com/FloatTech/AnimeAPI v1.3.1-0.20220311024222-ed58ddf6834e h1:PKm/g1M7rYu6YMOV5k8xCOkgXTKF2Tk9v2exeYyCe+0=
|
||||
github.com/FloatTech/AnimeAPI v1.3.1-0.20220311024222-ed58ddf6834e/go.mod h1:JNF2O/RdbrsDIccSQ29a4g1pQRrZsN0Jh3ggFZYzZuY=
|
||||
github.com/FloatTech/bot-manager v1.0.0/go.mod h1:8YYRJ16oroGHQGD2En0oVnmcKJkxR9O/jd5BPSfWfOQ=
|
||||
github.com/FloatTech/sqlite v0.2.1 h1:9t6Me48XJJCIoPy4nLRvcdhcVKfT0c2lilp7SEKROG8=
|
||||
github.com/FloatTech/sqlite v0.2.1/go.mod h1:6NfHRzqOo9RWeMJEoAQVuo51Omd5LFNxCNQhMF02/9U=
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220307053255-29a0c0203693/go.mod h1:1nzt5KFkggpZaqkW0faY3y0X/qeMKTodqWc8wbVYhoY=
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220307063102-42185420359d h1:G5rXr46dJnpVbU2jN5XevX3lhh2TQ+DkSk1n1TLS82o=
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220307063102-42185420359d/go.mod h1:nW53pKNJVrbYzSGr89CBuM1vZv/hnQnV8dJSp+NCeAA=
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220307143543-1139754cacdf/go.mod h1:u+PiX1khNvtAgfRVTVP4hkA2oUnn5q5dTZSk1Cgp0Gw=
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220311032316-df8ab8b3c180 h1:8tE9DYu0+YMk3oKeO0ffl80818ZrPM9afbRgb2ag0tQ=
|
||||
github.com/FloatTech/zbputils v1.3.1-0.20220311032316-df8ab8b3c180/go.mod h1:u+PiX1khNvtAgfRVTVP4hkA2oUnn5q5dTZSk1Cgp0Gw=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc h1:AAx50/fb/xS4lvsdQg+bFbGvqSDhyV1MF+p2PLCamZ0=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc/go.mod h1:OMmITAib6POA37xCichWM0aRnoVpSMZO1rB/G01wrr0=
|
||||
@@ -36,7 +36,6 @@ github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
|
||||
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
|
||||
github.com/fumiama/go-base16384 v1.3.0 h1:J5Xtwh/3alGJt/z/0IFralo5UQA89iFWQqbxj5ZQZi8=
|
||||
github.com/fumiama/go-base16384 v1.3.0/go.mod h1:RGA715p34BiLoZvPRtaxuo2q25Kq9jFsgUsJb8dwy14=
|
||||
github.com/fumiama/go-registry v0.1.0/go.mod h1:iJT3DVgH7KXpJZs6waXEjnWtJPUBBGhF+ByJIMRfngk=
|
||||
github.com/fumiama/go-registry v0.1.1 h1:cmCRizjXHFW2ApwUHCXi8wKLJ6Gtt4GrShJlamGPbVI=
|
||||
github.com/fumiama/go-registry v0.1.1/go.mod h1:iJT3DVgH7KXpJZs6waXEjnWtJPUBBGhF+ByJIMRfngk=
|
||||
github.com/fumiama/gofastTEA v0.0.9 h1:adaWz+014vMShnLUNWIHLBs0Yv6JNUohcaXZNtct5J0=
|
||||
@@ -162,8 +161,8 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM
|
||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220304040741-8e53f210618c h1:0ew7cwYvRZUm1nsn4Cn0HBDSxy0YT5JnudeP53JwwjA=
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220304040741-8e53f210618c/go.mod h1:NwXIp7PgjV+kUALMXJ4v4/3QcsRSOodtjhLekuPXFog=
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220307142419-a1b34e6da007 h1:yHCJCj8u3Y0JDgTlrUqPHxIO6KU0WK9+voECZ2im5lo=
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220307142419-a1b34e6da007/go.mod h1:NwXIp7PgjV+kUALMXJ4v4/3QcsRSOodtjhLekuPXFog=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
|
||||
@@ -14,10 +14,12 @@ var (
|
||||
"* Copyright © 2020 - 2022 FloatTech. All Rights Reserved.",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
}
|
||||
// Banner ...
|
||||
Banner = strings.Join(info[:], "\n")
|
||||
reg = registry.NewRegReader("reilia.westeurope.cloudapp.azure.com:32664", "fumiama")
|
||||
)
|
||||
|
||||
// PrintBanner ...
|
||||
func PrintBanner() {
|
||||
fmt.Print(
|
||||
"\n======================[ZeroBot-Plugin]======================",
|
||||
@@ -28,6 +30,7 @@ func PrintBanner() {
|
||||
)
|
||||
}
|
||||
|
||||
// Kanban ...
|
||||
func Kanban() string {
|
||||
err := reg.Connect()
|
||||
if err != nil {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Package kanban 打印版本信息
|
||||
package kanban
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
type follower struct {
|
||||
Mid int `json:"mid"`
|
||||
Uname string `json:"uname"`
|
||||
Video int `json:"video"`
|
||||
Roomid int `json:"roomid"`
|
||||
Rise int `json:"rise"`
|
||||
Follower int `json:"follower"`
|
||||
GuardNum int `json:"guardNum"`
|
||||
AreaRank int `json:"areaRank"`
|
||||
}
|
||||
|
||||
// 开启日报推送
|
||||
func init() {
|
||||
fansDaily()
|
||||
en := control.Register("fansdaily", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: true,
|
||||
Help: "fansdaily\n- /开启粉丝日报\n- /关闭粉丝日报",
|
||||
})
|
||||
zero.OnCommand("开启粉丝日报", zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
m, ok := control.Lookup("fansdaily")
|
||||
if ok {
|
||||
if m.IsEnabledIn(ctx.Event.GroupID) {
|
||||
ctx.Send(message.Text("已启用!"))
|
||||
} else {
|
||||
m.Enable(ctx.Event.GroupID)
|
||||
ctx.Send(message.Text("添加成功!"))
|
||||
}
|
||||
} else {
|
||||
ctx.Send(message.Text("找不到该服务!"))
|
||||
}
|
||||
})
|
||||
en.OnCommand("关闭粉丝日报", zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
m, ok := control.Lookup("fansdaily")
|
||||
if ok {
|
||||
if m.IsEnabledIn(ctx.Event.GroupID) {
|
||||
m.Disable(ctx.Event.GroupID)
|
||||
ctx.Send(message.Text("关闭成功!"))
|
||||
} else {
|
||||
ctx.Send(message.Text("未启用!"))
|
||||
}
|
||||
} else {
|
||||
ctx.Send(message.Text("找不到该服务!"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 定时任务每天晚上最后2分钟执行一次
|
||||
func fansDaily() {
|
||||
_, err := process.CronTab.AddFunc("58 23 * * *", func() { sendNotice() })
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取数据拼接消息链并发送
|
||||
func getMsg() message.MessageSegment {
|
||||
var (
|
||||
diana = fansapi("672328094")
|
||||
ava = fansapi("672346917")
|
||||
eileen = fansapi("672342685")
|
||||
bella = fansapi("672353429")
|
||||
carol = fansapi("351609538")
|
||||
)
|
||||
return message.Text(
|
||||
time.Now().Format("2006-01-02"), " Asoul全团粉丝日报如下", "\n\n",
|
||||
"uid: ", diana.Mid, "\n",
|
||||
"名字: ", diana.Uname, "\n",
|
||||
"当前粉丝数: ", diana.Follower, "\n",
|
||||
"今日涨粉数: ", diana.Rise, "\n",
|
||||
"视频投稿数: ", diana.Video, "\n",
|
||||
"直播间id: ", diana.Roomid, "\n",
|
||||
"舰队: ", diana.GuardNum, "\n",
|
||||
"直播总排名: ", diana.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672328094", "\n\n",
|
||||
|
||||
"uid: ", ava.Mid, "\n",
|
||||
"名字: ", ava.Uname, "\n",
|
||||
"当前粉丝数: ", ava.Follower, "\n",
|
||||
"今日涨粉数: ", ava.Rise, "\n",
|
||||
"视频投稿数: ", ava.Video, "\n",
|
||||
"直播间id: ", ava.Roomid, "\n",
|
||||
"舰队: ", ava.GuardNum, "\n",
|
||||
"直播总排名: ", ava.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672346917", "\n\n",
|
||||
|
||||
"uid: ", eileen.Mid, "\n",
|
||||
"名字: ", eileen.Uname, "\n",
|
||||
"当前粉丝数: ", eileen.Follower, "\n",
|
||||
"今日涨粉数: ", eileen.Rise, "\n",
|
||||
"视频投稿数: ", eileen.Video, "\n",
|
||||
"直播间id: ", eileen.Roomid, "\n",
|
||||
"舰队: ", eileen.GuardNum, "\n",
|
||||
"直播总排名: ", eileen.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672342685", "\n\n",
|
||||
|
||||
"uid: ", bella.Mid, "\n",
|
||||
"名字: ", bella.Uname, "\n",
|
||||
"当前粉丝数: ", bella.Follower, "\n",
|
||||
"今日涨粉数: ", bella.Rise, "\n",
|
||||
"视频投稿数: ", bella.Video, "\n",
|
||||
"直播间id: ", bella.Roomid, "\n",
|
||||
"舰队: ", bella.GuardNum, "\n",
|
||||
"直播总排名: ", bella.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672353429", "\n\n",
|
||||
|
||||
"uid: ", carol.Mid, "\n",
|
||||
"名字: ", carol.Uname, "\n",
|
||||
"当前粉丝数: ", carol.Follower, "\n",
|
||||
"今日涨粉数: ", carol.Rise, "\n",
|
||||
"视频投稿数: ", carol.Video, "\n",
|
||||
"直播间id: ", carol.Roomid, "\n",
|
||||
"舰队: ", carol.GuardNum, "\n",
|
||||
"直播总排名: ", carol.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "351609538",
|
||||
)
|
||||
}
|
||||
|
||||
// 获取数据拼接消息链并发送
|
||||
func sendNotice() {
|
||||
m, ok := control.Lookup("fansdaily")
|
||||
if ok {
|
||||
msg := getMsg()
|
||||
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
|
||||
for _, g := range ctx.GetGroupList().Array() {
|
||||
grp := g.Get("group_id").Int()
|
||||
if m.IsEnabledIn(grp) {
|
||||
ctx.SendGroupMessage(grp, msg)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 请求api
|
||||
func fansapi(uid string) *follower {
|
||||
url := "https://api.vtbs.moe/v1/detail/" + uid
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
result := &follower{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(result); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
@@ -47,7 +47,7 @@ func init() {
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package bilibili
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
@@ -23,37 +24,62 @@ func init() {
|
||||
}
|
||||
id := res.Get("data.result.0.mid").String()
|
||||
// 获取详情
|
||||
json := fansapi(id)
|
||||
fo, err := fansapi(id)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(
|
||||
"uid: ", json.Mid, "\n",
|
||||
"名字: ", json.Uname, "\n",
|
||||
"当前粉丝数: ", json.Follower, "\n",
|
||||
"24h涨粉数: ", json.Rise, "\n",
|
||||
"视频投稿数: ", json.Video, "\n",
|
||||
"直播间id: ", json.Roomid, "\n",
|
||||
"舰队: ", json.GuardNum, "\n",
|
||||
"直播总排名: ", json.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", json.Mid, "\n",
|
||||
"uid: ", fo.Mid, "\n",
|
||||
"名字: ", fo.Uname, "\n",
|
||||
"当前粉丝数: ", fo.Follower, "\n",
|
||||
"24h涨粉数: ", fo.Rise, "\n",
|
||||
"视频投稿数: ", fo.Video, "\n",
|
||||
"直播间id: ", fo.Roomid, "\n",
|
||||
"舰队: ", fo.GuardNum, "\n",
|
||||
"直播总排名: ", fo.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", fo.Mid, "\n",
|
||||
"数据获取时间: ", time.Now().Format("2006-01-02 15:04:05"),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
// 搜索api:通过把触发指令传入的昵称找出uid返回
|
||||
func uid(keyword string) (gjson.Result, error) {
|
||||
func uid(keyword string) (*gjson.Result, error) {
|
||||
api := "http://api.bilibili.com/x/web-interface/search/type?search_type=bili_user&&user_type=1&keyword=" + keyword
|
||||
resp, err := http.Get(api)
|
||||
data, err := web.GetData(api)
|
||||
if err != nil {
|
||||
return gjson.Result{}, err
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return gjson.Result{}, errors.New("code not 200")
|
||||
}
|
||||
data, _ := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
json := gjson.ParseBytes(data)
|
||||
if json.Get("data.numResults").Int() == 0 {
|
||||
return gjson.Result{}, errors.New("查无此人")
|
||||
return nil, errors.New("查无此人")
|
||||
}
|
||||
return json, nil
|
||||
return &json, nil
|
||||
}
|
||||
|
||||
type follower struct {
|
||||
Mid int `json:"mid"`
|
||||
Uname string `json:"uname"`
|
||||
Video int `json:"video"`
|
||||
Roomid int `json:"roomid"`
|
||||
Rise int `json:"rise"`
|
||||
Follower int `json:"follower"`
|
||||
GuardNum int `json:"guardNum"`
|
||||
AreaRank int `json:"areaRank"`
|
||||
}
|
||||
|
||||
// 请求api
|
||||
func fansapi(uid string) (*follower, error) {
|
||||
url := "https://api.vtbs.moe/v1/detail/" + uid
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
result := &follower{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package github
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -119,7 +119,7 @@ func netGet(dest string, header http.Header) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
23
plugin/inject/main.go
Normal file
23
plugin/inject/main.go
Normal file
@@ -0,0 +1,23 @@
|
||||
// Package inject 注入指令
|
||||
package inject
|
||||
|
||||
import (
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("inject", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "注入指令\n" +
|
||||
"- run[CQ码]",
|
||||
})
|
||||
// 运行 CQ 码
|
||||
en.OnPrefix("run", zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 可注入,权限为主人
|
||||
ctx.Send(message.UnescapeCQCodeText(ctx.State["args"].(string)))
|
||||
})
|
||||
}
|
||||
@@ -2,8 +2,10 @@
|
||||
package job
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"hash/crc64"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -13,26 +15,29 @@ import (
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/FloatTech/zbputils/vevent"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
"github.com/fumiama/cron"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
lo map[int64]vevent.Loop
|
||||
entries map[int64]cron.EntryID // id entryid
|
||||
mu sync.Mutex
|
||||
limit = rate.NewLimiter(time.Second*2, 1)
|
||||
lo map[int64]vevent.Loop
|
||||
entries = map[int64]cron.EntryID{} // id entryid
|
||||
matchers = map[int64]*zero.Matcher{}
|
||||
mu sync.Mutex
|
||||
limit = rate.NewLimiter(time.Second*2, 1)
|
||||
en = control.Register("job", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "定时指令触发器\n- 记录以\"完全匹配关键词\"触发的指令\n- 取消以\"完全匹配关键词\"触发的指令\n- 记录在\"cron\"触发的指令\n- 取消在\"cron\"触发的指令\n- 查看所有触发指令\n- 查看在\"cron\"触发的指令\n- 查看以\"完全匹配关键词\"触发的指令\n- 注入指令结果:任意指令\n- 执行指令:任意指令",
|
||||
PrivateDataFolder: "job",
|
||||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("job", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "定时指令触发器\n- 记录在\"cron\"触发的指令\n- 取消在\"cron\"触发的指令\n- 查看所有触发指令\n- 查看在\"cron\"触发的指令",
|
||||
PrivateDataFolder: "job",
|
||||
})
|
||||
db.DBPath = en.DataFolder() + "job.db"
|
||||
err := db.Open()
|
||||
if err != nil {
|
||||
@@ -42,7 +47,6 @@ func init() {
|
||||
process.GlobalInitMutex.Lock()
|
||||
process.SleepAbout1sTo2s()
|
||||
lo = make(map[int64]vevent.Loop, len(zero.BotConfig.Driver))
|
||||
entries = map[int64]cron.EntryID{}
|
||||
for _, drv := range zero.BotConfig.Driver {
|
||||
id := drv.SelfID()
|
||||
ids := strconv.FormatInt(id, 36)
|
||||
@@ -53,9 +57,21 @@ func init() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
db.FindFor(ids, c, "", func() error {
|
||||
_ = db.FindFor(ids, c, "", func() error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if strings.HasPrefix(c.Cron, "fm:") {
|
||||
m := en.OnFullMatch(c.Cron[3:] /* skip fm: */).SetBlock(true)
|
||||
m.Handle(generalhandler(c))
|
||||
matchers[c.ID] = getmatcher(m)
|
||||
return nil
|
||||
}
|
||||
if strings.HasPrefix(c.Cron, "sm:") {
|
||||
m := en.OnFullMatch(c.Cron[3:] /* skip fm: */).SetBlock(true)
|
||||
m.Handle(superuserhandler(c))
|
||||
matchers[c.ID] = getmatcher(m)
|
||||
return nil
|
||||
}
|
||||
eid, err := process.CronTab.AddFunc(c.Cron, inject(id, []byte(c.Cmd)))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -67,17 +83,7 @@ func init() {
|
||||
logrus.Infoln("[job]本地环回初始化完成")
|
||||
process.GlobalInitMutex.Unlock()
|
||||
}()
|
||||
en.OnRegex(`^记录在"(.*)"触发的指令$`, ctxext.UserOrGrpAdmin, islonotnil, func(ctx *zero.Ctx) bool {
|
||||
ctx.SendChain(message.Text("您的下一条指令将被记录,在", ctx.State["regex_matched"].([]string)[1], "时触发"))
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.SendChain(message.Text("指令记录超时"))
|
||||
return false
|
||||
case e := <-zero.NewFutureEvent("message", 0, false, zero.CheckUser(ctx.Event.UserID)).Next():
|
||||
ctx.State["job_raw_event"] = e.RawEvent.Raw
|
||||
return true
|
||||
}
|
||||
}).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^记录在"(.*)"触发的指令$`, ctxext.UserOrGrpAdmin, islonotnil, isfirstregmatchnotnil, logevent).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cron := ctx.State["regex_matched"].([]string)[1]
|
||||
command := ctx.State["job_raw_event"].(string)
|
||||
c := &cmd{
|
||||
@@ -92,9 +98,57 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
})
|
||||
en.OnRegex(`^取消在"(.*)"触发的指令$`, ctxext.UserOrGrpAdmin, islonotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^记录以"(.*)"触发的指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil, logevent).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cron := "fm:" + ctx.State["regex_matched"].([]string)[1]
|
||||
command := ctx.State["job_new_event"].(gjson.Result).Get("message").Raw
|
||||
logrus.Debugln("[job] get cmd:", command)
|
||||
c := &cmd{
|
||||
ID: idof(cron, command),
|
||||
Cron: cron,
|
||||
Cmd: command,
|
||||
}
|
||||
err := registercmd(ctx.Event.SelfID, c)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
})
|
||||
en.OnRegex(`^记录以"(.*)"触发的代表我执行的指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil, logevent).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cron := "sm:" + ctx.State["regex_matched"].([]string)[1]
|
||||
command := ctx.State["job_raw_event"].(string)
|
||||
logrus.Debugln("[job] get cmd:", command)
|
||||
c := &cmd{
|
||||
ID: idof(cron, command),
|
||||
Cron: cron,
|
||||
Cmd: command,
|
||||
}
|
||||
err := registercmd(ctx.Event.SelfID, c)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
})
|
||||
en.OnRegex(`^取消在"(.*)"触发的指令$`, ctxext.UserOrGrpAdmin, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
cron := ctx.State["regex_matched"].([]string)[1]
|
||||
err := rmcmd(ctx.Event.SelfID, cron)
|
||||
err := rmcmd(ctx.Event.SelfID, ctx.Event.UserID, cron)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
})
|
||||
en.OnRegex(`^取消以"(.*)"触发的(代表我执行的)?指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
issu := ctx.State["regex_matched"].([]string)[2] != ""
|
||||
cron := ""
|
||||
if issu {
|
||||
cron = "sm:"
|
||||
} else {
|
||||
cron = "fm:"
|
||||
}
|
||||
cron += ctx.State["regex_matched"].([]string)[1]
|
||||
err := delcmd(ctx.Event.SelfID, cron)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
@@ -122,7 +176,7 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Text(lst))
|
||||
})
|
||||
en.OnRegex(`^查看在"(.*)"触发的指令$`, zero.SuperUserPermission, islonotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^查看在"(.*)"触发的指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c := &cmd{}
|
||||
ids := strconv.FormatInt(ctx.Event.SelfID, 36)
|
||||
cron := ctx.State["regex_matched"].([]string)[1]
|
||||
@@ -144,12 +198,84 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Text(lst))
|
||||
})
|
||||
en.OnRegex(`^查看以"(.*)"触发的(代表我执行的)?指令$`, zero.SuperUserPermission, islonotnil, isfirstregmatchnotnil).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
c := &cmd{}
|
||||
ids := strconv.FormatInt(ctx.Event.SelfID, 36)
|
||||
issu := ctx.State["regex_matched"].([]string)[2] != ""
|
||||
cron := ""
|
||||
if issu {
|
||||
cron = "sm:"
|
||||
} else {
|
||||
cron = "fm:"
|
||||
}
|
||||
cron += ctx.State["regex_matched"].([]string)[1]
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
n, err := db.Count(ids)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
lst := make([]string, 0, n)
|
||||
err = db.FindFor(ids, c, "WHERE cron='"+cron+"'", func() error {
|
||||
lst = append(lst, c.Cmd+"\n")
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(lst))
|
||||
})
|
||||
en.OnPrefix("执行指令:", ctxext.UserOrGrpAdmin, islonotnil, func(ctx *zero.Ctx) bool {
|
||||
return ctx.State["args"].(string) != ""
|
||||
}, parseArgs).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
ev := strings.ReplaceAll(ctx.Event.RawEvent.Raw, "执行指令:", "")
|
||||
logrus.Debugln("[job] inject:", ev)
|
||||
inject(ctx.Event.SelfID, binary.StringToBytes(ev))()
|
||||
})
|
||||
en.OnPrefix("注入指令结果:", ctxext.UserOrGrpAdmin, islonotnil, func(ctx *zero.Ctx) bool {
|
||||
return ctx.State["args"].(string) != ""
|
||||
}, parseArgs).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
vevent.NewLoopOf(vevent.NewAPICallerHook(ctx, func(rsp zero.APIResponse, err error) {
|
||||
if err == nil {
|
||||
logrus.Debugln("[job] CallerHook returned")
|
||||
id := message.NewMessageID(rsp.Data.Get("message_id").String())
|
||||
if id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR:未获取到返回结果"))
|
||||
return
|
||||
}
|
||||
msg := ctx.GetMessage(id)
|
||||
ctx.Event.NativeMessage = json.RawMessage("\"" + msg.Elements.String() + "\"")
|
||||
ctx.Event.RawMessageID = json.RawMessage(msg.MessageId.String())
|
||||
ctx.Event.RawMessage = msg.Elements.String()
|
||||
time.Sleep(time.Second * 5) // 防止风控
|
||||
ctx.Event.Time = time.Now().Unix()
|
||||
ctx.DeleteMessage(id)
|
||||
vev, cl := binary.OpenWriterF(func(w *binary.Writer) {
|
||||
err = json.NewEncoder(w).Encode(ctx.Event)
|
||||
})
|
||||
if err != nil {
|
||||
cl()
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[job] inject:", binary.BytesToString(vev))
|
||||
inject(ctx.Event.SelfID, vev)()
|
||||
cl()
|
||||
}
|
||||
})).Echo(binary.StringToBytes(strings.ReplaceAll(ctx.Event.RawEvent.Raw, "注入指令结果:", "")))
|
||||
})
|
||||
}
|
||||
|
||||
func islonotnil(ctx *zero.Ctx) bool {
|
||||
return len(lo) > 0
|
||||
}
|
||||
|
||||
func isfirstregmatchnotnil(ctx *zero.Ctx) bool {
|
||||
return ctx.State["regex_matched"].([]string)[1] != ""
|
||||
}
|
||||
|
||||
func inject(bot int64, response []byte) func() {
|
||||
return func() {
|
||||
if limit.Acquire() {
|
||||
@@ -173,19 +299,243 @@ func addcmd(bot int64, c *cmd) error {
|
||||
return db.Insert(strconv.FormatInt(bot, 36), c)
|
||||
}
|
||||
|
||||
func rmcmd(bot int64, cron string) error {
|
||||
func registercmd(bot int64, c *cmd) error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
m := en.OnFullMatch(c.Cron[3:] /* skip fm: or sm: */).SetBlock(true)
|
||||
if strings.HasPrefix(c.Cron, "sm:") {
|
||||
m.Handle(superuserhandler(c))
|
||||
} else {
|
||||
m.Handle(generalhandler(c))
|
||||
}
|
||||
matchers[c.ID] = getmatcher(m)
|
||||
return db.Insert(strconv.FormatInt(bot, 36), c)
|
||||
}
|
||||
|
||||
func generalhandler(c *cmd) zero.Handler {
|
||||
return func(ctx *zero.Ctx) {
|
||||
ctx.Event.NativeMessage = json.RawMessage(c.Cmd) // c.Cmd only have message
|
||||
ctx.Event.Time = time.Now().Unix()
|
||||
var err error
|
||||
vev, cl := binary.OpenWriterF(func(w *binary.Writer) {
|
||||
err = json.NewEncoder(w).Encode(ctx.Event)
|
||||
})
|
||||
if err != nil {
|
||||
cl()
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[job] inject:", binary.BytesToString(vev))
|
||||
inject(ctx.Event.SelfID, vev)()
|
||||
cl()
|
||||
}
|
||||
}
|
||||
|
||||
func superuserhandler(c *cmd) zero.Handler {
|
||||
e := &zero.Event{Sender: new(zero.User)}
|
||||
err := json.Unmarshal(binary.StringToBytes(c.Cmd), e)
|
||||
return func(ctx *zero.Ctx) {
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
ctx.Event.UserID = e.UserID
|
||||
ctx.Event.RawMessage = e.RawMessage
|
||||
ctx.Event.Sender = e.Sender
|
||||
ctx.Event.NativeMessage = e.NativeMessage
|
||||
vev, cl := binary.OpenWriterF(func(w *binary.Writer) {
|
||||
err = json.NewEncoder(w).Encode(ctx.Event)
|
||||
})
|
||||
if err != nil {
|
||||
cl()
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[job] inject:", binary.BytesToString(vev))
|
||||
inject(ctx.Event.SelfID, vev)()
|
||||
cl()
|
||||
}
|
||||
}
|
||||
|
||||
func rmcmd(bot, caller int64, cron string) error {
|
||||
c := &cmd{}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
bots := strconv.FormatInt(bot, 36)
|
||||
e := new(zero.Event)
|
||||
var delcmd []string
|
||||
err := db.FindFor(bots, c, "WHERE cron='"+cron+"'", func() error {
|
||||
err := json.Unmarshal(binary.StringToBytes(c.Cmd), e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if e.UserID != caller {
|
||||
return nil
|
||||
}
|
||||
eid, ok := entries[c.ID]
|
||||
if ok {
|
||||
process.CronTab.Remove(eid)
|
||||
delete(entries, c.ID)
|
||||
delcmd = append(delcmd, "id="+strconv.FormatInt(c.ID, 10))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
db.Del(bots, "WHERE cron='"+cron+"'")
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(delcmd) > 0 {
|
||||
return db.Del(bots, "WHERE "+strings.Join(delcmd, " or "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func delcmd(bot int64, cron string) error {
|
||||
c := &cmd{}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
bots := strconv.FormatInt(bot, 36)
|
||||
var delcmd []string
|
||||
err := db.FindFor(bots, c, "WHERE cron='"+cron+"'", func() error {
|
||||
m, ok := matchers[c.ID]
|
||||
if ok {
|
||||
m.Delete()
|
||||
delete(matchers, c.ID)
|
||||
delcmd = append(delcmd, "id="+strconv.FormatInt(c.ID, 10))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(delcmd) > 0 {
|
||||
return db.Del(bots, "WHERE "+strings.Join(delcmd, " or "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseArgs(ctx *zero.Ctx) bool {
|
||||
cmds := ctx.State["args"].(string)
|
||||
if !strings.Contains(cmds, "?::") && !strings.Contains(cmds, "!::") {
|
||||
return true
|
||||
}
|
||||
args := make(map[int]string)
|
||||
for strings.Contains(ctx.Event.RawEvent.Raw, "?::") {
|
||||
start := strings.Index(ctx.Event.RawEvent.Raw, "?::")
|
||||
msgend := strings.Index(ctx.Event.RawEvent.Raw[start+3:], "::")
|
||||
if msgend < 0 {
|
||||
ctx.SendChain(message.Text("ERROR:找不到结束的::"))
|
||||
return false
|
||||
}
|
||||
msgend += start + 3
|
||||
numend := strings.Index(ctx.Event.RawEvent.Raw[msgend+2:], "!")
|
||||
if numend <= 0 {
|
||||
ctx.SendChain(message.Text("ERROR:找不到结束的!"))
|
||||
return false
|
||||
}
|
||||
numend += msgend + 2
|
||||
logrus.Debugln("[job]", start, msgend, numend)
|
||||
msg := ctx.Event.RawEvent.Raw[start+3 : msgend]
|
||||
arg, err := strconv.Atoi(ctx.Event.RawEvent.Raw[msgend+2 : numend])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
arr, ok := args[arg]
|
||||
if !ok {
|
||||
var id message.MessageID
|
||||
if msg == "" {
|
||||
id = ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入参数", arg))
|
||||
} else {
|
||||
id = ctx.SendChain(message.At(ctx.Event.UserID), message.Text("[", arg, "] ", msg))
|
||||
}
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("参数读取超时")))
|
||||
if msg[0] != '?' {
|
||||
return false
|
||||
}
|
||||
case e := <-zero.NewFutureEvent("message", 0, true, zero.CheckUser(ctx.Event.UserID)).Next():
|
||||
args[arg] = e.Message.String()
|
||||
arr = args[arg]
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Reply(e.MessageID), message.Text("已记录"))
|
||||
process.SleepAbout1sTo2s()
|
||||
}
|
||||
}
|
||||
ctx.Event.RawEvent.Raw = ctx.Event.RawEvent.Raw[:start] + arr + ctx.Event.RawEvent.Raw[numend+1:]
|
||||
}
|
||||
args = make(map[int]string)
|
||||
for strings.Contains(ctx.Event.RawEvent.Raw, "!::") {
|
||||
start := strings.Index(ctx.Event.RawEvent.Raw, "!::")
|
||||
msgend := strings.Index(ctx.Event.RawEvent.Raw[start+3:], "::")
|
||||
if msgend < 0 {
|
||||
ctx.SendChain(message.Text("ERROR:找不到结束的::"))
|
||||
return false
|
||||
}
|
||||
msgend += start + 3
|
||||
numend := strings.Index(ctx.Event.RawEvent.Raw[msgend+2:], "!")
|
||||
if numend <= 0 {
|
||||
ctx.SendChain(message.Text("ERROR:找不到结束的!"))
|
||||
return false
|
||||
}
|
||||
numend += msgend + 2
|
||||
logrus.Debugln("[job]", start, msgend, numend)
|
||||
u := ctx.Event.RawEvent.Raw[start+3 : msgend]
|
||||
if u == "" {
|
||||
return false
|
||||
}
|
||||
arg, err := strconv.Atoi(ctx.Event.RawEvent.Raw[msgend+2 : numend])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return false
|
||||
}
|
||||
arr, ok := args[arg]
|
||||
if !ok {
|
||||
isnilable := u[0] == '?'
|
||||
if isnilable {
|
||||
u = u[1:]
|
||||
if u == "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
b, err := web.GetData(u)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
if !isnilable {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if len(b) > 0 {
|
||||
type fakejson struct {
|
||||
Arg string `json:"arg"`
|
||||
}
|
||||
f := fakejson{Arg: binary.BytesToString(b)}
|
||||
w := binary.SelectWriter()
|
||||
defer binary.PutWriter(w)
|
||||
_ = json.NewEncoder(w).Encode(&f)
|
||||
arr = w.String()[8 : w.Len()-3]
|
||||
args[arg] = arr
|
||||
}
|
||||
}
|
||||
w := binary.SelectWriter()
|
||||
w.WriteString(ctx.Event.RawEvent.Raw[:start])
|
||||
w.WriteString(arr)
|
||||
w.WriteString(ctx.Event.RawEvent.Raw[numend+1:])
|
||||
ctx.Event.RawEvent.Raw = string(w.Bytes())
|
||||
binary.PutWriter(w)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func logevent(ctx *zero.Ctx) bool {
|
||||
ctx.SendChain(message.Text("您的下一条指令将被记录,在", ctx.State["regex_matched"].([]string)[1], "时触发"))
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.SendChain(message.Text("指令记录超时"))
|
||||
return false
|
||||
case e := <-zero.NewFutureEvent("message", 0, true, zero.CheckUser(ctx.Event.UserID)).Next():
|
||||
ctx.State["job_raw_event"] = e.RawEvent.Raw
|
||||
ctx.State["job_new_event"] = e.RawEvent
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
16
plugin/job/matcher.go
Normal file
16
plugin/job/matcher.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package job
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
)
|
||||
|
||||
type matcherinstance struct {
|
||||
m *zero.Matcher
|
||||
}
|
||||
|
||||
func getmatcher(m control.Matcher) *zero.Matcher {
|
||||
return (*matcherinstance)(unsafe.Pointer(&m)).m
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
package lolicon
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -16,6 +14,7 @@ import (
|
||||
"github.com/FloatTech/zbputils/img/pool"
|
||||
"github.com/FloatTech/zbputils/math"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
@@ -38,17 +37,11 @@ func init() {
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
go func() {
|
||||
for i := 0; i < math.Min(cap(queue)-len(queue), 2); i++ {
|
||||
resp, err := http.Get(api)
|
||||
data, err := web.GetData(api)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
continue
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
ctx.SendChain(message.Text("ERROR: code ", resp.StatusCode))
|
||||
continue
|
||||
}
|
||||
data, _ := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
json := gjson.ParseBytes(data)
|
||||
if e := json.Get("error").Str; e != "" {
|
||||
ctx.SendChain(message.Text("ERROR: ", e))
|
||||
@@ -58,7 +51,7 @@ func init() {
|
||||
url = strings.ReplaceAll(url, "i.pixiv.cat", "i.pixiv.re")
|
||||
name := url[strings.LastIndex(url, "/")+1 : len(url)-4]
|
||||
m, err := pool.GetImage(name)
|
||||
if err != nil && err != pool.ErrImgFileAsync {
|
||||
if err != nil {
|
||||
m.SetFile(url)
|
||||
_, err = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
|
||||
process.SleepAbout1sTo2s()
|
||||
|
||||
@@ -509,15 +509,6 @@ func init() { // 插件主体
|
||||
}
|
||||
ctx.SendChain(message.Text("找不到服务!"))
|
||||
})
|
||||
// 运行 CQ 码
|
||||
engine.OnRegex(`^run(.*)$`, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var cmd = ctx.State["regex_matched"].([]string)[1]
|
||||
cmd = strings.ReplaceAll(cmd, "[", "[")
|
||||
cmd = strings.ReplaceAll(cmd, "]", "]")
|
||||
// 可注入,权限为主人
|
||||
ctx.Send(cmd)
|
||||
})
|
||||
// 根据 gist 自动同意加群
|
||||
// 加群请在github新建一个gist,其文件名为本群群号的字符串的md5(小写),内容为一行,是当前unix时间戳(10分钟内有效)。
|
||||
// 然后请将您的用户名和gist哈希(小写)按照username/gisthash的格式填写到回答即可。
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -231,7 +231,7 @@ func netGet(url string, header http.Header) []byte {
|
||||
return nil
|
||||
}
|
||||
defer res.Body.Close()
|
||||
result, _ := ioutil.ReadAll(res.Body)
|
||||
result, _ := io.ReadAll(res.Body)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -245,6 +245,6 @@ func netPost(url string, data url.Values, header http.Header) []byte {
|
||||
return nil
|
||||
}
|
||||
defer res.Body.Close()
|
||||
result, _ := ioutil.ReadAll(res.Body)
|
||||
result, _ := io.ReadAll(res.Body)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package nbnhhsh
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -31,7 +31,7 @@ func getValue(text string) []string {
|
||||
urlValues.Add("text", text)
|
||||
resp, err := http.PostForm("https://lab.magiconch.com/api/nbnhhsh/guess", urlValues)
|
||||
if err == nil {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err == nil {
|
||||
resp.Body.Close()
|
||||
json := gjson.ParseBytes(body)
|
||||
|
||||
@@ -3,7 +3,7 @@ package novel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/url"
|
||||
@@ -164,7 +164,7 @@ func search(searchKey string) (searchHTML string) {
|
||||
log.Errorln("[novel]", err)
|
||||
}
|
||||
defer searchResp.Body.Close()
|
||||
searchData, err := ioutil.ReadAll(searchResp.Body)
|
||||
searchData, err := io.ReadAll(searchResp.Body)
|
||||
if err != nil {
|
||||
log.Errorf("[novel] get response for url=%s got error=%s\n", searchURL, err.Error())
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package runcode
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -104,9 +104,10 @@ func init() {
|
||||
"JavaScript || TypeScript || PHP || Shell \n" +
|
||||
"Kotlin || Rust || Erlang || Ruby || Swift \n" +
|
||||
"R || VB || Py2 || Perl || Pascal || Scala",
|
||||
}).ApplySingle(ctxext.DefaultSingle).OnRegex(`^>runcode\s(.+?)\s([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
}).ApplySingle(ctxext.DefaultSingle).OnRegex(`^>runcode(raw)?\s(.+?)\s([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
language := ctx.State["regex_matched"].([]string)[1]
|
||||
israw := ctx.State["regex_matched"].([]string)[1] != ""
|
||||
language := ctx.State["regex_matched"].([]string)[2]
|
||||
language = strings.ToLower(language)
|
||||
if runType, exist := table[language]; !exist {
|
||||
// 不支持语言
|
||||
@@ -116,10 +117,9 @@ func init() {
|
||||
)
|
||||
} else {
|
||||
// 执行运行
|
||||
block := ctx.State["regex_matched"].([]string)[2]
|
||||
block = message.UnescapeCQCodeText(block)
|
||||
if block == "help" {
|
||||
// 输出模板
|
||||
block := message.UnescapeCQText(ctx.State["regex_matched"].([]string)[3])
|
||||
switch block {
|
||||
case "help":
|
||||
ctx.SendChain(
|
||||
message.Text("> ", ctx.Event.Sender.NickName, " ", language, "-template:\n"),
|
||||
message.Text(
|
||||
@@ -127,7 +127,7 @@ func init() {
|
||||
templates[language],
|
||||
),
|
||||
)
|
||||
} else {
|
||||
default:
|
||||
if output, err := runCode(block, runType); err != nil {
|
||||
// 运行失败
|
||||
ctx.SendChain(
|
||||
@@ -136,10 +136,14 @@ func init() {
|
||||
)
|
||||
} else {
|
||||
// 运行成功
|
||||
ctx.SendChain(
|
||||
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
|
||||
message.Text(output),
|
||||
)
|
||||
if israw {
|
||||
ctx.SendChain(message.Text(output))
|
||||
} else {
|
||||
ctx.SendChain(
|
||||
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
|
||||
message.Text(output),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,7 +181,7 @@ func runCode(code string, runType [2]string) (string, error) {
|
||||
if body.StatusCode != http.StatusOK {
|
||||
return "", errors.New("code not 200")
|
||||
}
|
||||
res, err := ioutil.ReadAll(body.Body)
|
||||
res, err := io.ReadAll(body.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func init() { // 插件主体
|
||||
}
|
||||
logrus.Debugln("[sausenao]开始下载", n)
|
||||
err1 := illust.DownloadToCache(i)
|
||||
if err != pool.ErrImgFileAsync && err1 == nil {
|
||||
if err1 == nil {
|
||||
m.SetFile(f)
|
||||
_, _ = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
|
||||
}
|
||||
|
||||
@@ -163,10 +163,8 @@ func (p *imgpool) push(ctx *zero.Ctx, imgtype string, illust *pixiv.Illust) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if err != imagepool.ErrImgFileAsync {
|
||||
m.SetFile(f)
|
||||
_, _ = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
|
||||
}
|
||||
m.SetFile(f)
|
||||
_, _ = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
|
||||
msg = message.Image("file:///" + f)
|
||||
} else {
|
||||
msg = message.Image(m.String())
|
||||
|
||||
@@ -23,7 +23,7 @@ func init() {
|
||||
PublicDataFolder: "Chat",
|
||||
})
|
||||
go func() {
|
||||
data, err := file.GetLazyData(engine.DataFolder()+"kimoi.json", true, true)
|
||||
data, err := file.GetLazyData(engine.DataFolder()+"kimoi.json", true, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
package translation
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
@@ -14,29 +9,11 @@ import (
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/process"
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
|
||||
"github.com/FloatTech/zbputils/control/order"
|
||||
)
|
||||
|
||||
func tl(d string) ([]byte, error) {
|
||||
url := "https://api.cloolc.club/fanyi?data=" + d
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
_ = resp.Body.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if code := resp.StatusCode; code != 200 {
|
||||
// 如果返回不是200则立刻抛出错误
|
||||
errmsg := fmt.Sprintf("code %d", code)
|
||||
return nil, errors.New(errmsg)
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
control.Register("translation", order.AcquirePrio(), &control.Options{
|
||||
DisableOnDefault: false,
|
||||
@@ -45,11 +22,11 @@ func init() {
|
||||
}).OnRegex(`^>TL\s(-.{1,10}? )?(.*)$`).SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg := []string{ctx.State["regex_matched"].([]string)[2]}
|
||||
rely, err := tl(msg[0])
|
||||
data, err := web.GetData("https://api.cloolc.club/fanyi?data=" + msg[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
info := gjson.ParseBytes(rely)
|
||||
info := gjson.ParseBytes(data)
|
||||
repo := info.Get("data.0")
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SendChain(message.Text(repo.Get("value.0")))
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -199,7 +199,7 @@ func (vdb *VtbDB) GetVtbList() (uidList []string) {
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
bytes, err := ioutil.ReadAll(resp.Body)
|
||||
bytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
@@ -262,7 +262,7 @@ func (vdb *VtbDB) StoreVtb(uid string) {
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
bytes, err := ioutil.ReadAll(resp.Body)
|
||||
bytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return
|
||||
|
||||
@@ -3,9 +3,9 @@ package wtf
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/FloatTech/zbputils/web"
|
||||
)
|
||||
|
||||
/* JS path getter for https://wtf.hiigara.net/ranking
|
||||
@@ -134,12 +134,7 @@ func (w *wtf) predict(names ...string) (string, error) {
|
||||
name += "/" + url.QueryEscape(n)
|
||||
}
|
||||
u := apiprefix + w.path + name
|
||||
resp, err := http.Get(u)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
r, err := io.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
r, err := web.GetData(u)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user