Compare commits

..

328 Commits

Author SHA1 Message Date
源文雨
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
源文雨
9a3b4b3ecb 🔖 1.4.0-beta2 2022-04-29 20:41:57 +08:00
源文雨
cbaeb4d5f2 🐛 无法在job中移除匹配触发器 2022-04-29 20:40:37 +08:00
源文雨
592c306aa0 加速word count 2022-04-28 23:29:48 +08:00
源文雨
136e6bddf4 加速word count 2022-04-28 23:15:27 +08:00
源文雨
0e8bef0541 sync data 2022-04-28 22:26:00 +08:00
fumiama
9d8c52303e update deps 2022-04-28 22:19:53 +08:00
fumiama
e6ae7df546 🔖 1.4.0-beta1 2022-04-28 19:58:22 +08:00
fumiama
5b57a759be update deps 2022-04-28 19:56:37 +08:00
MSCxar#0293
cc96eeae32 🐛README.md查缺补漏 (#208) 2022-04-28 17:38:30 +08:00
himawari
484fef1228 🎨 优化vtb插件代码,更换shadiao的api (#206)
* 🎨 优化vtb插件代码,更换shadiao的api

* 🎨 正则全局变量

Co-authored-by: haibaraguo <haibaraguo@yeahka.com>
2022-04-28 17:37:57 +08:00
Coloured-glaze
ba4ca11c83 🎨增加文字回复 (#205)
* 🎨增加文字回复

* 🎨增加文字回复

* 🎨增加文字回复

* 🎨增加文字回复(fix)

* 🎨small letter=>

* Update ys.go

* Update ys.go

* Update ys.go

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-04-27 14:11:23 +08:00
Mayuri
9372902348 🐛fix : setutime regex (#203) 2022-04-25 09:33:53 +08:00
源文雨
0cc9420570 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-04-22 09:24:29 +08:00
源文雨
18fa48d283 🔖 1.3.3-fix1 2022-04-22 09:24:15 +08:00
源文雨
9034fedbd0 lolicon add custom rand api 2022-04-22 09:23:31 +08:00
源文雨
ec3b6ec5fa 🔥 remove plugin acgimage 2022-04-22 09:13:43 +08:00
Mayuri
8cc2a4174e 🐛 更新签到背景图API (#202) 2022-04-21 21:36:23 +08:00
Yiwen-Chan
8a0014928d 🐛 更新疫情API 2022-04-21 12:59:01 +08:00
github-actions[bot]
228ca7f9c0 🎨 改进代码样式 2022-04-20 04:50:42 +00:00
MoeMagicMango
c0fa7efb27 简单修了下网易点歌 (#200) 2022-04-20 12:49:24 +08:00
himawari
3553683bb1 🐛 兼容linux和windows文件换行不同 (#199) 2022-04-19 23:00:01 +08:00
源文雨
ccb58e0a6c 🎨 edit README 2022-04-19 13:02:13 +08:00
源文雨
93253e2188 🎨 edit README 2022-04-19 12:59:47 +08:00
MSCxar#0293
e34bcc9bbd [水pr]整理README.md (#198)
* 整理 README.md
2022-04-19 12:39:45 +08:00
源文雨
72169e3a4d 🔖 1.3.3 2022-04-18 23:07:49 +08:00
源文雨
41c499840f fix #197: 猜单词出现空指针报警 2022-04-18 22:59:33 +08:00
himawari
f5cef170f0 🚑️ 修复查看其他群聊热词的问题 (#195) 2022-04-18 16:31:09 +08:00
源文雨
d7922a7c9b ️ 优化pool 2022-04-18 16:29:09 +08:00
github-actions[bot]
23fc77e8e1 🎨 改进代码样式 2022-04-17 13:25:27 +00:00
himawari
51f3eda09a 👍 添加聊天热词 (#192)
*  添加聊天热词

*  添加聊天热词

*  添加聊天热词

* 🚨 修lint

* 🚨 修lint
2022-04-17 21:24:07 +08:00
源文雨
6ec08a5227 🐛 reg 时序 2022-04-17 21:22:08 +08:00
源文雨
4855f694cb 🎨 edit README 2022-04-17 00:11:54 +08:00
源文雨
eaef37a831 Update README.md 2022-04-16 19:10:06 +08:00
源文雨
b182ff36bb 🔖 1.3.3-beta6 2022-04-16 00:35:05 +08:00
源文雨
c4e543449c 使用真正lazy的资源下载方式 2022-04-16 00:33:50 +08:00
源文雨
c76d9d4461 🔥 remove debug info in gorm 2022-04-16 00:04:07 +08:00
源文雨
dfd184724b 使用真正lazy的资源下载方式 2022-04-16 00:02:41 +08:00
源文雨
fef254031e ️ banmap 使用 ttl 2022-04-15 19:02:06 +08:00
源文雨
89c4e59bf1 🔖 1.3.3-beta5 2022-04-15 15:29:45 +08:00
源文雨
2e9acd3276 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-04-15 15:28:02 +08:00
源文雨
5cab59c93f 🐛 戳一戳失效 2022-04-15 15:27:47 +08:00
Mayuri
ebfb5878a1 更新用法和README.md (#189)
* update help manual

* Update README.md
2022-04-15 09:25:25 +08:00
源文雨
de6b11aa22 🔖 1.3.3-beta4 2022-04-14 17:18:01 +08:00
源文雨
9e7e7159e8 🔖 1.3.3-beta3 2022-04-14 17:11:00 +08:00
源文雨
00c909271b 🔖 1.3.3-beta3 2022-04-14 17:10:21 +08:00
源文雨
7401a0cbec 🎨 优化代码结构 2022-04-14 17:09:28 +08:00
源文雨
a9327d1774 🐛 reg close 2022-04-10 16:33:34 +08:00
Mayuri
9e99ef1348 新增 {gid} {groupname} (#186)
* modified:   plugin/manager/manager.go

* use message.UnescapeCQCodeText instead
2022-04-10 11:46:50 +08:00
源文雨
5b4b9fdb01 🔖 1.3.3-beta2 2022-04-06 11:17:02 +08:00
源文雨
d2998c4908 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-04-06 11:15:27 +08:00
源文雨
4ab968d563 🎨 优化代码结构 2022-04-06 11:15:24 +08:00
himawari
9b26eea754 增加查看签到排名 (#180)
*  增加查看签到排名

* 🚨 修lint

* 🚨 修lint
2022-04-06 10:59:56 +08:00
源文雨
a6bd717971 🔥 精简 log 输出 2022-04-05 23:18:13 +08:00
Kanri
f2914adb65 Update README.md 2022-04-05 20:52:25 +08:00
Kanri
aa5a426aac 📄 更换 README 图片 2022-04-05 20:50:40 +08:00
Kanri
fef8144187 📄 change title picture 2022-04-05 20:48:32 +08:00
源文雨
d8a429d3b3 🚧 move tag & nsfw to azfun 2022-04-05 15:52:06 +08:00
github-actions[bot]
56e53b75a5 🎨 改进代码样式 2022-04-04 14:55:00 +00:00
himawari
f89b6f5feb ️wordle逻辑优化,bilibilipush、translate添加信息 (#179)
* :sparkles:添加查成分功能

* :rotating_light:修lint

* :rotating_light:减少空格

* :bug:修改网址

* :bug:修改vup数量错误问题

* :bug:图片读取不了,就不读了

* 🐛 固定头像大小,bilibilipush调公有库

* 🎨 修改json转换

*  bilibilipush添加新类型,同时修改命令正则,wordle添加时间提醒,和单词语义,translate充实信息

* ️使用公用的翻译函数

* 🚨 添加return和stop

Co-authored-by: Guohuiyuan <haibaraguo@yeahka.com>
2022-04-04 22:53:37 +08:00
源文雨
ec513e8893 🐛 job 指令触发可能失败 2022-04-04 14:36:25 +08:00
源文雨
35d6792d2e 🐛 job 指令触发可能失败 2022-04-04 13:28:50 +08:00
源文雨
74387aae2d 🔖 1.3.3-beta1 2022-04-03 18:53:06 +08:00
源文雨
959043962d Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-04-03 18:51:25 +08:00
源文雨
4efb71bafb 🍱 运势 增加底图 奇异恩典 2022-04-03 18:51:06 +08:00
TZMSky
6fd0bc0445 删除Onebot-YAYA (#177) 2022-04-02 22:53:10 +08:00
源文雨
176a2eb392 🔥 精简Register 2022-04-02 22:45:21 +08:00
源文雨
1a85deb36e 🎨 优化代码结构 2022-04-02 22:40:31 +08:00
源文雨
5b409ff3de 🐛 pixiv dns 2022-04-02 13:31:54 +08:00
源文雨
a9e13d3a92 🎨 优化代码结构 2022-03-31 19:50:34 +08:00
莫思潋
0698d8e3b1 fix:修复了枝网查重无法使用的问题 (#175)
* 优化在两个命令中使用空格分隔的体验
- fortune的设置底图功能
- b14的加密功能

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

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

* - 删去了遗漏的Trim

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

* 小调整

- 考虑到屌字既难打又有碍观瞻,改为正则匹配`[屌|弔|吊]图`
- 增加了退群提醒的定制

* - 修复退群提醒本身忘记修改了的问题

* fix:修复了枝网查重无法使用的问题

* readme适配上次的欢迎语修改

* 删去调试语句

* Update setu_geter.go

* Update zhiwang.go

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-03-31 19:36:29 +08:00
源文雨
8e4c496b54 🐛 MustProvicePicture goroutine 泄漏 2022-03-30 13:23:52 +08:00
源文雨
27054b9722 🐛 MustProvicePicture goroutine 泄漏 2022-03-30 13:17:37 +08:00
源文雨
bcad2c4998 🎨 优化代码结构 2022-03-29 16:29:29 +08:00
github-actions[bot]
aae2bd4884 🎨 改进代码样式 2022-03-29 05:05:36 +00:00
himawari
006ef6f672 👍 添加查成分功能,修改bilibili插件的正则 (#171)
* :sparkles:添加查成分功能

* :rotating_light:修lint

* :rotating_light:减少空格

* :bug:修改网址

* :bug:修改vup数量错误问题

* :bug:图片读取不了,就不读了

* 🐛 固定头像大小,bilibilipush调公有库

* 🎨 修改json转换

Co-authored-by: Guohuiyuan <haibaraguo@yeahka.com>
2022-03-29 13:03:46 +08:00
源文雨
7be1a61347 🎨 优化代码结构 2022-03-28 23:13:53 +08:00
源文雨
1ef48f6cd6 🎨 优化代码结构 2022-03-28 23:06:04 +08:00
源文雨
a9a061a4bb 🎨 优化代码结构 2022-03-28 23:01:36 +08:00
源文雨
14ed8b7af7 🐛 reg 2022-03-28 17:23:54 +08:00
源文雨
d17b8fa720 📝 edit readme 2022-03-28 17:14:39 +08:00
源文雨
68980a69b5 🐛 增加百人一首 修复Lazy不关闭 2022-03-28 17:11:44 +08:00
源文雨
636f14c450 🐛 md5 只能连接一次 2022-03-27 14:35:48 +08:00
源文雨
b066bc37b3 #150 缩减coser发图数 2022-03-27 14:26:28 +08:00
源文雨
9ac43fecf8 fix #151 2022-03-27 14:22:34 +08:00
源文雨
d6ff14167d add plugin 渲染任意文字到图片 2022-03-27 14:00:21 +08:00
源文雨
5837a765f1 add plugin 渲染任意文字到图片 2022-03-27 13:54:26 +08:00
源文雨
1bfb76a4b3 📝 edit readme 2022-03-27 12:59:08 +08:00
源文雨
2a78a602e2 shindan add 黄油角色 2022-03-27 12:56:57 +08:00
源文雨
884b0e4226 💩👌 make lint happy 2022-03-27 12:48:12 +08:00
源文雨
4e819eb5d9 fix ci 2022-03-27 12:44:02 +08:00
源文雨
e3a50cc014 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-03-27 00:24:56 +08:00
源文雨
25ab8c9234 fix: FutureEvent 2022-03-27 00:24:46 +08:00
github-actions[bot]
901e680fa4 🎨 改进代码样式 2022-03-26 14:03:46 +00:00
源文雨
82768fff59 fix b14 & cd 2022-03-26 22:01:50 +08:00
莫思潋
87e3297904 定制退群提醒+调整煎蛋网无聊图触发 (#166)
* 优化在两个命令中使用空格分隔的体验
- fortune的设置底图功能
- b14的加密功能

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

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

* - 删去了遗漏的Trim

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

* 小调整

- 考虑到屌字既难打又有碍观瞻,改为正则匹配`[屌|弔|吊]图`
- 增加了退群提醒的定制

* - 修复退群提醒本身忘记修改了的问题
2022-03-22 12:31:44 +08:00
Jiang-Red
81a4297eb1 添加更多数据,修改发送排版 (#167) 2022-03-21 18:18:29 +08:00
源文雨
17f5b52931 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-03-20 18:49:31 +08:00
源文雨
2250adf854 fix #161 2022-03-20 18:49:20 +08:00
GenesisAN
5cd46b3926 从url正则中去除用字 (#160)
从url正则中去除用字,以防止url中包含用字前缀导致图片显示失败
2022-03-20 14:43:55 +08:00
源文雨
6e2b10b788 fix lint 2022-03-20 14:40:47 +08:00
源文雨
5e301ccaaf fix lint 2022-03-20 14:33:43 +08:00
源文雨
206a38efab fix #154: 优化代码结构 2022-03-20 14:20:37 +08:00
Coloured-glaze
cdf844be52 🎨原神抽卡 (#156)
* Add files via upload

* 原神抽卡

* 🎨原神抽卡
2022-03-20 10:59:11 +08:00
源文雨
70cc28c191 fix ci 2022-03-19 19:58:16 +08:00
源文雨
35282fba6c update data 2022-03-19 19:52:54 +08:00
源文雨
e43f8e594d Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-03-19 19:51:59 +08:00
源文雨
21988fab76 ⬆️ update to go 1.18 2022-03-19 19:51:45 +08:00
himawari
2f3823abe2 feat:添加舔狗日记和修复睡眠管理的问题 (#152)
* feat:添加舔狗日记和修复睡眠管理的问题

* fix:修lint

* fix:修改铅笔小说网址

* fix:修改铅笔小说网址
2022-03-19 11:29:31 +08:00
源文雨
2c545e7b7f 🎨 优化pool 2022-03-18 16:50:07 +08:00
源文雨
22f2200778 🐛 b14 panic 2022-03-15 22:50:38 +08:00
源文雨
2f63253ec0 🎨 优化代码结构 2022-03-14 12:50:50 +08:00
源文雨
be7e8134f9 🎨 优化代码结构 2022-03-14 12:46:54 +08:00
源文雨
b85408e3e5 pixiv add backend dns result 2022-03-13 22:43:41 +08:00
源文雨
4828451f9e 🔖 v1.3.2 2022-03-13 13:21:52 +08:00
源文雨
b3b50e1353 🐛 搜图 有时无法下载图片 2022-03-13 13:14:01 +08:00
源文雨
95e8bf2f55 📝 edit readme 2022-03-12 20:22:28 +08:00
源文雨
cde7669c0b 优化代码结构 2022-03-12 11:35:20 +08:00
源文雨
ff4a33c51c edit readme 2022-03-12 11:05:19 +08:00
源文雨
06cf6f84aa edit readme 2022-03-12 00:27:27 +08:00
源文雨
556f6f134f edit readme 2022-03-12 00:27:15 +08:00
源文雨
b1ab7ef118 edit readme 2022-03-12 00:25:59 +08:00
源文雨
e5fd108a9c edit readme 2022-03-12 00:25:21 +08:00
源文雨
5a67bf2417 🐛 每天刷新 2022-03-12 00:18:26 +08:00
源文雨
cb020c1bbd 🐛 每天刷新 2022-03-12 00:17:33 +08:00
源文雨
bf75b29e33 🐛 每天刷新 2022-03-12 00:16:04 +08:00
源文雨
d730fd9cab 优化代码结构 2022-03-12 00:05:41 +08:00
Jiang-Red
a862e5be7c 添加 早报插件及设置欢迎语增加更多自定义 (#147)
* 添加 早报插件

* 添加 早报插件

* 添加 早报插件

* 添加 设置欢迎语更多自定义

* 添加 help说明

* 添加 manager设置欢迎语说明

* 怪

* 🎨 改进代码样式

* Update zaobao.go

* Update zaobao.go

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-03-11 23:47:39 +08:00
源文雨
ebca124c86 🐛 修复 run 2022-03-11 23:02:08 +08:00
源文雨
3b7803a81b 优化代码结构 2022-03-11 16:34:26 +08:00
源文雨
b7b9d92148 优化代码结构 2022-03-11 16:18:11 +08:00
Rainy
44575fb19e 增加城市疫情查询 (#146)
* 增加城市疫情查询

* 增加城市疫情查询

* 增加城市疫情查询

* 增加城市疫情查询

* 增加查询城市疫情

* 增加城市查询疫情

* 增加城市疫情查询

* Update epidemic.go

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-03-11 16:10:14 +08:00
源文雨
f181a4b9cd 🎨 可自行编辑json 2022-03-11 11:40:51 +08:00
源文雨
77e5d8b0c2 ⬆️ update deps 2022-03-11 11:36:55 +08:00
源文雨
edd9feb8f8 🔥 drop ioutil 2022-03-11 11:32:13 +08:00
源文雨
81d6a06dbe 🎨 ascii2d color -> bovw 2022-03-11 10:46:01 +08:00
源文雨
8afbc67bf7 💩👌 make lint happy 2022-03-11 10:26:29 +08:00
源文雨
a27132f907 job可获取网页信息,可代表执行 2022-03-09 12:14:20 +08:00
源文雨
183be05d82 job可编程 2022-03-08 23:18:31 +08:00
源文雨
bccf789714 job增加执行指令 2022-03-08 20:39:02 +08:00
源文雨
55944dddb3 job增加参数读取 2022-03-08 18:14:41 +08:00
源文雨
f67932cc56 job增加参数读取 2022-03-08 18:11:24 +08:00
源文雨
6d633fac6a 🐛 edit readme 2022-03-08 18:10:01 +08:00
源文雨
86fc5c51c8 job增加参数读取 2022-03-08 18:07:59 +08:00
源文雨
156e9f07ad 🐛 job禁止递归触发&增加README 2022-03-08 13:04:44 +08:00
源文雨
1ba4722fc7 💩👌 make lint happy 2022-03-07 23:27:11 +08:00
源文雨
54c9857219 🎉 job增加注入指令结果 2022-03-07 22:49:19 +08:00
源文雨
ea56c7d0d2 🐛 panic: sync: WaitGroup is reused 2022-03-07 14:43:25 +08:00
源文雨
0cbe43df97 🐛 panic: sync: WaitGroup is reused 2022-03-07 14:08:23 +08:00
源文雨
1f941d883a 🐛 panic: sync: WaitGroup is reused 2022-03-07 14:01:15 +08:00
源文雨
f5b3e423fb 🐛 panic: sync: WaitGroup is reused 2022-03-07 13:56:05 +08:00
源文雨
6c7f81ca55 🔖 1.3.1 2022-03-07 13:41:23 +08:00
源文雨
3911b5ed82 🎨 优化初始化逻辑 2022-03-07 13:40:32 +08:00
源文雨
f38f3ab69c 🐛 定时指令触发器插件增加查看 2022-03-07 13:15:26 +08:00
源文雨
846db6f063 📝 edit README 2022-03-06 22:53:59 +08:00
源文雨
ff068a05b0 🐛 定时指令触发器插件增加限速器 2022-03-06 22:52:38 +08:00
源文雨
051b7dd182 🐛 定时指令触发器插件允许非管理私聊使用 2022-03-06 22:46:12 +08:00
源文雨
11870aeed6 🐛 定时指令触发器插件在某些bot失效 2022-03-06 22:37:35 +08:00
源文雨
9bcff82d9c Update main.go 2022-03-06 21:27:19 +08:00
源文雨
309efe8cd8 增加定时指令触发器插件 2022-03-06 21:21:28 +08:00
源文雨
bf54789f0f 🎨 优化pixiv下载 2022-03-05 23:01:28 +08:00
Kanri
01e527abdb 增加六阶七阶猜单词 (#140) 2022-03-05 10:36:01 +08:00
fumiama
db6b558c75 ⬆️ update deps 2022-03-04 12:17:58 +08:00
fumiama
9a792eb144 🍱 运势增加底图 东方归言录 by @KafCoppelia 2022-03-02 22:37:41 +08:00
fumiama
44e99664a3 🎨 关键字搜图改用云函数反代 2022-03-01 23:10:10 +08:00
fumiama
9f3dd37bf0 🎨 关键字搜图改用云函数反代 2022-03-01 23:02:22 +08:00
fumiama
f5936d9cb7 🎨 某些发图应用合并转发 2022-03-01 19:47:25 +08:00
fumiama
27e69ef022 yandex与ascii2d并行 2022-03-01 17:30:59 +08:00
fumiama
6262aab6bd 替换CustomNode为ctxext的封装 2022-03-01 17:29:19 +08:00
fumiama
4781bc8eb7 sync 2022-02-27 19:34:47 +08:00
fumiama
b233c4b638 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-02-27 19:32:29 +08:00
fumiama
0a0cc807dc fix #139 2022-02-27 19:31:53 +08:00
github-actions[bot]
feeeb63e52 🎨 改进代码样式 2022-02-27 10:59:03 +00:00
himawari
5c620d6268 feat:添加月幕galgame网站图 (#138)
* feat:添加月幕galgame网站图

* fix:修lint

* fix:不重复更新

* fix:增加命令提醒语

* fix:增加日语匹配

* fix:换位置加锁

* fix:隐式声明

* fix:copy数组

* Update ai_tts.go

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-02-27 18:57:52 +08:00
fumiama
a469000d7a 🔖 v1.3.0 2022-02-27 15:04:09 +08:00
fumiama
0e15ac78b2 修复pixiv下载 2022-02-27 14:17:29 +08:00
fumiama
d9e195ccd0 💩👌 make lint happy 2022-02-26 23:22:37 +08:00
fumiama
cf52997279 fix: 图片缓存池 2022-02-26 23:20:08 +08:00
fumiama
88318a7151 增加插件 百度一下 2022-02-26 22:28:37 +08:00
fumiama
91f522b666 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-02-26 22:09:55 +08:00
fumiama
1895f8815e fix: gif 爬 撕 2022-02-26 22:09:37 +08:00
Kanri
7be5f52be4 ✏️ 修复抓不到日历的碧油鸡 (#137)
* ✏️ 修复抓不到日历的碧油鸡

* ✏️ 小修改
2022-02-26 21:58:29 +08:00
fumiama
0cfb2e4e06 🎨 优化目录结构 2022-02-25 22:15:14 +08:00
fumiama
5ccf753af3 🎨 优化目录结构 2022-02-25 22:06:30 +08:00
fumiama
bfcf3cac91 删除插件 minecraft 2022-02-25 22:01:37 +08:00
fumiama
bc3d7bc278 删除插件 minecraft 2022-02-25 22:00:03 +08:00
fumiama
7cf767f344 🐛 fix: 摸鱼日历&插件控制 2022-02-25 13:24:21 +08:00
fumiama
7aed9a2c89 fix: reg panic 2022-02-24 21:34:06 +08:00
fumiama
454196a462 sync 2022-02-24 20:02:02 +08:00
fumiama
1597ba7128 💩👌 make lint happy 2022-02-24 19:55:28 +08:00
fumiama
480523ff27 🎨 🔥 ️ feat: pack pooled img sending 2022-02-24 19:54:48 +08:00
Kanri
7ec7ab8682 ✏️ 修复一下碧油鸡 (#136) 2022-02-24 18:06:23 +08:00
Kanri
ba2d011d48 ✏️ 修复获取公众号链接错误的问题 (#135) 2022-02-24 16:56:50 +08:00
fumiama
504e6cd1cc fix(#134): 两个群同时猜单词会互相干扰 2022-02-23 17:10:33 +08:00
github-actions[bot]
b8f3700fe4 🎨 改进代码样式 2022-02-23 08:58:01 +00:00
Jiang-Red
b2cff862bb Update manager.go (#132)
* Update manager.go

修改 自定义欢迎语可带图
添加 修改名片/修改头衔/申请头衔字数限制

* Update manager.go

* Update manager.go

添加 测试欢迎语

* Update manager.go

* Update manager.go

* Update manager.go

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-02-23 16:57:06 +08:00
fumiama
dc348f8500 🔥 🎨 统一 cron 2022-02-23 16:52:40 +08:00
Kanri
8c40293fed 新增插件 摸鱼人日历 (#133)
*  新增插件 摸鱼人日历

*  新增插件 摸鱼人日历

* ✏️ 优化插件 摸鱼人日历
2022-02-23 16:36:23 +08:00
fumiama
48deaf3aca 🔥 🎨 tts 2022-02-23 11:38:00 +08:00
fumiama
6932643788 🔥 🎨 tts 2022-02-23 11:35:43 +08:00
fumiama
7f972e3d68 🐛 fix: wordle 2022-02-23 11:32:26 +08:00
github-actions[bot]
edb0880999 🎨 改进代码样式 2022-02-23 03:17:02 +00:00
himawari
45f0f5cd6c 将mockingbird统一到tts (#131)
* fix:处理回复文本

* feat:将以mockingbird统一到tts里

* fix:修lint

* fix:换一个正则函数

* fix:去掉ok

Co-authored-by: Guohuiyuan <haibaraguo@yeahka.com>
2022-02-23 11:15:42 +08:00
fumiama
e468ac1933 apply new api ImageBytes 2022-02-22 22:16:49 +08:00
fumiama
55b6b40acf fix: use Send instead of SendChain 2022-02-22 21:55:25 +08:00
fumiama
5f1190f72e feat: use single instead of sync.Map 2022-02-22 21:52:06 +08:00
Kanri
b0fbd6507d 发布插件猜单词 2022-02-22 19:48:13 +08:00
fumiama
598a664d30 🐛 修正放大图片 2022-02-22 13:13:04 +08:00
fumiama
211f0a667d 🐛 修正放大图片 2022-02-22 13:10:48 +08:00
fumiama
28fb788778 🎨 shrink imgpool hash 2022-02-21 22:24:29 +08:00
fumiama
628830fbf5 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-02-20 16:57:17 +08:00
fumiama
7d235d0077 🎨 scale 更改为 云函数 2022-02-20 16:57:01 +08:00
himawari
861b0b6cef fix:修改vtb语录存为本地路径,去掉bilibilipush缓存 (#130)
* fix:修改vtb语录存为本地路径,去掉bilibilipush缓存

* fix:bilibiliparse添加up和粉丝数,修改bilibilipush的时间

* Update bilibili_parse.go

Co-authored-by: Guohuiyuan <haibaraguo@yeahka.com>
Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-02-19 23:54:17 +08:00
fumiama
9986c57727 fix: 缓存池有时无法发出图片 2022-02-19 23:50:39 +08:00
fumiama
f1c9e2331c fix: 缓存池有时无法发出图片 2022-02-19 23:41:11 +08:00
fumiama
7c1ddc6ab1 💩👌 make lint happy 2022-02-19 18:03:35 +08:00
fumiama
44ad78761b 🎨 🔥 update sqlite 2022-02-19 16:16:48 +08:00
fumiama
bd6925f2f1 🎨 🔥 统一 seed 2022-02-18 20:20:25 +08:00
fumiama
3838d74cb8 🎨 🔥 优化代码结构 2022-02-18 20:15:07 +08:00
Kanri
eaad8beb7b 增加插件 猜单词 (#129)
*  增加插件 猜单词

* Update wordle.go

* Update wordle.go

* Update wordle.go

* Update wordle.go

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-02-18 19:08:02 +08:00
fumiama
14acdfdbc3 🎨 ️ control 增加数据库查询缓存 & log 采用 CQ 码打印 2022-02-16 21:57:14 +08:00
fumiama
a5fe7a5b40 scale 增加图片过大保护 2022-02-16 13:55:17 +08:00
fumiama
61df3c55b5 scale 增加图片过大保护 2022-02-16 13:50:12 +08:00
fumiama
eb0059c1a3 fix: writer endian 2022-02-16 12:29:49 +08:00
fumiama
4ca5038ae9 🎨 🔥 优化代码结构 2022-02-15 20:50:49 +08:00
fumiama
121403231a fix: acgimage block 2022-02-15 16:17:40 +08:00
fumiama
b945338a8d 🔥 update go-registry 2022-02-15 13:38:45 +08:00
fumiama
ae5ea542a0 🔥 update go-registry 2022-02-15 00:42:39 +08:00
fumiama
fe95dc8201 🐛 fix: image finder 2022-02-14 17:08:20 +08:00
fumiama
1eefb4e610 🐛 fix: image finder 2022-02-14 17:07:45 +08:00
fumiama
8660d8d990 🐛 fix: image finder 2022-02-14 17:06:54 +08:00
fumiama
37033fe48d 搜图增加 yandex 2022-02-14 16:34:46 +08:00
fumiama
30665ad8c6 💩👌 make lint happy 2022-02-14 14:50:42 +08:00
fumiama
f9e4b8db76 📝 edit README 2022-02-14 14:49:12 +08:00
fumiama
c486a210e4 增加插件 漂流瓶 #2 2022-02-14 14:46:33 +08:00
fumiama
0cd01959a0 ⬆️ update kimoi #126 2022-02-14 13:03:37 +08:00
fumiama
d5ac9f7920 💩👌 make lint happy 2022-02-13 21:27:43 +08:00
fumiama
6b2dd112a6 dd add image size limit 2022-02-13 12:08:50 +08:00
fumiama
01abfab133 🚀 update moyu 春节 to 2023 2022-02-13 11:51:41 +08:00
fumiama
e2a56872dc 🐛 fix: 防止自触发 2022-02-13 11:43:36 +08:00
fumiama
6f22a9c4bc fix: chat call name 2022-02-13 11:35:42 +08:00
fumiama
a2426de70c Squashed commit of the following:
commit 3e4b0216b9f952b800e9be880acd744af3afe593
Merge: 970cb14 aaf832e
Author: fumiama <s862105088@gmail.com>
Date:   Sat Feb 12 23:23:51 2022 +0800

    Merge branch 'master' of https://github.com/MoYoez/ZeroBot-Plugin into MoYoez-master

commit 970cb142256d4575b3e5170b9dfb9370f5802da5
Author: fumiama <s862105088@gmail.com>
Date:   Sat Feb 12 23:18:23 2022 +0800

     🐛 🔥 🎨 fix: gif panic

commit aaf832e3b5
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 21:06:21 2022 +0800

    Update chat.go

commit fae3458bcf
Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Date:   Sat Feb 12 13:05:37 2022 +0000

    🎨 改进代码样式

commit 610cae5229
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 21:05:08 2022 +0800

    Update chat.go

commit c445c61da5
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:58:57 2022 +0800

    Delete data.go

commit 70172f4d8b
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:53:10 2022 +0800

    换了个网易云音乐热评的API

commit c8b4827e91
Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Date:   Sat Feb 12 12:50:57 2022 +0000

    🎨 改进代码样式

commit a233586dfe
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:50:21 2022 +0800

    Update chat.go

commit 87501f6011
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:49:08 2022 +0800

    Update data.go

commit ecf6419065
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:48:14 2022 +0800

    Update chat.go

commit c3550503f0
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:47:47 2022 +0800

    Delete plugin_purechat directory

commit 1da3486d00
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:46:34 2022 +0800

    Add files via upload

commit 34ed8c89fd
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:38:46 2022 +0800

    Update main.go

commit aa08eb0120
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:38:19 2022 +0800

    修改过的回复 删掉了一些ex的词汇

commit faf198289f
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:29:59 2022 +0800

    Update main.go

commit 5ac3b7a790
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:28:48 2022 +0800

    Update chat.go

commit b046d45435
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:25:23 2022 +0800

    Rename purechat.go to chat.go

commit 6bbcdfcd58
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:24:54 2022 +0800

    Add files via upload

commit e7630b5904
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:24:32 2022 +0800

    Update purechat.go

commit 36c903bece
Author: MoeMagicMango <i@himoyo.cn>
Date:   Sat Feb 12 20:23:01 2022 +0800

    Create purechat.go
2022-02-12 23:38:45 +08:00
MoeMagicMango
ed7bbf54a7 Update chat.go 2022-02-12 23:36:58 +08:00
fumiama
69394377d0 fix: emojimix logical error 2022-02-12 14:48:12 +08:00
fumiama
8f20487a15 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-02-12 14:20:21 +08:00
fumiama
fae24db2df 💩👌 make lint happy 2022-02-12 14:20:10 +08:00
github-actions[bot]
f8fb791d8f 🎨 改进代码样式 2022-02-12 06:19:04 +00:00
Kanri
f320d9e1e5 增加插件 emojimix (#121)
*  增加插件 emojimix

* 🎨✏️ 优化代码格式

*  增加 qqface 支持

* Update main.go

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2022-02-12 14:18:05 +08:00
fumiama
18bd34fad2 fix(#122): 避免图片过大导致内存占用过多 2022-02-12 13:37:06 +08:00
fumiama
cf72d0b36a fix(#122): 避免图片过大导致内存占用过多 2022-02-12 13:32:26 +08:00
fumiama
c3722b0a6c ️ perf: 每次匹配仅检查一次 ban 2022-02-11 00:39:50 +08:00
fumiama
3af701e803 🎉 🎨 ️ 优化 base64 图片 log 体验 & 减少 ban 遍历 2022-02-10 23:47:39 +08:00
fumiama
bc4b2e89db 🎉 base14支持所有平台 2022-02-10 14:15:49 +08:00
fumiama
3cbb589d2c 💩👌 make lint happy 2022-02-09 21:00:42 +08:00
170 changed files with 8107 additions and 4351 deletions

View File

@@ -28,7 +28,7 @@ jobs:
- name: Setup Go environment
uses: actions/setup-go@v2.1.3
with:
go-version: 1.17
go-version: 1.18
- name: Cache downloaded module
uses: actions/cache@v2
with:

View File

@@ -8,7 +8,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18
- name: Check out code into the Go module directory
uses: actions/checkout@v2
@@ -28,9 +28,6 @@ jobs:
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true
# Optional: if set to true then the action will use pre-installed Go.
skip-go-installation: true
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
# skip-pkg-cache: true

View File

@@ -8,7 +8,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18
- name: Check out code into the Go module directory
uses: actions/checkout@v2
@@ -18,7 +18,6 @@ jobs:
with:
version: latest
args: --issues-exit-code=0
skip-go-installation: true
- name: Commit back
continue-on-error: true
run: |

View File

@@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: '1.17'
go-version: '1.18'
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2

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

View File

@@ -1,15 +1,11 @@
linters-settings:
errcheck:
ignore: fmt:.*,io/ioutil:^Read.*
ignore: fmt:.*
ignoretests: true
goimports:
local-prefixes: github.com/FloatTech/ZeroBot-Plugin
gocritic:
disabled-checks:
- exitAfterDefer
forbidigo:
# Forbid the following identifiers
forbid:
@@ -66,6 +62,7 @@ run:
tests: false
skip-dirs:
- order
go: '1.18'
# output configuration options
output:

1242
README.md

File diff suppressed because it is too large Load Diff

13
config.go Normal file
View File

@@ -0,0 +1,13 @@
package main
import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/driver"
)
type zbpcfg struct {
Z zero.Config `json:"zero"`
W []*driver.WSClient `json:"ws"`
}
var config zbpcfg

2
data

Submodule data updated: 0090d93bda...291200d5d4

54
go.mod
View File

@@ -1,40 +1,44 @@
module github.com/FloatTech/ZeroBot-Plugin
go 1.17
go 1.18
require (
github.com/FloatTech/AnimeAPI v1.3.0-beta2
github.com/FloatTech/sqlite v0.1.0
github.com/FloatTech/zbputils v1.3.0-beta2
github.com/FloatTech/AnimeAPI v1.4.1-0.20220520130802-b8c30f649145
github.com/FloatTech/sqlite v0.2.1
github.com/FloatTech/zbputils v1.4.1-0.20220525034822-233c3292b457
github.com/antchfx/htmlquery v1.2.4
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.2.1
github.com/fumiama/go-registry v0.0.2
github.com/fumiama/gofastTEA v0.0.6
github.com/fumiama/go-base16384 v1.5.2
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/logoove/sqlite v1.13.0
github.com/jozsefsallai/gophersauce v1.0.1
github.com/mroth/weightedrand v0.4.1
github.com/shirou/gopsutil/v3 v3.21.12
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.13.0
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220208041536-d463c1c92bb4
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
github.com/tidwall/gjson v1.14.1
github.com/wcharczuk/go-chart/v2 v2.1.0
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220509035736-f3ad8fa960d7
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9
)
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/disintegration/imaging v1.6.2 // indirect
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
github.com/gabriel-vasile/mimetype v1.0.4 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
@@ -42,23 +46,13 @@ require (
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.9 // indirect
github.com/tklauser/numcpus v0.3.0 // indirect
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/mod v0.5.1 // indirect
golang.org/x/net v0.0.0-20220111093109-d55c255bac03 // indirect
golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.9 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.35.22 // indirect
modernc.org/ccgo/v3 v3.15.13 // indirect
modernc.org/libc v1.14.5 // indirect
modernc.org/libc v1.14.6 // indirect
modernc.org/mathutil v1.4.1 // indirect
modernc.org/memory v1.0.5 // indirect
modernc.org/opt v0.1.1 // indirect
modernc.org/sqlite v1.14.6 // indirect
modernc.org/strutil v1.1.1 // indirect
modernc.org/token v1.0.0 // indirect
)

209
go.sum
View File

@@ -1,13 +1,12 @@
github.com/FloatTech/AnimeAPI v1.3.0-beta2 h1:htgptcTzPk50XNwoBdZlXabM3sF71upcrafMXACI9+Y=
github.com/FloatTech/AnimeAPI v1.3.0-beta2/go.mod h1:Y2o3MvmtZV8JoxCh18iu+2AgB1iLtNDKgYVT77bMsFQ=
github.com/FloatTech/bot-manager v1.0.0/go.mod h1:8YYRJ16oroGHQGD2En0oVnmcKJkxR9O/jd5BPSfWfOQ=
github.com/FloatTech/sqlite v0.1.0 h1:Geh6Z+DWZXmyXVOhM0U2oXT7b1Ob6sQtuyjInk+MCUk=
github.com/FloatTech/sqlite v0.1.0/go.mod h1:XS0oeSqtH6lFzpPRiDE9fV6+zMcuUF5/6o+tQVO1QZE=
github.com/FloatTech/zbputils v1.3.0-beta2 h1:Yo/NzZSOUlw/0jG/HYu4kzFwsdRcP54c5BXpqmPHyaE=
github.com/FloatTech/zbputils v1.3.0-beta2/go.mod h1:e9e8998yQkzS24IqZ8jLUssTk607hD/Tj3zGyBikIIc=
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb h1:Rkj28fqIwGx/EgBzRYtpmJRfH6wqVn7cNdc7aJ0QE4M=
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb/go.mod h1:imVKbfKqqeit+C/eaWGb4MKQ3z3gN6pRpBU5RMtp5so=
github.com/FloatTech/AnimeAPI v1.4.1-0.20220520130802-b8c30f649145 h1:COSibysiEmRsI7pICkZMdaX6XM35mlqbtB3f4Tbf6ow=
github.com/FloatTech/AnimeAPI v1.4.1-0.20220520130802-b8c30f649145/go.mod h1:7lhHG03Mqoze1ig/zXnzT3WZGSzdwCl6jk1Eh0f/T9s=
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.4.1-0.20220525034822-233c3292b457 h1:V6O5IqwT2oGAJTDg8WU3C2v7ReULUY3lXaVCd56ABqo=
github.com/FloatTech/zbputils v1.4.1-0.20220525034822-233c3292b457/go.mod h1:Cf2wAFtq7OUj4RUHcSQtcAYgAspP06wQseKZwtCJRXQ=
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=
@@ -17,7 +16,6 @@ github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8=
github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/corona10/goimagehash v1.0.3 h1:NZM518aKLmoNluluhfHGxT3LGOnrojrxhGn63DR/CZA=
github.com/corona10/goimagehash v1.0.3/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -25,7 +23,6 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6RO
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU=
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM=
@@ -33,205 +30,131 @@ github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DP
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
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.2.1 h1:6OGprW8g/95m2ocmryHi8mipZ7bx9StFMZDKEqLvMiA=
github.com/fumiama/go-base16384 v1.2.1/go.mod h1:1HTC0QFL7BjS0DuO5Qm+fBYKQkHqmAapLbRpCxrhPXQ=
github.com/fumiama/go-registry v0.0.2 h1:2EoZwZpqI7YhkQ1FnuAPvALYPpvUtbsCqk879+r7ehs=
github.com/fumiama/go-registry v0.0.2/go.mod h1:QkcmmHuw1y6y/w7/HiH1c9yjBw5Zt+6EER6YJKl9xh8=
github.com/fumiama/gofastTEA v0.0.6 h1:Yni3MXDbJVa/c4CecgdZDgCJK+fLdvGph+OBqY2mtiI=
github.com/fumiama/gofastTEA v0.0.6/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
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-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=
github.com/fumiama/gofastTEA v0.0.10/go.mod h1:RIdbYZyB4MbH6ZBlPymRaXn3cD6SedlCu5W/HHfMPBk=
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
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/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/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
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/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/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/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
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/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
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/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM=
github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
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/logoove/sqlite v1.13.0 h1:XM7QKK9R3tm8o7bI75R3zmwYBFQ5S3Jqg+XCaqsAMQQ=
github.com/logoove/sqlite v1.13.0/go.mod h1:MRpE/o3qQhT7AgfIdnBue5c63+//xT+KXV0gHeVAUAg=
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/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/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
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/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/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA=
github.com/shirou/gopsutil/v3 v3.21.12/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
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/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.13.0 h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M=
github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
github.com/wdvxdr1123/ZeroBot v1.3.2/go.mod h1:i2DIqQjtjE+3gvVi9r9sc+QpNaUuyTXx/HNXXayIpwI=
github.com/wdvxdr1123/ZeroBot v1.4.1/go.mod h1:7t9m4vDZPwWAmzKlhP6IvUoisOIiqNdm/3AJgiY3+ew=
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220208041536-d463c1c92bb4 h1:T/m7vDUFKdLd0xfSZHVPQGaRZ73nwPzidLW7hTn25mg=
github.com/wdvxdr1123/ZeroBot v1.4.2-0.20220208041536-d463c1c92bb4/go.mod h1:NwXIp7PgjV+kUALMXJ4v4/3QcsRSOodtjhLekuPXFog=
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
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/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.20220509035736-f3ad8fa960d7 h1:GDJ+ZhbaGGBdlaT6qljgt61A/rlZdrNtA5fQyb5uVP4=
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220509035736-f3ad8fa960d7/go.mod h1:LJ+VOf523i3IrykuLK53UEeWqnAclRL5d2wGT4sS4Zk=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.1/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=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/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-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8 h1:kACShD3qhmr/3rLmg1yXyt+N4HcwutKyPRB93s54TIU=
golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
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/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/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-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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220111093109-d55c255bac03 h1:0FB83qp0AzVJm+0wcIlauAjJ+tNdh7jLuacRYCIVv7s=
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/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-20180909124046-d0be0721c37e/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/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-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/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-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/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-20220207234003-57398862261d h1:Bm7BNOQt2Qv7ZqysjeLjgCBanX+88Z/OtdvsrEv1Djc=
golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
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/text v0.3.0/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=
@@ -239,32 +162,15 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
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.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
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/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
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.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
lukechampine.com/uint128 v1.2.0/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=
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
@@ -280,7 +186,6 @@ modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g
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 h1:BzShpwCAP7TWzFppM4k2t03RhXhgYqaibROWkrWq7lE=
modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
@@ -320,16 +225,10 @@ modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTS
modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko=
modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA=
modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4=
modernc.org/ccgo/v3 v3.15.1/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0=
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.15.13 h1:hqlCzNJTXLrhS70y1PqWckrF9x1btSQRC7JFuQcBg5c=
modernc.org/ccgo/v3 v3.15.13/go.mod h1:QHtvdpeODlXjdK3tsbpyK+7U9JV4PQsrPGIbtmc0KfY=
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/ccorpus v1.11.4 h1:YOmQBBzE8GC/puUx76D5j/gJYIZQsydrh6VMJVfXF0M=
modernc.org/ccorpus v1.11.4/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
@@ -372,8 +271,9 @@ modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
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 h1:DAHvwGoVRDZs5iJXnX9RJrgXSsorupCWmJ2ac964Owk=
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/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=
@@ -382,13 +282,6 @@ modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6
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/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.14.6 h1:Jt5P3k80EtDBWaq1beAxnWW+5MdHXbZITujnRS7+zWg=
modernc.org/sqlite v1.14.6/go.mod h1:yiCvMv3HblGmzENNIaNtFhfaNIwcla4u2JQEwJPzfEc=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.11.0/go.mod h1:zsTUpbQ+NxQEjOjCUlImDLPv1sG8Ww0qp66ZvyOxCgw=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.3.0/go.mod h1:+mvgLH814oDjtATDdT3rs84JnUIpkvAF5B8AVkNlE2g=

45
kanban/banner.go Normal file
View File

@@ -0,0 +1,45 @@
package kanban
import (
"fmt"
"strings"
"github.com/fumiama/go-registry"
)
var (
info = [...]string{
"* OneBot + ZeroBot + Golang",
"* Version 1.4.1-beta3 - 2022-05-25 11:58:18 +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")
)
// PrintBanner ...
func PrintBanner() {
fmt.Print(
"\n======================[ZeroBot-Plugin]======================",
"\n", Banner, "\n",
"----------------------[ZeroBot-公告栏]----------------------",
"\n", Kanban(), "\n",
"============================================================\n\n",
)
}
// Kanban ...
func Kanban() string {
err := reg.Connect()
if err != nil {
return err.Error()
}
defer reg.Close()
text, err := reg.Get("ZeroBot-Plugin/kanban")
if err != nil {
return err.Error()
}
return text
}

6
kanban/init.go Normal file
View File

@@ -0,0 +1,6 @@
// Package kanban 打印版本信息
package kanban
func init() {
PrintBanner()
}

253
main.go
View File

@@ -1,10 +1,15 @@
package main
import (
"encoding/json"
"flag"
"fmt"
"math/rand"
"os"
"strings"
"strconv"
"time"
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 在最前打印 banner
// ---------以下插件均可通过前面加 // 注释,注释后停用并不加载插件--------- //
// ----------------------插件优先级按顺序从高到低---------------------- //
@@ -22,13 +27,17 @@ import (
// webctrl "github.com/FloatTech/zbputils/control/web" // web 后端控制
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_chat" // 基础词库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat" // 基础词库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_sleep_manage" // 统计睡眠时间
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleep_manage" // 统计睡眠时间
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_atri" // ATRI词库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri" // ATRI词库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_manager" // 群管
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/manager" // 群管
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
_ "github.com/FloatTech/zbputils/job" // 定时指令触发器
// ^^^^ //
// ^^^^^^^^^^^^^^ //
@@ -48,53 +57,67 @@ import (
// vvvvvvvvvvvvvv //
// vvvv //
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_acgimage" // 随机图片与AI点评
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false" // 服务器监控
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_aiwife" // 随机老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_b14" // base16384加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili" // 查询b站用户信息
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili_parse" // b站视频链接解析
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_book_review" // 哀伤雪刃吧推书记录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_cangtoushi" // 藏头诗
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose" // 选择困难症帮手
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_chouxianghua" // 说抽象话
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_coser" // 三次元小姐姐
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_cpstory" // cp短打
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_danbooru" // DeepDanbooru二次元图标签识别
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_diana" // 嘉心糖发病
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_fortune" // 运势
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_funny" // 笑话
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_gif" // 制图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_github" // 搜索GitHub仓库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_hs" // 炉石
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_image_finder" // 关键字搜图
_ "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_minecraft" // MCSManager
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_moyu" // 摸鱼
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_music" // 点歌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nativesetu" // 本地涩图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nativewife" // 本地老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nbnhhsh" // 拼音首字母缩写释义工具
_ "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_reborn" // 投胎
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_runcode" // 在线运行代码
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_saucenao" // 以图搜图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_scale" // 叔叔的AI二次元图片放大
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_score" // 分数
_ "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_tracemoe" // 搜番
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_translation" // 翻译
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_vtb_quotation" // vtb语录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_wangyiyun" // 网易云音乐热评
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_false" // 服务器监控
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/b14" // base16384加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu" // 百度一下
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili" // 查询b站用户信息
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili_parse" // b站视频链接解析
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/book_review" // 哀伤雪刃吧推书记录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cangtoushi" // 藏头诗
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/choose" // 选择困难症帮手
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chouxianghua" // 说抽象话
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/coser" // 三次元小姐姐
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cpstory" // cp短打
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru" // DeepDanbooru二次元图标签识别
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana" // 嘉心糖发病
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/drift_bottle" // 漂流瓶
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/emojimix" // 合成emoji
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/epidemic" // 城市疫情查询
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/font" // 渲染任意文字到图片
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/fortune" // 运势
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/funny" // 笑话
_ "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/hs" // 炉石
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hyaku" // 百人一首
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/image_finder" // 关键字搜图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/inject" // 注入指令
_ "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/moyu" // 摸鱼
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu_calendar" // 摸鱼人日历
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/music" // 点歌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativesetu" // 本地涩图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativewife" // 本地老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nbnhhsh" // 拼音首字母缩写释义工具
_ "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" // 以图搜图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/scale" // 叔叔的AI二次元图片放大
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/score" // 分数
_ "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" // 翻译
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtb_quotation" // vtb语录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun" // 网易云音乐热评
_ "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站推送
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf" // 鬼东西
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili_push" // b站推送
// ^^^^ //
// ^^^^^^^^^^^^^^ //
@@ -114,9 +137,9 @@ import (
// vvvvvvvvvvvvvv //
// vvvv //
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_curse" // 骂人
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/curse" // 骂人
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_reply" // 人工智能回复
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply" // 人工智能回复
// ^^^^ //
// ^^^^^^^^^^^^^^ //
@@ -130,8 +153,7 @@ import (
// //
// //
// -----------------------以下为内置依赖,勿动------------------------ //
"github.com/FloatTech/zbputils/control/order"
"github.com/fumiama/go-registry"
"github.com/FloatTech/zbputils/process"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/driver"
@@ -139,41 +161,28 @@ import (
// -----------------------以上为内置依赖,勿动------------------------ //
)
var (
contents = []string{
"* OneBot + ZeroBot + Golang",
"* Version 1.3.0 - 2022-02-09 14:31:34 +0800 CST",
"* Copyright © 2020 - 2021 FloatTech. All Rights Reserved.",
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
}
nicks = []string{"ATRI", "atri", "亚托莉", "アトリ"}
banner = strings.Join(contents, "\n")
token *string
url *string
adana *string
prefix *string
reg = registry.NewRegReader("reilia.fumiama.top:32664", "fumiama")
)
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.")
// 解析命令行参数,输入 `-g 监听地址:端口` 指定 gui 访问地址,默认 127.0.0.1:3000
// g := flag.String("g", "127.0.0.1:3000", "Set web gui listening address.")
// 直接写死 AccessToken 时,请更改下面第二个参数
token = flag.String("t", "", "Set AccessToken of WSClient.")
token := flag.String("t", "", "Set AccessToken of WSClient.")
// 直接写死 URL 时,请更改下面第二个参数
url = flag.String("u", "ws://127.0.0.1:6700", "Set Url of WSClient.")
url := flag.String("u", "ws://127.0.0.1:6700", "Set Url of WSClient.")
// 默认昵称
adana = flag.String("n", "椛椛", "Set default nickname.")
prefix = flag.String("p", "/", "Set command prefix.")
adana := flag.String("n", "椛椛", "Set default nickname.")
prefix := flag.String("p", "/", "Set command prefix.")
runcfg := flag.String("c", "", "Run from config file.")
save := flag.String("s", "", "Save default config to file and exit.")
flag.Parse()
if *h {
printBanner()
kanban.PrintBanner()
fmt.Println("Usage:")
flag.PrintDefaults()
os.Exit(0)
@@ -186,53 +195,73 @@ func init() {
}
}
for _, s := range flag.Args() {
i, err := strconv.ParseInt(s, 10, 64)
if err != nil {
continue
}
sus = append(sus, i)
}
// 通过代码写死的方式添加主人账号
// sus = append(sus, 12345678)
// sus = append(sus, 87654321)
// 启用 gui
// webctrl.InitGui(*g)
}
func printBanner() {
fmt.Print(
"\n======================[ZeroBot-Plugin]======================",
"\n", banner, "\n",
"----------------------[ZeroBot-公告栏]----------------------",
"\n", getKanban(), "\n",
"============================================================\n",
)
}
if *runcfg != "" {
f, err := os.Open(*runcfg)
if err != nil {
panic(err)
}
config.W = make([]*driver.WSClient, 0, 2)
err = json.NewDecoder(f).Decode(&config)
f.Close()
if err != nil {
panic(err)
}
config.Z.Driver = make([]zero.Driver, len(config.W))
for i, w := range config.W {
config.Z.Driver[i] = w
}
logrus.Infoln("[main] 从", *runcfg, "读取配置文件")
return
}
func getKanban() string {
err := reg.Connect()
if err != nil {
return err.Error()
config.W = []*driver.WSClient{driver.NewWebSocketClient(*url, *token)}
config.Z = zero.Config{
NickName: append([]string{*adana}, "ATRI", "atri", "亚托莉", "アトリ"),
CommandPrefix: *prefix,
SuperUsers: sus,
Driver: []zero.Driver{config.W[0]},
}
defer reg.Close()
text, err := reg.Get("ZeroBot-Plugin/kanban")
if err != nil {
return err.Error()
if *save != "" {
f, err := os.Create(*save)
if err != nil {
panic(err)
}
err = json.NewEncoder(f).Encode(&config)
f.Close()
if err != nil {
panic(err)
}
logrus.Infoln("[main] 配置文件已保存到", *save)
os.Exit(0)
}
return text
}
func main() {
order.Wait()
printBanner()
rand.Seed(time.Now().UnixNano()) // 全局 seed其他插件无需再 seed
// 帮助
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(banner, "\n可发送\"/服务列表\"查看 bot 功能"))
ctx.SendChain(message.Text(kanban.Banner, "\n可发送\"/服务列表\"查看 bot 功能"))
})
zero.OnFullMatch("查看zbp公告", zero.OnlyToMe, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(getKanban()))
ctx.SendChain(message.Text(kanban.Kanban()))
})
zero.RunAndBlock(
zero.Config{
NickName: append([]string{*adana}, nicks...),
CommandPrefix: *prefix,
// SuperUsers 某些功能需要主人权限,可通过以下两种方式修改
// SuperUsers: []string{"12345678", "87654321"}, // 通过代码写死的方式添加主人账号
SuperUsers: flag.Args(), // 通过命令行参数的方式添加主人账号
Driver: []zero.Driver{driver.NewWebSocketClient(*url, *token)},
},
)
zero.RunAndBlock(config.Z, process.GlobalInitMutex.Unlock)
}

View File

@@ -12,14 +12,12 @@ import (
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/mem"
"github.com/FloatTech/zbputils/control/order"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() { // 插件主体
engine := control.Register("aifalse", order.AcquirePrio(), &control.Options{
engine := control.Register("aifalse", &control.Options{
DisableOnDefault: false,
Help: "AIfalse\n" +
"- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]",

184
plugin/ai_reply/ai_tts.go Normal file
View File

@@ -0,0 +1,184 @@
package aireply
import (
"errors"
"regexp"
"strconv"
"sync"
"github.com/pkumza/numcn"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/AnimeAPI/aireply"
"github.com/FloatTech/AnimeAPI/tts"
"github.com/FloatTech/AnimeAPI/tts/baidutts"
"github.com/FloatTech/AnimeAPI/tts/mockingbird"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
)
const ttsServiceName = "tts"
var re = regexp.MustCompile(`(\-|\+)?\d+(\.\d+)?`)
type ttsInstances struct {
sync.RWMutex
m map[string]tts.TTS
l []string
}
func (t *ttsInstances) List() []string {
t.RLock()
cl := make([]string, len(t.l))
_ = copy(cl, t.l)
t.RUnlock()
return cl
}
func init() {
t := &ttsInstances{
m: map[string]tts.TTS{
"百度女声": baidutts.NewBaiduTTS(0),
"百度男声": baidutts.NewBaiduTTS(1),
"百度度逍遥": baidutts.NewBaiduTTS(3),
"百度度丫丫": baidutts.NewBaiduTTS(4),
"拟声鸟阿梓": nil,
"拟声鸟文静": nil,
"拟声鸟药水哥": nil,
},
l: []string{"拟声鸟阿梓", "拟声鸟文静", "拟声鸟药水哥", "百度女声", "百度男声", "百度度逍遥", "百度度丫丫"},
}
engine := control.Register(ttsServiceName, &control.Options{
DisableOnDefault: true,
Help: "语音回复(包括拟声鸟和百度)\n" +
"- @Bot 任意文本(任意一句话回复)\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, err := t.new(t.getSoundMode(ctx))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
var reply string
if tts != nil {
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 {
log.Errorln("[tts]:", err)
return s
}
return numcn.EncodeFromFloat64(f)
})
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).
Handle(func(ctx *zero.Ctx) {
param := ctx.State["regex_matched"].([]string)[1]
err := t.setSoundMode(ctx, param)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前模式为", param))
})
engine.OnRegex(`^设置默认语音模式(.*)$`, ctxext.FirstValueInList(t)).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
param := ctx.State["regex_matched"].([]string)[1]
t.setDefaultSoundMode(param)
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,默认模式为", param))
})
}
// new 语音简单工厂
func (t *ttsInstances) new(name string) (ts tts.TTS, err error) {
t.RLock()
ts = t.m[name]
t.RUnlock()
if ts == nil {
switch name {
case "拟声鸟阿梓":
t.Lock()
ts, err = mockingbird.NewMockingBirdTTS(0)
t.Unlock()
case "拟声鸟文静":
t.Lock()
ts, err = mockingbird.NewMockingBirdTTS(1)
t.Unlock()
case "拟声鸟药水哥":
t.Lock()
ts, err = mockingbird.NewMockingBirdTTS(2)
t.Unlock()
}
}
return
}
func (t *ttsInstances) setSoundMode(ctx *zero.Ctx, name string) error {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
var index int64
t.RLock()
for i, s := range t.l {
if s == name {
index = int64(i)
break
}
}
t.RUnlock()
m, ok := control.Lookup(ttsServiceName)
if !ok {
return errors.New("no such plugin")
}
return m.SetData(gid, index)
}
func (t *ttsInstances) getSoundMode(ctx *zero.Ctx) (name string) {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
m, ok := control.Lookup(ttsServiceName)
if ok {
t.RLock()
defer t.RUnlock()
index := m.GetData(gid)
if int(index) < len(t.l) {
return t.l[index]
}
}
return "拟声鸟阿梓"
}
func (t *ttsInstances) setDefaultSoundMode(name string) {
var index int
t.RLock()
for _, s := range t.l {
if s == name {
break
}
index++
}
t.RUnlock()
t.Lock()
t.l[0], t.l[index] = t.l[index], t.l[0]
t.Unlock()
}

View File

@@ -10,18 +10,16 @@ import (
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
const (
serviceName = "aireply"
replyServiceName = "aireply"
)
var modes = [...]string{"青云客", "小爱"}
var replyModes = [...]string{"青云客", "小爱"}
func init() { // 插件主体
engine := control.Register(serviceName, order.AcquirePrio(), &control.Options{
engine := control.Register(replyServiceName, &control.Options{
DisableOnDefault: false,
Help: "人工智能回复\n" +
"- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客 | 小爱]\n- ",
@@ -59,7 +57,7 @@ func setReplyMode(ctx *zero.Ctx, name string) error {
}
var ok bool
var index int64
for i, s := range modes {
for i, s := range replyModes {
if s == name {
ok = true
index = int64(i)
@@ -69,7 +67,7 @@ func setReplyMode(ctx *zero.Ctx, name string) error {
if !ok {
return errors.New("no such mode")
}
m, ok := control.Lookup(serviceName)
m, ok := control.Lookup(replyServiceName)
if !ok {
return errors.New("no such plugin")
}
@@ -81,11 +79,11 @@ func getReplyMode(ctx *zero.Ctx) (name string) {
if gid == 0 {
gid = -ctx.Event.UserID
}
m, ok := control.Lookup(serviceName)
m, ok := control.Lookup(replyServiceName)
if ok {
index := m.GetData(gid)
if int(index) < len(modes) {
return modes[index]
if int(index) < len(replyModes) {
return replyModes[index]
}
}
return "青云客"

View File

@@ -4,14 +4,11 @@ package aiwife
import (
"fmt"
"math/rand"
"time"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
const (
@@ -19,8 +16,7 @@ const (
)
func init() { // 插件主体
rand.Seed(time.Now().UnixNano())
control.Register("aiwife", order.AcquirePrio(), &control.Options{
control.Register("aiwife", &control.Options{
DisableOnDefault: false,
Help: "AIWife\n" +
"- waifu | 随机waifu",

View File

@@ -14,8 +14,6 @@ import (
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/control/order"
)
const (
@@ -26,7 +24,7 @@ const (
)
func init() { // 插件主体
engine := control.Register(servicename, order.AcquirePrio(), &control.Options{
engine := control.Register(servicename, &control.Options{
DisableOnDefault: false,
Help: "本插件基于 ATRI ,为 Golang 移植版\n" +
"- ATRI醒醒\n- ATRI睡吧\n- 萝卜子\n- 喜欢 | 爱你 | 爱 | suki | daisuki | すき | 好き | 贴贴 | 老婆 | 亲一个 | mua\n" +
@@ -34,26 +32,16 @@ func init() { // 插件主体
"- 中午好 | 午安 | 午好\n- 晚安 | oyasuminasai | おやすみなさい | 晚好 | 晚上好\n- 高性能 | 太棒了 | すごい | sugoi | 斯国一 | よかった\n" +
"- 没事 | 没关系 | 大丈夫 | 还好 | 不要紧 | 没出大问题 | 没伤到哪\n- 好吗 | 是吗 | 行不行 | 能不能 | 可不可以\n- 啊这\n- 我好了\n- | ? | ¿\n" +
"- 离谱\n- 答应我",
OnEnable: func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("嗯呜呜……夏生先生……?"))
},
OnDisable: func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("Zzz……Zzz……"))
},
})
zero.OnFullMatch("ATRI醒醒", zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
c, ok := control.Lookup(servicename)
if ok && !c.IsEnabledIn(ctx.Event.GroupID) {
c.Enable(ctx.Event.GroupID)
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("嗯呜呜……夏生先生……?"))
}
})
engine.OnFullMatch("ATRI睡吧", zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
c, ok := control.Lookup(servicename)
if ok && c.IsEnabledIn(ctx.Event.GroupID) {
c.Disable(ctx.Event.GroupID)
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("Zzz……Zzz……"))
}
})
engine.OnFullMatch("萝卜子", atriSleep).SetBlock(true).
engine.OnFullMatch("萝卜子", isAtriSleeping).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
switch rand.Intn(2) {
@@ -63,12 +51,12 @@ func init() { // 插件主体
ctx.SendChain(randRecord("RocketPunch.amr"))
}
})
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, atriSleep, zero.OnlyToMe).SetBlock(true).
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
})
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, atriSleep, zero.OnlyToMe).SetBlock(true).
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
@@ -169,7 +157,7 @@ func init() { // 插件主体
))
}
})
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, atriSleep, zero.OnlyToMe).SetBlock(true).
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(randText(
@@ -190,7 +178,7 @@ func init() { // 插件主体
"呣......我的高性能,毫无遗憾地施展出来了......",
))
})
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, atriSleep, zero.OnlyToMe).SetBlock(true).
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, isAtriSleeping, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(randText(
@@ -205,26 +193,26 @@ func init() { // 插件主体
))
})
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, atriSleep).SetBlock(true).
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}, isAtriSleeping).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
if rand.Intn(2) == 0 {
ctx.SendChain(randImage("YES.png", "NO.jpg"))
}
})
engine.OnKeywordGroup([]string{"啊这"}, atriSleep).SetBlock(true).
engine.OnKeywordGroup([]string{"啊这"}, isAtriSleeping).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
if rand.Intn(2) == 0 {
ctx.SendChain(randImage("AZ.jpg", "AZ1.jpg"))
}
})
engine.OnKeywordGroup([]string{"我好了"}, atriSleep).SetBlock(true).
engine.OnKeywordGroup([]string{"我好了"}, isAtriSleeping).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText("不许好!", "憋回去!"))
})
engine.OnFullMatchGroup([]string{"", "?", "¿"}, atriSleep).SetBlock(true).
engine.OnFullMatchGroup([]string{"", "?", "¿"}, isAtriSleeping).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
switch rand.Intn(5) {
@@ -234,7 +222,7 @@ func init() { // 插件主体
ctx.SendChain(randImage("WH.jpg", "WH1.jpg", "WH2.jpg", "WH3.jpg"))
}
})
engine.OnKeyword("离谱", atriSleep).SetBlock(true).
engine.OnKeyword("离谱", isAtriSleeping).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
switch rand.Intn(5) {
case 0:
@@ -243,7 +231,7 @@ func init() { // 插件主体
ctx.SendChain(randImage("WH.jpg"))
}
})
engine.OnKeyword("答应我", atriSleep, zero.OnlyToMe).SetBlock(true).
engine.OnKeyword("答应我", isAtriSleeping, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(randText("我无法回应你的请求"))
@@ -262,8 +250,8 @@ func randRecord(file ...string) message.MessageSegment {
return message.Record(res + file[rand.Intn(len(file))])
}
// atriSleep 凌晨0点到6点ATRI 在睡觉,不回应任何请求
func atriSleep(ctx *zero.Ctx) bool {
// isAtriSleeping 凌晨0点到6点ATRI 在睡觉,不回应任何请求
func isAtriSleeping(ctx *zero.Ctx) bool {
if now := time.Now().Hour(); now >= 1 && now < 6 {
return false
}

View File

@@ -10,12 +10,10 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/zbputils/control/order"
)
func init() {
en := control.Register("base16384", order.AcquirePrio(), &control.Options{
en := control.Register("base16384", &control.Options{
DisableOnDefault: false,
Help: "base16384加解密\n" +
"- 加密xxx\n- 解密xxx\n- 用yyy加密xxx\n- 用yyy解密xxx",
@@ -23,9 +21,9 @@ func init() {
en.OnRegex(`^加密\s?(.*)`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es, err := base14.UTF16be2utf8(base14.EncodeString(str))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(es)))
es := base14.EncodeString(str)
if es != "" {
ctx.SendChain(message.Text(es))
} else {
ctx.SendChain(message.Text("加密失败!"))
}
@@ -33,9 +31,9 @@ func init() {
en.OnRegex(`^解密\s?([一-踀]*[㴁-㴆]?)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es, err := base14.UTF82utf16be(helper.StringToBytes(str))
if err == nil {
ctx.SendChain(message.Text(base14.DecodeString(es)))
es := base14.DecodeString(str)
if es != "" {
ctx.SendChain(message.Text(es))
} else {
ctx.SendChain(message.Text("解密失败!"))
}
@@ -44,7 +42,7 @@ func init() {
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := getea(key)
es, err := base14.UTF16be2utf8(base14.Encode(t.Encrypt(helper.StringToBytes(str))))
es, err := base14.UTF16BE2UTF8(base14.Encode(t.Encrypt(helper.StringToBytes(str))))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(es)))
} else {
@@ -55,7 +53,7 @@ func init() {
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := getea(key)
es, err := base14.UTF82utf16be(helper.StringToBytes(str))
es, err := base14.UTF82UTF16BE(helper.StringToBytes(str))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(t.Decrypt(base14.Decode(es)))))
} else {

26
plugin/baidu/search.go Normal file
View File

@@ -0,0 +1,26 @@
// Package baidu 百度一下
package baidu
import (
"net/url"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
)
func init() {
control.Register("baidu", &control.Options{
DisableOnDefault: false,
Help: "baidu\n" +
"- 百度下[xxx]",
}).OnPrefix("百度下").SetBlock(true).Limit(ctxext.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
txt := ctx.State["args"].(string)
if txt != "" {
ctx.SendChain(message.Text("https://buhuibaidu.me/?s=" + url.QueryEscape(txt)))
}
})
}

179
plugin/bilibili/api.go Normal file
View File

@@ -0,0 +1,179 @@
package bilibili
import (
"encoding/json"
"errors"
"io"
"net/http"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/web"
"github.com/tidwall/gjson"
)
var (
errNeedCookie = errors.New("该api需要设置b站cookie请发送命令设置cookie例如\"设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31\"")
)
type searchResult struct {
Mid int64 `json:"mid"`
Uname string `json:"uname"`
Gender int64 `json:"gender"`
Usign string `json:"usign"`
Level int64 `json:"level"`
}
// 搜索api通过把触发指令传入的昵称找出uid返回
func search(keyword string) (r []searchResult, err error) {
searchURL := "http://api.bilibili.com/x/web-interface/search/type?search_type=bili_user&keyword=" + keyword
data, err := web.GetData(searchURL)
if err != nil {
return
}
j := gjson.ParseBytes(data)
if j.Get("data.numResults").Int() == 0 {
err = errors.New("查无此人")
return
}
err = json.Unmarshal(binary.StringToBytes(j.Get("data.result").Raw), &r)
if err != nil {
return
}
return
}
type follower struct {
Mid int `json:"mid"`
Uname string `json:"uname"`
Video int `json:"video"`
Roomid int `json:"roomid"`
Rise int `json:"rise"`
Follower int `json:"follower"`
GuardNum int `json:"guardNum"`
AreaRank int `json:"areaRank"`
}
// 请求api
func fansapi(uid string) (result follower, err error) {
fanURL := "https://api.vtbs.moe/v1/detail/" + uid
data, err := web.GetData(fanURL)
if err != nil {
return
}
if err = json.Unmarshal(data, &result); err != nil {
return
}
return
}
func followings(uid string) (s string, err error) {
followingURL := "https://api.bilibili.com/x/relation/same/followings?vmid=" + uid
method := "GET"
client := &http.Client{}
req, err := http.NewRequest(method, followingURL, nil)
if err != nil {
return
}
c := vdb.getBilibiliCookie()
req.Header.Add("cookie", c.Value)
res, err := client.Do(req)
if err != nil {
return
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
return
}
j := gjson.ParseBytes(body)
s = j.Get("data.list.#.uname").Raw
if j.Get("code").Int() == -101 {
err = errNeedCookie
return
}
if j.Get("code").Int() != 0 {
err = errors.New(j.Get("message").String())
return
}
return
}
type userinfo struct {
Name string `json:"name"`
Mid string `json:"mid"`
Face string `json:"face"`
Fans int64 `json:"fans"`
Regtime int64 `json:"regtime"`
Attentions []int64 `json:"attentions"`
}
type medalInfo struct {
Mid int64 `json:"target_id"`
MedalName string `json:"medal_name"`
Level int64 `json:"level"`
MedalColorStart int64 `json:"medal_color_start"`
MedalColorEnd int64 `json:"medal_color_end"`
MedalColorBorder int64 `json:"medal_color_border"`
}
type medal struct {
Uname string `json:"target_name"`
medalInfo `json:"medal_info"`
}
type medalSlice []medal
func (m medalSlice) Len() int {
return len(m)
}
func (m medalSlice) Swap(i, j int) {
m[i], m[j] = m[j], m[i]
}
func (m medalSlice) Less(i, j int) bool {
return m[i].Level > m[j].Level
}
// 获取详情
func card(uid string) (result userinfo, err error) {
cardURL := "https://account.bilibili.com/api/member/getCardByMid?mid=" + uid
data, err := web.GetData(cardURL)
if err != nil {
return
}
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("card").Raw), &result)
if err != nil {
return
}
return
}
// 获得牌子
func medalwall(uid string) (result []medal, err error) {
medalwallURL := "https://api.live.bilibili.com/xlive/web-ucenter/user/MedalWall?target_id=" + uid
method := "GET"
client := &http.Client{}
req, err := http.NewRequest(method, medalwallURL, nil)
if err != nil {
return
}
c := vdb.getBilibiliCookie()
req.Header.Add("cookie", c.Value)
res, err := client.Do(req)
if err != nil {
return
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
return
}
j := gjson.ParseBytes(data)
if j.Get("code").Int() == -101 {
err = errNeedCookie
return
}
if j.Get("code").Int() != 0 {
err = errors.New(j.Get("message").String())
}
_ = json.Unmarshal(binary.StringToBytes(j.Get("data.list").Raw), &result)
return
}

357
plugin/bilibili/info.go Normal file
View File

@@ -0,0 +1,357 @@
// Package bilibili 查询b站用户信息
package bilibili
import (
"encoding/binary"
"fmt"
"image"
"image/color"
"os"
"path"
"regexp"
"sort"
"strconv"
"time"
control "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"
"github.com/FloatTech/zbputils/img/writer"
"github.com/FloatTech/zbputils/web"
"github.com/fogleman/gg"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var engine = control.Register("bilibili", &control.Options{
DisableOnDefault: false,
Help: "bilibili\n" +
"- >vup info [xxx]\n" +
"- >user info [xxx]\n" +
"- 查成分 [xxx]\n" +
"- 设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31\n" +
"- 更新vup",
PublicDataFolder: "Bilibili",
})
var re = regexp.MustCompile(`^\d+$`)
// 查成分的
func init() {
cachePath := engine.DataFolder() + "cache/"
_ = os.RemoveAll(cachePath)
_ = os.MkdirAll(cachePath, 0755)
var getdb = ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
var err error
_, _ = engine.GetLazyData("bilibili.db", false)
vdb, err = initialize(engine.DataFolder() + "bilibili.db")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
return true
})
engine.OnRegex(`^>user info\s?(.{1,25})$`, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]
uidRes, err := search(keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
id := strconv.FormatInt(uidRes[0].Mid, 10)
follwings, err := followings(id)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
}
ctx.SendChain(message.Text(
"search: ", uidRes[0].Mid, "\n",
"name: ", uidRes[0].Uname, "\n",
"sex: ", []string{"", "男", "女", "未知"}[uidRes[0].Gender], "\n",
"sign: ", uidRes[0].Usign, "\n",
"level: ", uidRes[0].Level, "\n",
"follow: ", follwings,
))
})
engine.OnRegex(`^>vup info\s?(.{1,25})$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]
res, err := search(keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
id := strconv.FormatInt(res[0].Mid, 10)
// 获取详情
fo, err := fansapi(id)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text(
"search: ", fo.Mid, "\n",
"名字: ", fo.Uname, "\n",
"当前粉丝数: ", fo.Follower, "\n",
"24h涨粉数: ", fo.Rise, "\n",
"视频投稿数: ", fo.Video, "\n",
"直播间id: ", fo.Roomid, "\n",
"舰队: ", fo.GuardNum, "\n",
"直播总排名: ", fo.AreaRank, "\n",
"数据来源: ", "https://vtbs.moe/detail/", fo.Mid, "\n",
"数据获取时间: ", time.Now().Format("2006-01-02 15:04:05"),
))
})
engine.OnRegex(`^查成分\s?(.{1,25})$`, getdb, getPara).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
id := ctx.State["uid"].(string)
today := time.Now().Format("20060102")
drawedFile := cachePath + id + today + "vupLike.png"
if file.IsExist(drawedFile) {
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
return
}
u, err := card(id)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
vups, err := vdb.filterVup(u.Attentions)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
vupLen := len(vups)
medals, err := medalwall(id)
sort.Sort(medalSlice(medals))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
}
frontVups := make([]vup, 0)
medalMap := make(map[int64]medal)
for _, v := range medals {
up := vup{
Mid: v.Mid,
Uname: v.Uname,
}
frontVups = append(frontVups, up)
medalMap[v.Mid] = v
}
vups = append(vups, frontVups...)
copy(vups[len(frontVups):], vups)
copy(vups, frontVups)
for i := len(frontVups); i < len(vups); i++ {
if _, ok := medalMap[vups[i].Mid]; ok {
vups = append(vups[:i], vups[i+1:]...)
i--
}
}
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
}
if len(vups) > 50 {
ctx.SendChain(message.Text(u.Name + "关注的up主太多了只展示前50个up"))
vups = vups[:50]
}
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, true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
}
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
sl, _ := canvas.MeasureString("好")
length, h := canvas.MeasureString(u.Mid)
n, _ := canvas.MeasureString(u.Name)
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, 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)
canvas.DrawRectangle(0, float64(backY)*1.1+float64(i)*float64(backY)/3, float64(backX*3), float64(backY)/3)
canvas.Fill()
}
canvas.SetColor(color.Black)
nl, _ := canvas.MeasureString(v.Uname)
canvas.DrawString(v.Uname, float64(backX)*0.1, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
ml, _ := canvas.MeasureString(strconv.FormatInt(v.Mid, 10))
canvas.DrawRoundedRectangle(nl-0.1*ml+float64(backX)*0.2, float64(backY)*1.1+float64(i+1)*float64(backY)/3-h*3.5, ml*1.2, h*2, fontSize*0.2)
canvas.SetRGB255(221, 221, 221)
canvas.Fill()
canvas.SetColor(color.Black)
canvas.DrawString(strconv.FormatInt(v.Mid, 10), nl+float64(backX)*0.2, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
if m, ok := medalMap[v.Mid]; ok {
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{R: uint8(r), G: uint8(g), B: uint8(b), A: 255})
r, g, b = int2rbg(m.MedalColorEnd)
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)
canvas.LineTo(nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
canvas.LineTo(nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
canvas.LineTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
canvas.ClosePath()
canvas.Fill()
canvas.SetColor(color.White)
canvas.DrawString(m.MedalName, nl+ml+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
r, g, b = int2rbg(m.MedalColorBorder)
canvas.SetRGB255(int(r), int(g), int(b))
canvas.DrawString(strconv.FormatInt(m.Level, 10), nl+ml+mnl+sl+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
mll, _ := canvas.MeasureString(strconv.FormatInt(m.Level, 10))
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)
canvas.LineTo(nl+ml+mnl+mll+sl/2+float64(backX)*0.5, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
canvas.LineTo(nl+ml+mnl+mll+sl/2+float64(backX)*0.5, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
canvas.LineTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
canvas.ClosePath()
canvas.Stroke()
}
}
f, err := os.Create(drawedFile)
if err != nil {
log.Errorln("[bilibili]", err)
data, cl := writer.ToBytes(canvas.Image())
ctx.SendChain(message.ImageBytes(data))
cl()
return
}
_, err = writer.WriteTo(canvas.Image(), f)
_ = f.Close()
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
})
engine.OnRegex(`^设置b站cookie?\s+(.{1,100})$`, zero.SuperUserPermission, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
cookie := ctx.State["regex_matched"].([]string)[1]
err := vdb.setBilibiliCookie(cookie)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("成功设置b站cookie为" + cookie))
})
engine.OnFullMatch("更新vup", zero.SuperUserPermission, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女祈祷中..."))
err := updateVup()
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("vup已更新"))
})
}
func initFacePic(filename, faceURL string) error {
if file.IsNotExist(filename) {
data, err := web.GetData(faceURL)
if err != nil {
return err
}
err = os.WriteFile(filename, data, 0666)
if err != nil {
return err
}
}
return nil
}
func int2rbg(t int64) (int64, int64, int64) {
var buf [8]byte
binary.LittleEndian.PutUint64(buf[:], uint64(t))
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
}
}
}
}

130
plugin/bilibili/model.go Normal file
View File

@@ -0,0 +1,130 @@
package bilibili
import (
"os"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/web"
_ "github.com/fumiama/sqlite3" // use sql
"github.com/jinzhu/gorm"
"github.com/tidwall/gjson"
)
const (
bilibiliCookie = "bilbili_cookie"
)
var (
vtbURLs = [...]string{"https://api.vtbs.moe/v1/short", "https://api.tokyo.vtbs.moe/v1/short", "https://vtbs.musedash.moe/v1/short"}
vdb *vupdb
)
// vupdb 分数数据库
type vupdb gorm.DB
type vup struct {
Mid int64 `gorm:"column:mid;primary_key"`
Uname string `gorm:"column:uname"`
Roomid int64 `gorm:"column:roomid"`
}
func (vup) TableName() string {
return "vup"
}
type config struct {
Key string `gorm:"column:key;primary_key"`
Value string `gorm:"column:value"`
}
func (config) TableName() string {
return "config"
}
// initialize 初始化vtb数据库
func initialize(dbpath string) (*vupdb, error) {
if _, err := os.Stat(dbpath); err != nil || os.IsNotExist(err) {
// 生成文件
f, err := os.Create(dbpath)
if err != nil {
return nil, err
}
defer f.Close()
}
gdb, err := gorm.Open("sqlite3", dbpath)
if err != nil {
return nil, err
}
gdb.AutoMigrate(&vup{}).AutoMigrate(&config{})
return (*vupdb)(gdb), nil
}
func (vdb *vupdb) insertVupByMid(mid int64, uname string, roomid int64) (err error) {
db := (*gorm.DB)(vdb)
v := vup{
Mid: mid,
Uname: uname,
Roomid: roomid,
}
if err = db.Model(&vup{}).First(&v, "mid = ? ", mid).Error; err != nil {
if gorm.IsRecordNotFoundError(err) {
err = db.Model(&vup{}).Create(&v).Error
}
}
return
}
// filterVup 筛选vup
func (vdb *vupdb) filterVup(ids []int64) (vups []vup, err error) {
db := (*gorm.DB)(vdb)
if err = db.Model(&vup{}).Find(&vups, "mid in (?)", ids).Error; err != nil {
return vups, err
}
return
}
func updateVup() error {
for _, v := range vtbURLs {
data, err := web.GetData(v)
if err != nil {
return err
}
gjson.Get(binary.BytesToString(data), "@this").ForEach(func(key, value gjson.Result) bool {
mid := value.Get("mid").Int()
uname := value.Get("uname").String()
roomid := value.Get("roomid").Int()
err = vdb.insertVupByMid(mid, uname, roomid)
return err == nil
})
if err != nil {
return err
}
}
return nil
}
func (vdb *vupdb) setBilibiliCookie(cookie string) (err error) {
db := (*gorm.DB)(vdb)
c := config{
Key: bilibiliCookie,
Value: cookie,
}
if err = db.Model(&config{}).First(&c, "key = ? ", bilibiliCookie).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
err = db.Model(&config{}).Create(&c).Error
}
} else {
err = db.Model(&config{}).Where("key = ? ", bilibiliCookie).Update(
map[string]interface{}{
"value": cookie,
}).Error
}
return
}
func (vdb *vupdb) getBilibiliCookie() (c config) {
db := (*gorm.DB)(vdb)
db.Model(&config{}).First(&c, "key = ?", bilibiliCookie)
return
}

View File

@@ -7,38 +7,39 @@ import (
"github.com/FloatTech/zbputils/control"
"github.com/antchfx/htmlquery"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
var (
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]+"
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]+)"
)
func init() {
engine := control.Register("bilibiliparse", order.AcquirePrio(), &control.Options{
engine := control.Register("bilibiliparse", &control.Options{
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 | 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 := parseURL(bilibiliURL)
m, err := parseURL(bilibiliURL)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if len(m) != 0 {
ctx.Send(m)
}
})
}
func parseURL(bilibiliURL string) (m message.Message) {
func parseURL(bilibiliURL string) (m message.Message, err error) {
doc, err := htmlquery.LoadURL(bilibiliURL)
if err != nil {
log.Errorln("[bilibiliparse]:访问的链接为", bilibiliURL, ",错误为", err)
return
}
videoURL := htmlquery.FindOne(doc, "/html/head/meta[@itemprop='url']").Attr[2].Val
re := regexp.MustCompile(validRe)
@@ -48,6 +49,9 @@ func parseURL(bilibiliURL string) (m message.Message) {
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"))
@@ -57,10 +61,10 @@ func parseURL(bilibiliURL string) (m message.Message) {
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"))
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("收藏:", strings.TrimSpace(collect)+"分享:", strings.TrimSpace(share)+"\n"))
m = append(m, message.Text(bv))
return
}

View File

@@ -5,22 +5,18 @@ import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"time"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/text"
"github.com/FloatTech/zbputils/web"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/zbputils/control/order"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img/text"
"github.com/FloatTech/zbputils/web"
)
const (
@@ -34,16 +30,20 @@ const (
serviceName = "bilibilipush"
)
// bdb bilibili推送数据库
var bdb *bilibilipushdb
var (
lastTime = map[int64]int64{}
typeMsg = map[int64]string{
1: "转发了一条动态",
2: "有图营业",
4: "无图营业",
8: "发布了新投稿",
16: "发布了短视频",
64: "发布了新专栏",
256: "发布了新音频",
1: "转发了一条动态",
2: "有图营业",
4: "无图营业",
8: "发布了新投稿",
16: "发布了短视频",
64: "发布了新专栏",
256: "发布了新音频",
2048: "发布了新简报",
}
liveStatus = map[int64]int{}
uidErrorMsg = map[int]string{
@@ -57,23 +57,36 @@ var (
func init() {
go bilibiliPushDaily()
en := control.Register(serviceName, order.AcquirePrio(), &control.Options{
en := control.Register(serviceName, &control.Options{
DisableOnDefault: false,
Help: "bilibilipush\n" +
"- 添加订阅[uid]\n" +
"- 取消订阅[uid]\n" +
"- 取消动态订阅[uid]\n" +
"- 取消直播订阅[uid]\n" +
"- 推送列表",
"- 添加b站订阅[uid]\n" +
"- 取消b站订阅[uid]\n" +
"- 取消b站动态订阅[uid]\n" +
"- 取消b站直播订阅[uid]\n" +
"- b站推送列表",
PrivateDataFolder: serviceName,
})
en.OnRegex(`^添加订阅\s?(\d+)$`, ctxext.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
// 加载数据库
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
status, name = checkBuid(buid)
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 {
@@ -88,18 +101,23 @@ func init() {
gid = -ctx.Event.UserID
}
if err := subscribe(buid, gid); err != nil {
log.Errorln("[bilibilipush]:", err)
} else {
ctx.SendChain(message.Text("已添加" + name + "的订阅"))
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("已添加" + name + "的订阅"))
})
en.OnRegex(`^取消订阅\s?(\d+)$`, ctxext.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
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
status, name = checkBuid(buid)
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 {
@@ -114,18 +132,23 @@ func init() {
gid = -ctx.Event.UserID
}
if err := unsubscribe(buid, gid); err != nil {
log.Errorln("[bilibilipush]:", err)
} else {
ctx.SendChain(message.Text("已取消" + name + "的订阅"))
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("已取消" + name + "的订阅"))
})
en.OnRegex(`^取消动态订阅\s?(\d+)$`, ctxext.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
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
status, name = checkBuid(buid)
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 {
@@ -140,18 +163,23 @@ func init() {
gid = -ctx.Event.UserID
}
if err := unsubscribeDynamic(buid, gid); err != nil {
log.Errorln("[bilibilipush]:", err)
} else {
ctx.SendChain(message.Text("已取消" + name + "的动态订阅"))
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("已取消" + name + "的动态订阅"))
})
en.OnRegex(`^取消直播订阅\s?(\d+)$`, ctxext.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
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
status, name = checkBuid(buid)
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 {
@@ -166,23 +194,21 @@ func init() {
gid = -ctx.Event.UserID
}
if err := unsubscribeLive(buid, gid); err != nil {
log.Errorln("[bilibilipush]:", err)
} else {
ctx.SendChain(message.Text("已取消" + name + "的直播订阅"))
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("已取消" + name + "的直播订阅"))
})
en.OnFullMatch("推送列表", ctxext.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
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)
fmt.Println(bpl)
msg := "--------推送列表--------"
msg := "--------b站推送列表--------"
for _, v := range bpl {
if _, ok := upMap[v.BilibiliUID]; !ok {
bdb.updateAllUp()
fmt.Println(upMap)
}
msg += fmt.Sprintf("\nuid:%-12d 动态:", v.BilibiliUID)
if v.DynamicDisable == 0 {
@@ -200,10 +226,11 @@ func init() {
}
data, err := text.RenderToBase64(msg, text.FontFile, 600, 20)
if err != nil {
log.Errorln("[bilibilipush]:", err)
ctx.SendChain(message.Text("ERROR:", err))
return
}
if id := ctx.SendChain(message.Image("base64://" + helper.BytesToString(data))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR:可能被风控了"))
}
})
}
@@ -212,19 +239,19 @@ func bilibiliPushDaily() {
t := time.NewTicker(time.Second * 10)
defer t.Stop()
for range t.C {
log.Println("-----bilibilipush拉取推送信息-----")
sendDynamic()
sendLive()
log.Debugln("-----bilibilipush拉取推送信息-----")
_ = sendDynamic()
_ = sendLive()
}
}
func checkBuid(buid int64) (status int, name string) {
data, err := web.ReqWith(fmt.Sprintf(infoURL, buid), "GET", referer, ua)
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 {
log.Errorln("[bilibilipush]:", err)
return
}
status = int(gjson.Get(helper.BytesToString(data), "code").Int())
name = gjson.Get(helper.BytesToString(data), "data.name").String()
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
@@ -276,50 +303,37 @@ func unsubscribeLive(buid, groupid int64) (err error) {
return
}
func getUserDynamicCard(buid int64) (cardList []gjson.Result) {
data, err := web.ReqWith(fmt.Sprintf(userDynamicURL, buid), "GET", referer, ua)
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 {
log.Errorln("[bilibilipush]:", err)
return
}
cardList = gjson.Get(helper.BytesToString(data), "data.cards").Array()
cardList = gjson.Get(binary.BytesToString(data), "data.cards").Array()
return
}
func getLiveList(uids ...int64) string {
func getLiveList(uids ...int64) (string, error) {
m := make(map[string]interface{})
m["uids"] = uids
b, _ := json.Marshal(m)
client := &http.Client{}
// 提交请求
request, err := http.NewRequest("POST", liveListURL, bytes.NewBuffer(b))
data, err := web.PostData(liveListURL, "application/json", bytes.NewReader(b))
if err != nil {
log.Errorln("[bilibilipush]:", err)
return "", err
}
request.Header.Add("Referer", referer)
request.Header.Add("User-Agent", ua)
response, err := client.Do(request)
if err != nil {
log.Errorln("[bilibilipush]:", err)
}
defer response.Body.Close()
data, err := io.ReadAll(response.Body)
if err != nil {
log.Errorln("[bilibilipush]:", err)
}
return helper.BytesToString(data)
return binary.BytesToString(data), nil
}
func sendDynamic() {
func sendDynamic() error {
uids := bdb.getAllBuidByDynamic()
for _, buid := range uids {
cardList := getUserDynamicCard(buid)
if len(cardList) == 0 {
return
cardList, err := getUserDynamicCard(buid)
if err != nil {
return err
}
t, ok := lastTime[buid]
if !ok {
lastTime[buid] = cardList[0].Get("desc.timestamp").Int()
return
return nil
}
for i := len(cardList) - 1; i >= 0; i-- {
ct := cardList[i].Get("desc.timestamp").Int()
@@ -368,7 +382,7 @@ func sendDynamic() {
msg = append(msg, message.Text(cContent+"\n"))
case 8:
cName := gjson.Get(cOrigin, "owner.name").String()
cTime := time.Unix(gjson.Get(cOrigin, "ctime").Int(), 0).Format("2006-01-02 15:04:05")
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))
@@ -406,6 +420,19 @@ func sendDynamic() {
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"))
}
@@ -467,6 +494,19 @@ func sendDynamic() {
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"))
}
@@ -481,8 +521,6 @@ func sendDynamic() {
ctx.SendGroupMessage(gid, msg)
case gid < 0:
ctx.SendPrivateMessage(-gid, msg)
default:
log.Errorln("[bilibilipush]:gid为0")
}
}
}
@@ -492,11 +530,16 @@ func sendDynamic() {
}
}
}
return nil
}
func sendLive() {
func sendLive() error {
uids := bdb.getAllBuidByLive()
gjson.Get(getLiveList(uids...), "data").ForEach(func(key, value gjson.Result) bool {
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
@@ -535,8 +578,6 @@ func sendLive() {
ctx.SendGroupMessage(gid, msg)
case gid < 0:
ctx.SendPrivateMessage(-gid, msg)
default:
log.Errorln("[bilibilipush]:gid为0")
}
}
}
@@ -548,4 +589,5 @@ func sendLive() {
}
return true
})
return nil
}

View File

@@ -4,8 +4,8 @@ import (
"encoding/json"
"os"
_ "github.com/fumiama/sqlite3" // import sql
"github.com/jinzhu/gorm"
_ "github.com/logoove/sqlite" // import sql
)
// bilibilipushdb bili推送数据库
@@ -59,12 +59,12 @@ func (bdb *bilibilipushdb) insertOrUpdateLiveAndDynamic(bpMap map[string]interfa
bp := bilibilipush{}
data, _ := json.Marshal(&bpMap)
_ = json.Unmarshal(data, &bp)
if err = db.Debug().Model(&bilibilipush{}).First(&bp, "bilibili_uid = ? and group_id = ?", bp.BilibiliUID, bp.GroupID).Error; err != nil {
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.Debug().Model(&bilibilipush{}).Create(&bp).Error
err = db.Model(&bilibilipush{}).Create(&bp).Error
}
} else {
err = db.Debug().Model(&bilibilipush{}).Where("bilibili_uid = ? and group_id = ?", bp.BilibiliUID, bp.GroupID).Update(bpMap).Error
err = db.Model(&bilibilipush{}).Where("bilibili_uid = ? and group_id = ?", bp.BilibiliUID, bp.GroupID).Update(bpMap).Error
}
return
}
@@ -72,7 +72,7 @@ func (bdb *bilibilipushdb) insertOrUpdateLiveAndDynamic(bpMap map[string]interfa
func (bdb *bilibilipushdb) getAllBuidByLive() (buidList []int64) {
db := (*gorm.DB)(bdb)
var bpl []bilibilipush
db.Debug().Model(&bilibilipush{}).Find(&bpl, "live_disable = 0")
db.Model(&bilibilipush{}).Find(&bpl, "live_disable = 0")
temp := make(map[int64]bool)
for _, v := range bpl {
_, ok := temp[v.BilibiliUID]
@@ -87,7 +87,7 @@ func (bdb *bilibilipushdb) getAllBuidByLive() (buidList []int64) {
func (bdb *bilibilipushdb) getAllBuidByDynamic() (buidList []int64) {
db := (*gorm.DB)(bdb)
var bpl []bilibilipush
db.Debug().Model(&bilibilipush{}).Find(&bpl, "dynamic_disable = 0")
db.Model(&bilibilipush{}).Find(&bpl, "dynamic_disable = 0")
temp := make(map[int64]bool)
for _, v := range bpl {
_, ok := temp[v.BilibiliUID]
@@ -102,7 +102,7 @@ func (bdb *bilibilipushdb) getAllBuidByDynamic() (buidList []int64) {
func (bdb *bilibilipushdb) getAllGroupByBuidAndLive(buid int64) (groupList []int64) {
db := (*gorm.DB)(bdb)
var bpl []bilibilipush
db.Debug().Model(&bilibilipush{}).Find(&bpl, "bilibili_uid = ? and live_disable = 0", buid)
db.Model(&bilibilipush{}).Find(&bpl, "bilibili_uid = ? and live_disable = 0", buid)
for _, v := range bpl {
groupList = append(groupList, v.GroupID)
}
@@ -112,7 +112,7 @@ func (bdb *bilibilipushdb) getAllGroupByBuidAndLive(buid int64) (groupList []int
func (bdb *bilibilipushdb) getAllGroupByBuidAndDynamic(buid int64) (groupList []int64) {
db := (*gorm.DB)(bdb)
var bpl []bilibilipush
db.Debug().Model(&bilibilipush{}).Find(&bpl, "bilibili_uid = ? and dynamic_disable = 0", buid)
db.Model(&bilibilipush{}).Find(&bpl, "bilibili_uid = ? and dynamic_disable = 0", buid)
for _, v := range bpl {
groupList = append(groupList, v.GroupID)
}
@@ -121,7 +121,7 @@ func (bdb *bilibilipushdb) getAllGroupByBuidAndDynamic(buid int64) (groupList []
func (bdb *bilibilipushdb) getAllPushByGroup(groupID int64) (bpl []bilibilipush) {
db := (*gorm.DB)(bdb)
db.Debug().Model(&bilibilipush{}).Find(&bpl, "group_id = ? and (live_disable = 0 or dynamic_disable = 0)", groupID)
db.Model(&bilibilipush{}).Find(&bpl, "group_id = ? and (live_disable = 0 or dynamic_disable = 0)", groupID)
return
}
@@ -131,13 +131,13 @@ func (bdb *bilibilipushdb) insertBilibiliUp(buid int64, name string) {
BilibiliUID: buid,
Name: name,
}
db.Debug().Model(&bilibiliup{}).Create(bu)
db.Model(&bilibiliup{}).Create(bu)
}
func (bdb *bilibilipushdb) updateAllUp() {
db := (*gorm.DB)(bdb)
var bul []bilibiliup
db.Debug().Model(&bilibiliup{}).Find(&bul)
db.Model(&bilibiliup{}).Find(&bul)
for _, v := range bul {
upMap[v.BilibiliUID] = v.Name
}

View File

@@ -0,0 +1,66 @@
// Package bookreview 书评
package bookreview
import (
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/text"
)
func init() {
engine := control.Register("bookreview", &control.Options{
DisableOnDefault: false,
Help: "哀伤雪刃推书记录\n- 书评[xxx]\n- 随机书评",
PublicDataFolder: "BookReview",
})
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = engine.DataFolder() + "bookreview.db"
// os.RemoveAll(dbpath)
_, _ = engine.GetLazyData("bookreview.db", true)
err := db.Create("bookreview", &book{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
n, err := db.Count("bookreview")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
log.Infof("[bookreview]读取%d条书评", n)
return true
})
// 中文、英文、数字但不包括下划线等符号
engine.OnRegex("^书评([\u4E00-\u9FA5A-Za-z0-9]{1,25})$", getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
b := getBookReviewByKeyword(ctx.State["regex_matched"].([]string)[1])
data, err := text.RenderToBase64(b.BookReview, text.FontFile, 400, 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:可能被风控了"))
}
})
engine.OnFullMatch("随机书评", getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
br := getRandomBookReview()
data, err := text.RenderToBase64(br.BookReview, text.FontFile, 400, 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:可能被风控了"))
}
})
}

View File

@@ -1,10 +1,14 @@
package bookreview
import sql "github.com/FloatTech/sqlite"
type book struct {
ID uint64 `db:"id"`
BookReview string `db:"bookreview"`
}
var db = &sql.Sqlite{}
// 暂时随机选择一个书评
func getBookReviewByKeyword(keyword string) (b book) {
_ = db.Find("bookreview", &b, "where bookreview LIKE '%"+keyword+"%'")

View File

@@ -11,12 +11,9 @@ import (
control "github.com/FloatTech/zbputils/control"
"github.com/antchfx/htmlquery"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/zbputils/control/order"
)
const (
@@ -32,92 +29,110 @@ var (
)
func init() {
engine := control.Register("cangtoushi", order.AcquirePrio(), &control.Options{
engine := control.Register("cangtoushi", &control.Options{
DisableOnDefault: false,
Help: "藏头诗\n" +
"- 藏头诗[xxx]\n- 藏尾诗[xxx]",
})
engine.OnRegex(`藏头诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
kw := ctx.State["regex_matched"].([]string)[1]
login()
err := login()
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
data, err := search(kw, "7", "0")
if err != nil {
log.Errorln("[cangtoushi]:", err)
ctx.SendChain(message.Text("ERROR:", err))
return
}
text, err := dealHTML(helper.BytesToString(data))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
text := dealHTML(helper.BytesToString(data))
ctx.SendChain(message.Text(text))
})
engine.OnRegex(`藏尾诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
kw := ctx.State["regex_matched"].([]string)[1]
login()
err := login()
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
data, err := search(kw, "7", "2")
if err != nil {
log.Errorln("[cangtoushi]:", err)
ctx.SendChain(message.Text("ERROR:", err))
return
}
text, err := dealHTML(helper.BytesToString(data))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
text := dealHTML(helper.BytesToString(data))
ctx.SendChain(message.Text(text))
})
}
func login() {
func login() error {
gCurCookieJar, _ = cookiejar.New(nil)
client := &http.Client{
Jar: gCurCookieJar,
}
request, err := http.NewRequest("GET", loginURL, nil)
if err != nil {
log.Errorln("[cangtoushi]:", err)
return err
}
request.Header.Add("User-Agent", ua)
response, err := client.Do(request)
if err != nil {
log.Errorln("[cangtoushi]:", err)
return err
}
data, err := io.ReadAll(response.Body)
if err != nil {
log.Errorln("[cangtoushi]:", err)
return err
}
response.Body.Close()
doc, err := htmlquery.Parse(strings.NewReader(helper.BytesToString(data)))
if err != nil {
log.Errorln("[cangtoushi]:", err)
return err
}
csrf = htmlquery.SelectAttr(htmlquery.FindOne(doc, "//input[@name='_csrf']"), "value")
return nil
}
func search(kw, zishu, position string) (data []byte, err error) {
postStr := fmt.Sprintf("_csrf=%s&kw=%s&zishu=%s&position=%s", url.QueryEscape(csrf), url.QueryEscape(kw), zishu, position)
log.Println("postStr:", postStr)
client := &http.Client{
Jar: gCurCookieJar,
}
request, err := http.NewRequest("POST", searchURL, strings.NewReader(postStr))
if err != nil {
log.Errorln("[cangtoushi]:", err)
return nil, err
}
request.Header.Add("Referer", referer)
request.Header.Add("User-Agent", ua)
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
response, err := client.Do(request)
if err != nil {
log.Errorln("[cangtoushi]:", err)
return nil, err
}
data, err = io.ReadAll(response.Body)
if err != nil {
log.Errorln("[cangtoushi]:", err)
return nil, err
}
response.Body.Close()
return
}
func dealHTML(data string) (text string) {
func dealHTML(data string) (text string, err error) {
doc, err := htmlquery.Parse(strings.NewReader(data))
if err != nil {
log.Errorln("[cangtoushi]:", err)
return "", err
}
text = htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@class='card']/div[@class='card']"))
text = strings.ReplaceAll(text, " ", "")
text = strings.Replace(text, "\n", "", 1)
return text
return text, nil
}

View File

@@ -10,23 +10,14 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
const (
dbpath = "data/Chat/"
dbfile = dbpath + "kimoi.json"
)
var (
poke = rate.NewManager(time.Minute*5, 8) // 戳一戳
engine = control.Register("chat", order.AcquirePrio(), &control.Options{
poke = rate.NewManager[int64](time.Minute*5, 8) // 戳一戳
engine = control.Register("chat", &control.Options{
DisableOnDefault: false,
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]\n- mua | 啾咪 | 摸 | 上你 | 傻 | 裸 | 贴 | 老婆 | 抱 | 亲 | 一下 | 咬 | 操 | 123 | 进去 | 调教 | 搓 | 让 | 捏 | 挤 | 略 | 呐 | 原味 | 胖次 | 内裤 | 内衣 | 衣服 | ghs | 批 | 憨批 | kkp | 咕 | 骚 | 喜欢 | suki | 好き | 看 | 不能 | 砸了 | 透 | 口我 | 草我 | 自慰 | onani | オナニー | 炸了 | 色图 | 涩图 | 告白 | 对不起 | 回来 | 吻 | 软 | 壁咚 | 掰开 | 女友 | 是 | 喵 | 嗷呜 | 叫 | 拜 | 佬 | awsl | 臭 | 香 | 腿 | 张开 | 脚 | 脸 | 头发 | 手 | pr | 舔 | 小穴 | 腰 | 诶嘿嘿 | 可爱 | 扭蛋 | 鼻 | 眼 | 色气 | 推 | 床 | 举 | 手冲 | 饿 | 变 | 敲 | 爬 | 怕 | 冲 | 射 | 不穿 | 迫害 | 猫粮 | 揪尾巴 | 薄荷 | 早 | 晚安 | 揉 | 榨 | 掐 | 胸 | 奶子 | 欧派 | 嫩 | 蹭 | 牵手 | 握手 | 拍照 | w | 睡不着 | 欧尼酱 | 哥 | 爱你 | 过来 | 自闭 | 打不过 | 么么哒 | 很懂 | 膝枕 | 累了 | 安慰 | 洗澡 | 一起睡觉 | 一起 | 多大 | 姐姐 | 糖 | 嗦 | 牛子 | 🐂子 | 🐮子 | 嫌弃 | 紧 | baka | 笨蛋 | 插 | 插进来 | 屁股 | 翘 | 翘起来 | 抬 | 抬起 | 爸 | 傲娇 | rua | 咕噜咕噜 | 咕噜 | 上床 | 做爱 | 吃掉 | 吃 | 揪 | 种草莓 | 种草 | 掀 | 妹 | 病娇 | 嘻",
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]",
})
kimomap = make(kimo, 256)
chatList = make([]string, 0, 256)
)
func init() { // 插件主体
@@ -111,13 +102,4 @@ func init() { // 插件主体
))
}
})
initChatList(func() {
engine.OnFullMatchGroup(chatList, zero.OnlyToMe).SetBlock(true).Handle(
func(ctx *zero.Ctx) {
key := ctx.MessageString()
val := *kimomap[key]
text := val[rand.Intn(len(val))]
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
})
})
}

View File

@@ -9,12 +9,10 @@ import (
control "github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
func init() {
engine := control.Register("choose", order.AcquirePrio(), &control.Options{
engine := control.Register("choose", &control.Options{
DisableOnDefault: false,
Help: "choose\n" +
"- 选择可口可乐还是百事可乐\n" +

View File

@@ -0,0 +1,64 @@
// Package chouxianghua 抽象话转化
package chouxianghua
import (
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
)
func init() {
en := control.Register("chouxianghua", &control.Options{
DisableOnDefault: false,
Help: "抽象话\n- 抽象翻译xxx",
PublicDataFolder: "ChouXiangHua",
})
en.OnRegex("^抽象翻译((\\s|[\\r\\n]|[\\p{Han}\\p{P}A-Za-z0-9])+)$",
ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = en.DataFolder() + "cxh.db"
// os.RemoveAll(dbpath)
_, _ = en.GetLazyData("cxh.db", true)
err := db.Create("pinyin", &pinyin{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
n, err := db.Count("pinyin")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
logrus.Printf("[chouxianghua]读取%d条拼音", n)
return true
}),
).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
r := cx(ctx.State["regex_matched"].([]string)[1])
ctx.SendChain(message.Text(r))
})
}
func cx(s string) (r string) {
h := []rune(s)
for i := 0; i < len(h); i++ {
if i < len(h)-1 {
e := getEmojiByPronun(getPronunByDWord(h[i], h[i+1]))
if e != "" {
r += e
i++
continue
}
}
e := getEmojiByPronun(getPinyinByWord(string(h[i])))
if e != "" {
r += e
continue
}
r += string(h[i])
}
return
}

View File

@@ -1,5 +1,7 @@
package chouxianghua
import sql "github.com/FloatTech/sqlite"
type pinyin struct {
Word string `db:"word"`
Pronun string `db:"pronunciation"`
@@ -9,6 +11,8 @@ type emoji struct {
Emoji string `db:"emoji"`
}
var db = &sql.Sqlite{}
func getPinyinByWord(word string) string {
var p pinyin
_ = db.Find("pinyin", &p, "where word = '"+word+"'")

View File

@@ -2,9 +2,10 @@
package coser
import (
"regexp"
"github.com/tidwall/gjson"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
@@ -12,50 +13,43 @@ import (
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
"github.com/FloatTech/zbputils/control/order"
)
var (
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36"
coserURL = "http://ovooa.com/API/cosplay/api.php"
datestr = regexp.MustCompile(`/\d{4}-\d{2}-\d{2}/`)
)
func init() {
control.Register("coser", order.AcquirePrio(), &control.Options{
control.Register("coser", &control.Options{
DisableOnDefault: false,
Help: "三次元小姐姐\n- coser",
}).ApplySingle(ctxext.DefaultSingle).OnFullMatch("coser", zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女祈祷中......"))
data, err := web.ReqWith(coserURL, "GET", "", ua)
data, err := web.RequestDataWith(web.NewDefaultClient(), coserURL, "GET", "", ua)
if err != nil {
log.Println("err为:", err)
ctx.SendChain(message.Text("ERROR:", err))
return
}
var m message.Message
text := gjson.Get(helper.BytesToString(data), "data.Title").String()
m = append(m,
message.CustomNode(
ctx.Event.Sender.NickName,
ctx.Event.UserID,
text,
))
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text(text))}
ds := ""
gjson.Get(helper.BytesToString(data), "data.data").ForEach(func(_, value gjson.Result) bool {
m = append(m,
message.CustomNode(
ctx.Event.Sender.NickName,
ctx.Event.UserID,
[]message.MessageSegment{
message.Image(value.String()),
}),
)
if ds == "" {
ds = datestr.FindString(value.String())
} else if ds != datestr.FindString(value.String()) {
return false
}
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Image(value.String())))
return true
})
if id := ctx.SendGroupForwardMessage(
ctx.Event.GroupID,
m).Get("message_id").Int(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控"))
ctx.SendChain(message.Text("ERROR:可能被风控或下载图片用时过长,请耐心等待"))
}
})
}

View File

@@ -4,32 +4,51 @@ package cpstory
import (
"strings"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/math"
"github.com/FloatTech/zbputils/control/order"
)
func init() {
engine := control.Register("cpstory", order.AcquirePrio(), &control.Options{
engine := control.Register("cpstory", &control.Options{
DisableOnDefault: false,
Help: "cp短打\n- 组cp[@xxx][@xxx]\n- 磕cp大老师 雪乃",
PublicDataFolder: "CpStory",
})
engine.OnRegex("^组cp.*?(\\d+).*?(\\d+)", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = engine.DataFolder() + "cp.db"
// os.RemoveAll(dbpath)
_, _ = engine.GetLazyData("cp.db", true)
err := db.Create("cp_story", &cpstory{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
n, err := db.Count("cp_story")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
logrus.Printf("[cpstory]读取%d条故事", n)
return true
})
engine.OnRegex("^组cp.*?(\\d+).*?(\\d+)", zero.OnlyGroup, getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
cs := getRandomCpStory()
gong := ctxext.CardOrNickName(ctx, math.Str2Int64(ctx.State["regex_matched"].([]string)[1]))
shou := ctxext.CardOrNickName(ctx, math.Str2Int64(ctx.State["regex_matched"].([]string)[2]))
gong := ctx.CardOrNickName(math.Str2Int64(ctx.State["regex_matched"].([]string)[1]))
shou := ctx.CardOrNickName(math.Str2Int64(ctx.State["regex_matched"].([]string)[2]))
text := strings.ReplaceAll(cs.Story, "<攻>", gong)
text = strings.ReplaceAll(text, "<受>", shou)
text = strings.ReplaceAll(text, cs.Gong, gong)
text = strings.ReplaceAll(text, cs.Shou, gong)
ctx.SendChain(message.Text(text))
})
engine.OnPrefix("磕cp").SetBlock(true).Handle(func(ctx *zero.Ctx) {
engine.OnPrefix("磕cp", getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {
cs := getRandomCpStory()
params := strings.Split(ctx.State["args"].(string), " ")
if len(params) < 2 {

View File

@@ -1,5 +1,7 @@
package cpstory
import sql "github.com/FloatTech/sqlite"
type cpstory struct {
ID int64 `db:"id"`
Gong string `db:"gong"`
@@ -7,6 +9,8 @@ type cpstory struct {
Story string `db:"story"`
}
var db = &sql.Sqlite{}
func getRandomCpStory() (cs cpstory) {
_ = db.Pick("cp_story", &cs)
return

View File

@@ -2,14 +2,13 @@
package curse
import (
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/control/order"
)
const (
@@ -18,24 +17,46 @@ const (
)
func init() {
engine := control.Register("curse", order.AcquirePrio(), &control.Options{
engine := control.Register("curse", &control.Options{
DisableOnDefault: true,
Help: "骂人(求骂,自卫)\n- 骂我\n- 大力骂我",
PublicDataFolder: "Curse",
})
engine.OnFullMatch("骂我").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
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.Create("curse", &curse{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
c, err := db.Count("curse")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
logrus.Infoln("[curse]加载", c, "条骂人语录")
return true
})
engine.OnFullMatch("骂我", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
text := getRandomCurseByLevel(minLevel).Text
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
})
engine.OnFullMatch("大力骂我").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
engine.OnFullMatch("大力骂我", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
text := getRandomCurseByLevel(maxLevel).Text
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))
})
engine.OnKeywordGroup([]string{"他妈", "公交车", "你妈", "操", "屎", "去死", "快死", "我日", "逼", "尼玛", "艾滋", "癌症", "有病", "烦你", "你爹", "屮", "cnm"}, zero.OnlyToMe).SetBlock(true).
engine.OnKeywordGroup([]string{"他妈", "公交车", "你妈", "操", "屎", "去死", "快死", "我日", "逼", "尼玛", "艾滋", "癌症", "有病", "烦你", "你爹", "屮", "cnm"}, zero.OnlyToMe, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
text := getRandomCurseByLevel(maxLevel).Text
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(text))

View File

@@ -1,11 +1,15 @@
package curse
import sql "github.com/FloatTech/sqlite"
type curse struct {
ID uint32 `db:"id"`
Text string `db:"text"`
Level string `db:"level"`
}
var db = &sql.Sqlite{}
func getRandomCurseByLevel(level string) (c curse) {
_ = db.Find("curse", &c, "where level = '"+level+"' ORDER BY RANDOM() limit 1")
return

View File

@@ -4,53 +4,38 @@ package deepdanbooru
import (
"crypto/md5"
"encoding/hex"
"os"
"github.com/FloatTech/AnimeAPI/danbooru"
"github.com/FloatTech/AnimeAPI/saucenao"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img/writer"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/zbputils/control/order"
)
const cachefile = "data/danbooru/"
func init() { // 插件主体
_ = os.RemoveAll(cachefile)
err := os.MkdirAll(cachefile, 0755)
if err != nil {
panic(err)
}
engine := control.Register("danbooru", order.AcquirePrio(), &control.Options{
engine := control.Register("danbooru", &control.Options{
DisableOnDefault: false,
Help: "二次元图片标签识别\n" +
"- 鉴赏图片[图片]",
PrivateDataFolder: "danbooru",
})
cachefolder := engine.DataFolder()
// 上传一张图进行评价
engine.OnKeywordGroup([]string{"鉴赏图片"}, zero.OnlyGroup, ctxext.MustProvidePicture).SetBlock(true).
engine.OnKeywordGroup([]string{"鉴赏图片"}, zero.OnlyGroup, zero.MustProvidePicture).SetBlock(true).
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
}
digest := md5.Sum(helper.StringToBytes(url))
f := cachefile + hex.EncodeToString(digest[:])
f := cachefolder + hex.EncodeToString(digest[:])
if file.IsNotExist(f) {
_ = writer.SavePNG2Path(f, t)
}

View File

@@ -2,48 +2,53 @@
package diana
import (
"math/rand"
"time"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/control/order"
"github.com/FloatTech/ZeroBot-Plugin/plugin_diana/data"
"github.com/FloatTech/ZeroBot-Plugin/plugin/diana/data"
)
var engine = control.Register("diana", order.AcquirePrio(), &control.Options{
var engine = control.Register("diana", &control.Options{
DisableOnDefault: false,
Help: "嘉然\n" +
"- 小作文\n" +
"- 发大病\n" +
"- 教你一篇小作文[作文]\n" +
"- [回复]查重",
PublicDataFolder: "Diana",
})
func init() {
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
err := data.LoadText(engine.DataFolder() + "text.db")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
return true
})
// 随机发送一篇上面的小作文
engine.OnFullMatch("小作文").SetBlock(true).
engine.OnFullMatch("小作文", getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
rand.Seed(time.Now().UnixNano())
// 绕过第一行发病
ctx.SendChain(message.Text(data.RandText()))
})
// 逆天
engine.OnFullMatch("发大病").SetBlock(true).
engine.OnFullMatch("发大病", getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 第一行是发病
ctx.SendChain(message.Text(data.HentaiText()))
})
// 增加小作文
engine.OnRegex(`^教你一篇小作文(.*)$`, zero.AdminPermission).SetBlock(true).
engine.OnRegex(`^教你一篇小作文(.*)$`, zero.AdminPermission, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
err := data.AddText(ctx.State["regex_matched"].([]string)[1])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
ctx.SendChain(message.Text("ERROR:", err))
} else {
ctx.SendChain(message.Text("记住啦!"))
}

65
plugin/diana/data/text.go Normal file
View File

@@ -0,0 +1,65 @@
// Package data 加载位于 datapath 的小作文
package data
import (
"crypto/md5"
"encoding/binary"
sql "github.com/FloatTech/sqlite"
binutils "github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/file"
"github.com/sirupsen/logrus"
)
var db = sql.Sqlite{}
type text struct {
ID int64 `db:"id"`
Data string `db:"data"`
}
// LoadText 加载小作文
func LoadText(dbfile string) error {
_, err := file.GetLazyData(dbfile, false)
db.DBPath = dbfile
if err != nil {
return err
}
err = db.Create("text", &text{})
if err != nil {
return err
}
c, err := db.Count("text")
if err != nil {
return err
}
logrus.Printf("[Diana]读取%d条小作文", c)
return nil
}
// AddText 添加小作文
func AddText(txt string) error {
s := md5.Sum(binutils.StringToBytes(txt))
i := binary.LittleEndian.Uint64(s[:8])
return db.Insert("text", &text{ID: int64(i), Data: txt})
}
// RandText 随机小作文
func RandText() string {
var t text
err := db.Pick("text", &t)
if err != nil {
return err.Error()
}
return t.Data
}
// HentaiText 发大病
func HentaiText() string {
var t text
err := db.Find("text", &t, "where id = -3802576048116006195")
if err != nil {
return err.Error()
}
return t.Data
}

89
plugin/diana/zhiwang.go Normal file
View File

@@ -0,0 +1,89 @@
// Package diana 嘉然相关
package diana
import (
"bytes"
"math"
"strings"
"time"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
"github.com/tidwall/gjson"
"github.com/wdvxdr1123/ZeroBot/message"
zero "github.com/wdvxdr1123/ZeroBot"
)
// 小作文查重: 回复要查的消息 查重
func init() {
engine.OnMessage(func(ctx *zero.Ctx) bool {
msg := ctx.Event.Message
if msg[0].Type != "reply" {
return false
}
for _, elem := range msg {
if elem.Type == "text" {
text := elem.Data["text"]
text = strings.ReplaceAll(text, " ", "")
text = strings.ReplaceAll(text, "\r", "")
text = strings.ReplaceAll(text, "\n", "")
if text == "查重" {
return true
}
}
}
return false
}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
msg := ctx.GetMessage(message.NewMessageIDFromString(ctx.Event.Message[0].Data["id"])).Elements[0].Data["text"]
result, err := zhiwangapi(msg)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if result.Get("code").Int() != 0 {
ctx.SendChain(message.Text("api返回错误:", result.Get("code").Int()))
return
}
if result.Get("data.related.#").Int() == 0 {
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("枝网没搜到查重率为0%,鉴定为原创")))
return
}
related := result.Get("data.related.0.reply").Map()
rate := result.Get("data.related.0.rate").Float()
relatedcontent := related["content"].String()
if len(relatedcontent) > 102 {
relatedcontent = relatedcontent[:102] + "....."
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(
"枝网文本复制检测报告(简洁)", "\n",
"查重时间: ", time.Now().Format("2006-01-02 15:04:05"), "\n",
"总文字复制比: ", math.Floor(rate*100), "%", "\n",
"相似小作文:", "\n", relatedcontent, "\n",
"获赞数:", related["like_num"].String(), "\n",
result.Get("data.related.0.reply_url").String(), "\n",
"作者: ", related["m_name"].String(), "\n",
"发表时间: ", time.Unix(int64(related["ctime"].Float()), 0).Format("2006-01-02 15:04:05"), "\n",
"查重结果仅作参考,请注意辨别是否为原创", "\n",
"数据来源: https://asoulcnki.asia/",
)))
})
}
func zhiwangapi(text string) (*gjson.Result, error) {
b, cl := binary.OpenWriterF(func(w *binary.Writer) {
w.WriteString("{\n\"text\":\"")
w.WriteString(text)
w.WriteString("\"\n}")
})
data, err := web.PostData("https://asoulcnki.asia/v1/api/check", "application/json", bytes.NewReader(b))
cl()
if err != nil {
return nil, err
}
result := gjson.ParseBytes(data)
return &result, nil
}

View File

@@ -0,0 +1,53 @@
package driftbottle
import (
"fmt"
"hash/crc64"
"strconv"
"sync"
sql "github.com/FloatTech/sqlite"
"github.com/FloatTech/zbputils/binary"
)
type bottle struct {
ID int64 `db:"id"` // ID qq_grp_name_msg 的 crc64
QQ int64 `db:"qq"` // QQ 发送者 qq
Grp int64 `db:"grp"` // Grp 限制抽出的群 / 人(负数)
Name string `db:"name"` // Name 发送者 昵称
Msg string `db:"msg"` // Msg 消息,纯文本
}
var sea = &sql.Sqlite{}
var seamu sync.RWMutex
func newBottle(qq, grp int64, name, msg string) *bottle {
id := int64(crc64.Checksum(binary.StringToBytes(fmt.Sprintf("%d_%d_%s_%s", qq, grp, name, msg)), crc64.MakeTable(crc64.ISO)))
return &bottle{ID: id, QQ: qq, Grp: grp, Name: name, Msg: msg}
}
func (b *bottle) throw(db *sql.Sqlite, channel string) error {
seamu.Lock()
defer seamu.Unlock()
return db.Insert(channel, b)
}
func (b *bottle) destroy(db *sql.Sqlite, channel string) error {
seamu.Lock()
defer seamu.Unlock()
return db.Del(channel, "WHERE id="+strconv.FormatInt(b.ID, 10))
}
// fetchBottle grp != 0
func fetchBottle(db *sql.Sqlite, channel string, grp int64) (*bottle, error) {
seamu.RLock()
defer seamu.RUnlock()
b := new(bottle)
return b, db.Find(channel, b, "WHERE grp=0 or grp="+strconv.FormatInt(grp, 10)+" ORDER BY RANDOM() limit 1")
}
func createChannel(db *sql.Sqlite, channel string) error {
seamu.Lock()
defer seamu.Unlock()
return db.Create(channel, &bottle{})
}

131
plugin/drift_bottle/main.go Normal file
View File

@@ -0,0 +1,131 @@
// Package driftbottle 漂流瓶
package driftbottle
import (
"strconv"
"strings"
"sync"
"github.com/FloatTech/zbputils/control"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
en := control.Register("driftbottle", &control.Options{
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()
if err != nil {
panic(err)
}
_ = createChannel(sea, "global")
en.OnRegex(`^(在群\d+)?丢漂流瓶(到频道\w+)?\s+(.*)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
msgs := ctx.State["regex_matched"].([]string)
grp := ctx.Event.GroupID
channel := "global"
msg := msgs[3]
var err error
if msgs[1] != "" {
grp, err = strconv.ParseInt(msgs[1][6:], 10, 64)
if err != nil {
ctx.SendChain(message.Text("群号非法!"))
return
}
}
if msgs[2] != "" {
channel = msgs[2][9:]
}
if msg == "" {
ctx.SendChain(message.Text("消息为空!"))
return
}
logrus.Debugln("[driftbottle]", grp, channel, msg)
err = newBottle(
ctx.Event.UserID,
grp,
ctx.CardOrNickName(ctx.Event.UserID),
msg,
).throw(sea, channel)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你将它扔进大海,希望有人捞到吧~")))
})
en.OnRegex(`^(从频道\w+)?捡漂流瓶$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
msgs := ctx.State["regex_matched"].([]string)
grp := ctx.Event.GroupID
if grp == 0 {
grp = -ctx.Event.UserID
}
if grp == 0 {
ctx.SendChain(message.Text("找不到对象!"))
return
}
channel := "global"
if msgs[1] != "" {
channel = msgs[1][9:]
}
logrus.Debugln("[driftbottle]", grp, channel)
b, err := fetchBottle(sea, channel, grp)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
err = b.destroy(sea, channel)
wg.Done()
}()
ctx.Send(
message.ReplyWithMessage(
ctx.Event.MessageID,
message.Text("你在海边捡到了一个来自 ", b.Name, " 的漂流瓶,打开瓶子,里面有一张纸条,写着:"),
message.Text(b.Msg),
),
)
wg.Wait()
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
})
en.OnPrefix("创建频道", zero.SuperUserPermission, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
channel := strings.TrimRight(ctx.State["args"].(string), " ")
if channel == "" {
ctx.SendChain(message.Text("频道名为空!"))
return
}
err := createChannel(sea, channel)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("成功~")))
})
en.OnRegex(`^跳入(\w+)?海中$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
msgs := ctx.State["regex_matched"].([]string)
channel := "global"
if msgs[1] != "" {
channel = msgs[1]
}
seamu.RLock()
c, err := sea.Count(channel)
seamu.RUnlock()
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你缓缓走入大海,感受着海浪轻柔地拍打着你的小腿,膝盖……\n波浪卷着你的腰腹你感觉有些把握不住平衡了……\n……\n你沉入海中", c, " 个物体与你一同沉浮。\n不知何处涌来一股暗流你失去了意识。")))
})
}

249
plugin/emojimix/emoji.go Normal file
View File

@@ -0,0 +1,249 @@
// Package emojimix 合成emoji
package emojimix
var emojis = map[rune]int64{
128516: 20201001, // 😄 grinning face with smiling eyes
128512: 20201001, // 😀 grinning face
128578: 20201001, // 🙂 slightly smiling face
128579: 20201001, // 🙃 upside-down face
128521: 20201001, // 😉 winking face
128522: 20201001, // 😊 smiling face with smiling eyes
128518: 20201001, // 😆 grinning squinting face
128515: 20201001, // 😃 grinning face with big eyes
128513: 20201001, // 😁 beaming face with smiling eyes
129315: 20201001, // 🤣 rolling on the floor laughing
128517: 20201001, // 😅 grinning face with sweat
128514: 20201001, // 😂 face with tears of joy
128519: 20201001, // 😇 smiling face with halo
129392: 20201001, // 🥰 smiling face with hearts
128525: 20201001, // 😍 smiling face with heart-eyes
128536: 20201001, // 😘 face blowing a kiss
129321: 20201001, // 🤩 star-struck
128535: 20201001, // 😗 kissing face
128538: 20201001, // 😚 kissing face with closed eyes
128537: 20201001, // 😙 kissing face with smiling eyes
128539: 20201001, // 😛 face with tongue
128541: 20201001, // 😝 squinting face with tongue
128523: 20201001, // 😋 face savoring food
129394: 20201001, // 🥲 smiling face with tear
129297: 20201001, // 🤑 money-mouth face
128540: 20201001, // 😜 winking face with tongue
129303: 20201001, // 🤗 smiling face with open hands hugs
129323: 20201001, // 🤫 shushing face quiet whisper
129300: 20201001, // 🤔 thinking face question hmmm
129325: 20201001, // 🤭 face with hand over mouth embarrassed
129320: 20201001, // 🤨 face with raised eyebrow question
129296: 20201001, // 🤐 zipper-mouth face
128528: 20201001, // 😐 neutral face
128529: 20201001, // 😑 expressionless face
128566: 20201001, // 😶 face without mouth
129322: 20201001, // 🤪 zany face
128527: 20201001, // 😏 smirking face suspicious
128530: 20201001, // 😒 unamused face
128580: 20201001, // 🙄 face with rolling eyes
128556: 20201001, // 😬 grimacing face
128558: 20210218, // 😮 face exhaling
129317: 20201001, // 🤥 lying face
128524: 20201001, // 😌 relieved face
128532: 20201001, // 😔 pensive face
128554: 20201001, // 😪 sleepy face
129316: 20201001, // 🤤 drooling face
128564: 20201001, // 😴 sleeping face
128567: 20201001, // 😷 face with medical mask
129298: 20201001, // 🤒 face with thermometer
129301: 20201001, // 🤕 face with head-bandage
129314: 20201001, // 🤢 nauseated face
129326: 20201001, // 🤮 face vomiting throw
129319: 20201001, // 🤧 sneezing face
129397: 20201001, // 🥵 hot face warm
129398: 20201001, // 🥶 cold face freezing ice
128565: 20201001, // 😵 face with crossed-out eyes
129396: 20201001, // 🥴 woozy face drunk tipsy drug high
129327: 20201001, // 🤯 exploding head mindblow
129312: 20201001, // 🤠 cowboy hat face
129395: 20201001, // 🥳 partying face
129400: 20201001, // 🥸 disguised face
129488: 20201001, // 🧐 face with monocle glasses
128526: 20201001, // 😎 smiling face with sunglasses
128533: 20201001, // 😕 confused face
128543: 20201001, // 😟 worried face
128577: 20201001, // 🙁 slightly frowning face
128559: 20201001, // 😯 hushed face
128562: 20201001, // 😲 astonished face
129299: 20201001, // 🤓 nerd face glasses
128563: 20201001, // 😳 flushed face
129402: 20201001, // 🥺 pleading face
128551: 20201001, // 😧 anguished face
128552: 20201001, // 😨 fearful face
128550: 20201001, // 😦 frowning face with open mouth
128560: 20201001, // 😰 anxious face with sweat
128549: 20201001, // 😥 sad but relieved face
128557: 20201001, // 😭 loudly crying face
128553: 20201001, // 😩 weary face
128546: 20201001, // 😢 crying face
128547: 20201001, // 😣 persevering face
128544: 20201001, // 😠 angry face
128531: 20201001, // 😓 downcast face with sweat
128534: 20201001, // 😖 confounded face
129324: 20201001, // 🤬 face with symbols on mouth
128542: 20201001, // 😞 disappointed face
128555: 20201001, // 😫 tired face
128548: 20201001, // 😤 face with steam from nose
129393: 20201001, // 🥱 yawning face
128169: 20201001, // 💩 pile of poo
128545: 20201001, // 😡 pouting face
128561: 20201001, // 😱 face screaming in fear
128127: 20201001, // 👿 angry face with horns
128128: 20201001, // 💀 skull
128125: 20201001, // 👽 alien
128520: 20201001, // 😈 smiling face with horns devil
129313: 20201001, // 🤡 clown face
128123: 20201001, // 👻 ghost
129302: 20201001, // 🤖 robot
128175: 20201001, // 💯 hundred points percent
128064: 20201001, // 👀 eyes
127801: 20201001, // 🌹 rose flower
127804: 20201001, // 🌼 blossom flower
127799: 20201001, // 🌷 tulip flower
127797: 20201001, // 🌵 cactus
127821: 20201001, // 🍍 pineapple
127874: 20201001, // 🎂 birthday cake
127751: 20210831, // 🌇 sunset
129473: 20201001, // 🧁 cupcake muffin
127911: 20210521, // 🎧 headphone earphone
127800: 20210218, // 🌸 cherry blossom flower
129440: 20201001, // 🦠 microbe germ bacteria virus covid corona
128144: 20201001, // 💐 bouquet flowers
127789: 20201001, // 🌭 hot dog food
128139: 20201001, // 💋 kiss mark lips
127875: 20201001, // 🎃 jack-o-lantern pumpkin
129472: 20201001, // 🧀 cheese wedge
9749: 20201001, // ☕ hot beverage coffee cup tea
127882: 20201001, // 🎊 confetti ball
127880: 20201001, // 🎈 balloon
9924: 20201001, // ⛄ snowman without snow
128142: 20201001, // 💎 gem stone crystal diamond
127794: 20201001, // 🌲 evergreen tree
129410: 20210218, // 🦂 scorpion
128584: 20201001, // 🙈 see-no-evil monkey
128148: 20201001, // 💔 broken heart
128140: 20201001, // 💌 love letter heart
128152: 20201001, // 💘 heart with arrow
128159: 20201001, // 💟 heart decoration
128158: 20201001, // 💞 revolving hearts
128147: 20201001, // 💓 beating heart
128149: 20201001, // 💕 two hearts
128151: 20201001, // 💗 growing heart
129505: 20201001, // 🧡 orange heart
128155: 20201001, // 💛 yellow heart
10084: 20210218, // ❤ mending heart
128156: 20201001, // 💜 purple heart
128154: 20201001, // 💚 green heart
128153: 20201001, // 💙 blue heart
129294: 20201001, // 🤎 brown heart
129293: 20201001, // 🤍 white heart
128420: 20201001, // 🖤 black heart
128150: 20201001, // 💖 sparkling heart
128157: 20201001, // 💝 heart with ribbon
127873: 20211115, // 🎁 wrapped-gift
129717: 20211115, // 🪵 wood
127942: 20211115, // 🏆 trophy
127838: 20210831, // 🍞 bread
128240: 20201001, // 📰 newspaper
128302: 20201001, // 🔮 crystal ball
128081: 20201001, // 👑 crown
128055: 20201001, // 🐷 pig face
129412: 20210831, // 🦄 unicorn
127771: 20201001, // 🌛 first quarter moon face
129420: 20201001, // 🦌 deer
129668: 20210521, // 🪄 magic wand
128171: 20201001, // 💫 dizzy
128049: 20201001, // 🐱 meow cat face
129409: 20201001, // 🦁 lion
128293: 20201001, // 🔥 fire
128038: 20210831, // 🐦 bird
129415: 20201001, // 🦇 bat
129417: 20210831, // 🦉 owl
127752: 20201001, // 🌈 rainbow
128053: 20201001, // 🐵 monkey face
128029: 20201001, // 🐝 honeybee bumblebee wasp
128034: 20201001, // 🐢 turtle
128025: 20201001, // 🐙 octopus
129433: 20201001, // 🦙 llama alpaca
128016: 20210831, // 🐐 goat
128060: 20201001, // 🐼 panda
128040: 20201001, // 🐨 koala
129445: 20201001, // 🦥 sloth
128059: 20210831, // 🐻 bear
128048: 20201001, // 🐰 rabbit face
129428: 20201001, // 🦔 hedgehog
128054: 20211115, // 🐶 dog puppy
128041: 20211115, // 🐩 poodle dog
129437: 20211115, // 🦝 raccoon
128039: 20211115, // 🐧 penguin
128012: 20210218, // 🐌 snail
128045: 20201001, // 🐭 mouse face rat
128031: 20210831, // 🐟 fish
127757: 20201001, // 🌍 globe showing Europe-Africa
127774: 20201001, // 🌞 sun with face
127775: 20201001, // 🌟 glowing star
11088: 20201001, // ⭐ star
127772: 20201001, // 🌜 last quarter moon face
129361: 20201001, // 🥑 avocado
127820: 20211115, // 🍌 banana
127827: 20210831, // 🍓 strawberry
127819: 20210521, // 🍋 lemon
127818: 20211115, // 🍊 tangerine orange
}
var qqface = map[int]rune{
0: 128558, // 😮 face exhaling
1: 128556, // 😬 grimacing face
2: 128525, // 😍 smiling face with heart-eyes
4: 128526, // 😎 smiling face with sunglasses
5: 128557, // 😭 loudly crying face
6: 129402, // 🥺 pleading face
7: 129296, // 🤐 zipper-mouth face
8: 128554, // 😪 sleepy face
11: 128545, // 😡 pouting face
12: 128539, // 😛 face with tongue
13: 128513, // 😁 beaming face with smiling eyes
14: 128578, // 🙂 slightly smiling face
15: 128577, // 🙁 slightly frowning face
16: 128526, // 😎 smiling face with sunglasses
19: 129326, // 🤮 face vomiting throw
20: 129325, // 🤭 face with hand over mouth embarrassed
21: 128522, // 😊 smiling face with smiling eyes
23: 128533, // 😕 confused face
24: 128523, // 😋 face savoring food
27: 128531, // 😓 downcast face with sweat
28: 128516, // 😄 grinning face with smiling eyes
31: 129324, // 🤬 face with symbols on mouth
32: 129300, // 🤔 thinking face question hmmm
33: 129323, // 🤫 shushing face quiet whisper
34: 128565, // 😵 face with crossed-out eyes
35: 128547, // 😣 persevering face
37: 128128, // 💀 skull
46: 128055, // 🐷 pig face
53: 127874, // 🎂 birthday cake
59: 128169, // 💩 pile of poo
60: 9749, // ☕ hot beverage coffee cup tea
63: 127801, // 🌹 rose flower
66: 10084, // ❤ mending heart
67: 128148, // 💔 broken heart
69: 127873, // 🎁 wrapped-gift
74: 127774, // 🌞 sun with face
75: 127772, // 🌜 last quarter moon face
96: 128517, // 😅 grinning face with sweat
104: 129393, // 🥱 yawning face
109: 128535, // 😗 kissing face
110: 128562, // 😲 astonished face
111: 129402, // 🥺 pleading face
172: 128539, // 😛 face with tongue
182: 128514, // 😂 face with tears of joy
187: 128123, // 👻 ghost
247: 128567, // 😷 face with medical mask
272: 128579, // 🙃 upside-down face
320: 129395, // 🥳 partying face
325: 128561, // 😱 face screaming in fear
}

100
plugin/emojimix/mix.go Normal file
View File

@@ -0,0 +1,100 @@
// Package emojimix 合成emoji
package emojimix
import (
"fmt"
"net/http"
"strconv"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const bed = "https://www.gstatic.com/android/keyboard/emojikitchen/%d/u%x/u%x_u%x.png"
func init() {
control.Register("emojimix", &control.Options{
DisableOnDefault: false,
Help: "合成emoji\n" +
"- [emoji][emoji]",
}).OnMessage(match).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
r := ctx.State["emojimix"].([]rune)
logrus.Debugln("[emojimix] match:", r)
r1, r2 := r[0], r[1]
u1 := fmt.Sprintf(bed, emojis[r1], r1, r1, r2)
u2 := fmt.Sprintf(bed, emojis[r2], r2, r2, r1)
logrus.Debugln("[emojimix] u1:", u1)
logrus.Debugln("[emojimix] u2:", u2)
resp1, err := http.Head(u1)
if err == nil {
resp1.Body.Close()
if resp1.StatusCode == http.StatusOK {
ctx.SendChain(message.Image(u1))
return
}
}
resp2, err := http.Head(u2)
if err == nil {
resp2.Body.Close()
if resp2.StatusCode == http.StatusOK {
ctx.SendChain(message.Image(u2))
return
}
}
})
}
func match(ctx *zero.Ctx) bool {
logrus.Debugln("[emojimix] msg:", ctx.Event.Message)
if len(ctx.Event.Message) == 2 {
r1 := face2emoji(ctx.Event.Message[0])
if _, ok := emojis[r1]; !ok {
return false
}
r2 := face2emoji(ctx.Event.Message[1])
if _, ok := emojis[r2]; !ok {
return false
}
ctx.State["emojimix"] = []rune{r1, r2}
return true
}
r := []rune(ctx.Event.RawMessage)
logrus.Debugln("[emojimix] raw msg:", ctx.Event.RawMessage)
if len(r) == 2 {
if _, ok := emojis[r[0]]; !ok {
return false
}
if _, ok := emojis[r[1]]; !ok {
return false
}
ctx.State["emojimix"] = r
return true
}
return false
}
func face2emoji(face message.MessageSegment) rune {
if face.Type == "text" {
r := []rune(face.Data["text"])
if len(r) != 1 {
return 0
}
return r[0]
}
if face.Type != "face" {
return 0
}
id, err := strconv.Atoi(face.Data["id"])
if err != nil {
return 0
}
if r, ok := qqface[id]; ok {
return r
}
return 0
}

122
plugin/epidemic/epidemic.go Normal file
View File

@@ -0,0 +1,122 @@
// Package epidemic 城市疫情查询
package epidemic
import (
"encoding/json"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/web"
)
const (
servicename = "epidemic"
txurl = "https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=statisGradeCityDetail,diseaseh5Shelf"
)
// result 疫情查询结果
type result struct {
Data struct {
Epidemic epidemic `json:"diseaseh5Shelf"`
} `json:"data"`
}
// epidemic 疫情数据
type epidemic struct {
LastUpdateTime string `json:"lastUpdateTime"`
AreaTree []*area `json:"areaTree"`
}
// area 城市疫情数据
type area struct {
Name string `json:"name"`
Today struct {
Confirm int `json:"confirm"`
Wzzadd interface{} `json:"wzz_add"`
} `json:"today"`
Total struct {
NowConfirm int `json:"nowConfirm"`
Confirm int `json:"confirm"`
Dead int `json:"dead"`
Heal int `json:"heal"`
Grade string `json:"grade"`
Wzz int `json:"wzz"`
} `json:"total"`
Children []*area `json:"children"`
}
func init() {
engine := control.Register(servicename, &control.Options{
DisableOnDefault: false,
Help: "城市疫情查询\n" +
"- xxx疫情\n",
})
engine.OnSuffix("疫情").SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
city := ctx.State["args"].(string)
if city == "" {
ctx.SendChain(message.Text("你还没有输入城市名字呢!"))
return
}
data, time, err := queryEpidemic(city)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if data == nil {
ctx.SendChain(message.Text("没有找到【", city, "】城市的疫情数据."))
return
}
ctx.SendChain(
message.Text(
"【", data.Name, "】疫情数据\n",
"新增人数:", data.Today.Confirm, "\n",
"现有确诊:", data.Total.NowConfirm, "\n",
"累计确诊:", data.Total.Confirm, "\n",
"治愈人数:", data.Total.Heal, "\n",
"死亡人数:", data.Total.Dead, "\n",
"无症状人数:", data.Total.Wzz, "\n",
"新增无症状:", data.Today.Wzzadd, "\n",
"更新时间:\n『", time, "』",
),
)
})
}
// rcity 查找城市
func rcity(a *area, cityName string) *area {
if a == nil {
return nil
}
if a.Name == cityName {
return a
}
for _, v := range a.Children {
if v.Name == cityName {
return v
}
c := rcity(v, cityName)
if c != nil {
return c
}
}
return nil
}
// queryEpidemic 查询城市疫情
func queryEpidemic(findCityName string) (citydata *area, times string, err error) {
data, err := web.GetData(txurl)
if err != nil {
return
}
var r result
err = json.Unmarshal(data, &r)
if err != nil {
return
}
citydata = rcity(r.Data.Epidemic.AreaTree[0], findCityName)
return citydata, r.Data.Epidemic.LastUpdateTime, nil
}

43
plugin/font/main.go Normal file
View File

@@ -0,0 +1,43 @@
// Package font 渲染任意文字到图片
package font
import (
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/text"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
control.Register("font", &control.Options{
DisableOnDefault: false,
Help: "渲染任意文字到图片\n- (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体])渲染文字xxx",
}).OnRegex(`^(用.+)?渲染文字([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
fnt := ctx.State["regex_matched"].([]string)[1]
txt := ctx.State["regex_matched"].([]string)[2]
switch fnt {
case "用终末体":
fnt = text.SyumatuFontFile
case "用终末变体":
fnt = text.NisiFontFile
case "用紫罗兰体":
fnt = text.VioletEvergardenFontFile
case "用樱酥体":
fnt = text.SakuraFontFile
case "用Consolas体":
fnt = text.ConsolasFontFile
case "用苹方体":
fallthrough
default:
fnt = text.FontFile
}
b, err := text.RenderToBase64(txt, fnt, 400, 20)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Image("base64://" + binary.BytesToString(b)))
})
}

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"
@@ -25,8 +23,6 @@ import (
"github.com/FloatTech/zbputils/img/pool"
"github.com/FloatTech/zbputils/img/writer"
"github.com/FloatTech/zbputils/math"
"github.com/FloatTech/zbputils/control/order"
)
const (
@@ -41,9 +37,8 @@ const (
)
var (
// 底图类型列表:车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌
// 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师 赛马娘
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师", "赛马娘"}
// 底图类型列表
table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师", "赛马娘", "东方归言录", "奇异恩典", "夏日口袋"}
// 映射底图与 index
index = make(map[string]uint8)
// 签文
@@ -51,37 +46,22 @@ var (
)
func init() {
for i, s := range table {
index[s] = uint8(i)
}
err := os.MkdirAll(images, 0755)
if err != nil {
panic(err)
}
_ = os.RemoveAll(cache)
err = os.MkdirAll(cache, 0755)
if err != nil {
panic(err)
}
data, err := file.GetLazyData(omikujson, true, false)
if err != nil {
panic(err)
}
err = json.Unmarshal(data, &omikujis)
if err != nil {
panic(err)
}
_, err = file.GetLazyData(font, false, true)
if err != nil {
panic(err)
}
// 插件主体
en := control.Register("fortune", order.AcquirePrio(), &control.Options{
en := control.Register("fortune", &control.Options{
DisableOnDefault: false,
Help: "每日运势: \n" +
"- 运势 | 抽签\n" +
"- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘]",
"- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘 | 东方归言录 | 奇异恩典 | 夏日口袋]",
PublicDataFolder: "Fortune",
})
_ = os.RemoveAll(cache)
err := os.MkdirAll(cache, 0755)
if err != nil {
panic(err)
}
for i, s := range table {
index[s] = uint8(i)
}
en.OnRegex(`^设置底图\s?(.*)`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
@@ -93,7 +73,7 @@ func init() {
if ok {
c, ok := control.Lookup("fortune")
if ok {
err = c.SetData(gid, int64(i)&0xff)
err := c.SetData(gid, int64(i)&0xff)
if err != nil {
ctx.SendChain(message.Text("设置失败:", err))
return
@@ -106,7 +86,26 @@ func init() {
}
ctx.SendChain(message.Text("没有这个底图哦~"))
})
en.OnFullMatchGroup([]string{"运势", "抽签"}).SetBlock(true).
en.OnFullMatchGroup([]string{"运势", "抽签"}, ctxext.DoOnceOnSuccess(
func(ctx *zero.Ctx) bool {
data, err := file.GetLazyData(omikujson, false)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = json.Unmarshal(data, &omikujis)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
_, err = file.GetLazyData(font, true)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
return true
},
)).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 获取该群背景类型,默认车万
kind := "车万"
@@ -125,73 +124,53 @@ 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))
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))
ctx.SendChain(message.Text("ERROR:", err))
return
}
// 随机获取签文
title, text := randtext(seed)
randtextindex := ctxext.RandSenderPerDayN(ctx, 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[:])
m, err := pool.GetImage(cachefile)
if err != nil {
logrus.Debugln("[fortune]", err)
if file.IsNotExist(cachefile) {
f, err := os.Create(cachefile)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
_, err = draw(background, title, text, f)
_ = f.Close()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
}
m.SetFile(file.BOTPATH + "/" + cachefile)
hassent, err := m.Push(ctxext.Send(ctx), ctxext.GetMessage(ctx))
err = pool.SendImageFromPool(cachefile, cachefile, func() error {
f, err := os.Create(cachefile)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if hassent {
return
return err
}
_, err = draw(background, title, text, f)
_ = f.Close()
return err
}, ctxext.Send(ctx), ctxext.GetMessage(ctx))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
// 发送图片
ctx.SendChain(message.Image(m.String()))
})
}
// @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()
rand.Seed(seed)
index = rand.Intn(len(reader.File))
file := reader.File[index]
file := reader.File[ctxext.RandSenderPerDayN(ctx, len(reader.File))]
f, err := file.Open()
if err != nil {
return
@@ -202,16 +181,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) {
rand.Seed(seed)
r := rand.Intn(len(omikujis))
return omikujis[r]["title"], omikujis[r]["content"]
}
// @function draw 绘制运势图
// @param background 背景图片路径
// @param seed 随机数种子

61
plugin/funny/laugh.go Normal file
View File

@@ -0,0 +1,61 @@
// Package funny 冷笑话
package funny
import (
"strings"
"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"
"github.com/FloatTech/zbputils/ctxext"
)
type joke struct {
ID uint32 `db:"id"`
Text string `db:"text"`
}
var db = &sql.Sqlite{}
func init() {
en := control.Register("funny", &control.Options{
DisableOnDefault: false,
Help: "讲个笑话\n" +
"- 讲个笑话[@xxx|qq号|人名] | 夸夸[@xxx|qq号|人名] ",
PublicDataFolder: "Funny",
})
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.Create("jokes", &joke{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
c, err := db.Count("jokes")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
logrus.Infoln("[funny]加载", c, "个笑话")
return true
})).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
// 获取名字
name := ctx.NickName()
var j joke
err := db.Pick("jokes", &j)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text(strings.ReplaceAll(j.Text, "%name", name)))
})
}

16
plugin/genshin/data.go Normal file
View File

@@ -0,0 +1,16 @@
package genshin
type storage uint64
func (s *storage) is5starsmode() bool {
return *s&1 == 1
}
func (s *storage) setmode(is5stars bool) bool {
if is5stars {
*s |= 1
} else {
*s &= 0xffffffff_fffffffe
}
return is5stars
}

374
plugin/genshin/ys.go Normal file
View File

@@ -0,0 +1,374 @@
// Package genshin 原神抽卡
package genshin
import (
"archive/zip"
"image"
"image/color"
"image/draw"
"image/jpeg"
"image/png"
"math/rand"
"regexp"
"strings"
"sync/atomic"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/writer"
"github.com/FloatTech/zbputils/process"
"github.com/golang/freetype"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
type zipfilestructure map[string][]*zip.File
var (
totl uint64 // 累计抽奖次数
filetree = make(zipfilestructure, 32)
starN3, starN4, starN5 *zip.File
namereg = regexp.MustCompile(`_(.*)\.png`)
)
func init() {
engine := control.Register("genshin", &control.Options{
DisableOnDefault: false,
Help: "原神抽卡\n- 原神十连\n- 切换原神卡池",
PublicDataFolder: "Genshin",
}).ApplySingle(ctxext.DefaultSingle)
engine.OnFullMatch("切换原神卡池").SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
c, ok := control.Lookup("genshin")
if !ok {
ctx.SendChain(message.Text("找不到服务!"))
return
}
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
store := (storage)(c.GetData(gid))
if store.setmode(!store.is5starsmode()) {
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("切换到五星卡池~"))
} else {
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("切换到普通卡池~"))
}
err := c.SetData(gid, int64(store))
if err != nil {
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("ERROR:", err))
}
})
engine.OnFullMatch("原神十连", ctxext.DoOnceOnSuccess(
func(ctx *zero.Ctx) bool {
zipfile := engine.DataFolder() + "Genshin.zip"
_, err := engine.GetLazyData("Genshin.zip", false)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
err = parsezip(zipfile)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
return true
},
)).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
c, ok := control.Lookup("genshin")
if !ok {
ctx.SendChain(message.Text("找不到服务!"))
return
}
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
store := (storage)(c.GetData(gid))
img, str, mode, err := randnums(10, store)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
b, cl := writer.ToBytes(img)
if mode {
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
message.Text("恭喜你抽到了: \n", str), message.ImageBytes(b)))
} else {
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
message.Text("十连成功~"), message.ImageBytes(b)))
}
cl()
})
}
func randnums(nums int, store storage) (rgba *image.RGBA, str string, replyMode bool, err error) {
var (
fours, fives = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 抽到 四, 五星角色
threeArms, fourArms, fiveArms = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 抽到 三 , 四, 五星武器
fourN, fiveN = 0, 0 // 抽到 四, 五星角色的数量
bgs = make([]*zip.File, 0, 10) // 背景图片名
threeN2, fourN2, fiveN2 = 0, 0, 0 // 抽到 三 , 四, 五星武器的数量
hero, stars = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 角色武器名, 储存星级图标
cicon = make([]*zip.File, 0, 10) // 元素图标
fivebg, fourbg, threebg = filetree["five_bg.jpg"][0], filetree["four_bg.jpg"][0], filetree["three_bg.jpg"][0] // 背景图片名
fivelen = len(filetree["five"])
five2len = len(filetree["five2"])
threelen = len(filetree["Three"])
fourlen = len(filetree["four"])
four2len = len(filetree["four2"])
)
if totl%9 == 0 { // 累计9次加入一个五星
switch rand.Intn(2) {
case 0:
fiveN++
fives = append(fives, filetree["five"][rand.Intn(fivelen)])
case 1:
fiveN2++
fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)])
}
nums--
}
if store.is5starsmode() { // 5星模式
for i := 0; i < nums; i++ {
switch rand.Intn(2) {
case 0:
fiveN++
fives = append(fives, filetree["five"][rand.Intn(fivelen)])
case 1:
fiveN2++
fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)])
}
}
} else { // 默认模式
for i := 0; i < nums; i++ {
a := rand.Intn(1000) // 抽卡几率 三星80% 四星17% 五星3%
switch {
case a >= 0 && a <= 800:
threeN2++
threeArms = append(threeArms, filetree["Three"][rand.Intn(threelen)])
case a > 800 && a <= 885:
fourN++
fours = append(fours, filetree["four"][rand.Intn(fourlen)]) // 随机角色
case a > 885 && a <= 970:
fourN2++
fourArms = append(fourArms, filetree["four2"][rand.Intn(four2len)]) // 随机武器
case a > 970 && a <= 985:
fiveN++
fives = append(fives, filetree["five"][rand.Intn(fivelen)])
default:
fiveN2++
fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)])
}
}
if fourN+fourN2 == 0 && threeN2 > 0 { // 没有四星时自动加入
threeN2--
threeArms = threeArms[:len(threeArms)-1]
switch rand.Intn(2) {
case 0:
fourN++
fours = append(fours, filetree["four"][rand.Intn(fourlen)]) // 随机角色
case 1:
fourN2++
fourArms = append(fourArms, filetree["four2"][rand.Intn(four2len)]) // 随机武器
}
}
_ = atomic.AddUint64(&totl, 1)
}
icon := func(f *zip.File) *zip.File {
name := f.Name
name = name[strings.LastIndex(name, "/")+1:strings.Index(name, "_")] + ".png"
logrus.Debugln("[genshin]get named file", name)
return filetree[name][0]
}
he := func(cnt int, id int, f *zip.File, bg *zip.File) {
var hen *[]*zip.File
for i := 0; i < cnt; i++ {
switch id {
case 1:
hen = &threeArms
case 2:
hen = &fourArms
case 3:
hen = &fours
case 4:
hen = &fiveArms
case 5:
hen = &fives
}
bgs = append(bgs, bg) // 加入颜色背景
hero = append(hero, (*hen)[i])
stars = append(stars, f) // 加入星级图标
cicon = append(cicon, icon((*hen)[i])) // 加入元素图标
}
}
if fiveN > 0 { // 按顺序加入
he(fiveN, 5, starN5, fivebg) // 五星角色
str += reply(fives, 1, str)
replyMode = true
}
if fourN > 0 {
he(fourN, 3, starN4, fourbg) // 四星角色
}
if fiveN2 > 0 {
he(fiveN2, 4, starN5, fivebg) // 五星武器
str += reply(fiveArms, 2, str)
replyMode = true
}
if fourN2 > 0 {
he(fourN2, 2, starN4, fourbg) // 四星武器
}
if threeN2 > 0 {
he(threeN2, 1, starN3, threebg) // 三星武器
}
var c1, c2, c3 uint8 = 50, 50, 50 // 背景颜色
img00, err := filetree["bg0.jpg"][0].Open() // 打开背景图片
if err != nil {
return
}
rectangle := image.Rect(0, 0, 1920, 1080) // 图片宽度, 图片高度
rgba = image.NewRGBA(rectangle)
draw.Draw(rgba, rgba.Bounds(), image.NewUniform(color.RGBA{c1, c2, c3, 255}), image.Point{}, draw.Over)
context := freetype.NewContext() // 创建一个新的上下文
context.SetDPI(72) // 每英寸 dpi
context.SetClip(rgba.Bounds())
context.SetDst(rgba)
defer img00.Close()
img0, err := jpeg.Decode(img00) // 读取一个本地图像
if err != nil {
return
}
offset := image.Pt(0, 0) // 图片在背景上的位置
draw.Draw(rgba, img0.Bounds().Add(offset), img0, image.Point{}, draw.Over)
w1, h1 := 230, 0
for i := 0; i < len(hero); i++ {
if i > 0 {
w1 += 146 // 图片宽度
}
imgs, err := bgs[i].Open() // 取出背景图片
if err != nil {
return nil, "", false, err
}
defer imgs.Close()
img, _ := jpeg.Decode(imgs)
offset := image.Pt(w1, h1)
draw.Draw(rgba, img.Bounds().Add(offset), img, image.Point{}, draw.Over)
imgs1, err := hero[i].Open() // 取出图片名
if err != nil {
return nil, "", false, err
}
defer imgs1.Close()
img1, _ := png.Decode(imgs1)
offset1 := image.Pt(w1, h1)
draw.Draw(rgba, img1.Bounds().Add(offset1), img1, image.Point{}, draw.Over)
imgs2, err := stars[i].Open() // 取出星级图标
if err != nil {
return nil, "", false, err
}
defer imgs2.Close()
img2, _ := png.Decode(imgs2)
offset2 := image.Pt(w1, h1)
draw.Draw(rgba, img2.Bounds().Add(offset2), img2, image.Point{}, draw.Over)
imgs3, err := cicon[i].Open() // 取出类型图标
if err != nil {
return nil, "", false, err
}
defer imgs3.Close()
img3, _ := png.Decode(imgs3)
offset3 := image.Pt(w1, h1)
draw.Draw(rgba, img3.Bounds().Add(offset3), img3, image.Point{}, draw.Over)
}
imgs4, err := filetree["Reply.png"][0].Open() // "分享" 图标
if err != nil {
return nil, "", false, err
}
defer imgs4.Close()
img4, err := png.Decode(imgs4)
if err != nil {
return nil, "", false, err
}
offset4 := image.Pt(1270, 945) // 宽, 高
draw.Draw(rgba, img4.Bounds().Add(offset4), img4, image.Point{}, draw.Over)
return
}
func parsezip(zipFile string) error {
zipReader, err := zip.OpenReader(zipFile) // will not close
if err != nil {
return err
}
for _, f := range zipReader.File {
if f.FileInfo().IsDir() {
filetree[f.Name] = make([]*zip.File, 0, 32)
continue
}
f.Name = f.Name[8:]
i := strings.LastIndex(f.Name, "/")
if i < 0 {
filetree[f.Name] = []*zip.File{f}
logrus.Debugln("[genshin]insert file", f.Name)
continue
}
folder := f.Name[:i]
if folder != "" {
filetree[folder] = append(filetree[folder], f)
logrus.Debugln("[genshin]insert file into", folder)
if folder == "gacha" {
switch f.Name[i+1:] {
case "ThreeStar.png":
starN3 = f
case "FourStar.png":
starN4 = f
case "FiveStar.png":
starN5 = f
}
}
}
}
return nil
}
// 取出角色武器名
func reply(z []*zip.File, num int, nameStr string) string {
var tmp strings.Builder
tmp.Grow(128)
switch {
case num == 1:
tmp.WriteString("★五星角色★\n")
case num == 2 && len(nameStr) > 0:
tmp.WriteString("\n★五星武器★\n")
default:
tmp.WriteString("★五星武器★\n")
}
for i := range z {
tmp.WriteString(namereg.FindStringSubmatch(z[i].Name)[1] + " * ")
}
return tmp.String()
}

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

85
plugin/gif/context.go Normal file
View File

@@ -0,0 +1,85 @@
package gif
import (
"os"
"strconv"
"sync"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img"
"github.com/sirupsen/logrus"
)
type context struct {
usrdir string
headimgsdir []string
}
func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
defer wg.Done()
target := datapath + `materials/` + name
var err error
if file.IsNotExist(target) {
err = file.DownloadTo(`https://gitcode.net/u011570312/imagematerials/-/raw/main/`+name, target, true)
if err != nil {
exit(err)
return
}
logrus.Debugln("[gif] dl", name, "to", target, "succeeded")
} else {
logrus.Debugln("[gif] dl", name, "exists at", target)
}
*s = target
}
func dlblock(name string) (string, error) {
target := datapath + `materials/` + name
if file.IsNotExist(target) {
err := file.DownloadTo(`https://gitcode.net/u011570312/imagematerials/-/raw/main/`+name, target, true)
if err != nil {
return "", err
}
logrus.Debugln("[gif] dl", name, "to", target, "succeeded")
} else {
logrus.Debugln("[gif] dl", name, "exists at", target)
}
return target, nil
}
func dlrange(prefix string, end int, wg *sync.WaitGroup, exit func(error)) []string {
if file.IsNotExist(datapath + `materials/` + prefix) {
err := os.MkdirAll(datapath+`materials/`+prefix, 0755)
if err != nil {
exit(err)
return nil
}
}
c := make([]string, end)
for i := range c {
wg.Add(1)
go dlchan(prefix+"/"+strconv.Itoa(i)+".png", &c[i], wg, exit)
}
return c
}
// 新的上下文
func newContext(user int64) *context {
c := new(context)
c.usrdir = datapath + "users/" + strconv.FormatInt(user, 10) + `/`
_ = os.MkdirAll(c.usrdir, 0755)
c.headimgsdir = make([]string, 2)
c.headimgsdir[0] = c.usrdir + "0.gif"
c.headimgsdir[1] = c.usrdir + "1.gif"
return c
}
func loadFirstFrames(paths []string, size int) (imgs []*img.ImgFactory, err error) {
imgs = make([]*img.ImgFactory, size)
for i := range imgs {
imgs[i], err = img.LoadFirstFrame(paths[i], 0, 0)
if err != nil {
return nil, err
}
}
return imgs, nil
}

345
plugin/gif/gif.go Normal file
View File

@@ -0,0 +1,345 @@
package gif
import (
"image"
"sync"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/writer"
)
// A摸
func (cc *context) A摸() (string, error) {
var wg sync.WaitGroup
var err error
var m sync.Mutex
name := cc.usrdir + "摸.gif"
c := dlrange("mo", 5, &wg, func(e error) {
m.Lock()
err = e
m.Unlock()
})
if err != nil {
return "", err
}
tou, err := cc.getLogo(0, 0)
if err != nil {
return "", err
}
wg.Wait()
if err != nil {
return "", err
}
imgs, err := loadFirstFrames(c, 5)
if err != nil {
return "", err
}
mo := []*image.NRGBA{
imgs[0].InsertBottom(tou, 80, 80, 32, 32).Im,
imgs[1].InsertBottom(tou, 70, 90, 42, 22).Im,
imgs[2].InsertBottom(tou, 75, 85, 37, 27).Im,
imgs[3].InsertBottom(tou, 85, 75, 27, 37).Im,
imgs[4].InsertBottom(tou, 90, 70, 22, 42).Im,
}
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, mo))
}
// A搓
func (cc *context) A搓() (string, error) {
var wg sync.WaitGroup
var err error
var m sync.Mutex
name := cc.usrdir + "搓.gif"
c := dlrange("cuo", 5, &wg, func(e error) {
m.Lock()
err = e
m.Unlock()
})
if err != nil {
return "", err
}
tou, err := cc.getLogo(110, 110)
if err != nil {
return "", err
}
m1 := img.Rotate(tou, 72, 0, 0)
m2 := img.Rotate(tou, 144, 0, 0)
m3 := img.Rotate(tou, 216, 0, 0)
m4 := img.Rotate(tou, 288, 0, 0)
wg.Wait()
if err != nil {
return "", err
}
imgs, err := loadFirstFrames(c, 5)
if err != nil {
return "", err
}
cuo := []*image.NRGBA{
imgs[0].InsertBottomC(tou, 0, 0, 75, 130).Im,
imgs[1].InsertBottomC(m1.Im, 0, 0, 75, 130).Im,
imgs[2].InsertBottomC(m2.Im, 0, 0, 75, 130).Im,
imgs[3].InsertBottomC(m3.Im, 0, 0, 75, 130).Im,
imgs[4].InsertBottomC(m4.Im, 0, 0, 75, 130).Im,
}
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(5, cuo))
}
// A敲
func (cc *context) A敲() (string, error) {
var wg sync.WaitGroup
var err error
var m sync.Mutex
name := cc.usrdir + "敲.gif"
c := dlrange("qiao", 2, &wg, func(e error) {
m.Lock()
err = e
m.Unlock()
})
if err != nil {
return "", err
}
tou, err := cc.getLogo(40, 40)
if err != nil {
return "", err
}
wg.Wait()
if err != nil {
return "", err
}
imgs, err := loadFirstFrames(c, 2)
if err != nil {
return "", err
}
qiao := []*image.NRGBA{
imgs[0].InsertUp(tou, 40, 33, 57, 52).Im,
imgs[1].InsertUp(tou, 38, 36, 58, 50).Im,
}
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, qiao))
}
// A吃
func (cc *context) A吃() (string, error) {
var wg sync.WaitGroup
var err error
var m sync.Mutex
name := cc.usrdir + "吃.gif"
c := dlrange("chi", 3, &wg, func(e error) {
m.Lock()
err = e
m.Unlock()
})
if err != nil {
return "", err
}
tou, err := cc.getLogo(32, 32)
if err != nil {
return "", err
}
wg.Wait()
if err != nil {
return "", err
}
imgs, err := loadFirstFrames(c, 3)
if err != nil {
return "", err
}
chi := []*image.NRGBA{
imgs[0].InsertBottom(tou, 0, 0, 1, 38).Im,
imgs[1].InsertBottom(tou, 0, 0, 1, 38).Im,
imgs[2].InsertBottom(tou, 0, 0, 1, 38).Im,
}
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, chi))
}
// A蹭
func (cc *context) A蹭() (string, error) {
var wg sync.WaitGroup
var err error
var m sync.Mutex
name := cc.usrdir + "蹭.gif"
c := dlrange("ceng", 6, &wg, func(e error) {
m.Lock()
err = e
m.Unlock()
})
if err != nil {
return "", err
}
tou, err := cc.getLogo(100, 100)
if err != nil {
return "", err
}
tou2, err := cc.getLogo2(100, 100)
if err != nil {
return "", err
}
wg.Wait()
if err != nil {
return "", err
}
imgs, err := loadFirstFrames(c, 6)
if err != nil {
return "", err
}
ceng := []*image.NRGBA{
imgs[0].InsertUp(tou, 75, 77, 40, 88).InsertUp(tou2, 77, 103, 102, 81).Im,
imgs[1].InsertUp(tou, 75, 77, 46, 100).InsertUp(img.Rotate(tou2, 10, 62, 127).Im, 0, 0, 92, 40).Im,
imgs[2].InsertUp(tou, 75, 77, 67, 99).InsertUp(tou2, 76, 117, 90, 8).Im,
imgs[3].InsertUp(tou, 75, 77, 52, 83).InsertUp(img.Rotate(tou2, -40, 94, 94).Im, 0, 0, 53, -20).Im,
imgs[4].InsertUp(tou, 75, 77, 56, 110).InsertUp(img.Rotate(tou2, -66, 132, 80).Im, 0, 0, 78, 40).Im,
imgs[5].InsertUp(tou, 75, 77, 62, 102).InsertUp(tou2, 71, 100, 110, 94).Im,
}
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(8, ceng))
}
// A啃
func (cc *context) A啃() (string, error) {
var wg sync.WaitGroup
var err error
var m sync.Mutex
name := cc.usrdir + "啃.gif"
c := dlrange("ken", 16, &wg, func(e error) {
m.Lock()
err = e
m.Unlock()
})
if err != nil {
return "", err
}
tou, err := cc.getLogo(100, 100)
if err != nil {
return "", err
}
wg.Wait()
if err != nil {
return "", err
}
imgs, err := loadFirstFrames(c, 16)
if err != nil {
return "", err
}
ken := []*image.NRGBA{
imgs[0].InsertBottom(tou, 90, 90, 105, 150).Im,
imgs[1].InsertBottom(tou, 90, 83, 96, 172).Im,
imgs[2].InsertBottom(tou, 90, 90, 106, 148).Im,
imgs[3].InsertBottom(tou, 88, 88, 97, 167).Im,
imgs[4].InsertBottom(tou, 90, 85, 89, 179).Im,
imgs[5].InsertBottom(tou, 90, 90, 106, 151).Im,
imgs[6].Im,
imgs[7].Im,
imgs[8].Im,
imgs[9].Im,
imgs[10].Im,
imgs[11].Im,
imgs[12].Im,
imgs[13].Im,
imgs[14].Im,
imgs[15].Im,
}
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, ken))
}
// A拍
func (cc *context) A拍() (string, error) {
var wg sync.WaitGroup
var err error
var m sync.Mutex
name := cc.usrdir + "拍.gif"
c := dlrange("pai", 2, &wg, func(e error) {
m.Lock()
err = e
m.Unlock()
})
if err != nil {
return "", err
}
tou, err := cc.getLogo(30, 30)
if err != nil {
return "", err
}
wg.Wait()
if err != nil {
return "", err
}
imgs, err := loadFirstFrames(c, 2)
if err != nil {
return "", err
}
pai := []*image.NRGBA{
imgs[0].InsertUp(tou, 0, 0, 1, 47).Im,
imgs[1].InsertUp(tou, 0, 0, 1, 67).Im,
}
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, pai))
}
// A冲
func (cc *context) A冲() (string, error) {
var wg sync.WaitGroup
var err error
var m sync.Mutex
name := cc.usrdir + "冲.gif"
c := dlrange("xqe", 2, &wg, func(e error) {
m.Lock()
err = e
m.Unlock()
})
if err != nil {
return "", err
}
tou, err := cc.getLogo(0, 0)
if err != nil {
return "", err
}
wg.Wait()
if err != nil {
return "", err
}
imgs, err := loadFirstFrames(c, 2)
if err != nil {
return "", err
}
chong := []*image.NRGBA{
imgs[0].InsertUp(tou, 30, 30, 15, 53).Im,
imgs[1].InsertUp(tou, 30, 30, 40, 53).Im,
}
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(1, chong))
}
// A丢
func (cc *context) A丢() (string, error) {
var wg sync.WaitGroup
var err error
var m sync.Mutex
name := cc.usrdir + "丢.gif"
c := dlrange("diu", 8, &wg, func(e error) {
m.Lock()
err = e
m.Unlock()
})
if err != nil {
return "", err
}
tou, err := cc.getLogo(0, 0)
if err != nil {
return "", err
}
wg.Wait()
if err != nil {
return "", err
}
imgs, err := loadFirstFrames(c, 8)
if err != nil {
return "", err
}
diu := []*image.NRGBA{
imgs[0].InsertUp(tou, 32, 32, 108, 36).Im,
imgs[1].InsertUp(tou, 32, 32, 122, 36).Im,
imgs[2].Im,
imgs[3].InsertUp(tou, 123, 123, 19, 129).Im,
imgs[4].InsertUp(tou, 185, 185, -50, 200).InsertUp(tou, 33, 33, 289, 70).Im,
imgs[5].InsertUp(tou, 32, 32, 280, 73).Im,
imgs[6].InsertUp(tou, 35, 35, 259, 31).Im,
imgs[7].InsertUp(tou, 175, 175, -50, 220).Im,
}
return "file:///" + name, writer.SaveGIF2Path(name, img.MergeGif(7, diu))
}

41
plugin/gif/logo.go Normal file
View File

@@ -0,0 +1,41 @@
package gif
import (
"image"
"strconv"
"strings"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img"
)
func (cc *context) prepareLogos(s ...string) error {
for i, v := range s {
_, err := strconv.Atoi(v)
if err != nil {
err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.usrdir+strconv.Itoa(i)+".gif", true)
} else {
err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif", true)
}
if err != nil {
return err
}
}
return nil
}
func (cc *context) getLogo(w int, h int) (*image.NRGBA, error) {
frame, err := img.LoadFirstFrame(cc.headimgsdir[0], w, h)
if err != nil {
return nil, err
}
return frame.Circle(0).Im, nil
}
func (cc *context) getLogo2(w int, h int) (*image.NRGBA, error) {
frame, err := img.LoadFirstFrame(cc.headimgsdir[1], w, h)
if err != nil {
return nil, err
}
return frame.Circle(0).Im, nil
}

108
plugin/gif/png.go Normal file
View File

@@ -0,0 +1,108 @@
package gif
import (
"errors"
"image"
"math/rand"
"os"
"strconv"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/writer"
)
// A爬
func (cc *context) A爬() (string, error) {
name := cc.usrdir + `爬.png`
tou, err := cc.getLogo(0, 0)
if err != nil {
return "", err
}
// 随机爬图序号
rand := rand.Intn(60) + 1
if file.IsNotExist(datapath + "materials/pa") {
err = os.MkdirAll(datapath+"materials/pa", 0755)
if err != nil {
return "", err
}
}
f, err := dlblock(`pa/` + strconv.Itoa(rand) + `.png`)
if err != nil {
return "", err
}
imgf, err := img.LoadFirstFrame(f, 0, 0)
if err != nil {
return "", err
}
return "file:///" + name, writer.SavePNG2Path(name, imgf.InsertBottom(tou, 100, 100, 0, 400).Im)
}
// A撕
func (cc *context) A撕() (string, error) {
name := cc.usrdir + `撕.png`
tou, err := cc.getLogo(0, 0)
if err != nil {
return "", err
}
im1 := img.Rotate(tou, 20, 380, 380)
im2 := img.Rotate(tou, -12, 380, 380)
if file.IsNotExist(datapath + "materials/si") {
err = os.MkdirAll(datapath+"materials/si", 0755)
if err != nil {
return "", err
}
}
f, err := dlblock(`si/0.png`)
if err != nil {
return "", err
}
imgf, err := img.LoadFirstFrame(f, 0, 0)
if err != nil {
return "", err
}
return "file:///" + name, writer.SavePNG2Path(name, imgf.InsertBottom(im1.Im, im1.W, im1.H, -3, 370).InsertBottom(im2.Im, im2.W, im2.H, 653, 310).Im)
}
// 简单
func (cc *context) other(value ...string) (string, error) {
name := cc.usrdir + value[0] + `.png`
// 加载图片
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
if err != nil {
return "", err
}
var imgnrgba *image.NRGBA
switch value[0] {
case "上翻", "下翻":
imgnrgba = im.FlipV().Im
case "左翻", "右翻":
imgnrgba = im.FlipH().Im
case "反色":
imgnrgba = im.Invert().Im
case "灰度":
imgnrgba = im.Grayscale().Im
case "负片":
imgnrgba = im.Invert().Grayscale().Im
case "浮雕":
imgnrgba = im.Convolve3x3().Im
case "打码":
imgnrgba = im.Blur(10).Im
case "旋转":
r, _ := strconv.ParseFloat(value[1], 64)
imgnrgba = img.Rotate(im.Im, r, 0, 0).Im
case "变形":
w, err := strconv.Atoi(value[1])
if err != nil {
return "", err
}
h, err := strconv.Atoi(value[2])
if err != nil {
return "", err
}
imgnrgba = img.Size(im.Im, w, h).Im
default:
return "", errors.New("no such method")
}
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
}

54
plugin/gif/run.go Normal file
View File

@@ -0,0 +1,54 @@
// Package gif 制图
package gif
import (
"reflect"
"strconv"
"strings"
control "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"
)
var (
cmds = []string{"搓", "冲", "摸", "拍", "丢", "吃", "敲", "啃", "蹭", "爬", "撕",
"灰度", "上翻", "下翻", "左翻", "右翻", "反色", "浮雕", "打码", "负片"}
datapath string
)
func init() { // 插件主体
en := control.Register("gif", &control.Options{
DisableOnDefault: false,
Help: "制图\n- " + strings.Join(cmds, "\n- "),
PrivateDataFolder: "gif",
}).ApplySingle(ctxext.DefaultSingle)
datapath = file.BOTPATH + "/" + en.DataFolder()
en.OnRegex(`^(` + strings.Join(cmds, "|") + `)\D*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`).
SetBlock(true).Handle(func(ctx *zero.Ctx) {
c := newContext(ctx.Event.UserID)
list := ctx.State["regex_matched"].([]string)
err := c.prepareLogos(list[4]+list[5]+list[6], strconv.FormatInt(ctx.Event.UserID, 10))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
var picurl string
if len([]rune(list[1])) == 1 {
r := reflect.ValueOf(c).MethodByName("A" + list[1]).Call(nil)
picurl = r[0].String()
if !r[1].IsNil() {
err = r[1].Interface().(error)
}
} else {
picurl, err = c.other(list[1]) // "灰度", "上翻", "下翻", "左翻", "右翻", "反色", "倒放", "浮雕", "打码", "负片"
}
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Image(picurl))
})
}

View File

@@ -4,7 +4,7 @@ package github
import (
"errors"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"strings"
@@ -13,13 +13,11 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
"github.com/tidwall/gjson"
)
func init() { // 插件主体
control.Register("github", order.AcquirePrio(), &control.Options{
control.Register("github", &control.Options{
DisableOnDefault: false,
Help: "GitHub仓库搜索\n" +
"- >github [xxx]\n" +
@@ -36,12 +34,12 @@ func init() { // 插件主体
}.Encode()
body, err := netGet(api.String(), header)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
ctx.SendChain(message.Text("ERROR:", err))
}
// 解析请求
info := gjson.ParseBytes(body)
if info.Get("total_count").Int() == 0 {
ctx.SendChain(message.Text("ERROR: 没有找到这样的仓库"))
ctx.SendChain(message.Text("ERROR:没有找到这样的仓库"))
return
}
repo := info.Get("items.0")
@@ -97,7 +95,7 @@ func init() { // 插件主体
}
// notnull 如果传入文本为空,则返回默认值
//nolint: unparam
func notnull(text, defstr string) string {
if text == "" {
return defstr
@@ -119,7 +117,7 @@ func netGet(dest string, header http.Header) ([]byte, error) {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -2,7 +2,6 @@
package hs
import (
"fmt"
"os"
"strconv"
"strings"
@@ -16,15 +15,10 @@ import (
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/web"
"github.com/FloatTech/zbputils/control/order"
)
var (
cachedir = file.BOTPATH + "/data/hs/"
reqconf = [...]string{"GET", "https://hs.fbigame.com",
"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36"}
)
var reqconf = [...]string{"GET", "https://hs.fbigame.com",
"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36"}
const (
hs = `https://hs.fbigame.com/ajax.php?`
@@ -46,19 +40,15 @@ const (
)
func init() {
os.RemoveAll(cachedir)
err := os.MkdirAll(cachedir, 0755)
if err != nil {
panic(err)
}
engine := control.Register("hs", order.AcquirePrio(), &control.Options{
engine := control.Register("hs", &control.Options{
DisableOnDefault: false,
Help: "炉石\n" +
"- 搜卡[xxxx]\n" +
"- [卡组代码xxx]\n" +
"- 更多搜卡指令参数https://hs.fbigame.com/misc/searchhelp",
PrivateDataFolder: "hs",
}).ApplySingle(ctxext.DefaultSingle)
cachedir := file.BOTPATH + "/" + engine.DataFolder()
engine.OnRegex(`^搜卡(.+)$`).
SetBlock(true).Handle(func(ctx *zero.Ctx) {
List := ctx.State["regex_matched"].([]string)[1]
@@ -73,7 +63,7 @@ func init() {
cid := gjson.Get(g, `list.`+strconv.Itoa(i)+`.CardID`).String()
cachefile := cachedir + cid
if file.IsNotExist(cachefile) {
data, err := web.ReqWith(
data, err := web.RequestDataWith(web.NewDefaultClient(),
`https://res.fbigame.com/hs/v13/`+cid+`.png?auth_key=`+
gjson.Get(g, `list.`+strconv.Itoa(i)+`.auth_key`).String(),
reqconf[0], reqconf[1], reqconf[2])
@@ -84,26 +74,18 @@ func init() {
continue
}
}
sk = append(
sk,
message.CustomNode(
zero.BotConfig.NickName[0],
ctx.Event.SelfID,
[]message.MessageSegment{message.Image("file:///" + cachefile)}, // 图片
),
)
sk = append(sk, ctxext.FakeSenderForwardNode(ctx, message.Image("file:///"+cachefile)))
}
if id := ctx.SendGroupForwardMessage(
ctx.Event.GroupID,
sk,
).Get("message_id").Int(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
ctx.SendChain(message.Text("ERROR:可能被风控了"))
}
})
// 卡组
engine.OnRegex(`^[\s\S]*?(AAE[a-zA-Z0-9/\+=]{70,})[\s\S]*$`).
SetBlock(true).Handle(func(ctx *zero.Ctx) {
fmt.Print("成功")
List := ctx.State["regex_matched"].([]string)[1]
ctx.SendChain(
message.Image(kz(List)),
@@ -112,10 +94,10 @@ func init() {
}
func sh(s string) string {
data, err := web.ReqWith("https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
data, err := web.RequestDataWith(web.NewDefaultClient(), "https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
if err == nil {
url := hs + para + "&hash=" + strings.SplitN(strings.SplitN(helper.BytesToString(data), `var hash = "`, 2)[1], `"`, 2)[0] + "&search=" + s
r, err := web.ReqWith(url, reqconf[0], reqconf[1], reqconf[2])
r, err := web.RequestDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2])
if err == nil {
return helper.BytesToString(r)
}
@@ -124,10 +106,10 @@ func sh(s string) string {
}
func kz(s string) string {
data, err := web.ReqWith("https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
data, err := web.RequestDataWith(web.NewDefaultClient(), "https://hs.fbigame.com", reqconf[0], reqconf[1], reqconf[2])
if err == nil {
url := hs + para + "mod=general_deck_image&deck_code=" + s + "&deck_text=&hash=" + strings.SplitN(strings.SplitN(helper.BytesToString(data), `var hash = "`, 2)[1], `"`, 2)[0] + "&search=" + s
r, err := web.ReqWith(url, reqconf[0], reqconf[1], reqconf[2])
r, err := web.RequestDataWith(web.NewDefaultClient(), url, reqconf[0], reqconf[1], reqconf[2])
if err == nil {
return "base64://" + gjson.Get(helper.BytesToString(r), "img").String()
}

122
plugin/hyaku/main.go Normal file
View File

@@ -0,0 +1,122 @@
// Package hyaku 百人一首
package hyaku
import (
"encoding/csv"
"fmt"
"math/rand"
"os"
"reflect"
"strconv"
"unsafe"
"github.com/FloatTech/zbputils/binary"
"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"
)
const bed = "https://gitcode.net/u011570312/OguraHyakuninIsshu/-/raw/master/"
//nolint: asciicheck
type line struct {
番号, 歌人, 上の句, 下の句, 上の句ひらがな, 下の句ひらがな string
}
func (l *line) String() string {
b := binary.NewWriterF(func(w *binary.Writer) {
r := reflect.ValueOf(l).Elem().Type()
for i := 0; i < r.NumField(); i++ {
switch i {
case 0:
w.WriteString("●")
case 1:
w.WriteString("◉")
case 2, 3:
w.WriteString("○")
case 4, 5:
w.WriteString("◎")
}
w.WriteString(r.Field(i).Name)
w.WriteString("")
w.WriteString((*[6]string)(unsafe.Pointer(l))[i])
w.WriteString("\n")
}
})
return binary.BytesToString(b)
}
var lines [100]*line
func init() {
engine := control.Register("hyaku", &control.Options{
DisableOnDefault: false,
Help: "百人一首\n" +
"- 百人一首(随机发一首)\n" +
"- 百人一首之n",
PrivateDataFolder: "hyaku",
})
csvfile := engine.DataFolder() + "hyaku.csv"
go func() {
if file.IsNotExist(csvfile) {
err := file.DownloadTo(bed+"小倉百人一首.csv", csvfile, true)
if err != nil {
_ = os.Remove(csvfile)
panic(err)
}
}
f, err := os.Open(csvfile)
if err != nil {
panic(err)
}
records, err := csv.NewReader(f).ReadAll()
if err != nil {
panic(err)
}
_ = f.Close()
records = records[1:] // skip title
if len(records) != 100 {
panic("invalid csvfile")
}
for j, r := range records {
if len(r) != 6 {
panic("invalid csvfile")
}
i, err := strconv.Atoi(r[0])
if err != nil {
panic(err)
}
i--
if j != i {
panic("invalid csvfile")
}
lines[i] = (*line)(*(*unsafe.Pointer)(unsafe.Pointer(&r)))
}
}()
engine.OnFullMatch("百人一首").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
i := rand.Intn(100)
ctx.SendChain(
message.Image(fmt.Sprintf(bed+"img/%03d.jpg", i+1)),
message.Text("\n", lines[i]),
message.Image(fmt.Sprintf(bed+"img/%03d.png", i+1)),
)
})
engine.OnRegex(`^百人一首之\s?(\d+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
i, err := strconv.Atoi(ctx.State["regex_matched"].([]string)[1])
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if i > 100 || i < 1 {
ctx.SendChain(message.Text("ERROR:超出范围"))
return
}
ctx.SendChain(
message.Image(fmt.Sprintf(bed+"img/%03d.jpg", i)),
message.Text("\n", lines[i-1]),
message.Image(fmt.Sprintf(bed+"img/%03d.png", i)),
)
})
}

View File

@@ -0,0 +1,87 @@
// Package imagefinder 关键字搜图
package imagefinder
import (
"encoding/json"
"errors"
"math/rand"
"net/url"
"strings"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/AnimeAPI/pixiv"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/pool"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/web"
)
type resultjson struct {
Data struct {
Illusts []struct {
ID int64 `json:"id"`
Title string `json:"title"`
AltTitle string `json:"altTitle"`
Description string `json:"description"`
Sanity int `json:"sanity"`
} `json:"illusts"`
} `json:"data"`
Error bool `json:"error"`
Message string `json:"message"`
}
func init() {
control.Register("imgfinder", &control.Options{
DisableOnDefault: false,
Help: "关键字搜图\n" +
"- 来张 [xxx]",
}).OnRegex(`^来张\s?(.*)$`, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]
soutujson, err := soutuapi(keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
rannum := rand.Intn(len(soutujson.Data.Illusts))
illust, err := pixiv.Works(soutujson.Data.Illusts[rannum].ID)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
u := illust.ImageUrls[0]
n := u[strings.LastIndex(u, "/")+1 : len(u)-4]
f := illust.Path(0)
err = pool.SendImageFromPool(n, f, func() error {
// 下载图片
return illust.DownloadToCache(0)
}, ctxext.SendFakeForwardToGroup(ctx), ctxext.GetFirstMessageInForward(ctx))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
})
}
// soutuapi 请求api
func soutuapi(keyword string) (r resultjson, err error) {
var data []byte
for i := 0; i < 3; i++ {
data, err = web.GetData("https://copymanga.azurewebsites.net/api/pixivel?" + url.QueryEscape(keyword) + "?page=0")
if err != nil {
process.SleepAbout1sTo2s()
continue
}
err = json.Unmarshal(data, &r)
if err == nil && r.Error {
err = errors.New(r.Message)
}
return
}
return
}

22
plugin/inject/main.go Normal file
View File

@@ -0,0 +1,22 @@
// Package inject 注入指令
package inject
import (
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
en := control.Register("inject", &control.Options{
DisableOnDefault: false,
Help: "注入指令\n" +
"- run[CQ码]",
})
// 运行 CQ 码
en.OnPrefix("run", zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 可注入,权限为主人
ctx.Send(message.UnescapeCQCodeText(ctx.State["args"].(string)))
})
}

24
plugin/jandan/data.go Normal file
View File

@@ -0,0 +1,24 @@
package jandan
import (
"sync"
sql "github.com/FloatTech/sqlite"
)
var db = &sql.Sqlite{}
var mu sync.RWMutex
type picture struct {
ID uint64 `db:"id"`
URL string `db:"url"`
}
func getRandomPicture() (u string, err error) {
var p picture
mu.RLock()
err = db.Pick("picture", &p)
mu.RUnlock()
u = p.URL
return
}

View File

@@ -9,12 +9,11 @@ import (
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/antchfx/htmlquery"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
const (
@@ -22,12 +21,30 @@ const (
)
func init() {
engine := control.Register("jandan", order.AcquirePrio(), &control.Options{
engine := control.Register("jandan", &control.Options{
DisableOnDefault: false,
Help: "煎蛋网无聊图\n- 来份屌图\n- 更新屌图\n",
Help: "煎蛋网无聊图\n- 来份[屌|弔|吊]图\n- 更新[屌|弔|吊]图\n",
PublicDataFolder: "Jandan",
})
engine.OnFullMatch("来份屌图").SetBlock(true).
getdb := ctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = engine.DataFolder() + "pics.db"
_, _ = engine.GetLazyData("pics.db", false)
err := db.Create("picture", &picture{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
n, err := db.Count("picture")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
logrus.Printf("[jandan]读取%d张图片", n)
return true
})
engine.OnRegex(`来份[屌|弔|吊]图`, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
u, err := getRandomPicture()
if err != nil {
@@ -37,7 +54,7 @@ func init() {
ctx.SendChain(message.Image(u))
})
engine.OnFullMatch("更新屌图", zero.SuperUserPermission).SetBlock(true).
engine.OnRegex(`更新[屌|弔|吊]图`, zero.SuperUserPermission, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.Send("少女更新中...")
webpageURL := api
@@ -54,7 +71,7 @@ func init() {
}
LOOP:
for i := 0; i < pageTotal; i++ {
logrus.Infoln("[jandan]", fmt.Sprintf("处理第%d/%d页...", i, pageTotal))
logrus.Debugln("[jandan]", fmt.Sprintf("处理第%d/%d页...", i, pageTotal))
doc, err = htmlquery.LoadURL(webpageURL)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
@@ -74,7 +91,7 @@ func init() {
mu.RUnlock()
if !ok {
mu.Lock()
db.Insert("picture", &picture{ID: i, URL: u})
_ = db.Insert("picture", &picture{ID: i, URL: u})
mu.Unlock()
} else {
// 开始重复,说明之后都是重复

View File

@@ -9,13 +9,10 @@ import (
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/zbputils/control/order"
)
const (
@@ -25,7 +22,7 @@ const (
)
func init() {
control.Register("juejuezi", order.AcquirePrio(), &control.Options{
control.Register("juejuezi", &control.Options{
DisableOnDefault: false,
Help: "绝绝子生成器\n" +
"- 喝奶茶绝绝子 | 绝绝子吃饭",
@@ -37,14 +34,16 @@ func init() {
case 2:
data, err := juejuezi(string(toDealStr[0]), string(toDealStr[1]))
if err != nil {
ctx.SendChain(message.Text(err))
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text(gjson.Get(helper.BytesToString(data), "text").String()))
default:
params := ctx.GetWordSlices(string(toDealStr)).Get("slices").Array()
data, err := juejuezi(params[0].String(), params[1].String())
if err != nil {
ctx.SendChain(message.Text(err))
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text(gjson.Get(helper.BytesToString(data), "text").String()))
}
@@ -57,13 +56,13 @@ func juejuezi(verb, noun string) (data []byte, err error) {
// 提交请求
request, err := http.NewRequest("POST", juejueziURL, strings.NewReader(juejueziStr))
if err != nil {
log.Errorln("[juejuezi]:", err)
return nil, err
}
request.Header.Add("Referer", referer)
request.Header.Add("User-Agent", ua)
response, err := client.Do(request)
if err != nil {
log.Errorln("[juejuezi]:", err)
return nil, err
}
data, err = io.ReadAll(response.Body)
response.Body.Close()

View File

@@ -2,8 +2,7 @@
package lolicon
import (
"io/ioutil"
"net/http"
"encoding/base64"
"strings"
"time"
@@ -16,8 +15,7 @@ import (
"github.com/FloatTech/zbputils/img/pool"
"github.com/FloatTech/zbputils/math"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/control/order"
"github.com/FloatTech/zbputils/web"
)
const (
@@ -26,32 +24,38 @@ const (
)
var (
queue = make(chan string, capacity)
queue = make(chan string, capacity)
custapi = ""
)
func init() {
control.Register("lolicon", order.AcquirePrio(), &control.Options{
en := control.Register("lolicon", &control.Options{
DisableOnDefault: false,
Help: "lolicon\n" +
"- 来份萝莉",
}).ApplySingle(ctxext.DefaultSingle).OnFullMatch("来份萝莉").SetBlock(true).
"- 来份萝莉\n" +
"- 设置随机图片地址[http...]",
}).ApplySingle(ctxext.DefaultSingle)
en.OnFullMatch("来份萝莉").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
go func() {
for i := 0; i < math.Min(cap(queue)-len(queue), 2); i++ {
resp, err := http.Get(api)
if custapi != "" {
data, err := web.GetData(custapi)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
continue
}
queue <- "base64://" + base64.StdEncoding.EncodeToString(data)
continue
}
data, err := web.GetData(api)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
ctx.SendChain(message.Text("ERROR:", err))
continue
}
if resp.StatusCode != http.StatusOK {
ctx.SendChain(message.Text("ERROR: code ", resp.StatusCode))
continue
}
data, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
json := gjson.ParseBytes(data)
if e := json.Get("error").Str; e != "" {
ctx.SendChain(message.Text("ERROR: ", e))
ctx.SendChain(message.Text("ERROR:", e))
continue
}
url := json.Get("data.0.urls.original").Str
@@ -72,9 +76,25 @@ func init() {
}()
select {
case <-time.After(time.Minute):
ctx.SendChain(message.Text("ERROR: 等待填充,请稍后再试......"))
case url := <-queue:
ctx.SendChain(message.Image(url))
ctx.SendChain(message.Text("ERROR:等待填充,请稍后再试......"))
case img := <-queue:
id := ctx.SendChain(message.Image(img))
if id.ID() == 0 {
process.SleepAbout1sTo2s()
id = ctx.SendChain(message.Image(img).Add("cache", "0"))
if id.ID() == 0 {
ctx.SendChain(message.Text("ERROR:图片发送失败,可能被风控了~"))
}
}
}
})
en.OnPrefix("设置随机图片地址", zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
u := strings.TrimSpace(ctx.State["args"].(string))
if !strings.HasPrefix(u, "http") {
ctx.SendChain(message.Text("ERROR:url非法!"))
return
}
custapi = u
})
}

View File

@@ -4,7 +4,6 @@ package manager
import (
"fmt"
"math/rand"
"os"
"sort"
"strconv"
"strings"
@@ -20,15 +19,11 @@ import (
"github.com/FloatTech/zbputils/math"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/control/order"
"github.com/FloatTech/ZeroBot-Plugin/plugin_manager/timer"
"github.com/FloatTech/ZeroBot-Plugin/plugin/manager/timer"
)
const (
datapath = "data/manager/"
confile = datapath + "config.db"
hint = "====群管====\n" +
hint = "====群管====\n" +
"- 禁言@QQ 1分钟\n" +
"- 解除禁言 @QQ\n" +
"- 我要自闭 1分钟\n" +
@@ -51,25 +46,27 @@ const (
"- 取消在\"cron\"的提醒\n" +
"- 列出所有提醒\n" +
"- 翻牌\n" +
"- 设置欢迎语XXX\n" +
"- 设置欢迎语XXX 可选添加 [{at}] [{nickname}] [{avatar}] [{uid}] [{gid}] [{groupname}] {at}可在发送时艾特被欢迎者 {nickname}是被欢迎者名字 {avatar}是被欢迎者头像 {uid}是被欢迎者QQ号 {gid}是当前群群号 {groupname} 是当前群群名\n" +
"- 测试欢迎语\n" +
"- 设置告别辞 参数同设置欢迎语\n" +
"- 测试告别辞\n" +
"- [开启 | 关闭]入群验证"
)
var (
db = &sql.Sqlite{DBPath: confile}
db = &sql.Sqlite{}
clock timer.Clock
)
func init() { // 插件主体
engine := control.Register("manager", order.AcquirePrio(), &control.Options{
DisableOnDefault: false,
Help: hint,
engine := control.Register("manager", &control.Options{
DisableOnDefault: false,
Help: hint,
PrivateDataFolder: "manager",
})
go func() {
defer order.DoneOnExit()()
process.SleepAbout1sTo2s()
_ = os.MkdirAll(datapath, 0755)
db.DBPath = engine.DataFolder() + "config.db"
clock = timer.NewClock(db)
err := db.Create("welcome", &welcome{})
if err != nil {
@@ -79,6 +76,10 @@ func init() { // 插件主体
if err != nil {
panic(err)
}
err = db.Create("farewell", &welcome{})
if err != nil {
panic(err)
}
}()
// 升为管理
@@ -213,6 +214,10 @@ func init() { // 插件主体
// 修改名片
engine.OnRegex(`^修改名片.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if len(ctx.State["regex_matched"].([]string)[2]) > 60 {
ctx.SendChain(message.Text("名字太长啦!"))
return
}
ctx.SetGroupCard(
ctx.Event.GroupID,
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群名片的人
@@ -223,6 +228,10 @@ func init() { // 插件主体
// 修改头衔
engine.OnRegex(`^修改头衔.*?(\d+).*?\s(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if len(ctx.State["regex_matched"].([]string)[1]) > 18 {
ctx.SendChain(message.Text("头衔太长啦!"))
return
}
ctx.SetGroupSpecialTitle(
ctx.Event.GroupID,
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
@@ -233,6 +242,10 @@ func init() { // 插件主体
// 申请头衔
engine.OnRegex(`^申请头衔(.*)`, zero.OnlyGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if len(ctx.State["regex_matched"].([]string)[1]) > 18 {
ctx.SendChain(message.Text("头衔太长啦!"))
return
}
ctx.SetGroupSpecialTitle(
ctx.Event.GroupID,
ctx.Event.UserID, // 被修改群头衔的人
@@ -272,7 +285,7 @@ func init() { // 插件主体
dateStrs := ctx.State["regex_matched"].([]string)
ts := timer.GetFilledTimer(dateStrs, ctx.Event.SelfID, ctx.Event.GroupID, false)
if ts.En() {
go clock.RegisterTimer(ts, true)
go clock.RegisterTimer(ts, true, false)
ctx.SendChain(message.Text("记住了~"))
} else {
ctx.SendChain(message.Text("参数非法:" + ts.Alert))
@@ -285,7 +298,7 @@ func init() { // 插件主体
var url, alert string
switch len(dateStrs) {
case 4:
url = dateStrs[2]
url = strings.TrimPrefix(dateStrs[2], "用")
alert = dateStrs[3]
case 3:
alert = dateStrs[2]
@@ -295,7 +308,7 @@ func init() { // 插件主体
}
logrus.Debugln("[manager] cron:", dateStrs[1])
ts := timer.GetFilledCronTimer(dateStrs[1], alert, url, ctx.Event.SelfID, ctx.Event.GroupID)
if clock.RegisterTimer(ts, true) {
if clock.RegisterTimer(ts, true, false) {
ctx.SendChain(message.Text("记住了~"))
} else {
ctx.SendChain(message.Text("参数非法:" + ts.Alert))
@@ -336,16 +349,11 @@ func init() { // 插件主体
engine.OnFullMatchGroup([]string{"翻牌"}, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
// 无缓存获取群员列表
list := ctx.CallAction("get_group_member_list", zero.Params{
"group_id": ctx.Event.GroupID,
"no_cache": true,
}).Data
temp := list.Array()
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)-10):]
rand.Seed(time.Now().UnixNano())
who := temp[rand.Intn(len(temp))]
if who.Get("user_id").Int() == ctx.Event.SelfID {
ctx.SendChain(message.Text("幸运儿居然是我自己"))
@@ -373,7 +381,7 @@ func init() { // 插件主体
var w welcome
err := db.Find("welcome", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
if err == nil {
ctx.SendChain(message.Text(w.Msg))
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
} else {
ctx.SendChain(message.Text("欢迎~"))
}
@@ -403,13 +411,13 @@ func init() { // 插件主体
}
return false
}
next := zero.NewFutureEvent("message", 999, false, zero.CheckUser(ctx.Event.UserID), rule)
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession(), rule)
recv, cancel := next.Repeat()
select {
case <-time.After(time.Minute):
cancel()
ctx.SendChain(message.Text("拜拜啦~"))
ctx.SetGroupKick(ctx.Event.GroupID, uid, false)
cancel()
case <-recv:
cancel()
ctx.SendChain(message.Text("答对啦~"))
@@ -422,16 +430,24 @@ func init() { // 插件主体
engine.OnNotice().SetBlock(false).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.NoticeType == "group_decrease" {
userid := ctx.Event.UserID
ctx.SendChain(message.Text(ctxext.CardOrNickName(ctx, userid), "(", userid, ")", "离开了我们..."))
var w welcome
err := db.Find("farewell", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
if err == nil {
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
} else {
userid := ctx.Event.UserID
ctx.SendChain(message.Text(ctx.CardOrNickName(userid), "(", userid, ")", "离开了我们..."))
}
}
})
// 设置欢迎语
engine.OnRegex(`^设置欢迎语([\s\S]*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
welcomestring := ctx.State["regex_matched"].([]string)[1]
welcomestring = message.UnescapeCQCodeText(welcomestring)
w := &welcome{
GrpID: ctx.Event.GroupID,
Msg: ctx.State["regex_matched"].([]string)[1],
Msg: welcomestring,
}
err := db.Insert("welcome", w)
if err == nil {
@@ -440,6 +456,45 @@ func init() { // 插件主体
ctx.SendChain(message.Text("出错啦: ", err))
}
})
// 测试欢迎语
engine.OnFullMatch("测试欢迎语", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
var w welcome
err := db.Find("welcome", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
if err == nil {
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
} else {
ctx.SendChain(message.Text("欢迎~"))
}
})
// 设置告别辞
engine.OnRegex(`^设置告别辞([\s\S]*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
farewellstring := ctx.State["regex_matched"].([]string)[1]
farewellstring = message.UnescapeCQCodeText(farewellstring)
w := &welcome{
GrpID: ctx.Event.GroupID,
Msg: farewellstring,
}
err := db.Insert("farewell", w)
if err == nil {
ctx.SendChain(message.Text("记住啦!"))
} else {
ctx.SendChain(message.Text("出错啦: ", err))
}
})
// 测试告别辞
engine.OnFullMatch("测试告别辞", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
var w welcome
err := db.Find("farewell", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
if err == nil {
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
} else {
userid := ctx.Event.UserID
ctx.SendChain(message.Text(ctx.CardOrNickName(userid), "(", userid, ")", "离开了我们..."))
}
})
// 入群后验证开关
engine.OnRegex(`^(.*)入群验证$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
@@ -490,15 +545,6 @@ func init() { // 插件主体
}
ctx.SendChain(message.Text("找不到服务!"))
})
// 运行 CQ 码
engine.OnRegex(`^run(.*)$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
var cmd = ctx.State["regex_matched"].([]string)[1]
cmd = strings.ReplaceAll(cmd, "&#91;", "[")
cmd = strings.ReplaceAll(cmd, "&#93;", "]")
// 可注入,权限为主人
ctx.Send(cmd)
})
// 根据 gist 自动同意加群
// 加群请在github新建一个gist其文件名为本群群号的字符串的md5(小写)内容为一行是当前unix时间戳(10分钟内有效)。
// 然后请将您的用户名和gist哈希(小写)按照username/gisthash的格式填写到回答即可。
@@ -518,7 +564,7 @@ func init() { // 插件主体
}
ghun := ans[:divi]
hash := ans[divi+1:]
logrus.Infoln("[manager]收到加群申请, 用户:", ghun, ", hash:", hash)
logrus.Debugln("[manager]收到加群申请, 用户:", ghun, ", hash:", hash)
ok, reason := checkNewUser(ctx.Event.UserID, ctx.Event.GroupID, ghun, hash)
if ok {
ctx.SetGroupAddRequest(ctx.Event.Flag, "add", true, "")
@@ -530,3 +576,20 @@ func init() { // 插件主体
}
})
}
// 传入 ctx 和 welcome格式string 返回cq格式string 使用方法:welcometocq(ctx,w.Msg)
func welcometocq(ctx *zero.Ctx, welcome string) string {
uid := strconv.FormatInt(ctx.Event.UserID, 10) // 用户id
nickname := ctx.CardOrNickName(ctx.Event.UserID) // 用户昵称
at := "[CQ:at,qq=" + uid + "]" // at用户
avatar := "[CQ:image,file=" + "http://q4.qlogo.cn/g?b=qq&nk=" + uid + "&s=640]" // 用户头像
gid := strconv.FormatInt(ctx.Event.GroupID, 10) // 群id
groupname := ctx.GetGroupInfo(ctx.Event.GroupID, true).Name // 群名
cqstring := strings.ReplaceAll(welcome, "{at}", at)
cqstring = strings.ReplaceAll(cqstring, "{nickname}", nickname)
cqstring = strings.ReplaceAll(cqstring, "{avatar}", avatar)
cqstring = strings.ReplaceAll(cqstring, "{uid}", uid)
cqstring = strings.ReplaceAll(cqstring, "{gid}", gid)
cqstring = strings.ReplaceAll(cqstring, "{groupname}", groupname)
return cqstring
}

View File

@@ -106,10 +106,10 @@ func GetFilledTimer(dateStrs []string, botqq, grp int64, matchDateOnly bool) *Ti
urlStr := dateStrs[5]
if urlStr != "" { // 是图片url
t.URL = urlStr[3:] // utf-8下用为3字节
logrus.Println("[群管]" + t.URL)
logrus.Debugln("[群管]" + t.URL)
if !strings.HasPrefix(t.URL, "http") {
t.URL = "illegal"
logrus.Println("[群管]url非法")
logrus.Debugln("[群管]url非法")
return &t
}
}

View File

@@ -8,6 +8,7 @@ import (
"time"
sql "github.com/FloatTech/sqlite"
"github.com/FloatTech/zbputils/process"
"github.com/fumiama/cron"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -47,7 +48,7 @@ func NewClock(db *sql.Sqlite) (c Clock) {
}
// RegisterTimer 注册计时器
func (c *Clock) RegisterTimer(ts *Timer, save bool) bool {
func (c *Clock) RegisterTimer(ts *Timer, save, isinit bool) bool {
var key uint32
if save {
key = ts.GetTimerID()
@@ -59,9 +60,12 @@ func (c *Clock) RegisterTimer(ts *Timer, save bool) bool {
if t != ts && ok { // 避免重复注册定时器
t.SetEn(false)
}
logrus.Println("[群管]注册计时器", key)
logrus.Infoln("[群管]注册计时器", key)
if ts.Cron != "" {
var ctx *zero.Ctx
if isinit {
process.GlobalInitMutex.Lock()
}
if ts.SelfID != 0 {
ctx = zero.GetBot(ts.SelfID)
} else {
@@ -71,6 +75,9 @@ func (c *Clock) RegisterTimer(ts *Timer, save bool) bool {
return false
})
}
if isinit {
process.GlobalInitMutex.Unlock()
}
eid, err := c.cron.AddFunc(ts.Cron, func() { ts.sendmsg(ts.GrpID, ctx) })
if err == nil {
c.entmu.Lock()
@@ -187,7 +194,7 @@ func (c *Clock) loadTimers(db *sql.Sqlite) {
var t Timer
_ = c.db.FindFor("timer", &t, "", func() error {
tescape := t
go c.RegisterTimer(&tescape, false)
go c.RegisterTimer(&tescape, false, true)
return nil
})
}

View File

@@ -8,11 +8,10 @@ import (
reg "github.com/fumiama/go-registry"
)
var sr = reg.NewRegedit("reilia.fumiama.top:32664", "fumiama", "--")
var sr = reg.NewRegedit("reilia.westeurope.cloudapp.azure.com:32664", "fumiama", "--")
func TestGetHoliday(t *testing.T) {
registry.Connect()
holidaymap = make(map[string]*Holiday)
h := GetHoliday("元旦")
registry.Close()
t.Fatal(h)
@@ -28,7 +27,7 @@ func TestSetHoliday(t *testing.T) {
if err != nil {
t.Fatal(err)
}
err = SetHoliday("春节", 7, 2022, 1, 31)
err = SetHoliday("春节", 7, 2023, 1, 21)
if err != nil {
t.Fatal(err)
}

View File

@@ -21,29 +21,20 @@ 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.fumiama.top:32664", "fumiama")
holidaymap map[string]*Holiday
)
var registry = reg.NewRegReader("reilia.westeurope.cloudapp.azure.com:32664", "fumiama")
// GetHoliday 从 reg 服务器获取节日
func GetHoliday(name string) *Holiday {
var dur, year int
var month time.Month
var day int
h, ok := holidaymap[name]
if ok {
return h
}
ret, err := registry.Get("holiday/" + name)
if err != nil {
return NewHoliday(name+err.Error(), 0, 0, 0, 0)
}
fmt.Sscanf(ret, "%d_%d_%d_%d", &dur, &year, &month, &day)
logrus.Debugln("[moyu]获取节日:", name, dur, year, month, day)
h = NewHoliday(name, dur, year, month, day)
holidaymap[name] = h
return h
return NewHoliday(name, dur, year, month, day)
}
// String 获取两个时间相差

61
plugin/moyu/run.go Normal file
View File

@@ -0,0 +1,61 @@
// Package moyu 摸鱼
package moyu
import (
"sync"
"time"
control "github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var (
msg message.Message
mu sync.Mutex
lastupdate time.Time
)
func init() { // 插件主体
control.Register("moyu", &control.Options{
DisableOnDefault: true,
Help: "moyu\n" +
"- /启用 moyu\n" +
"- /禁用 moyu\n" +
"- 记录在\"0 10 * * *\"触发的指令\n" +
" - 摸鱼提醒",
}).OnFullMatch("摸鱼提醒").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
mu.Lock()
defer mu.Unlock()
if msg == nil || time.Since(lastupdate) > time.Hour*20 {
if registry.Connect() != nil {
return
}
msg = message.Message{
message.Text(time.Now().Format("2006-01-02")),
message.Text("上午好,摸鱼人!\n工作再累一定不要忘记摸鱼哦有事没事起身去茶水间去厕所去廊道走走别老在工位上坐着钱是老板的,但命是自己的。\n"),
message.Text(weekend()),
message.Text("\n"),
message.Text(GetHoliday("元旦")),
message.Text("\n"),
message.Text(GetHoliday("春节")),
message.Text("\n"),
message.Text(GetHoliday("清明节")),
message.Text("\n"),
message.Text(GetHoliday("劳动节")),
message.Text("\n"),
message.Text(GetHoliday("端午节")),
message.Text("\n"),
message.Text(GetHoliday("中秋节")),
message.Text("\n"),
message.Text(GetHoliday("国庆节")),
message.Text("\n"),
message.Text("上班是帮老板赚钱,摸鱼是赚老板的钱!最后,祝愿天下所有摸鱼人,都能愉快的渡过每一天…"),
}
_ = registry.Close()
lastupdate = time.Now()
}
ctx.Send(msg)
})
}

View File

@@ -0,0 +1,28 @@
// Package moyucalendar 摸鱼人日历
package moyucalendar
import (
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/web"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
control.Register("moyucalendar", &control.Options{
DisableOnDefault: true,
Help: "摸鱼人日历\n" +
"- /启用 moyucalendar\n" +
"- /禁用 moyucalendar\n" +
"- 记录在\"30 8 * * *\"触发的指令\n" +
" - 摸鱼人日历",
}).OnFullMatch("摸鱼人日历").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
data, err := web.GetData("https://api.vvhan.com/api/moyu")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.ImageBytes(data))
})
}

View File

@@ -5,23 +5,23 @@ import (
"crypto/md5"
"encoding/hex"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"strings"
"time"
"github.com/FloatTech/zbputils/web"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
func init() {
control.Register("music", order.AcquirePrio(), &control.Options{
control.Register("music", &control.Options{
DisableOnDefault: false,
Help: "点歌\n" +
"- 点歌[xxx]\n" +
@@ -136,81 +136,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{
"offset": []string{"0"},
"total": []string{"true"},
"limit": []string{"9"},
"type": []string{"1"},
"s": []string{keyword},
}
// 搜索音乐信息 第一首歌
info := gjson.ParseBytes(netPost("http://music.163.com/api/search/pc", data, headers)).Get("result.songs.0")
// 返回音乐卡片
return message.CustomMusic(
fmt.Sprintf("http://y.music.163.com/m/song?id=%d", info.Get("id").Int()),
fmt.Sprintf("http://music.163.com/song/media/outer/url?id=%d.mp3", info.Get("id").Int()),
info.Get("name").Str,
).Add("content", info.Get("artists.0.name").Str).Add("image", info.Get("album.blurPicUrl").Str)
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
@@ -231,20 +178,6 @@ func netGet(url string, header http.Header) []byte {
return nil
}
defer res.Body.Close()
result, _ := ioutil.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, _ := ioutil.ReadAll(res.Body)
result, _ := io.ReadAll(res.Body)
return result
}

View File

@@ -10,14 +10,10 @@ import (
"github.com/corona10/goimagehash"
"github.com/sirupsen/logrus"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
_ "golang.org/x/image/webp" // import webp decoding
sql "github.com/FloatTech/sqlite"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/process"
"github.com/FloatTech/zbputils/control/order"
)
// setuclass holds setus in a folder, which is the class name.
@@ -27,25 +23,7 @@ type setuclass struct {
Path string `db:"path"` // Path 图片路径
}
var ns = &nsetu{db: &sql.Sqlite{DBPath: dbfile}}
func init() {
go func() {
defer order.DoneOnExit()()
process.SleepAbout1sTo2s()
err := os.MkdirAll(datapath, 0755)
if err != nil {
panic(err)
}
if file.IsExist(cfgfile) {
b, err := os.ReadFile(cfgfile)
if err == nil {
setupath = helper.BytesToString(b)
logrus.Println("[nsetu] set setu dir to", setupath)
}
}
}()
}
var ns = &nsetu{db: &sql.Sqlite{}}
type nsetu struct {
db *sql.Sqlite

View File

@@ -12,14 +12,7 @@ import (
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/control/order"
)
const (
datapath = "data/nsetu"
dbfile = datapath + "/data.db"
cfgfile = datapath + "/setupath.txt"
"github.com/FloatTech/zbputils/file"
)
var (
@@ -27,7 +20,7 @@ var (
)
func init() {
engine := control.Register("nativesetu", order.AcquirePrio(), &control.Options{
engine := control.Register("nativesetu", &control.Options{
DisableOnDefault: false,
Help: "本地涩图\n" +
"- 本地[xxx]\n" +
@@ -35,7 +28,19 @@ func init() {
"- 设置本地setu绝对路径[xxx]\n" +
"- 刷新所有本地setu\n" +
"- 所有本地setu分类",
PrivateDataFolder: "nsetu",
})
ns.db.DBPath = engine.DataFolder() + "data.db"
cfgfile := engine.DataFolder() + "setupath.txt"
if file.IsExist(cfgfile) {
b, err := os.ReadFile(cfgfile)
if err == nil {
setupath = helper.BytesToString(b)
logrus.Infoln("[nsetu] set setu dir to", setupath)
}
}
engine.OnRegex(`^本地(.*)$`, ctxext.FirstValueInList(ns)).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
imgtype := ctx.State["regex_matched"].([]string)[1]
@@ -44,9 +49,16 @@ func init() {
err := ns.db.Pick(imgtype, sc)
ns.mu.RUnlock()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
ctx.SendChain(message.Text("ERROR:", err))
} else {
p := "file:///" + setupath + "/" + sc.Path
if ctx.Event.GroupID != 0 {
ctx.SendGroupForwardMessage(ctx.Event.GroupID, message.Message{
ctxext.FakeSenderForwardNode(ctx,
message.Text(imgtype, ": ", sc.Name, "\n"), message.Image(p),
)})
return
}
ctx.SendChain(message.Text(imgtype, ": ", sc.Name, "\n"), message.Image(p))
}
})
@@ -57,7 +69,7 @@ func init() {
if err == nil {
ctx.SendChain(message.Text("成功!"))
} else {
ctx.SendChain(message.Text("ERROR: ", err))
ctx.SendChain(message.Text("ERROR:", err))
}
})
engine.OnRegex(`^设置本地setu绝对路径(.*)$`, zero.SuperUserPermission).SetBlock(true).
@@ -67,7 +79,7 @@ func init() {
if err == nil {
ctx.SendChain(message.Text("成功!"))
} else {
ctx.SendChain(message.Text("ERROR: ", err))
ctx.SendChain(message.Text("ERROR:", err))
}
})
engine.OnFullMatch("刷新所有本地setu", zero.SuperUserPermission).SetBlock(true).
@@ -76,7 +88,7 @@ func init() {
if err == nil {
ctx.SendChain(message.Text("成功!"))
} else {
ctx.SendChain(message.Text("ERROR: ", err))
ctx.SendChain(message.Text("ERROR:", err))
}
})
engine.OnFullMatch("所有本地setu分类").SetBlock(true).

View File

@@ -16,26 +16,18 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"github.com/FloatTech/zbputils/control/order"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
)
const base = "data/nwife"
var baseuri = "file:///" + file.BOTPATH + "/" + base
func init() {
err := os.MkdirAll(base, 0755)
if err != nil {
panic(err)
}
engine := control.Register("nwife", order.AcquirePrio(), &control.Options{
DisableOnDefault: false,
Help: "nativewife\n- 抽wife[@xxx]\n- 添加wife[名字][图片]\n- 删除wife[名字]\n- [让 | 不让]所有人均可添加wife",
engine := control.Register("nwife", &control.Options{
DisableOnDefault: false,
Help: "nativewife\n- 抽wife[@xxx]\n- 添加wife[名字][图片]\n- 删除wife[名字]\n- [让 | 不让]所有人均可添加wife",
PrivateDataFolder: "nwife",
})
base := engine.DataFolder()
baseuri := "file:///" + file.BOTPATH + "/" + base
engine.OnPrefix("抽wife", zero.OnlyGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
grpf := strconv.FormatInt(ctx.Event.GroupID, 36)
@@ -52,7 +44,7 @@ func init() {
ctx.SendChain(message.Text("大家的wife都是", wn, "\n"), message.Image(baseuri+"/"+grpf+"/"+wn), message.Text("\n哦~"))
default:
// 获取名字
name := ctxext.NickName(ctx)
name := ctx.NickName()
now := time.Now()
s := md5.Sum(helper.StringToBytes(fmt.Sprintf("%s%d%d%d", name, now.Year(), now.Month(), now.Day())))
r := rand.New(rand.NewSource(int64(binary.LittleEndian.Uint64(s[:]))))
@@ -62,7 +54,7 @@ func init() {
}
})
// 上传一张图
engine.OnPrefix("添加wife", zero.OnlyGroup, chkAddWifePermission, ctxext.MustProvidePicture).SetBlock(true).
engine.OnPrefix("添加wife", zero.OnlyGroup, chkAddWifePermission, zero.MustProvidePicture).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
name := ""
for _, elem := range ctx.Event.Message {
@@ -78,13 +70,13 @@ func init() {
url := ctx.State["image_url"].([]string)[0]
grpfolder := base + "/" + strconv.FormatInt(ctx.Event.GroupID, 36)
if file.IsNotExist(grpfolder) {
err = os.Mkdir(grpfolder, 0755)
err := os.Mkdir(grpfolder, 0755)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("错误:", err.Error()))
return
}
}
err = file.DownloadTo(url, grpfolder+"/"+name, true)
err := file.DownloadTo(url, grpfolder+"/"+name, true)
if err == nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功!"))
} else {
@@ -108,7 +100,7 @@ func init() {
}
if name != "" {
grpfolder := base + "/" + strconv.FormatInt(ctx.Event.GroupID, 36)
err = os.Remove(grpfolder + "/" + name)
err := os.Remove(grpfolder + "/" + name)
if err == nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功!"))
} else {

View File

@@ -2,7 +2,7 @@
package nbnhhsh
import (
"io/ioutil"
"io"
"net/http"
"net/url"
"strings"
@@ -11,12 +11,10 @@ import (
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
func init() {
control.Register("nbnhhsh", order.AcquirePrio(), &control.Options{
control.Register("nbnhhsh", &control.Options{
DisableOnDefault: false,
Help: "拼音首字母释义工具\n- ?? [缩写]",
}).OnRegex(`^[?]{1,2} ?([a-z0-9]+)$`).SetBlock(false).
@@ -31,7 +29,7 @@ func getValue(text string) []string {
urlValues.Add("text", text)
resp, err := http.PostForm("https://lab.magiconch.com/api/nbnhhsh/guess", urlValues)
if err == nil {
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err == nil {
resp.Body.Close()
json := gjson.ParseBytes(body)

View File

@@ -3,7 +3,7 @@ package novel
import (
"fmt"
"io/ioutil"
"io"
"net/http"
"net/http/cookiejar"
"net/url"
@@ -11,7 +11,6 @@ import (
"strings"
"github.com/antchfx/htmlquery"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
@@ -20,19 +19,17 @@ import (
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/text"
"github.com/FloatTech/zbputils/control/order"
)
const (
websiteURL = "https://www.23qb.net"
websiteURL = "https://www.23qb.com"
websiteTitle = "铅笔小说"
errorTitle = "出现错误!"
username = "zerobot"
password = "123456"
submit = "%26%23160%3B%B5%C7%26%23160%3B%26%23160%3B%C2%BC%26%23160%3B"
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
loginURL = websiteURL + "/login.php?do=submit&jumpurl=https%3A%2F%2Fwww.23qb.net%2F"
loginURL = websiteURL + "/login.php?do=submit&jumpurl=https%3A%2F%2Fwww.23qb.com%2F"
searchURL = websiteURL + "/saerch.php"
idReg = `/(\d+)/`
)
@@ -40,25 +37,35 @@ const (
var gCurCookieJar *cookiejar.Jar
func init() {
control.Register("novel", order.AcquirePrio(), &control.Options{
control.Register("novel", &control.Options{
DisableOnDefault: false,
Help: "铅笔小说网搜索\n- 小说[xxx]",
}).OnRegex("^小说([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女祈祷中......"))
login(username, password)
err := login(username, password)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
searchKey := ctx.State["regex_matched"].([]string)[1]
searchHTML := search(searchKey)
searchHTML, err := search(searchKey)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
doc, err := htmlquery.Parse(strings.NewReader(searchHTML))
if err != nil {
log.Errorln("[novel]", err)
ctx.SendChain(message.Text("ERROR:", err))
return
}
htmlTitle := htmlquery.InnerText(htmlquery.FindOne(doc, "/html/head/title"))
switch htmlTitle {
case websiteTitle:
list, err := htmlquery.QueryAll(doc, "//dl[@id='nr']")
if err != nil {
log.Errorln("[novel]", err)
ctx.SendChain(message.Text("ERROR:", err))
return
}
if len(list) != 0 {
txt := ""
@@ -81,10 +88,11 @@ func init() {
}
data, err := text.RenderToBase64(txt, text.FontFile, 400, 20)
if err != nil {
log.Println("err:", err)
ctx.SendChain(message.Text("ERROR:", err))
return
}
if id := ctx.SendChain(message.Image("base64://" + helper.BytesToString(data))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
ctx.SendChain(message.Text("ERROR:可能被风控了"))
}
} else {
text := htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@id='tipss']"))
@@ -116,38 +124,39 @@ func init() {
})
}
func login(username, password string) {
func login(username, password string) (err error) {
gCurCookieJar, _ = cookiejar.New(nil)
client := &http.Client{
Jar: gCurCookieJar,
}
usernameData, err := ub.UTF82GBK(helper.StringToBytes(username))
if err != nil {
log.Errorln("[novel]", err)
return
}
usernameGbk := helper.BytesToString(usernameData)
passwordData, err := ub.UTF82GBK(helper.StringToBytes(password))
if err != nil {
log.Errorln("[novel]", err)
return
}
passwordGbk := helper.BytesToString(passwordData)
loginReq, err := http.NewRequest("POST", loginURL, strings.NewReader(fmt.Sprintf("username=%s&password=%s&usecookie=315360000&action=login&submit=%s", url.QueryEscape(usernameGbk), url.QueryEscape(passwordGbk), submit)))
if err != nil {
log.Errorln("[novel]", err)
return
}
loginReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
loginReq.Header.Set("User-Agent", ua)
loginResp, err := client.Do(loginReq)
if err != nil {
log.Errorln("[novel]", err)
return
}
defer loginResp.Body.Close()
_ = loginResp.Body.Close()
return
}
func search(searchKey string) (searchHTML string) {
func search(searchKey string) (searchHTML string, err error) {
searchKeyData, err := ub.UTF82GBK(helper.StringToBytes(searchKey))
if err != nil {
log.Errorln("[novel]", err)
return
}
searchKeyGbk := helper.BytesToString(searchKeyData)
client := &http.Client{
@@ -155,23 +164,23 @@ func search(searchKey string) (searchHTML string) {
}
searchReq, err := http.NewRequest("POST", searchURL, strings.NewReader(fmt.Sprintf("searchkey=%s&searchtype=all", url.QueryEscape(searchKeyGbk))))
if err != nil {
log.Errorln("[novel]", err)
return
}
searchReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
searchReq.Header.Set("User-Agent", ua)
searchResp, err := client.Do(searchReq)
if err != nil {
log.Errorln("[novel]", err)
return
}
defer searchResp.Body.Close()
searchData, err := ioutil.ReadAll(searchResp.Body)
searchData, err := io.ReadAll(searchResp.Body)
_ = searchResp.Body.Close()
if err != nil {
log.Errorf("[novel] get response for url=%s got error=%s\n", searchURL, err.Error())
return
}
searchData, err = ub.GBK2UTF8(searchData)
if err != nil {
log.Errorln("[novel]", err)
return
}
searchHTML = helper.BytesToString(searchData)
return searchHTML
return searchHTML, nil
}

View File

@@ -8,49 +8,48 @@ import (
"github.com/FloatTech/zbputils/process"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
const hso = "https://gchat.qpic.cn/gchatpic_new//--4234EDEC5F147A4C319A41149D7E0EA9/0"
func init() {
engine := control.Register("nsfw", order.AcquirePrio(), &control.Options{
engine := control.Register("nsfw", &control.Options{
DisableOnDefault: false,
Help: "nsfw图片识别\n- nsfw打分[图片]",
}).ApplySingle(ctxext.DefaultSingle)
// 上传一张图进行评价
engine.OnKeywordGroup([]string{"nsfw打分"}, zero.OnlyGroup, ctxext.MustProvidePicture).SetBlock(true).
engine.OnKeywordGroup([]string{"nsfw打分"}, zero.OnlyGroup, zero.MustProvidePicture).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
url := ctx.State["image_url"].([]string)
if len(url) > 0 {
ctx.SendChain(message.Text("少女祈祷中..."))
p, err := nsfw.Classify(url...)
p, err := nsfw.Classify(url[0])
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(judge(p[0]))))
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(judge(p))))
}
})
en := control.Register("nsfwauto", order.AcquirePrio(), &control.Options{
control.Register("nsfwauto", &control.Options{
DisableOnDefault: true,
Help: "nsfw图片自动识别\n- 当图片属于非 neutral 类别时自动发送评价",
})
en.OnMessage(ctxext.IsPicExists).SetBlock(false).
}).OnMessage(zero.HasPicture).SetBlock(false).
Handle(func(ctx *zero.Ctx) {
url := ctx.State["image_url"].([]string)
if len(url) > 0 {
process.SleepAbout1sTo2s()
p, err := nsfw.Classify(url...)
p, err := nsfw.Classify(url[0])
if err != nil {
return
}
process.SleepAbout1sTo2s()
autojudge(ctx, p[0])
autojudge(ctx, p)
}
})
}
func judge(p nsfw.Picture) string {
func judge(p *nsfw.Picture) string {
if p.Neutral > 0.3 {
return "普通哦"
}
@@ -72,7 +71,7 @@ func judge(p nsfw.Picture) string {
return c
}
func autojudge(ctx *zero.Ctx, p nsfw.Picture) {
func autojudge(ctx *zero.Ctx, p *nsfw.Picture) {
if p.Neutral > 0.3 {
return
}
@@ -96,6 +95,6 @@ func autojudge(ctx *zero.Ctx, p nsfw.Picture) {
i++
}
if i > 0 {
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(c)))
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(c, "\n"), message.Image(hso)))
}
}

View File

@@ -1,12 +1,18 @@
package omikuji
import "strconv"
import (
"strconv"
sql "github.com/FloatTech/sqlite"
)
type kuji struct {
ID uint8 `db:"id"`
Text string `db:"text"`
}
var db = &sql.Sqlite{}
// 返回一个解签
func getKujiByBango(id uint8) string {
var s kuji

73
plugin/omikuji/sensou.go Normal file
View File

@@ -0,0 +1,73 @@
// Package omikuji 浅草寺求签
package omikuji
import (
"fmt"
"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"
"github.com/FloatTech/zbputils/ctxext"
"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{
DisableOnDefault: false,
Help: "浅草寺求签\n" +
"- 求签 | 占卜\n- 解签",
PublicDataFolder: "Omikuji",
}).ApplySingle(ctxext.DefaultSingle)
engine.OnFullMatchGroup([]string{"求签", "占卜"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
i := ctxext.RandSenderPerDayN(ctx, 100) + 1
ctx.SendChain(
message.At(ctx.Event.UserID),
message.Image(fmt.Sprintf(bed, i, 0)),
message.Image(fmt.Sprintf(bed, i, 1)),
)
})
engine.OnFullMatch("解签", ctxext.DoOnceOnSuccess(
func(ctx *zero.Ctx) bool {
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.Create("kuji", &kuji{})
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
n, err := db.Count("kuji")
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
logrus.Infof("[kuji]读取%d条签文", n)
return true
},
)).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
kujiBytes, err := text.RenderToBase64(
getKujiByBango(
uint8(ctxext.RandSenderPerDayN(ctx, 100)+1),
),
text.FontFile, 400, 20,
)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if id := ctx.SendChain(message.At(ctx.Event.UserID), message.Image("base64://"+helper.BytesToString(kujiBytes))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR:可能被风控了"))
}
})
}

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

@@ -0,0 +1,421 @@
// Package qqwife 娶群友 基于“翻牌”和江林大佬的“群老婆”插件魔改作品
package qqwife
import (
"math/rand"
"sort"
"strconv"
"sync"
"time"
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/ctxext"
"github.com/FloatTech/zbputils/math"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
)
//nolint: asciicheck
type 婚姻登记 struct {
sync.Mutex
mp map[int64]map[int64]*userinfo
}
// 结婚证信息
type userinfo struct {
target int64 // 对象身份证号
username string // 户主名称
targetname string // 对象名称
}
//nolint: asciicheck
func 新登记处() (db 婚姻登记) {
db.mp = make(map[int64]map[int64]*userinfo, 64)
return
}
func (db *婚姻登记) 重置() {
db.Lock()
defer db.Unlock()
for k := range db.mp {
delete(db.mp, k)
}
}
func (db *婚姻登记) 离婚休妻(gid, wife int64) {
db.Lock()
defer db.Unlock()
delete(db.mp[gid], -wife)
}
func (db *婚姻登记) 离婚休夫(gid, husband int64) {
db.Lock()
defer db.Unlock()
delete(db.mp[gid], husband)
}
func (db *婚姻登记) 有登记(gid int64) (ok bool) {
db.Lock()
defer db.Unlock()
mp, ok := db.mp[gid]
if !ok {
return
}
for range mp {
return true
}
return
}
func (db *婚姻登记) 花名册(ctx *zero.Ctx, gid int64) string {
db.Lock()
defer db.Unlock()
mp, ok := db.mp[gid]
if !ok {
return "民政局的花名册出问题了额..."
}
return binary.BytesToString(binary.NewWriterF(func(w *binary.Writer) {
w.WriteString("群老公←———→群老婆\n-----------")
for uid, userinfo := range mp {
if uid > 0 {
_ = w.WriteByte('\n')
w.WriteString(userinfo.username)
w.WriteString(" & ")
w.WriteString(userinfo.targetname)
}
}
}))
}
func (db *婚姻登记) 查户口(gid, uid int64) (userinfo *userinfo, gender int, ok bool) {
db.Lock()
defer db.Unlock()
gender = 0
mp, ok := db.mp[gid]
if !ok {
return
}
userinfo, ok = mp[uid]
if !ok {
gender = 1
userinfo, ok = mp[-uid]
}
return
}
func (db *婚姻登记) 登记(gid, uid, target int64, username, targetname string) {
db.Lock()
defer db.Unlock()
_, ok := db.mp[gid]
if !ok {
db.mp[gid] = make(map[int64]*userinfo, 32)
}
// 填写夫妻信息
uidinfo := &userinfo{
target: target,
username: username,
targetname: targetname,
}
targetinfo := &userinfo{
target: uid,
username: targetname,
targetname: username,
}
// 民政局登记数据
db.mp[gid][uid] = uidinfo
db.mp[gid][-target] = targetinfo
}
var (
//nolint: asciicheck
民政局 = 新登记处()
skillCD = rate.NewManager[string](time.Hour*24, 1)
lastdate time.Time
sendtext = [...][]string{
{ // 表白成功
"今天你向ta表白了ta羞涩的点了点头同意了\n",
"你对ta说“以我之名冠你指间一天相伴一天相随”.ta捂着嘴点了点头\n\n",
},
{ // 表白失败
"今天你向ta表白了ta毫无感情的拒绝了你",
"今天你向ta表白了ta对你说“你是一个非常好的人”",
"今天你向ta表白了ta给了你一个拥抱后擦肩而过",
},
{ // ntr成功
"你处心积虑的接近tata最终选择跟随你\n",
},
}
)
func init() {
engine := control.Register("qqwife", &control.Options{
DisableOnDefault: false,
Help: "一群一天一夫一妻制群老婆\n每天凌晨刷新CP\n" +
"- 娶群友\n- 群老婆列表\n" +
"--------------------------------\n以下技能每人只能二选一\n CD24H不跨天刷新\n--------------------------------\n" +
"- (娶|嫁)@对方QQ\n- 当[对方Q号|@对方QQ]的小三\n",
})
engine.OnFullMatch("娶群友", zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
if time.Now().Day() != lastdate.Day() {
民政局.重置()
// 更新时间
lastdate = time.Now()
}
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
targetinfo, status, ok := 民政局.查户口(gid, uid)
if ok {
switch status {
case 0: // 娶过别人
ctx.SendChain(
message.At(uid),
message.Text("今天你的群老婆是"),
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, ")哒",
),
)
default: // 嫁给别人
ctx.SendChain(
message.At(uid),
message.Text("今天你的群老公是"),
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
}
// 无缓存获取群员列表
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()
_, _, ok := 民政局.查户口(gid, usr)
if ok {
continue
}
qqgrouplist = append(qqgrouplist, usr)
}
// 没有人(只剩自己)的时候
if len(qqgrouplist) == 0 {
ctx.SendChain(message.Text("噢, 此时此刻你还是一只单身狗, 等待下一次情缘吧"))
return
}
// 随机抽娶
fiancee := qqgrouplist[rand.Intn(len(qqgrouplist))]
if fiancee == uid { // 如果是自己
ctx.SendChain(message.Text("噢, 此时此刻你还是一只单身狗, 等待下一次情缘吧"))
return
}
// 去民政局办证
民政局.登记(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
// 请大家吃席
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, 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
if uid == fiancee { // 如果是自己
ctx.SendChain(message.Text("今日获得成就:自恋狂"))
return
}
if rand.Intn(2) == 1 { // 二分之一的概率表白成功
gid := ctx.Event.GroupID
// 去民政局登记
var choicetext string
switch choice {
case "娶":
民政局.登记(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
choicetext = "今天你的群老婆是"
default:
民政局.登记(gid, fiancee, uid, ctx.CardOrNickName(fiancee), ctx.CardOrNickName(uid))
choicetext = "今天你的群老公是"
}
// 请大家吃席
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, ")哒",
),
)
return
}
ctx.SendChain(message.Text(sendtext[1][rand.Intn(len(sendtext[1]))]))
})
// NTR技能
engine.OnRegex(`^当(\[CQ:at,qq=(\d+)\] |(\d+))的小三`, zero.OnlyGroup, 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)
if rand.Intn(10)/4 != 0 { // 十分之三的概率NTR成功
ctx.SendChain(message.Text("你的ntr计划失败了"))
return
}
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
// 判断target是老公还是老婆
var choicetext string
targetinfo, gender, _ := 民政局.查户口(gid, fiancee)
switch gender {
case 0:
// 让对象离婚
民政局.离婚休妻(gid, targetinfo.target)
// 和对象结婚登记
choicetext = "老公"
民政局.登记(gid, fiancee, uid, ctx.CardOrNickName(fiancee), ctx.CardOrNickName(uid))
default:
// 让对象离婚
民政局.离婚休夫(gid, targetinfo.target)
// 和对象结婚登记
choicetext = "老婆"
民政局.登记(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
}
// 输出结果
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).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
if !民政局.有登记(ctx.Event.GroupID) {
ctx.SendChain(message.Text("你群并没有任何的CP额"))
return
}
ctx.SendChain(message.Text(民政局.花名册(ctx, ctx.Event.GroupID)))
})
}
// 以群号和昵称为限制
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 {
gid := ctx.Event.GroupID
if !民政局.有登记(gid) {
return true // 如果没有人登记,说明全是单身
}
fiancee, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
if err != nil {
ctx.SendChain(message.Text("额你的target好像不存在"))
return false
}
// 获取用户信息
uid := ctx.Event.UserID
uidtarget, uidstatus, ok1 := 民政局.查户口(gid, uid)
_, fianceestatus, ok2 := 民政局.查户口(gid, fiancee)
if !ok1 && !ok2 { // 必须是两个单身
return true
}
if ok1 {
if uidtarget.target == fiancee { // 如果本就是一块
ctx.SendChain(message.Text("笨蛋~你们明明已经在一起了啊w"))
return false
}
switch uidstatus {
case 0: // 如果如为攻
ctx.SendChain(message.Text("笨蛋~你家里还有个吃白饭的w"))
default: // 如果为受
ctx.SendChain(message.Text("该是0就是0当0有什么不好"))
}
return false
}
if ok2 {
switch fianceestatus {
case 0: // 如果如为攻
ctx.SendChain(message.Text("他有别的女人了,你该放下了"))
default: // 如果为受
ctx.SendChain(message.Text("这是一个纯爱的世界拒绝NTR"))
}
return false
}
return true
}
// 注入判断 是否满足小三要求
func checkcp(ctx *zero.Ctx) bool {
// 检查群内是否有人登记了
gid := ctx.Event.GroupID
if !民政局.有登记(gid) {
ctx.SendChain(message.Text("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
if fiancee == uid {
ctx.SendChain(message.Text("自我攻略?"))
return false
}
// 检查用户是否登记过
userinfo, uidstatus, ok := 民政局.查户口(gid, uid)
if ok {
if userinfo.target == fiancee { // 如果本就是一块
ctx.SendChain(message.Text("笨蛋~你们明明已经在一起了啊w"))
return false
}
switch uidstatus {
case 0: // 如果如为攻
ctx.SendChain(message.Text("抱歉,建国之后不支持后宫"))
default: // 如果为受
ctx.SendChain(message.Text("该是0就是0当0有什么不好"))
}
return false
}
_, _, ok = 民政局.查户口(gid, fiancee)
if !ok {
ctx.SendChain(message.Text("ta无法达成你当小三的条件"))
return false
}
return true
}

View File

@@ -4,7 +4,13 @@ import (
wr "github.com/mroth/weightedrand"
)
type rate []struct {
Name string `json:"name"`
Weight float64 `json:"weight"`
}
var (
areac *wr.Chooser
gender, _ = wr.NewChooser(
wr.Choice{Item: "男孩子", Weight: 50707},
wr.Choice{Item: "女孩子", Weight: 48292},

16
plugin/reborn/load.go Normal file
View File

@@ -0,0 +1,16 @@
package reborn
import (
"encoding/json"
"github.com/FloatTech/zbputils/file"
)
// load 加载rate数据
func load(area *rate, jsonfile string) error {
data, err := file.GetLazyData(jsonfile, true)
if err != nil {
return err
}
return json.Unmarshal(data, area)
}

54
plugin/reborn/main.go Normal file
View File

@@ -0,0 +1,54 @@
// Package reborn 投胎 来自 https://github.com/YukariChiba/tgbot/blob/main/modules/Reborn.py
package reborn
import (
"fmt"
"math/rand"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
wr "github.com/mroth/weightedrand"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
en := control.Register("reborn", &control.Options{
DisableOnDefault: false,
Help: "投胎\n- reborn",
PublicDataFolder: "Reborn",
})
en.OnFullMatch("reborn", ctxext.DoOnceOnSuccess(
func(ctx *zero.Ctx) bool {
datapath := en.DataFolder()
jsonfile := datapath + "rate.json"
area := make(rate, 226)
err := load(&area, jsonfile)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
choices := make([]wr.Choice, len(area))
for i, a := range area {
choices[i].Item = a.Name
choices[i].Weight = uint(a.Weight * 1e9)
}
areac, err = wr.NewChooser(choices...)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return false
}
logrus.Printf("[Reborn]读取%d个国家/地区", len(area))
return true
},
)).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if rand.Int31() > 1<<27 {
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("投胎成功!\n您出生在 %s, 是 %s。", randcoun(), randgen())))
} else {
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("投胎失败!\n您没能活到出生祝您下次好运"))
}
})
}

View File

@@ -3,7 +3,7 @@ package runcode
import (
"errors"
"io/ioutil"
"io"
"net/http"
"net/url"
"strings"
@@ -14,8 +14,6 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
"github.com/tidwall/gjson"
)
@@ -93,7 +91,7 @@ var (
)
func init() {
control.Register("runcode", order.AcquirePrio(), &control.Options{
control.Register("runcode", &control.Options{
DisableOnDefault: false,
Help: "在线代码运行: \n" +
">runcode [language] [code block]\n" +
@@ -104,9 +102,10 @@ func init() {
"JavaScript || TypeScript || PHP || Shell \n" +
"Kotlin || Rust || Erlang || Ruby || Swift \n" +
"R || VB || Py2 || Perl || Pascal || Scala",
}).ApplySingle(ctxext.DefaultSingle).OnRegex(`^>runcode\s(.+?)\s([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).
}).ApplySingle(ctxext.DefaultSingle).OnRegex(`^>runcode(raw)?\s(.+?)\s([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
language := ctx.State["regex_matched"].([]string)[1]
israw := ctx.State["regex_matched"].([]string)[1] != ""
language := ctx.State["regex_matched"].([]string)[2]
language = strings.ToLower(language)
if runType, exist := table[language]; !exist {
// 不支持语言
@@ -116,10 +115,9 @@ func init() {
)
} else {
// 执行运行
block := ctx.State["regex_matched"].([]string)[2]
block = message.UnescapeCQCodeText(block)
if block == "help" {
// 输出模板
block := message.UnescapeCQText(ctx.State["regex_matched"].([]string)[3])
switch block {
case "help":
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, " ", language, "-template:\n"),
message.Text(
@@ -127,19 +125,23 @@ func init() {
templates[language],
),
)
} else {
default:
if output, err := runCode(block, runType); err != nil {
// 运行失败
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
message.Text("ERROR: ", err),
message.Text("ERROR:", err),
)
} else {
// 运行成功
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
message.Text(output),
)
if israw {
ctx.SendChain(message.Text(output))
} else {
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
message.Text(output),
)
}
}
}
}
@@ -177,7 +179,7 @@ func runCode(code string, runType [2]string) (string, error) {
if body.StatusCode != http.StatusOK {
return "", errors.New("code not 200")
}
res, err := ioutil.ReadAll(body.Body)
res, err := io.ReadAll(body.Body)
if err != nil {
return "", err
}

206
plugin/saucenao/searcher.go Normal file
View File

@@ -0,0 +1,206 @@
// Package saucenao P站ID/saucenao/ascii2d搜图
package saucenao
import (
"fmt"
"net/http"
"os"
"reflect"
"strconv"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/AnimeAPI/ascii2d"
"github.com/FloatTech/AnimeAPI/pixiv"
"github.com/jozsefsallai/gophersauce"
"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{
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) {
id, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
ctx.SendChain(message.Text("少女祈祷中......"))
// 获取P站插图信息
illust, err := pixiv.Works(id)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if illust.Pid > 0 {
name := strconv.FormatInt(illust.Pid, 10)
var imgs message.Message
for i := range illust.ImageUrls {
f := file.BOTPATH + "/" + illust.Path(i)
n := name + "_p" + strconv.Itoa(i)
var m *pool.Image
if file.IsNotExist(f) {
m, err = pool.GetImage(n)
if err == nil {
imgs = append(imgs, message.Image(m.String()))
continue
}
logrus.Debugln("[sausenao]开始下载", n)
logrus.Debugln("[sausenao]urls:", illust.ImageUrls)
err1 := illust.DownloadToCache(i)
if err1 == nil {
m.SetFile(f)
_, _ = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
}
if err1 != nil {
logrus.Debugln("[sausenao]下载err:", err1)
}
}
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,
)
if imgs != nil {
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)
}
} else {
ctx.SendChain(message.Text("图片不存在!"))
}
})
// 以图搜图
engine.OnKeywordGroup([]string{"以图搜图", "搜索图片", "以图识图"}, zero.OnlyGroup, zero.MustProvidePicture).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 开始搜索图片
ctx.SendChain(message.Text("少女祈祷中..."))
for _, pic := range ctx.State["image_url"].([]string) {
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 {
ctx.SendChain(message.Text("请私聊发送 设置 saucenao api key [apikey] 以启用 saucenao 搜图, key 请前往 https://saucenao.com/user.php?page=search-api 获取"))
}
// ascii2d 搜索
if result, err := ascii2d.Ascii2d(pic); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
continue
} else {
msg := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text("ascii2d搜图结果"))}
for i := 0; i < len(result) && i < 5; i++ {
msg = append(msg, ctxext.FakeSenderForwardNode(ctx,
message.Image(result[i].Thumb),
message.Text(fmt.Sprintf(
"标题: %s\n图源: %s\n画师: %s\n画师链接: %s\n图片链接: %s",
result[i].Name,
result[i].Type,
result[i].AuthNm,
result[i].Author,
result[i].Link,
))),
)
}
if id := ctx.SendGroupForwardMessage(
ctx.Event.GroupID,
msg,
).Get("message_id").Int(); id == 0 {
ctx.SendChain(message.Text("ERROR:可能被风控了"))
}
}
}
})
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

@@ -2,54 +2,100 @@
package scale
import (
"bytes"
"image"
"math"
"os"
"strconv"
"time"
"github.com/FloatTech/AnimeAPI/nsfw"
"github.com/FloatTech/AnimeAPI/scale"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/file"
_ "image/gif" // import gif decoding
_ "image/jpeg" // import jpg decoding
_ "image/png" // import png decoding
_ "golang.org/x/image/webp" // import webp decoding
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
"github.com/FloatTech/AnimeAPI/nsfw"
"github.com/FloatTech/AnimeAPI/scale"
"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/writer"
"github.com/FloatTech/zbputils/web"
)
const cachedir = "data/scale/"
func init() {
_ = os.RemoveAll(cachedir)
err := os.MkdirAll(cachedir, 0755)
if err != nil {
panic(err)
}
engine := control.Register("scale", order.AcquirePrio(), &control.Options{
DisableOnDefault: false,
Help: "叔叔的AI二次元图片放大\n- 放大图片[图片]",
engine := control.Register("scale", &control.Options{
DisableOnDefault: false,
Help: "叔叔的AI二次元图片放大\n- 放大图片[图片]",
PrivateDataFolder: "scale",
}).ApplySingle(ctxext.DefaultSingle)
cachedir := engine.DataFolder()
// 上传一张图进行评价
engine.OnKeywordGroup([]string{"放大图片"}, zero.OnlyGroup, ctxext.MustProvidePicture, getPara).SetBlock(true).
engine.OnKeywordGroup([]string{"放大图片"}, zero.OnlyGroup, zero.MustProvidePicture, getPara).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
url := ctx.State["image_url"].([]string)
if len(url) > 0 {
datachan := make(chan []byte, 1)
var errsub error
go func() {
var d []byte
d, errsub = web.GetData(url[0])
datachan <- d
}()
ctx.SendChain(message.Text("少女祈祷中..."))
p, err := nsfw.Classify(url[0])
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
if p[0].Drawings < 0.1 || p[0].Neutral > 0.8 {
if p.Drawings < 0.1 || p.Neutral > 0.8 {
ctx.SendChain(message.Text("请发送二次元图片!"))
return
}
paras := ctx.State["scale_paras"].([2]int)
data, err := scale.Get(url[0], paras[0], paras[1], 2)
data := <-datachan
if errsub != nil {
ctx.SendChain(message.Text("ERROR:", errsub))
return
}
im, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
px := im.Bounds().Size().X * im.Bounds().Size().Y
paras := ctx.State["scale_paras"].([2]int)
if px > 512*512 {
px = int(math.Pow(float64(px), 0.5) + 0.5)
x := im.Bounds().Size().X * 512 / px
y := im.Bounds().Size().Y * 512 / px
ctx.SendChain(message.Text("图片", im.Bounds().Size().X, "x", im.Bounds().Size().Y, "过大,调整图片至", x, "x", y))
im = img.Size(im, x, y).Im
w := binary.SelectWriter()
defer binary.PutWriter(w)
_, err = writer.WriteTo(im, w)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
data, err = scale.Post(bytes.NewReader(w.Bytes()), paras[0], paras[1], 2)
} else {
data, err = scale.Get(url[0], paras[0], paras[1], 2)
}
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
n := cachedir + strconv.Itoa(int(ctx.Event.UserID))
f, err := os.Create(n)
if err != nil {
@@ -64,7 +110,7 @@ func init() {
}
func getPara(ctx *zero.Ctx) bool {
next := zero.NewFutureEvent("message", 999, false, zero.CheckUser(ctx.Event.UserID))
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
recv, cancel := next.Repeat()
i := 0
paras := [2]int{}
@@ -72,9 +118,10 @@ func getPara(ctx *zero.Ctx) bool {
for {
select {
case <-time.After(time.Second * 120):
cancel()
return false
case e := <-recv:
msg := e.Message.ExtractPlainText()
case c := <-recv:
msg := c.Event.Message.ExtractPlainText()
num, err := strconv.Atoi(msg)
if err != nil {
ctx.SendChain(message.Text("请输入数字!"))

View File

@@ -4,10 +4,13 @@ import (
"os"
"time"
_ "github.com/fumiama/sqlite3" // import sql
"github.com/jinzhu/gorm"
_ "github.com/logoove/sqlite" // import sql
)
// sdb 得分数据库
var sdb *scoredb
// scoredb 分数数据库
type scoredb gorm.DB
@@ -62,7 +65,7 @@ func (sdb *scoredb) Close() error {
// GetScoreByUID 取得分数
func (sdb *scoredb) GetScoreByUID(uid int64) (s scoretable) {
db := (*gorm.DB)(sdb)
db.Debug().Model(&scoretable{}).FirstOrCreate(&s, "uid = ? ", uid)
db.Model(&scoretable{}).FirstOrCreate(&s, "uid = ? ", uid)
return s
}
@@ -73,13 +76,13 @@ func (sdb *scoredb) InsertOrUpdateScoreByUID(uid int64, score int) (err error) {
UID: uid,
Score: score,
}
if err = db.Debug().Model(&scoretable{}).First(&s, "uid = ? ", uid).Error; err != nil {
if err = db.Model(&scoretable{}).First(&s, "uid = ? ", uid).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
err = db.Debug().Model(&scoretable{}).Create(&s).Error // newUser not user
err = db.Model(&scoretable{}).Create(&s).Error // newUser not user
}
} else {
err = db.Debug().Model(&scoretable{}).Where("uid = ? ", uid).Update(
err = db.Model(&scoretable{}).Where("uid = ? ", uid).Update(
map[string]interface{}{
"score": score,
}).Error
@@ -90,7 +93,7 @@ func (sdb *scoredb) InsertOrUpdateScoreByUID(uid int64, score int) (err error) {
// GetSignInByUID 取得签到次数
func (sdb *scoredb) GetSignInByUID(uid int64) (si signintable) {
db := (*gorm.DB)(sdb)
db.Debug().Model(&signintable{}).FirstOrCreate(&si, "uid = ? ", uid)
db.Model(&signintable{}).FirstOrCreate(&si, "uid = ? ", uid)
return si
}
@@ -101,16 +104,22 @@ func (sdb *scoredb) InsertOrUpdateSignInCountByUID(uid int64, count int) (err er
UID: uid,
Count: count,
}
if err = db.Debug().Model(&signintable{}).First(&si, "uid = ? ", uid).Error; err != nil {
if err = db.Model(&signintable{}).First(&si, "uid = ? ", uid).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
db.Debug().Model(&signintable{}).Create(&si) // newUser not user
db.Model(&signintable{}).Create(&si) // newUser not user
}
} else {
err = db.Debug().Model(&signintable{}).Where("uid = ? ", uid).Update(
err = db.Model(&signintable{}).Where("uid = ? ", uid).Update(
map[string]interface{}{
"count": count,
}).Error
}
return
}
func (sdb *scoredb) GetScoreRankByTopN(n int) (st []scoretable, err error) {
db := (*gorm.DB)(sdb)
err = db.Model(&scoretable{}).Order("score desc").Limit(n).Find(&st).Error
return
}

Some files were not shown because too many files have changed in this diff Show More