Compare commits

..

137 Commits

Author SHA1 Message Date
源文雨
d9b361f765 🔖 v1.5.0-beta1 2022-07-03 09:52:01 +08:00
Fox_white
5b2810e6c5 为猜歌插件添加config (#285)
*  猜歌添加config

* 📚 猜歌帮助信息更新

* 📚 猜歌帮助信息更新

*  猜歌错误信息继承

*  错误处理

*  错误处理ep2

* 🐛 猜歌插件bug修正和命名修改

*  猜歌插件不再使用gjson

* Update struct.go

* 修复-动漫2无法下载歌曲问题

* 🐛 Resolve Compilation error

* 🐛 Resolve Lint

* 🐛 Resolve Lint

Co-authored-by: 方柳煜 <101934327+fangliuyu@users.noreply.github.com>
2022-07-03 09:25:14 +08:00
github-actions[bot]
15a5b347e8 🎨 改进代码样式 2022-06-29 12:58:24 +00:00
方柳煜
477ffa825b 优化qqwife插件,新增猜歌插件 (#283)
* 猜歌插件

* 猜歌插件

* 猜歌插件

* 优化重置花名册指令

* Update main.go

* Update main.go

* Update main.go

* Update main.go

* Update main.go

* Update main.go

* Update main.go

* Update main.go

* Update main.go

* Update main.go

* Update main.go

* Update main.go

* Update README.md
2022-06-29 20:57:58 +08:00
Jiang-Red
84363b1513 删除无法使用的zaobao (#278)
* drop zaobao

* edit readme

* drop zaobao
2022-06-24 21:00:55 +08:00
方柳煜
01bf6f049b 修复存在误解的文案 (#272)
* 修复存在误解的文案

* Update qqmapwife.go
2022-06-19 20:51:47 +08:00
莫思潋
a8d93de000 feat:塔罗牌阵 (#268)
* 优化在两个命令中使用空格分隔的体验
- fortune的设置底图功能
- b14的加密功能

* 优化四个插件中使用空格分隔的体验
- 加密
- 哔哩哔哩推送
- 藏头诗
- 运势

* 优化并修正了上一个commit
- 加上了因为复制粘贴疏忽又没有注意测试遗漏的`?`
- 调整藏头诗和加密的正则触发,使其不必多此一举
- 删去了未被发现的测试代码

* - 删去了遗漏的Trim

* 优化了更多插件中使用空格的体验
- 优化了music bilibili image_finder 中使用空格的体验
- 补上了plugin_bilibili中未实现的vup开头触发
- 为plugin_bilibili_parse输出的消息加上一个换行符,优化排版

* - 调整funny
- 补回readme中bilibili_push的注释说明

* - 简化funny说明

* - 用暴力的办法使抽多张塔罗牌不重复
- 逆位的图片现在可以倒过来了

* - 解塔罗牌

* - 修改readme

* 大幅减少全局变量,简化抽塔罗牌输出

* - 更新了塔罗牌阵

* - 顺lint心意
- 添加判断避免重复装填

* 调整塔罗牌阵消息
- 用图片说明牌阵信息避免被封

* 调整DoOnceOnSuccess,减少冗余

* 🎨 改进代码样式

* 调整发送牌阵信息

* 🎨 改进代码样式

* 改回base64

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-06-18 16:51:11 +08:00
github-actions[bot]
2da5de3743 🎨 改进代码样式 2022-06-18 04:06:33 +00:00
方柳煜
bf6bac7be6 修复花名册会显示单身贵族的问题 (#269)
* 修复花名册会显示单身贵族的问题

* Update qqmapwife.go

* Update qqmapwife.go
2022-06-18 12:06:07 +08:00
源文雨
394d2e4a08 edit README 2022-06-17 11:59:26 +08:00
himawari
0dd447e270 添加txt转midi,优化midi转txt (#267)
* 🐛 长字符串发文件

*  添加txt转midi

*  音色自定义

*  添加windows脚本说明

* 🐛 修复某些midi读取不了的问题

*  多音轨转换

Co-authored-by: haibaraguo <haibaraguo@yeahka.com>
2022-06-17 11:46:09 +08:00
源文雨
92c913e3eb 🔖 1.4.1 2022-06-16 13:31:33 +08:00
github-actions[bot]
5dea461963 🎨 改进代码样式 2022-06-16 05:29:07 +00:00
方柳煜
f768081849 优化花名册名字切片报错问题 (#263) 2022-06-16 13:27:47 +08:00
himawari
668418c48a 添加mid2txt接口 (#264)
Co-authored-by: haibaraguo <haibaraguo@yeahka.com>
2022-06-16 13:27:23 +08:00
github-actions[bot]
2bf387a57c 🎨 改进代码样式 2022-06-15 04:24:49 +00:00
方柳煜
42a4726985 修复checkupdate报错问题 (#262)
* 修复checkupdate报错问题

* Update qqmapwife.go

* Update qqmapwife.go
2022-06-15 12:24:19 +08:00
源文雨
5c4b5359e0 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-06-13 13:05:42 +08:00
源文雨
8e3f56a3a2 move info 2022-06-13 13:05:21 +08:00
github-actions[bot]
91a837477a 🎨 改进代码样式 2022-06-13 04:32:42 +00:00
源文雨
a2dfc54068 🐛 fix: b14 decode 2022-06-13 12:32:09 +08:00
github-actions[bot]
7ded2fe13a 🎨 改进代码样式 2022-06-13 04:09:52 +00:00
方柳煜
b6f1b27a81 Update qqmapwife.go (#261) 2022-06-13 12:09:22 +08:00
源文雨
621fd614ea 💩👌 make lint happy 2022-06-11 21:06:08 +08:00
源文雨
be3e7c892c fix b14 2022-06-11 18:27:26 +08:00
源文雨
1f640b7644 drop webgui 2022-06-11 17:00:22 +08:00
源文雨
987b505d32 fix regex 2022-06-11 16:27:09 +08:00
源文雨
4b2f23f093 优化正则 2022-06-11 16:13:26 +08:00
源文雨
1d52d0bafc 优化 parse 2022-06-11 16:04:57 +08:00
源文雨
e73db14976 运势 add ASoul 2022-06-11 14:27:03 +08:00
源文雨
fe8a677541 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-06-11 14:16:36 +08:00
源文雨
926cba8197 运势 add ASoul 2022-06-11 14:16:22 +08:00
Jiang-Red
ee6e5db0a6 Update bilibili_parse.go (#259)
修复 粉丝数据获取出错
优化 简化数据显示
优化 不返回无效链接的错误
2022-06-11 11:53:19 +08:00
源文雨
0c62d8dd07 fix: imgfinder format 2022-06-10 23:34:05 +08:00
源文雨
d6e352b3b4 fix: imgfinder format 2022-06-10 23:28:12 +08:00
源文雨
59e46be262 fix: imgfinder format 2022-06-10 23:24:14 +08:00
源文雨
746c048550 优化代码结构 2022-06-10 19:00:27 +08:00
himawari
a92c584997 添加简易midi制作 (#257)
*  添加简易midi制作

* 🐛 修lint

Co-authored-by: haibaraguo <haibaraguo@yeahka.com>
2022-06-10 18:55:28 +08:00
源文雨
7f4c6eb4ac 🔖 1.4.1-beta6 2022-06-10 15:48:33 +08:00
源文雨
fbeb048c44 ⬆️ update sqlite 2022-06-10 15:47:47 +08:00
源文雨
9f748a8119 imgfinder add more info 2022-06-10 13:42:03 +08:00
源文雨
b9fd590095 fix #256: 关键字搜图无法使用 2022-06-10 13:21:31 +08:00
源文雨
430e210b3c update deps 2022-06-10 13:04:16 +08:00
Jiang-Red
706d54db76 更换api版bilibiliparse (#255)
* Update bilibili_parse.go

* make lint happy

* 改进提出的问题
2022-06-10 12:54:53 +08:00
源文雨
9ac276767d change reg host 2022-06-04 17:59:31 +08:00
源文雨
29144348b3 🔖 1.4.1-beta5 2022-06-04 17:27:08 +08:00
源文雨
2f91b11672 fix manager 2022-06-04 15:01:00 +08:00
源文雨
caf0ef88ac update control 2022-06-04 14:55:15 +08:00
源文雨
c8154db108 fix workflow 2022-06-02 12:38:46 +08:00
源文雨
7ce6b5592a 🎨 优化代码格式 2022-06-02 12:30:38 +08:00
源文雨
e1bc4fdf36 优化 score 2022-06-02 12:29:37 +08:00
MoeMagicMango
fd7f5f719f fix:修复API变动造成图片无法返回的问题 (#250) 2022-06-02 12:20:17 +08:00
源文雨
6678ca6c93 💩👌 make lint happy 2022-06-02 12:19:41 +08:00
源文雨
180e03e249 try fixing #249: once SIGSEGV 2022-05-30 14:43:08 +08:00
源文雨
357f15eb01 🔖 1.4.1-beta4 2022-05-29 13:11:24 +08:00
未归404
a08704b60f 更新README.md (#247) 2022-05-29 12:50:36 +08:00
源文雨
03ba81a9c5 🎨 优化 bilibiliparse 2022-05-27 19:16:13 +08:00
源文雨
2933962df8 🎨 优化 bilibiliparse 2022-05-27 19:09:44 +08:00
源文雨
4f248c4dc7 🎨 优化 bilibiliparse 2022-05-27 19:09:07 +08:00
源文雨
14096f24ba add 设置默认限速 #241 2022-05-27 01:00:48 +08:00
源文雨
c0b75accf4 fix #243: add ctrl /改变默认启用状态 2022-05-27 00:41:44 +08:00
源文雨
cb1b7d5da7 add more limiter (#241) 2022-05-26 13:55:14 +08:00
源文雨
c8072171f0 🔖 1.4.1-beta3 2022-05-25 11:58:32 +08:00
源文雨
485f6d4cef 🐛 job panic 2022-05-25 11:58:01 +08:00
源文雨
2b85097e30 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-05-24 10:56:15 +08:00
源文雨
0904789291 🔖 1.4.1-beta2 2022-05-24 10:56:00 +08:00
方柳煜
fda69793a5 修复单身技能会报错问题 (#237) 2022-05-24 10:54:11 +08:00
源文雨
3c22aaf99d 🐛 job panic 2022-05-24 10:52:49 +08:00
MoeMagicMango
151a5d480f Fix: 更换稳定的背景api + 修复因api问题签到结果无法出现但数据库已经记录的问题 (#236)
* 通过修改顺序解决签到背景API出问题

* Update sign_in.go

* 🎨 改进代码样式

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-05-21 22:53:20 +08:00
源文雨
88d136626d update deps 2022-05-20 23:36:46 +08:00
源文雨
170f5bba79 🔖 1.4.1-beta1 2022-05-20 21:15:45 +08:00
源文雨
c4cbb0cd59 添加我问你答 2022-05-20 21:13:49 +08:00
源文雨
0fa04070f1 Update README.md 2022-05-20 15:23:39 +08:00
方柳煜
f8bea241a2 修复小三技能的判断逻辑的缺陷 (#230) 2022-05-16 22:51:54 +08:00
github-actions[bot]
bb6b2e4b29 🎨 改进代码样式 2022-05-16 14:45:37 +00:00
源文雨
557251a679 saucenao 搜图 使用合并转发 2022-05-16 22:44:47 +08:00
github-actions[bot]
696783b0fe 🎨 改进代码样式 2022-05-16 06:42:24 +00:00
源文雨
6eb29d2cc9 🔖 1.4.0 2022-05-16 14:41:45 +08:00
github-actions[bot]
4b4cafcda8 🎨 改进代码样式 2022-05-16 05:40:05 +00:00
方柳煜
ed2ed8d968 修复CD共用问题,新增功能 (#229) 2022-05-16 13:39:48 +08:00
Jiang-Red
fbb387bd9f fix:saucenao插件搜图相似度判断 (#228) 2022-05-14 23:50:25 +08:00
源文雨
0db2db482f 🐛 job 注入指令结果 递归 2022-05-14 19:10:05 +08:00
himawari
af2fe727fc 添加拟声鸟类型和马丁路德骂人语录 (#227)
*  mockingbird添加类型

*  添加马丁路德骂人语录

Co-authored-by: haibaraguo <haibaraguo@yeahka.com>
2022-05-14 11:32:25 +08:00
源文雨
a7387dcf22 💩👌 make lint happy 2022-05-13 13:12:39 +08:00
github-actions[bot]
5ce44fb161 🎨 改进代码样式 2022-05-13 05:09:55 +00:00
Jiang-Red
9086b9c3ca 修复一个小问题 (#225) 2022-05-13 13:09:13 +08:00
github-actions[bot]
4837c5387a 🎨 改进代码样式 2022-05-13 05:08:51 +00:00
源文雨
5d73216238 🐛 saucenao reflect 2022-05-13 13:08:02 +08:00
源文雨
5053091e44 💩👌 make lint happy 2022-05-13 13:00:54 +08:00
源文雨
6319ed0473 hide saucenao error 2022-05-12 19:07:59 +08:00
源文雨
c67c109af6 优化 qqwife 2022-05-12 14:43:30 +08:00
源文雨
b3cdb1464b 优化 imagefinder 2022-05-12 14:05:18 +08:00
源文雨
3c01c3f0ba 优化 danbooru 2022-05-12 14:01:24 +08:00
源文雨
07d541be20 🔖 1.4.0-beta7 2022-05-12 12:38:12 +08:00
源文雨
4a0dc59585 优化 saucenao 2022-05-12 12:27:02 +08:00
源文雨
b1dd8f52e8 edit README 2022-05-12 11:24:53 +08:00
github-actions[bot]
6907fe230f 🎨 改进代码样式 2022-05-12 03:23:21 +00:00
方柳煜
f2e4071b90 修复单身狗技能逻辑 (#224)
* ⬆️ update deps

* 更改源酱提出的问题

* Update qqmapwife.go

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-05-12 11:22:07 +08:00
源文雨
452f5e5f83 💩👌 make lint happy 2022-05-12 11:21:20 +08:00
源文雨
c94b9f54ce ⬆️ update deps 2022-05-10 23:34:09 +08:00
源文雨
e993f93cf4 🔖 1.4.0-beta6 2022-05-10 23:22:57 +08:00
源文雨
e9fac38c1b 🔖 1.4.0-beta6 2022-05-10 23:00:20 +08:00
源文雨
31a49b8ff9 fix: gif 503 2022-05-10 22:52:46 +08:00
源文雨
7831cdf10c fix: groupwife url 2022-05-09 12:22:36 +08:00
源文雨
c0f176f0af fix #173: 今日早报变成昨日火星晚报 2022-05-09 12:18:57 +08:00
源文雨
dc96a557eb 🔖 1.4.0-beta5 2022-05-09 12:12:18 +08:00
源文雨
7a8c915e62 优化代码结构 2022-05-09 11:23:34 +08:00
github-actions[bot]
dec42cc72b 🎨 改进代码样式 2022-05-09 03:09:45 +00:00
方柳煜
92c9d1d2ce 一天一夫一妻制群老婆 (#219) 2022-05-09 11:08:22 +08:00
Kanri
de017fcd27 Update README.md 2022-05-09 01:57:38 +08:00
MSCxar#0293
1229f62abd README.md: 新增tg群组 (#222)
* README.md: 新增tg群组
2022-05-09 01:38:21 +08:00
github-actions[bot]
512852b817 🎨 改进代码样式 2022-05-08 14:13:47 +00:00
himawari
5a087000a9 🐛 疫情查询、网易点歌、qq点歌问题 (#220)
* 🐛 修复网易点歌,qq点歌问题

* 🚨 错误输出

* 🚨 错误输出
2022-05-08 22:12:27 +08:00
莫思潋
6b56d6649e feat:解塔罗牌 (#217) 2022-05-08 18:31:18 +08:00
林沐馨
5081aab497 fix #215: 摸鱼日历 (#143)
* Update calendar.go

更换API方式

* Update calendar.go

* 更换API

修复BUG

* 🎨 改进代码样式

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-05-07 22:35:32 +08:00
源文雨
bbb4afde53 fix: kanban scale 2022-05-06 22:30:51 +08:00
源文雨
d28495c3eb 优化显示 2022-05-06 21:11:29 +08:00
源文雨
1785e0c4a3 优化显示 2022-05-06 21:09:47 +08:00
源文雨
1e93e75aac add kanban 2022-05-06 21:06:45 +08:00
github-actions[bot]
a3ed7eeee2 🎨 改进代码样式 2022-05-06 12:04:03 +00:00
himawari
c3582637df 🎨 查成分增加可选择查uid (#214)
*  查成分添加注册日期信息

* 🐛 修复头像是webp图片使用不了的问题

* 🎨 查成分增加可选择查uid
2022-05-06 20:02:36 +08:00
源文雨
3b277b0eb0 搜图 drop yandex 2022-05-06 18:54:39 +08:00
源文雨
5e0991681f 抽n张塔罗牌 2022-05-05 14:19:52 +08:00
源文雨
354fbb7cdd 抽n张塔罗牌 2022-05-05 14:19:33 +08:00
源文雨
a166d06096 抽n张塔罗牌 2022-05-05 14:19:12 +08:00
源文雨
b8a6e07095 优化每日随机 2022-05-05 13:50:54 +08:00
源文雨
a8fba6e7b5 优化GetLazyData 2022-05-05 13:31:22 +08:00
源文雨
17a8c10f8c 🎨 modify badge 2022-05-04 23:40:37 +08:00
源文雨
7ccd29faac 🎨 modify badge 2022-05-04 23:40:01 +08:00
源文雨
d432e48cce 🔖 1.4.0-beta4 2022-05-04 23:21:50 +08:00
莫思潋
19091319cc feat:抽塔罗牌 (#213)
* 优化在两个命令中使用空格分隔的体验
- fortune的设置底图功能
- b14的加密功能

* 优化四个插件中使用空格分隔的体验
- 加密
- 哔哩哔哩推送
- 藏头诗
- 运势

* 优化并修正了上一个commit
- 加上了因为复制粘贴疏忽又没有注意测试遗漏的`?`
- 调整藏头诗和加密的正则触发,使其不必多此一举
- 删去了未被发现的测试代码

* - 删去了遗漏的Trim

* 优化了更多插件中使用空格的体验
- 优化了music bilibili image_finder 中使用空格的体验
- 补上了plugin_bilibili中未实现的vup开头触发
- 为plugin_bilibili_parse输出的消息加上一个换行符,优化排版

* - 调整funny
- 补回readme中bilibili_push的注释说明

* - 简化funny说明

* feat:抽塔罗牌

* 🎨 改进代码样式

* 加上一个换行符

* 🎨 改进代码样式

* - At用户

* 🎨 改进代码样式

* -改进抽塔罗牌

* typo: 小写struct名

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-05-04 23:19:21 +08:00
源文雨
d29e12a92c fortune add plugin 夏日口袋 by @XHLin-gamer 2022-05-04 21:23:54 +08:00
himawari
5db03b0441 查成分新增字段注册日期 (#212)
*  查成分添加注册日期信息

* 🐛 修复头像是webp图片使用不了的问题
2022-05-03 14:42:58 +08:00
源文雨
f8c7e2bf6d 🔖 1.4.0-beta3 2022-05-02 10:56:49 +08:00
源文雨
a7fdc6a88f 🐛 服务列表不显示名称 2022-05-02 10:55:17 +08:00
莫思潋
4aaf5b0779 调整讲个笑话 (#210) 2022-05-02 10:46:53 +08:00
源文雨
6150e4c736 add playground instruction 2022-04-30 00:37:12 +08:00
98 changed files with 3654 additions and 1705 deletions

BIN
.github/gopher.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

View File

@@ -24,13 +24,13 @@ jobs:
goarch: arm64
fail-fast: true
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@master
- name: Setup Go environment
uses: actions/setup-go@v2.1.3
uses: actions/setup-go@master
with:
go-version: 1.18
- name: Cache downloaded module
uses: actions/cache@v2
uses: actions/cache@master
with:
path: |
~/.cache/go-build
@@ -48,7 +48,7 @@ jobs:
export CGO_ENABLED=0
go build -o "output/$BINARY_NAME" -trimpath -ldflags "$LD_FLAGS" .
- name: Upload artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@master
if: ${{ !github.head_ref }}
with:
name: ${{ matrix.goos }}_${{ matrix.goarch }}

View File

@@ -6,12 +6,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@master
with:
go-version: 1.18
- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@master
- name: golangci-lint
uses: golangci/golangci-lint-action@master

View File

@@ -6,12 +6,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@master
with:
go-version: 1.18
- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@master
- name: golangci-lint
uses: golangci/golangci-lint-action@master

View File

@@ -9,17 +9,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
uses: actions/checkout@master
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@master
with:
go-version: '1.18'
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
uses: goreleaser/goreleaser-action@master
with:
version: latest
args: release --rm-dist

BIN
.github/yaya.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

BIN
.github/黒金.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

194
README.md
View File

@@ -1,35 +1,42 @@
<div align="center">
<img src=".github/gopher.jpg" width = "200" height = "150" alt="Gopher"><br>
<a href="https://crypko.ai/crypko/5k8HyUVTq5421/">
<img src=".github/黒金.jpg" alt="看板娘" width = "400">
</a><br>
<h1>ZeroBot-Plugin</h1>
ZeroBot-Plugin 是 ZeroBot 的 实用插件合集<br><br>
<img src="http://sayuri.fumiama.top/cmoe?name=ZeroBot-Plugin&theme=r34" />
[![GOCQ](https://img.shields.io/badge/OneBot-MiraiGo-green.svg?style=social&logo=appveyor)](https://github.com/Mrs4s/go-cqhttp)
[![OICQ](https://img.shields.io/badge/OneBot-OICQ-green.svg?style=social&logo=appveyor)](https://github.com/takayama-lily/node-onebot)
[![MIRAI](https://img.shields.io/badge/OneBot-Mirai-green.svg?style=social&logo=appveyor)](https://github.com/yyuueexxiinngg/onebot-kotlin)
<img src="http://cmoe.azurewebsites.net/cmoe?name=ZeroBot-Plugin&theme=r34" /><br>
[![Go Report Card](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin?style=flat-square&logo=go)](https://goreportcard.com/report/github.com/github.com/FloatTech/ZeroBot-Plugin)
[![Badge](https://img.shields.io/badge/onebot-v11-black?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAMAAADxPgR5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////29vbr6+vAAAAk1hCcwAAAAR0Uk5T////AEAqqfQAAAKcSURBVHja7NrbctswDATQXfD//zlpO7FlmwAWIOnOtNaTM5JwDMa8E+PNFz7g3waJ24fviyDPgfhz8fHP39cBcBL9KoJbQUxjA2iYqHL3FAnvzhL4GtVNUcoSZe6eSHizBcK5LL7dBr2AUZlev1ARRHCljzRALIEog6H3U6bCIyqIZdAT0eBuJYaGiJaHSjmkYIZd+qSGWAQnIaz2OArVnX6vrItQvbhZJtVGB5qX9wKqCMkb9W7aexfCO/rwQRBzsDIsYx4AOz0nhAtWu7bqkEQBO0Pr+Ftjt5fFCUEbm0Sbgdu8WSgJ5NgH2iu46R/o1UcBXJsFusWF/QUaz3RwJMEgngfaGGdSxJkE/Yg4lOBryBiMwvAhZrVMUUvwqU7F05b5WLaUIN4M4hRocQQRnEedgsn7TZB3UCpRrIJwQfqvGwsg18EnI2uSVNC8t+0QmMXogvbPg/xk+Mnw/6kW/rraUlvqgmFreAA09xW5t0AFlHrQZ3CsgvZm0FbHNKyBmheBKIF2cCA8A600aHPmFtRB1XvMsJAiza7LpPog0UJwccKdzw8rdf8MyN2ePYF896LC5hTzdZqxb6VNXInaupARLDNBWgI8spq4T0Qb5H4vWfPmHo8OyB1ito+AysNNz0oglj1U955sjUN9d41LnrX2D/u7eRwxyOaOpfyevCWbTgDEoilsOnu7zsKhjRCsnD/QzhdkYLBLXjiK4f3UWmcx2M7PO21CKVTH84638NTplt6JIQH0ZwCNuiWAfvuLhdrcOYPVO9eW3A67l7hZtgaY9GZo9AFc6cryjoeFBIWeU+npnk/nLE0OxCHL1eQsc1IciehjpJv5mqCsjeopaH6r15/MrxNnVhu7tmcslay2gO2Z1QfcfX0JMACG41/u0RrI9QAAAABJRU5ErkJggg==)](https://github.com/howmanybots/onebot)
[![Badge](https://img.shields.io/badge/zerobot-v1.5.1-black?style=flat-square&logo=go)](https://github.com/wdvxdr1123/ZeroBot)
[![License](https://img.shields.io/github/license/FloatTech/ZeroBot-Plugin.svg?style=flat-square&logo=gnu)](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
[![qq group](https://img.shields.io/badge/group-1048452984-red?style=flat-square&logo=tencent-qq)](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
[![miraigo](https://img.shields.io/badge/OneBot-MiraiGo-green.svg?style=social&logo=appveyor)](https://github.com/Mrs4s/MiraiGo)
[![oicq](https://img.shields.io/badge/OneBot-OICQ-green.svg?style=social&logo=appveyor)](https://github.com/takayama-lily/oicq)
[![mirai](https://img.shields.io/badge/OneBot-Mirai-green.svg?style=social&logo=appveyor)](https://github.com/mamoe/mirai)
本项目符合 [OneBot](https://github.com/howmanybots/onebot) 标准,可基于以下项目与机器人框架/平台进行交互
| 项目地址 | 平台 | 核心作者 |
| --- | --- | --- |
| [Mrs4s/go-cqhttp](https://github.com/Mrs4s/go-cqhttp) | [MiraiGo](https://github.com/Mrs4s/MiraiGo) | Mrs4s |
| [yyuueexxiinngg/cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai) | [Mirai](https://github.com/mamoe/mirai) | yyuueexxiinngg |
| [takayama-lily/onebot](https://github.com/takayama-lily/onebot) | [OICQ](https://github.com/takayama-lily/oicq) | takayama |
[![go](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin?style=flat-square&logo=go)](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin)
[![onebot](https://img.shields.io/badge/onebot-v11-black?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAMAAADxPgR5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////29vbr6+vAAAAk1hCcwAAAAR0Uk5T////AEAqqfQAAAKcSURBVHja7NrbctswDATQXfD//zlpO7FlmwAWIOnOtNaTM5JwDMa8E+PNFz7g3waJ24fviyDPgfhz8fHP39cBcBL9KoJbQUxjA2iYqHL3FAnvzhL4GtVNUcoSZe6eSHizBcK5LL7dBr2AUZlev1ARRHCljzRALIEog6H3U6bCIyqIZdAT0eBuJYaGiJaHSjmkYIZd+qSGWAQnIaz2OArVnX6vrItQvbhZJtVGB5qX9wKqCMkb9W7aexfCO/rwQRBzsDIsYx4AOz0nhAtWu7bqkEQBO0Pr+Ftjt5fFCUEbm0Sbgdu8WSgJ5NgH2iu46R/o1UcBXJsFusWF/QUaz3RwJMEgngfaGGdSxJkE/Yg4lOBryBiMwvAhZrVMUUvwqU7F05b5WLaUIN4M4hRocQQRnEedgsn7TZB3UCpRrIJwQfqvGwsg18EnI2uSVNC8t+0QmMXogvbPg/xk+Mnw/6kW/rraUlvqgmFreAA09xW5t0AFlHrQZ3CsgvZm0FbHNKyBmheBKIF2cCA8A600aHPmFtRB1XvMsJAiza7LpPog0UJwccKdzw8rdf8MyN2ePYF896LC5hTzdZqxb6VNXInaupARLDNBWgI8spq4T0Qb5H4vWfPmHo8OyB1ito+AysNNz0oglj1U955sjUN9d41LnrX2D/u7eRwxyOaOpfyevCWbTgDEoilsOnu7zsKhjRCsnD/QzhdkYLBLXjiK4f3UWmcx2M7PO21CKVTH84638NTplt6JIQH0ZwCNuiWAfvuLhdrcOYPVO9eW3A67l7hZtgaY9GZo9AFc6cryjoeFBIWeU+npnk/nLE0OxCHL1eQsc1IciehjpJv5mqCsjeopaH6r15/MrxNnVhu7tmcslay2gO2Z1QfcfX0JMACG41/u0RrI9QAAAABJRU5ErkJggg==)](https://t.me/zerobotplugin)
[![zerobot](https://img.shields.io/badge/zerobot-v1.5.1-black?style=flat-square&logo=go)](https://github.com/wdvxdr1123/ZeroBot)
[![license](https://img.shields.io/github/license/FloatTech/ZeroBot-Plugin.svg?style=flat-square&logo=gnu)](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
[![tencent-qq](https://img.shields.io/badge/group-1048452984-red?style=flat-square&logo=tencent-qq)](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
[![telegram](https://img.shields.io/badge/Telegram-click%20me-informational?style=flat-square&logo=telegram)](https://t.me/zerobotplugin)
本项目符合 [OneBot](https://github.com/howmanybots/onebot) 标准,可基于以下项目与机器人框架/平台进行交互
| 项目地址 | 平台 | 核心作者 |
| --- | --- | --- |
| [Mrs4s/go-cqhttp](https://github.com/Mrs4s/go-cqhttp) | [MiraiGo](https://github.com/Mrs4s/MiraiGo) | Mrs4s |
| [yyuueexxiinngg/cqhttp-mirai](https://github.com/yyuueexxiinngg/cqhttp-mirai) | [Mirai](https://github.com/mamoe/mirai) | yyuueexxiinngg |
| [takayama-lily/onebot](https://github.com/takayama-lily/onebot) | [OICQ](https://github.com/takayama-lily/oicq) | takayama |
</div>
> 如果您不知道什么是 [OneBot](https://github.com/howmanybots/onebot) 或不希望运行多个程序,还可以直接前往 [gocqzbp](https://github.com/FloatTech/gocqzbp) 的 [Release](https://github.com/FloatTech/gocqzbp/releases) 页面下载单一可执行文件或前往 [Packages](https://github.com/FloatTech/gocqzbp/pkgs/container/gocqzbp) 页面使用`docker`,运行后按提示登录即可。
> 如果您对开发插件感兴趣,欢迎加入[ZeroBot-Plugin-Playground](https://github.com/FloatTech/ZeroBot-Plugin-Playground)
## 命令行参数
> `[]`代表是可选参数
```bash
zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname] [-p prefix] [-d|w] [-g 监听地址:端口] [qq1 qq2 qq3 ...] [&]
zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname] [-p prefix] [-d|w] [qq1 qq2 qq3 ...] [&]
```
- **-c config.json**: 从`config.json`加载`bot`配置
- **-h**: 显示帮助
@@ -39,7 +46,6 @@ zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname]
- **-n nickname**: 设置默认昵称,默认为`椛椛`
- **-p prefix**: 设置命令前缀,默认为`/`
- **-d|w**: 开启 debug | warning 级别及以上日志输出
- **-g 监听地址:端口**: 在 http://监听地址:端口 上开启 [webgui](https://github.com/FloatTech/bot-manager)
- **qqs**: superusers 的 qq 号
- **&**: 驻留在后台,必须放在最后,仅`Linux`下有效
@@ -86,6 +92,8 @@ zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname]
- 注:当全局未配置或与默认相同时,状态取决于单独配置,后备为默认配置;当全局与默认不同时,状态取决于全局配置,单独配置失效。
- [x] /改变默认启用状态 xxx
- [x] /禁止 service qq1 qq2... (禁止 qqs 使用服务 service)
- [x] /允许 service qq1 qq2... (重新允许 qqs 使用服务 service)
@@ -113,16 +121,6 @@ zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname]
</details>
### *高优先级*
<details>
<summary>web管理</summary>
`import _ "github.com/FloatTech/zbputils/control/web"`
- 开启后可执行文件大约增加 5M ,默认注释不开启。如需开启请自行编辑`main.go`取消注释
- 需要配合 [webgui](https://github.com/FloatTech/bot-manager) 使用
</details>
<details>
<summary>聊天</summary>
@@ -311,6 +309,15 @@ print("run[CQ:image,file="+j["img"]+"]")
```
![随机b站404页趣图](https://user-images.githubusercontent.com/41315874/157371451-c09ad3bb-c61a-4a42-9c47-fab3305bc0f8.png)
- [x] [我|大家|有人][说|问][正则表达式]你[答|说|做|执行][模版]
- [x] [查看|看看][我|大家|有人][说|问][正则表达式]
- [x] 删除[大家|有人|我][说|问|让你做|让你执行][正则表达式]
- 注:模版是指含有`$1` `$2`这样的未定参数,会在正则匹配时按顺序填入子匹配对应值
</details>
### *中优先级*
@@ -322,11 +329,7 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]
- [x] 清理缓存 (仅适用于 gocq 且需要 bot 的运行目录和 gocq 相同)
- [ ] 简易语音
- [ ] 爬图合成 [@xxx]
- [x] 设置默认限速为每 m [分钟 | 秒] n 次触发
</details>
<details>
@@ -474,6 +477,20 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 注:不显式限制时,私聊发送可在所有群抽到,群聊发送仅可在本群抽到,默认频道为 global
</details>
<details>
<summary>一群一天一夫一妻制群老婆</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife"`
- [x] 娶群友
- [x] (娶|嫁)[@对方QQ]
- [x] 当[对方Q号|@对方QQ]的小三
- [x] 群老婆列表
</details>
<details>
<summary>合成emoji</summary>
@@ -505,7 +522,7 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 运势 | 抽签
- [x] 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师 赛马娘 东方归言录 奇异恩典]
- [x] 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师 赛马娘 东方归言录 奇异恩典 夏日口袋 ASoul]
</details>
<details>
@@ -513,7 +530,7 @@ print("run[CQ:image,file="+j["img"]+"]")
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/funny"`
- [x] 讲个笑话[@xxx] | 讲个笑话[qq号]
- [x] 讲个笑话[@xxx|qq号|人名] | 夸夸[@xxx|qq号|人名]
</details>
<details>
@@ -549,6 +566,30 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] >github -p [xxx]
</details>
<details>
<summary>猜歌</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/guessmusic"`
- 猜歌插件该插件依赖ffmpeg
- [x] 个人猜歌
- [x] 团队猜歌
- [x] 设置猜歌缓存歌库路径 [绝对路径]
- [x] 设置猜歌本地 [true/false]
- [x] 设置猜歌Api [true/false]
- 注:默认歌库为网易云热歌榜
- 1.可在后面添加“-动漫”进行动漫歌猜歌(这个只能猜歌名和歌手)
- 2.可在后面添加“-动漫2”进行动漫歌猜歌(这个可以猜番名,但歌手经常“未知”)
</details>
<details>
<summary>炉石</summary>
@@ -612,8 +653,37 @@ print("run[CQ:image,file="+j["img"]+"]")
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon"`
- [x] 来份萝莉
- [x] 设置随机图片地址[http...]
- 每一小时发一张图
```
记录在"@every 1h"触发的指令
来份萝莉
```
</details>
<details>
<summary>简易midi音乐制作</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/midicreate"`
- [x] midi制作 CCGGAAGR FFEEDDCR GGFFEEDR GGFFEEDR CCGGAAGR FFEEDDCR
- [x] 个人听音练习
- [x] 团队听音练习
- [x] *.mid (midi 转 txt)
- [x] midi制作*.txt (txt 转 midi)
- [x] 设置音色40 (0~127)
- [x] 注: 该插件需要安装timidity,linux安装脚本可参考 https://gitcode.net/anto_july/midi/-/raw/master/timidity.sh , windows安装脚本可参考 https://gitcode.net/anto_july/midi/-/raw/master/timidity.bat , windows需要管理员模式运行
- [x] 符号说明: C5是中央C,后面不写数字,默认接5,Cb6<1,b代表降调,#代表升调,6比5高八度,<1代表音长×2,<3代表音长×8,<-1代表音长×0.5,<-3代表音长×0.125,R是休止符
</details>
<details>
<summary>摸鱼</summary>
@@ -770,12 +840,26 @@ print("run[CQ:image,file="+j["img"]+"]")
</details>
<details>
<summary>签到得分</summary>
<summary>签到得分</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_score"`
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/score"`
- [x] 签到
- [x] 获得签到背景[@xxx] | 获得签到背景
- [x] 获得签到背景[@xxx] | 获得签到背景
</details>
<details>
<summary>沙雕app</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/shadiao"`
- [x] 哄我
- [x] 渣我
- [x] 来碗绿茶
- [x] 发个朋友圈
- [x] 来碗毒鸡汤
- [x] 讲个段子
- [x] 马丁路德骂我
</details>
<details>
@@ -793,6 +877,17 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 黄油角色[@xxx]
</details>
<details>
<summary>抽塔罗牌</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/tarot"`
- [x] 抽塔罗牌
- [x] 抽n张塔罗牌
- [x] 解塔罗牌[牌名]
- [x] 塔罗牌阵[圣三角|时间之流|四要素|五牌阵|吉普赛十字|马蹄|六芒星]"
</details>
<details>
<summary>搜番</summary>
@@ -855,23 +950,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 更新gal
</details>
<details>
<summary>早报</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/zaobao"`
- api早上8点更新推荐定时在8点30后。配合插件`job`中的记录在"cron"触发的指令使用
- [x] /启用 zaobao
- [x] /禁用 zaobao
```
记录在"00 9 * * *"触发的指令
今日早报
```
</details>
<details>
<summary>舔狗日记</summary>
@@ -916,6 +994,8 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] b站推送列表
-由于需要安装Chrome默认注释具体看[这里](https://www.yuque.com/xiangrikuidezhongzi/zerobot/qrwxth)
</details>
### *低优先级*
@@ -939,10 +1019,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 设置回复模式[青云客 | 小爱]
</details>
<details>
<summary>TODO...</summary>
</details>
## 三种使用方法,推荐第一种

2
data

Submodule data updated: e2591640c4...5ce4b48c12

46
go.mod
View File

@@ -3,43 +3,58 @@ module github.com/FloatTech/ZeroBot-Plugin
go 1.18
require (
github.com/FloatTech/AnimeAPI v1.3.4-0.20220428145645-93a688024a47
github.com/FloatTech/sqlite v0.2.1
github.com/FloatTech/zbputils v1.3.4-0.20220429123316-f504c32b198b
github.com/antchfx/htmlquery v1.2.4
github.com/FloatTech/AnimeAPI v1.4.1-0.20220613042537-0adf8c5616ec
github.com/FloatTech/sqlite v0.3.2
github.com/FloatTech/zbpctrl v1.4.1-0.20220610074608-425160596f27
github.com/FloatTech/zbputils v1.4.1-0.20220613042833-33e22060e8d9
github.com/antchfx/htmlquery v1.2.5
github.com/corona10/goimagehash v1.0.3
github.com/fogleman/gg v1.3.0
github.com/fumiama/cron v1.3.0
github.com/fumiama/go-base16384 v1.5.2
github.com/fumiama/go-base16384 v1.5.3
github.com/fumiama/go-registry v0.1.6
github.com/fumiama/gofastTEA v0.0.10
github.com/fumiama/gotracemoe v0.0.3
github.com/fumiama/sqlite3 v1.14.6
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/jinzhu/gorm v1.9.16
github.com/jozsefsallai/gophersauce v1.0.1
github.com/lucas-clemente/quic-go v0.27.2
github.com/mroth/weightedrand v0.4.1
github.com/pkg/errors v0.8.1
github.com/pkumza/numcn v1.0.0
github.com/shirou/gopsutil/v3 v3.22.3
github.com/sirupsen/logrus v1.8.1
github.com/tidwall/gjson v1.14.1
github.com/wcharczuk/go-chart/v2 v2.1.0
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220429121512-29258eb2cd2d
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220610070647-9eeffcb277ee
gitlab.com/gomidi/midi/v2 v2.0.17
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd
)
require (
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c // indirect
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc // indirect
github.com/antchfx/xpath v1.2.0 // indirect
github.com/antchfx/xpath v1.2.1 // indirect
github.com/cheekybits/genny v1.0.0 // indirect
github.com/disintegration/imaging v1.6.2 // indirect
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gabriel-vasile/mimetype v1.0.4 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/marten-seemann/qpack v0.2.1 // indirect
github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.4 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/tidwall/match v1.1.1 // indirect
@@ -47,10 +62,15 @@ require (
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 // indirect
golang.org/x/text v0.3.7 // indirect
modernc.org/libc v1.14.6 // indirect
golang.org/x/tools v0.1.1 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
modernc.org/libc v1.16.8 // indirect
modernc.org/mathutil v1.4.1 // indirect
modernc.org/memory v1.0.5 // indirect
modernc.org/memory v1.1.1 // indirect
)

314
go.sum
View File

@@ -1,19 +1,39 @@
github.com/FloatTech/AnimeAPI v1.3.4-0.20220428145645-93a688024a47 h1:/91ayCAwvhyJw9iQ4so9QDfJcu1GMPFJNTq1JjePkcY=
github.com/FloatTech/AnimeAPI v1.3.4-0.20220428145645-93a688024a47/go.mod h1:K10BsQlE9FJtDRfcjvH2XNX/JFejWfL3oTdMjHvEHr4=
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.4-0.20220429123316-f504c32b198b h1:S+DVRtlWVCzUV2jF5TDucPF/yyGkI1S4Um2gnZF/1co=
github.com/FloatTech/zbputils v1.3.4-0.20220429123316-f504c32b198b/go.mod h1:yYXxsdc8fouB9yd2XMr17wso2TV0fH1ukARwhV3U43M=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/FloatTech/AnimeAPI v1.4.1-0.20220613042537-0adf8c5616ec h1:Hl/BxaQoQFEJUIGmdhR0NyBvZChb7qkfCrF916bNxnI=
github.com/FloatTech/AnimeAPI v1.4.1-0.20220613042537-0adf8c5616ec/go.mod h1:MrCZ7P6WvF0JWHMeedAx6fVm5BP1s6/RUy0r0Jvqrds=
github.com/FloatTech/sqlite v0.3.2 h1:iTg2ZKnzjjZAdlSN3hXmpCBn15odc4Ud484OoM3yXGA=
github.com/FloatTech/sqlite v0.3.2/go.mod h1:VFtLofV5qxw5eBneZRbWwD451SLSm50o9J3J43iB1iw=
github.com/FloatTech/zbpctrl v1.4.1-0.20220610074608-425160596f27 h1:C+D30vpxfgbJetTFXWAHzuU8GydbFb/A8Kv6E3PdRS4=
github.com/FloatTech/zbpctrl v1.4.1-0.20220610074608-425160596f27/go.mod h1:5FDkrlVaQCxUfeqH7XJPTfej0q+y9fzImhvZI4ofu9Y=
github.com/FloatTech/zbputils v1.4.1-0.20220613042833-33e22060e8d9 h1:IeUs08sUqdR/g8DfxPNTSBfsE1g0OtmffLNgKzbrVZ4=
github.com/FloatTech/zbputils v1.4.1-0.20220613042833-33e22060e8d9/go.mod h1:A9AeVHZsv5chyw8p4fDI0cHnEOfMpmsTLoLWqUT7TO4=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c h1:cNPOdTNiVwxLpROLjXCgbIPvdkE+BwvxDvgmdYmWx6Q=
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c/go.mod h1:KqZzu7slNKROh3TSYEH/IUMG6f4M+1qubZ5e52QypsE=
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=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/antchfx/htmlquery v1.2.4 h1:qLteofCMe/KGovBI6SQgmou2QNyedFUW+pE+BpeZ494=
github.com/antchfx/htmlquery v1.2.4/go.mod h1:2xO6iu3EVWs7R2JYqBbp8YzG50gj/ofqs5/0VZoDZLc=
github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8=
github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antchfx/htmlquery v1.2.5 h1:1lXnx46/1wtv1E/kzmH8vrfMuUKYgkdDBA9pIdMJnk4=
github.com/antchfx/htmlquery v1.2.5/go.mod h1:2MCVBzYVafPBmKbrmwB9F5xdd+IEgRY61ci2oOsOQVw=
github.com/antchfx/xpath v1.2.1 h1:qhp4EW6aCOVr5XIkT+l6LJ9ck/JsUH/yyauNgTQkBF8=
github.com/antchfx/xpath v1.2.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/corona10/goimagehash v1.0.3 h1:NZM518aKLmoNluluhfHGxT3LGOnrojrxhGn63DR/CZA=
github.com/corona10/goimagehash v1.0.3/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -28,12 +48,17 @@ github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+Jl
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
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.5.2 h1:cbxXTcDH92PNgG7bEBwiCEoWb5O+nwZKxKOG94ilFo8=
github.com/fumiama/go-base16384 v1.5.2/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
github.com/fumiama/go-base16384 v1.5.3 h1:IUZUlm2ajJB1nEJzauP6yD5IeJoVHyBEkzKJf9O82zs=
github.com/fumiama/go-base16384 v1.5.3/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
github.com/fumiama/go-registry v0.1.6 h1:Ee/tXCCIR/xt8celhbbw0W/xDMdhAXLwy2YFBB/LWFk=
github.com/fumiama/go-registry v0.1.6/go.mod h1:dIUVbiOgfk9oZcsgwDvNLC72i+ctibVukSXR/9bLviI=
github.com/fumiama/gofastTEA v0.0.10 h1:JJJ+brWD4kie+mmK2TkspDXKzqq0IjXm89aGYfoGhhQ=
@@ -42,59 +67,178 @@ github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
github.com/fumiama/sqlite3 v1.14.6 h1:+e+iygyiDXQJVi7xeXIviBvR7hAc5y20WA9hRwfKn10=
github.com/fumiama/sqlite3 v1.14.6/go.mod h1:Xx9a2/OtHuy9pBjow0N+bE/RhNeZ7zZz5xh25vqbA5A=
github.com/gabriel-vasile/mimetype v1.0.4 h1:uBejfH8l3/2f+5vjl1e4xIaSyNEhRBZ5N/ij7ohpNd8=
github.com/gabriel-vasile/mimetype v1.0.4/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM=
github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lucas-clemente/quic-go v0.27.2 h1:zsMwwniyybb8B/UDNXRSYee7WpQJVOcjQEGgpw2ikXs=
github.com/lucas-clemente/quic-go v0.27.2/go.mod h1:vXgO/11FBSKM+js1NxoaQ/bPtVFYfB7uxhfHXyMhl1A=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs=
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ=
github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ=
github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s=
github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM=
github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mroth/weightedrand v0.4.1 h1:rHcbUBopmi/3x4nnrvwGJBhX9d0vk+KgoLUZeDP6YyI=
github.com/mroth/weightedrand v0.4.1/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkumza/numcn v1.0.0 h1:ZT5cf9IJkUZgRgEtCiNNykk0RwsrKXSTsvDHOwUTzgE=
github.com/pkumza/numcn v1.0.0/go.mod h1:QSeH+al9dWCd8di5HZM/ZqHqhZmUKfph572e9Ev/ETc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil/v3 v3.22.3 h1:UebRzEomgMpv61e3hgD1tGooqX5trFbdU/ehphbHd00=
github.com/shirou/gopsutil/v3 v3.22.3/go.mod h1:D01hZJ4pVHPpCTZ3m3T2+wDF2YAGfd+H4ifUguaQzHM=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
@@ -105,67 +249,176 @@ github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03O
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220429121512-29258eb2cd2d h1:gi/AuWH5LRwdKzftIqMA/YGrI1g82E8Ol80HG+u3evU=
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220429121512-29258eb2cd2d/go.mod h1:LJ+VOf523i3IrykuLK53UEeWqnAclRL5d2wGT4sS4Zk=
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220610070647-9eeffcb277ee h1:b2f+KLhZv+BCMQZuwMJvhKQOrz5YXzOduHC3G1DjQR0=
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220610070647-9eeffcb277ee/go.mod h1:LJ+VOf523i3IrykuLK53UEeWqnAclRL5d2wGT4sS4Zk=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
gitlab.com/gomidi/midi/v2 v2.0.17 h1:kf16wNwFFOskl0trvarOwMuZUQICdIGn37LP9QqIRuo=
gitlab.com/gomidi/midi/v2 v2.0.17/go.mod h1:quTyMKSQ4Klevxu6gY4gy2USbeZra0fV5SalndmPfsY=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE=
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd h1:9NbNcTg//wfC5JskFW4Z3sqwVnjmJKHxLAol1bW2qgw=
golang.org/x/image v0.0.0-20220601225756-64ec528b34cd/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 h1:z8Hj/bl9cOV2grsOpEaQFUaly0JWN3i97mo3jXKJNp0=
golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
@@ -183,6 +436,9 @@ modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=
modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw=
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
@@ -224,8 +480,11 @@ modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi
modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0=
modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8=
modernc.org/ccgo/v3 v3.15.12/go.mod h1:VFePOWoCd8uDGRJpq/zfJ29D0EVzMSyID8LCMWYbX6I=
modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
@@ -268,16 +527,21 @@ modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34=
modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ=
modernc.org/libc v1.14.5/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
modernc.org/libc v1.14.6 h1:SSiZiE5199iYsGM9gtkDj90xqcXVwubWG8CtoYE+Mnk=
modernc.org/libc v1.14.6/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A=
modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU=
modernc.org/libc v1.16.8 h1:Ux98PaOMvolgoFX/YwusFOHBnanXdGRmWgI8ciI2z4o=
modernc.org/libc v1.16.8/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU=
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

View File

@@ -10,13 +10,13 @@ import (
var (
info = [...]string{
"* OneBot + ZeroBot + Golang",
"* Version 1.4.0-beta2 - 2022-04-29 20:41:26 +0800 CST",
"* Version 1.5.0-beta1 - 2022-07-03 09:51:04 +0800 CST",
"* 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")
reg = registry.NewRegReader("reilia.fumiama.top:32664", "fumiama")
)
// PrintBanner ...

12
main.go
View File

@@ -25,8 +25,6 @@ import (
// vvvvvvvvvvvvvv //
// vvvv //
// webctrl "github.com/FloatTech/zbputils/control/web" // web 后端控制
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat" // 基础词库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleep_manage" // 统计睡眠时间
@@ -80,6 +78,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/genshin" // 原神抽卡
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/gif" // 制图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/github" // 搜索GitHub仓库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/guessmusic" // 猜歌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs" // 炉石
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hyaku" // 百人一首
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/image_finder" // 关键字搜图
@@ -87,6 +86,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jandan" // 煎蛋网无聊图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi" // 绝绝子生成器
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon" // lolicon 随机图片
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/midicreate" // 简易midi音乐制作
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu" // 摸鱼
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu_calendar" // 摸鱼人日历
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/music" // 点歌
@@ -96,6 +96,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/novel" // 铅笔小说网搜索
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nsfw" // nsfw图片识别
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/omikuji" // 浅草寺求签
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife" // 一群一天一夫一妻制群老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/reborn" // 投胎
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode" // 在线运行代码
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/saucenao" // 以图搜图
@@ -104,6 +105,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/setutime" // 来份涩图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shadiao" // 沙雕app
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shindan" // 测定
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tarot" // 抽塔罗牌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou" // 舔狗日记
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tracemoe" // 搜番
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/translation" // 翻译
@@ -112,7 +114,6 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count" // 聊天热词
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/zaobao" // 早报
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf" // 鬼东西
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili_push" // b站推送
@@ -162,8 +163,6 @@ import (
func init() {
sus := make([]int64, 0, 16)
// 解析命令行参数
// 输入 `-g 监听地址:端口` 指定 gui 访问地址,默认 127.0.0.1:3000
// g := flag.String("g", "127.0.0.1:3000", "Set web gui listening address.")
d := flag.Bool("d", false, "Enable debug level log and higher.")
w := flag.Bool("w", false, "Enable warning level log and higher.")
h := flag.Bool("h", false, "Display this help.")
@@ -205,9 +204,6 @@ func init() {
// sus = append(sus, 12345678)
// sus = append(sus, 87654321)
// 启用 gui
// webctrl.InitGui(*g)
if *runcfg != "" {
f, err := os.Open(*runcfg)
if err != nil {

View File

@@ -4,24 +4,39 @@ package aifalse
import (
"fmt"
"math"
"os"
"strconv"
"time"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/mem"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() { // 插件主体
engine := control.Register("aifalse", &control.Options{
engine := control.Register("aifalse", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "AIfalse\n" +
"- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]",
"- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]\n" +
"- 设置默认限速为每 m [分钟 | 秒] n 次触发",
})
c, ok := control.Lookup("aifalse")
if !ok {
panic("register aifalse error")
}
m := c.GetData(0)
n := (m >> 16) & 0xffff
m &= 0xffff
if m != 0 || n != 0 {
ctxext.SetDefaultLimiterManagerParam(time.Duration(m)*time.Second, int(n))
logrus.Infoln("设置默认限速为每", m, "秒触发", n, "次")
}
engine.OnFullMatchGroup([]string{"检查身体", "自检", "启动自检", "系统状态"}, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(
@@ -31,14 +46,41 @@ func init() { // 插件主体
),
)
})
engine.OnFullMatch("清理缓存", zero.SuperUserPermission).SetBlock(true).
engine.OnRegex(`^设置默认限速为每\s*(\d+)\s*(分钟|秒)\s*(\d+)\s*次触发$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
err := os.RemoveAll("data/cache/*")
if err != nil {
ctx.SendChain(message.Text("错误: ", err.Error()))
} else {
ctx.SendChain(message.Text("成功!"))
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("ERROR:no such plugin"))
return
}
m, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if ctx.State["regex_matched"].([]string)[2] == "分钟" {
m *= 60
}
if m >= 65536 || m <= 0 {
ctx.SendChain(message.Text("ERROR:interval too big"))
return
}
n, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[3], 10, 64)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if n >= 65536 || n <= 0 {
ctx.SendChain(message.Text("ERROR:burst too big"))
return
}
ctxext.SetDefaultLimiterManagerParam(time.Duration(m)*time.Second, int(n))
err = c.SetData(0, (m&0xffff)|((n<<16)&0xffff0000))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("设置默认限速为每", m, "秒触发", n, "次"))
})
}

View File

@@ -1,7 +1,6 @@
package aireply
import (
"errors"
"regexp"
"strconv"
"sync"
@@ -15,6 +14,7 @@ import (
"github.com/FloatTech/AnimeAPI/tts"
"github.com/FloatTech/AnimeAPI/tts/baidutts"
"github.com/FloatTech/AnimeAPI/tts/mockingbird"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
)
@@ -45,25 +45,31 @@ func init() {
"百度度逍遥": baidutts.NewBaiduTTS(3),
"百度度丫丫": baidutts.NewBaiduTTS(4),
"拟声鸟阿梓": nil,
"拟声鸟文静": nil,
"拟声鸟药水哥": nil,
},
l: []string{"拟声鸟阿梓", "拟声鸟药水哥", "百度女声", "百度男声", "百度度逍遥", "百度度丫丫"},
l: []string{"拟声鸟阿梓", "拟声鸟文静", "拟声鸟药水哥", "百度女声", "百度男声", "百度度逍遥", "百度度丫丫"},
}
engine := control.Register(ttsServiceName, &control.Options{
engine := control.Register(ttsServiceName, &ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Help: "语音回复(包括拟声鸟和百度)\n" +
"- @Bot 任意文本(任意一句话回复)\n" +
"- 设置语音模式[拟声鸟阿梓 | 拟声鸟药水哥 | 百度女声 | 百度男声| 百度度逍遥 | 百度度丫丫]\n" +
"- 设置默认语音模式[拟声鸟阿梓 | 拟声鸟药水哥 | 百度女声 | 百度男声| 百度度逍遥 | 百度度丫丫]\n",
"- 设置语音模式[拟声鸟阿梓 | 拟声鸟文静 | 拟声鸟药水哥 | 百度女声 | 百度男声| 百度度逍遥 | 百度度丫丫]\n" +
"- 设置默认语音模式[拟声鸟阿梓 | 拟声鸟文静 | 拟声鸟药水哥 | 百度女声 | 百度男声| 百度度逍遥 | 百度度丫丫]\n",
})
engine.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
msg := ctx.ExtractPlainText()
r := aireply.NewAIReply(getReplyMode(ctx))
tts := t.new(t.getSoundMode(ctx))
tts, err := t.new(t.getSoundMode(ctx))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
var reply string
if tts != nil {
ctx.SendChain(message.Record(tts.Speak(ctx.Event.UserID, func() string {
reply := r.TalkPlain(msg, zero.BotConfig.NickName[0])
rec, err := tts.Speak(ctx.Event.UserID, func() string {
reply = r.TalkPlain(msg, zero.BotConfig.NickName[0])
reply = re.ReplaceAllStringFunc(reply, func(s string) string {
f, err := strconv.ParseFloat(s, 64)
if err != nil {
@@ -74,10 +80,15 @@ func init() {
})
log.Debugln("[tts]:", reply)
return reply
})))
})
if err == nil {
ctx.SendChain(message.Record(rec))
} else {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
}
}
})
engine.OnRegex(`^设置语音模式(.*)$`, ctxext.FirstValueInList(t)).SetBlock(true).
engine.OnRegex(`^设置语音模式(.*)$`, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, t)).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
param := ctx.State["regex_matched"].([]string)[1]
err := t.setSoundMode(ctx, param)
@@ -87,7 +98,7 @@ func init() {
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前模式为", param))
})
engine.OnRegex(`^设置默认语音模式(.*)$`, ctxext.FirstValueInList(t)).SetBlock(true).
engine.OnRegex(`^设置默认语音模式(.*)$`, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, t)).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
param := ctx.State["regex_matched"].([]string)[1]
t.setDefaultSoundMode(param)
@@ -96,7 +107,7 @@ func init() {
}
// new 语音简单工厂
func (t *ttsInstances) new(name string) (ts tts.TTS) {
func (t *ttsInstances) new(name string) (ts tts.TTS, err error) {
t.RLock()
ts = t.m[name]
t.RUnlock()
@@ -104,11 +115,15 @@ func (t *ttsInstances) new(name string) (ts tts.TTS) {
switch name {
case "拟声鸟阿梓":
t.Lock()
ts, _ = mockingbird.NewMockingBirdTTS(0)
ts, err = mockingbird.NewMockingBirdTTS(0)
t.Unlock()
case "拟声鸟文静":
t.Lock()
ts, err = mockingbird.NewMockingBirdTTS(1)
t.Unlock()
case "拟声鸟药水哥":
t.Lock()
ts, _ = mockingbird.NewMockingBirdTTS(1)
ts, err = mockingbird.NewMockingBirdTTS(2)
t.Unlock()
}
}
@@ -129,10 +144,7 @@ func (t *ttsInstances) setSoundMode(ctx *zero.Ctx, name string) error {
}
}
t.RUnlock()
m, ok := control.Lookup(ttsServiceName)
if !ok {
return errors.New("no such plugin")
}
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
return m.SetData(gid, index)
}
@@ -141,7 +153,7 @@ func (t *ttsInstances) getSoundMode(ctx *zero.Ctx) (name string) {
if gid == 0 {
gid = -ctx.Event.UserID
}
m, ok := control.Lookup(ttsServiceName)
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
t.RLock()
defer t.RUnlock()

View File

@@ -6,7 +6,8 @@ import (
"time"
"github.com/FloatTech/AnimeAPI/aireply"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -19,7 +20,7 @@ const (
var replyModes = [...]string{"青云客", "小爱"}
func init() { // 插件主体
engine := control.Register(replyServiceName, &control.Options{
engine := control.Register(replyServiceName, &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "人工智能回复\n" +
"- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客 | 小爱]\n- ",
@@ -67,7 +68,7 @@ func setReplyMode(ctx *zero.Ctx, name string) error {
if !ok {
return errors.New("no such mode")
}
m, ok := control.Lookup(replyServiceName)
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
return errors.New("no such plugin")
}
@@ -79,7 +80,7 @@ func getReplyMode(ctx *zero.Ctx) (name string) {
if gid == 0 {
gid = -ctx.Event.UserID
}
m, ok := control.Lookup(replyServiceName)
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
index := m.GetData(gid)
if int(index) < len(replyModes) {

View File

@@ -5,7 +5,8 @@ import (
"fmt"
"math/rand"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -16,7 +17,7 @@ const (
)
func init() { // 插件主体
control.Register("aiwife", &control.Options{
control.Register("aiwife", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "AIWife\n" +
"- waifu | 随机waifu",

View File

@@ -12,7 +12,8 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/process"
)
@@ -24,7 +25,7 @@ const (
)
func init() { // 插件主体
engine := control.Register(servicename, &control.Options{
engine := control.Register(servicename, &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "本插件基于 ATRI ,为 Golang 移植版\n" +
"- ATRI醒醒\n- ATRI睡吧\n- 萝卜子\n- 喜欢 | 爱你 | 爱 | suki | daisuki | すき | 好き | 贴贴 | 老婆 | 亲一个 | mua\n" +

View File

@@ -4,7 +4,8 @@ package b14coder
import (
"unsafe"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
base14 "github.com/fumiama/go-base16384"
tea "github.com/fumiama/gofastTEA"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -13,12 +14,12 @@ import (
)
func init() {
en := control.Register("base16384", &control.Options{
en := control.Register("base16384", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "base16384加解密\n" +
"- 加密xxx\n- 解密xxx\n- 用yyy加密xxx\n- 用yyy解密xxx",
})
en.OnRegex(`^加密\s?(.*)`).SetBlock(true).
en.OnRegex(`^加密\s*(.*)`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es := base14.EncodeString(str)
@@ -28,7 +29,7 @@ func init() {
ctx.SendChain(message.Text("加密失败!"))
}
})
en.OnRegex(`^解密\s?([一-踀]*[㴁-㴆]?)$`).SetBlock(true).
en.OnRegex(`^解密\s*([一-踀]*[㴁-㴆]?)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es := base14.DecodeString(str)
@@ -38,7 +39,7 @@ func init() {
ctx.SendChain(message.Text("解密失败!"))
}
})
en.OnRegex(`^用(.*)加密\s?(.*)`).SetBlock(true).
en.OnRegex(`^用(.*)加密\s*(.*)`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := getea(key)
@@ -49,7 +50,7 @@ func init() {
ctx.SendChain(message.Text("加密失败!"))
}
})
en.OnRegex(`^用(.*)解密\s?([一-踀]*[㴁-㴆]?)$`).SetBlock(true).
en.OnRegex(`^用(.*)解密\s*([一-踀]*[㴁-㴆]?)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := getea(key)

View File

@@ -7,12 +7,13 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
)
func init() {
control.Register("baidu", &control.Options{
control.Register("baidu", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "baidu\n" +
"- 百度下[xxx]",

View File

@@ -85,14 +85,14 @@ func followings(uid string) (s string, err error) {
if err != nil {
return
}
json := gjson.ParseBytes(body)
s = json.Get("data.list.#.uname").Raw
if json.Get("code").Int() == -101 {
j := gjson.ParseBytes(body)
s = j.Get("data.list.#.uname").Raw
if j.Get("code").Int() == -101 {
err = errNeedCookie
return
}
if json.Get("code").Int() != 0 {
err = errors.New(json.Get("message").String())
if j.Get("code").Int() != 0 {
err = errors.New(j.Get("message").String())
return
}
return
@@ -103,6 +103,7 @@ type userinfo struct {
Mid string `json:"mid"`
Face string `json:"face"`
Fans int64 `json:"fans"`
Regtime int64 `json:"regtime"`
Attentions []int64 `json:"attentions"`
}

View File

@@ -4,13 +4,17 @@ package bilibili
import (
"encoding/binary"
"fmt"
"image"
"image/color"
"os"
"path"
"regexp"
"sort"
"strconv"
"time"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img"
@@ -23,7 +27,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
)
var engine = control.Register("bilibili", &control.Options{
var engine = control.Register("bilibili", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "bilibili\n" +
"- >vup info [xxx]\n" +
@@ -33,6 +37,7 @@ var engine = control.Register("bilibili", &control.Options{
"- 更新vup",
PublicDataFolder: "Bilibili",
})
var re = regexp.MustCompile(`^\d+$`)
// 查成分的
func init() {
@@ -41,9 +46,8 @@ func init() {
_ = os.MkdirAll(cachePath, 0755)
var getdb = ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
var err error
dbfile := engine.DataFolder() + "bilibili.db"
_, _ = file.GetLazyData(dbfile, false, false)
vdb, err = initialize(dbfile)
_, _ = engine.GetLazyData("bilibili.db", false)
vdb, err = initialize(engine.DataFolder() + "bilibili.db")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
@@ -103,15 +107,9 @@ func init() {
))
})
engine.OnRegex(`^查成分\s?(.{1,25})$`, getdb).SetBlock(true).
engine.OnRegex(`^查成分\s?(.{1,25})$`, getdb, getPara).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]
searchRes, err := search(keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
id := strconv.FormatInt(searchRes[0].Mid, 10)
id := ctx.State["uid"].(string)
today := time.Now().Format("20060102")
drawedFile := cachePath + id + today + "vupLike.png"
if file.IsExist(drawedFile) {
@@ -153,35 +151,36 @@ func init() {
i--
}
}
facePath := cachePath + id + "vupFace.png"
err = initFacePic(facePath, u.Face)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
facePath := cachePath + id + "vupFace" + path.Ext(u.Face)
backX := 500
backY := 500
var back image.Image
if path.Ext(u.Face) != ".webp" {
err = initFacePic(facePath, u.Face)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
back, err = gg.LoadImage(facePath)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
back = img.Size(back, backX, backY).Im
}
var backX int
var backY int
back, err := gg.LoadImage(facePath)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
back = img.Limit(back, 500, 500)
backX = back.Bounds().Size().X
backY = back.Bounds().Size().Y
if len(vups) > 50 {
ctx.SendChain(message.Text(u.Name + "关注的up主太多了只展示前50个up"))
vups = vups[:50]
}
canvas := gg.NewContext(backX*3, int(float64(backY)*(1.1+float64(len(vups))/3)))
fontSize := float64(backX) * 0.1
canvas := gg.NewContext(1500, int(500*(1.1+float64(len(vups))/3)))
fontSize := 50.0
canvas.SetColor(color.White)
canvas.Clear()
if back != nil {
canvas.DrawImage(back, 0, 0)
}
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, false, true)
_, err = file.GetLazyData(text.BoldFontFile, true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
}
@@ -192,16 +191,18 @@ func init() {
sl, _ := canvas.MeasureString("好")
length, h := canvas.MeasureString(u.Mid)
n, _ := canvas.MeasureString(u.Name)
canvas.DrawString(u.Name, float64(backX)*1.1, float64(backY)/3-h)
canvas.DrawRoundedRectangle(float64(backX)*1.2+n-length*0.1, float64(backY)/3-h*2.5, length*1.2, h*2, fontSize*0.2)
canvas.DrawString(u.Name, 550, 160-h)
canvas.DrawRoundedRectangle(600+n-length*0.1, 160-h*2.5, length*1.2, h*2, fontSize*0.2)
canvas.SetRGB255(221, 221, 221)
canvas.Fill()
canvas.SetColor(color.Black)
canvas.DrawString(u.Mid, float64(backX)*1.2+n, float64(backY)/3-h)
canvas.DrawString(fmt.Sprintf("粉丝:%d", u.Fans), float64(backX)*1.1, float64(backY)/3*2-2.5*h)
canvas.DrawString(fmt.Sprintf("关注:%d", len(u.Attentions)), float64(backX)*2, float64(backY)/3*2-2.5*h)
canvas.DrawString(fmt.Sprintf("管人痴成分:%.2f%%%d/%d", float64(vupLen)/float64(len(u.Attentions))*100, vupLen, len(u.Attentions)), float64(backX)*1.1, float64(backY)-4*h)
canvas.DrawString("日期:"+time.Now().Format("2006-01-02"), float64(backX)*1.1, float64(backY)-h)
canvas.DrawString(u.Mid, 600+n, 160-h)
canvas.DrawString(fmt.Sprintf("粉丝:%d", u.Fans), 550, 240-h)
canvas.DrawString(fmt.Sprintf("关注:%d", len(u.Attentions)), 1000, 240-h)
canvas.DrawString(fmt.Sprintf("管人痴成分:%.2f%%%d/%d", float64(vupLen)/float64(len(u.Attentions))*100, vupLen, len(u.Attentions)), 550, 320-h)
regtime := time.Unix(u.Regtime, 0).Format("2006-01-02 15:04:05")
canvas.DrawString("注册日期:"+regtime, 550, 400-h)
canvas.DrawString("查询日期:"+time.Now().Format("2006-01-02"), 550, 480-h)
for i, v := range vups {
if i%2 == 1 {
canvas.SetRGB255(245, 245, 245)
@@ -221,9 +222,9 @@ func init() {
mnl, _ := canvas.MeasureString(m.MedalName)
grad := gg.NewLinearGradient(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h, nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
r, g, b := int2rbg(m.MedalColorStart)
grad.AddColorStop(0, color.RGBA{uint8(r), uint8(g), uint8(b), 255})
grad.AddColorStop(0, color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: 255})
r, g, b = int2rbg(m.MedalColorEnd)
grad.AddColorStop(1, color.RGBA{uint8(r), uint8(g), uint8(b), 255})
grad.AddColorStop(1, color.RGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: 255})
canvas.SetFillStyle(grad)
canvas.SetLineWidth(4)
canvas.MoveTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
@@ -307,3 +308,51 @@ func int2rbg(t int64) (int64, int64, int64) {
b, g, r := int64(buf[0]), int64(buf[1]), int64(buf[2])
return r, g, b
}
func getPara(ctx *zero.Ctx) bool {
keyword := ctx.State["regex_matched"].([]string)[1]
if !re.MatchString(keyword) {
searchRes, err := search(keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
ctx.State["uid"] = strconv.FormatInt(searchRes[0].Mid, 10)
return true
}
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
recv, cancel := next.Repeat()
defer cancel()
ctx.SendChain(message.Text("输入为纯数字请选择查询uid还是用户名输入对应序号\n0. 查询uid\n1. 查询用户名"))
for {
select {
case <-time.After(time.Second * 10):
ctx.SendChain(message.Text("时间太久啦!", zero.BotConfig.NickName[0], "帮你选择查询uid"))
ctx.State["uid"] = keyword
return true
case c := <-recv:
msg := c.Event.Message.ExtractPlainText()
num, err := strconv.Atoi(msg)
if err != nil {
ctx.SendChain(message.Text("请输入数字!"))
continue
}
if num < 0 || num > 1 {
ctx.SendChain(message.Text("序号非法!"))
continue
}
if num == 0 {
ctx.State["uid"] = keyword
return true
} else if num == 1 {
searchRes, err := search(keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
ctx.State["uid"] = strconv.FormatInt(searchRes[0].Mid, 10)
return true
}
}
}
}

View File

@@ -94,10 +94,7 @@ func updateVup() error {
uname := value.Get("uname").String()
roomid := value.Get("roomid").Int()
err = vdb.insertVupByMid(mid, uname, roomid)
if err != nil {
return false
}
return true
return err == nil
})
if err != nil {
return err

View File

@@ -2,69 +2,189 @@
package bilibiliparse
import (
"encoding/json"
"net/http"
"regexp"
"strconv"
"strings"
"time"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/antchfx/htmlquery"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
type result struct {
Data struct {
Bvid string `json:"bvid"`
Aid int `json:"aid"`
Copyright int `json:"copyright"`
Pic string `json:"pic"`
Title string `json:"title"`
Pubdate int `json:"pubdate"`
Ctime int `json:"ctime"`
Rights struct {
IsCooperation int `json:"is_cooperation"`
} `json:"rights"`
Owner struct {
Mid int `json:"mid"`
Name string `json:"name"`
} `json:"owner"`
Stat struct {
Aid int `json:"aid"`
View int `json:"view"`
Danmaku int `json:"danmaku"`
Reply int `json:"reply"`
Favorite int `json:"favorite"`
Coin int `json:"coin"`
Share int `json:"share"`
Like int `json:"like"`
} `json:"stat"`
Staff []struct {
Title string `json:"title"`
Name string `json:"name"`
Follower int `json:"follower"`
} `json:"staff"`
} `json:"data"`
}
type owner struct {
Data struct {
Card struct {
Fans int `json:"fans"`
} `json:"card"`
} `json:"data"`
}
const (
bilibiliRe = "https://www.bilibili.com/video/av[0-9]+|https://www.bilibili.com/video/BV[0-9a-zA-Z]+|https://b23.tv/[0-9a-zA-Z]+|https://www.bilibili.com/video/bv[0-9a-zA-Z]+"
validRe = "https://www.bilibili.com/video/(BV[0-9a-zA-Z]+)"
videoapi = "https://api.bilibili.com/x/web-interface/view?"
cardapi = "http://api.bilibili.com/x/web-interface/card?"
origin = "https://www.bilibili.com/video/"
)
var (
reg = regexp.MustCompile(`https://www.bilibili.com/video/([0-9a-zA-Z]+)`)
limit = ctxext.NewLimiterManager(time.Second*10, 1)
)
// 插件主体
func init() {
engine := control.Register("bilibiliparse", &control.Options{
en := control.Register("bilibiliparse", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "b站视频链接解析\n" +
"- https://www.bilibili.com/video/BV1xx411c7BF | https://www.bilibili.com/video/av1605 | https://b23.tv/I8uzWCA | https://www.bilibili.com/video/bv1xx411c7BF",
})
engine.OnRegex(bilibiliRe).SetBlock(true).Handle(func(ctx *zero.Ctx) {
bilibiliURL := ctx.State["regex_matched"].([]string)[0]
m, err := parseURL(bilibiliURL)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if len(m) != 0 {
en.OnRegex(`(av[0-9]+|BV[0-9a-zA-Z]{10}){1}`).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
if strings.Contains(ctx.MessageString(), "[CQ:forward") {
return
}
id := ctx.State["regex_matched"].([]string)[1]
m, err := parse(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(m)
}
})
})
en.OnRegex(`https://www.bilibili.com/video/([0-9a-zA-Z]+)`).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
id := ctx.State["regex_matched"].([]string)[1]
m, err := parse(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(m)
})
en.OnRegex(`(https://b23.tv/[0-9a-zA-Z]+)`).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
url := ctx.State["regex_matched"].([]string)[1]
realurl, err := getrealurl(url)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
m, err := parse(cuturl(realurl))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(m)
})
}
func parseURL(bilibiliURL string) (m message.Message, err error) {
doc, err := htmlquery.LoadURL(bilibiliURL)
// parse 解析视频数据
func parse(id string) (m message.Message, err error) {
var vid string
switch id[:2] {
case "av":
vid = "aid=" + id[2:]
case "BV":
vid = "bvid=" + id
}
data, err := web.GetData(videoapi + vid)
if err != nil {
return
}
videoURL := htmlquery.FindOne(doc, "/html/head/meta[@itemprop='url']").Attr[2].Val
re := regexp.MustCompile(validRe)
if !re.MatchString(videoURL) {
var r result
err = json.Unmarshal(data, &r)
if err != nil {
return
}
bv := re.FindStringSubmatch(videoURL)[1]
title := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/h1/span/text()").Data
m = append(m, message.Text(title+"\n"))
upName := strings.TrimSpace(htmlquery.FindOne(doc, "//*[@id='v_upinfo']/div[2]/div[1]/a[1]/text()").Data)
fanNumber := htmlquery.InnerText(htmlquery.FindOne(doc, "//i[@class='van-icon-general_addto_s']").NextSibling.NextSibling)
m = append(m, message.Text("up"+upName+",粉丝:"+fanNumber+"\n"))
view := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[@class='view']/text()").Data
dm := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[@class='dm']/text()").Data
m = append(m, message.Text(view+dm+"\n"))
t := htmlquery.FindOne(doc, "//*[@id='viewbox_report']/div/span[3]/text()").Data
m = append(m, message.Text(t))
image := htmlquery.FindOne(doc, "/html/head/meta[@itemprop='image']").Attr[2].Val
m = append(m, message.Image(image))
like := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='like']/text()").Data
coin := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='coin']/text()").Data
m = append(m, message.Text("\n点赞:", strings.TrimSpace(like)+",投币:", strings.TrimSpace(coin)+"\n"))
collect := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='collect']/text()").Data
share := htmlquery.FindOne(doc, "//*[@id='arc_toolbar_report']/div[1]/span[@class='share']/text()").Data
m = append(m, message.Text("收藏:", strings.TrimSpace(collect)+",分享:", strings.TrimSpace(share)+"\n"))
m = append(m, message.Text(bv))
m = make(message.Message, 0, 16)
m = append(m, message.Text("标题: ", r.Data.Title, "\n"))
if r.Data.Rights.IsCooperation == 1 {
for i := 0; i < len(r.Data.Staff); i++ {
m = append(m, message.Text(r.Data.Staff[i].Title, ": ", r.Data.Staff[i].Name, ", 粉丝: ", row(r.Data.Staff[i].Follower), "\n"))
}
} else {
o, err := getcard(r.Data.Owner.Mid)
if err != nil {
return m, err
}
m = append(m, message.Text("UP主: ", r.Data.Owner.Name, ", 粉丝: ", row(o.Data.Card.Fans), "\n"))
}
m = append(m, message.Text("播放: ", row(r.Data.Stat.View), ", 弹幕: ", row(r.Data.Stat.Danmaku), "\n"),
message.Image(r.Data.Pic),
message.Text("\n点赞: ", row(r.Data.Stat.Like), ", 投币: ", row(r.Data.Stat.Coin), "\n收藏: ", row(r.Data.Stat.Favorite), ", 分享: ", row(r.Data.Stat.Share), "\n", origin, id))
return
}
// getrealurl 获取跳转后的链接
func getrealurl(url string) (realurl string, err error) {
data, err := http.Head(url)
if err != nil {
return
}
realurl = data.Request.URL.String()
return
}
// cuturl 获取aid或者bvid
func cuturl(url string) (id string) {
if !reg.MatchString(url) {
return
}
return reg.FindStringSubmatch(url)[1]
}
// getcard 获取个人信息
func getcard(mid int) (o owner, err error) {
data, err := web.GetData(cardapi + "mid=" + strconv.Itoa(mid))
if err != nil {
return
}
err = json.Unmarshal(data, &o)
return
}
func row(res int) string {
if res/10000 != 0 {
return strconv.FormatFloat(float64(res)/10000, 'f', 2, 64) + "万"
}
return strconv.Itoa(res)
}

View File

@@ -1,593 +0,0 @@
// Package bilibilipush b站推送
package bilibilipush
import (
"bytes"
"encoding/json"
"fmt"
"strconv"
"time"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img/text"
"github.com/FloatTech/zbputils/web"
)
const (
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
referer = "https://www.bilibili.com/"
infoURL = "https://api.bilibili.com/x/space/acc/info?mid=%d"
userDynamicURL = "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/space_history?host_uid=%d&offset_dynamic_id=0&need_top=0"
liveListURL = "https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids"
tURL = "https://t.bilibili.com/"
liveURL = "https://live.bilibili.com/"
serviceName = "bilibilipush"
)
// bdb bilibili推送数据库
var bdb *bilibilipushdb
var (
lastTime = map[int64]int64{}
typeMsg = map[int64]string{
1: "转发了一条动态",
2: "有图营业",
4: "无图营业",
8: "发布了新投稿",
16: "发布了短视频",
64: "发布了新专栏",
256: "发布了新音频",
2048: "发布了新简报",
}
liveStatus = map[int64]int{}
uidErrorMsg = map[int]string{
0: "输入的uid有效",
-400: "uid不存在注意uid不是房间号",
-402: "uid不存在注意uid不是房间号",
-412: "操作过于频繁IP暂时被风控请半小时后再尝试",
}
upMap = map[int64]string{}
)
func init() {
go bilibiliPushDaily()
en := control.Register(serviceName, &control.Options{
DisableOnDefault: false,
Help: "bilibilipush\n" +
"- 添加b站订阅[uid]\n" +
"- 取消b站订阅[uid]\n" +
"- 取消b站动态订阅[uid]\n" +
"- 取消b站直播订阅[uid]\n" +
"- b站推送列表",
PrivateDataFolder: serviceName,
})
// 加载数据库
go func() {
dbpath := en.DataFolder()
dbfile := dbpath + "push.db"
bdb = initialize(dbfile)
}()
en.OnRegex(`^添加b站订阅\s?(\d+)$`, zero.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
buid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
var name string
var ok bool
if name, ok = upMap[buid]; !ok {
var status int
var err error
status, name, err = checkBuid(buid)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if status != 0 {
msg, ok := uidErrorMsg[status]
if !ok {
msg = "未知错误,请私聊反馈给" + zero.BotConfig.NickName[0]
}
ctx.SendChain(message.Text(msg))
return
}
}
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
if err := subscribe(buid, gid); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("已添加" + name + "的订阅"))
})
en.OnRegex(`^取消b站订阅\s?(\d+)$`, zero.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
buid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
var name string
var ok bool
if name, ok = upMap[buid]; !ok {
var status int
var err error
status, name, err = checkBuid(buid)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if status != 0 {
msg, ok := uidErrorMsg[status]
if !ok {
msg = "未知错误,请私聊反馈给" + zero.BotConfig.NickName[0]
}
ctx.SendChain(message.Text(msg))
return
}
}
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
if err := unsubscribe(buid, gid); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("已取消" + name + "的订阅"))
})
en.OnRegex(`^取消b站动态订阅\s?(\d+)$`, zero.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
buid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
var name string
var ok bool
if name, ok = upMap[buid]; !ok {
var status int
var err error
status, name, err = checkBuid(buid)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if status != 0 {
msg, ok := uidErrorMsg[status]
if !ok {
msg = "未知错误,请私聊反馈给" + zero.BotConfig.NickName[0]
}
ctx.SendChain(message.Text(msg))
return
}
}
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
if err := unsubscribeDynamic(buid, gid); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("已取消" + name + "的动态订阅"))
})
en.OnRegex(`^取消b站直播订阅\s?(\d+)$`, zero.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
buid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
var name string
var ok bool
if name, ok = upMap[buid]; !ok {
var status int
var err error
status, name, err = checkBuid(buid)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if status != 0 {
msg, ok := uidErrorMsg[status]
if !ok {
msg = "未知错误,请私聊反馈给" + zero.BotConfig.NickName[0]
}
ctx.SendChain(message.Text(msg))
return
}
}
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
if err := unsubscribeLive(buid, gid); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("已取消" + name + "的直播订阅"))
})
en.OnFullMatch("b站推送列表", zero.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
bpl := bdb.getAllPushByGroup(gid)
msg := "--------b站推送列表--------"
for _, v := range bpl {
if _, ok := upMap[v.BilibiliUID]; !ok {
bdb.updateAllUp()
}
msg += fmt.Sprintf("\nuid:%-12d 动态:", v.BilibiliUID)
if v.DynamicDisable == 0 {
msg += "●"
} else {
msg += "○"
}
msg += " 直播:"
if v.LiveDisable == 0 {
msg += "●"
} else {
msg += "○"
}
msg += " up主" + upMap[v.BilibiliUID]
}
data, err := text.RenderToBase64(msg, text.FontFile, 600, 20)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR:可能被风控了"))
}
})
}
func bilibiliPushDaily() {
t := time.NewTicker(time.Second * 10)
defer t.Stop()
for range t.C {
log.Debugln("-----bilibilipush拉取推送信息-----")
_ = sendDynamic()
_ = sendLive()
}
}
func checkBuid(buid int64) (status int, name string, err error) {
data, err := web.RequestDataWith(web.NewDefaultClient(), fmt.Sprintf(infoURL, buid), "GET", referer, ua)
if err != nil {
return
}
status = int(gjson.Get(binary.BytesToString(data), "code").Int())
name = gjson.Get(binary.BytesToString(data), "data.name").String()
if status == 0 {
bdb.insertBilibiliUp(buid, name)
upMap[buid] = name
}
return
}
// subscribe 订阅
func subscribe(buid, groupid int64) (err error) {
bpMap := map[string]interface{}{
"bilibili_uid": buid,
"group_id": groupid,
"live_disable": 0,
"dynamic_disable": 0,
}
err = bdb.insertOrUpdateLiveAndDynamic(bpMap)
return
}
// unsubscribe 取消订阅
func unsubscribe(buid, groupid int64) (err error) {
bpMap := map[string]interface{}{
"bilibili_uid": buid,
"group_id": groupid,
"live_disable": 1,
"dynamic_disable": 1,
}
err = bdb.insertOrUpdateLiveAndDynamic(bpMap)
return
}
func unsubscribeDynamic(buid, groupid int64) (err error) {
bpMap := map[string]interface{}{
"bilibili_uid": buid,
"group_id": groupid,
"dynamic_disable": 1,
}
err = bdb.insertOrUpdateLiveAndDynamic(bpMap)
return
}
func unsubscribeLive(buid, groupid int64) (err error) {
bpMap := map[string]interface{}{
"bilibili_uid": buid,
"group_id": groupid,
"live_disable": 1,
}
err = bdb.insertOrUpdateLiveAndDynamic(bpMap)
return
}
func getUserDynamicCard(buid int64) (cardList []gjson.Result, err error) {
data, err := web.RequestDataWith(web.NewDefaultClient(), fmt.Sprintf(userDynamicURL, buid), "GET", referer, ua)
if err != nil {
return
}
cardList = gjson.Get(binary.BytesToString(data), "data.cards").Array()
return
}
func getLiveList(uids ...int64) (string, error) {
m := make(map[string]interface{})
m["uids"] = uids
b, _ := json.Marshal(m)
data, err := web.PostData(liveListURL, "application/json", bytes.NewReader(b))
if err != nil {
return "", err
}
return binary.BytesToString(data), nil
}
func sendDynamic() error {
uids := bdb.getAllBuidByDynamic()
for _, buid := range uids {
cardList, err := getUserDynamicCard(buid)
if err != nil {
return err
}
t, ok := lastTime[buid]
if !ok {
lastTime[buid] = cardList[0].Get("desc.timestamp").Int()
return nil
}
for i := len(cardList) - 1; i >= 0; i-- {
ct := cardList[i].Get("desc.timestamp").Int()
if ct > t && ct > time.Now().Unix()-600 {
lastTime[buid] = ct
m, ok := control.Lookup(serviceName)
if ok {
groupList := bdb.getAllGroupByBuidAndDynamic(buid)
var msg []message.MessageSegment
cType := cardList[i].Get("desc.type").Int()
cardStr := cardList[i].Get("card").String()
switch cType {
case 0:
cName := cardList[i].Get("desc.user_profile.info.uname").String()
cTime := time.Unix(cardList[i].Get("desc.timestamp").Int(), 0).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cName+"在"+cTime+typeMsg[cType]+"\n"))
case 1:
cName := gjson.Get(cardStr, "user.uname").String()
msg = append(msg, message.Text(cName+typeMsg[cType]+"\n"))
cContent := gjson.Get(cardStr, "item.content").String()
msg = append(msg, message.Text(cContent+"\n"))
msg = append(msg, message.Text("转发的内容:\n"))
cOrigType := gjson.Get(cardStr, "item.orig_type").Int()
cOrigin := gjson.Get(cardStr, "origin").String()
switch cOrigType {
case 1:
cName := gjson.Get(cOrigin, "user.uname").String()
msg = append(msg, message.Text(cName+typeMsg[cOrigType]+"\n"))
case 2:
cName := gjson.Get(cOrigin, "user.name").String()
cUploadTime := time.Unix(gjson.Get(cOrigin, "item.upload_time").Int(), 0).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cName+"在"+cUploadTime+typeMsg[cOrigType]+"\n"))
cDescription := gjson.Get(cOrigin, "item.description")
msg = append(msg, message.Text(cDescription))
if gjson.Get(cOrigin, "item.pictures.#").Int() != 0 {
gjson.Get(cOrigin, "item.pictures").ForEach(func(_, v gjson.Result) bool {
msg = append(msg, message.Image(v.Get("img_src").String()))
return true
})
}
case 4:
cName := gjson.Get(cOrigin, "user.uname").String()
cTimestamp := time.Unix(gjson.Get(cOrigin, "item.timestamp").Int(), 0).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cName+"在"+cTimestamp+typeMsg[cOrigType]+"\n"))
cContent := gjson.Get(cOrigin, "item.content").String()
msg = append(msg, message.Text(cContent+"\n"))
case 8:
cName := gjson.Get(cOrigin, "owner.name").String()
cTime := time.Unix(gjson.Get(cOrigin, "pubdate").Int(), 0).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cName+"在"+cTime+typeMsg[cOrigType]+"\n"))
cTitle := gjson.Get(cOrigin, "title").String()
msg = append(msg, message.Text(cTitle))
cPic := gjson.Get(cOrigin, "pic").String()
msg = append(msg, message.Image(cPic))
cDesc := gjson.Get(cOrigin, "desc").String()
msg = append(msg, message.Text(cDesc+"\n"))
cShareSubtitle := gjson.Get(cOrigin, "share_subtitle").String()
msg = append(msg, message.Text(cShareSubtitle+"\n"))
cShortLink := gjson.Get(cOrigin, "short_link").String()
msg = append(msg, message.Text("视频链接:"+cShortLink+"\n"))
case 16:
cName := gjson.Get(cOrigin, "user.name").String()
cUploadTime := gjson.Get(cOrigin, "item.upload_time").String()
msg = append(msg, message.Text(cName+"在"+cUploadTime+typeMsg[cOrigType]+"\n"))
cDescription := gjson.Get(cOrigin, "item.description")
msg = append(msg, message.Text(cDescription))
cCover := gjson.Get(cOrigin, "item.cover.default").String()
msg = append(msg, message.Image(cCover))
case 64:
cName := gjson.Get(cOrigin, "author.name").String()
cPublishTime := time.Unix(gjson.Get(cOrigin, "publish_time").Int(), 0).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cName+"在"+cPublishTime+typeMsg[cOrigType]+"\n"))
cTitle := gjson.Get(cOrigin, "title").String()
msg = append(msg, message.Text(cTitle+"\n"))
cSummary := gjson.Get(cOrigin, "summary").String()
msg = append(msg, message.Text(cSummary))
cBannerURL := gjson.Get(cOrigin, "banner_url").String()
msg = append(msg, message.Image(cBannerURL))
case 256:
cUpper := gjson.Get(cOrigin, "upper").String()
cTime := time.UnixMilli(gjson.Get(cOrigin, "ctime").Int()).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cUpper+"在"+cTime+typeMsg[cOrigType]+"\n"))
cTitle := gjson.Get(cOrigin, "title").String()
msg = append(msg, message.Text(cTitle))
cCover := gjson.Get(cOrigin, "cover").String()
msg = append(msg, message.Image(cCover))
case 2048:
cName := gjson.Get(cOrigin, "user.uname").String()
msg = append(msg, message.Text(cName+typeMsg[cOrigType]+"\n"))
cContent := gjson.Get(cOrigin, "vest.content").String()
msg = append(msg, message.Text(cContent+"\n"))
cTitle := gjson.Get(cOrigin, "sketch.title").String()
msg = append(msg, message.Text(cTitle+"\n"))
cDescText := gjson.Get(cOrigin, "sketch.desc_text").String()
msg = append(msg, message.Text(cDescText))
cCoverURL := gjson.Get(cOrigin, "sketch.cover_url").String()
msg = append(msg, message.Image(cCoverURL))
cTargetURL := gjson.Get(cOrigin, "sketch.target_url").String()
msg = append(msg, message.Text("简报链接:"+cTargetURL+"\n"))
default:
msg = append(msg, message.Text("未知动态类型"+strconv.FormatInt(cOrigType, 10)+"\n"))
}
case 2:
cName := gjson.Get(cardStr, "user.name").String()
cUploadTime := time.Unix(gjson.Get(cardStr, "item.upload_time").Int(), 0).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cName+"在"+cUploadTime+typeMsg[cType]+"\n"))
cDescription := gjson.Get(cardStr, "item.description")
msg = append(msg, message.Text(cDescription))
if gjson.Get(cardStr, "item.pictures.#").Int() != 0 {
gjson.Get(cardStr, "item.pictures").ForEach(func(_, v gjson.Result) bool {
msg = append(msg, message.Image(v.Get("img_src").String()))
return true
})
}
case 4:
cName := gjson.Get(cardStr, "user.uname").String()
cTimestamp := time.Unix(gjson.Get(cardStr, "item.timestamp").Int(), 0).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cName+"在"+cTimestamp+typeMsg[cType]+"\n"))
cContent := gjson.Get(cardStr, "item.content").String()
msg = append(msg, message.Text(cContent+"\n"))
case 8:
cName := gjson.Get(cardStr, "owner.name").String()
cTime := time.Unix(gjson.Get(cardStr, "ctime").Int(), 0).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cName+"在"+cTime+typeMsg[cType]+"\n"))
cTitle := gjson.Get(cardStr, "title").String()
msg = append(msg, message.Text(cTitle))
cPic := gjson.Get(cardStr, "pic").String()
msg = append(msg, message.Image(cPic))
cDesc := gjson.Get(cardStr, "desc").String()
msg = append(msg, message.Text(cDesc+"\n"))
cShareSubtitle := gjson.Get(cardStr, "share_subtitle").String()
msg = append(msg, message.Text(cShareSubtitle+"\n"))
cShortLink := gjson.Get(cardStr, "short_link").String()
msg = append(msg, message.Text("视频链接:"+cShortLink+"\n"))
case 16:
cName := gjson.Get(cardStr, "user.name").String()
cUploadTime := gjson.Get(cardStr, "item.upload_time").String()
msg = append(msg, message.Text(cName+"在"+cUploadTime+typeMsg[cType]+"\n"))
cDescription := gjson.Get(cardStr, "item.description")
msg = append(msg, message.Text(cDescription))
cCover := gjson.Get(cardStr, "item.cover.default").String()
msg = append(msg, message.Image(cCover))
case 64:
cName := gjson.Get(cardStr, "author.name").String()
cPublishTime := time.Unix(gjson.Get(cardStr, "publish_time").Int(), 0).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cName+"在"+cPublishTime+typeMsg[cType]+"\n"))
cTitle := gjson.Get(cardStr, "title").String()
msg = append(msg, message.Text(cTitle+"\n"))
cSummary := gjson.Get(cardStr, "summary").String()
msg = append(msg, message.Text(cSummary))
cBannerURL := gjson.Get(cardStr, "banner_url").String()
msg = append(msg, message.Image(cBannerURL))
case 256:
cUpper := gjson.Get(cardStr, "upper").String()
cTime := time.UnixMilli(gjson.Get(cardStr, "ctime").Int()).Format("2006-01-02 15:04:05")
msg = append(msg, message.Text(cUpper+"在"+cTime+typeMsg[cType]+"\n"))
cTitle := gjson.Get(cardStr, "title").String()
msg = append(msg, message.Text(cTitle))
cCover := gjson.Get(cardStr, "cover").String()
msg = append(msg, message.Image(cCover))
case 2048:
cName := gjson.Get(cardStr, "user.uname").String()
msg = append(msg, message.Text(cName+typeMsg[cType]+"\n"))
cContent := gjson.Get(cardStr, "vest.content").String()
msg = append(msg, message.Text(cContent+"\n"))
cTitle := gjson.Get(cardStr, "sketch.title").String()
msg = append(msg, message.Text(cTitle+"\n"))
cDescText := gjson.Get(cardStr, "sketch.desc_text").String()
msg = append(msg, message.Text(cDescText))
cCoverURL := gjson.Get(cardStr, "sketch.cover_url").String()
msg = append(msg, message.Image(cCoverURL))
cTargetURL := gjson.Get(cardStr, "sketch.target_url").String()
msg = append(msg, message.Text("简报链接:"+cTargetURL+"\n"))
default:
msg = append(msg, message.Text("未知动态类型"+strconv.FormatInt(cType, 10)+"\n"))
}
cID := cardList[i].Get("desc.dynamic_id").String()
msg = append(msg, message.Text("动态链接:", tURL+cID))
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
for _, gid := range groupList {
if m.IsEnabledIn(gid) {
switch {
case gid > 0:
ctx.SendGroupMessage(gid, msg)
case gid < 0:
ctx.SendPrivateMessage(-gid, msg)
}
}
}
return true
})
}
}
}
}
return nil
}
func sendLive() error {
uids := bdb.getAllBuidByLive()
ll, err := getLiveList(uids...)
if err != nil {
return err
}
gjson.Get(ll, "data").ForEach(func(key, value gjson.Result) bool {
newStatus := int(value.Get("live_status").Int())
if newStatus == 2 {
newStatus = 0
}
if _, ok := liveStatus[key.Int()]; !ok {
liveStatus[key.Int()] = newStatus
return true
}
oldStatus := liveStatus[key.Int()]
if newStatus != oldStatus && newStatus == 1 {
liveStatus[key.Int()] = newStatus
m, ok := control.Lookup(serviceName)
if ok {
groupList := bdb.getAllGroupByBuidAndLive(key.Int())
roomID := value.Get("short_id").Int()
if roomID == 0 {
roomID = value.Get("room_id").Int()
}
lURL := liveURL + strconv.FormatInt(roomID, 10)
lName := value.Get("uname").String()
lTitle := value.Get("title").String()
lCover := value.Get("cover_from_user").String()
if lCover == "" {
lCover = value.Get("keyframe").String()
}
var msg []message.MessageSegment
msg = append(msg, message.Text(lName+" 正在直播:\n"))
msg = append(msg, message.Text(lTitle))
msg = append(msg, message.Image(lCover))
msg = append(msg, message.Text("直播链接:", lURL))
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
for _, gid := range groupList {
if m.IsEnabledIn(gid) {
switch {
case gid > 0:
ctx.SendGroupMessage(gid, msg)
case gid < 0:
ctx.SendPrivateMessage(-gid, msg)
}
}
}
return true
})
}
} else if newStatus != oldStatus {
liveStatus[key.Int()] = newStatus
}
return true
})
return nil
}

View File

@@ -1,144 +0,0 @@
package bilibilipush
import (
"encoding/json"
"os"
_ "github.com/fumiama/sqlite3" // import sql
"github.com/jinzhu/gorm"
)
// bilibilipushdb bili推送数据库
type bilibilipushdb gorm.DB
type bilibilipush struct {
ID int64 `gorm:"column:id;primary_key" json:"id"`
BilibiliUID int64 `gorm:"column:bilibili_uid;index:idx_buid_gid" json:"bilibili_uid"`
GroupID int64 `gorm:"column:group_id;index:idx_buid_gid" json:"group_id"`
LiveDisable int64 `gorm:"column:live_disable;default:0" json:"live_disable"`
DynamicDisable int64 `gorm:"column:dynamic_disable;default:0" json:"dynamic_disable"`
}
// TableName ...
func (bilibilipush) TableName() string {
return "bilibili_push"
}
type bilibiliup struct {
BilibiliUID int64 `gorm:"column:bilibili_uid;primary_key"`
Name string `gorm:"column:name"`
}
// TableName ...
func (bilibiliup) TableName() string {
return "bilibili_up"
}
// initialize 初始化ScoreDB数据库
func initialize(dbpath string) *bilibilipushdb {
var err error
if _, err = os.Stat(dbpath); err != nil || os.IsNotExist(err) {
// 生成文件
f, err := os.Create(dbpath)
if err != nil {
return nil
}
defer f.Close()
}
gdb, err := gorm.Open("sqlite3", dbpath)
if err != nil {
panic(err)
}
gdb.AutoMigrate(&bilibilipush{}).AutoMigrate(&bilibiliup{})
return (*bilibilipushdb)(gdb)
}
// insertOrUpdateLiveAndDynamic 插入或更新数据库
func (bdb *bilibilipushdb) insertOrUpdateLiveAndDynamic(bpMap map[string]interface{}) (err error) {
db := (*gorm.DB)(bdb)
bp := bilibilipush{}
data, _ := json.Marshal(&bpMap)
_ = json.Unmarshal(data, &bp)
if err = db.Model(&bilibilipush{}).First(&bp, "bilibili_uid = ? and group_id = ?", bp.BilibiliUID, bp.GroupID).Error; err != nil {
if gorm.IsRecordNotFoundError(err) {
err = db.Model(&bilibilipush{}).Create(&bp).Error
}
} else {
err = db.Model(&bilibilipush{}).Where("bilibili_uid = ? and group_id = ?", bp.BilibiliUID, bp.GroupID).Update(bpMap).Error
}
return
}
func (bdb *bilibilipushdb) getAllBuidByLive() (buidList []int64) {
db := (*gorm.DB)(bdb)
var bpl []bilibilipush
db.Model(&bilibilipush{}).Find(&bpl, "live_disable = 0")
temp := make(map[int64]bool)
for _, v := range bpl {
_, ok := temp[v.BilibiliUID]
if !ok {
buidList = append(buidList, v.BilibiliUID)
temp[v.BilibiliUID] = true
}
}
return
}
func (bdb *bilibilipushdb) getAllBuidByDynamic() (buidList []int64) {
db := (*gorm.DB)(bdb)
var bpl []bilibilipush
db.Model(&bilibilipush{}).Find(&bpl, "dynamic_disable = 0")
temp := make(map[int64]bool)
for _, v := range bpl {
_, ok := temp[v.BilibiliUID]
if !ok {
buidList = append(buidList, v.BilibiliUID)
temp[v.BilibiliUID] = true
}
}
return
}
func (bdb *bilibilipushdb) getAllGroupByBuidAndLive(buid int64) (groupList []int64) {
db := (*gorm.DB)(bdb)
var bpl []bilibilipush
db.Model(&bilibilipush{}).Find(&bpl, "bilibili_uid = ? and live_disable = 0", buid)
for _, v := range bpl {
groupList = append(groupList, v.GroupID)
}
return
}
func (bdb *bilibilipushdb) getAllGroupByBuidAndDynamic(buid int64) (groupList []int64) {
db := (*gorm.DB)(bdb)
var bpl []bilibilipush
db.Model(&bilibilipush{}).Find(&bpl, "bilibili_uid = ? and dynamic_disable = 0", buid)
for _, v := range bpl {
groupList = append(groupList, v.GroupID)
}
return
}
func (bdb *bilibilipushdb) getAllPushByGroup(groupID int64) (bpl []bilibilipush) {
db := (*gorm.DB)(bdb)
db.Model(&bilibilipush{}).Find(&bpl, "group_id = ? and (live_disable = 0 or dynamic_disable = 0)", groupID)
return
}
func (bdb *bilibilipushdb) insertBilibiliUp(buid int64, name string) {
db := (*gorm.DB)(bdb)
bu := bilibiliup{
BilibiliUID: buid,
Name: name,
}
db.Model(&bilibiliup{}).Create(bu)
}
func (bdb *bilibilipushdb) updateAllUp() {
db := (*gorm.DB)(bdb)
var bul []bilibiliup
db.Model(&bilibiliup{}).Find(&bul)
for _, v := range bul {
upMap[v.BilibiliUID] = v.Name
}
}

View File

@@ -2,30 +2,36 @@
package bookreview
import (
"time"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img/text"
)
func init() {
engine := control.Register("bookreview", &control.Options{
engine := control.Register("bookreview", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "哀伤雪刃推书记录\n- 书评[xxx]\n- 随机书评",
PublicDataFolder: "BookReview",
})
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
dbpath := engine.DataFolder()
db.DBPath = dbpath + "bookreview.db"
db.DBPath = engine.DataFolder() + "bookreview.db"
// os.RemoveAll(dbpath)
_, _ = file.GetLazyData(db.DBPath, false, true)
err := db.Create("bookreview", &book{})
_, _ = engine.GetLazyData("bookreview.db", true)
err := db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = db.Create("bookreview", &book{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false

View File

@@ -9,7 +9,8 @@ import (
"net/url"
"strings"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/antchfx/htmlquery"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -29,7 +30,7 @@ var (
)
func init() {
engine := control.Register("cangtoushi", &control.Options{
engine := control.Register("cangtoushi", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "藏头诗\n" +
"- 藏头诗[xxx]\n- 藏尾诗[xxx]",

View File

@@ -6,7 +6,8 @@ import (
"strconv"
"time"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -14,7 +15,7 @@ import (
var (
poke = rate.NewManager[int64](time.Minute*5, 8) // 戳一戳
engine = control.Register("chat", &control.Options{
engine = control.Register("chat", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]",
})

View File

@@ -6,13 +6,14 @@ import (
"strconv"
"strings"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
engine := control.Register("choose", &control.Options{
engine := control.Register("choose", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "choose\n" +
"- 选择可口可乐还是百事可乐\n" +

View File

@@ -2,17 +2,19 @@
package chouxianghua
import (
"time"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
)
func init() {
en := control.Register("chouxianghua", &control.Options{
en := control.Register("chouxianghua", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "抽象话\n- 抽象翻译xxx",
PublicDataFolder: "ChouXiangHua",
@@ -20,11 +22,15 @@ func init() {
en.OnRegex("^抽象翻译((\\s|[\\r\\n]|[\\p{Han}\\p{P}A-Za-z0-9])+)$",
ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
dbpath := en.DataFolder()
db.DBPath = dbpath + "cxh.db"
db.DBPath = en.DataFolder() + "cxh.db"
// os.RemoveAll(dbpath)
_, _ = file.GetLazyData(db.DBPath, false, true)
err := db.Create("pinyin", &pinyin{})
_, _ = en.GetLazyData("cxh.db", true)
err := db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = db.Create("pinyin", &pinyin{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false

View File

@@ -10,7 +10,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
)
@@ -22,7 +23,7 @@ var (
)
func init() {
control.Register("coser", &control.Options{
control.Register("coser", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "三次元小姐姐\n- coser",
}).ApplySingle(ctxext.DefaultSingle).OnFullMatch("coser", zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).

View File

@@ -3,30 +3,35 @@ package cpstory
import (
"strings"
"time"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/math"
)
func init() {
engine := control.Register("cpstory", &control.Options{
engine := control.Register("cpstory", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "cp短打\n- 组cp[@xxx][@xxx]\n- 磕cp大老师 雪乃",
PublicDataFolder: "CpStory",
})
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
dbpath := engine.DataFolder()
db.DBPath = dbpath + "cp.db"
db.DBPath = engine.DataFolder() + "cp.db"
// os.RemoveAll(dbpath)
_, _ = file.GetLazyData(db.DBPath, false, true)
err := db.Create("cp_story", &cpstory{})
_, _ = engine.GetLazyData("cp.db", true)
err := db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = db.Create("cp_story", &cpstory{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false

View File

@@ -2,13 +2,15 @@
package curse
import (
"time"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
)
@@ -18,16 +20,20 @@ const (
)
func init() {
engine := control.Register("curse", &control.Options{
engine := control.Register("curse", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Help: "骂人(求骂,自卫)\n- 骂我\n- 大力骂我",
PublicDataFolder: "Curse",
})
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
dbpath := engine.DataFolder()
db.DBPath = dbpath + "curse.db"
_, err := file.GetLazyData(db.DBPath, false, true)
db.DBPath = engine.DataFolder() + "curse.db"
_, err := engine.GetLazyData("curse.db", true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false

View File

@@ -6,7 +6,7 @@ import (
"encoding/hex"
"github.com/FloatTech/AnimeAPI/danbooru"
"github.com/FloatTech/AnimeAPI/saucenao"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img/writer"
@@ -16,7 +16,7 @@ import (
)
func init() { // 插件主体
engine := control.Register("danbooru", &control.Options{
engine := control.Register("danbooru", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "二次元图片标签识别\n" +
"- 鉴赏图片[图片]",
@@ -30,14 +30,7 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女祈祷中..."))
for _, url := range ctx.State["image_url"].([]string) {
name := ""
r, err := saucenao.SauceNAO(url)
if err != nil {
name = "未知图片"
} else {
name = r[0].Title
}
t, err := danbooru.TagURL(name, url)
t, err := danbooru.TagURL("", url)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return

View File

@@ -5,13 +5,14 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/ZeroBot-Plugin/plugin/diana/data"
)
var engine = control.Register("diana", &control.Options{
var engine = control.Register("diana", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "嘉然\n" +
"- 小作文\n" +

View File

@@ -4,6 +4,7 @@ package data
import (
"crypto/md5"
"encoding/binary"
"time"
sql "github.com/FloatTech/sqlite"
binutils "github.com/FloatTech/zbputils/binary"
@@ -20,11 +21,15 @@ type text struct {
// LoadText 加载小作文
func LoadText(dbfile string) error {
_, err := file.GetLazyData(dbfile, false, false)
_, err := file.GetLazyData(dbfile, false)
db.DBPath = dbfile
if err != nil {
return err
}
err = db.Open(time.Hour * 24)
if err != nil {
return err
}
err = db.Create("text", &text{})
if err != nil {
return err

View File

@@ -5,7 +5,9 @@ import (
"strconv"
"strings"
"sync"
"time"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -13,13 +15,13 @@ import (
)
func init() {
en := control.Register("driftbottle", &control.Options{
en := control.Register("driftbottle", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "漂流瓶\n- (在群xxx)丢漂流瓶(到频道xxx) [消息]\n- (从频道xxx)捡漂流瓶\n- @BOT 创建频道 xxx\n- 跳入(频道)海中\n- 注:不显式限制时,私聊发送可在所有群抽到,群聊发送仅可在本群抽到,默认频道为 global",
PrivateDataFolder: "driftbottle",
})
sea.DBPath = en.DataFolder() + "sea.db"
err := sea.Open()
err := sea.Open(time.Hour * 24)
if err != nil {
panic(err)
}

View File

@@ -6,6 +6,7 @@ import (
"net/http"
"strconv"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/sirupsen/logrus"
@@ -16,7 +17,7 @@ import (
const bed = "https://www.gstatic.com/android/keyboard/emojikitchen/%d/u%x/u%x_u%x.png"
func init() {
control.Register("emojimix", &control.Options{
control.Register("emojimix", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "合成emoji\n" +
"- [emoji][emoji]",

View File

@@ -7,6 +7,7 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
@@ -34,8 +35,8 @@ type epidemic struct {
type area struct {
Name string `json:"name"`
Today struct {
Confirm int `json:"confirm"`
Wzzadd int `json:"wzz_add"`
Confirm int `json:"confirm"`
Wzzadd interface{} `json:"wzz_add"`
} `json:"today"`
Total struct {
NowConfirm int `json:"nowConfirm"`
@@ -49,7 +50,7 @@ type area struct {
}
func init() {
engine := control.Register(servicename, &control.Options{
engine := control.Register(servicename, &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "城市疫情查询\n" +
"- xxx疫情\n",

View File

@@ -2,6 +2,7 @@
package font
import (
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -11,7 +12,7 @@ import (
)
func init() {
control.Register("font", &control.Options{
control.Register("font", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "渲染任意文字到图片\n- (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体])渲染文字xxx",
}).OnRegex(`^(用.+)?渲染文字([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
@@ -29,6 +30,7 @@ func init() {
case "用Consolas体":
fnt = text.ConsolasFontFile
case "用苹方体":
fallthrough
default:
fnt = text.FontFile
}

View File

@@ -8,10 +8,8 @@ import (
"encoding/json"
"image"
"io"
"math/rand"
"os"
"strconv"
"time"
"github.com/fogleman/gg" // 注册了 jpg png gif
"github.com/sirupsen/logrus"
@@ -19,7 +17,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img/pool"
@@ -40,7 +39,7 @@ const (
var (
// 底图类型列表
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师", "赛马娘", "东方归言录", "奇异恩典"}
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师", "赛马娘", "东方归言录", "奇异恩典", "夏日口袋", "ASoul"}
// 映射底图与 index
index = make(map[string]uint8)
// 签文
@@ -49,11 +48,11 @@ var (
func init() {
// 插件主体
en := control.Register("fortune", &control.Options{
en := control.Register("fortune", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "每日运势: \n" +
"- 运势 | 抽签\n" +
"- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘 | 东方归言录 | 奇异恩典]",
"- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘 | 东方归言录 | 奇异恩典 | 夏日口袋 | ASoul]",
PublicDataFolder: "Fortune",
})
_ = os.RemoveAll(cache)
@@ -73,7 +72,7 @@ func init() {
}
i, ok := index[ctx.State["regex_matched"].([]string)[1]]
if ok {
c, ok := control.Lookup("fortune")
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
err := c.SetData(gid, int64(i)&0xff)
if err != nil {
@@ -90,7 +89,7 @@ func init() {
})
en.OnFullMatchGroup([]string{"运势", "抽签"}, ctxext.DoOnceOnSuccess(
func(ctx *zero.Ctx) bool {
data, err := file.GetLazyData(omikujson, true, false)
data, err := file.GetLazyData(omikujson, false)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
@@ -100,14 +99,14 @@ func init() {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
_, err = file.GetLazyData(font, false, true)
_, err = file.GetLazyData(font, true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
return true
},
)).SetBlock(true).
)).Limit(ctxext.LimitByGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 获取该群背景类型,默认车万
kind := "车万"
@@ -117,7 +116,7 @@ func init() {
gid = -ctx.Event.UserID
}
logrus.Debugln("[fortune]gid:", ctx.Event.GroupID, "uid:", ctx.Event.UserID)
c, ok := control.Lookup("fortune")
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
v := uint8(c.GetData(gid) & 0xff)
if int(v) < len(table) {
@@ -126,25 +125,22 @@ func init() {
}
// 检查背景图片是否存在
zipfile := images + kind + ".zip"
_, err := file.GetLazyData(zipfile, false, false)
_, err := file.GetLazyData(zipfile, false)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
// 生成种子
t, _ := strconv.ParseInt(time.Now().Format("20060102"), 10, 64)
seed := ctx.Event.UserID + t
// 随机获取背景
background, index, err := randimage(zipfile, seed)
background, index, err := randimage(zipfile, ctx)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
// 随机获取签文
title, text := randtext(seed)
randtextindex := ctxext.RandSenderPerDayN(ctx.Event.UserID, len(omikujis))
title, text := omikujis[randtextindex]["title"], omikujis[randtextindex]["content"]
digest := md5.Sum(helper.StringToBytes(zipfile + strconv.Itoa(index) + title + text))
cachefile := cache + hex.EncodeToString(digest[:])
@@ -166,18 +162,16 @@ func init() {
// @function randimage 随机选取zip内的文件
// @param path zip路径
// @param seed 随机数种子
// @param ctx *zero.Ctx
// @return 文件路径 & 错误信息
func randimage(path string, seed int64) (im image.Image, index int, err error) {
func randimage(path string, ctx *zero.Ctx) (im image.Image, index int, err error) {
reader, err := zip.OpenReader(path)
if err != nil {
return
}
defer reader.Close()
r := rand.New(rand.NewSource(seed))
index = r.Intn(len(reader.File))
file := reader.File[index]
file := reader.File[ctxext.RandSenderPerDayN(ctx.Event.UserID, len(reader.File))]
f, err := file.Open()
if err != nil {
return
@@ -188,16 +182,6 @@ func randimage(path string, seed int64) (im image.Image, index int, err error) {
return
}
// @function randtext 随机选取签文
// @param file 文件路径
// @param seed 随机数种子
// @return 签名 & 签文 & 错误信息
func randtext(seed int64) (string, string) {
r := rand.New(rand.NewSource(seed))
i := r.Intn(len(omikujis))
return omikujis[i]["title"], omikujis[i]["content"]
}
// @function draw 绘制运势图
// @param background 背景图片路径
// @param seed 随机数种子

View File

@@ -3,15 +3,16 @@ package funny
import (
"strings"
"time"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
sql "github.com/FloatTech/sqlite"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
)
type joke struct {
@@ -22,17 +23,21 @@ type joke struct {
var db = &sql.Sqlite{}
func init() {
en := control.Register("funny", &control.Options{
en := control.Register("funny", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "讲个笑话\n" +
"- 讲个笑话[@xxx] | 讲个笑话[qq号]",
"- 讲个笑话[@xxx|qq号|人名] | 夸夸[@xxx|qq号|人名] ",
PublicDataFolder: "Funny",
})
en.OnPrefix("讲个笑话", ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
dbpath := en.DataFolder()
db.DBPath = dbpath + "jokes.db"
_, err := file.GetLazyData(db.DBPath, false, true)
en.OnPrefixGroup([]string{"讲个笑话", "夸夸"}, ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = en.DataFolder() + "jokes.db"
_, err := en.GetLazyData("jokes.db", true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false

View File

@@ -13,9 +13,9 @@ import (
"strings"
"sync/atomic"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img/writer"
"github.com/FloatTech/zbputils/process"
"github.com/golang/freetype"
@@ -34,7 +34,7 @@ var (
)
func init() {
engine := control.Register("genshin", &control.Options{
engine := control.Register("genshin", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "原神抽卡\n- 原神十连\n- 切换原神卡池",
PublicDataFolder: "Genshin",
@@ -42,7 +42,7 @@ func init() {
engine.OnFullMatch("切换原神卡池").SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
c, ok := control.Lookup("genshin")
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("找不到服务!"))
return
@@ -69,7 +69,7 @@ func init() {
engine.OnFullMatch("原神十连", ctxext.DoOnceOnSuccess(
func(ctx *zero.Ctx) bool {
zipfile := engine.DataFolder() + "Genshin.zip"
_, err := file.GetLazyData(zipfile, false, false)
_, err := engine.GetLazyData("Genshin.zip", false)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
@@ -83,7 +83,7 @@ func init() {
},
)).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
c, ok := control.Lookup("genshin")
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("找不到服务!"))
return

View File

@@ -1,6 +1,6 @@
# ZeroBot-Plugin-Gif
[ZeroBot QQ机器人](https://github.com/wdvxdr1123/ZeroBot)插件可以制作各种沙雕gif图
> 素材包地址: https://codechina.csdn.net/u011570312/imagematerials
> 素材包地址: https://gitcode.net/u011570312/imagematerials
## 触发方式
1. [指令词]+[qq号] 如爬123456

View File

@@ -20,7 +20,7 @@ func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
target := datapath + `materials/` + name
var err error
if file.IsNotExist(target) {
err = file.DownloadTo(`https://codechina.csdn.net/u011570312/imagematerials/-/raw/main/`+name, target, true)
err = file.DownloadTo(`https://gitcode.net/u011570312/imagematerials/-/raw/main/`+name, target, true)
if err != nil {
exit(err)
return
@@ -35,7 +35,7 @@ func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
func dlblock(name string) (string, error) {
target := datapath + `materials/` + name
if file.IsNotExist(target) {
err := file.DownloadTo(`https://codechina.csdn.net/u011570312/imagematerials/-/raw/main/`+name, target, true)
err := file.DownloadTo(`https://gitcode.net/u011570312/imagematerials/-/raw/main/`+name, target, true)
if err != nil {
return "", err
}

View File

@@ -6,7 +6,8 @@ import (
"strconv"
"strings"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -20,7 +21,7 @@ var (
)
func init() { // 插件主体
en := control.Register("gif", &control.Options{
en := control.Register("gif", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "制图\n- " + strings.Join(cmds, "\n- "),
PrivateDataFolder: "gif",

View File

@@ -9,7 +9,8 @@ import (
"net/url"
"strings"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -17,7 +18,7 @@ import (
)
func init() { // 插件主体
control.Register("github", &control.Options{
control.Register("github", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "GitHub仓库搜索\n" +
"- >github [xxx]\n" +

594
plugin/guessmusic/main.go Normal file
View File

@@ -0,0 +1,594 @@
// Package guessmusic 基于zbp的猜歌插件
package guessmusic
import (
"bytes"
"encoding/json"
"io/fs"
"io/ioutil"
"math/rand"
"net/http"
"net/url"
"os"
"os/exec"
"strconv"
"strings"
"time"
"github.com/pkg/errors"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/web"
"github.com/wdvxdr1123/ZeroBot/extension/single"
)
const (
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66"
)
var (
cuttime = [...]string{"00:00:05", "00:00:30", "00:01:00"} // 音乐切割时间点,可自行调节时间(时:分:秒)
cfg = config{ // 默认 config
MusicPath: file.BOTPATH + "/data/guessmusic/music/", // 绝对路径,歌库根目录,通过指令进行更改
Local: true, // 是否使用本地音乐库
API: true, // 是否使用 Api
}
)
func init() { // 插件主体
engine := control.Register("guessmusic", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "猜歌插件该插件依赖ffmpeg\n" +
"- 个人猜歌\n" +
"- 团队猜歌\n" +
"- 设置猜歌缓存歌库路径 [绝对路径]\n" +
"- 设置猜歌本地 [true/false]\n" +
"- 设置猜歌Api [true/false]\n" +
"注:默认歌库为网易云热歌榜\n" +
"1.可在后面添加“-动漫”进行动漫歌猜歌\n-这个只能猜歌名和歌手\n" +
"2.可在后面添加“-动漫2”进行动漫歌猜歌\n-这个可以猜番名,但歌手经常“未知”",
PrivateDataFolder: "guessmusic",
}).ApplySingle(single.New(
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
single.WithPostFn[int64](func(ctx *zero.Ctx) {
ctx.Send(
message.ReplyWithMessage(ctx.Event.MessageID,
message.Text("已经有正在进行的游戏..."),
),
)
}),
))
cachePath := engine.DataFolder() + "cache/"
err := os.MkdirAll(cachePath, 0755)
if err != nil {
panic(err)
}
cfgFile := engine.DataFolder() + "config.json"
if file.IsExist(cfgFile) {
reader, err := os.Open(cfgFile)
if err == nil {
err = json.NewDecoder(reader).Decode(&cfg)
if err != nil {
panic(err)
}
} else {
panic(err)
}
err = reader.Close()
if err != nil {
panic(err)
}
} else {
err = saveConfig(cfgFile)
if err != nil {
panic(err)
}
}
engine.OnRegex(`^设置猜歌(缓存歌库路径|本地|Api)\s*(.*)$`, func(ctx *zero.Ctx) bool {
if !zero.SuperUserPermission(ctx) {
ctx.SendChain(message.Text("只有bot主人可以设置"))
return false
}
return true
}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
option := ctx.State["regex_matched"].([]string)[1]
value := ctx.State["regex_matched"].([]string)[2]
switch option {
case "缓存歌库路径":
if value == "" {
ctx.SendChain(message.Text("请输入正确的路径!"))
return
}
musicPath := strings.ReplaceAll(value, "\\", "/")
if !strings.HasSuffix(musicPath, "/") {
musicPath += "/"
}
cfg.MusicPath = musicPath
case "本地":
choice, err := strconv.ParseBool(value)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
cfg.Local = choice
case "Api":
choice, err := strconv.ParseBool(value)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
cfg.API = choice
}
err = saveConfig(cfgFile)
if err == nil {
ctx.SendChain(message.Text("成功!"))
} else {
ctx.SendChain(message.Text("ERROR:", err))
}
})
engine.OnRegex(`^(个人|团队)猜歌(-动漫|-动漫2)?$`, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
mode := ctx.State["regex_matched"].([]string)[2]
gid := strconv.FormatInt(ctx.Event.GroupID, 10)
if mode == "-动漫2" {
ctx.SendChain(message.Text("正在准备歌曲,请稍等\n回答“-[歌曲名称|歌手|番剧|提示|取消]”\n一共3段语音6次机会"))
} else {
ctx.SendChain(message.Text("正在准备歌曲,请稍等\n回答“-[歌曲名称|歌手|提示|取消]”\n一共3段语音6次机会"))
}
// 随机抽歌
musicName, pathOfMusic, err := musicLottery(mode, cfg.MusicPath)
if err != nil {
ctx.SendChain(message.Text(err))
return
}
// 切割音频生成3个10秒的音频
outputPath := cachePath + gid + "/"
err = cutMusic(musicName, pathOfMusic, outputPath)
if err != nil {
ctx.SendChain(message.Text(err))
return
}
// 进行猜歌环节
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + "0.wav"))
answerString := strings.Split(musicName, " - ")
var next *zero.FutureEvent
if ctx.State["regex_matched"].([]string)[1] == "个人" {
next = zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`^-\S{1,}`), ctx.CheckSession())
} else {
next = zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`^-\S{1,}`), zero.CheckGroup(ctx.Event.GroupID))
}
var musicCount = 0 // 音频数量
var answerCount = 0 // 问答次数
recv, cancel := next.Repeat()
defer cancel()
wait := time.NewTimer(40 * time.Second)
tick := time.NewTimer(105 * time.Second)
after := time.NewTimer(120 * time.Second)
for {
select {
case <-tick.C:
ctx.SendChain(message.Text("猜歌游戏你还有15s作答时间"))
case <-after.C:
msg := make(message.Message, 0, 3)
msg = append(msg, message.Reply(ctx.Event.MessageID))
msg = append(msg, message.Text("猜歌超时,游戏结束\n答案是:",
"\n歌名:", answerString[0],
"\n歌手:", answerString[1]))
if mode == "-动漫2" {
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
}
ctx.Send(msg)
return
case <-wait.C:
wait.Reset(40 * time.Second)
musicCount++
if musicCount > 2 {
wait.Stop()
continue
}
ctx.SendChain(
message.Text("好像有些难度呢,再听这段音频,要仔细听哦"),
)
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
case c := <-recv:
wait.Reset(40 * time.Second)
tick.Reset(105 * time.Second)
after.Reset(120 * time.Second)
answer := strings.Replace(c.Event.Message.String(), "-", "", 1)
switch {
case answer == "取消":
if c.Event.UserID == ctx.Event.UserID {
wait.Stop()
tick.Stop()
after.Stop()
msg := make(message.Message, 0, 3)
msg = append(msg, message.Reply(c.Event.MessageID))
msg = append(msg, message.Text("游戏已取消,猜歌答案是",
"\n歌名:", answerString[0],
"\n歌手:", answerString[1]))
if mode == "-动漫2" {
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
}
ctx.Send(msg)
return
}
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("你无权限取消"),
),
)
case answer == "提示":
musicCount++
if musicCount > 2 {
wait.Stop()
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("已经没有提示了哦"),
),
)
continue
}
wait.Reset(40 * time.Second)
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("再听这段音频,要仔细听哦"),
),
)
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
case strings.Contains(answerString[0], answer) || strings.EqualFold(answerString[0], answer):
wait.Stop()
tick.Stop()
after.Stop()
msg := make(message.Message, 0, 3)
msg = append(msg, message.Reply(c.Event.MessageID))
msg = append(msg, message.Text("太棒了,你猜对歌曲名了!答案是",
"\n歌名:", answerString[0],
"\n歌手:", answerString[1]))
if mode == "-动漫2" {
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
}
ctx.Send(msg)
return
case answerString[1] == "未知" && answer == "未知":
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("该模式禁止回答“未知”"),
),
)
case strings.Contains(answerString[1], answer) || strings.EqualFold(answerString[1], answer):
wait.Stop()
tick.Stop()
after.Stop()
msg := make(message.Message, 0, 3)
msg = append(msg, message.Reply(c.Event.MessageID))
msg = append(msg, message.Text("太棒了,你猜对歌手名了!答案是",
"\n歌名:", answerString[0],
"\n歌手:", answerString[1]))
if mode == "-动漫2" {
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
}
ctx.Send(msg)
return
default:
if mode == "-动漫2" && (strings.Contains(answerString[2], answer) || strings.EqualFold(answerString[2], answer)) {
wait.Stop()
tick.Stop()
after.Stop()
ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
message.Text("太棒了,你猜对番剧名了!答案是:",
"\n歌名:", answerString[0],
"\n歌手:", answerString[1],
"\n歌曲出自:", answerString[2]),
))
return
}
musicCount++
switch {
case musicCount > 2 && answerCount < 6:
wait.Stop()
answerCount++
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("答案不对哦,加油啊~"),
),
)
case musicCount > 2:
wait.Stop()
tick.Stop()
after.Stop()
msg := make(message.Message, 0, 3)
msg = append(msg, message.Reply(c.Event.MessageID))
msg = append(msg, message.Text("次数到了,你没能猜出来。\n答案是:",
"\n歌名:", answerString[0],
"\n歌手:", answerString[1]))
if mode == "-动漫2" {
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
}
ctx.Send(msg)
return
default:
wait.Reset(40 * time.Second)
answerCount++
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("答案不对,再听这段音频,要仔细听哦"),
),
)
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
}
}
}
}
})
}
func saveConfig(cfgFile string) (err error) {
if reader, err := os.OpenFile(cfgFile, os.O_CREATE, os.ModePerm); err == nil {
err = json.NewEncoder(reader).Encode(&cfg)
if err != nil {
return err
}
} else {
return err
}
return nil
}
// 随机抽取音乐
func musicLottery(mode, musicPath string) (musicName, pathOfMusic string, err error) {
switch mode {
case "-动漫":
pathOfMusic = musicPath + "动漫/"
case "-动漫2":
pathOfMusic = musicPath + "动漫2/"
default:
pathOfMusic = musicPath + "歌榜/"
}
err = os.MkdirAll(pathOfMusic, 0755)
if err != nil {
err = errors.Errorf("[生成文件夹错误]ERROR:%s", err)
return
}
files, err := ioutil.ReadDir(pathOfMusic)
if err != nil {
err = errors.Errorf("[读取本地列表错误]ERROR:%s", err)
return
}
if cfg.Local && cfg.API {
switch {
case len(files) == 0:
// 如果没有任何本地就下载歌曲
musicName, err = getAPIMusic(mode, pathOfMusic)
if err != nil {
err = errors.Errorf("[本地数据为0歌曲下载错误]ERROR:%s", err)
return
}
case rand.Intn(2) == 0:
// [0,1)只会取到0rand不允许的
musicName = getLocalMusic(files)
default:
musicName, err = getAPIMusic(mode, pathOfMusic)
if err != nil {
// 如果下载失败就从本地抽一个歌曲
musicName = getLocalMusic(files)
err = nil
}
}
return
}
if cfg.Local {
if len(files) == 0 {
err = errors.New("[本地数据为0未开启API数据]")
return
}
musicName = getLocalMusic(files)
return
}
if cfg.API {
musicName, err = getAPIMusic(mode, pathOfMusic)
if err != nil {
err = errors.Errorf("[获取API失败未开启本地数据] ERROR:%s", err)
return
}
return
}
err = errors.New("[未开启API以及本地数据]")
return
}
func getAPIMusic(mode string, musicPath string) (musicName string, err error) {
switch mode {
case "-动漫":
musicName, err = getPaugramData(musicPath)
case "-动漫2":
musicName, err = getAnimeData(musicPath)
default:
musicName, err = getNetEaseData(musicPath)
}
return
}
func getLocalMusic(files []fs.FileInfo) (musicName string) {
if len(files) > 1 {
musicName = strings.Replace(files[rand.Intn(len(files))].Name(), ".mp3", "", 1)
} else {
musicName = strings.Replace(files[0].Name(), ".mp3", "", 1)
}
return
}
// 下载保罗API的歌曲
func getPaugramData(musicPath string) (musicName string, err error) {
api := "https://api.paugram.com/acgm/?list=1"
referer := "https://api.paugram.com/"
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
if err != nil {
return
}
var parsed paugramData
err = json.Unmarshal(data, &parsed)
if err != nil {
return
}
name := parsed.Title
artistsName := parsed.Artist
musicURL := parsed.Link
if name == "" || artistsName == "" {
err = errors.New("无法获API取歌曲信息")
return
}
musicName = name + " - " + artistsName
downMusic := musicPath + "/" + musicName + ".mp3"
response, err := http.Head(musicURL)
if err != nil {
err = errors.Errorf("下载音乐失败, ERROR: %s", err)
return
}
if response.StatusCode != 200 {
err = errors.Errorf("下载音乐失败, Status Code: %d", response.StatusCode)
return
}
if file.IsNotExist(downMusic) {
data, err = web.GetData(musicURL)
if err != nil {
return
}
err = os.WriteFile(downMusic, data, 0666)
if err != nil {
return
}
}
return
}
// 下载animeMusic API的歌曲
func getAnimeData(musicPath string) (musicName string, err error) {
api := "https://anime-music.jijidown.com/api/v2/music"
referer := "https://anime-music.jijidown.com/"
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
if err != nil {
return
}
var parsed animeData
err = json.Unmarshal(data, &parsed)
if err != nil {
return
}
name := parsed.Res.Title
artistName := parsed.Res.Author
acgName := parsed.Res.AnimeInfo.Title
//musicURL := parsed.Res.PlayURL
if name == "" || artistName == "" {
err = errors.New("无法获API取歌曲信息")
return
}
requestURL := "https://autumnfish.cn/search?keywords=" + url.QueryEscape(name+" "+artistName) + "&limit=1"
if artistName == "未知" {
requestURL = "https://autumnfish.cn/search?keywords=" + url.QueryEscape(acgName+" "+name) + "&limit=1"
}
data, err = web.GetData(requestURL)
if err != nil {
err = errors.Errorf("API歌曲查询失败, ERROR: %s", err)
return
}
var autumnfish autumnfishData
err = json.Unmarshal(data, &autumnfish)
if err != nil {
return
}
if autumnfish.Code != 200 {
err = errors.Errorf("下载音乐失败, Status Code: %d", autumnfish.Code)
return
}
musicID := strconv.Itoa(autumnfish.Result.Songs[0].ID)
if artistName == "未知" {
artistName = strings.ReplaceAll(autumnfish.Result.Songs[0].Artists[0].Name, " - ", "-")
}
musicName = name + " - " + artistName + " - " + acgName
downMusic := musicPath + "/" + musicName + ".mp3"
musicURL := "http://music.163.com/song/media/outer/url?id=" + musicID
response, err := http.Head(musicURL)
if err != nil {
err = errors.Errorf("下载音乐失败, ERROR: %s", err)
return
}
if response.StatusCode != 200 {
err = errors.Errorf("下载音乐失败, Status Code: %d", response.StatusCode)
return
}
if file.IsNotExist(downMusic) {
data, err = web.GetData(musicURL)
if err != nil {
return
}
err = os.WriteFile(downMusic, data, 0666)
if err != nil {
return
}
}
return
}
// 下载网易云热歌榜音乐
func getNetEaseData(musicPath string) (musicName string, err error) {
api := "https://api.uomg.com/api/rand.music?sort=%E7%83%AD%E6%AD%8C%E6%A6%9C&format=json"
referer := "https://api.uomg.com/api/rand.music"
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
if err != nil {
return
}
var parsed netEaseData
err = json.Unmarshal(data, &parsed)
if err != nil {
return
}
name := parsed.Data.Name
musicURL := parsed.Data.URL
artistsName := parsed.Data.Artistsname
if name == "" || artistsName == "" {
err = errors.New("无法获API取歌曲信息")
return
}
musicName = name + " - " + artistsName
downMusic := musicPath + "/" + musicName + ".mp3"
if file.IsNotExist(downMusic) {
data, err = web.GetData(musicURL)
if err != nil {
return
}
err = os.WriteFile(downMusic, data, 0666)
if err != nil {
return
}
}
return
}
// 切割音乐成三个10s音频
func cutMusic(musicName, pathOfMusic, outputPath string) (err error) {
err = os.MkdirAll(outputPath, 0755)
if err != nil {
err = errors.Errorf("[生成歌曲目录错误]ERROR:%s", err)
return
}
var stderr bytes.Buffer
cmdArguments := []string{"-y", "-i", pathOfMusic + musicName + ".mp3",
"-ss", cuttime[0], "-t", "10", file.BOTPATH + "/" + outputPath + "0.wav",
"-ss", cuttime[1], "-t", "10", file.BOTPATH + "/" + outputPath + "1.wav",
"-ss", cuttime[2], "-t", "10", file.BOTPATH + "/" + outputPath + "2.wav", "-hide_banner"}
cmd := exec.Command("ffmpeg", cmdArguments...)
cmd.Stderr = &stderr
err = cmd.Run()
if err != nil {
err = errors.Errorf("[生成歌曲错误]ERROR:%s", stderr.String())
return
}
return
}

107
plugin/guessmusic/struct.go Normal file
View File

@@ -0,0 +1,107 @@
package guessmusic
type config struct {
MusicPath string `json:"musicPath"`
Local bool `json:"local"`
API bool `json:"api"`
}
type paugramData struct {
ID int `json:"id"`
Title string `json:"title"`
Artist string `json:"artist"`
Album string `json:"album"`
Cover string `json:"cover"`
Lyric string `json:"lyric"`
SubLyric string `json:"sub_lyric"`
Link string `json:"link"`
Cached bool `json:"cached"`
}
type animeData struct {
Msg string `json:"msg"`
Res struct {
ID string `json:"id"`
AnimeInfo struct {
Desc string `json:"desc"`
ID string `json:"id"`
Atime int `json:"atime"`
Logo string `json:"logo"`
Year int `json:"year"`
Bg string `json:"bg"`
Title string `json:"title"`
Month int `json:"month"`
} `json:"anime_info"`
PlayURL string `json:"play_url"`
Atime int `json:"atime"`
Title string `json:"title"`
Author string `json:"author"`
Type string `json:"type"`
Recommend bool `json:"recommend"`
} `json:"res"`
Code int `json:"code"`
}
type netEaseData struct {
Code int `json:"code"`
Data struct {
Name string `json:"name"`
URL string `json:"url"`
Picurl string `json:"picurl"`
Artistsname string `json:"artistsname"`
} `json:"data"`
}
type autumnfishData struct {
Result struct {
Songs []struct {
ID int `json:"id"`
Name string `json:"name"`
Artists []struct {
ID int `json:"id"`
Name string `json:"name"`
PicURL interface{} `json:"picUrl"`
Alias []interface{} `json:"alias"`
AlbumSize int `json:"albumSize"`
PicID int `json:"picId"`
Img1V1URL string `json:"img1v1Url"`
Img1V1 int `json:"img1v1"`
Trans interface{} `json:"trans"`
} `json:"artists"`
Album struct {
ID int `json:"id"`
Name string `json:"name"`
Artist struct {
ID int `json:"id"`
Name string `json:"name"`
PicURL interface{} `json:"picUrl"`
Alias []interface{} `json:"alias"`
AlbumSize int `json:"albumSize"`
PicID int `json:"picId"`
Img1V1URL string `json:"img1v1Url"`
Img1V1 int `json:"img1v1"`
Trans interface{} `json:"trans"`
} `json:"artist"`
PublishTime int64 `json:"publishTime"`
Size int `json:"size"`
CopyrightID int `json:"copyrightId"`
Status int `json:"status"`
PicID int64 `json:"picId"`
Mark int `json:"mark"`
} `json:"album"`
Duration int `json:"duration"`
CopyrightID int `json:"copyrightId"`
Status int `json:"status"`
Alias []interface{} `json:"alias"`
Rtype int `json:"rtype"`
Ftype int `json:"ftype"`
Mvid int `json:"mvid"`
Fee int `json:"fee"`
RURL interface{} `json:"rUrl"`
Mark int `json:"mark"`
} `json:"songs"`
HasMore bool `json:"hasMore"`
SongCount int `json:"songCount"`
} `json:"result"`
Code int `json:"code"`
}

View File

@@ -11,7 +11,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/web"
@@ -40,7 +41,7 @@ const (
)
func init() {
engine := control.Register("hs", &control.Options{
engine := control.Register("hs", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "炉石\n" +
"- 搜卡[xxxx]\n" +

View File

@@ -1,3 +1,4 @@
// Package hyaku 百人一首
package hyaku
import (
@@ -9,6 +10,7 @@ import (
"strconv"
"unsafe"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -50,7 +52,7 @@ func (l *line) String() string {
var lines [100]*line
func init() {
engine := control.Register("hyaku", &control.Options{
engine := control.Register("hyaku", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "百人一首\n" +
"- 百人一首(随机发一首)\n" +

View File

@@ -5,14 +5,21 @@ import (
"encoding/json"
"errors"
"math/rand"
"net/http"
"net/url"
"reflect"
"regexp"
"strings"
"github.com/lucas-clemente/quic-go/http3"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/AnimeAPI/pixiv"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/pool"
@@ -20,21 +27,42 @@ import (
)
type resultjson struct {
Data struct {
Error bool `json:"error"`
Message string `json:"message"`
Data struct {
Illusts []struct {
ID int64 `json:"id"`
Title string `json:"title"`
AltTitle string `json:"altTitle"`
Description string `json:"description"`
Sanity int `json:"sanity"`
Type int64 `json:"type"`
CreateDate string `json:"createDate"`
UploadDate string `json:"uploadDate"`
Sanity int64 `json:"sanity"`
Width int64 `json:"width"`
Height int64 `json:"height"`
PageCount int64 `json:"pageCount"`
Tags []struct {
Name string `json:"name"`
Translation string `json:"translation"`
} `json:"tags"`
Statistic struct {
Bookmarks int64 `json:"bookmarks"`
Likes int64 `json:"likes"`
Comments int64 `json:"comments"`
Views int64 `json:"views"`
} `json:"statistic"`
Image string `json:"image"`
} `json:"illusts"`
Scores []float64 `json:"scores"`
HasNext bool `json:"has_next"`
} `json:"data"`
Error bool `json:"error"`
Message string `json:"message"`
}
var hrefre = regexp.MustCompile(`<a href=".*">`)
func init() {
control.Register("imgfinder", &control.Options{
control.Register("imgfinder", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "关键字搜图\n" +
"- 来张 [xxx]",
@@ -47,7 +75,8 @@ func init() {
return
}
rannum := rand.Intn(len(soutujson.Data.Illusts))
illust, err := pixiv.Works(soutujson.Data.Illusts[rannum].ID)
il := soutujson.Data.Illusts[rannum]
illust, err := pixiv.Works(il.ID)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
@@ -59,7 +88,18 @@ func init() {
err = pool.SendImageFromPool(n, f, func() error {
// 下载图片
return illust.DownloadToCache(0)
}, ctxext.SendFakeForwardToGroup(ctx), ctxext.GetFirstMessageInForward(ctx))
}, ctxext.SendFakeForwardToGroup(ctx,
message.Text(
il.Width, "x", il.Height, "\n",
"标题: ", il.Title, "\n",
"副标题: ", il.AltTitle, "\n",
"ID: ", il.ID, "\n",
"画师: ", illust.UserName, " (", illust.UserId, ")", "\n",
"分级:", il.Sanity, "\n",
hrefre.ReplaceAllString(strings.ReplaceAll(strings.ReplaceAll(il.Description, "<br />", "\n"), "</a>", ""), ""),
printtags(reflect.ValueOf(&il.Tags)),
),
), ctxext.GetFirstMessageInForward(ctx))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
@@ -69,7 +109,13 @@ func init() {
// soutuapi 请求api
func soutuapi(keyword string) (r resultjson, err error) {
data, err := web.GetData("https://copymanga.azurewebsites.net/api/pixivel?" + url.QueryEscape(keyword) + "?page=0")
var data []byte
data, err = web.RequestDataWith(&http.Client{Transport: &http3.RoundTripper{}},
"https://api.pixivel.moe/v2/pixiv/illust/search/"+url.QueryEscape(keyword)+"?page=0",
"GET",
"https://pixivel.moe/",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36",
)
if err != nil {
return
}
@@ -79,3 +125,21 @@ func soutuapi(keyword string) (r resultjson, err error) {
}
return
}
func printtags(r reflect.Value) string {
tags := r.Elem()
s := binary.BytesToString(binary.NewWriterF(func(w *binary.Writer) {
for i := 0; i < tags.Len(); i++ {
_ = w.WriteByte('\n')
tag := tags.Index(i)
_ = w.WriteByte('#')
w.WriteString(tag.Field(0).String())
if !tag.Field(1).IsZero() {
w.WriteString(" (")
w.WriteString(tag.Field(1).String())
w.WriteString(")")
}
}
}))
return s
}

View File

@@ -2,13 +2,14 @@
package inject
import (
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
en := control.Register("inject", &control.Options{
en := control.Register("inject", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "注入指令\n" +
"- run[CQ码]",

View File

@@ -6,11 +6,12 @@ import (
"hash/crc64"
"regexp"
"strconv"
"time"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/antchfx/htmlquery"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -22,17 +23,21 @@ const (
)
func init() {
engine := control.Register("jandan", &control.Options{
engine := control.Register("jandan", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "煎蛋网无聊图\n- 来份[屌|弔|吊]图\n- 更新[屌|弔|吊]图\n",
PublicDataFolder: "Jandan",
})
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
dbpath := engine.DataFolder()
db.DBPath = dbpath + "pics.db"
_, _ = file.GetLazyData(db.DBPath, false, false)
err := db.Create("picture", &picture{})
db.DBPath = engine.DataFolder() + "pics.db"
_, _ = engine.GetLazyData("pics.db", false)
err := db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = db.Create("picture", &picture{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false

View File

@@ -7,7 +7,8 @@ import (
"net/http"
"strings"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -22,7 +23,7 @@ const (
)
func init() {
control.Register("juejuezi", &control.Options{
control.Register("juejuezi", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "绝绝子生成器\n" +
"- 喝奶茶绝绝子 | 绝绝子吃饭",

View File

@@ -10,7 +10,8 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/pool"
"github.com/FloatTech/zbputils/math"
@@ -29,13 +30,13 @@ var (
)
func init() {
en := control.Register("lolicon", &control.Options{
en := control.Register("lolicon", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "lolicon\n" +
"- 来份萝莉\n" +
"- 设置随机图片地址[http...]",
}).ApplySingle(ctxext.DefaultSingle)
en.OnFullMatch("来份萝莉").SetBlock(true).
en.OnFullMatch("来份萝莉").Limit(ctxext.LimitByGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
go func() {
for i := 0; i < math.Min(cap(queue)-len(queue), 2); i++ {

View File

@@ -14,7 +14,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
sql "github.com/FloatTech/sqlite"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/math"
"github.com/FloatTech/zbputils/process"
@@ -59,7 +60,7 @@ var (
)
func init() { // 插件主体
engine := control.Register("manager", &control.Options{
engine := control.Register("manager", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: hint,
PrivateDataFolder: "manager",
@@ -67,8 +68,12 @@ func init() { // 插件主体
go func() {
db.DBPath = engine.DataFolder() + "config.db"
err := db.Open(time.Hour * 24)
if err != nil {
panic(err)
}
clock = timer.NewClock(db)
err := db.Create("welcome", &welcome{})
err = db.Create("welcome", &welcome{})
if err != nil {
panic(err)
}
@@ -385,7 +390,7 @@ func init() { // 插件主体
} else {
ctx.SendChain(message.Text("欢迎~"))
}
c, ok := control.Lookup("manager")
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
enable := c.GetData(ctx.Event.GroupID)&1 == 1
if enable {
@@ -499,7 +504,7 @@ func init() { // 插件主体
engine.OnRegex(`^(.*)入群验证$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
option := ctx.State["regex_matched"].([]string)[1]
c, ok := control.Lookup("manager")
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
data := c.GetData(ctx.Event.GroupID)
switch option {
@@ -524,7 +529,7 @@ func init() { // 插件主体
engine.OnRegex(`^(.*)gist加群自动审批$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
option := ctx.State["regex_matched"].([]string)[1]
c, ok := control.Lookup("manager")
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
data := c.GetData(ctx.Event.GroupID)
switch option {
@@ -552,7 +557,7 @@ func init() { // 插件主体
/*if ctx.Event.RequestType == "friend" {
ctx.SetFriendAddRequest(ctx.Event.Flag, true, "")
}*/
c, ok := control.Lookup("manager")
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok && c.GetData(ctx.Event.GroupID)&0x10 == 0x10 && ctx.Event.RequestType == "group" && ctx.Event.SubType == "add" {
// gist 文件名是群号的 ascii 编码的 md5
// gist 内容是当前 uinx 时间戳,在 10 分钟内视为有效

View File

@@ -0,0 +1,539 @@
// Package midicreate 简易midi音乐制作
package midicreate
import (
"bytes"
"fmt"
"math"
"math/rand"
"os"
"os/exec"
"path"
"path/filepath"
"strconv"
"strings"
"time"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/web"
"github.com/pkg/errors"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"gitlab.com/gomidi/midi/v2"
"gitlab.com/gomidi/midi/v2/smf"
)
func init() {
engine := control.Register("midicreate", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "midi音乐制作,该插件需要安装timidity,linux安装脚本可参考https://gitcode.net/anto_july/midi/-/raw/master/timidity.sh,windows安装脚本可参考https://gitcode.net/anto_july/midi/-/raw/master/timidity.bat,windows需要管理员模式运行\n" +
"- midi制作 CCGGAAGR FFEEDDCR GGFFEEDR GGFFEEDR CCGGAAGR FFEEDDCR\n" +
"- 个人听音练习\n" +
"- 团队听音练习\n" +
"- *.mid (midi 转 txt)\n" +
"- midi制作*.txt (txt 转 midi)\n" +
"- 设置音色40 (0~127)",
PrivateDataFolder: "midicreate",
})
cachePath := engine.DataFolder() + "cache/"
_ = os.RemoveAll(cachePath)
err := os.MkdirAll(cachePath, 0755)
if err != nil {
panic(err)
}
engine.OnPrefix("midi制作").SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID
input := ctx.State["args"].(string)
midiFile := cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
cmidiFile, err := str2music(ctx, input, midiFile)
if err != nil {
if file.IsExist(midiFile) {
ctx.UploadThisGroupFile(file.BOTPATH+"/"+midiFile, filepath.Base(midiFile), "")
return
}
ctx.SendChain(message.Text("ERROR:无法转换midi文件,", err))
return
}
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
})
engine.OnRegex("^(个人|团队)听音练习$", zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID
ctx.SendChain(message.Text("欢迎来到听音练习, 一共有5个问题, 每个问题1分"))
var mode int
var next *zero.FutureEvent
var maxErrorCount int
if ctx.State["regex_matched"].([]string)[1] == "个人" {
mode = 0
next = zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^[A-G][b|#]?\d{0,2}$`),
zero.OnlyGroup, ctx.CheckSession())
maxErrorCount = 3
} else {
mode = 1
next = zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^[A-G][b|#]?\d{0,2}$`),
zero.OnlyGroup, zero.CheckGroup(ctx.Event.GroupID))
maxErrorCount = 10
}
recv, cancel := next.Repeat()
defer cancel()
score := make(map[int64]float64)
round := 1
maxRound := 6
errorCount := 0
target := uint8(55 + rand.Intn(34))
answer := name(target) + strconv.Itoa(int(target/12))
midiFile := cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
cmidiFile, err := str2music(ctx, answer, midiFile)
if err != nil {
ctx.SendChain(message.Text("ERROR:听音练习结束, 无法转换midi文件, ", err))
return
}
time.Sleep(time.Millisecond * 500)
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
ctx.Send(
message.ReplyWithMessage(ctx.Event.MessageID,
message.Text("判断上面的音频, 输入音符, 例如C#6"),
),
)
tick := time.NewTimer(45 * time.Second)
after := time.NewTimer(60 * time.Second)
for {
select {
case <-tick.C:
ctx.SendChain(message.Text("听音练习, 你还有15s作答时间"))
case <-after.C:
var text string
for k, v := range score {
text += fmt.Sprintf("%s: %.1f\n", ctx.CardOrNickName(k), v)
}
ctx.Send(
message.ReplyWithMessage(ctx.Event.MessageID,
message.Text("听音练习超时, 练习结束...答案是: ", answer, "\n所得分数如下:\n", text),
),
)
return
case c := <-recv:
tick.Reset(45 * time.Second)
after.Reset(60 * time.Second)
n := processOne(c.Event.Message.String())
if n != target {
errorCount++
}
if errorCount == maxErrorCount || n == target {
if n == target {
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("恭喜你回答正确, 答案是: ", answer),
),
)
} else if errorCount == maxErrorCount {
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("你的回答是: "),
),
)
midiFile = cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
cmidiFile, err = str2music(ctx, c.Event.Message.String(), midiFile)
if err != nil {
ctx.SendChain(message.Text("ERROR: can't convert midi file,", err))
return
}
time.Sleep(time.Millisecond * 500)
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("回答错误, 答案是: ", answer, ", 错误次数已达3次, 进入下一关"),
),
)
}
// 统计分数
if mode == 0 {
switch errorCount {
case 0:
score[c.Event.UserID] += 1.0
case 1:
score[c.Event.UserID] += 0.5
case 2:
score[c.Event.UserID] += 0.2
}
} else if mode == 1 {
if errorCount != maxErrorCount {
score[c.Event.UserID] += 1.0
}
}
// 下一关
round++
if round != maxRound {
errorCount = 0
target = uint8(55 + rand.Intn(34))
answer = name(target) + strconv.Itoa(int(target/12))
midiFile = cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
cmidiFile, err = str2music(ctx, answer, midiFile)
if err != nil {
ctx.SendChain(message.Text("ERROR:听音练习结束, 无法转换midi文件, ", err))
return
}
time.Sleep(time.Millisecond * 500)
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("判断上面的音频, 输入音符, 例如C#6"),
),
)
}
} else if n != target {
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("你的回答是: "),
),
)
time.Sleep(time.Millisecond * 500)
midiFile = cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
cmidiFile, err = str2music(ctx, c.Event.Message.String(), midiFile)
if err != nil {
ctx.SendChain(message.Text("ERROR: can't convert midi file,", err))
return
}
time.Sleep(time.Millisecond * 500)
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("回答错误, 错误次数为", errorCount, ", 请继续回答"),
),
)
}
if round == maxRound {
var text string
for k, v := range score {
text += fmt.Sprintf("%s: %.1f\n", ctx.CardOrNickName(k), v)
}
ctx.Send(
message.ReplyWithMessage(c.Event.MessageID,
message.Text("回答完毕, 所得分数如下:\n", text),
),
)
return
}
}
}
})
engine.On("notice/group_upload", func(ctx *zero.Ctx) bool {
return path.Ext(ctx.Event.File.Name) == ".mid"
}).SetBlock(false).Limit(ctxext.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
fileURL := ctx.GetThisGroupFileUrl(ctx.Event.File.BusID, ctx.Event.File.ID)
data, err := web.GetData(fileURL)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
s, err := smf.ReadFrom(bytes.NewReader(data))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
for i := 0; i < int(s.NumTracks()); i++ {
midStr := mid2txt(data, i)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
fileName := strings.ReplaceAll(cachePath+"/"+ctx.Event.File.Name, ".mid", fmt.Sprintf("-%d.txt", i))
_ = os.WriteFile(fileName, binary.StringToBytes(midStr), 0666)
ctx.UploadThisGroupFile(file.BOTPATH+"/"+fileName, filepath.Base(fileName), "")
}
})
engine.On("notice/group_upload", func(ctx *zero.Ctx) bool {
return path.Ext(ctx.Event.File.Name) == ".txt" && strings.Contains(ctx.Event.File.Name, "midi制作")
}).SetBlock(false).Limit(ctxext.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
fileURL := ctx.GetThisGroupFileUrl(ctx.Event.File.BusID, ctx.Event.File.ID)
data, err := web.GetData(fileURL)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
uid := ctx.Event.UserID
midiFile := cachePath + strconv.FormatInt(uid, 10) + time.Now().Format("20060102150405") + "_midicreate.mid"
cmidiFile, err := str2music(ctx, binary.BytesToString(data), midiFile)
if err != nil {
ctx.SendChain(message.Text("ERROR:无法转换midi文件,", err))
return
}
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cmidiFile))
})
engine.OnPrefix("设置音色").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
param := ctx.State["args"].(string)
timbre, err := strconv.Atoi(param)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
}
err = setTimbreMode(ctx, int64(timbre))
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功"))
})
}
var (
noteMap = map[string]uint8{
"C": 60,
"Db": 61,
"D": 62,
"Eb": 63,
"E": 64,
"F": 65,
"Gb": 66,
"G": 67,
"Ab": 68,
"A": 69,
"Bb": 70,
"B": 71,
}
)
func str2music(ctx *zero.Ctx, input, midiFile string) (cmidiFile string, err error) {
err = mkMidi(ctx, midiFile, input)
if err != nil {
return
}
cmidiFile = strings.ReplaceAll(midiFile, ".mid", ".wav")
cmd := exec.Command("timidity", file.BOTPATH+"/"+midiFile, "-Ow", "-o", file.BOTPATH+"/"+cmidiFile)
err = cmd.Run()
return
}
func mkMidi(ctx *zero.Ctx, filePath, input string) error {
if file.IsExist(filePath) {
return nil
}
var (
clock smf.MetricTicks
tr smf.Track
)
tr.Add(0, smf.MetaMeter(4, 4))
tr.Add(0, smf.MetaTempo(72))
tr.Add(0, smf.MetaInstrument("Violin"))
timbre := getTimbreMode(ctx)
tr.Add(0, midi.ProgramChange(0, uint8(timbre)))
k := strings.ReplaceAll(input, " ", "")
var (
base uint8
level uint8
delay uint32
sleepFlag bool
lengthBytes = make([]byte, 0)
)
for i := 0; i < len(k); {
base = 0
level = 0
sleepFlag = false
lengthBytes = lengthBytes[:0]
for {
switch {
case k[i] == 'R':
sleepFlag = true
i++
case k[i] >= 'A' && k[i] <= 'G':
base = noteMap[k[i:i+1]] % 12
i++
case k[i] == 'b':
base--
i++
case k[i] == '#':
base++
i++
case k[i] >= '0' && k[i] <= '9':
level = level*10 + k[i] - '0'
i++
case k[i] == '<':
i++
for i < len(k) && (k[i] == '-' || (k[i] >= '0' && k[i] <= '9')) {
lengthBytes = append(lengthBytes, k[i])
i++
}
default:
return errors.Errorf("无法解析第%d个位置的%c字符", i, k[i])
}
if i >= len(k) || (k[i] >= 'A' && k[i] <= 'G') || k[i] == 'R' {
break
}
}
length, _ := strconv.Atoi(string(lengthBytes))
if sleepFlag {
if length >= 0 {
delay = clock.Ticks4th() * (1 << length)
} else {
delay = clock.Ticks4th() / (1 << -length)
}
continue
}
if level == 0 {
level = 5
}
tr.Add(delay, midi.NoteOn(0, o(base, level), 120))
if length >= 0 {
tr.Add(clock.Ticks4th()*(1<<length), midi.NoteOff(0, o(base, level)))
} else {
tr.Add(clock.Ticks4th()/(1<<-length), midi.NoteOff(0, o(base, level)))
}
delay = 0
}
tr.Close(0)
s := smf.New()
s.TimeFormat = clock
err := s.Add(tr)
if err != nil {
return err
}
f, err := os.Create(filePath)
if err != nil {
return err
}
_, err = s.WriteTo(f)
f.Close()
return err
}
func o(base uint8, oct uint8) uint8 {
if oct > 10 {
oct = 10
}
if oct == 0 {
return base
}
res := base + 12*oct
if res > 127 {
res -= 12
}
return res
}
func name(n uint8) string {
for k, v := range noteMap {
if v%12 == n%12 {
return k
}
}
return ""
}
func processOne(note string) uint8 {
k := strings.ReplaceAll(note, " ", "")
var (
base uint8
level uint8
)
for i := 0; i < len(k); i++ {
switch {
case k[i] >= 'A' && k[i] <= 'G':
base = noteMap[k[i:i+1]] % 12
case k[i] == 'b':
base--
case k[i] == '#':
base++
case k[i] >= '0' && k[i] <= '9':
level = level*10 + k[i] - '0'
}
}
if level == 0 {
level = 5
}
return o(base, level)
}
func mid2txt(midBytes []byte, trackNo int) (midStr string) {
var (
absTicksStart float64
absTicksEnd float64
startNote byte
endNote byte
defaultMetric = 960.0
)
_ = smf.ReadTracksFrom(bytes.NewReader(midBytes), trackNo).
Do(
func(te smf.TrackEvent) {
if !te.Message.IsMeta() {
b := te.Message.Bytes()
if te.Message.Is(midi.NoteOnMsg) && b[2] > 0 {
absTicksStart = float64(te.AbsTicks)
startNote = b[1]
}
if te.Message.Is(midi.NoteOffMsg) || (te.Message.Is(midi.NoteOnMsg) && b[2] == 0x00) {
absTicksEnd = float64(te.AbsTicks)
endNote = b[1]
if startNote == endNote {
sign := name(b[1])
level := b[1] / 12
length := (absTicksEnd - absTicksStart) / defaultMetric
midStr += sign
if level != 5 {
midStr += strconv.Itoa(int(level))
}
pow := int(math.Round(math.Log2(length)))
if pow >= -4 && pow != 0 {
midStr += "<" + strconv.Itoa(pow)
}
startNote = 0
endNote = 0
}
}
if (te.Message.Is(midi.NoteOnMsg) && b[2] > 0) && absTicksStart > absTicksEnd {
length := (absTicksStart - absTicksEnd) / defaultMetric
pow := int(math.Round(math.Log2(length)))
if pow == 0 {
midStr += "R"
} else if pow >= -4 {
midStr += "R<" + strconv.Itoa(pow)
}
}
}
},
)
return
}
func setTimbreMode(ctx *zero.Ctx, timbre int64) error {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
if timbre < 0 || timbre > 127 {
return errors.New("音色应该在0~127之间")
}
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
return errors.New("no such plugin")
}
return m.SetData(gid, timbre)
}
func getTimbreMode(ctx *zero.Ctx) (index int64) {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
index := m.GetData(gid)
return index
}
return 40
}

View File

@@ -8,7 +8,7 @@ import (
reg "github.com/fumiama/go-registry"
)
var sr = reg.NewRegedit("reilia.westeurope.cloudapp.azure.com:32664", "fumiama", "--")
var sr = reg.NewRegedit("reilia.fumiama.top:32664", "fumiama", "--")
func TestGetHoliday(t *testing.T) {
registry.Connect()

View File

@@ -21,7 +21,7 @@ func NewHoliday(name string, dur, year int, month time.Month, day int) *Holiday
return &Holiday{name: name, date: time.Date(year, month, day, 0, 0, 0, 0, time.Local), dur: time.Duration(dur) * time.Hour * 24}
}
var registry = reg.NewRegReader("reilia.westeurope.cloudapp.azure.com:32664", "fumiama")
var registry = reg.NewRegReader("reilia.fumiama.top:32664", "fumiama")
// GetHoliday 从 reg 服务器获取节日
func GetHoliday(name string) *Holiday {

View File

@@ -5,7 +5,8 @@ import (
"sync"
"time"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
@@ -17,7 +18,7 @@ var (
)
func init() { // 插件主体
control.Register("moyu", &control.Options{
control.Register("moyu", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Help: "moyu\n" +
"- /启用 moyu\n" +

View File

@@ -2,30 +2,15 @@
package moyucalendar
import (
"bufio"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"regexp"
"strings"
"time"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/web"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
xpath "github.com/antchfx/htmlquery"
)
var ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"
var weixin = regexp.MustCompile(`url \+= '(.+)';`)
var client = &http.Client{}
func init() {
control.Register("moyucalendar", &control.Options{
control.Register("moyucalendar", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Help: "摸鱼人日历\n" +
"- /启用 moyucalendar\n" +
@@ -34,159 +19,11 @@ func init() {
" - 摸鱼人日历",
}).OnFullMatch("摸鱼人日历").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
title := fmt.Sprintf("摸鱼人日历 %d月%d日", time.Now().Month(), time.Now().Day())
sg, cookies, err := sougou(title, "摸鱼人日历", ua)
data, err := web.GetData("https://api.vvhan.com/api/moyu")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
wx, err := redirect(sg, cookies, ua)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
image, err := calendar(wx, ua)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Image(image))
ctx.SendChain(message.ImageBytes(data))
})
}
func sougou(title, publisher, ua string) (string, []*http.Cookie, error) {
u, _ := url.Parse("https://weixin.sogou.com/weixin")
u.RawQuery = url.Values{
"type": []string{"2"},
"s_from": []string{"input"},
"query": []string{title},
}.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
return "", nil, err
}
req.Header.Set("User-Agent", ua)
resp, err := client.Do(req)
if err != nil {
return "", nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", nil, errors.New("status not ok")
}
// 解析XPATH
doc, err := xpath.Parse(resp.Body)
if err != nil {
return "", nil, err
}
// 取出每个返回的结果
list := xpath.Find(doc, `//*[@class="news-list"]/li/div[@class="txt-box"]`)
if len(list) == 0 {
return "", nil, errors.New("sougou result not found")
}
var match string
for i := range list {
account := xpath.FindOne(list[i], `//div[@class="s-p"]/a[@class="account"]`)
if account == nil {
continue
}
if xpath.InnerText(account) != publisher {
continue
}
target := xpath.FindOne(list[i], `//h3/a[@target="_blank"]`)
if target == nil {
continue
}
match = xpath.SelectAttr(target, "href")
break
}
if match == "" {
return "", nil, errors.New("sougou result not found")
}
return "https://weixin.sogou.com" + match, resp.Cookies(), nil
}
func redirect(link string, cookies []*http.Cookie, ua string) (string, error) {
req, err := http.NewRequest("GET", link, nil)
if err != nil {
return "", err
}
req.Header.Set("User-Agent", ua)
var c = make([]string, 0, 4)
for _, cookie := range cookies {
if cookie.Name != "ABTEST" && cookie.Name != "SNUID" &&
cookie.Name != "IPLOC" && cookie.Name != "SUID" {
continue
}
c = append(c, cookie.Name+"="+cookie.Value)
}
req.Header.Set("Cookie", strings.Join(c, "; "))
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", errors.New("status not ok")
}
br := bufio.NewReader(resp.Body)
var u = make([]string, 0)
for {
b, _, err := br.ReadLine()
if err == io.EOF {
break
}
if err != nil {
return "", err
}
matcha := weixin.FindStringSubmatch(string(b))
if len(matcha) < 2 {
continue
}
u = append(u, strings.ReplaceAll(matcha[1], "@", ""))
}
if len(u) == 0 {
return "", errors.New("weixin url not found")
}
return strings.Join(u, ""), nil
}
func calendar(link, ua string) (string, error) {
req, err := http.NewRequest("GET", link, nil)
req.Header.Set("User-Agent", ua)
if err != nil {
return "", err
}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", errors.New("status not ok")
}
doc, err := xpath.Parse(resp.Body)
if err != nil {
return "", err
}
html := xpath.OutputHTML(doc, false)
if !strings.Contains(html, time.Now().Format("2006-01-02")) {
return "", errors.New("calendar not today")
}
images := xpath.Find(doc, `//*[@id="js_content"]/p/img`)
if images == nil {
return "", errors.New("calendar not found")
}
var image string
for i := range images {
if xpath.SelectAttr(images[i], "data-w") != "540" {
continue
}
image = xpath.SelectAttr(images[i], "data-src")
break
}
if image == "" {
return "", errors.New("image not found")
}
return image, nil
}

View File

@@ -11,7 +11,10 @@ import (
"strings"
"time"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -19,7 +22,7 @@ import (
)
func init() {
control.Register("music", &control.Options{
control.Register("music", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "点歌\n" +
"- 点歌[xxx]\n" +
@@ -134,72 +137,28 @@ func kugou(keyword string) message.MessageSegment {
}
// cloud163 返回网易云音乐卡片
func cloud163(keyword string) message.MessageSegment {
headers := http.Header{
"Content-Type": []string{"application/x-www-form-urlencoded"},
"User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0"},
func cloud163(keyword string) (msg message.MessageSegment) {
requestURL := "https://autumnfish.cn/search?keywords=" + url.QueryEscape(keyword)
data, err := web.GetData(requestURL)
if err != nil {
msg = message.Text("ERROR:", err)
return
}
data := url.Values{
"keywords": []string{keyword},
}
// 通过API 搜索音乐信息 第一首
// 返回音乐卡片
return message.Music("163", gjson.ParseBytes(netPost("https://nemapi.windis.xyz/search", data, headers)).Get("result.songs.0.id").Int())
msg = message.Music("163", gjson.ParseBytes(data).Get("result.songs.0.id").Int())
return
}
// qqmusic 返回QQ音乐卡片
func qqmusic(keyword string) message.MessageSegment {
// 搜索音乐信息 第一首歌
h1 := http.Header{
"User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0"},
func qqmusic(keyword string) (msg message.MessageSegment) {
requestURL := "https://c.y.qq.com/soso/fcgi-bin/client_search_cp?w=" + url.QueryEscape(keyword)
data, err := web.RequestDataWith(web.NewDefaultClient(), requestURL, "GET", "", web.RandUA())
if err != nil {
msg = message.Text("ERROR:", err)
return
}
search, _ := url.Parse("https://c.y.qq.com/soso/fcgi-bin/client_search_cp")
search.RawQuery = url.Values{
"w": []string{keyword},
}.Encode()
res := netGet(search.String(), h1)
info := gjson.ParseBytes(res[9 : len(res)-1]).Get("data.song.list.0")
// 获得音乐直链
h2 := http.Header{
"User-Agent": []string{"Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"},
"referer": []string{"http://y.qq.com"},
}
music, _ := url.Parse("https://u.y.qq.com/cgi-bin/musicu.fcg")
music.RawQuery = url.Values{
"data": []string{`{"req": {"module": "CDN.SrfCdnDispatchServer", "method": "GetCdnDispatch", "param": {"guid": "3982823384", "calltype": 0, "userip": ""}}, "req_0": {"module": "vkey.GetVkeyServer", "method": "CgiGetVkey", "param": {"guid": "3982823384", "songmid": ["` + info.Get("songmid").Str + `"], "songtype": [0], "uin": "0", "loginflag": 1, "platform": "20"}}, "comm": {"uin": 0, "format": "json", "ct": 24, "cv": 0}}`},
}.Encode()
audio := gjson.ParseBytes(netGet(music.String(), h2))
// 获得音乐封面
image := "https://y.gtimg.cn/music/photo_new/" +
find(
`photo_new\u002F`,
"?max_age",
string(
netGet("https://y.qq.com/n/yqq/song/"+info.Get("songmid").Str+".html", nil),
),
)
// 返回音乐卡片
return message.CustomMusic(
"https://y.qq.com/n/yqq/song/"+info.Get("songmid").Str+".html",
"https://isure.stream.qqmusic.qq.com/"+audio.Get("req_0.data.midurlinfo.0.purl").Str,
info.Get("songname").Str,
).Add("content", info.Get("singer.0.name").Str).Add("image", image)
}
// find 返回 pre 到 suf 之间的文本
func find(pre string, suf string, str string) string {
n := strings.Index(str, pre)
if n == -1 {
n = 0
} else {
n += len(pre)
}
str = str[n:]
m := strings.Index(str, suf)
if m == -1 {
m = len(str)
}
return str[:m]
info := gjson.ParseBytes(data[9 : len(data)-1]).Get("data.song.list.0")
msg = message.Music("qq", info.Get("songid").Int())
return
}
// md5str 返回字符串 MD5
@@ -223,17 +182,3 @@ func netGet(url string, header http.Header) []byte {
result, _ := io.ReadAll(res.Body)
return result
}
// netPost 返回请求数据
func netPost(url string, data url.Values, header http.Header) []byte {
client := &http.Client{}
request, _ := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
request.Header = header
res, err := client.Do(request)
if err != nil {
return nil
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
return result
}

View File

@@ -7,6 +7,7 @@ import (
"os"
"strings"
"sync"
"time"
"github.com/corona10/goimagehash"
"github.com/sirupsen/logrus"
@@ -32,7 +33,7 @@ type nsetu struct {
func (n *nsetu) List() (l []string) {
if file.IsExist(n.db.DBPath) {
err := n.db.Open()
err := n.db.Open(time.Hour * 24)
if err == nil {
l, err = n.db.ListTables()
}
@@ -77,7 +78,8 @@ func (n *nsetu) scanclass(root fs.FS, path, clsn string) error {
return err
}
n.mu.Lock()
_ = n.db.Truncate(clsn)
_ = n.db.Drop(clsn)
_ = n.db.Create(clsn, &setuclass{})
n.mu.Unlock()
for _, d := range ds {
nm := d.Name()

View File

@@ -10,6 +10,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
@@ -20,7 +21,7 @@ var (
)
func init() {
engine := control.Register("nativesetu", &control.Options{
engine := control.Register("nativesetu", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "本地涩图\n" +
"- 本地[xxx]\n" +
@@ -41,7 +42,7 @@ func init() {
}
}
engine.OnRegex(`^本地(.*)$`, ctxext.FirstValueInList(ns)).SetBlock(true).
engine.OnRegex(`^本地(.*)$`, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, ns)).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
imgtype := ctx.State["regex_matched"].([]string)[1]
sc := new(setuclass)
@@ -62,7 +63,7 @@ func init() {
ctx.SendChain(message.Text(imgtype, ": ", sc.Name, "\n"), message.Image(p))
}
})
engine.OnRegex(`^刷新本地(.*)$`, ctxext.FirstValueInList(ns), zero.SuperUserPermission).SetBlock(true).
engine.OnRegex(`^刷新本地(.*)$`, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, ns), zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
imgtype := ctx.State["regex_matched"].([]string)[1]
err := ns.scanclass(os.DirFS(setupath), imgtype, imgtype)

View File

@@ -16,12 +16,13 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/file"
)
func init() {
engine := control.Register("nwife", &control.Options{
engine := control.Register("nwife", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "nativewife\n- 抽wife[@xxx]\n- 添加wife[名字][图片]\n- 删除wife[名字]\n- [让 | 不让]所有人均可添加wife",
PrivateDataFolder: "nwife",
@@ -123,9 +124,9 @@ func init() {
var err error
switch text {
case "设置", "授予", "让":
err = setEveryoneCanAddWife(ctx.Event.GroupID, true)
err = setEveryoneCanAddWife(ctx, true)
case "取消", "撤销", "不让":
err = setEveryoneCanAddWife(ctx.Event.GroupID, false)
err = setEveryoneCanAddWife(ctx, false)
}
if err == nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功!"))
@@ -138,7 +139,7 @@ func init() {
func chkAddWifePermission(ctx *zero.Ctx) bool {
gid := ctx.Event.GroupID
if gid > 0 {
m, ok := control.Lookup("nwife")
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
data := m.GetData(gid)
if data&1 == 1 {
@@ -150,13 +151,13 @@ func chkAddWifePermission(ctx *zero.Ctx) bool {
return false
}
func setEveryoneCanAddWife(gid int64, canadd bool) error {
m, ok := control.Lookup("nwife")
func setEveryoneCanAddWife(ctx *zero.Ctx, canadd bool) error {
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
if canadd {
return m.SetData(gid, 1)
return m.SetData(ctx.Event.GroupID, 1)
}
return m.SetData(gid, 0)
return m.SetData(ctx.Event.GroupID, 0)
}
return errors.New("no such plugin")
}

View File

@@ -7,6 +7,7 @@ import (
"net/url"
"strings"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -14,7 +15,7 @@ import (
)
func init() {
control.Register("nbnhhsh", &control.Options{
control.Register("nbnhhsh", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "拼音首字母释义工具\n- ?? [缩写]",
}).OnRegex(`^[?]{1,2} ?([a-z0-9]+)$`).SetBlock(false).

View File

@@ -15,8 +15,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
ctrl "github.com/FloatTech/zbpctrl"
ub "github.com/FloatTech/zbputils/binary"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/text"
)
@@ -37,7 +38,7 @@ const (
var gCurCookieJar *cookiejar.Jar
func init() {
control.Register("novel", &control.Options{
control.Register("novel", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "铅笔小说网搜索\n- 小说[xxx]",
}).OnRegex("^小说([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).Limit(ctxext.LimitByUser).

View File

@@ -3,6 +3,7 @@ package nsfw
import (
"github.com/FloatTech/AnimeAPI/nsfw"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/process"
@@ -13,7 +14,7 @@ import (
const hso = "https://gchat.qpic.cn/gchatpic_new//--4234EDEC5F147A4C319A41149D7E0EA9/0"
func init() {
engine := control.Register("nsfw", &control.Options{
engine := control.Register("nsfw", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "nsfw图片识别\n- nsfw打分[图片]",
}).ApplySingle(ctxext.DefaultSingle)
@@ -31,7 +32,7 @@ func init() {
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(judge(p))))
}
})
control.Register("nsfwauto", &control.Options{
control.Register("nsfwauto", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Help: "nsfw图片自动识别\n- 当图片属于非 neutral 类别时自动发送评价",
}).OnMessage(zero.HasPicture).SetBlock(false).

View File

@@ -3,25 +3,23 @@ package omikuji
import (
"fmt"
"log"
"math/rand"
"strconv"
"time"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img/text"
)
const bed = "https://gitcode.net/u011570312/senso-ji-omikuji/-/raw/main/%d_%d.jpg"
func init() { // 插件主体
engine := control.Register("omikuji", &control.Options{
engine := control.Register("omikuji", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "浅草寺求签\n" +
"- 求签 | 占卜\n- 解签",
@@ -30,22 +28,22 @@ func init() { // 插件主体
engine.OnFullMatchGroup([]string{"求签", "占卜"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
miku, err := bangoToday(ctx.Event.UserID)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
i := ctxext.RandSenderPerDayN(ctx.Event.UserID, 100) + 1
ctx.SendChain(
message.At(ctx.Event.UserID),
message.Image(fmt.Sprintf(bed, miku, 0)),
message.Image(fmt.Sprintf(bed, miku, 1)),
message.Image(fmt.Sprintf(bed, i, 0)),
message.Image(fmt.Sprintf(bed, i, 1)),
)
})
engine.OnFullMatch("解签", ctxext.DoOnceOnSuccess(
func(ctx *zero.Ctx) bool {
dbpath := engine.DataFolder()
db.DBPath = dbpath + "kuji.db"
_, err := file.GetLazyData(db.DBPath, false, true)
db.DBPath = engine.DataFolder() + "kuji.db"
_, err := engine.GetLazyData("kuji.db", true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
@@ -60,17 +58,17 @@ func init() { // 插件主体
ctx.SendChain(message.Text("ERROR:", err))
return false
}
log.Printf("[kuji]读取%d条签文", n)
logrus.Infof("[kuji]读取%d条签文", n)
return true
},
)).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
bg, err := bangoToday(ctx.Event.UserID)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
kujiBytes, err := text.RenderToBase64(getKujiByBango(bg), text.FontFile, 400, 20)
kujiBytes, err := text.RenderToBase64(
getKujiByBango(
uint8(ctxext.RandSenderPerDayN(ctx.Event.UserID, 100)+1),
),
text.FontFile, 400, 20,
)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
@@ -80,13 +78,3 @@ func init() { // 插件主体
}
})
}
func bangoToday(uid int64) (uint8, error) {
today, err := strconv.ParseInt(time.Now().Format("20060102"), 10, 64)
if err != nil {
return 0, err
}
seed := uid + today
r := rand.New(rand.NewSource(seed))
return uint8(r.Intn(100) + 1), nil
}

798
plugin/qqwife/qqmapwife.go Normal file
View File

@@ -0,0 +1,798 @@
// Package qqwife 娶群友 基于“翻牌”和江林大佬的“群老婆”插件魔改作品文案采用了Hana的zbp娶群友文案
package qqwife
import (
"math/rand"
"sort"
"strconv"
"sync"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
ctrl "github.com/FloatTech/zbpctrl"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/math"
// 数据库
sql "github.com/FloatTech/sqlite"
// 定时器
"github.com/wdvxdr1123/ZeroBot/extension/rate"
// 画图
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img/text"
"github.com/FloatTech/zbputils/img/writer"
"github.com/fogleman/gg"
)
//nolint: asciicheck
type 婚姻登记 struct {
db *sql.Sqlite
dbmu sync.RWMutex
}
// 结婚证信息
type userinfo struct {
User int64 // 用户身份证
Target int64 // 对象身份证号
Username string // 户主名称
Targetname string // 对象名称
Updatetime string // 登记时间
}
// 民政局的当前时间
type updateinfo struct {
GID int64
Updatetime string // 登记时间
}
func (sql *婚姻登记) checkupdate(gid int64) (updatetime string, err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
err = sql.db.Create("updateinfo", &updateinfo{})
if err != nil {
return
}
gidstr := strconv.FormatInt(gid, 10)
dbinfo := updateinfo{}
err = sql.db.Find("updateinfo", &dbinfo, "where gid is "+gidstr) // 获取表格更新的时间
if err != nil {
updatetime = time.Now().Format("2006/01/02")
err = sql.db.Insert("updateinfo", &updateinfo{GID: gid, Updatetime: updatetime})
return
}
updatetime = dbinfo.Updatetime
return
}
func (sql *婚姻登记) 重置(gid string) error {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
if gid != "ALL" {
err := sql.db.Drop(gid)
if err != nil {
err = sql.db.Create(gid, &userinfo{})
return err
}
gidint, _ := strconv.ParseInt(gid, 10, 64)
updateinfo := updateinfo{
GID: gidint,
Updatetime: time.Now().Format("2006/01/02"),
}
err = sql.db.Insert("updateinfo", &updateinfo)
return err
}
grouplist, err := sql.db.ListTables()
if err != nil {
return err
}
for _, gid := range grouplist {
err = sql.db.Drop(gid)
if err != nil {
continue
}
gidint, _ := strconv.ParseInt(gid, 10, 64)
updateinfo := updateinfo{
GID: gidint,
Updatetime: time.Now().Format("2006/01/02"),
}
err = sql.db.Insert("updateinfo", &updateinfo)
}
return err
}
func (sql *婚姻登记) 离婚休妻(gid, wife int64) error {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
wifestr := strconv.FormatInt(wife, 10)
// 先判断用户是否存在
err := sql.db.Del(gidstr, "where target = "+wifestr)
return err
}
func (sql *婚姻登记) 离婚休夫(gid, husband int64) error {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
husbandstr := strconv.FormatInt(husband, 10)
// 先判断用户是否存在
err := sql.db.Del(gidstr, "where target = "+husbandstr)
return err
}
func (sql *婚姻登记) 复婚(gid, uid, target int64, username, targetname string) error {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
uidstr := strconv.FormatInt(uid, 10)
tagstr := strconv.FormatInt(target, 10)
var info userinfo
err := sql.db.Find(gidstr, &info, "where user = "+uidstr)
if err == nil {
err = sql.db.Find(gidstr, &info, "where user = "+tagstr)
}
if err == nil {
return err
}
updatetime := time.Now().Format("2006/01/02")
// 更改夫妻信息
info.User = uid
info.Username = username
info.Target = target
info.Targetname = targetname
info.Updatetime = updatetime
// 民政局登记数据
err = sql.db.Insert(gidstr, &info)
return err
}
func (sql *婚姻登记) 花名册(gid int64) (list [][4]string, number int, err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
err = sql.db.Create(gidstr, &userinfo{})
if err != nil {
return
}
number, err = sql.db.Count(gidstr)
if err != nil || number <= 0 {
return
}
var info userinfo
list = make([][4]string, 0, number)
err = sql.db.FindFor(gidstr, &info, "GROUP BY user", func() error {
if info.Target == 0 {
return nil
}
dbinfo := [4]string{
info.Username,
strconv.FormatInt(info.User, 10),
info.Targetname,
strconv.FormatInt(info.Target, 10),
}
list = append(list, dbinfo)
return nil
})
if len(list) == 0 {
number = 0
}
return
}
func slicename(name string, canvas *gg.Context) (resultname string) {
usermane := []rune(name) // 将每个字符单独放置
widthlen := 0
numberlen := 0
for i, v := range usermane {
width, _ := canvas.MeasureString(string(v)) // 获取单个字符的宽度
widthlen += int(width)
if widthlen > 350 {
break // 总宽度不能超过350
}
numberlen = i
}
if widthlen > 350 {
resultname = string(usermane[:numberlen-1]) + "......" // 名字切片
} else {
resultname = name
}
return
}
func (sql *婚姻登记) 查户口(gid, uid int64) (info userinfo, status int, err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
uidstr := strconv.FormatInt(uid, 10)
status = 3
if err = sql.db.Create(gidstr, &userinfo{}); err != nil {
status = 2
return
}
err = sql.db.Find(gidstr, &info, "where user = "+uidstr)
if err == nil {
status = 1
return
}
err = sql.db.Find(gidstr, &info, "where target = "+uidstr)
if err == nil {
status = 0
return
}
return
}
func (sql *婚姻登记) 登记(gid, uid, target int64, username, targetname string) error {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
err := sql.db.Create(gidstr, &userinfo{})
if err != nil {
return err
}
updatetime := time.Now().Format("2006/01/02")
// 填写夫妻信息
uidinfo := userinfo{
User: uid,
Username: username,
Target: target,
Targetname: targetname,
Updatetime: updatetime,
}
// 民政局登记数据
err = sql.db.Insert(gidstr, &uidinfo)
return err
}
var (
//nolint: asciicheck
民政局 = &婚姻登记{
db: &sql.Sqlite{},
}
skillCD = rate.NewManager[string](time.Hour*12, 1)
sendtext = [...][]string{
{ // 表白成功
"是个勇敢的孩子(*/ω\*) 今天的运气都降临在你的身边~\n\n",
"(´・ω・`)对方答应了你 并表示愿意当今天的CP\n\n",
},
{ // 表白失败
"今天的运气有一点背哦~明天再试试叭",
"_(:з」∠)_下次还有机会 咱抱抱你w",
"今天失败了惹. 摸摸头~咱明天还有机会",
},
{ // ntr成功
"因为你的个人魅力~~今天他就是你的了w\n\n",
},
{ // 离婚失败
"打是情,骂是爱,,不打不亲不相爱。答应我不要分手。",
"床头打架床尾和,夫妻没有隔夜仇。安啦安啦,不要闹变扭。",
},
{ // 离婚成功
"离婚成功力\n天涯何处无芳草何必单恋一枝花不如再摘一支bushi",
"离婚成功力\n话说你不考虑当个1",
},
}
)
func init() {
engine := control.Register("qqwife", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
PrivateDataFolder: "qqwife",
Help: "一群一天一夫一妻制群老婆\n每天凌晨刷新CP\n" +
"- 娶群友\n- 群老婆列表\n" +
"--------------------------------\n以下技能每人只能三选一\n CD12H不跨天刷新\n--------------------------------\n" +
"- (娶|嫁)@对方QQ\n- 当[对方Q号|@对方QQ]的小三\n- 闹离婚",
})
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
民政局.db.DBPath = engine.DataFolder() + "结婚登记表.db"
// 如果数据库不存在则下载
// _, _ = engine.GetLazyData("结婚登记表.db", false)
err := 民政局.db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return false
}
return true
})
engine.OnFullMatch("娶群友", zero.OnlyGroup, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
updatetime, err := 民政局.checkupdate(gid)
switch {
case err != nil:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
case time.Now().Format("2006/01/02") != updatetime:
if err := 民政局.重置(strconv.FormatInt(gid, 10)); err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
}
uid := ctx.Event.UserID
targetinfo, status, err := 民政局.查户口(gid, uid)
switch {
case status == 2:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
case status != 3 && targetinfo.Target == 0: // 如果为单身贵族
ctx.SendChain(message.Text("今天你是单身贵族噢"))
return
case status == 1: // 娶过别人
ctx.SendChain(
message.At(uid),
message.Text("\n今天你已经娶过了群老婆是"),
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(targetinfo.Target, 10)+"&s=640").Add("cache", 0),
message.Text(
"\n",
"[", targetinfo.Targetname, "]",
"(", targetinfo.Target, ")哒",
),
)
return
case status == 0: // 嫁给别人
ctx.SendChain(
message.At(uid),
message.Text("\n今天你被娶了群老公是"),
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(targetinfo.User, 10)+"&s=640").Add("cache", 0),
message.Text(
"\n",
"[", targetinfo.Username, "]",
"(", targetinfo.User, ")哒",
),
)
return
}
// 无缓存获取群员列表
temp := ctx.GetThisGroupMemberListNoCache().Array()
sort.SliceStable(temp, func(i, j int) bool {
return temp[i].Get("last_sent_time").Int() < temp[j].Get("last_sent_time").Int()
})
temp = temp[math.Max(0, len(temp)-30):]
// 将已经娶过的人剔除
qqgrouplist := make([]int64, 0, len(temp))
for k := 0; k < len(temp); k++ {
usr := temp[k].Get("user_id").Int()
_, status, _ := 民政局.查户口(gid, usr)
if status != 3 {
continue
}
qqgrouplist = append(qqgrouplist, usr)
}
// 没有人(只剩自己)的时候
if len(qqgrouplist) == 1 {
ctx.SendChain(message.Text("~群里没有ta人是单身了哦 明天再试试叭"))
return
}
// 随机抽娶
fiancee := qqgrouplist[rand.Intn(len(qqgrouplist))]
if fiancee == uid { // 如果是自己
ctx.SendChain(message.Text("呜...没娶到,你可以再尝试一次"))
return
}
// 去民政局办证
err = 民政局.登记(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
// 请大家吃席
ctx.SendChain(
message.At(uid),
message.Text("今天你的群老婆是"),
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(fiancee, 10)+"&s=640").Add("cache", 0),
message.Text(
"\n",
"[", ctx.CardOrNickName(fiancee), "]",
"(", fiancee, ")哒",
),
)
})
// 单身技能
engine.OnRegex(`^(娶|嫁)\[CQ:at,qq=(\d+)\]`, zero.OnlyGroup, getdb, checkdog).SetBlock(true).Limit(cdcheck, iscding).
Handle(func(ctx *zero.Ctx) {
choice := ctx.State["regex_matched"].([]string)[1]
fiancee, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
uid := ctx.Event.UserID
gid := ctx.Event.GroupID
if uid == fiancee { // 如果是自己
switch rand.Intn(3) {
case 1:
err := 民政局.登记(gid, uid, 0, "", "")
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
ctx.SendChain(message.Text("今日获得成就:单身贵族"))
default:
ctx.SendChain(message.Text("今日获得成就:自恋狂"))
}
return
}
if rand.Intn(2) == 0 { // 二分之一的概率表白成功
ctx.SendChain(message.Text(sendtext[1][rand.Intn(len(sendtext[1]))]))
return
}
// 去民政局登记
var choicetext string
switch choice {
case "娶":
err := 民政局.登记(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
choicetext = "\n今天你的群老婆是"
default:
err := 民政局.登记(gid, fiancee, uid, ctx.CardOrNickName(fiancee), ctx.CardOrNickName(uid))
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
choicetext = "\n今天你的群老公是"
}
// 请大家吃席
ctx.SendChain(
message.Text(sendtext[0][rand.Intn(len(sendtext[0]))]),
message.At(uid),
message.Text(choicetext),
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(fiancee, 10)+"&s=640").Add("cache", 0),
message.Text(
"\n",
"[", ctx.CardOrNickName(fiancee), "]",
"(", fiancee, ")哒",
),
)
})
// NTR技能
engine.OnRegex(`^当(\[CQ:at,qq=(\d+)\]\s?|(\d+))的小三`, zero.OnlyGroup, getdb, checkcp).SetBlock(true).Limit(cdcheck, iscding).
Handle(func(ctx *zero.Ctx) {
fid := ctx.State["regex_matched"].([]string)
fiancee, _ := strconv.ParseInt(fid[2]+fid[3], 10, 64)
uid := ctx.Event.UserID
if fiancee == uid {
ctx.SendChain(message.Text("今日获得成就:自我攻略"))
return
}
if rand.Intn(10)/4 != 0 { // 十分之三的概率NTR成功
ctx.SendChain(message.Text("失败了!可惜"))
return
}
gid := ctx.Event.GroupID
// 判断target是老公还是老婆
var choicetext string
_, gender, err := 民政局.查户口(gid, fiancee)
switch gender {
case 3:
ctx.SendChain(message.Text("ta现在还是单身哦快向ta表白吧"))
return
case 2:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
case 1:
// 和对象结婚登记
err = 民政局.复婚(gid, fiancee, uid, ctx.CardOrNickName(fiancee), ctx.CardOrNickName(uid))
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
choicetext = "老公"
case 0:
// 和对象结婚登记
err = 民政局.复婚(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
choicetext = "老婆"
default:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员"))
return
}
// 输出结果
ctx.SendChain(
message.Text(sendtext[2][rand.Intn(len(sendtext[2]))]),
message.At(uid),
message.Text("今天你的群"+choicetext+"是"),
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(fiancee, 10)+"&s=640").Add("cache", 0),
message.Text(
"\n",
"[", ctx.CardOrNickName(fiancee), "]",
"(", fiancee, ")哒",
),
)
})
engine.OnFullMatch("群老婆列表", zero.OnlyGroup, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
updatetime, err := 民政局.checkupdate(gid)
switch {
case err != nil:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
case time.Now().Format("2006/01/02") != updatetime:
if err := 民政局.重置(strconv.FormatInt(gid, 10)); err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
ctx.SendChain(message.Text("今天还没有人结婚哦"))
return
}
list, number, err := 民政局.花名册(gid)
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
if number <= 0 {
ctx.SendChain(message.Text("今天还没有人结婚哦"))
return
}
/***********设置图片的大小和底色***********/
fontSize := 50.0
if number < 10 {
number = 10
}
canvas := gg.NewContext(1500, int(250+fontSize*float64(number)))
canvas.SetRGB(1, 1, 1) // 白色
canvas.Clear()
/***********下载字体,可以注销掉***********/
_, err = file.GetLazyData(text.BoldFontFile, true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
}
/***********设置字体颜色为黑色***********/
canvas.SetRGB(0, 0, 0)
/***********设置字体大小,并获取字体高度用来定位***********/
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize*2); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
sl, h := canvas.MeasureString("群老婆列表")
/***********绘制标题***********/
canvas.DrawString("群老婆列表", (1500-sl)/2, 160-h) // 放置在中间位置
canvas.DrawString("————————————————————", 0, 250-h)
/***********设置字体大小,并获取字体高度用来定位***********/
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
_, h = canvas.MeasureString("焯")
for i, info := range list {
canvas.DrawString(slicename(info[0], canvas), 0, float64(260+50*i)-h)
canvas.DrawString("("+info[1]+")", 350, float64(260+50*i)-h)
canvas.DrawString("←→", 700, float64(260+50*i)-h)
canvas.DrawString(slicename(info[2], canvas), 800, float64(260+50*i)-h)
canvas.DrawString("("+info[3]+")", 1150, float64(260+50*i)-h)
}
data, cl := writer.ToBytes(canvas.Image())
ctx.SendChain(message.ImageBytes(data))
cl()
})
engine.OnFullMatchGroup([]string{"闹离婚", "办离婚"}, zero.OnlyGroup, getdb, checkfiancee).SetBlock(true).Limit(cdcheck, iscding2).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
info, uidstatus, err := 民政局.查户口(gid, uid)
switch uidstatus {
case 2:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
case 1:
if rand.Intn(10) != 1 { // 十分之一的概率成功
ctx.SendChain(message.Text(sendtext[3][rand.Intn(len(sendtext[3]))]))
return
}
err := 民政局.离婚休妻(gid, info.Target)
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
ctx.SendChain(message.Text(sendtext[4][0]))
case 0:
if rand.Intn(10) != 0 { // 十分之一的概率成功
ctx.SendChain(message.Text(sendtext[3][rand.Intn(len(sendtext[3]))]))
return
}
err := 民政局.离婚休夫(gid, info.User)
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return
}
ctx.SendChain(message.Text(sendtext[4][1]))
}
})
engine.OnRegex(`^重置(所有|本群|/d+)?花名册$`, zero.SuperUserPermission, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
cmd := "ALL"
switch ctx.State["regex_matched"].([]string)[1] {
case "":
if ctx.Event.GroupID == 0 {
ctx.SendChain(message.Text("该功能只能在群组使用或者指定群组"))
return
}
cmd = strconv.FormatInt(ctx.Event.GroupID, 10)
case "所有":
break
case "本群":
if ctx.Event.GroupID == 0 {
ctx.SendChain(message.Text("该功能只能在群组使用或者指定群组"))
return
}
cmd = strconv.FormatInt(ctx.Event.GroupID, 10)
default:
cmd = ctx.State["regex_matched"].([]string)[1]
}
err := 民政局.重置(cmd)
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
return
}
ctx.SendChain(message.Text("重置成功"))
})
}
// 以群号和昵称为限制
func cdcheck(ctx *zero.Ctx) *rate.Limiter {
limitID := strconv.FormatInt(ctx.Event.GroupID, 10) + strconv.FormatInt(ctx.Event.UserID, 10)
return skillCD.Load(limitID)
}
func iscding(ctx *zero.Ctx) {
ctx.SendChain(message.Text("你的技能现在正在CD中"))
}
// 注入判断 是否为单身
func checkdog(ctx *zero.Ctx) bool {
// 得先判断用户是否存在才行在,再重置
fiancee, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
if err != nil {
ctx.SendChain(message.Text("额你的target好像不存在"))
return false
}
// 判断是否需要重置
gid := ctx.Event.GroupID
updatetime, err := 民政局.checkupdate(gid)
switch {
case err != nil:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return false
case time.Now().Format("2006/01/02") != updatetime:
if err := 民政局.重置(strconv.FormatInt(gid, 10)); err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return false
}
return true // 重置后也全是单身
}
uid := ctx.Event.UserID
// 获取用户信息
uidtarget, uidstatus, err1 := 民政局.查户口(gid, uid)
fianceeinfo, fianceestatus, err2 := 民政局.查户口(gid, fiancee)
switch {
case uidstatus == 2 || fianceestatus == 2:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err1, "\n", err2))
return false
case uidstatus == 3 && fianceestatus == 3: // 必须是两个单身
return true
case uidtarget.Target == fiancee: // 如果本就是一块
ctx.SendChain(message.Text("笨蛋~你们明明已经在一起了啊w"))
return false
case uidstatus != 3 && uidtarget.Target == 0: // 如果是单身贵族
ctx.SendChain(message.Text("今天的你是单身贵族噢"))
return false
case uidstatus == 1: // 如果如为攻
ctx.SendChain(message.Text("笨蛋~你家里还有个吃白饭的w"))
return false
case uidstatus == 0: // 如果为受
ctx.SendChain(message.Text("该是0就是0当0有什么不好"))
return false
case fianceestatus != 3 && fianceeinfo.Target == 0:
ctx.SendChain(message.Text("今天的ta是单身贵族噢"))
return false
case fianceestatus == 1: // 如果如为攻
ctx.SendChain(message.Text("他有别的女人了,你该放下了"))
return false
case fianceestatus == 0: // 如果为受
ctx.SendChain(message.Text("这是一个纯爱的世界拒绝NTR"))
return false
}
return true
}
// 注入判断 是否满足小三要求
func checkcp(ctx *zero.Ctx) bool {
gid := ctx.Event.GroupID
updatetime, err := 民政局.checkupdate(gid)
switch {
case err != nil:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return false
case time.Now().Format("2006/01/02") != updatetime:
if err := 民政局.重置(strconv.FormatInt(gid, 10)); err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
} else {
ctx.SendChain(message.Text("ta现在还是单身哦快向ta表白吧"))
}
return false // 重置后全是单身
}
// 检查target
fid := ctx.State["regex_matched"].([]string)
fiancee, err := strconv.ParseInt(fid[2]+fid[3], 10, 64)
if err != nil {
ctx.SendChain(message.Text("额,你的对象好像不存在?"))
return false
}
// 检查用户是否登记过
uid := ctx.Event.UserID
userinfo, uidstatus, err := 民政局.查户口(gid, uid)
switch {
case uidstatus == 2:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return false
case userinfo.Target == fiancee: // 如果本就是一块
ctx.SendChain(message.Text("笨蛋~你们明明已经在一起了啊w"))
return false
case uidstatus != 3 && userinfo.Target == 0: // 如果是单身贵族
ctx.SendChain(message.Text("今天的你是单身贵族哦"))
return false
case fiancee == uid: // 自我攻略
return true
case uidstatus == 1: // 如果如为攻
ctx.SendChain(message.Text("打灭,不给纳小妾!"))
return false
case uidstatus == 0: // 如果为受
ctx.SendChain(message.Text("该是0就是0当0有什么不好"))
return false
}
fianceeinfo, fianceestatus, err := 民政局.查户口(gid, fiancee)
switch {
case fianceestatus == 2:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return false
case fianceestatus == 3:
ctx.SendChain(message.Text("ta现在还是单身哦快向ta表白吧"))
return false
case fianceeinfo.Target == 0:
ctx.SendChain(message.Text("今天的ta是单身贵族哦"))
return false
}
return true
}
func checkfiancee(ctx *zero.Ctx) bool {
gid := ctx.Event.GroupID
updatetime, err := 民政局.checkupdate(gid)
switch {
case err != nil:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return false
case time.Now().Format("2006/01/02") != updatetime:
if err := 民政局.重置(strconv.FormatInt(gid, 10)); err != nil {
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return false
}
ctx.SendChain(message.Text("今天你还没有结婚哦"))
return false
}
// 获取用户信息
uid := ctx.Event.UserID
_, uidstatus, err := 民政局.查户口(gid, uid)
switch uidstatus {
case 2:
ctx.SendChain(message.Text("数据库发生问题力请联系bot管理员\n[error]", err))
return false
case 3: // 如果是单身
ctx.SendChain(message.Text("今天你还没有结婚哦"))
return false
}
return true
}
func iscding2(ctx *zero.Ctx) {
ctx.SendChain(message.Text("打灭,禁止离婚 (你的技能正在CD中)"))
}

View File

@@ -8,7 +8,7 @@ import (
// load 加载rate数据
func load(area *rate, jsonfile string) error {
data, err := file.GetLazyData(jsonfile, true, true)
data, err := file.GetLazyData(jsonfile, true)
if err != nil {
return err
}

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"math/rand"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
wr "github.com/mroth/weightedrand"
@@ -14,7 +15,7 @@ import (
)
func init() {
en := control.Register("reborn", &control.Options{
en := control.Register("reborn", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "投胎\n- reborn",
PublicDataFolder: "Reborn",

View File

@@ -9,7 +9,8 @@ import (
"strings"
"time"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -91,7 +92,7 @@ var (
)
func init() {
control.Register("runcode", &control.Options{
control.Register("runcode", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "在线代码运行: \n" +
">runcode [language] [code block]\n" +

View File

@@ -3,6 +3,9 @@ package saucenao
import (
"fmt"
"net/http"
"os"
"reflect"
"strconv"
"github.com/sirupsen/logrus"
@@ -11,22 +14,42 @@ import (
"github.com/FloatTech/AnimeAPI/ascii2d"
"github.com/FloatTech/AnimeAPI/pixiv"
"github.com/FloatTech/AnimeAPI/saucenao"
"github.com/FloatTech/AnimeAPI/yandex"
"github.com/jozsefsallai/gophersauce"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img/pool"
)
var (
saucenaocli *gophersauce.Client
)
func init() { // 插件主体
engine := control.Register("saucenao", &control.Options{
engine := control.Register("saucenao", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "搜图\n" +
"- 以图搜图 | 搜索图片 | 以图识图[图片]\n" +
"- 搜图[P站图片ID]",
PrivateDataFolder: "saucenao",
})
apikeyfile := engine.DataFolder() + "apikey.txt"
if file.IsExist(apikeyfile) {
key, err := os.ReadFile(apikeyfile)
if err != nil {
panic(err)
}
saucenaocli, err = gophersauce.NewClient(&gophersauce.Settings{
MaxResults: 1,
APIKey: binary.BytesToString(key),
})
if err != nil {
panic(err)
}
}
// 根据 PID 搜图
engine.OnRegex(`^搜图(\d+)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
@@ -65,15 +88,22 @@ func init() { // 插件主体
imgs = append(imgs, message.Image("file:///"+f))
}
txt := message.Text(
"标题", illust.Title, "\n",
"插画ID", illust.Pid, "\n",
"画师", illust.UserName, "\n",
"画师ID", illust.UserId, "\n",
"直链", "https://pixivel.moe/detail?id=", illust.Pid,
"标题: ", illust.Title, "\n",
"插画ID: ", illust.Pid, "\n",
"画师: ", illust.UserName, "\n",
"画师ID: ", illust.UserId, "\n",
"直链: ", "https://pixivel.moe/detail?id=", illust.Pid,
)
if imgs != nil {
// 发送搜索结果
ctx.Send(append(imgs, message.Text("\n"), txt))
if zero.OnlyGroup(ctx) {
ctx.SendGroupForwardMessage(ctx.Event.GroupID, message.Message{
ctxext.FakeSenderForwardNode(ctx, txt),
ctxext.FakeSenderForwardNode(ctx, imgs...),
})
} else {
// 发送搜索结果
ctx.Send(append(imgs, message.Text("\n"), txt))
}
} else {
// 图片下载失败,仅发送文字结果
ctx.SendChain(txt)
@@ -86,43 +116,49 @@ func init() { // 插件主体
engine.OnKeywordGroup([]string{"以图搜图", "搜索图片", "以图识图"}, zero.OnlyGroup, zero.MustProvidePicture).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 开始搜索图片
ctx.SendChain(message.Text("少女祈祷中......"))
ctx.SendChain(message.Text("少女祈祷中..."))
for _, pic := range ctx.State["image_url"].([]string) {
if result, err := saucenao.SauceNAO(pic); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
if saucenaocli != nil {
resp, err := saucenaocli.FromURL(pic)
if err == nil && resp.Count() > 0 {
result := resp.First()
s, err := strconv.ParseFloat(result.Header.Similarity, 64)
if err == nil {
rr := reflect.ValueOf(&result.Data).Elem()
b := binary.NewWriterF(func(w *binary.Writer) {
r := rr.Type()
for i := 0; i < r.NumField(); i++ {
if !rr.Field(i).IsZero() {
w.WriteString("\n")
w.WriteString(r.Field(i).Name)
w.WriteString(": ")
w.WriteString(fmt.Sprint(rr.Field(i).Interface()))
}
}
})
resp, err := http.Head(result.Header.Thumbnail)
msg := make(message.Message, 0, 3)
if s > 80.0 {
msg = append(msg, message.Text("我有把握是这个!"))
} else {
msg = append(msg, message.Text("也许是这个?"))
}
if err == nil && resp.StatusCode == http.StatusOK {
msg = append(msg, message.Image(result.Header.Thumbnail))
} else {
msg = append(msg, message.Image(pic))
}
msg = append(msg, message.Text("\n图源: ", result.Header.IndexName, binary.BytesToString(b)))
ctx.Send(msg)
if s > 80.0 {
continue
}
}
}
} else {
// 返回SauceNAO的结果
ctx.SendChain(
message.Text("我有把握是这个!"),
message.Image(result[0].Thumbnail),
message.Text(
"\n",
"相似度:", result[0].Similarity, "\n",
"标题:", result[0].Title, "\n",
"插画ID", result[0].PixivID, "\n",
"画师:", result[0].MemberName, "\n",
"画师ID", result[0].MemberID, "\n",
"直链:", "https://pixivel.moe/detail?id=", result[0].PixivID,
),
)
continue
ctx.SendChain(message.Text("请私聊发送 设置 saucenao api key [apikey] 以启用 saucenao 搜图, key 请前往 https://saucenao.com/user.php?page=search-api 获取"))
}
if result, err := yandex.Yandex(pic); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
} else {
ctx.SendChain(
message.Text("也许是这个?"),
message.Text(
"\n",
"标题:", result.Title, "\n",
"插画ID", result.Pid, "\n",
"画师:", result.UserName, "\n",
"画师ID", result.UserId, "\n",
"直链:", "https://pixivel.moe/detail?id=", result.Pid,
),
)
}
// 不论结果如何都执行 ascii2d 搜索
// ascii2d 搜索
if result, err := ascii2d.Ascii2d(pic); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
continue
@@ -132,7 +168,7 @@ func init() { // 插件主体
msg = append(msg, ctxext.FakeSenderForwardNode(ctx,
message.Image(result[i].Thumb),
message.Text(fmt.Sprintf(
"标题%s\n图源%s\n画师%s\n画师链接%s\n图片链接%s",
"标题: %s\n图源: %s\n画师: %s\n画师链接: %s\n图片链接: %s",
result[i].Name,
result[i].Type,
result[i].AuthNm,
@@ -150,4 +186,22 @@ func init() { // 插件主体
}
}
})
engine.OnRegex(`^设置\s?saucenao\s?api\s?key\s?([0-9a-f]{40})$`, zero.SuperUserPermission, zero.OnlyPrivate).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
var err error
saucenaocli, err = gophersauce.NewClient(&gophersauce.Settings{
MaxResults: 1,
APIKey: ctx.State["regex_matched"].([]string)[1],
})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
err = os.WriteFile(apikeyfile, binary.StringToBytes(saucenaocli.APIKey), 0644)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("成功!"))
})
}

View File

@@ -21,6 +21,7 @@ import (
"github.com/FloatTech/AnimeAPI/nsfw"
"github.com/FloatTech/AnimeAPI/scale"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -31,7 +32,7 @@ import (
)
func init() {
engine := control.Register("scale", &control.Options{
engine := control.Register("scale", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "叔叔的AI二次元图片放大\n- 放大图片[图片]",
PrivateDataFolder: "scale",

View File

@@ -15,7 +15,10 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/text"
@@ -24,7 +27,7 @@ import (
)
const (
backgroundURL = "https://iw233.cn/api.php?sort=pc&type=json"
backgroundURL = "https://mirlkoi.ifast3.vipnps.vip/api.php?sort=pc&type=json"
referer = "https://iw233.cn/main.html"
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
signinMax = 1
@@ -35,7 +38,7 @@ const (
var levelArray = [...]int{0, 1, 2, 5, 10, 20, 35, 55, 75, 100, 120}
func init() {
engine := control.Register("score", &control.Options{
engine := control.Register("score", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "签到得分\n- 签到\n- 获得签到背景[@xxx] | 获得签到背景\n- 查看分数排名",
PrivateDataFolder: "score",
@@ -49,18 +52,17 @@ func init() {
}
sdb = initialize(engine.DataFolder() + "score.db")
}()
engine.OnFullMatch("签到", zero.OnlyGroup).SetBlock(true).
engine.OnFullMatch("签到", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID
now := time.Now()
today := now.Format("20060102")
si := sdb.GetSignInByUID(uid)
siUpdateTimeStr := si.UpdatedAt.Format("20060102")
if siUpdateTimeStr != today {
_ = sdb.InsertOrUpdateSignInCountByUID(uid, 0)
}
drawedFile := cachePath + strconv.FormatInt(uid, 10) + today + "signin.png"
picFile := cachePath + strconv.FormatInt(uid, 10) + today + ".png"
if si.Count >= signinMax && siUpdateTimeStr == today {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("今天你已经签到过了!"))
if file.IsExist(drawedFile) {
@@ -68,21 +70,21 @@ func init() {
}
return
}
picFile := cachePath + strconv.FormatInt(uid, 10) + today + ".png"
err := initPic(picFile)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
_ = sdb.InsertOrUpdateSignInCountByUID(uid, si.Count+1)
back, err := gg.LoadImage(picFile)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if siUpdateTimeStr != today {
_ = sdb.InsertOrUpdateSignInCountByUID(uid, 0)
}
_ = sdb.InsertOrUpdateSignInCountByUID(uid, si.Count+1)
// 避免图片过大,最大 1280*720
back = img.Limit(back, 1280, 720)
@@ -94,7 +96,7 @@ func init() {
monthWord := now.Format("01/02")
hourWord := getHourWord(now)
_, err = file.GetLazyData(text.BoldFontFile, false, true)
_, err = file.GetLazyData(text.BoldFontFile, true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
@@ -107,7 +109,7 @@ func init() {
canvas.DrawString(hourWord, float64(back.Bounds().Size().X)*0.1, float64(back.Bounds().Size().Y)*1.2)
canvas.DrawString(monthWord, float64(back.Bounds().Size().X)*0.6, float64(back.Bounds().Size().Y)*1.2)
nickName := ctx.CardOrNickName(uid)
_, err = file.GetLazyData(text.FontFile, false, true)
_, err = file.GetLazyData(text.FontFile, true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
@@ -159,7 +161,7 @@ func init() {
}
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
})
engine.OnPrefix("获得签到背景", zero.OnlyGroup).SetBlock(true).
engine.OnPrefix("获得签到背景", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
param := ctx.State["args"].(string)
var uidStr string
@@ -175,7 +177,7 @@ func init() {
}
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + picFile))
})
engine.OnFullMatch("查看分数排名", zero.OnlyGroup).SetBlock(true).
engine.OnFullMatch("查看分数排名", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
today := time.Now().Format("20060102")
drawedFile := cachePath + today + "scoreRank.png"
@@ -192,7 +194,7 @@ func init() {
ctx.SendChain(message.Text("ERROR:目前还没有人签到过"))
return
}
_, err = file.GetLazyData(text.FontFile, false, true)
_, err = file.GetLazyData(text.FontFile, true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
@@ -207,14 +209,17 @@ func init() {
ctx.SendChain(message.Text("ERROR:", err))
return
}
f, err := os.Create(drawedFile)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
bars := make([]chart.Value, len(st))
for i, v := range st {
bars[i] = chart.Value{
Value: float64(v.Score),
Label: ctx.CardOrNickName(v.UID),
}
bars[i].Value = float64(v.Score)
bars[i].Label = ctx.CardOrNickName(v.UID)
}
graph := chart.BarChart{
err = chart.BarChart{
Font: font,
Title: "饼干排名",
Background: chart.Style{
@@ -225,13 +230,7 @@ func init() {
Height: 500,
BarWidth: 50,
Bars: bars,
}
f, err := os.Create(drawedFile)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
err = graph.Render(chart.PNG, f)
}.Render(chart.PNG, f)
_ = f.Close()
if err != nil {
_ = os.Remove(drawedFile)
@@ -243,16 +242,17 @@ func init() {
}
func getHourWord(t time.Time) string {
h := t.Hour()
switch {
case 6 <= t.Hour() && t.Hour() < 12:
case 6 <= h && h < 12:
return "早上好"
case 12 <= t.Hour() && t.Hour() < 14:
case 12 <= h && h < 14:
return "中午好"
case 14 <= t.Hour() && t.Hour() < 19:
case 14 <= h && h < 19:
return "下午好"
case 19 <= t.Hour() && t.Hour() < 24:
case 19 <= h && h < 24:
return "晚上好"
case 0 <= t.Hour() && t.Hour() < 6:
case 0 <= h && h < 6:
return "凌晨好"
default:
return ""
@@ -271,20 +271,17 @@ func getLevel(count int) int {
}
func initPic(picFile string) error {
if file.IsNotExist(picFile) {
data, err := web.RequestDataWith(web.NewDefaultClient(), backgroundURL, "GET", referer, ua)
if err != nil {
return err
}
picURL := gjson.Get(string(data), "pic").String()
data, err = web.RequestDataWith(web.NewDefaultClient(), picURL, "GET", "", ua)
if err != nil {
return err
}
err = os.WriteFile(picFile, data, 0666)
if err != nil {
return err
}
if file.IsExist(picFile) {
return nil
}
return nil
data, err := web.RequestDataWith(web.NewDefaultClient(), backgroundURL, "GET", referer, ua)
if err != nil {
return err
}
picURL := gjson.Get(binary.BytesToString(data), "pic.0").Str
data, err = web.RequestDataWith(web.NewDefaultClient(), picURL, "GET", "", ua)
if err != nil {
return err
}
return os.WriteFile(picFile, data, 0644)
}

View File

@@ -10,7 +10,8 @@ import (
"github.com/FloatTech/AnimeAPI/pixiv"
sql "github.com/FloatTech/sqlite"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
fileutil "github.com/FloatTech/zbputils/file"
imagepool "github.com/FloatTech/zbputils/img/pool"
@@ -49,7 +50,7 @@ var pool = &imgpool{
}
func init() { // 插件主体
engine := control.Register("setutime", &control.Options{
engine := control.Register("setutime", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "涩图\n" +
"- 来份[涩图/二次元/风景/车万]\n" +
@@ -62,8 +63,8 @@ func init() { // 插件主体
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
// 如果数据库不存在则下载
pool.db.DBPath = engine.DataFolder() + "SetuTime.db"
_, _ = fileutil.GetLazyData(pool.db.DBPath, false, false)
err := pool.db.Open()
_, _ = engine.GetLazyData("SetuTime.db", false)
err := pool.db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
@@ -77,7 +78,7 @@ func init() { // 插件主体
return true
})
engine.OnRegex(`^来份(.+)$`, getdb, ctxext.FirstValueInList(pool)).SetBlock(true).Limit(ctxext.LimitByUser).
engine.OnRegex(`^来份(.+)$`, getdb, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, pool)).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
var imgtype = ctx.State["regex_matched"].([]string)[1]
// 补充池子
@@ -111,7 +112,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("成功向分类", imgtype, "添加图片", id))
})
engine.OnRegex(`^删除\s*([^0-9\s]+)\s*(\d+)$`, getdb, ctxext.FirstValueInList(pool), zero.SuperUserPermission).SetBlock(true).
engine.OnRegex(`^删除\s*([^0-9\s]+)\s*(\d+)$`, getdb, ctxext.ValueInList(func(ctx *zero.Ctx) string { return ctx.State["regex_matched"].([]string)[1] }, pool), zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
var (
imgtype = ctx.State["regex_matched"].([]string)[1]

View File

@@ -1,21 +0,0 @@
package shadiao
import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
)
func init() {
engine.OnFullMatch("哄我").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
data, err := web.RequestDataWith(web.NewDefaultClient(), chpURL, "GET", chpReferer, ua)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(helper.BytesToString(data)))
})
}

View File

@@ -1,21 +0,0 @@
package shadiao
import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
)
func init() {
engine.OnFullMatch("来碗毒鸡汤").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
data, err := web.RequestDataWith(web.NewDefaultClient(), duURL, "GET", duReferer, ua)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(helper.BytesToString(data)))
})
}

View File

@@ -0,0 +1,24 @@
package shadiao
import (
"github.com/FloatTech/zbputils/ctxext"
"github.com/antchfx/htmlquery"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
engine.OnFullMatch("马丁路德骂我").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
doc, err := htmlquery.LoadURL(ergofabulousURL)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
node, err := htmlquery.Query(doc, "//main[@role=\"main\"]/p[@class=\"larger\"]/text()")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(node.Data))
})
}

View File

@@ -1,21 +0,0 @@
package shadiao
import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
)
func init() {
engine.OnFullMatch("发个朋友圈").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
data, err := web.RequestDataWith(web.NewDefaultClient(), pyqURL, "GET", pyqReferer, ua)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(helper.BytesToString(data)))
})
}

View File

@@ -2,28 +2,46 @@
package shadiao
import (
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
chpURL = "https://chp.shadiao.app/chp"
chpURL = "https://api.shadiao.app/chp"
duURL = "https://api.shadiao.app/du"
pyqURL = "https://api.shadiao.app/pyq"
yduanziURL = "http://www.yduanzi.com/duanzi/getduanzi"
chayiURL = "https://api.lovelive.tools/api/SweetNothings/Web/0"
ganhaiURL = "https://api.lovelive.tools/api/SweetNothings/Web/1"
ergofabulousURL = "https://ergofabulous.org/luther/?"
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
chpReferer = "https://chp.shadiao.app/"
duReferer = "https://du.shadiao.app/"
pyqReferer = "https://pyq.shadiao.app/"
sdReferer = "https://api.shadiao.app/"
yduanziReferer = "http://www.yduanzi.com/?utm_source=shadiao.app"
loveliveReferer = "https://lovelive.tools/"
)
var (
engine = control.Register("shadiao", &control.Options{
engine = control.Register("shadiao", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "沙雕app\n" +
"- 哄我\n- 渣我\n- 来碗绿茶\n- 发个朋友圈\n- 来碗毒鸡汤\n- 讲个段子",
"- 哄我\n- 渣我\n- 来碗绿茶\n- 发个朋友圈\n- 来碗毒鸡汤\n- 讲个段子\n- 马丁路德骂我\n",
})
sdMap = map[string]string{"哄我": chpURL, "来碗毒鸡汤": duURL, "发个朋友圈": pyqURL}
)
func init() {
engine.OnFullMatchGroup([]string{"哄我", "来碗毒鸡汤", "发个朋友圈"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
requestURL := sdMap[ctx.State["matched"].(string)]
data, err := web.RequestDataWith(web.NewDefaultClient(), requestURL, "GET", sdReferer, ua)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(gjson.GetBytes(data, "data.text").String()))
})
}

View File

@@ -7,13 +7,14 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/text"
)
func init() {
engine := control.Register("shindan", &control.Options{
engine := control.Register("shindan", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "shindan\n" +
"- 今天是什么少女[@xxx]\n" +

View File

@@ -9,11 +9,12 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
)
func init() {
engine := control.Register("sleepmanage", &control.Options{
engine := control.Register("sleepmanage", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "sleepmanage\n- 早安\n- 晚安",
PrivateDataFolder: "sleep",

205
plugin/tarot/tarot.go Normal file
View File

@@ -0,0 +1,205 @@
// Package tarot 塔罗牌
package tarot
import (
"encoding/json"
"fmt"
"math/rand"
"strconv"
"strings"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/text"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const bed = "https://gitcode.net/shudorcl/zbp-tarot/-/raw/master/"
type cardInfo struct {
Description string `json:"description"`
ReverseDescription string `json:"reverseDescription"`
ImgURL string `json:"imgUrl"`
}
type card struct {
Name string `json:"name"`
cardInfo `json:"info"`
}
type formation struct {
CardsNum int `json:"cards_num"`
IsCut bool `json:"is_cut"`
Represent [][]string `json:"represent"`
}
type cardSet = map[string]card
var cardMap = make(cardSet, 30)
var infoMap = make(map[string]cardInfo, 30)
var formationMap = make(map[string]formation, 10)
// var cardName = make([]string, 30)
// var formationName = make([]string, 10)
func init() {
engine := control.Register("tarot", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "塔罗牌\n" +
"- 抽塔罗牌\n" +
"- 抽n张塔罗牌\n" +
"- 解塔罗牌[牌名]\n" +
"- 塔罗牌阵[圣三角|时间之流|四要素|五牌阵|吉普赛十字|马蹄|六芒星]",
PublicDataFolder: "Tarot",
}).ApplySingle(ctxext.DefaultSingle)
getTarot := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
data, err := engine.GetLazyData("tarots.json", true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = json.Unmarshal(data, &cardMap)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
for _, card := range cardMap {
infoMapKey := strings.Split(card.Name, "(")[0]
infoMap[infoMapKey] = card.cardInfo
// 可以拿来显示大阿尔卡纳列表
// cardName = append(cardName, infoMapKey)
}
logrus.Infof("[tarot]读取%d张大阿尔卡纳塔罗牌", len(cardMap))
formation, err := engine.GetLazyData("formation.json", true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = json.Unmarshal(formation, &formationMap)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
logrus.Infof("[tarot]读取%d组塔罗牌阵", len(formationMap))
return true
})
engine.OnRegex(`^抽(\d{1,2}张)?塔罗牌$`, getTarot).SetBlock(true).Limit(ctxext.LimitByGroup).Handle(func(ctx *zero.Ctx) {
match := ctx.State["regex_matched"].([]string)[1]
n := 1
reasons := [...]string{"您抽到的是~\n", "锵锵锵,塔罗牌的预言是~\n", "诶,让我看看您抽到了~\n"}
position := [...]string{"正位", "逆位"}
reverse := [...]string{"", "Reverse"}
if match != "" {
var err error
n, err = strconv.Atoi(match[:len(match)-3])
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if n <= 0 {
ctx.SendChain(message.Text("ERROR:张数必须为正"))
return
}
if n > 1 && !zero.OnlyGroup(ctx) {
ctx.SendChain(message.Text("ERROR:抽取多张仅支持群聊"))
return
}
if n > 20 {
ctx.SendChain(message.Text("ERROR:抽取张数过多"))
return
}
}
if n == 1 {
i := rand.Intn(22)
p := rand.Intn(2)
card := cardMap[(strconv.Itoa(i))]
name := card.Name
if id := ctx.SendChain(
message.Text(reasons[rand.Intn(len(reasons))], position[p], " 的 ", name, "\n"),
message.Image(fmt.Sprintf(bed+"MajorArcana%s/%d.png", reverse[p], i))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR:可能被风控了"))
}
return
}
msg := make([]message.MessageSegment, n)
randomIntMap := make(map[int]int, 30)
for i := range msg {
j := rand.Intn(22)
_, ok := randomIntMap[j]
for ok {
j = rand.Intn(22)
_, ok = randomIntMap[j]
}
randomIntMap[j] = 0
p := rand.Intn(2)
card := cardMap[(strconv.Itoa(j))]
name := card.Name
tarotMsg := []message.MessageSegment{
message.Text(reasons[rand.Intn(len(reasons))], position[p], " 的 ", name, "\n"),
message.Image(fmt.Sprintf(bed+"MajorArcana%s/%d.png", reverse[p], j))}
msg[i] = ctxext.FakeSenderForwardNode(ctx, tarotMsg...)
}
ctx.SendGroupForwardMessage(ctx.Event.GroupID, msg)
})
engine.OnRegex(`^解塔罗牌\s?(.*)`, getTarot).SetBlock(true).Limit(ctxext.LimitByGroup).Handle(func(ctx *zero.Ctx) {
match := ctx.State["regex_matched"].([]string)[1]
info, ok := infoMap[match]
if ok {
ctx.SendChain(
message.Image(bed+info.ImgURL),
message.Text("\n", match, "的含义是~"),
message.Text("\n正位:", info.Description),
message.Text("\n逆位:", info.ReverseDescription))
} else {
ctx.SendChain(message.Text("没有找到", match, "噢~"))
}
})
engine.OnRegex(`^塔罗牌阵\s?(.*)`, getTarot).SetBlock(true).Limit(ctxext.LimitByGroup).Handle(func(ctx *zero.Ctx) {
match := ctx.State["regex_matched"].([]string)[1]
info, ok := formationMap[match]
position := [...]string{"正位", "逆位"}
reverse := [...]string{"", "Reverse"}
if ok {
var build strings.Builder
build.WriteString(ctx.CardOrNickName(ctx.Event.UserID))
build.WriteString("\n")
msg := make([]message.MessageSegment, info.CardsNum)
randomIntMap := make(map[int]int, 30)
for i := range msg {
j := rand.Intn(22)
_, ok := randomIntMap[j]
for ok {
j = rand.Intn(22)
_, ok = randomIntMap[j]
}
randomIntMap[j] = 0
p := rand.Intn(2)
card := cardMap[(strconv.Itoa(j))]
name := card.Name
tarotMsg := []message.MessageSegment{message.Image(fmt.Sprintf(bed+"MajorArcana%s/%d.png", reverse[p], j))}
build.WriteString(info.Represent[0][i])
build.WriteString(": ")
build.WriteString(position[p])
build.WriteString(" 的 ")
build.WriteString(name)
build.WriteString("\n")
msg[i] = ctxext.FakeSenderForwardNode(ctx, tarotMsg...)
}
txt := build.String()
formation, err := text.RenderToBase64(txt, text.FontFile, 400, 20)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
// TODO 视gocq变化将牌阵信息加入转发列表中
ctx.SendChain(message.Image("base64://" + binary.BytesToString(formation)))
ctx.SendGroupForwardMessage(ctx.Event.GroupID, msg)
} else {
ctx.SendChain(message.Text("没有找到", match, "噢~"))
}
})
}

View File

@@ -5,8 +5,8 @@ import (
"encoding/json"
"math/rand"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/file"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -15,13 +15,13 @@ import (
type kimo = map[string]*[]string
func init() {
engine := control.Register("thesaurus", &control.Options{
engine := control.Register("thesaurus", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "thesaurus\n- 词典匹配回复",
PublicDataFolder: "Chat",
})
go func() {
data, err := file.GetLazyData(engine.DataFolder()+"kimoi.json", true, false)
data, err := engine.GetLazyData("kimoi.json", false)
if err != nil {
panic(err)
}

View File

@@ -2,10 +2,12 @@
package tiangou
import (
"time"
sql "github.com/FloatTech/sqlite"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -19,7 +21,7 @@ type tiangou struct {
var db = &sql.Sqlite{}
func init() {
en := control.Register("tiangou", &control.Options{
en := control.Register("tiangou", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "舔狗日记\n" +
"- 舔狗日记",
@@ -28,9 +30,13 @@ func init() {
en.OnFullMatch("舔狗日记", ctxext.DoOnceOnSuccess(
func(ctx *zero.Ctx) bool {
dbpath := en.DataFolder()
db.DBPath = dbpath + "tiangou.db"
_, err := file.GetLazyData(db.DBPath, false, true)
db.DBPath = en.DataFolder() + "tiangou.db"
_, err := en.GetLazyData("tiangou.db", true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false

View File

@@ -2,7 +2,8 @@
package tracemoe
import (
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
trmoe "github.com/fumiama/gotracemoe"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -13,7 +14,7 @@ var (
)
func init() { // 插件主体
engine := control.Register("tracemoe", &control.Options{
engine := control.Register("tracemoe", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "tracemoe\n- 搜番 | 搜索番剧[图片]",
})

View File

@@ -3,14 +3,15 @@ package translation
import (
"github.com/FloatTech/AnimeAPI/tl"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
control.Register("translation", &control.Options{
control.Register("translation", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "翻译\n" +
">TL 你好",

View File

@@ -18,7 +18,8 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img/text"
@@ -30,7 +31,7 @@ import (
var reg = regexp.MustCompile(".*/(.*)")
func init() {
engine := control.Register("vtbquotation", &control.Options{
engine := control.Register("vtbquotation", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "vtbkeyboard.moe\n- vtb语录\n- 随机vtb\n- 更新vtb\n",
PublicDataFolder: "VtbQuotation",
@@ -43,7 +44,7 @@ func init() {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
_, err = file.GetLazyData(dbfile, false, false)
_, err = engine.GetLazyData("vtb.db", false)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false

View File

@@ -2,6 +2,7 @@
package wangyiyun
import (
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
@@ -17,7 +18,7 @@ const (
)
func init() {
control.Register("wangyiyun", &control.Options{
control.Register("wangyiyun", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "wangyiyun \n- 来份网易云热评",
}).OnFullMatch("来份网易云热评").SetBlock(true).Limit(ctxext.LimitByUser).

View File

@@ -11,6 +11,7 @@ import (
"sync"
"time"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -30,7 +31,7 @@ var (
)
func init() {
engine := control.Register("wordcount", &control.Options{
engine := control.Register("wordcount", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "聊天热词\n" +
"- 热词 [群号] [消息数目]|热词 123456 1000",
@@ -40,7 +41,7 @@ func init() {
_ = os.RemoveAll(cachePath)
_ = os.MkdirAll(cachePath, 0755)
engine.OnRegex(`^热词\s?(\d*)\s?(\d*)$`, zero.OnlyGroup, ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
_, err := file.GetLazyData(engine.DataFolder()+"stopwords.txt", false, false)
_, err := engine.GetLazyData("stopwords.txt", false)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
@@ -56,7 +57,7 @@ func init() {
return true
})).Limit(ctxext.LimitByUser).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
_, err := file.GetLazyData(text.FontFile, false, true)
_, err := file.GetLazyData(text.FontFile, true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return

View File

@@ -13,12 +13,11 @@ import (
"time"
"github.com/FloatTech/AnimeAPI/tl"
"github.com/sirupsen/logrus"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img/writer"
"github.com/fogleman/gg"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -61,7 +60,7 @@ type dictionary map[int]struct {
var words = make(dictionary)
func init() {
en := control.Register("wordle", &control.Options{
en := control.Register("wordle", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "猜单词\n" +
"- 个人猜单词\n" +
@@ -87,8 +86,7 @@ func init() {
wg.Add(2)
go func(i int) {
defer wg.Done()
dc, err := file.GetLazyData(fmt.Sprintf("%scet-4_%d.txt", en.DataFolder(), i), true, true)
logrus.Debugln("[wordle] get", fmt.Sprintf("%scet-4_%d.txt", en.DataFolder(), i))
dc, err := en.GetLazyData(fmt.Sprintf("cet-4_%d.txt", i), true)
if err != nil {
atomic.AddUint32(&errcnt, 1)
return
@@ -103,8 +101,7 @@ func init() {
}(i)
go func(i int) {
defer wg.Done()
dd, err := file.GetLazyData(fmt.Sprintf("%sdict_%d.txt", en.DataFolder(), i), true, true)
logrus.Debugln("[wordle] get", fmt.Sprintf("%sdict_%d.txt", en.DataFolder(), i))
dd, err := en.GetLazyData(fmt.Sprintf("dict_%d.txt", i), true)
if err != nil {
atomic.AddUint32(&errcnt, 1)
return

View File

@@ -5,14 +5,15 @@ import (
"fmt"
"strconv"
control "github.com/FloatTech/zbputils/control"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
en := control.Register("wtf", &control.Options{
en := control.Register("wtf", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "鬼东西\n- 鬼东西列表\n- 查询鬼东西[序号][@xxx]",
})

View File

@@ -4,22 +4,22 @@ package ymgal
import (
"strings"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
engine := control.Register("ymgal", &control.Options{
engine := control.Register("ymgal", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "月幕galgame\n- 随机galCG\n- 随机gal表情包\n- galCG[xxx]\n- gal表情包[xxx]\n- 更新gal\n",
PublicDataFolder: "Ymgal",
})
dbfile := engine.DataFolder() + "ymgal.db"
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
_, err := file.GetLazyData(dbfile, false, false)
dbfile := engine.DataFolder() + "ymgal.db"
_, err := engine.GetLazyData("ymgal.db", false)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false

View File

@@ -1,65 +0,0 @@
// Package zaobao 易即今日公众号api的今日早报
package zaobao
import (
"sync"
"time"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/binary"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/web"
)
const (
api = "http://api.soyiji.com/news_jpg"
referer = "safe.soyiji.com"
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66"
)
var (
picdata []byte
mu sync.Mutex
pictime time.Time
)
func init() { // 插件主体
engine := control.Register("zaobao", &control.Options{
DisableOnDefault: true,
Help: "易即今日公众号api的今日早报\n" +
"api早上8点更新推荐定时在8点30后\n" +
"配合插件job中的记录在\"cron\"触发的指令使用\n" +
"- 记录在\"0 9 * * *\"触发的指令\n" +
" - 今日早报",
})
engine.OnFullMatch("今日早报", zero.OnlyGroup).SetBlock(false).
Handle(func(ctx *zero.Ctx) {
err := getdata()
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.ImageBytes(picdata))
})
}
func getdata() error { // 获取图片链接并且下载
mu.Lock()
defer mu.Unlock()
if picdata != nil && time.Since(pictime) <= time.Hour*20 {
return nil
}
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", "", ua)
if err != nil {
return err
}
picdata, err = web.RequestDataWith(web.NewDefaultClient(), gjson.Get(binary.BytesToString(data), "url").String(), "GET", referer, ua)
if err != nil {
return err
}
pictime = time.Now()
return nil
}