Compare commits

..

283 Commits

Author SHA1 Message Date
源文雨
bab5c4c308 🔖 v1.7.8 2024-04-30 17:51:36 +09:00
github-actions[bot]
e0891200af chore(lint): 改进代码样式 (#891)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-23 16:12:34 +09:00
himawari
b050b5d5b5 🐛 修复tts语音切换问题 (#890)
* 🐛 修复tts语音切换问题

* 🎨 文案不变化

* 🎨 语音放到上层方法

*  添加新回复模式

*  优化回复内容

* 🐛 调整顺序
2024-04-23 16:11:30 +09:00
源文雨
2ff164c2df chore(plugin): remove moegoe due to deletion 2024-04-14 15:28:03 +09:00
github-actions[bot]
cab917d054 chore(lint): 改进代码样式 (#888)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-13 17:52:33 +09:00
himawari
dfe6d347a5 添加两个api接口 (#886)
*  添加两个api接口

*  让代码简洁

*  一起处理

*  修改成map

* 🎨 删掉空
2024-04-13 17:51:13 +09:00
源文雨
5c6af1af61 chore(plugin): remove scale due to deletion 2024-04-11 16:35:39 +09:00
himawari
d7cdfb1544 Fix bilibilipush 20240404 (#884)
*  添加cookie

*  添加签名

* 🐛 修改嵌套错误

* 🐛 优化infoURL

*  添加cookie
2024-04-05 14:03:17 +09:00
源文雨
cf0e87ab9a 🔖 v1.7.7 2024-04-01 21:35:41 +09:00
源文雨
0a33224571 💩👌 make lint happy 2024-04-01 21:33:31 +09:00
源文雨
dd878f7dfe 💩👌 make lint happy 2024-04-01 21:31:04 +09:00
himawari
ac52c9cfca 🎨 修复查弹幕问题 (#883) 2024-04-01 21:26:12 +09:00
源文雨
ece68dae9b chore(revive): make lint happy 2024-03-04 15:38:26 +09:00
Eat Hatsune Shallots
6c20f22548 baidu: 对要查询的内容进行URI编码 (#866) 2024-03-04 15:33:36 +09:00
Nobody6825
6f2c9f7fc0 Initial Commit for nix (#856)
* Initial Commit for nix

* Update description

* nix fmt

* update version

---------

Co-authored-by: anonymous <anonymous@anonymous.anonymous44>
2024-01-27 16:11:24 +09:00
vatebur
b8858f0acd [issues 840] Modify the "score" of the Image send type add base64 (#853)
Modify the "score":Image send type add base64
适配shamrock,以路径发送图片失败后,使用base64发送图片。
2024-01-25 17:44:06 +09:00
vatebur
9c65383a7c update guessmusic:Reduce the difficulty (#854)
* update guessmusic:Reduce the difficulty

猜歌时忽略大小写和简繁体,降低猜歌难度

* chore(lint): 改进代码样式

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-25 17:40:11 +09:00
源文雨
a006b30392 Update pull.yml 2023-12-28 16:34:06 +09:00
源文雨
54c67e30f4 fix: danbooru 2023-11-19 19:03:28 +09:00
Jiang-Red
61168adb2e fix chess & kfc && optimize lolicon & bilibili (#817)
* fix chess & kfc && optimize bilibili & lolicon

* chore(lint): 改进代码样式 (#27)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-12 14:21:37 +09:00
Jiang-Red
73b879a6f4 fix hyaku & omikuji lazy & score (#815) 2023-11-08 22:06:05 +09:00
源文雨
a5d2e3dfc3 🔖 v1.7.6 2023-11-08 14:13:52 +09:00
源文雨
0ea804fc86 fix: hyaku 2023-11-08 14:13:26 +09:00
源文雨
17bfa2a35c 🔖 v1.7.5 2023-11-08 13:20:32 +09:00
源文雨
ff3d1d1de3 🐛 custom lazy 2023-11-08 13:20:04 +09:00
源文雨
3a31802735 🔖 v1.7.4 2023-11-07 21:51:40 +09:00
源文雨
a514bde4e6 使用自建data仓库 2023-11-07 21:47:55 +09:00
莫思潋
7f90ba278a update wife data (#811) 2023-11-05 22:45:09 +09:00
源文雨
2e77703571 enhance pull check 2023-11-05 16:00:27 +09:00
源文雨
192eef2bbb update deps 2023-10-17 23:54:57 +09:00
源文雨
73ecc47e4c Update README.md 2023-10-16 22:51:12 +09:00
源文雨
714df78ea2 Update README.md 2023-10-16 22:49:53 +09:00
源文雨
f4f50acb1d Update README.md 2023-10-16 22:49:07 +09:00
himawari
8c24194772 添加AI视频总结 (#787)
*  添加AI视频总结

* 🐛 添加空格

* 🎨 修改文本格式
2023-10-15 00:23:52 +09:00
源文雨
844b727859 fix action 2023-10-04 22:46:58 +09:00
Jiang-Red
148f271586 aifalse add nightstyle & chess use resvg (#782)
* aifalse add nightstyle & chess use resvg

* make lint happy

* make lint happy

* chore(lint): 改进代码样式 (#25)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-04 21:55:08 +09:00
Jiang-Red
b062198fae fix register (#778) 2023-10-02 23:08:57 +09:00
方柳煜
1c57a64002 Add files via upload (#774) 2023-10-01 12:39:17 +09:00
源文雨
13bb760f9f fix closepr 2023-10-01 12:31:17 +09:00
源文雨
6c1257184b fix closepr 2023-10-01 12:26:49 +09:00
源文雨
b0463b3cb4 chore: make lint happy 2023-09-24 13:15:49 +09:00
源文雨
1bb8e8b058 chore: make lint happy 2023-09-24 13:14:16 +09:00
源文雨
209b2e8a1f optimize: workflow 2023-09-24 13:12:45 +09:00
源文雨
0c55c743f7 optimize: workflow 2023-09-24 13:10:22 +09:00
吃饭
ba7c6cb0a0 bilibilipush添加艾特全体功能 (#758)
* 添加艾特全体功能

* bilibilipush添加艾特全体功能
2023-09-24 02:59:06 +09:00
源文雨
d3e587f935 fix: workflow 2023-09-20 21:03:09 +09:00
源文雨
36190a4f6a fix: workflow 2023-09-20 21:01:46 +09:00
源文雨
54d9486c06 fix: workflow 2023-09-20 21:00:50 +09:00
源文雨
fe6130872b fix: workflow 2023-09-20 20:59:29 +09:00
源文雨
5e41c15d88 fix: workflow 2023-09-20 20:58:31 +09:00
源文雨
e776d02d98 fix: workflow 2023-09-20 20:45:08 +09:00
源文雨
cc39d0fdb4 fix: workflow 2023-09-20 20:43:53 +09:00
源文雨
1456bed668 fix: workflow 2023-09-20 20:41:06 +09:00
源文雨
8d2da4199d fix: workflow 2023-09-20 20:40:24 +09:00
源文雨
50e75b2257 fix: workflow 2023-09-20 20:39:05 +09:00
源文雨
a6e82d578a fix: workflow 2023-09-20 20:37:11 +09:00
源文雨
5b6ab7e20d fix: workflow 2023-09-20 20:34:45 +09:00
源文雨
23fea2dae9 fix: workflow 2023-09-20 20:33:19 +09:00
源文雨
97c1985479 fix: workflow 2023-09-20 20:30:20 +09:00
源文雨
035ed3bd13 fix: workflow 2023-09-20 20:27:41 +09:00
源文雨
3e04445cac fix: workflow 2023-09-20 20:27:23 +09:00
源文雨
f0078bb23f fix: workflow 2023-09-20 20:24:31 +09:00
源文雨
1a8ebe02fb fix: workflow 2023-09-20 20:24:14 +09:00
源文雨
de986d8be8 fix: workflow 2023-09-20 20:16:11 +09:00
源文雨
ab7daa6bdc fix: workflow 2023-09-20 20:15:05 +09:00
源文雨
0bf3253cbb fix: workflow 2023-09-20 20:11:43 +09:00
源文雨
21269ee835 fix: workflow 2023-09-20 20:06:44 +09:00
源文雨
df927d0b7f fix: workflow 2023-09-20 20:06:29 +09:00
源文雨
6a3456f4b0 fix: workflow 2023-09-20 19:58:48 +09:00
源文雨
db1d583a37 feat(workflow): add job close-pr in pull.yml 2023-09-20 19:56:42 +09:00
源文雨
146ea6812e feat(workflow): add job close-pr in pull.yml 2023-09-20 19:52:47 +09:00
方柳煜
99b14e183a fix: mcfish (#743) 2023-09-19 21:19:48 +09:00
github-actions[bot]
cb52bf6af7 🎨 改进代码样式 (#737)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-15 10:42:00 +09:00
喵酱
a534c9efbd 导入钓鱼模拟器 (#732)
* 导入钓鱼模拟器

导入钓鱼模拟器

* Update main.go
2023-09-15 10:37:58 +09:00
github-actions[bot]
7ac397373d 🎨 改进代码样式 (#727)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-07 15:35:22 +08:00
方柳煜
73c6f4795e 优化钓鱼插件一些逻辑问题 (#726)
* Update main.go

* Update pole.go

* Update store.go

* Update main.go

* Update store.go

* Update store.go
2023-09-06 21:33:47 +08:00
github-actions[bot]
598efe182c 🎨 改进代码样式 (#725)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-03 23:05:48 +08:00
方柳煜
a9bb078079 修复钓鱼插件的逻辑错误 (#724)
* Update fish.go

* Update main.go

* Update fish.go

* Update fish.go

* Update main.go

* Update fish.go

* Update fish.go

* Update main.go
2023-09-03 23:04:26 +08:00
源文雨
673c715d2f optimize(mcfish): migrate to AutoRegister 2023-09-03 14:13:58 +08:00
github-actions[bot]
dbda1b466d 🎨 改进代码样式 (#723)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-03 14:12:33 +08:00
方柳煜
b7e21fc111 [新增插件]钓鱼模拟器 (#721)
* Add files via upload

* Update README.md

* Add files via upload

* Add files via upload

* Update pole.go

* Update pole.go

* Update main.go

* Add files via upload

* Add files via upload

* Update main.go

* Update pack.go

* Add files via upload
2023-09-03 14:09:37 +08:00
源文雨
6bff62b91b 插件名称自动注册 2023-09-03 13:53:25 +08:00
Aimer Neige
5485cc3be9 [BUG FIX] 国际象棋插件 bug 修复 (#722)
* 只有正确安装 inkscape 时才需要清理临时文件

* fix lint && bug
2023-09-02 23:09:34 +08:00
Aimer Neige
ba0ef37b74 国际象棋 (#720)
* init commit for chess

* fix lint & error

* remove issue link

* fix lint

* remove embed

* regex fix

* use strings.Builder

* 改不动了,先 push 了备份下

* 基本上改好了

* limit

* 使用等宽字体渲染棋盘

* use syncx

* 不会更新依赖库😭

* 先 push 备份下

* 更新依赖版本,确保能读取到字体文件

* fix log
2023-09-01 22:21:07 +08:00
源文雨
9676b26de0 🔖 v1.7.3 2023-08-28 16:14:49 +08:00
源文雨
30f60bc7e9 fix: gsvits 2023-08-28 00:21:41 +08:00
源文雨
9dade7f3e8 fix: customize tts download 2023-08-28 00:05:09 +08:00
源文雨
f043fbf0c0 fix: tts speaker 2023-08-27 23:30:26 +08:00
源文雨
e75814e3b3 fix windows 2023-08-27 23:06:41 +08:00
源文雨
245b50ba94 update genshin tts 2023-08-27 22:54:27 +08:00
源文雨
16e5b84e5c 🐛 fix: 优先级乱序 2023-08-27 16:28:11 +08:00
Jiang-Red
26e4b3c513 chore: bump to go1.21 (#717) 2023-08-25 21:56:27 +08:00
莲宝坏坏坏
986e50705d fix bilibili (#710)
* fix bilibili

* 1

* fix

* 123

* 做了一下修改的提交

* 1

* make master happy

* 最后一次
2023-08-23 12:25:22 +08:00
源文雨
38b11bb8c9 📝 edit README 2023-07-28 16:32:00 +08:00
源文雨
0357405cdf 🐛 心跳 2023-07-28 16:29:56 +08:00
源文雨
7f264964c2 🔖 v1.7.2 2023-07-28 13:59:33 +08:00
源文雨
c8dcdbb0b2 world: 一大波优化与功能更新
- fix #441
- 优化wsserver解析
- 完善 ctx.this 相关函数
- 自动已读: Config 的 MarkMessage
2023-07-28 13:56:48 +08:00
Jiang-Red
ebcd3cdef2 fix shindan (#706) 2023-07-27 13:20:51 +08:00
Jiang-Red
eb43f84d34 fix title (#705) 2023-07-23 00:41:00 +08:00
莫思潋
5931e03c00 *update help command (#703) 2023-07-18 23:46:28 +08:00
Jiang-Red
aaf659f6d4 fix runcode (#702)
* fix runcode

* fix permission
2023-07-17 22:57:58 +08:00
weigui404
f4add826ff Update README.md (#701) 2023-07-16 15:50:45 +08:00
Jiang-Red
0d8157e2f8 修复反向ws顺便禁用新版ci的某个功能 (#700) 2023-07-13 14:23:25 +08:00
alexskim
283667cfe5 修多功能抽签不刷新列表bug (#693) 2023-06-13 11:46:06 +08:00
源文雨
6403614fa8 🐛 fix control cache 2023-05-14 23:49:46 +08:00
源文雨
bdcb833217 🐛 fix control cache 2023-05-09 13:35:50 +08:00
源文雨
278d7e0cf9 🔖 v1.7.1 2023-04-30 13:52:25 +08:00
源文雨
821f8d4949 update wife 2023-04-30 13:51:25 +08:00
源文雨
436838d2f8 fix 2023-04-22 14:53:32 +08:00
源文雨
30301f1aba 🦙请求改POST 2023-04-22 14:40:35 +08:00
源文雨
df1d71b9b2 remove 🦙 reply 2023-04-21 14:49:34 +08:00
源文雨
0315718ab7 优化 2023-04-20 01:14:32 +08:00
源文雨
971c179227 优化 2023-04-19 23:26:15 +08:00
源文雨
1c0270fda0 thesarus add 🦙 2023-04-19 23:07:43 +08:00
源文雨
5463945b6c 🔖 v1.7.1-beta3 2023-04-19 11:36:52 +08:00
莲宝坏坏坏
8eb058fb26 add 维基百科 (#673)
* add 维基百科

* make happy
2023-04-19 00:47:44 +08:00
github-actions[bot]
33e5b0286f 🎨 改进代码样式 (#669)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 16:14:17 +08:00
GenesisAN
296fd60cd7 ️ gif改为使用base64发送 (#664) 2023-04-17 04:40:45 +00:00
himawari
667c9fbcca 添加据意查句 (#660) 2023-04-17 03:23:37 +00:00
莲宝坏坏坏
3d8d0ad107 fix 权重查询 (#666) 2023-04-15 15:32:09 +08:00
源文雨
f35a89e401 update deps 2023-04-15 13:13:37 +08:00
GenesisAN
c5c63d0b64 wfapi 锁问题修复,设置TLS请求为1.2 (#663)
Co-authored-by: GenesisAN <501946815@qq.com>
2023-04-12 14:02:49 +08:00
weigui404
3e15754031 Update shindan.go (#662) 2023-04-12 00:34:33 +08:00
源文雨
c1e37b293c remove ca 2023-04-11 19:48:32 +08:00
源文雨
8edc3f6de6 update deps 2023-04-11 14:00:06 +08:00
源文雨
416cb3f2b8 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2023-04-11 13:59:41 +08:00
源文雨
8050f12d51 db cache time to time.Hour 2023-04-11 13:59:33 +08:00
苜蓿紫
292fc311d6 fix dish.go (#661) 2023-04-11 11:56:24 +08:00
源文雨
28cb0491f7 🐛 fix ca 2023-04-10 23:28:21 +08:00
源文雨
1bad611018 🎨 优化触发权限 2023-04-10 14:21:27 +08:00
源文雨
d49224fd50 🐛 fix ca 2023-04-10 14:16:00 +08:00
源文雨
2324837052 🐛 fix ca 2023-04-10 13:52:48 +08:00
源文雨
35f8458d67 🐛 fix ca 2023-04-10 12:46:51 +08:00
源文雨
8a6b7f65c7 🐛 fix ca 2023-04-10 12:21:18 +08:00
源文雨
7b1d2b7eaa fix 设置语音模式 2023-04-10 11:57:10 +08:00
源文雨
7ced79c6bb fix 设置语音模式 2023-04-10 11:56:24 +08:00
源文雨
e224bf9252 add 插件冲突避免 2023-04-10 11:50:52 +08:00
源文雨
2b1caafa16 🔖 v1.7.1-beta2 2023-04-09 11:02:35 +08:00
源文雨
c1702c5d5e 百度tts自行指定 id&secret 2023-04-09 11:01:14 +08:00
源文雨
5c8ead8b1d fix extra 2023-04-08 17:18:36 +08:00
源文雨
635eb9832a fix help 2023-04-07 17:56:49 +08:00
源文雨
f1e49dc02e remove 拟声鸟, add TTSCN 2023-04-07 17:52:55 +08:00
github-actions[bot]
573c942a9d 🎨 改进代码样式 (#657)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-06 19:43:24 +08:00
Sunist
e8b61b39f0 HowToCook function Integration (#650) 2023-04-06 19:28:14 +08:00
Jiang-Red
ed26d31326 add: score new style (#655)
* newstyle

* make lint happy
2023-04-04 23:32:29 +08:00
源文雨
76dbf5a4b6 提高the触发概率 2023-03-31 15:54:28 +08:00
源文雨
f1ea658c7d 🔖 v1.7.1-beta1 2023-03-31 15:53:35 +08:00
源文雨
2964986ee5 font增加更多字体 2023-03-31 15:52:52 +08:00
github-actions[bot]
52ef28cd6a 🎨 改进代码样式 (#648)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-30 15:24:15 +08:00
莲宝坏坏坏
df4c0438a2 抖动文字 (#647) 2023-03-30 13:13:27 +08:00
苜蓿紫
864f92a728 增加签到3 (#644) 2023-03-27 22:43:19 +08:00
源文雨
6ea50cf8b7 降低simi触发概率 2023-03-25 22:09:27 +08:00
源文雨
d66dd9b7fa fix wifw 2023-03-25 21:56:43 +08:00
源文雨
4a15326977 优化wife 2023-03-25 21:51:52 +08:00
源文雨
b4a1f93993 fix wifw 2023-03-25 21:47:24 +08:00
源文雨
0c8dfb3f9c 优化 ctx ERROR 2023-03-25 20:23:56 +08:00
源文雨
1aa11879dc fix wife 2023-03-25 20:21:44 +08:00
源文雨
14c596be1f 🔖 v1.7.1-beta1 2023-03-25 20:10:19 +08:00
源文雨
309afecadd wife add brief 2023-03-25 20:09:04 +08:00
源文雨
f465e78460 恢复thesaurus 2023-03-25 20:06:49 +08:00
源文雨
aa5c324592 抽老婆插件 2023-03-25 17:36:17 +08:00
github-actions[bot]
1a0575af64 🎨 改进代码样式 (#638)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-25 11:07:00 +08:00
莲宝坏坏坏
587d3967ef 增加签到预设切换 (#634) 2023-03-25 03:06:00 +00:00
Sora39
d693f988bb fix: steam ヘルプにある api の申请地址 (#637) 2023-03-24 17:25:04 +08:00
anyanfei
500dcaa9ed fix: baidu 正则匹配 (#636) 2023-03-24 06:03:18 +00:00
莫思潋
1376803b07 fix: always (#633)
* update deps

* update always

* fix: always: broken images and fonts
2023-03-22 20:17:15 +08:00
源文雨
68386910c4 🔖 v1.7.0 2023-03-20 12:28:19 +08:00
莲宝坏坏坏
1734f1f7d4 更换百度一下为百度百科 (#627) 2023-03-20 12:23:52 +08:00
DreamZero
86b87c2b4e fix slow aifalse (#631) 2023-03-20 11:59:03 +08:00
DreamZero
e9eb4c5602 Fix steam & lint (#630)
* fix

* make lint happy
2023-03-20 11:57:46 +08:00
方柳煜
6474b36ccd 修复底部出现黑条的问题 (#626) 2023-03-18 12:07:13 +08:00
github-actions[bot]
107149892c 🎨 改进代码样式 (#625)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-18 00:32:36 +08:00
DreamZero
f1dba97922 feat: steam plugin (#621) 2023-03-18 00:30:22 +08:00
莲宝坏坏坏
bc3c4303be fix jiami api (#624) 2023-03-18 00:28:31 +08:00
源文雨
f7a61ed0ee 🎨 edit README 2023-03-16 19:24:26 +08:00
源文雨
107b38e2f5 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2023-03-16 19:22:38 +08:00
源文雨
0d85fa04e1 🔖 v1.7.0-beta5 2023-03-16 19:22:30 +08:00
KoiParadise
1d8f5a7869 fix: unexpected misplaced name (#622) 2023-03-16 19:21:18 +08:00
源文雨
5e93368e57 fix #586: 以图搜图分开发找不到 url 2023-03-16 19:20:28 +08:00
源文雨
56e931665e fix: gif by @nekohouse09 2023-03-16 19:18:35 +08:00
方柳煜
e5b2b369e3 修改加签逻辑 (#620)
* Update main.go

* Update main.go

* Update main.go
2023-03-15 23:03:01 +08:00
苜蓿紫
58cf08fc39 fix typo (#619)
* fix typo

* fix typo
2023-03-14 19:57:10 +08:00
源文雨
c18f9b8b72 🔖 v1.7.0-beta4 2023-03-12 12:28:53 +08:00
源文雨
0df465e1c6 fix: saucenao panic 2023-03-12 12:27:29 +08:00
himawari
8b010321d5 添加一言 (#616)
*  添加一言

* 🎨 优化随机数

* 🎨 更新包

* 🎨 优化随机结构

* 🎨 修改随机算法

---------

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2023-03-12 11:09:07 +08:00
Fox_white
e1591c44b6 Fix: Intn Panic when the len is 0 (#617) 2023-03-11 15:45:40 +08:00
源文雨
cc26eb1332 优化 ai_false diskstate 2023-03-11 11:48:40 +08:00
源文雨
366c7acb90 Update README.md 2023-03-10 22:26:33 +08:00
苜蓿紫
d8cb5206e8 update: drawlots (#613) 2023-03-09 22:14:26 +08:00
源文雨
90efebf02f 🔖 v1.7.0-beta3 2023-03-09 13:57:31 +08:00
源文雨
960cd3ad8b fix: drawlots 2023-03-09 13:56:51 +08:00
源文雨
09a3e807c9 🚑 默认不编译webui 2023-03-09 13:55:15 +08:00
苜蓿紫
fb2718b495 fix README.md (#612)
修正抽签readme
2023-03-09 13:29:31 +08:00
方柳煜
1550cb7fcc 新增多功能抽签插件 (#606) 2023-03-09 00:04:09 +08:00
源文雨
7b27bc8f7a update icon 2023-03-08 16:21:46 +08:00
github-actions[bot]
54598fbf54 🎨 改进代码样式 (#611)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-08 00:57:14 +08:00
himawari
bb844eaa40 Feature gui 20230219 (#597)
*  添加gui

* 🐛 添加位置

*  修改为0.0.0.0

*  添加webui说明

* 🎨 修改为本地

*  添加webui默认url

* 📝 修改readme

* 🎨 修改方法名

*  修改readme

* 🎨 修改命令

* 🎨 更新包

* 🎨 调整位置
2023-03-08 00:44:47 +08:00
源文雨
4ef6f584c9 Update README.md 2023-03-07 19:14:08 +08:00
源文雨
861b3cc82f 优化baiduaudit 2023-03-05 00:46:53 +08:00
源文雨
5226548cec 优化代码结构 2023-03-04 23:30:51 +08:00
github-actions[bot]
d41ae01f01 🎨 改进代码样式 (#609)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-04 19:57:35 +08:00
GenesisAN
e294059de4 fix 初始化未能获取数据的问题 (#602)
* fix 初始化未能获取数据的问题

* fix 添加读写锁

* fix lint

* fix lint

* change 改为全局锁
2023-03-04 19:54:56 +08:00
源文雨
84bc79eaa6 fix 2023-03-01 21:14:51 +08:00
源文雨
8f9a396821 fix: platform that fails to set vt100 2023-03-01 21:13:18 +08:00
源文雨
6f96c389c4 make ci happy 2023-03-01 16:21:18 +08:00
源文雨
c55e31ed6f 🔖 v1.7.0-beta1 2023-03-01 16:17:10 +08:00
源文雨
f3a0813fed edit README 2023-03-01 16:14:37 +08:00
源文雨
c1602c323d fix: md5 cat & add: updater cache 2023-03-01 16:10:24 +08:00
源文雨
1bceaa52ff fix winres 2023-03-01 14:49:34 +08:00
源文雨
86296a28df 优化 manifest 2023-03-01 14:35:13 +08:00
源文雨
fe9b5023f6 feat: add icon 2023-03-01 14:20:36 +08:00
源文雨
d68223f63d add winres 2023-03-01 12:45:35 +08:00
源文雨
1c274d6eb8 优化 banner 2023-03-01 12:22:14 +08:00
源文雨
0e52bbe0f7 fix: set title 2023-03-01 12:07:15 +08:00
源文雨
a177448315 fix: set title 2023-03-01 11:47:49 +08:00
源文雨
ca3ff1b522 fix: set title 2023-03-01 11:46:00 +08:00
源文雨
41f0b11469 fix: set title 2023-03-01 11:43:37 +08:00
源文雨
ba0e471a19 fix: set title 2023-03-01 11:39:47 +08:00
源文雨
84115a7316 优化 windows console 2023-03-01 11:26:21 +08:00
源文雨
4dc837854b fix windows console input 2023-03-01 11:11:01 +08:00
Fox_white
64f9e309ef Feat: Better Setup Console (#601)
* Feat: Better Setup Console

* Feat: Better Setup Console
2023-02-28 20:18:10 +08:00
源文雨
67a1050df6 make lint happy 2023-02-28 18:33:36 +08:00
源文雨
d85865825e 优化windows输出 2023-02-28 18:29:39 +08:00
源文雨
2704d3e7d4 优化color 2023-02-28 12:15:54 +08:00
源文雨
0944fc7854 优化arch 2023-02-28 11:45:03 +08:00
源文雨
611c275092 🔖 v1.6.2 2023-02-27 21:01:31 +08:00
莫思潋
e3e991e6ab fix: ent->enr (#600) 2023-02-27 19:45:17 +08:00
源文雨
f2cebcf95a edit help 2023-02-27 14:14:02 +08:00
源文雨
4aca16a393 make lint happy 2023-02-27 14:11:07 +08:00
源文雨
891bbb96aa make lint happy 2023-02-27 14:10:44 +08:00
源文雨
d60acd3a47 update to go1.20 2023-02-27 13:59:31 +08:00
源文雨
7dc6499127 edit readme 2023-02-27 13:54:18 +08:00
源文雨
f28e746652 aireply add chatgpt 2023-02-27 13:52:12 +08:00
源文雨
3c905d9061 moegoe 恢复原 API 2023-02-27 13:22:31 +08:00
himawari
091d3170fc Feature zbpp bilibilipush 20230224 (#599)
* 🔥 删除小鸡词典

*  添加新插件和修改bilibilipush问题

* 🎨 去掉多余结构

* 🎨 简化语句
2023-02-25 19:48:13 +08:00
源文雨
bdc4138d78 fix: fortune 2023-02-24 11:29:15 +08:00
源文雨
e231235ed1 fix: 自检 2023-02-19 20:05:03 +08:00
源文雨
1795b9196b fix: 自检 2023-02-19 20:03:33 +08:00
源文雨
d5d0563544 fix: 自检 2023-02-19 19:52:45 +08:00
源文雨
723b7a9857 fix: 自检 2023-02-19 19:40:17 +08:00
源文雨
6a0a16662e fix: slow 自检 2023-02-19 19:30:47 +08:00
github-actions[bot]
f82ba852ba 🎨 改进代码样式 (#588)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-17 13:07:21 +08:00
MoeMagicMango
180945670b feat:新设计的签到 (#587) 2023-02-17 13:03:44 +08:00
源文雨
56984ef7fb 🔖 v1.6.2-beta4 2023-02-15 17:27:52 +08:00
源文雨
ac4de84188 fix: render text 2023-02-15 17:27:29 +08:00
源文雨
591ad79201 🔖 v1.6.2-beta3 2023-02-10 15:00:18 +08:00
源文雨
2e51c9e9c3 🚀 优化字体加载 2023-02-10 14:59:27 +08:00
源文雨
ca89f01f7d update deps 2023-02-07 16:53:30 +08:00
lianhong2758
5dfc118f64 修复原神 vits api失效 (#582) 2023-02-07 16:50:09 +08:00
源文雨
2410a7b3ed make lint happy 2023-02-07 16:46:26 +08:00
源文雨
7e11924b3f update deps 2023-02-07 16:39:07 +08:00
lianhong2758
4f65900688 readme add kokomi (#579) 2023-02-07 12:20:21 +08:00
源文雨
20821827b3 🔖 v1.6.2-beta2 2023-02-06 21:47:25 +08:00
源文雨
3dd10169e3 update deps 2023-02-06 21:40:41 +08:00
DreamZero
8cd60a84d5 复制黏贴被发现了( (#578) 2023-02-06 16:49:55 +08:00
DreamZero
03a2f4c331 给aifalse加一点细节 (#575) 2023-02-05 12:59:50 +08:00
icarus-ai
cfc9b55fce 更新quic-go版本,以支持使用Go 1.20编译 (#577)
* 支持 Go 1.20

* fix workflows (≖_≖ )

* 回滚 workflows

* 回滚 workflows
2023-02-04 12:05:14 +08:00
苜蓿紫
fc99eb3e22 修正qq号大小比较 (#576) 2023-02-02 11:42:52 +08:00
源文雨
93625f9c4f 优化代码结构 2023-02-01 15:03:05 +08:00
苜蓿紫
b6ce9f7b2e 修正错别字&增加提示语 (#574)
* 修正错别字

* 修正错别字

* 增加整理提示语

代发方柳
2023-02-01 14:53:10 +08:00
github-actions[bot]
20642b3776 🎨 改进代码样式 (#573)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-01 11:52:42 +08:00
GenesisAN
16ab7c08f6 fix 初始化错误,改善阅读体验 (#572) 2023-02-01 11:47:04 +08:00
源文雨
7bce7f28dc make lint happy 2023-01-31 18:25:32 +08:00
源文雨
8c695c96d7 优化代码结构 2023-01-31 18:23:08 +08:00
源文雨
d4a057e21a 优化代码结构 2023-01-31 18:20:12 +08:00
github-actions[bot]
f18c809355 🎨 改进代码样式 (#571)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-31 16:30:11 +08:00
github-actions[bot]
0d9c8d9a43 🎨 改进代码样式 (#570)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-31 16:29:02 +08:00
github-actions[bot]
76e7f81a6c 🎨 改进代码样式 (#569)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-31 16:27:43 +08:00
方柳煜
faf00dfea7 优化好感度系统,修复重复人名问题 (#568) 2023-01-31 16:23:27 +08:00
GenesisAN
39af90e63d add WarframeAPI (#541) 2023-01-31 16:22:19 +08:00
源文雨
36b09b8e94 tts append 。 2023-01-30 18:36:47 +08:00
源文雨
7ec2b46d75 🔖 v1.6.2-beta1 2023-01-30 18:01:56 +08:00
源文雨
7cc5771a9a update deps 2023-01-30 18:00:14 +08:00
DreamZero
f96b5f8965 优化代码结构 (#565) 2023-01-30 17:42:53 +08:00
himawari
07e6f33b04 添加小说下载 (#553)
*  添加小说下载

* 🎨 修改readme

* 🎨 修lint

* 🎨 修改包

* 🎨 使用新版http封装

* 🎨 new line
2023-01-30 17:40:57 +08:00
源文雨
f1a33a1845 🔖 v1.6.1-fix1 2023-01-16 11:36:31 +08:00
源文雨
0a72566378 fix #561: render text black & shindan 2023-01-16 11:35:11 +08:00
lianhong2758
a029add486 权重查询美化 (#560) 2023-01-16 11:25:39 +08:00
源文雨
778b8749ea 🐛 修复pixiv无法获取original url 2023-01-13 16:28:17 +08:00
源文雨
7d5944fccf 🔖 v1.6.1 2023-01-13 00:51:00 +08:00
github-actions[bot]
3e16a24ab5 🎨 改进代码样式 (#559)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-12 18:21:06 +08:00
源文雨
ff682da3fe 🔥 remove atri sleep due to global latency 2023-01-12 18:17:12 +08:00
源文雨
a0120485de fix #551: atri 发图 2023-01-12 18:14:47 +08:00
181 changed files with 12163 additions and 2330 deletions

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

View File

@@ -28,7 +28,7 @@ jobs:
- name: Setup Go environment
uses: actions/setup-go@master
with:
go-version: 1.19
go-version: '1.20'
- name: Cache downloaded module
uses: actions/cache@master
with:

View File

@@ -1,6 +1,24 @@
name: PullLint
on: [ pull_request ]
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
jobs:
# This workflow closes invalid PR
close-pr:
name: closepr
# The type of runner that the job will run on
runs-on: ubuntu-latest
permissions: write-all
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: Close PR if commit message contains ".go"
if: contains(github.event.pull_request.title, '.go')
uses: superbrothers/close-pull-request@v3
with:
# Optional. Post a issue comment just before closing a pull request.
comment: "非法PR. 请`fork`后修改自己的仓库, 而不是向主仓库提交更改. 如果您确信您的PR是为了给主仓库新增功能或修复bug, 请更改默认PR标题. **注意**: 如果您再次触发本提示, 则有可能导致账号被封禁."
golangci:
name: lint
runs-on: ubuntu-latest
@@ -8,7 +26,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@master
with:
go-version: 1.19
go-version: '1.20'
- name: Check out code into the Go module directory
uses: actions/checkout@master

View File

@@ -8,12 +8,12 @@ jobs:
- name: Set up Go
uses: actions/setup-go@master
with:
go-version: 1.19
go-version: '1.20'
- name: Check out code into the Go module directory
uses: actions/checkout@master
- name: golangci-lint
- name: Run Lint
uses: golangci/golangci-lint-action@master
with:
version: latest
@@ -25,7 +25,7 @@ jobs:
git config --local user.name 'github-actions[bot]'
git config --local user.email '41898282+github-actions[bot]@users.noreply.github.com'
git add --all
git commit -m "🎨 改进代码样式"
git commit -m "chore(lint): 改进代码样式"
- name: Create Pull Request
if: ${{ !github.head_ref }}

View File

@@ -16,12 +16,12 @@ jobs:
- name: Set up Go
uses: actions/setup-go@master
with:
go-version: '1.19'
go-version: '1.20'
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@master
with:
version: latest
args: release --rm-dist
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

2
.gitignore vendored
View File

@@ -7,3 +7,5 @@ go-zero*
nohup.out
zerobot
ZeroBot-Plugin*
*.syso
/.direnv

View File

@@ -18,7 +18,7 @@ linters:
fast: false
enable:
- bodyclose
- depguard
#- depguard
- dogsled
- errcheck
- exportloopref
@@ -59,7 +59,7 @@ run:
tests: false
skip-dirs:
- order
go: '1.19'
go: '1.20'
# output configuration options
output:

View File

@@ -4,6 +4,8 @@ env:
before:
hooks:
- go mod tidy
- go install github.com/tc-hib/go-winres@latest
- go-winres make
builds:
- id: nowin
env:
@@ -64,7 +66,7 @@ archives:
format: zip
nfpms:
- license: GPL 3.0
- license: AGPL 3.0
homepage: https://github.com/FloatTech/ZeroBot-Plugin
file_name_template: "zbp_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
formats:

382
README.md
View File

@@ -1,7 +1,6 @@
<div align="center">
<a href="https://crypko.ai/crypko/5k8HyUVTq5421/">
<img src=".github/hua_nobg_512.gif" alt="椛" width = "400">
</a><br>
<br>
<h1>ZeroBot-Plugin</h1>
@@ -10,17 +9,23 @@
ZeroBot-Plugin 是 ZeroBot 的 实用插件合集<br><br>
<img src="http://cmoe.azurewebsites.net/cmoe?name=ZeroBot-Plugin&theme=r34" /><br>
<img src="https://counter.seku.su/cmoe?name=ZeroBot-Plugin&theme=r34" /><br>
[![miraigo](https://img.shields.io/badge/OneBot-MiraiGo-green.svg?style=social&logo=appveyor)](https://github.com/Mrs4s/MiraiGo)
[![oicq](https://img.shields.io/badge/OneBot-OICQ-green.svg?style=social&logo=appveyor)](https://github.com/takayama-lily/oicq)
[![mirai](https://img.shields.io/badge/OneBot-Mirai-green.svg?style=social&logo=appveyor)](https://github.com/mamoe/mirai)
[![go](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin?style=flat-square&logo=go)](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin)
[![onebot](https://img.shields.io/badge/onebot-v11-black?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAMAAADxPgR5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////29vbr6+vAAAAk1hCcwAAAAR0Uk5T////AEAqqfQAAAKcSURBVHja7NrbctswDATQXfD//zlpO7FlmwAWIOnOtNaTM5JwDMa8E+PNFz7g3waJ24fviyDPgfhz8fHP39cBcBL9KoJbQUxjA2iYqHL3FAnvzhL4GtVNUcoSZe6eSHizBcK5LL7dBr2AUZlev1ARRHCljzRALIEog6H3U6bCIyqIZdAT0eBuJYaGiJaHSjmkYIZd+qSGWAQnIaz2OArVnX6vrItQvbhZJtVGB5qX9wKqCMkb9W7aexfCO/rwQRBzsDIsYx4AOz0nhAtWu7bqkEQBO0Pr+Ftjt5fFCUEbm0Sbgdu8WSgJ5NgH2iu46R/o1UcBXJsFusWF/QUaz3RwJMEgngfaGGdSxJkE/Yg4lOBryBiMwvAhZrVMUUvwqU7F05b5WLaUIN4M4hRocQQRnEedgsn7TZB3UCpRrIJwQfqvGwsg18EnI2uSVNC8t+0QmMXogvbPg/xk+Mnw/6kW/rraUlvqgmFreAA09xW5t0AFlHrQZ3CsgvZm0FbHNKyBmheBKIF2cCA8A600aHPmFtRB1XvMsJAiza7LpPog0UJwccKdzw8rdf8MyN2ePYF896LC5hTzdZqxb6VNXInaupARLDNBWgI8spq4T0Qb5H4vWfPmHo8OyB1ito+AysNNz0oglj1U955sjUN9d41LnrX2D/u7eRwxyOaOpfyevCWbTgDEoilsOnu7zsKhjRCsnD/QzhdkYLBLXjiK4f3UWmcx2M7PO21CKVTH84638NTplt6JIQH0ZwCNuiWAfvuLhdrcOYPVO9eW3A67l7hZtgaY9GZo9AFc6cryjoeFBIWeU+npnk/nLE0OxCHL1eQsc1IciehjpJv5mqCsjeopaH6r15/MrxNnVhu7tmcslay2gO2Z1QfcfX0JMACG41/u0RrI9QAAAABJRU5ErkJggg==)](https://t.me/zerobotplugin)
[![zerobot](https://img.shields.io/badge/zerobot-v1.6.6-black?style=flat-square&logo=go)](https://github.com/wdvxdr1123/ZeroBot)
[![zerobot](https://img.shields.io/badge/zerobot-v1.7.4-black?style=flat-square&logo=go)](https://github.com/wdvxdr1123/ZeroBot)
[![license](https://img.shields.io/github/license/FloatTech/ZeroBot-Plugin.svg?style=flat-square&logo=gnu)](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
[![tencent-qq](https://img.shields.io/badge/group-1048452984-red?style=flat-square&logo=tencent-qq)](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
[![tencent-qq](https://img.shields.io/badge/%E7%BE%A4-1048452984-red?style=flat-square&logo=tencent-qq)](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
[![tencent-guild](https://img.shields.io/badge/%E9%A2%91%E9%81%93-Zer0BotPlugin-yellow?style=flat-square&logo=tencent-qq)](https://pd.qq.com/s/fjkx81mnr)
[![telegram](https://img.shields.io/badge/Telegram-click%20me-informational?style=flat-square&logo=telegram)](https://t.me/zerobotplugin)
本项目符合 [OneBot](https://github.com/howmanybots/onebot) 标准,可基于以下项目与机器人框架/平台进行交互
@@ -34,25 +39,31 @@
</div>
> 专为[后 go-cqhttp 时代](https://github.com/Mrs4s/go-cqhttp/issues/2471)开发迁移的`类zbp`新机器人现已出炉基于官方api稳定不风控: [NanoBot-Plugin](https://github.com/FloatTech/NanoBot-Plugin)
> 如果您不知道什么是 [OneBot](https://github.com/howmanybots/onebot) 或不希望运行多个程序,还可以直接前往 [gocqzbp](https://github.com/FloatTech/gocqzbp) 的 [Release](https://github.com/FloatTech/gocqzbp/releases) 页面下载单一可执行文件或前往 [Packages](https://github.com/FloatTech/gocqzbp/pkgs/container/gocqzbp) 页面使用`docker`,运行后按提示登录即可。
> 如果您对开发插件感兴趣,欢迎加入[ZeroBot-Plugin-Playground](https://github.com/FloatTech/ZeroBot-Plugin-Playground)
> webui持续开发中, 欢迎加入[ZeroBot-Plugin-Webui](https://github.com/FloatTech/ZeroBot-Plugin-Webui)
## 命令行参数
> `[]`代表是可选参数
```bash
zerobot [-h] [-n nickname] [-t token] [-u url] [-p prefix] [-d|w] [-c|s config.json] [-l latency] [-r ringlen] [-x max process time] [qq1 qq2 qq3 ...] [&]
zerobot [-h] [-m] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w] [-c|s config.json] [-l latency] [-r ringlen] [-x max process time] [qq1 qq2 qq3 ...] [&]
```
- **-h**: 显示帮助
- **-m**: 不自动标记消息为已读
- **-n nickname**: 设置默认昵称,默认为`椛椛`
- **-t token**: 设置`AccessToken`,默认为空
- **-u url**: 设置`Url`,默认为`ws://127.0.0.1:6700`
- ~~**-g url**~~(默认禁用): 设置`webui url`,默认为`127.0.0.1:3000`
- **-p prefix**: 设置命令前缀,默认为`/`
- **-d|w**: 开启 debug | warning 级别及以上日志输出
- **-c config.json**: 从`config.json`加载`bot`配置
- **-s config.json**: 保存现在`bot`配置到`config.json`
- **-l latency**: 全局处理延时 (ms)
- **-r ringlen**: 接收消息环缓冲区大小
- **-r ringlen**: 接收消息环缓冲区大小`0`为不设缓冲,并发处理
- **-x max process time**: 最大处理时间 (min)
- **qqs**: superusers 的 qq 号
- **&**: 驻留在后台,必须放在最后,仅`Linux`下有效
@@ -60,34 +71,28 @@ zerobot [-h] [-n nickname] [-t token] [-u url] [-p prefix] [-d|w] [-c|s config.j
默认配置文件格式如下。当选择从配置文件加载时,将忽略相应命令行参数。
```json
{
"zero": {
"nickname": [
"椛椛",
"ATRI",
"atri",
"亚托莉",
"アトリ"
],
"command_prefix": "/",
"super_users": [],
"ring_len": 4096,
"latency": 233000000,
"max_process_time": 240000000000
},
"ws": [
{
"Url": "ws://127.0.0.1:6700",
"AccessToken": ""
}
],
"wss": null
"zero": {
"nickname": ["椛椛", "ATRI", "atri", "亚托莉", "アトリ"],
"command_prefix": "/",
"super_users": [],
"ring_len": 4096,
"latency": 233000000,
"max_process_time": 240000000000,
"mark_message": true
},
"ws": [{ "Url": "ws://127.0.0.1:6700", "AccessToken": "" }],
"wss": null
}
```
## 功能
> 在编译时,以下功能除插件控制外,均可通过注释`main.go`中的相应`import`而物理禁用,减小插件体积。
> 通过插件控制,还可动态管理某个功能在某个群的打开/关闭。
> 插件的优先级为`import`的先后顺序
> 插件的优先级为`import`的先后顺序。
> `webui`默认禁用不编译,打开后会增加程序体积。
<details>
<summary>插件控制</summary>
@@ -104,6 +109,10 @@ zerobot [-h] [-n nickname] [-t token] [-u url] [-p prefix] [-d|w] [-c|s config.j
- [x] /禁用 xxx (在发送的群/用户禁用xxx)
- [x] /此处启用所有插件
- [x] /此处禁用所有插件
- [x] /全局启用 xxx
- [x] /全局禁用 xxx
@@ -126,9 +135,14 @@ zerobot [-h] [-n nickname] [-t token] [-u url] [-p prefix] [-d|w] [-c|s config.j
- [x] /服务列表
- [x] /设置服务列表显示行数 xx
- [x] /设置服务列表显示行数 xx (默认值为 9, 该设置仅运行时有效, zbp 重启后重置)
- [x] (默认禁用) /设置webui用户名 zerobot 密码 123456
- [x] (默认禁用) /webui启动
- [x] (默认禁用) /webui停止
默认值为9,该设置仅运行时有效,zbp重启后重置
- [x] @Bot 插件冲突检测 (会在本群发送一条消息并在约 1s 后撤回以检测其它同类 bot 中已启用的插件并禁用)
</details>
@@ -228,6 +242,8 @@ zerobot [-h] [-n nickname] [-t token] [-u url] [-p prefix] [-d|w] [-c|s config.j
- [x] 列出所有提醒
- [x] 翻牌
- [x] 赞我
- [x] [开启 | 关闭]入群验证
@@ -421,11 +437,11 @@ print("run[CQ:image,file="+j["img"]+"]")
</details>
<details>
<summary>百度一下</summary>
<summary>百</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu"`
- [x] 百度[xxx]
- [x] 百度/百科/维基/wiki[xxx]
</details>
<details>
@@ -544,7 +560,7 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] b站推送列表
- [x] 拉取b站推送 (使用job执行定时任务------记录在"@every 10s"触发的指令)
- [x] 拉取b站推送 (使用job执行定时任务------记录在"@every 5m"触发的指令)
</details>
<details>
@@ -556,14 +572,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 随机书评
</details>
<details>
<summary>打断复读</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/breakrepeat"`
- [x] (打断三次以上的复读)
</details>
<details>
<summary>藏头诗</summary>
@@ -616,6 +624,14 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 磕cp大老师 雪乃
</details>
<details>
<summary>今日早报</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/dailynews"`
- [x] 今日早报
</details>
<details>
<summary>DeepDanbooru二次元图标签识别</summary>
@@ -636,6 +652,34 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 教你一篇小作文[作文]
</details>
<details>
<summary>程序员做饭指南</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/dish"`
- [x] 怎么做 | 烹饪[菜名]
- [x] 随机菜谱 | 随便做点菜
</details>
<details>
<summary>多功能抽签</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/drawlots"`
支持图包文件夹和gif抽签
- [x] (刷新)抽签列表
- [x] 抽[签名]签
- [x] 看签[gif签名]
- [x] 加签[签名][gif图片]
- [x] 删签[gif签名]
</details>
<details>
<summary>女装</summary>
@@ -686,7 +730,8 @@ print("run[CQ:image,file="+j["img"]+"]")
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/font"`
- [x] (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体])渲染文字xxx
- [x] (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|粗苹方体|未来荧黑体|Gugi体|八丸体|Impact体|猫啃体|苹方体])渲染(抖动)文字xxx
</details>
<details>
<summary>每日运势</summary>
@@ -780,6 +825,16 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 来点黑丝/白丝/jk/巨乳/足控/网红
</details>
<details>
<summary>一言</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/hitokoto"`
- [x] 一言[xxx]
- [x] 系列一言
</details>
<details>
<summary>炉石</summary>
@@ -868,6 +923,26 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 喝奶茶绝绝子 | 绝绝子吃饭
</details>
<details>
<summary>疯狂星期四</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/kfccrazythursday"`
- [x] 疯狂星期四
</details>
<details>
<summary>kokomi原神面板</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/kokomi"`
- [x] kokomi菜单
- [x] XX面板
- 注:本插件未并入主仓库,需自行安装(须源码方式运行才能添加插件),安装地址[kokomi-原神面板查询插件](https://github.com/lianhong2758/kokomi-plugin)
</details>
<details>
<summary>lolicon</summary>
@@ -886,6 +961,24 @@ print("run[CQ:image,file="+j["img"]+"]")
来份萝莉
```
</details>
<details>
<summary>桑帛云 API</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolimi"`
- [x] 随机妹子
- [x] 随机绕口令
- [x] 颜值鉴定[图片]
- [x] 随机情话
- [x] 发病 嘉然
- [x] 让[嘉然|塔菲|东雪莲|懒羊羊|科比|孙笑川|陈泽|丁真|空|荧|派蒙|纳西妲|阿贝多|温迪|枫原万叶|钟离|荒泷一斗|八重神子|艾尔海森|提纳里|迪希雅|卡维|宵宫|莱依拉|赛诺|诺艾尔|托马|凝光|莫娜|北斗|神里绫华|雷电将军|芭芭拉|鹿野院平藏|五郎|迪奥娜|凯亚|安柏|班尼特|琴|柯莱|夜兰|妮露|辛焱|珐露珊|魈|香菱|达达利亚|砂糖|早柚|云堇|刻晴|丽莎|迪卢克|烟绯|重云|珊瑚宫心海|胡桃|可莉|流浪者|久岐忍|神里绫人|甘雨|戴因斯雷布|优菈|菲谢尔|行秋|白术|九条裟罗|雷泽|申鹤|迪娜泽黛|凯瑟琳|多莉|坎蒂丝|萍姥姥|罗莎莉亚|留云借风真君|绮良良|瑶瑶|七七|奥兹|米卡|夏洛蒂|埃洛伊|博士|女士|大慈树王|三月七|娜塔莎|希露瓦|虎克|克拉拉|丹恒|希儿|布洛妮娅|瓦尔特|杰帕德|佩拉|姬子|艾丝妲|白露|星|穹|桑博|伦纳德|停云|罗刹|卡芙卡|彦卿|史瓦罗|螺丝咕姆|阿兰|银狼|素裳|丹枢|黑塔|景元|帕姆|可可利亚|半夏|符玄|公输师傅|奥列格|青雀|大毫|青镞|费斯曼|绿芙蓉|镜流|信使|丽塔|失落迷迭|缭乱星棘|伊甸|伏特加女孩|狂热蓝调|莉莉娅|萝莎莉娅|八重樱|八重霞|卡莲|第六夜想曲|卡萝尔|姬子|极地战刃|布洛妮娅|次生银翼|理之律者|真理之律者|迷城骇兔|希儿|魇夜星渊|黑希儿|帕朵菲莉丝|天元骑英|幽兰黛尔|德丽莎|月下初拥|朔夜观星|暮光骑士|明日香|李素裳|格蕾修|梅比乌斯|渡鸦|人之律者|爱莉希雅|爱衣|天穹游侠|琪亚娜|空之律者|终焉之律者|薪炎之律者|云墨丹心|符华|识之律者|维尔薇|始源之律者|芽衣|雷之律者|苏莎娜|阿波尼亚|陆景和|莫弈|夏彦|左然]说我测尼玛
</details>
<details>
<summary>MagicPrompt-Stable-Diffusion吟唱提示</summary>
@@ -894,6 +987,23 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 吟唱提示[xxxx]
</details>
<details>
<summary>钓鱼模拟器</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/mcfish"`
- [x] 钓鱼商店
- [x] 购买xxx [数量]
- [x] 出售xxx [数量]
- [x] 钓鱼背包
- [x] 装备[xx竿|三叉戟|美西螈]
- [x] 附魔[诱钓|海之眷顾]
- [x] 修复鱼竿
- [x] 合成[xx竿|三叉戟]
- [x] 进行钓鱼
- [x] 进行n次钓鱼
</details>
<details>
<summary>简易midi音乐制作</summary>
@@ -922,10 +1032,6 @@ print("run[CQ:image,file="+j["img"]+"]")
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/moegoe"`
- [x] 让[宁宁|爱瑠|芳乃|茉子|丛雨|小春|七海]说(日语)
- [x] 让[수아|미미르|아린|연화|유화|선배]说(韩语)
- [x] 让[派蒙|空|荧|阿贝多|枫原万叶|温迪|八重神子|纳西妲|钟离|诺艾尔|凝光|托马|北斗|莫娜|荒泷一斗|提纳里|芭芭拉|艾尔海森|雷电将军|赛诺|琴|班尼特|五郎|神里绫华|迪希雅|夜兰|辛焱|安柏|宵宫|云堇|妮露|烟绯|鹿野院平藏|凯亚|达达利亚|迪卢克|可莉|早柚|香菱|重云|刻晴|久岐忍|珊瑚宫心海|迪奥娜|戴因斯雷布|魈|神里绫人|丽莎|优菈|凯瑟琳|雷泽|菲谢尔|九条裟罗|甘雨|行秋|胡桃|迪娜泽黛|柯莱|申鹤|砂糖|萍姥姥|奥兹|罗莎莉亚|式大将|哲平|坎蒂丝|托克|留云借风真君|昆钧|塞琉斯|多莉|大肉丸|莱依拉|散兵|拉赫曼|杜拉夫|阿守|玛乔丽|纳比尔|海芭夏|九条镰治|阿娜耶|阿晃|阿扎尔|七七|博士|白术|埃洛伊|大慈树王|女士|丽塔|失落迷迭|缭乱星棘|伊甸|伏特加女孩|狂热蓝调|莉莉娅|萝莎莉娅|八重樱|八重霞|卡莲|第六夜想曲|卡萝尔|姬子|极地战刃|布洛妮娅|次生银翼|理之律者|迷城骇兔|希儿|魇夜星渊|黑希儿|帕朵菲莉丝|天元骑英|幽兰黛尔|德丽莎|月下初拥|朔夜观星|暮光骑士|明日香|李素裳|格蕾修|梅比乌斯|渡鸦|人之律者|爱莉希雅|爱衣|天穹游侠|琪亚娜|空之律者|薪炎之律者|云墨丹心|符华|识之律者|维尔薇|芽衣|雷之律者|阿波尼亚]说(中文)
</details>
@@ -1032,6 +1138,12 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 小说[xxx]
- 设置小说配置 zerobot 123456
- 下载小说30298
- 注: 建议去https://www.23qb.com/ 注册一个账号, 小说下载有积分限制
</details>
<details>
<summary>nsfw图片识别</summary>
@@ -1154,14 +1266,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 设置 saucenao api key [apikey]
</details>
<details>
<summary>叔叔的AI二次元图片放大</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/scale"`
- [x] 放大图片[图片]
</details>
<details>
<summary>签到得分</summary>
@@ -1170,6 +1274,7 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 签到
- [x] 获得签到背景[@xxx] | 获得签到背景
- [x] 设置签到预设(0~3)
- [x] 查看等级排名
- 注:跨群排行
- [x] 查看我的钱包
@@ -1202,10 +1307,26 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 卖萌[@xxx]
- [x] 老婆[@xxx]
- [x] 今日老婆[@xxx]
- [x] 黄油角色[@xxx]
</details>
<details>
<summary>steam</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/steam"`
- [x] steam[添加|删除]订阅xxxxx
- [x] steam查询订阅
- [x] steam绑定 api key xxxxxxx
- [x] 查看apikey
- [x] 拉取steam订阅 (使用job执行定时任务------记录在"@every 1m"触发的指令)
</details>
<details>
<summary>抽塔罗牌</summary>
@@ -1261,6 +1382,26 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 更新vtb
</details>
<details>
<summary>vtb点歌</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtbmusic"`
- [x] vtb点歌
- [x] vtb随机点歌
</details>
<details>
<summary>钱包</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wallet"`
- [x] 查看我的钱包
- [x] 查看钱包排名
</details>
<details>
<summary>网易云音乐热评</summary>
@@ -1269,6 +1410,33 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 来份网易云热评
</details>
<details>
<summary>据意查句</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wantquotes"`
- [x] 据意查句 大海
- [x] 登录据意查句
</details>
<details>
<summary>星际战甲</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/warframeapi"`
- [x] wf时间同步
- [x] [金星|地球|火卫二]平原状态
- [x] .wm [物品名称]
- [x] 仲裁
- [x] 警报
- [x] 每日特惠
</details>
<details>
<summary>天气/拼音查询-名言</summary>
@@ -1329,19 +1497,11 @@ print("run[CQ:image,file="+j["img"]+"]")
</details>
<details>
<summary>月幕galgame图</summary>
<summary>抽老婆</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal"`
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wife"`
- [x] 随机galCG
- [x] 随机gal表情包
- [x] galCG[xxx]
- [x] gal表情包[xxx]
- [x] 更新gal
- [x] 抽老婆
</details>
<details>
@@ -1365,6 +1525,18 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 团队七阶猜单词
</details>
<details>
<summary>鬼东西</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf"`
- [x] 鬼东西列表
- [x] 查询鬼东西[序号][@xxx]
- 注:由于需要科学,默认注释。
</details>
<details>
<summary>一些游戏王插件</summary>
@@ -1390,26 +1562,55 @@ print("run[CQ:image,file="+j["img"]+"]")
</details>
<details>
<summary>词典匹配回复</summary>
<summary>月幕galgame图</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus"`
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal"`
- [x] 切换[kimo|傲娇|可爱]词库
- [x] 设置词库触发概率0.x (0<x<9)
- [x] 随机galCG
- 注:由于占用资源较大,默认注释。
- [x] 随机gal表情包
- [x] galCG[xxx]
- [x] gal表情包[xxx]
- [x] 更新gal
</details>
<details>
<summary>鬼东西</summary>
<summary>遇见API</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf"`
- [x] 鬼东西列表
- [x] 查询鬼东西[序号][@xxx]
- 注:由于需要科学,默认注释。
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/yujn"`
- [x] 小姐姐视频
- [x] 小姐姐视频2
- [x] 黑丝视频
- [x] 白丝视频
- [x] 欲梦视频
- [x] 甜妹视频
- [x] 双倍快乐
- [x] 纯情女高
- [x] 萝莉视频
- [x] 玉足视频
- [x] 帅哥视频
- [x] 热舞视频
- [x] 吊带视频
- [x] 汉服视频
- [x] 极品狱卒
- [x] 清纯视频
- [x] 快手变装
- [x] 抖音变装
- [x] 萌娃视频
- [x] 穿搭视频
- [x] 完美身材
- [x] 御姐撒娇
- [x] 绿茶语音
- [x] 怼人语音
- [x] 随机骚话
- [x] 随机污句子
- [x] 随机美句
- [x] 土味情话
- [x] 让[lulu]说我测尼玛
</details>
@@ -1432,7 +1633,26 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] @Bot 任意文本(任意一句话回复)
- [x] 设置回复模式[青云客 | 小爱]
- [x] 设置文字回复模式[婧枫|沫沫|青云客|小爱|ChatGPT]
- [x] 设置 ChatGPT api key xxx
</details>
<details>
<summary>词典匹配回复</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus"`
- [x] 切换[kimo|傲娇|可爱]词库
- [x] 设置词库触发概率0.x (0<x<9)
</details>
<details>
<summary>打断复读</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/breakrepeat"`
- [x] (打断三次以上的复读)
</details>

14
console/console_ansi.go Normal file
View File

@@ -0,0 +1,14 @@
//go:build !windows
// Package console sets console's behavior on init
package console
import (
"fmt"
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
)
func init() {
fmt.Print("\033]0;ZeroBot-Blugin " + banner.Version + " " + banner.Copyright + "\007")
}

144
console/console_windows.go Normal file
View File

@@ -0,0 +1,144 @@
// Package console sets console's behavior on init
package console
import (
"bytes"
"os"
"strings"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
"github.com/sirupsen/logrus"
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
)
var (
//go:linkname modkernel32 golang.org/x/sys/windows.modkernel32
modkernel32 *windows.LazyDLL
procSetConsoleTitle = modkernel32.NewProc("SetConsoleTitleW")
)
//go:linkname errnoErr golang.org/x/sys/windows.errnoErr
func errnoErr(e syscall.Errno) error
func setConsoleTitle(title string) (err error) {
var p0 *uint16
p0, err = syscall.UTF16PtrFromString(title)
if err != nil {
return
}
r1, _, e1 := syscall.Syscall(procSetConsoleTitle.Addr(), 1, uintptr(unsafe.Pointer(p0)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func init() {
stdin := windows.Handle(os.Stdin.Fd())
var mode uint32
err := windows.GetConsoleMode(stdin, &mode)
if err != nil {
panic(err)
}
mode &^= windows.ENABLE_QUICK_EDIT_MODE // 禁用快速编辑模式
mode |= windows.ENABLE_EXTENDED_FLAGS // 启用扩展标志
mode &^= windows.ENABLE_MOUSE_INPUT // 禁用鼠标输入
mode |= windows.ENABLE_PROCESSED_INPUT // 启用控制输入
mode &^= windows.ENABLE_INSERT_MODE // 禁用插入模式
mode |= windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT // 启用输入回显&逐行输入
mode &^= windows.ENABLE_WINDOW_INPUT // 禁用窗口输入
mode &^= windows.ENABLE_VIRTUAL_TERMINAL_INPUT // 禁用虚拟终端输入
err = windows.SetConsoleMode(stdin, mode)
if err != nil {
panic(err)
}
stdout := windows.Handle(os.Stdout.Fd())
err = windows.GetConsoleMode(stdout, &mode)
if err != nil {
panic(err)
}
mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING // 启用虚拟终端处理
mode |= windows.ENABLE_PROCESSED_OUTPUT // 启用处理后的输出
err = windows.SetConsoleMode(stdout, mode)
// windows 带颜色 log 自定义格式
logrus.SetFormatter(&logFormat{hasColor: err == nil})
if err != nil {
logrus.Warnln("VT100设置失败, 将以无色模式输出")
}
err = setConsoleTitle("ZeroBot-Plugin " + banner.Version + " " + banner.Copyright)
if err != nil {
panic(err)
}
}
const (
colorCodePanic = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
colorCodeFatal = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
colorCodeError = "\x1b[31m" // color.Style{color.Red}.String()
colorCodeWarn = "\x1b[33m" // color.Style{color.Yellow}.String()
colorCodeInfo = "\x1b[37m" // color.Style{color.White}.String()
colorCodeDebug = "\x1b[32m" // color.Style{color.Green}.String()
colorCodeTrace = "\x1b[36m" // color.Style{color.Cyan}.String()
colorReset = "\x1b[0m"
)
// logFormat specialize for zbp
type logFormat struct {
hasColor bool
}
// Format implements logrus.Formatter
func (f logFormat) Format(entry *logrus.Entry) ([]byte, error) {
buf := new(bytes.Buffer)
buf.WriteByte('[')
if f.hasColor {
buf.WriteString(getLogLevelColorCode(entry.Level))
}
buf.WriteString(strings.ToUpper(entry.Level.String()))
if f.hasColor {
buf.WriteString(colorReset)
}
buf.WriteString("] ")
buf.WriteString(entry.Message)
buf.WriteString(" \n")
return buf.Bytes(), nil
}
// getLogLevelColorCode 获取日志等级对应色彩code
func getLogLevelColorCode(level logrus.Level) string {
switch level {
case logrus.PanicLevel:
return colorCodePanic
case logrus.FatalLevel:
return colorCodeFatal
case logrus.ErrorLevel:
return colorCodeError
case logrus.WarnLevel:
return colorCodeWarn
case logrus.InfoLevel:
return colorCodeInfo
case logrus.DebugLevel:
return colorCodeDebug
case logrus.TraceLevel:
return colorCodeTrace
default:
return colorCodeInfo
}
}

2
data

Submodule data updated: 00088d0e74...9b983625ca

25
default.nix Normal file
View File

@@ -0,0 +1,25 @@
{
pkgs ? (
let
inherit (builtins) fetchTree fromJSON readFile;
inherit ((fromJSON (readFile ./flake.lock)).nodes) nixpkgs gomod2nix;
in
import (fetchTree nixpkgs.locked) {
overlays = [
(import "${fetchTree gomod2nix.locked}/overlay.nix")
];
}
),
buildGoApplication ? pkgs.buildGoApplication,
}:
buildGoApplication {
pname = "ZeroBot-Plugin";
version = "1.7.6";
pwd = ./.;
src = ./.;
# spec go version manually bcs
# https://github.com/nix-community/gomod2nix/blob/30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6/builder/default.nix#L130
# do no work
go = pkgs.go_1_20;
modules = ./gomod2nix.toml;
}

85
flake.lock generated Normal file
View File

@@ -0,0 +1,85 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1705309234,
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"flake-utils": [
"flake-utils"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1705314449,
"narHash": "sha256-yfQQ67dLejP0FLK76LKHbkzcQqNIrux6MFe32MMFGNQ=",
"owner": "nix-community",
"repo": "gomod2nix",
"rev": "30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "gomod2nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1705856552,
"narHash": "sha256-JXfnuEf5Yd6bhMs/uvM67/joxYKoysyE3M2k6T3eWbg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "612f97239e2cc474c13c9dafa0df378058c5ad8d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"gomod2nix": "gomod2nix",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

36
flake.nix Normal file
View File

@@ -0,0 +1,36 @@
{
description = " ZeroBot OneBot ";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.gomod2nix.url = "github:nix-community/gomod2nix";
inputs.gomod2nix.inputs.nixpkgs.follows = "nixpkgs";
inputs.gomod2nix.inputs.flake-utils.follows = "flake-utils";
outputs = {
self,
nixpkgs,
flake-utils,
gomod2nix,
}: (
flake-utils.lib.eachDefaultSystem
(system: let
pkgs = nixpkgs.legacyPackages.${system};
# The current default sdk for macOS fails to compile go projects, so we use a newer one for now.
# This has no effect on other platforms.
callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage;
in {
# doCheck will fail at write files
packages.default =
(callPackage ./. {
inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
})
.overrideAttrs (_: {doCheck = false;});
devShells.default = callPackage ./shell.nix {
inherit (gomod2nix.legacyPackages.${system}) mkGoEnv gomod2nix;
};
formatter = pkgs.alejandra;
})
);
}

67
go.mod
View File

@@ -1,54 +1,65 @@
module github.com/FloatTech/ZeroBot-Plugin
go 1.19
go 1.20
require (
github.com/Baidu-AIP/golang-sdk v1.1.1
github.com/Coloured-glaze/gg v1.3.4
github.com/FloatTech/AnimeAPI v1.6.1-0.20230111055153-4d8aebd3eab9
github.com/FloatTech/floatbox v0.0.0-20230111053652-a03d6334fadf
github.com/FloatTech/sqlite v1.5.7
github.com/FloatTech/AnimeAPI v1.7.1-0.20240423052513-58ad4b85322a
github.com/FloatTech/floatbox v0.0.0-20240304064110-78a83f1af9a6
github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9
github.com/FloatTech/sqlite v1.6.3
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
github.com/FloatTech/zbpctrl v1.5.3-0.20230109124217-41203036b80a
github.com/FloatTech/zbputils v1.6.1
github.com/FloatTech/zbpctrl v1.6.0
github.com/FloatTech/zbputils v1.7.1-0.20231107124514-083e678fbfe6
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5
github.com/antchfx/htmlquery v1.2.5
github.com/corona10/goimagehash v1.1.0
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3
github.com/disintegration/imaging v1.6.2
github.com/fumiama/ahsai v0.1.0
github.com/fumiama/cron v1.3.0
github.com/fumiama/go-base16384 v1.6.4
github.com/fumiama/go-registry v0.2.5
github.com/fumiama/go-base16384 v1.7.0
github.com/fumiama/go-registry v0.2.6
github.com/fumiama/gotracemoe v0.0.3
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565
github.com/fumiama/unibase2n v0.0.0-20221020155353-02876e777430
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/jinzhu/gorm v1.9.16
github.com/jozsefsallai/gophersauce v1.0.1
github.com/lucas-clemente/quic-go v0.31.1
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5
github.com/lithammer/fuzzysearch v1.1.5
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5
github.com/mroth/weightedrand v1.0.0
github.com/notnil/chess v1.9.0
github.com/pkg/errors v0.9.1
github.com/shirou/gopsutil/v3 v3.22.11
github.com/sirupsen/logrus v1.9.0
github.com/quic-go/quic-go v0.38.1
github.com/shirou/gopsutil/v3 v3.23.1
github.com/sirupsen/logrus v1.9.3
github.com/tidwall/gjson v1.14.4
github.com/wcharczuk/go-chart/v2 v2.1.0
github.com/wdvxdr1123/ZeroBot v1.6.7
github.com/wdvxdr1123/ZeroBot v1.7.5-0.20240410141841-6970df23ca54
gitlab.com/gomidi/midi/v2 v2.0.25
golang.org/x/image v0.3.0
golang.org/x/sys v0.8.0
golang.org/x/text v0.9.0
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/FloatTech/rendercard v0.0.3 // indirect
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d // indirect
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca // indirect
github.com/antchfx/xpath v1.2.1 // indirect
github.com/disintegration/imaging v1.6.2 // indirect
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
github.com/faiface/beep v1.1.0 // indirect
github.com/fumiama/go-simple-protobuf v0.1.0 // indirect
github.com/fumiama/gofastTEA v0.0.10 // indirect
github.com/fumiama/imgsz v0.0.2 // indirect
github.com/gabriel-vasile/mimetype v1.0.4 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
@@ -58,30 +69,32 @@ require (
github.com/jfreymuth/vorbis v1.0.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/liuzl/cedar-go v0.0.0-20170805034717-80a9c64b256d // indirect
github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/marten-seemann/qpack v0.3.0 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pkumza/numcn v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/tetratelabs/wazero v1.5.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/crypto v0.4.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9 // indirect
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/text v0.6.0 // indirect
golang.org/x/tools v0.1.12 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/tools v0.9.1 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
modernc.org/libc v1.21.5 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.4.0 // indirect

136
go.sum
View File

@@ -1,28 +1,34 @@
github.com/Baidu-AIP/golang-sdk v1.1.1 h1:RQsAmgDSAkiq22I6n7XJ2t3afgzFeqjY46FGhvrx4cw=
github.com/Baidu-AIP/golang-sdk v1.1.1/go.mod h1:bXnGw7xPeKt8aF7UCELKrV6UZ/46spItONK1RQBQj1Y=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Coloured-glaze/gg v1.3.4 h1:l31zIF/HaVwkzjrj+A56RGQoSKyKuR1IWtIrqXGFStI=
github.com/Coloured-glaze/gg v1.3.4/go.mod h1:Ih5NLNNDHOy3RJbB0EPqGTreIzq/H02TGThIagh8HJg=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/FloatTech/AnimeAPI v1.6.1-0.20230111055153-4d8aebd3eab9 h1:TOd10BBqoHPwbOmULK4a6imdaljkOxKIZFyFKbQqTEA=
github.com/FloatTech/AnimeAPI v1.6.1-0.20230111055153-4d8aebd3eab9/go.mod h1:aOU5EVMvflX5Btv0jGLgB6gcSYeR/FNiR2cJG07vd4U=
github.com/FloatTech/floatbox v0.0.0-20230111053652-a03d6334fadf h1:aVmgzw9hJA39/2iR800qq1dU682LpW9/czIkoshDzKw=
github.com/FloatTech/floatbox v0.0.0-20230111053652-a03d6334fadf/go.mod h1:0+3iDgifrdiEoEsmYe+yiAlUQcmnudhTiiBdSkam2XY=
github.com/FloatTech/rendercard v0.0.3 h1:eKOKlmotlDq/YbAcJKe0GMzBjGTsT5eSsyEfjT+hy10=
github.com/FloatTech/rendercard v0.0.3/go.mod h1:FwwKoWpv1fW7AZ1mwBVWF8GCH9mEqYYIE9LzdmozCZQ=
github.com/FloatTech/sqlite v1.5.7 h1:Bvo4LSojcZ6dVtbHrkqvt6z4v8e+sj0G5PSUIvdawsk=
github.com/FloatTech/sqlite v1.5.7/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY=
github.com/FloatTech/AnimeAPI v1.7.1-0.20240423052513-58ad4b85322a h1:K+1RAkIBb+3kkSxSkSTdTugSIsXJXrjEbwuv/BwUsP8=
github.com/FloatTech/AnimeAPI v1.7.1-0.20240423052513-58ad4b85322a/go.mod h1:bNHsYcUd1+Y5Al3CR6tdzKxcc0XLivXjmUsL9xG6sSw=
github.com/FloatTech/floatbox v0.0.0-20240304064110-78a83f1af9a6 h1:Vaj8ulVbN8vTD4W7aj+BYeT6x8iKFneDnkgBCezomDY=
github.com/FloatTech/floatbox v0.0.0-20240304064110-78a83f1af9a6/go.mod h1:TeTlp+hTxpJti4JSdmUqzxGEr4wUBOVct9YWBepilpc=
github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08 h1:dPLeoiTVSBlgls+66EB/UJ2e38BaASmBN5nANaycSBU=
github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08/go.mod h1:uzPzAeT35egARdRuu+1oyjU3CmTwCceoq3Vvje7LpcI=
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef h1:CJbK/2FRwPuZpeb6M4sWK2d7oXDnBEGhpkQuQrgc91A=
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs=
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9 h1:hffajvmQFfP68U6wUwHemPuuwCUoss+SEFfoLYwbGwE=
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9/go.mod h1:NBFPhWae4hqVMeG8ELBBnUQkKce3nDjkljVn6PdiUNs=
github.com/FloatTech/sqlite v1.6.3 h1:MQkqBNlkPuCoKQQgoNLuTL/2Ci3tBTFAnVYBdD0Wy4M=
github.com/FloatTech/sqlite v1.6.3/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY=
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw=
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
github.com/FloatTech/zbpctrl v1.5.3-0.20230109124217-41203036b80a h1:O+GS8J1pEM4E8q05EcopHBK6kfIr0BJJ/cHuPa8yWLM=
github.com/FloatTech/zbpctrl v1.5.3-0.20230109124217-41203036b80a/go.mod h1:UT3bZNKMF/+r2XzSvIVXWudnTgmWsQrRPOJ3bmBfjFI=
github.com/FloatTech/zbputils v1.6.1 h1:VcufWTkZl8ny4aB6leJ+CE4TS6OdA4i4zeKgYQdx97c=
github.com/FloatTech/zbputils v1.6.1/go.mod h1:IrPicT+CKYW2ZwPlG//DSNG7bHAQAII2mNyETnRQDG4=
github.com/FloatTech/zbpctrl v1.6.0 h1:BWg9aRR4bUCmNNKj6GPH0TmzFRWYImIi6rQcQTTYRs4=
github.com/FloatTech/zbpctrl v1.6.0/go.mod h1:i3GGM5K4HiDsXzvmXQSYoH1QT3tsSaAHjRzHwKGsHG0=
github.com/FloatTech/zbputils v1.7.1-0.20231107124514-083e678fbfe6 h1:EMdvLnt6i5dSFloLD1klOM8bdoFZqTtILcMCciOpcMo=
github.com/FloatTech/zbputils v1.7.1-0.20231107124514-083e678fbfe6/go.mod h1:4oXgjQ6bGosAF4GbuL/keAhTrGWOV369X5X0ISFebmw=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA=
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5 h1:bBmmB7he0iVN4m5mcehfheeRUEer/Avo4ujnxI3uCqs=
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5/go.mod h1:0UcFaCkhp6vZw6l5Dpq0Dp673CoF9GdvA8lTfst0GiU=
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d h1:ir/IFJU5xbja5UaBEQLjcvn7aAU01nqU/NUyOBEU+ew=
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d/go.mod h1:PRWNwWq0yifz6XDPZu48aSld8BWwBfr2JKB2bGWiEd4=
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca h1:kWzLcty5V2rzOqJM7Tp/MfSX0RMSI1x4IOLApEefYxA=
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/antchfx/htmlquery v1.2.5 h1:1lXnx46/1wtv1E/kzmH8vrfMuUKYgkdDBA9pIdMJnk4=
github.com/antchfx/htmlquery v1.2.5/go.mod h1:2MCVBzYVafPBmKbrmwB9F5xdd+IEgRY61ci2oOsOQVw=
@@ -38,6 +44,8 @@ github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozb
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=
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3 h1:qshMBFxVjYjzI+kwvWvgoByF3uMCvnJiaK8KslWAbr8=
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3/go.mod h1:M9fx6rAdHSYLKxXPgUXGgblb586CA7ceNrpu4DEc2No=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
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=
@@ -54,16 +62,18 @@ github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b h1:Zt3pFQditAdWTHCO
github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
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.6.4 h1:rYDRwD/th2cG4U7QLokpzmST1cCxZGXtHmolOUePt5o=
github.com/fumiama/go-base16384 v1.6.4/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
github.com/fumiama/go-registry v0.2.5 h1:Y6tnHnTThQPv7E4JPM2vBprU+4EQw/LEDO33HCmxgI4=
github.com/fumiama/go-registry v0.2.5/go.mod h1:GP45kejHuDLFxcWdksrt75r5rHBqYwtfeUl3JzGWxfQ=
github.com/fumiama/go-base16384 v1.7.0 h1:6fep7XPQWxRlh4Hu+KsdH+6+YdUp+w6CwRXtMWSsXCA=
github.com/fumiama/go-base16384 v1.7.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
github.com/fumiama/go-registry v0.2.6 h1:+vEeBUwa1+GC87ujW3Km42fi8O/H7QcpVJWu1iuGNh0=
github.com/fumiama/go-registry v0.2.6/go.mod h1:HjYagPZXzR2xCCxaSQerqX7JRzC0yiv2kslDdBiTq/g=
github.com/fumiama/go-simple-protobuf v0.1.0 h1:rLzJgNqB6LHNDVMl81yyNt6ZKziWtVfu+ioF0edlEVw=
github.com/fumiama/go-simple-protobuf v0.1.0/go.mod h1:5yYNapXq1tQMOZg9bOIVhQlZk9pQqpuFIO4DZLbsdy4=
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/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565 h1:sQuR2+N5HurnvsZhiKdEg+Ig354TaqgCQRxd/0KgIOQ=
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565/go.mod h1:UUEvyLTJ7yoOA/viKG4wEis4ERydM7+Ny6gZUWgkS80=
github.com/fumiama/sqlite3 v1.20.0-with-win386 h1:ZR1AXGBEtkfq9GAXehOVcwn+aaCG8itrkgEsz4ggx5k=
@@ -77,13 +87,14 @@ github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebK
github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
github.com/go-audio/wav v1.0.0/go.mod h1:3yoReyQOsiARkvPl3ERCi8JFjihzG6WhjYpZCf5zAWE=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
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.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
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=
@@ -93,7 +104,7 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -120,23 +131,28 @@ github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM=
github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg=
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5 h1:BXnB1Gz4y/zwQh+ZFNy7rgd+ZfMOrwRr4uZSHEI+ieY=
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5/go.mod h1:c9+VS9GaommgIOzNWb5ze4lYwfT8BZ2UDyGiuQTT7yc=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lucas-clemente/quic-go v0.31.1 h1:O8Od7hfioqq0PMYHDyBkxU2aA7iZ2W9pjbrWuja2YR4=
github.com/lucas-clemente/quic-go v0.31.1/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q=
github.com/liuzl/cedar-go v0.0.0-20170805034717-80a9c64b256d h1:qSmEGTgjkESUX5kPMSGJ4pcBUtYVDdkNzMrjQyvRvp0=
github.com/liuzl/cedar-go v0.0.0-20170805034717-80a9c64b256d/go.mod h1:x7SghIWwLVcJObXbjK7S2ENsT1cAcdJcPl7dRaSFog0=
github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d h1:hTRDIpJ1FjS9ULJuEzu69n3qTgc18eI+ztw/pJv47hs=
github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d/go.mod h1:7xD3p0XnHvJFQ3t/stEJd877CSIMkH/fACVWen5pYnc=
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5 h1:wnbHIeP1UX8ClYEWKGnw66PfYvReCHu9G5lXSte3Sqc=
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5/go.mod h1:7KaV9YIR92M1FpbczAcfYQ3UZ5ayT27pNtunDmXvLBo=
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
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/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6ki6hE=
github.com/marten-seemann/qpack v0.3.0/go.mod h1:cGfKPBiP4a9EQdxCwEwI/GEeWAsjSekBvx/X8mh58+g=
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
@@ -148,9 +164,13 @@ github.com/mroth/weightedrand v1.0.0 h1:V8JeHChvl2MP1sAoXq4brElOcza+jxLkRuwvtQu8
github.com/mroth/weightedrand v1.0.0/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/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
github.com/notnil/chess v1.9.0 h1:YMxR5kUVjtwcuFptGU0/3q7eG3MSHQNbg0VUekvRKV0=
github.com/notnil/chess v1.9.0/go.mod h1:cRuJUIBFq9Xki05TWHJxHYkC+fFpq45IWwk94DdlCrA=
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -161,21 +181,29 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
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/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE=
github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/shirou/gopsutil/v3 v3.22.11 h1:kxsPKS+Eeo+VnEQ2XCaGJepeP6KY53QoRTETx3+1ndM=
github.com/shirou/gopsutil/v3 v3.22.11/go.mod h1:xl0EeL4vXJ+hQMAGN8B9VFpxukEMA0XdevQOe5MZ1oY=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4=
github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tetratelabs/wazero v1.5.0 h1:Yz3fZHivfDiZFUXnWMPUoiW7s8tC1sjdBtlJn08qYa0=
github.com/tetratelabs/wazero v1.5.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
@@ -188,8 +216,8 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
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.6.7 h1:JK29W0j9k82X4FdGcbgqP5IFikUYMaUysUOIALGfQrw=
github.com/wdvxdr1123/ZeroBot v1.6.7/go.mod h1:T5kD5vLi/YxL/fyDOCOaawi96LRBdJjcXh2CIjDyFfg=
github.com/wdvxdr1123/ZeroBot v1.7.5-0.20240410141841-6970df23ca54 h1:s7k0Pf4RoeCUHe9rlVsg0mqAH3WO7xLMhe9qih/CxnE=
github.com/wdvxdr1123/ZeroBot v1.7.5-0.20240410141841-6970df23ca54/go.mod h1:y29UIOy0RD3P+0meDNIWRhcJF3jtWPN9xP9hgt/AJAU=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
@@ -201,12 +229,13 @@ golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
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-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9 h1:tLxpBz7qD8qFkRDC159unetNbxKp4zeqsqw2rLwvdxc=
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8=
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
@@ -224,8 +253,9 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -237,8 +267,8 @@ golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -259,30 +289,34 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

284
gomod2nix.toml Normal file
View File

@@ -0,0 +1,284 @@
schema = 3
[mod]
[mod."github.com/Baidu-AIP/golang-sdk"]
version = "v1.1.1"
hash = "sha256-hKshA0K92bKuK92mmtM0osVmqLJcSbeobeWSDpQoRCo="
[mod."github.com/FloatTech/AnimeAPI"]
version = "v1.7.1-0.20231017135344-aefd1d56e900"
hash = "sha256-YV9VQ7bA8R5g5dcAsbzS6MicVwDgMu08d9GF4uqXH7M="
[mod."github.com/FloatTech/floatbox"]
version = "v0.0.0-20231107124407-e38535efa2a2"
hash = "sha256-B86GBuJAjeFjhAjNbBF6OO6DTH2/fpPkrdQynwX+sxg="
[mod."github.com/FloatTech/gg"]
version = "v1.1.3-0.20230226151425-6ea91286ba08"
hash = "sha256-AeMzjMK1ZwFERb5xuNAV5PdHp7rzoT4ZF7kZ6Kj2/0s="
[mod."github.com/FloatTech/imgfactory"]
version = "v0.2.2-0.20230413152719-e101cc3606ef"
hash = "sha256-2okFyPQSYIxrc8hxICsbjEM9xq25a3I2A4wmDIYFCg8="
[mod."github.com/FloatTech/rendercard"]
version = "v0.0.10-0.20230223064326-45d29fa4ede9"
hash = "sha256-Zn8agmyWWEC2QQfIBa60jlQrEap9Bps+z1Ekay6Y0cg="
[mod."github.com/FloatTech/sqlite"]
version = "v1.6.3"
hash = "sha256-zWPByEMi89ms67ubPg0fAPIRxfpBC2IRKc0iNVLqkPU="
[mod."github.com/FloatTech/ttl"]
version = "v0.0.0-20220715042055-15612be72f5b"
hash = "sha256-vVQTn7f2dFPNrLqutWbeHMCpEdNi7uPxUzpphzaYPpM="
[mod."github.com/FloatTech/zbpctrl"]
version = "v1.6.0"
hash = "sha256-2ZPGFvSgTWcPOo8+p8kmg590HY2b8v/L3674ba+b7+A="
[mod."github.com/FloatTech/zbputils"]
version = "v1.7.1-0.20231107124514-083e678fbfe6"
hash = "sha256-Bg3aAI8oDx71kWielITcK5Rg2H47/DQZX+4+dO5AtK4="
[mod."github.com/RomiChan/syncx"]
version = "v0.0.0-20221202055724-5f842c53020e"
hash = "sha256-FbmvziRRDEzeXW17IQdyWMWsCVq4fvwKGjbFZqJKAMQ="
[mod."github.com/RomiChan/websocket"]
version = "v1.4.3-0.20220227141055-9b2c6168c9c5"
hash = "sha256-Adx+gvqB+CCoUXx7ebIaBDjVkav+wS5qZPmaqcApBWA="
[mod."github.com/adamzy/cedar-go"]
version = "v0.0.0-20170805034717-80a9c64b256d"
hash = "sha256-N19KTxh70IUBqnchFuWkrJD8uuFOIVqv1iSuN3YFIT0="
[mod."github.com/ajstarks/svgo"]
version = "v0.0.0-20200320125537-f189e35d30ca"
hash = "sha256-ALeRuEJN9jHjGb4wNKJcxC59vVx8Tj7hHikEGkaZZ0s="
[mod."github.com/antchfx/htmlquery"]
version = "v1.2.5"
hash = "sha256-lkpdz+NNHadn0VIshszAZS5ZodOic0sp2d7VN6sIl/M="
[mod."github.com/antchfx/xpath"]
version = "v1.2.1"
hash = "sha256-ffHNkJiraDyjy6NsFDNTfqreiY+DER/93J/i11xUPw8="
[mod."github.com/corona10/goimagehash"]
version = "v1.1.0"
hash = "sha256-HyS8nc7kUNnDaVBDzJ9Ym4pRs83YB4M2vHSRwfm6mr4="
[mod."github.com/davidscholberg/go-durationfmt"]
version = "v0.0.0-20170122144659-64843a2083d3"
hash = "sha256-0rdbpBf3AAjMpxvVEGFb2ImgB2i7vdEhIwCyqJs1iHE="
[mod."github.com/disintegration/imaging"]
version = "v1.6.2"
hash = "sha256-pSeMTPvSkxlthh65LjNYYhPLvCZDkBgVgAGYWW0Aguo="
[mod."github.com/ericpauley/go-quantize"]
version = "v0.0.0-20200331213906-ae555eb2afa4"
hash = "sha256-sMN6D7IlDpDqUWM8ppoE5Sdb7DvLAJaN6qAucBWJ3rs="
[mod."github.com/faiface/beep"]
version = "v1.1.0"
hash = "sha256-66qAbnJjUjhXofxlGCa6G1+vjQcSTyN/POCZvYzHaQo="
[mod."github.com/fumiama/ahsai"]
version = "v0.1.0"
hash = "sha256-lSoos+SFjALcL0ZYPsbOb8wntwn2fcubvSsz0YKgL9c="
[mod."github.com/fumiama/cron"]
version = "v1.3.0"
hash = "sha256-/sN7X8dKXQgv8J+EDzVUB+o+AY9gBC8e1C6sYhaTy1k="
[mod."github.com/fumiama/go-base16384"]
version = "v1.7.0"
hash = "sha256-vTAsBBYe2ISzb2Nba5E96unodZSkhMcqo6hbwR01nz8="
[mod."github.com/fumiama/go-registry"]
version = "v0.2.6"
hash = "sha256-DgkdYYWsCs/bBrIiCHK4tPInv8pTy5/AqwHmI5UPTo8="
[mod."github.com/fumiama/go-simple-protobuf"]
version = "v0.1.0"
hash = "sha256-itOBeIU4PRBANDP79eRWlCDNhNUnde6dgcpUlUbm0zU="
[mod."github.com/fumiama/gofastTEA"]
version = "v0.0.10"
hash = "sha256-FOCbkXoS8s/K54yZbhX5pmaN/ouELnCHZoNS8a90VAg="
[mod."github.com/fumiama/gotracemoe"]
version = "v0.0.3"
hash = "sha256-O3cDkVXu5NG1ZtzubxhH+S91zfgu4uH1L+OiSGYSNXQ="
[mod."github.com/fumiama/imgsz"]
version = "v0.0.2"
hash = "sha256-eYUjP1TKWUrsY++rzg4rezOvmvmjADZFBizIIDHnZtY="
[mod."github.com/fumiama/jieba"]
version = "v0.0.0-20221203025406-36c17a10b565"
hash = "sha256-DvDx1pdldkdaSszrbadM/VwqT9TTSmWl6G6a+ysXYEM="
[mod."github.com/fumiama/unibase2n"]
version = "v0.0.0-20221020155353-02876e777430"
hash = "sha256-//vCLy5/vgId7m9WnRGqmh/wnglboiYz2YzQruIe97o="
[mod."github.com/gabriel-vasile/mimetype"]
version = "v1.0.4"
hash = "sha256-5hl9zBo3nkPt8dZfcLoOix8lAKLm3qIkWhopoS4V34E="
[mod."github.com/go-ole/go-ole"]
version = "v1.2.6"
hash = "sha256-+oxitLeJxYF19Z6g+6CgmCHJ1Y5D8raMi2Cb3M6nXCs="
[mod."github.com/go-task/slim-sprig"]
version = "v0.0.0-20230315185526-52ccab3ef572"
hash = "sha256-D6NjCQbcYC53NdwzyAm4i9M1OjTJIVu4EIt3AD/Vxfg="
[mod."github.com/golang/freetype"]
version = "v0.0.0-20170609003504-e2365dfdc4a0"
hash = "sha256-AHAFBd20/tqxohkWyQkui2bUef9i1HWYgk9LOIFErvA="
[mod."github.com/golang/groupcache"]
version = "v0.0.0-20210331224755-41bb18bfe9da"
hash = "sha256-7Gs7CS9gEYZkbu5P4hqPGBpeGZWC64VDwraSKFF+VR0="
[mod."github.com/golang/mock"]
version = "v1.6.0"
hash = "sha256-fWdnMQisRbiRzGT3ISrUHovquzLRHWvcv1JEsJFZRno="
[mod."github.com/google/pprof"]
version = "v0.0.0-20210407192527-94a9f03dee38"
hash = "sha256-ryvI75ePFCfy0qvAhEFbtB/c/Er7nvLwm7CVASBRhsI="
[mod."github.com/google/uuid"]
version = "v1.3.0"
hash = "sha256-QoR55eBtA94T2tBszyxfDtO7/pjZZSGb5vm7U0Xhs0Y="
[mod."github.com/hajimehoshi/oto"]
version = "v0.7.1"
hash = "sha256-eRgbEbsziY5F0oI7wAe29FepZG7uGmq2M4deouDHcXI="
[mod."github.com/jfreymuth/oggvorbis"]
version = "v1.0.1"
hash = "sha256-DpkiTLxAA/iCoiylpNRvMzvaDWtK+U4UMJYNnnCmJMU="
[mod."github.com/jfreymuth/vorbis"]
version = "v1.0.0"
hash = "sha256-6kTol+g3NnZ3MazD786fvraw7ydUf0RWNBzHpzgN9Jk="
[mod."github.com/jinzhu/gorm"]
version = "v1.9.16"
hash = "sha256-qKEwgNE8NxcX1uzT20LwC1TKVmve/nIy+oxdAKlxAuc="
[mod."github.com/jinzhu/inflection"]
version = "v1.0.0"
hash = "sha256-3h3pHib5MaCXKyKLIMyQnSptDJ16kPjCOQPoEBoQsZg="
[mod."github.com/jozsefsallai/gophersauce"]
version = "v1.0.1"
hash = "sha256-29DsfnGmK51DPunR/leRBKCcokN/yLoB7S2HxCsqtgY="
[mod."github.com/kanrichan/resvg-go"]
version = "v0.0.2-0.20231001163256-63db194ca9f5"
hash = "sha256-plRZ3yhyCafCXmAD4vnFUoCTRsHmLp7Jn9gFKcEKbds="
[mod."github.com/kr/pretty"]
version = "v0.3.1"
hash = "sha256-DlER7XM+xiaLjvebcIPiB12oVNjyZHuJHoRGITzzpKU="
[mod."github.com/lithammer/fuzzysearch"]
version = "v1.1.5"
hash = "sha256-2vJLR4z5o3ch9q4tV7NT5RnfNxEdYspjI8YxQao2A6w="
[mod."github.com/liuzl/cedar-go"]
version = "v0.0.0-20170805034717-80a9c64b256d"
hash = "sha256-N19KTxh70IUBqnchFuWkrJD8uuFOIVqv1iSuN3YFIT0="
[mod."github.com/liuzl/da"]
version = "v0.0.0-20180704015230-14771aad5b1d"
hash = "sha256-J43kwDFmB6LzDhS3Ig/4ddZUTXz1cKztbTA3hILScs8="
[mod."github.com/liuzl/gocc"]
version = "v0.0.0-20231231122217-0372e1059ca5"
hash = "sha256-Dr1xDbO+eR4Y/EpPgQ/S6g6C5etRFKWr8de77skcJR8="
[mod."github.com/lufia/plan9stats"]
version = "v0.0.0-20211012122336-39d0f177ccd0"
hash = "sha256-thb+rkDx5IeWMgw5/5jgu5gZ+6RjJAUXeMgSkJHhRlA="
[mod."github.com/mattn/go-isatty"]
version = "v0.0.16"
hash = "sha256-YMaPZvShDfA98vqw1+zWWl7M1IT4nHPGBrAt7kHo8Iw="
[mod."github.com/mroth/weightedrand"]
version = "v1.0.0"
hash = "sha256-bP+yIaBUY5+oI455mNM8zh14z/SNPaQg44L3RJ0/v/c="
[mod."github.com/nfnt/resize"]
version = "v0.0.0-20180221191011-83c6a9932646"
hash = "sha256-yvPV+HlDOyJsiwAcVHQkmtw8DHSXyw+cXHkigXm8rAA="
[mod."github.com/notnil/chess"]
version = "v1.9.0"
hash = "sha256-2bHp/H5hBE/hPMT1HLOBqMaCZ/DYWJMDri26O9Yzoms="
[mod."github.com/onsi/ginkgo/v2"]
version = "v2.9.5"
hash = "sha256-3HO85y+nGsg92NEg3OOYXy5GxB59Yl1idF5sBZnyIi4="
[mod."github.com/pbnjay/memory"]
version = "v0.0.0-20210728143218-7b4eea64cf58"
hash = "sha256-QI+F1oPLOOtwNp8+m45OOoSfYFs3QVjGzE0rFdpF/IA="
[mod."github.com/pkg/errors"]
version = "v0.9.1"
hash = "sha256-mNfQtcrQmu3sNg/7IwiieKWOgFQOVVe2yXgKBpe/wZw="
[mod."github.com/pkumza/numcn"]
version = "v1.0.0"
hash = "sha256-cPxqj5tb10+MurN1Lehkk/v8KjaxXpL08+pVgL4x4Hg="
[mod."github.com/power-devops/perfstat"]
version = "v0.0.0-20210106213030-5aafc221ea8c"
hash = "sha256-ywykDYuqcMt0TvZOz1l9Z6Z2JMTYQw8cP2fT8AtpmX4="
[mod."github.com/quic-go/qpack"]
version = "v0.4.0"
hash = "sha256-QWIumzmHD94DlNp9G3AQf9QCtF+Kv0pShT1+FH7/I/c="
[mod."github.com/quic-go/qtls-go1-20"]
version = "v0.3.3"
hash = "sha256-YiT0g2gUxaZgJlQqQDkQqJme44LYHdzErHVEbY3bIa0="
[mod."github.com/quic-go/quic-go"]
version = "v0.38.1"
hash = "sha256-CC1E4sLcoMA1Jb9QdiVBaBq9GNUmxAPGBz3f/SJaHDY="
[mod."github.com/remyoudompheng/bigfft"]
version = "v0.0.0-20211011143303-6e0bfa3c836b"
hash = "sha256-SHwiLdLvGHYnbWm+03ddYc2550RdFdx/VadJfZyQEKA="
replaced = "github.com/fumiama/bigfft"
[mod."github.com/shirou/gopsutil/v3"]
version = "v3.23.1"
hash = "sha256-DYoN9o+PGrnYev7i+NISAKEqFdCKpimpi4s0FWmFpkY="
[mod."github.com/sirupsen/logrus"]
version = "v1.9.3"
hash = "sha256-EnxsWdEUPYid+aZ9H4/iMTs1XMvCLbXZRDyvj89Ebms="
[mod."github.com/tetratelabs/wazero"]
version = "v1.5.0"
hash = "sha256-fGdJM4LJrZA9jxHuYVo4EUQ3I1k0IVG3QQCBCgZkeZI="
[mod."github.com/tidwall/gjson"]
version = "v1.14.4"
hash = "sha256-3DS2YNL95wG0qSajgRtIABD32J+oblaKVk8LIw+KSOc="
[mod."github.com/tidwall/match"]
version = "v1.1.1"
hash = "sha256-M2klhPId3Q3T3VGkSbOkYl/2nLHnsG+yMbXkPkyrRdg="
[mod."github.com/tidwall/pretty"]
version = "v1.2.0"
hash = "sha256-esRQGsn2Ee/CiySlwyuOICSLdqUkH4P7u8qXszos8Yc="
[mod."github.com/tklauser/go-sysconf"]
version = "v0.3.11"
hash = "sha256-io8s7PJi4OX+wXkCm+v5pKy4yiqA/RE/I4ksy6mKX30="
[mod."github.com/tklauser/numcpus"]
version = "v0.6.0"
hash = "sha256-6jssTsP5L6yVl43tXfqDdgeI+tEkBp3BpiWwKXLTHAM="
[mod."github.com/wcharczuk/go-chart/v2"]
version = "v2.1.0"
hash = "sha256-0s07aT7i3zMyVaS1hHO6SaCilVy39HwC8Po6wcENn9E="
[mod."github.com/wdvxdr1123/ZeroBot"]
version = "v1.7.5-0.20231009162356-57f71b9f5258"
hash = "sha256-sIrH0WUDJeEGMD8FWh8UyrI3aHNN6NT7l+/isSl3ico="
[mod."github.com/yusufpapurcu/wmi"]
version = "v1.2.2"
hash = "sha256-Rno6F82JIeglBobQl6YKl3U6+FvWXmFavJlzpOJgoXI="
[mod."gitlab.com/gomidi/midi/v2"]
version = "v2.0.25"
hash = "sha256-3oTPzuPX1hNd+6/5kRUcMfMztvQa2UWHPppp8OPiP90="
[mod."golang.org/x/crypto"]
version = "v0.4.0"
hash = "sha256-PvHIbuooDItiNyQEi8kKgybkc0o95B0aeMd9awVGFCY="
[mod."golang.org/x/exp"]
version = "v0.0.0-20221205204356-47842c84f3db"
hash = "sha256-HWHDTTbsKZp1bMN06ZKluiLt8Yfjtnf1XhR9GWp4rQk="
[mod."golang.org/x/exp/shiny"]
version = "v0.0.0-20221126150942-6ab00d035af9"
hash = "sha256-+OAzuS+wyjOBSarGBuHjMeQV3vZzTbmF7CH8wnE7aA8="
[mod."golang.org/x/image"]
version = "v0.3.0"
hash = "sha256-d6/w/CwI5GRGjuOGA7L7x4rEPfcHAVV3ZzsKxKmMYR4="
[mod."golang.org/x/mobile"]
version = "v0.0.0-20201217150744-e6ae53a27f4f"
hash = "sha256-NdxlpSJhVpmE/T84HHoPtQ1GPCvDNkbNzNTYa5HEEYE="
[mod."golang.org/x/mod"]
version = "v0.10.0"
hash = "sha256-g0T2wz+K0nhPWdVQJRGGqEqzlTHMBahv+9C3y090eIM="
[mod."golang.org/x/net"]
version = "v0.10.0"
hash = "sha256-HkGiUYBZOBdOtt7mYo3N3swFjjAXzW++pG2JeWGJR9Q="
[mod."golang.org/x/sys"]
version = "v0.8.0"
hash = "sha256-wLPPnoFkHM1HPUaFIfRyQZOJjrqXVZimB0nMySly7Xg="
[mod."golang.org/x/text"]
version = "v0.9.0"
hash = "sha256-tkhDeMsSQZr3jo7vmKehWs3DvWetwXR0IB+DCLbQ4nk="
[mod."golang.org/x/tools"]
version = "v0.9.1"
hash = "sha256-6jvh0cvdVMvGBceeBxWFj0+bFvboB8wuIYPHabxrST0="
[mod."gopkg.in/check.v1"]
version = "v1.0.0-20201130134442-10cb98267c6c"
hash = "sha256-VlIpM2r/OD+kkyItn6vW35dyc0rtkJufA93rjFyzncs="
[mod."gopkg.in/yaml.v3"]
version = "v3.0.1"
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
[mod."modernc.org/libc"]
version = "v1.21.5"
hash = "sha256-q2ZMb7TY1mp/Ia6e/I+44mrmpUBHErW4Q6/lPXpep28="
[mod."modernc.org/mathutil"]
version = "v1.5.0"
hash = "sha256-5xM9HjjHf9sB0vLfN53PdGpT0qPF1+KI1/lgN0/4LQo="
[mod."modernc.org/memory"]
version = "v1.4.0"
hash = "sha256-x78QWQ1H82eolL7JiG6eP6l4fHhRNyIlSryQKpibcBo="
[mod."modernc.org/sqlite"]
version = "v1.20.0-with-win386"
hash = "sha256-ICV8xqeBvySJtmVV4DpqihUyRbXdaq11ba+UvMltFn8="
replaced = "github.com/fumiama/sqlite3"

View File

@@ -1,10 +0,0 @@
package kanban
// Version ...
var Version = "v1.6.1-beta5"
// Banner ...
var Banner = "* OneBot + ZeroBot + Golang\n" +
"* Version " + Version + " - 2023-01-11 14:46:24 +0800 CST\n" +
"* Copyright © 2020 - 2023 FloatTech. All Rights Reserved.\n" +
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"

15
kanban/banner/banner.go Normal file
View File

@@ -0,0 +1,15 @@
// Code generated by kanban/gen. DO NOT EDIT.
package banner
// Version ...
var Version = "v1.7.8"
// Copyright ...
var Copyright = "© 2020 - 2024 FloatTech"
// Banner ...
var Banner = "* OneBot + ZeroBot + Golang\n" +
"* Version " + Version + " - 2024-04-30 17:51:12 +0900 JST\n" +
"* Copyright " + Copyright + ". All Rights Reserved.\n" +
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"

View File

@@ -10,22 +10,27 @@ import (
"time"
)
const banner = `package kanban
const banner = `// Code generated by kanban/gen. DO NOT EDIT.
package banner
// Version ...
var Version = "%s"
// Copyright ...
var Copyright = "© 2020 - %d FloatTech"
// Banner ...
var Banner = "* OneBot + ZeroBot + Golang\n" +
"* Version " + Version + " - %s\n" +
"* Copyright © 2020 - %d FloatTech. All Rights Reserved.\n" +
"* Copyright " + Copyright + ". All Rights Reserved.\n" +
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
`
const timeformat = `2006-01-02 15:04:05 +0800 CST`
const timeformat = `2006-01-02 15:04:05 +0900 JST`
func main() {
f, err := os.Create("banner.go")
f, err := os.Create("banner/banner.go")
if err != nil {
panic(err)
}
@@ -39,7 +44,7 @@ func main() {
}
s := strings.Split(vartag.String(), "\n")
now := time.Now()
_, err = fmt.Fprintf(f, banner, s[len(s)-2], now.Format(timeformat), now.Year())
_, err = fmt.Fprintf(f, banner, s[len(s)-2], now.Year(), now.Format(timeformat))
if err != nil {
panic(err)
}

View File

@@ -3,18 +3,17 @@ package kanban
import (
"fmt"
"sync"
"github.com/FloatTech/zbputils/control"
"github.com/fumiama/go-registry"
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
)
//go:generate go run github.com/FloatTech/ZeroBot-Plugin/kanban/gen
var once sync.Once
func init() {
once.Do(PrintBanner)
PrintBanner()
}
var reg = registry.NewRegReader("reilia.fumiama.top:32664", control.Md5File, "fumiama")
@@ -23,7 +22,7 @@ var reg = registry.NewRegReader("reilia.fumiama.top:32664", control.Md5File, "fu
func PrintBanner() {
fmt.Print(
"\n======================[ZeroBot-Plugin]======================",
"\n", Banner, "\n",
"\n", banner.Banner, "\n",
"----------------------[ZeroBot-公告栏]----------------------",
"\n", Kanban(), "\n",
"============================================================\n\n",

View File

@@ -0,0 +1,5 @@
//go:build go1.21
package kanban
const Error int = "请使用小于1.21版本的Go"

221
main.go
View File

@@ -7,10 +7,14 @@ import (
"fmt"
"math/rand"
"os"
"runtime"
"strconv"
"strings"
"time"
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 在最前打印 banner
_ "github.com/FloatTech/ZeroBot-Plugin/console" // 更改控制台属性
"github.com/FloatTech/ZeroBot-Plugin/kanban" // 打印 banner
// ---------以下插件均可通过前面加 // 注释,注释后停用并不加载插件--------- //
// ----------------------插件优先级按顺序从高到低---------------------- //
@@ -30,7 +34,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat" // 基础词库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleep_manage" // 统计睡眠时间
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleepmanage" // 统计睡眠时间
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri" // ATRI词库
@@ -56,90 +60,101 @@ import (
// vvvvvvvvvvvvvv //
// vvvv //
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ahsai" // ahsai tts
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_false" // 服务器监控
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aipaint" // ai绘图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/alipayvoice" // 支付宝到账语音
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/autowithdraw" // 触发者撤回时也自动撤回
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/b14" // base16384加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu" // 百度一下
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baiduaudit" // 百度内容审核
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/base64gua" // base64卦加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baseamasiro" // base天城文加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili" // 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/chrev" // 英文字符翻转
_ "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/dress" // 女装
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/drift_bottle" // 漂流瓶
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/emojimix" // 合成emoji
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/event" // 好友申请群聊邀请事件处理
_ "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/guessmusic" // 猜歌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/heisi" // 黑丝
_ "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/jiami" // 兽语加密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jikipedia" // 小鸡词典
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jptingroom" // 日语听力学习材料
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi" // 绝绝子生成器
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon" // lolicon 随机图片
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/magicprompt" // magicprompt吟唱提示
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/midicreate" // 简易midi音乐制作
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moegoe" // 日韩 VITS 模型拟声
_ "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/nihongo" // 日语语法学习
_ "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/quan" // QQ权重查询
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/qzone" // qq空间表白墙
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/realcugan" // realcugan清晰术
_ "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/vitsnyaru" // vits猫雷
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtb_quotation" // vtb语录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wallet" // 钱包
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun" // 网易云音乐热评
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenben" // 文本指令大全
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinAI" // 百度文心AI画图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count" // 聊天热词
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygo" // 游戏王相关插件
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ahsai" // ahsai tts
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aifalse" // 服务器监控
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aipaint" // ai绘图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/alipayvoice" // 支付宝到账语音
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/autowithdraw" // 触发者撤回时也自动撤回
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu" // 百度一下
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baiduaudit" // 百度内容审核
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/base16384" // base16384加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/base64gua" // base64卦加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baseamasiro" // base天城文加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili" // b站相关
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/bookreview" // 哀伤雪刃吧推书记录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cangtoushi" // 藏头诗
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chess" // 国际象棋
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/choose" // 选择困难症帮手
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chouxianghua" // 说抽象话
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chrev" // 英文字符翻转
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/coser" // 三次元小姐姐
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cpstory" // cp短打
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/dailynews" // 今日早报
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru" // DeepDanbooru二次元图标签识别
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana" // 嘉心糖发病
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/dish" // 程序员做饭指南
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/drawlots" // 多功能抽签
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/dress" // 女装
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/driftbottle" // 漂流瓶
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/emojimix" // 合成emoji
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/event" // 好友申请群聊邀请事件处理
_ "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/guessmusic" // 猜歌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/heisi" // 黑丝
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hitokoto" // 一言
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs" // 炉石
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hyaku" // 百人一首
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/imgfinder" // 关键字搜图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/inject" // 注入指令
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jandan" // 煎蛋网无聊图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jiami" // 兽语加密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jptingroom" // 日语听力学习材料
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi" // 绝绝子生成器
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/kfccrazythursday" // 疯狂星期四
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon" // lolicon 随机图片
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolimi" // 桑帛云 API
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/magicprompt" // magicprompt吟唱提示
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/mcfish" // 钓鱼模拟器
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/midicreate" // 简易midi音乐制作
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moegoe" // 日韩 VITS 模型拟声
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyu" // 摸鱼
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/moyucalendar" // 摸鱼人日历
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/music" // 点歌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativesetu" // 本地涩图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nbnhhsh" // 拼音首字母缩写释义工具
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nihongo" // 日语语法学习
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/novel" // 铅笔小说网搜索
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nsfw" // nsfw图片识别
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nwife" // 本地老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/omikuji" // 浅草寺求签
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife" // 一群一天一夫一妻制群老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/quan" // QQ权重查询
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/qzone" // qq空间表白墙
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/realcugan" // realcugan清晰术
_ "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/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/steam" // steam相关
_ "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/vitsnyaru" // vits猫雷
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtbmusic" // vtb点歌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtbquotation" // vtb语录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wallet" // 钱包
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun" // 网易云音乐热评
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wantquotes" // 据意查句
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/warframeapi" // warframeAPI插件
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenben" // 文本指令大全
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinvilg" // 百度文心AI画图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wife" // 抽老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordcount" // 聊天热词
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygo" // 游戏王相关插件
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/yujn" // 遇见API
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf" // 鬼东西
// ^^^^ //
@@ -164,6 +179,8 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply" // 人工智能回复
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/breakrepeat" // 打断复读
// ^^^^ //
@@ -183,6 +200,10 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/driver"
"github.com/wdvxdr1123/ZeroBot/message"
// webctrl "github.com/FloatTech/zbputils/control/web"
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
// -----------------------以上为内置依赖,勿动------------------------ //
)
@@ -200,6 +221,7 @@ func init() {
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 := flag.String("g", "127.0.0.1:3000", "Set webui url.")
// 直接写死 AccessToken 时,请更改下面第二个参数
token := flag.String("t", "", "Set AccessToken of WSClient.")
// 直接写死 URL 时,请更改下面第二个参数
@@ -212,6 +234,7 @@ func init() {
late := flag.Uint("l", 233, "Response latency (ms).")
rsz := flag.Uint("r", 4096, "Receiving buffer ring size.")
maxpt := flag.Uint("x", 4, "Max process time (min).")
markmsg := flag.Bool("m", false, "Don't mark message as read automatically")
flag.Parse()
@@ -219,13 +242,12 @@ func init() {
fmt.Println("Usage:")
flag.PrintDefaults()
os.Exit(0)
} else {
if *d && !*w {
logrus.SetLevel(logrus.DebugLevel)
}
if *w {
logrus.SetLevel(logrus.WarnLevel)
}
}
if *d && !*w {
logrus.SetLevel(logrus.DebugLevel)
}
if *w {
logrus.SetLevel(logrus.WarnLevel)
}
for _, s := range flag.Args() {
@@ -240,6 +262,9 @@ func init() {
// sus = append(sus, 12345678)
// sus = append(sus, 87654321)
// 启用 webui
// go webctrl.RunGui(*g)
if *runcfg != "" {
f, err := os.Open(*runcfg)
if err != nil {
@@ -261,7 +286,6 @@ func init() {
logrus.Infoln("[main] 从", *runcfg, "读取配置文件")
return
}
config.W = []*driver.WSClient{driver.NewWebSocketClient(*url, *token)}
config.Z = zero.Config{
NickName: append([]string{*adana}, "ATRI", "atri", "亚托莉", "アトリ"),
@@ -270,6 +294,7 @@ func init() {
RingLen: *rsz,
Latency: time.Duration(*late) * time.Millisecond,
MaxProcessTime: time.Duration(*maxpt) * time.Minute,
MarkMessage: !*markmsg,
Driver: []zero.Driver{config.W[0]},
}
@@ -289,15 +314,17 @@ func init() {
}
func main() {
rand.Seed(time.Now().UnixNano()) // 全局 seed其他插件无需再 seed
if !strings.Contains(runtime.Version(), "go1.2") { // go1.20之前版本需要全局 seed其他插件无需再 seed
rand.Seed(time.Now().UnixNano()) //nolint: staticcheck
}
// 帮助
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).
zero.OnFullMatchGroup([]string{"help", "/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(kanban.Banner, "\n发送\"/服务列表\"查看 bot 功能"))
ctx.SendChain(message.Text(banner.Banner, "\n管理发送\"/服务列表\"查看 bot 功能\n发送\"/用法name\"查看功能用法"))
})
zero.OnFullMatch("查看zbp公告", zero.OnlyToMe, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(kanban.Kanban()))
ctx.SendChain(message.Text(strings.ReplaceAll(kanban.Kanban(), "\t", "")))
})
zero.RunAndBlock(&config.Z, process.GlobalInitMutex.Unlock)
}

View File

@@ -1,70 +0,0 @@
//go:build windows
// +build windows
package main
import (
"bytes"
"strings"
"github.com/sirupsen/logrus"
)
func init() {
// windows 带颜色 log 自定义格式
logrus.SetFormatter(&LogFormat{})
}
const (
colorCodePanic = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
colorCodeFatal = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String()
colorCodeError = "\x1b[31m" // color.Style{color.Red}.String()
colorCodeWarn = "\x1b[33m" // color.Style{color.Yellow}.String()
colorCodeInfo = "\x1b[37m" // color.Style{color.White}.String()
colorCodeDebug = "\x1b[32m" // color.Style{color.Green}.String()
colorCodeTrace = "\x1b[36m" // color.Style{color.Cyan}.String()
colorReset = "\x1b[0m"
)
// LogFormat specialize for zbp
type LogFormat struct{}
// Format implements logrus.Formatter
func (f LogFormat) Format(entry *logrus.Entry) ([]byte, error) {
buf := new(bytes.Buffer)
buf.WriteString(getLogLevelColorCode(entry.Level))
buf.WriteByte('[')
buf.WriteString(strings.ToUpper(entry.Level.String()))
buf.WriteString("] ")
buf.WriteString(entry.Message)
buf.WriteString(" \n")
buf.WriteString(colorReset)
return buf.Bytes(), nil
}
// getLogLevelColorCode 获取日志等级对应色彩code
func getLogLevelColorCode(level logrus.Level) string {
switch level {
case logrus.PanicLevel:
return colorCodePanic
case logrus.FatalLevel:
return colorCodeFatal
case logrus.ErrorLevel:
return colorCodeError
case logrus.WarnLevel:
return colorCodeWarn
case logrus.InfoLevel:
return colorCodeInfo
case logrus.DebugLevel:
return colorCodeDebug
case logrus.TraceLevel:
return colorCodeTrace
default:
return colorCodeInfo
}
}

View File

@@ -27,10 +27,10 @@ var (
)
func init() {
engine := control.Register("ahsai", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "フリーテキスト音声合成",
Help: "- 使[伊織弓鶴|紲星あかり|結月ゆかり|京町セイカ|東北きりたん|東北イタコ|ついなちゃん標準語|ついなちゃん関西弁|音街ウナ|琴葉茜|吉田くん|民安ともえ|桜乃そら|月読アイ|琴葉葵|東北ずん子|月読ショウタ|水奈瀬コウ]说(日语)\n",
Help: "- 使[伊織弓鶴|紲星あかり|結月ゆかり|京町セイカ|東北きりたん|東北イタコ|ついなちゃん標準語|ついなちゃん関西弁|音街ウナ|琴葉茜|吉田くん|民安ともえ|桜乃そら|月読アイ|琴葉葵|東北ずん子|月読ショウタ|水奈瀬コウ]说(日语)",
PrivateDataFolder: "ahsai",
})
cachePath := engine.DataFolder() + "cache/"

View File

@@ -1,121 +0,0 @@
// Package aifalse 暂时只有服务器监控
package aifalse
import (
"fmt"
"math"
"strconv"
"time"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/mem"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() { // 插件主体
engine := control.Register("aifalse", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "自检, 全局限速",
Help: "- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]\n" +
"- 设置默认限速为每 m [分钟 | 秒] n 次触发",
})
c, ok := control.Lookup("aifalse")
if !ok {
panic("register aifalse error")
}
m := c.GetData(0)
n := (m >> 16) & 0xffff
m &= 0xffff
if m != 0 || n != 0 {
ctxext.SetDefaultLimiterManagerParam(time.Duration(m)*time.Second, int(n))
logrus.Infoln("设置默认限速为每", m, "秒触发", n, "次")
}
engine.OnFullMatchGroup([]string{"检查身体", "自检", "启动自检", "系统状态"}, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(
"* CPU占用: ", cpuPercent(), "%\n",
"* RAM占用: ", memPercent(), "%\n",
"* 硬盘使用: ", diskPercent(),
),
)
})
engine.OnRegex(`^设置默认限速为每\s*(\d+)\s*(分钟|秒)\s*(\d+)\s*次触发$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("ERROR: no such plugin"))
return
}
m, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if ctx.State["regex_matched"].([]string)[2] == "分钟" {
m *= 60
}
if m >= 65536 || m <= 0 {
ctx.SendChain(message.Text("ERROR: interval too big"))
return
}
n, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[3], 10, 64)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if n >= 65536 || n <= 0 {
ctx.SendChain(message.Text("ERROR: burst too big"))
return
}
ctxext.SetDefaultLimiterManagerParam(time.Duration(m)*time.Second, int(n))
err = c.SetData(0, (m&0xffff)|((n<<16)&0xffff0000))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("设置默认限速为每", m, "秒触发", n, "次"))
})
}
func cpuPercent() float64 {
percent, err := cpu.Percent(time.Second, false)
if err != nil {
return -1
}
return math.Round(percent[0])
}
func memPercent() float64 {
memInfo, err := mem.VirtualMemory()
if err != nil {
return -1
}
return math.Round(memInfo.UsedPercent)
}
func diskPercent() string {
parts, err := disk.Partitions(true)
if err != nil {
return err.Error()
}
msg := ""
for _, p := range parts {
diskInfo, err := disk.Usage(p.Mountpoint)
if err != nil {
msg += "\n - " + err.Error()
continue
}
pc := uint(math.Round(diskInfo.UsedPercent))
if pc > 0 {
msg += fmt.Sprintf("\n - %s(%dM) %d%%", p.Mountpoint, diskInfo.Total/1024/1024, pc)
}
}
return msg
}

View File

@@ -2,50 +2,76 @@ package aireply
import (
"errors"
"net/url"
"strings"
"github.com/RomiChan/syncx"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/FloatTech/AnimeAPI/aireply"
"github.com/FloatTech/AnimeAPI/tts"
"github.com/FloatTech/AnimeAPI/tts/baidutts"
"github.com/FloatTech/AnimeAPI/tts/genshin"
"github.com/FloatTech/AnimeAPI/tts/mockingbird"
"github.com/FloatTech/AnimeAPI/tts/lolimi"
"github.com/FloatTech/AnimeAPI/tts/ttscn"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
)
// 数据结构: [4 bits] [4 bits] [8 bits] [8 bits]
// [拟声鸟模式] [百度模式] [tts模式] [回复模式]
// 数据结构: [8 bits] [8 bits] [8 bits]
// [具体人物] [tts模式] [回复模式]
// defaultttsindexkey
// 数据结构: [4 bits] [4 bits] [8 bits]
// [拟声鸟模式] [百度模式] [tts模式]
// 数据结构: [8 bits] [8 bits]
// [具体人物] [tts模式]
// [tts模式]: 0~63 genshin 64 baidu 65 mockingbird
// [tts模式]: 0~200 genshin 201 baidu 202 ttscn 203 lolimi
const (
lastgsttsindex = 63 + iota
baiduttsindex
mockingbirdttsindex
baiduttsindex = 201 + iota
ttscnttsindex
lolimittsindex
)
const (
defaultttsindexkey = -2905
// extrattsname is the tts other than genshin vits
var extrattsname = []string{"百度", "TTSCN", "桑帛云"}
var ttscnspeakers = [...]string{
"晓晓(女 - 年轻人)",
"云扬(男 - 年轻人)",
"晓辰(女 - 年轻人 - 抖音热门)",
"晓涵(女 - 年轻人)",
"晓墨(女 - 年轻人)",
"晓秋(女 - 中年人)",
"晓睿(女 - 老年)",
"晓双(女 - 儿童)",
"晓萱(女 - 年轻人)",
"晓颜(女 - 年轻人)",
"晓悠(女 - 儿童)",
"云希(男 - 年轻人 - 抖音热门)",
"云野(男 - 中年人)",
"晓梦(女 - 年轻人)",
"晓伊(女 - 儿童)",
"晓甄(女 - 年轻人)",
}
const defaultttsindexkey = -2905
var (
= newapikeystore("./data/tts/o.txt")
ཆཏ = newapikeystore("./data/tts/c.txt")
= newapikeystore("./data/tts/b.txt")
)
var replyModes = [...]string{"青云客", "小爱"}
type replymode []string
func setReplyMode(ctx *zero.Ctx, name string) error {
func (r replymode) setReplyMode(ctx *zero.Ctx, name string) error {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
var ok bool
var index int64
for i, s := range replyModes {
for i, s := range r {
if s == name {
ok = true
index = int64(i)
@@ -59,42 +85,51 @@ func setReplyMode(ctx *zero.Ctx, name string) error {
if !ok {
return errors.New("no such plugin")
}
return m.SetData(gid, (m.GetData(index)&^0xff)|(index&0xff))
return m.SetData(gid, (m.GetData(gid)&^0xff)|(index&0xff))
}
func getReplyMode(ctx *zero.Ctx) aireply.AIReply {
func (r replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
if m.GetData(gid)&0xff == 1 {
switch m.GetData(gid) & 0xff {
case 0:
return aireply.NewLolimiAi(aireply.JingfengURL, aireply.JingfengBotName)
case 1:
return aireply.NewLolimiAi(aireply.MomoURL, aireply.MomoBotName)
case 2:
return aireply.NewQYK(aireply.QYKURL, aireply.QYKBotName)
case 3:
return aireply.NewXiaoAi(aireply.XiaoAiURL, aireply.XiaoAiBotName)
case 4:
k := ཆཏ.k
if k != "" {
return aireply.NewChatGPT(aireply.ChatGPTURL, k)
}
return aireply.NewLolimiAi(aireply.JingfengURL, aireply.JingfengBotName)
}
return aireply.NewQYK(aireply.QYKURL, aireply.QYKBotName)
}
return aireply.NewQYK(aireply.QYKURL, aireply.QYKBotName)
return aireply.NewLolimiAi(aireply.JingfengURL, aireply.JingfengBotName)
}
var ttsins = func() map[string]tts.TTS {
m := make(map[string]tts.TTS, 128)
for _, mode := range append(genshin.SoundList[:], "百度", "拟声鸟") {
m := make(map[string]tts.TTS, 512)
for _, mode := range append(genshin.SoundList[:], extrattsname...) {
m[mode] = nil
}
return m
}()
var ttsModes = func() []string {
s := append(genshin.SoundList[:], make([]string, 64-len(genshin.SoundList))...) // 0-63
s = append(s, "百度", "拟声鸟") // 64 65
s := append(genshin.SoundList[:], make([]string, baiduttsindex-len(genshin.SoundList))...) // 0-200
s = append(s, extrattsname...) // 201 202 ...
return s
}()
type ttsmode struct {
APIKey string // APIKey is for genshin vits
mode syncx.Map[int64, int64] `json:"-"` // mode grp index
}
type ttsmode syncx.Map[int64, int64]
func list(list []string, num int) string {
s := ""
@@ -112,34 +147,18 @@ func list(list []string, num int) string {
func newttsmode() *ttsmode {
t := &ttsmode{}
m, ok := control.Lookup("tts")
t.mode = syncx.Map[int64, int64]{}
t.mode.Store(defaultttsindexkey, 0)
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, 0)
if ok {
index := m.GetData(defaultttsindexkey)
msk := index & 0xff
if msk >= 0 && (msk < int64(len(genshin.SoundList)) || msk == baiduttsindex || msk == mockingbirdttsindex) {
t.mode.Store(defaultttsindexkey, index)
if msk >= 0 && (msk < int64(len(ttsModes))) {
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, index)
}
}
return t
}
func (t *ttsmode) getAPIKey(ctx *zero.Ctx) string {
if t.APIKey == "" {
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
_ = m.Manager.GetExtra(-1, &t)
logrus.Debugln("[tts] get api key:", t.APIKey)
}
return url.QueryEscape(t.APIKey)
}
func (t *ttsmode) setAPIKey(m *ctrl.Control[*zero.Ctx], key string) error {
t.APIKey = key
_ = m.Manager.Response(-1)
return m.Manager.SetExtra(-1, t)
}
func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, baiduper, mockingsynt int) error {
func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, character int) error {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
@@ -151,23 +170,27 @@ func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, baiduper, mockingsynt
var index = int64(-1)
for i, s := range genshin.SoundList {
if s == name {
index = int64(i)
index = int64(i + 1)
break
}
}
if index == -1 {
switch name {
case "百度":
case extrattsname[0]:
index = baiduttsindex
case "拟声鸟":
index = mockingbirdttsindex
case extrattsname[1]:
index = ttscnttsindex
case extrattsname[2]:
index = lolimittsindex
default:
return errors.New("语音人物" + name + "未注册index")
}
}
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
t.mode.Store(gid, index)
return m.SetData(gid, (m.GetData(gid)&^0xffff00)|((index<<8)&0xff00)|((int64(baiduper)<<16)&0x0f0000)|((int64(mockingsynt)<<20)&0xf00000))
// 按原来的逻辑map存的是前16位
storeIndex := (m.GetData(gid) &^ 0xffff00) | ((index << 8) & 0xff00) | ((int64(character) << 16) & 0xff0000)
(*syncx.Map[int64, int64])(t).Store(gid, (storeIndex>>8)&0xffff)
return m.SetData(gid, storeIndex)
}
func (t *ttsmode) getSoundMode(ctx *zero.Ctx) (tts.TTS, error) {
@@ -175,35 +198,42 @@ func (t *ttsmode) getSoundMode(ctx *zero.Ctx) (tts.TTS, error) {
if gid == 0 {
gid = -ctx.Event.UserID
}
i, ok := t.mode.Load(gid)
i, ok := (*syncx.Map[int64, int64])(t).Load(gid)
if !ok {
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
i = m.GetData(gid) >> 8
}
m := i & 0xff
if m < 0 || (m >= int64(len(genshin.SoundList)) && m != baiduttsindex && m != mockingbirdttsindex) {
i, _ = t.mode.Load(defaultttsindexkey)
if m <= 0 || (m >= int64(len(ttsModes))) {
i, _ = (*syncx.Map[int64, int64])(t).Load(defaultttsindexkey)
if i == 0 {
i = ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).GetData(defaultttsindexkey)
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, i)
}
m = i & 0xff
}
mode := ttsModes[m]
ins, ok := ttsins[mode]
if !ok || ins == nil {
switch mode {
case "百度":
ins = baidutts.NewBaiduTTS(int(i&0x0f00) >> 8)
case "拟声鸟":
case extrattsname[0]:
id, sec, _ := strings.Cut(.k, ",")
ins = baidutts.NewBaiduTTS(int(i&0xff00)>>8, id, sec)
case extrattsname[1]:
var err error
ins, err = mockingbird.NewMockingBirdTTS(int(i&0xf000) >> 12)
ins, err = ttscn.NewTTSCN("中文(普通话,简体)", ttscnspeakers[int(i&0xff00)>>8], ttscn.KBRates[0])
if err != nil {
return nil, err
}
case extrattsname[2]:
ins = lolimi.NewLolimi(int(i&0xff00) >> 8)
default: // 原神
k := t.getAPIKey(ctx)
k := .k
if k != "" {
ins = genshin.NewGenshin(int(m), t.getAPIKey(ctx))
ins = genshin.NewGenshin(int(m-1), .k)
ttsins[mode] = ins
} else {
return nil, errors.New("no valid speaker")
ins = lolimi.NewLolimi(int(i&0xff00) >> 8)
}
}
}
@@ -216,11 +246,12 @@ func (t *ttsmode) resetSoundMode(ctx *zero.Ctx) error {
gid = -ctx.Event.UserID
}
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
index := m.GetData(defaultttsindexkey)
return m.SetData(gid, (m.GetData(gid)&0xff)|((index&^0xff)<<8)) // 重置数据
// 只保留后面8位
(*syncx.Map[int64, int64])(t).Delete(gid)
return m.SetData(gid, (m.GetData(gid) & 0xff)) // 重置数据
}
func (t *ttsmode) setDefaultSoundMode(name string, baiduper, mockingsynt int) error {
func (t *ttsmode) setDefaultSoundMode(name string, character int) error {
_, ok := ttsins[name]
if !ok {
return errors.New("不支持设置语音人物" + name)
@@ -228,16 +259,18 @@ func (t *ttsmode) setDefaultSoundMode(name string, baiduper, mockingsynt int) er
index := int64(-1)
for i, s := range genshin.SoundList {
if s == name {
index = int64(i)
index = int64(i + 1)
break
}
}
if index == -1 {
switch name {
case "百度":
case extrattsname[0]:
index = baiduttsindex
case "拟声鸟":
index = mockingbirdttsindex
case extrattsname[1]:
index = ttscnttsindex
case extrattsname[2]:
index = lolimittsindex
default:
return errors.New("语音人物" + name + "未注册index")
}
@@ -246,6 +279,7 @@ func (t *ttsmode) setDefaultSoundMode(name string, baiduper, mockingsynt int) er
if !ok {
return errors.New("[tts] service not found")
}
t.mode.Store(defaultttsindexkey, index)
return m.SetData(defaultttsindexkey, (index&0xff)|((int64(baiduper)<<8)&0x0f00)|((int64(mockingsynt)<<12)&0xf000))
storeIndex := (index & 0xff) | ((int64(character) << 8) & 0xff00)
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, storeIndex)
return m.SetData(defaultttsindexkey, storeIndex)
}

View File

@@ -2,7 +2,10 @@
package aireply
import (
"os"
"regexp"
"strconv"
"strings"
"time"
"github.com/FloatTech/AnimeAPI/tts/genshin"
@@ -14,76 +17,116 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
)
var t = newttsmode()
var replmd = replymode([]string{"婧枫", "沫沫", "青云客", "小爱", "ChatGPT"})
var ttsmd = newttsmode()
func init() { // 插件主体
ent := control.Register("tts", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Brief: "人工智能语音回复",
Help: "- @Bot 任意文本(任意一句话回复)\n" +
"- 设置语音模式[原神人物/百度/拟声鸟] 数字(百度/拟声鸟模式)\n" +
"- 设置默认语音模式[原神人物/百度/拟声鸟] 数字(百度/拟声鸟模式)\n" +
"- 设置语音模式[原神人物/百度/TTSCN/桑帛云] 数字(百度/TTSCN说话人/桑帛云)\n" +
"- 设置默认语音模式[原神人物/百度/TTSCN/桑帛云] 数字(百度/TTSCN说话人/桑帛云)\n" +
"- 恢复成默认语音模式\n" +
"- 设置语音回复模式[沫沫|婧枫|青云客|小爱|ChatGPT]\n" +
"- 设置原神语音 api key xxxxxx (key请加开发群获得)\n" +
"当前适用的原神人物含有以下:\n" + list(genshin.SoundList[:], 5),
"- 设置百度语音 api id xxxxxx secret xxxxxx (请自行获得)\n" +
"当前适用的原神人物含有以下: \n" + list(genshin.SoundList[:], 5) +
"\n当前适用的TTSCN人物含有以下(以数字顺序代表): \n" + list(ttscnspeakers[:], 5),
PrivateDataFolder: "tts",
})
enr := control.Register("aireply", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "人工智能回复",
Help: "- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客|小爱]",
Help: "- @Bot 任意文本(任意一句话回复)\n- 设置文字回复模式[婧枫|沫沫|青云客|小爱|ChatGPT]\n- 设置 ChatGPT api key xxx",
PrivateDataFolder: "aireply",
})
enr.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
aireply := getReplyMode(ctx)
aireply := replmd.getReplyMode(ctx)
reply := message.ParseMessageFromString(aireply.Talk(ctx.Event.UserID, ctx.ExtractPlainText(), zero.BotConfig.NickName[0]))
// 回复
time.Sleep(time.Second * 1)
if zero.OnlyPublic(ctx) {
reply = append(reply, message.Reply(ctx.Event.MessageID))
ctx.Send(reply)
return
}
reply = append(reply, message.Reply(ctx.Event.MessageID))
ctx.Send(reply)
})
enr.OnPrefix("设置回复模式", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
setReplyMode := func(ctx *zero.Ctx) {
param := ctx.State["args"].(string)
err := setReplyMode(ctx, param)
err := replmd.setReplyMode(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("成功"))
}
enr.OnPrefix("设置文字回复模式", zero.AdminPermission).SetBlock(true).Handle(setReplyMode)
enr.OnRegex(`^设置\s*ChatGPT\s*api\s*key\s*(.*)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
err := ཆཏ.set(ctx.State["regex_matched"].([]string)[1])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("设置成功"))
})
endpre := regexp.MustCompile(`\pP$`)
ttscachedir := ent.DataFolder() + "cache/"
_ = os.RemoveAll(ttscachedir)
err := os.MkdirAll(ttscachedir, 0755)
if err != nil {
panic(err)
}
ent.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
msg := ctx.ExtractPlainText()
// 获取回复模式
r := getReplyMode(ctx)
r := replmd.getReplyMode(ctx)
// 获取回复的文本
reply := r.TalkPlain(ctx.Event.UserID, msg, zero.BotConfig.NickName[0])
reply := message.ParseMessageFromString(r.TalkPlain(ctx.Event.UserID, msg, zero.BotConfig.NickName[0]))
// 过滤掉文字消息
filterMsg := make([]message.MessageSegment, 0, len(reply))
sb := strings.Builder{}
for _, v := range reply {
if v.Type != "text" {
filterMsg = append(filterMsg, v)
} else {
sb.WriteString(v.Data["text"])
}
}
// 纯文本
plainReply := sb.String()
plainReply = strings.ReplaceAll(plainReply, "\n", "")
// 获取语音
speaker, err := t.getSoundMode(ctx)
speaker, err := ttsmd.getSoundMode(ctx)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
rec, err := speaker.Speak(ctx.Event.UserID, func() string { return reply })
rec, err := speaker.Speak(ctx.Event.UserID, func() string {
if !endpre.MatchString(plainReply) {
return plainReply + "。"
}
return plainReply
})
// 发送前面的图片
if len(filterMsg) != 0 {
filterMsg = append(filterMsg, message.Reply(ctx.Event.MessageID))
ctx.Send(filterMsg)
}
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(plainReply))
return
}
// 发送语音
if id := ctx.SendChain(message.Record(rec)); id.ID() == 0 {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(plainReply))
}
})
ent.OnRegex(`^设置语音模式\s*([\S\D]*)\s*(\d*)$`, zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
ent.OnPrefix("设置语音回复模式", zero.AdminPermission).SetBlock(true).Handle(setReplyMode)
ent.OnRegex(`^设置语音模式\s*([\S\D]*)\s+(\d*)$`, zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
param := ctx.State["regex_matched"].([]string)[1]
num := ctx.State["regex_matched"].([]string)[2]
n := 0
@@ -96,37 +139,39 @@ func init() { // 插件主体
}
}
// 保存设置
logrus.Debugln("[tts] t.setSoundMode( ctx", param, n, n, ")")
err = t.setSoundMode(ctx, param, n, n)
logrus.Debugln("[tts] t.setSoundMode( ctx", param, n, ")")
err = ttsmd.setSoundMode(ctx, param, n)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
if banner, ok := genshin.TestRecord[param]; ok {
logrus.Debugln("[tts] banner:", banner, "get sound mode...")
// 设置验证
speaker, err := t.getSoundMode(ctx)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
logrus.Debugln("[tts] got sound mode, speaking...")
rec, err := speaker.Speak(ctx.Event.UserID, func() string { return banner })
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("无法发送测试语音,请重试。"))
return
}
logrus.Debugln("[tts] sending...")
if id := ctx.SendChain(message.Record(rec).Add("cache", 0)); id.ID() == 0 {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("无法发送测试语音,请重试。"))
return
}
time.Sleep(time.Second * 2)
banner := genshin.TestRecord[param]
if banner == "" {
banner = genshin.TestRecord["默认"]
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功"))
logrus.Debugln("[tts] banner:", banner, "get sound mode...")
// 设置验证
speaker, err := ttsmd.getSoundMode(ctx)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
logrus.Debugln("[tts] got sound mode, speaking...")
rec, err := speaker.Speak(ctx.Event.UserID, func() string { return banner })
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("无法发送测试语音,请重试。"))
return
}
logrus.Debugln("[tts] sending...")
if id := ctx.SendChain(message.Record(rec).Add("cache", 0)); id.ID() == 0 {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("无法发送测试语音,请重试。"))
return
}
time.Sleep(time.Second * 2)
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前为", speaker))
})
ent.OnRegex(`^设置默认语音模式\s*([\S\D]*)\s*(\d*)$`, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
ent.OnRegex(`^设置默认语音模式\s*([\S\D]*)\s+(\d*)$`, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
param := ctx.State["regex_matched"].([]string)[1]
num := ctx.State["regex_matched"].([]string)[2]
n := 0
@@ -139,7 +184,7 @@ func init() { // 插件主体
}
}
// 保存设置
err = t.setDefaultSoundMode(param, n, n)
err = ttsmd.setDefaultSoundMode(param, n)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
@@ -148,13 +193,13 @@ func init() { // 插件主体
})
ent.OnFullMatch("恢复成默认语音模式", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
err := t.resetSoundMode(ctx)
err := ttsmd.resetSoundMode(ctx)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
// 设置验证
speaker, err := t.getSoundMode(ctx)
speaker, err := ttsmd.getSoundMode(ctx)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -163,7 +208,16 @@ func init() { // 插件主体
})
ent.OnRegex(`^设置原神语音\s*api\s*key\s*([0-9a-zA-Z-_]{54}==)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
err := t.setAPIKey(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), ctx.State["regex_matched"].([]string)[1])
err := .set(ctx.State["regex_matched"].([]string)[1])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("设置成功"))
})
ent.OnRegex(`^设置百度语音\s*api\s*id\s*(.*)\s*secret\s*(.*)\s*$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
err := .set(ctx.State["regex_matched"].([]string)[1] + "," + ctx.State["regex_matched"].([]string)[2])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return

29
plugin/ai_reply/model.go Normal file
View File

@@ -0,0 +1,29 @@
package aireply
import (
"os"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
)
type apikeystore struct {
k string
p string
}
func newapikeystore(p string) (s apikeystore) {
s.p = p
if file.IsExist(p) {
data, err := os.ReadFile(p)
if err == nil {
s.k = binary.BytesToString(data)
}
}
return
}
func (s *apikeystore) set(k string) error {
s.k = k
return os.WriteFile(s.p, binary.StringToBytes(k), 0644)
}

709
plugin/aifalse/main.go Normal file
View File

@@ -0,0 +1,709 @@
// Package aifalse 暂时只有服务器监控
package aifalse
import (
"bytes"
"errors"
"image"
"image/color"
"math"
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"unsafe"
"github.com/FloatTech/AnimeAPI/bilibili"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/gg"
"github.com/FloatTech/imgfactory"
"github.com/FloatTech/rendercard"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/text"
"github.com/disintegration/imaging"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/mem"
"github.com/sirupsen/logrus"
"golang.org/x/text/cases"
"golang.org/x/text/language"
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
backgroundURL = "https://iw233.cn/api.php?sort=mp"
referer = "https://weibo.com/"
)
var (
boottime = time.Now()
bgdata *[]byte
bgcount uintptr
isday bool
lightcolor = [3][4]uint8{{255, 70, 0, 255}, {255, 165, 0, 255}, {145, 240, 145, 255}}
darkcolor = [3][4]uint8{{215, 50, 0, 255}, {205, 135, 0, 255}, {115, 200, 115, 255}}
)
func init() { // 插件主体
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "自检, 全局限速",
Help: "- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]\n" +
"- 设置默认限速为每 m [分钟 | 秒] n 次触发",
})
c, ok := control.Lookup("aifalse")
if !ok {
panic("register aifalse error")
}
m := c.GetData(0)
n := (m >> 16) & 0xffff
m &= 0xffff
if m != 0 || n != 0 {
ctxext.SetDefaultLimiterManagerParam(time.Duration(m)*time.Second, int(n))
logrus.Infoln("设置默认限速为每", m, "秒触发", n, "次")
}
engine.OnFullMatchGroup([]string{"检查身体", "自检", "启动自检", "系统状态"}, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
isday = now > 7 && now < 19
botrunstatus := ctx.CallAction("get_status", zero.Params{}).Data
botverisoninfo := ctx.GetVersionInfo()
sb := &strings.Builder{}
sb.WriteString("在线(")
sb.WriteString(botverisoninfo.Get("app_name").String())
sb.WriteString("-")
sb.WriteString(botverisoninfo.Get("app_version").String())
sb.WriteString(") | 收")
sb.WriteString(botrunstatus.Get("stat").Get("message_received").String())
sb.WriteString(" | 发")
sb.WriteString(botrunstatus.Get("stat").Get("message_sent").String())
sb.WriteString(" | 群")
sb.WriteString(strconv.Itoa(len(ctx.GetGroupList().Array())))
sb.WriteString(" | 好友")
sb.WriteString(strconv.Itoa(len(ctx.GetFriendList().Array())))
img, err := drawstatus(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), ctx.Event.SelfID, zero.BotConfig.NickName[0], sb.String())
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
sendimg, err := imgfactory.ToBytes(img)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if id := ctx.SendChain(message.ImageBytes(sendimg)); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
})
engine.OnRegex(`^设置默认限速为每\s*(\d+)\s*(分钟|秒)\s*(\d+)\s*次触发$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("ERROR: no such plugin"))
return
}
m, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if ctx.State["regex_matched"].([]string)[2] == "分钟" {
m *= 60
}
if m >= 65536 || m <= 0 {
ctx.SendChain(message.Text("ERROR: interval too big"))
return
}
n, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[3], 10, 64)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if n >= 65536 || n <= 0 {
ctx.SendChain(message.Text("ERROR: burst too big"))
return
}
ctxext.SetDefaultLimiterManagerParam(time.Duration(m)*time.Second, int(n))
err = c.SetData(0, (m&0xffff)|((n<<16)&0xffff0000))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("设置默认限速为每", m, "秒触发", n, "次"))
})
}
func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string, botrunstatus string) (sendimg image.Image, err error) {
diskstate, err := diskstate()
if err != nil {
return
}
diskcardh := 40 + (20+50)*len(diskstate) + 40 - 20
moreinfo, err := moreinfo(m)
if err != nil {
return
}
moreinfocardh := 30 + (20+32*72/96)*len(moreinfo) + 30 - 20
basicstate, err := basicstate()
if err != nil {
return
}
dldata := (*[]byte)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&bgdata))))
if dldata == (*[]byte)(nil) || uintptr(time.Since(boottime).Hours()/24) >= atomic.LoadUintptr(&bgcount) {
url, err1 := bilibili.GetRealURL(backgroundURL)
if err1 != nil {
return nil, err1
}
data, err1 := web.RequestDataWith(web.NewDefaultClient(), url, "", referer, "", nil)
if err1 != nil {
return nil, err1
}
atomic.AddUintptr(&bgcount, 1)
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&bgdata)), unsafe.Pointer(&data))
dldata = &data
}
data := *dldata
back, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return
}
data, err = web.GetData("http://q4.qlogo.cn/g?b=qq&nk=" + strconv.FormatInt(uid, 10) + "&s=640")
if err != nil {
return
}
avatar, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return
}
avatarf := imgfactory.Size(avatar, 200, 200)
fontbyte, err := file.GetLazyData(text.GlowSansFontFile, control.Md5File, true)
if err != nil {
return
}
canvas := gg.NewContext(1280, 70+250+40+380+diskcardh+40+moreinfocardh+40+70)
bh, bw, ch, cw := float64(back.Bounds().Dy()), float64(back.Bounds().Dx()), float64(canvas.H()), float64(canvas.W())
if bh/bw < ch/cw {
back = imgfactory.Size(back, int(bw*ch/bh), int(bh*ch/bh)).Image()
canvas.DrawImageAnchored(back, canvas.W()/2, canvas.H()/2, 0.5, 0.5)
} else {
back = imgfactory.Size(back, int(bw*cw/bw), int(bh*cw/bw)).Image()
canvas.DrawImage(back, 0, 0)
}
var blurback image.Image
bwg := &sync.WaitGroup{}
bwg.Add(1)
go func() {
defer bwg.Done()
blurback = imaging.Blur(canvas.Image(), 8)
}()
if !isday {
canvas.SetRGBA255(0, 0, 0, 50)
canvas.DrawRectangle(0, 0, cw, ch)
canvas.Fill()
}
wg := &sync.WaitGroup{}
wg.Add(5)
cardw := canvas.W() - 70 - 70
titlecardh := 250
basiccardh := 380
var titleimg, basicimg, diskimg, moreinfoimg, shadowimg image.Image
go func() {
defer wg.Done()
titlecard := gg.NewContext(cardw, titlecardh)
bwg.Wait()
titlecard.DrawImage(blurback, -70, -70)
titlecard.DrawRoundedRectangle(1, 1, float64(titlecard.W()-1*2), float64(titlecardh-1*2), 16)
titlecard.SetLineWidth(3)
titlecard.SetColor(colorswitch(100))
titlecard.StrokePreserve()
titlecard.SetColor(colorswitch(140))
titlecard.Fill()
titlecard.DrawImage(avatarf.Circle(0).Image(), (titlecardh-avatarf.H())/2, (titlecardh-avatarf.H())/2)
err = titlecard.ParseFontFace(fontbyte, 72)
if err != nil {
return
}
fw, _ := titlecard.MeasureString(botname)
titlecard.SetColor(fontcolorswitch())
titlecard.DrawStringAnchored(botname, float64(titlecardh)+fw/2, float64(titlecardh)*0.5/2, 0.5, 0.5)
err = titlecard.ParseFontFace(fontbyte, 24)
if err != nil {
return
}
titlecard.SetColor(fontcolorswitch())
titlecard.NewSubPath()
titlecard.MoveTo(float64(titlecardh), float64(titlecardh)/2)
titlecard.LineTo(float64(titlecard.W()-titlecardh), float64(titlecardh)/2)
titlecard.Stroke()
fw, _ = titlecard.MeasureString(botrunstatus)
titlecard.DrawStringAnchored(botrunstatus, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.25/2), 0.5, 0.5)
brt, err := botruntime()
if err != nil {
return
}
fw, _ = titlecard.MeasureString(brt)
titlecard.DrawStringAnchored(brt, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.5/2), 0.5, 0.5)
bs, err := botstatus()
if err != nil {
return
}
fw, _ = titlecard.MeasureString(bs)
titlecard.DrawStringAnchored(bs, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.75/2), 0.5, 0.5)
titleimg = rendercard.Fillet(titlecard.Image(), 16)
}()
go func() {
defer wg.Done()
basiccard := gg.NewContext(cardw, basiccardh)
bwg.Wait()
basiccard.DrawImage(blurback, -70, -70-titlecardh-40)
basiccard.DrawRoundedRectangle(1, 1, float64(basiccard.W()-1*2), float64(basiccardh-1*2), 16)
basiccard.SetLineWidth(3)
basiccard.SetColor(colorswitch(100))
basiccard.StrokePreserve()
basiccard.SetColor(colorswitch(140))
basiccard.Fill()
bslen := len(basicstate)
for i, v := range basicstate {
offset := float64(i) * ((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1) + 200)
basiccard.SetRGBA255(57, 57, 57, 255)
if isday {
basiccard.SetRGBA255(235, 235, 235, 255)
}
basiccard.DrawCircle((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 100)
basiccard.Fill()
colors := darkcolor
if isday {
colors = lightcolor
}
switch {
case v.precent > 90:
basiccard.SetColor(slice2color(colors[0]))
case v.precent > 70:
basiccard.SetColor(slice2color(colors[1]))
default:
basiccard.SetColor(slice2color(colors[2]))
}
basiccard.NewSubPath()
basiccard.MoveTo((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2)
basiccard.DrawEllipticalArc((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 100, 100, -0.5*math.Pi, -0.5*math.Pi+2*v.precent*0.01*math.Pi)
basiccard.Fill()
basiccard.SetColor(colorswitch(255))
basiccard.DrawCircle((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 80)
basiccard.Fill()
err = basiccard.ParseFontFace(fontbyte, 42)
if err != nil {
return
}
basiccard.SetRGBA255(213, 213, 213, 255)
basiccard.DrawStringAnchored(strconv.FormatFloat(v.precent, 'f', 0, 64)+"%", (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 0.5, 0.5)
basiccard.SetColor(fontcolorswitch())
_, fw := basiccard.MeasureString(v.name)
basiccard.DrawStringAnchored(v.name, (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200+15+basiccard.FontHeight()/2, 0.5, 0.5)
err = basiccard.ParseFontFace(fontbyte, 20)
if err != nil {
return
}
basiccard.SetColor(fontcolorswitch())
textoffsety := basiccard.FontHeight() + 10
for k, s := range v.text {
basiccard.DrawStringAnchored(s, (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200+15+fw+15+basiccard.FontHeight()/2+float64(k)*textoffsety, 0.5, 0.5)
}
}
basicimg = rendercard.Fillet(basiccard.Image(), 16)
}()
go func() {
defer wg.Done()
diskcard := gg.NewContext(cardw, diskcardh)
bwg.Wait()
diskcard.DrawImage(blurback, -70, -70-titlecardh-40-basiccardh-40)
diskcard.DrawRoundedRectangle(1, 1, float64(diskcard.W()-1*2), float64(diskcardh-1*2), 16)
diskcard.SetLineWidth(3)
diskcard.SetColor(colorswitch(100))
diskcard.StrokePreserve()
diskcard.SetColor(colorswitch(140))
diskcard.Fill()
err = diskcard.ParseFontFace(fontbyte, 32)
if err != nil {
return
}
dslen := len(diskstate)
if dslen == 1 {
diskcard.SetRGBA255(57, 57, 57, 255)
if isday {
diskcard.SetRGBA255(192, 192, 192, 255)
}
diskcard.DrawRoundedRectangle(40, 40, float64(diskcard.W())-40-100, 50, 12)
diskcard.ClipPreserve()
diskcard.Fill()
colors := darkcolor
if isday {
colors = lightcolor
}
switch {
case diskstate[0].precent > 90:
diskcard.SetColor(slice2color(colors[0]))
case diskstate[0].precent > 70:
diskcard.SetColor(slice2color(colors[1]))
default:
diskcard.SetColor(slice2color(colors[2]))
}
diskcard.DrawRoundedRectangle(40, 40, (float64(diskcard.W())-40-100)*diskstate[0].precent*0.01, 50, 12)
diskcard.Fill()
diskcard.ResetClip()
diskcard.SetColor(fontcolorswitch())
fw, _ := diskcard.MeasureString(diskstate[0].name)
fw1, _ := diskcard.MeasureString(diskstate[0].text[0])
diskcard.DrawStringAnchored(diskstate[0].name, 40+10+fw/2, 40+50/2, 0.5, 0.5)
diskcard.DrawStringAnchored(diskstate[0].text[0], (float64(diskcard.W())-100-10)-fw1/2, 40+50/2, 0.5, 0.5)
diskcard.DrawStringAnchored(strconv.FormatFloat(diskstate[0].precent, 'f', 0, 64)+"%", float64(diskcard.W())-100/2, 40+50/2, 0.5, 0.5)
} else {
for i, v := range diskstate {
offset := float64(i)*(50+20) - 20
diskcard.SetRGBA255(57, 57, 57, 255)
if isday {
diskcard.SetRGBA255(192, 192, 192, 255)
}
diskcard.DrawRoundedRectangle(40, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+offset, float64(diskcard.W())-40-100, 50, 12)
diskcard.Fill()
colors := darkcolor
if isday {
colors = lightcolor
}
switch {
case v.precent > 90:
diskcard.SetColor(slice2color(colors[0]))
case v.precent > 70:
diskcard.SetColor(slice2color(colors[1]))
default:
diskcard.SetColor(slice2color(colors[2]))
}
diskcard.DrawRoundedRectangle(40, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+offset, (float64(diskcard.W())-40-100)*v.precent*0.01, 50, 12)
diskcard.Fill()
diskcard.SetColor(fontcolorswitch())
fw, _ := diskcard.MeasureString(v.name)
fw1, _ := diskcard.MeasureString(v.text[0])
diskcard.DrawStringAnchored(v.name, 40+10+fw/2, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+50/2+offset, 0.5, 0.5)
diskcard.DrawStringAnchored(v.text[0], (float64(diskcard.W())-100-10)-fw1/2, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+50/2+offset, 0.5, 0.5)
diskcard.DrawStringAnchored(strconv.FormatFloat(v.precent, 'f', 0, 64)+"%", float64(diskcard.W())-100/2, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+50/2+offset, 0.5, 0.5)
}
}
diskimg = rendercard.Fillet(diskcard.Image(), 16)
}()
go func() {
defer wg.Done()
moreinfocard := gg.NewContext(cardw, moreinfocardh)
bwg.Wait()
moreinfocard.DrawImage(blurback, -70, -70-titlecardh-40-basiccardh-40-diskcardh-40)
moreinfocard.DrawRoundedRectangle(1, 1, float64(moreinfocard.W()-1*2), float64(moreinfocard.H()-1*2), 16)
moreinfocard.SetLineWidth(3)
moreinfocard.SetColor(colorswitch(100))
moreinfocard.StrokePreserve()
moreinfocard.SetColor(colorswitch(140))
moreinfocard.Fill()
err = moreinfocard.ParseFontFace(fontbyte, 32)
if err != nil {
return
}
milen := len(moreinfo)
for i, v := range moreinfo {
offset := float64(i)*(20+moreinfocard.FontHeight()) - 20
moreinfocard.SetColor(fontcolorswitch())
fw, _ := moreinfocard.MeasureString(v.name)
fw1, _ := moreinfocard.MeasureString(v.text[0])
moreinfocard.DrawStringAnchored(v.name, 20+fw/2, 30+(float64(moreinfocardh-30*2)-moreinfocard.FontHeight()*float64(milen))/float64(milen-1)+moreinfocard.FontHeight()/2+offset, 0.5, 0.5)
moreinfocard.DrawStringAnchored(v.text[0], float64(moreinfocard.W())-20-fw1/2, 30+(float64(moreinfocardh-30*2)-moreinfocard.FontHeight()*float64(milen))/float64(milen-1)+moreinfocard.FontHeight()/2+offset, 0.5, 0.5)
}
moreinfoimg = rendercard.Fillet(moreinfocard.Image(), 16)
}()
go func() {
defer wg.Done()
shadow := gg.NewContext(canvas.W(), canvas.H())
shadow.SetRGBA255(0, 0, 0, 100)
shadow.SetLineWidth(12)
shadow.DrawRoundedRectangle(70, 70, float64(cardw), float64(titlecardh), 16)
shadow.Stroke()
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40), float64(cardw), float64(basiccardh), 16)
shadow.Stroke()
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40), float64(cardw), float64(diskcardh), 16)
shadow.Stroke()
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40+diskcardh+40), float64(cardw), float64(moreinfocardh), 16)
shadow.Stroke()
shadowimg = imaging.Blur(shadow.Image(), 24)
}()
wg.Wait()
if shadowimg == nil || titleimg == nil || basicimg == nil || diskimg == nil || moreinfoimg == nil {
err = errors.New("图片渲染失败")
return
}
canvas.DrawImage(shadowimg, 0, 0)
canvas.DrawImage(titleimg, 70, 70)
canvas.DrawImage(basicimg, 70, 70+titlecardh+40)
canvas.DrawImage(diskimg, 70, 70+titlecardh+40+basiccardh+40)
canvas.DrawImage(moreinfoimg, 70, 70+titlecardh+40+basiccardh+40+diskcardh+40)
err = canvas.ParseFontFace(fontbyte, 28)
if err != nil {
return
}
canvas.SetRGBA255(0, 0, 0, 255)
canvas.DrawStringAnchored("Created By ZeroBot-Plugin "+banner.Version, float64(canvas.W())/2+3, float64(canvas.H())-70/2+3, 0.5, 0.5)
canvas.SetRGBA255(255, 255, 255, 255)
canvas.DrawStringAnchored("Created By ZeroBot-Plugin "+banner.Version, float64(canvas.W())/2, float64(canvas.H())-70/2, 0.5, 0.5)
sendimg = canvas.Image()
return
}
func botruntime() (string, error) {
hostinfo, err := host.Info()
if err != nil {
return "", err
}
t := &strings.Builder{}
t.WriteString("ZeroBot-Plugin 已运行 ")
t.WriteString(strconv.FormatInt((time.Now().Unix()-boottime.Unix())/86400, 10))
t.WriteString(" 天 ")
t.WriteString(time.Unix(time.Now().Unix()-boottime.Unix(), 0).UTC().Format("15:04:05"))
t.WriteString(" | 系统运行 ")
t.WriteString(strconv.FormatInt(int64(hostinfo.Uptime)/86400, 10))
t.WriteString(" 天 ")
t.WriteString(time.Unix(int64(hostinfo.Uptime), 0).UTC().Format("15:04:05"))
return t.String(), nil
}
func botstatus() (string, error) {
hostinfo, err := host.Info()
if err != nil {
return "", err
}
t := &strings.Builder{}
t.WriteString(time.Now().Format("2006-01-02 15:04:05"))
t.WriteString(" | Compiled by ")
t.WriteString(runtime.Version())
t.WriteString(" | ")
t.WriteString(cases.Title(language.English).String(hostinfo.OS))
t.WriteString(" ")
t.WriteString(runtime.GOARCH)
return t.String(), nil
}
type status struct {
precent float64
name string
text []string
}
func basicstate() (stateinfo [3]*status, err error) {
percent, err := cpu.Percent(time.Second, true)
if err != nil {
return
}
cpuinfo, err := cpu.Info()
if err != nil {
return
}
cpucore, err := cpu.Counts(false)
if err != nil {
return
}
cputhread, err := cpu.Counts(true)
if err != nil {
return
}
cores := strconv.Itoa(cpucore) + "C" + strconv.Itoa(cputhread) + "T"
times := "最大 " + strconv.FormatFloat(cpuinfo[0].Mhz/1000, 'f', 1, 64) + "Ghz"
stateinfo[0] = &status{
precent: math.Round(percent[0]),
name: "CPU",
text: []string{cores, times},
}
raminfo, err := mem.VirtualMemory()
if err != nil {
return
}
total := "总共 " + storagefmt(float64(raminfo.Total))
used := "已用 " + storagefmt(float64(raminfo.Used))
free := "剩余 " + storagefmt(float64(raminfo.Free))
stateinfo[1] = &status{
precent: math.Round(raminfo.UsedPercent),
name: "RAM",
text: []string{total, used, free},
}
swapinfo, err := mem.SwapMemory()
if err != nil {
return
}
total = "总共 " + storagefmt(float64(swapinfo.Total))
used = "已用 " + storagefmt(float64(swapinfo.Used))
free = "剩余 " + storagefmt(float64(swapinfo.Free))
stateinfo[2] = &status{
precent: math.Round(swapinfo.UsedPercent),
name: "SWAP",
text: []string{total, used, free},
}
return
}
func storagefmt(num float64) string {
if num /= 1024; num < 1 {
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "B"
}
if num /= 1024; num < 1 {
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "KB"
}
if num /= 1024; num < 1 {
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "MB"
}
if num /= 1024; num < 1 {
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "GB"
}
return strconv.FormatFloat(num, 'f', 2, 64) + "TB"
}
func diskstate() (stateinfo []*status, err error) {
parts, err := disk.Partitions(false)
if err != nil {
return
}
stateinfo = make([]*status, 0, len(parts))
for _, v := range parts {
mp := v.Mountpoint
if strings.HasPrefix(mp, "/snap/") || strings.HasPrefix(mp, "/apex/") {
continue
}
diskusage, err := disk.Usage(mp)
if err != nil {
continue
}
stateinfo = append(stateinfo, &status{
precent: math.Round(diskusage.UsedPercent),
name: mp,
text: []string{storagefmt(float64(diskusage.Used)) + " / " + storagefmt(float64(diskusage.Total))},
})
}
return stateinfo, nil
}
func moreinfo(m *ctrl.Control[*zero.Ctx]) (stateinfo []*status, err error) {
var mems runtime.MemStats
runtime.ReadMemStats(&mems)
fmtmem := storagefmt(float64(mems.Sys))
hostinfo, err := host.Info()
if err != nil {
return
}
cpuinfo, err := cpu.Info()
if err != nil {
return
}
count := len(m.Manager.M)
stateinfo = []*status{
{name: "OS", text: []string{hostinfo.Platform}},
{name: "CPU", text: []string{strings.TrimSpace(cpuinfo[0].ModelName)}},
{name: "Version", text: []string{hostinfo.PlatformVersion}},
{name: "Plugin", text: []string{"共 " + strconv.Itoa(count) + " 个"}},
{name: "Memory", text: []string{"已用 " + fmtmem}},
}
return
}
func colorswitch(a uint8) color.Color {
if isday {
return color.NRGBA{255, 255, 255, a}
}
return color.NRGBA{0, 0, 0, a}
}
func fontcolorswitch() color.Color {
if isday {
return color.NRGBA{30, 30, 30, 255}
}
return color.NRGBA{235, 235, 235, 255}
}
func slice2color(c [4]uint8) color.Color {
return color.NRGBA{c[0], c[1], c[2], c[3]}
}

View File

@@ -46,7 +46,7 @@ func (r *result) String() string {
}
func init() { // 插件主体
engine := control.Register("aipaint", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "ai绘图",
Help: "- [ ai绘图 | 生成色图 | 生成涩图 | ai画图 ] xxx\n" +
@@ -54,9 +54,9 @@ func init() { // 插件主体
"- 设置ai绘图配置 [server] [token]\n" +
"- 设置ai绘图撤回时间90s\n" +
"- 查看ai绘图配置\n" +
"例: 设置ai绘图配置 http://91.217.139.190:5010 abc\n" +
"Tips: 使用前请先前往 http://91.217.139.190:5010/token 按提示获取token" +
"设置token示例(请确保是主人并且响应): 设置ai绘图配置 http://91.217.139.190:5010 [token] (中括号无需输入)\n" +
"参考服务器 http://91.217.139.190:5010, http://91.216.169.75:5010, http://185.80.202.180:5010\n" +
"通过 http://91.217.139.190:5010/token 获取token\n" +
"[prompt]参数如下\n" +
"tags:tag词条\nntags:ntag词条\nshape:[Portrait|Landscape|Square]\nscale:[6:20]\nseed:种子\nstrength:[0-1] 建议0-0.7\nnoise:[0-1] 建议0-0.15" +
"参数与参数内容用:连接,每个参数之间用回车分割",
@@ -146,7 +146,7 @@ func init() { // 插件主体
}
sendAiImg(ctx, data, cfg.Interval)
})
engine.OnRegex(`^设置ai绘图配置\s(.*[^\s$])\s(.+)$`, zero.SuperUserPermission).SetBlock(true).
engine.OnRegex(`^设置ai绘图配置\s(.*[^\s$])\s(.+)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
regexMatched := ctx.State["regex_matched"].([]string)
err := cfg.load()
@@ -159,8 +159,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("ERROR: ", err))
return
}
text := fmt.Sprintf("成功设置\nbase_url: %v\ntoken: %v\ninterval: %v\n", cfg.BaseURL, cfg.Token, cfg.Interval)
ctx.SendChain(message.Text(text))
ctx.SendChain(message.Text("成功设置\nbase_url: ", cfg.BaseURL, "\ntoken: ", cfg.Token, "\ninterval: ", cfg.Interval))
})
engine.OnRegex(`^设置ai绘图撤回时间(\d{1,3})s$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
@@ -180,18 +179,16 @@ func init() { // 插件主体
ctx.SendChain(message.Text("ERROR: ", err))
return
}
text := fmt.Sprintf("成功设置\nbase_url: %v\ntoken: %v\ninterval: %v\n", cfg.BaseURL, cfg.Token, cfg.Interval)
ctx.SendChain(message.Text(text))
ctx.SendChain(message.Text("成功设置撤回时间为", cfg.Interval, "s"))
})
engine.OnFullMatch(`查看ai绘图配置`, zero.SuperUserPermission).SetBlock(true).
engine.OnFullMatch(`查看ai绘图配置`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
text := fmt.Sprintf("base_url: %v\ntoken: %v\ninterval: %v\n", cfg.BaseURL, cfg.Token, cfg.Interval)
ctx.SendChain(message.Text(text))
ctx.SendChain(message.Text("base_url: ", cfg.BaseURL, "\ntoken: ", cfg.Token, "\ninterval: ", cfg.Interval))
})
}

View File

@@ -11,8 +11,8 @@ import (
"strings"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/imgfactory"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -73,7 +73,7 @@ func init() { // 插件主体
}
// 图片转base64
base64Bytes, err := writer.ToBase64(img)
base64Bytes, err := imgfactory.ToBase64(img)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return

View File

@@ -17,7 +17,7 @@ const (
)
func init() { // 插件主体
control.Register("aiwife", &ctrl.Options[*zero.Ctx]{
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "ai随机生成老婆",
Help: "- waifu | 随机waifu",

View File

@@ -16,7 +16,7 @@ const (
)
func init() { // 插件主体
engine := control.Register("alipayvoice", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "支付宝到账语音",
Help: "- 支付宝到账 1",

View File

@@ -38,7 +38,7 @@ func onDel(uid int64, _ struct{}) {
}
func init() {
engine := control.Register("antiabuse", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "违禁词检测",
Help: "- /[添加|删除|查看]违禁词",
@@ -70,7 +70,7 @@ func init() {
if err := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).Manager.DoBlock(uid); err == nil {
t := time.Now().Unix()
cache.Set(uid, struct{}{})
ctx.SetGroupBan(gid, uid, int64(bandur.Minutes()))
ctx.SetThisGroupBan(uid, int64(bandur.Minutes()))
ctx.SendChain(message.Text("检测到违禁词, 已封禁/屏蔽", bandur))
db.Lock()
defer db.Unlock()

View File

@@ -13,7 +13,6 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/floatbox/process"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
)
@@ -41,7 +40,7 @@ func randText(text ...string) message.MessageSegment {
}
// isAtriSleeping 凌晨0点到6点ATRI 在睡觉,不回应任何请求
func isAtriSleeping(ctx *zero.Ctx) bool {
func isAtriSleeping(*zero.Ctx) bool {
if now := time.Now().Hour(); now >= 1 && now < 6 {
return false
}
@@ -49,7 +48,7 @@ func isAtriSleeping(ctx *zero.Ctx) bool {
}
func init() { // 插件主体
engine := control.Register("atri", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "atri人格文本回复",
Help: "本插件基于 ATRI ,为 Golang 移植版\n" +
@@ -58,12 +57,11 @@ func init() { // 插件主体
"- 中午好 | 午安 | 午好\n- 晚安 | oyasuminasai | おやすみなさい | 晚好 | 晚上好\n- 高性能 | 太棒了 | すごい | sugoi | 斯国一 | よかった\n" +
"- 没事 | 没关系 | 大丈夫 | 还好 | 不要紧 | 没出大问题 | 没伤到哪\n- 好吗 | 是吗 | 行不行 | 能不能 | 可不可以\n- 啊这\n- 我好了\n- | ? | ¿\n" +
"- 离谱\n- 答应我",
PublicDataFolder: "Atri",
OnEnable: func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("嗯呜呜……夏生先生……?"))
},
OnDisable: func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("Zzz……Zzz……"))
},
})
@@ -71,7 +69,6 @@ func init() { // 插件主体
var dgtr datagetter = engine.GetLazyData
engine.OnFullMatch("萝卜子").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
switch rand.Intn(2) {
case 0:
ctx.SendChain(randText("萝卜子是对机器人的蔑称!", "是亚托莉......萝卜子可是对机器人的蔑称"))
@@ -81,18 +78,15 @@ func init() { // 插件主体
})
engine.OnFullMatchGroup([]string{"喜欢", "爱你", "爱", "suki", "daisuki", "すき", "好き", "贴贴", "老婆", "亲一个", "mua"}, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(dgtr.randImage("SUKI.jpg", "SUKI1.jpg", "SUKI2.png"))
})
engine.OnKeywordGroup([]string{"草你妈", "操你妈", "脑瘫", "废柴", "fw", "five", "废物", "战斗", "爬", "爪巴", "sb", "SB", "傻B"}, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(dgtr.randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
})
engine.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早", "早早早"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
process.SleepAbout1sTo2s()
switch {
case now < 6: // 凌晨
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
@@ -133,7 +127,6 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
if now > 11 && now < 15 { // 中午
process.SleepAbout1sTo2s()
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
"午安w",
"午觉要好好睡哦ATRI会陪伴在你身旁的w",
@@ -145,7 +138,6 @@ func init() { // 插件主体
engine.OnFullMatchGroup([]string{"晚安", "oyasuminasai", "おやすみなさい", "晚好", "晚上好"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
process.SleepAbout1sTo2s()
switch {
case now < 6: // 凌晨
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText(
@@ -187,7 +179,6 @@ func init() { // 插件主体
})
engine.OnKeywordGroup([]string{"高性能", "太棒了", "すごい", "sugoi", "斯国一", "よかった"}, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(randText(
"当然,我是高性能的嘛~",
"小事一桩,我是高性能的嘛",
@@ -208,7 +199,6 @@ func init() { // 插件主体
})
engine.OnKeywordGroup([]string{"没事", "没关系", "大丈夫", "还好", "不要紧", "没出大问题", "没伤到哪"}, zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(randText(
"当然,我是高性能的嘛~",
"没事没事,因为我是高性能的嘛!嗯哼!",
@@ -223,26 +213,22 @@ func init() { // 插件主体
engine.OnKeywordGroup([]string{"好吗", "是吗", "行不行", "能不能", "可不可以"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
if rand.Intn(2) == 0 {
ctx.SendChain(dgtr.randImage("YES.png", "NO.jpg"))
}
})
engine.OnKeywordGroup([]string{"啊这"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
if rand.Intn(2) == 0 {
ctx.SendChain(dgtr.randImage("AZ.jpg", "AZ1.jpg"))
}
})
engine.OnKeywordGroup([]string{"我好了"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(message.Reply(ctx.Event.MessageID), randText("不许好!", "憋回去!"))
})
engine.OnFullMatchGroup([]string{"", "?", "¿"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
switch rand.Intn(5) {
case 0:
ctx.SendChain(randText("?", "", "嗯?", "(。´・ω・)ん?", "ん?"))
@@ -261,7 +247,6 @@ func init() { // 插件主体
})
engine.OnKeyword("答应我", zero.OnlyToMe).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
process.SleepAbout1sTo2s()
ctx.SendChain(randText("我无法回应你的请求"))
})
}

View File

@@ -10,7 +10,7 @@ import (
)
func init() {
control.Register("autowithdraw", &ctrl.Options[*zero.Ctx]{
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "触发者撤回时也自动撤回",
Help: "- 撤回一条消息\n",

View File

@@ -1,27 +1,61 @@
// Package baidu 百度一下
// Package baidu 百度百科
package baidu
import (
"encoding/json"
"fmt"
"net/url"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
control.Register("baidu", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "不会百度吗",
Help: "- 百度下[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)))
}
})
const (
duURL = "https://api.a20safe.com/api.php?api=21&key=%s&text=%s" // api地址
wikiURL = "https://api.a20safe.com/api.php?api=23&key=%s&text=%s"
key = "7d06a110e9e20a684e02934549db1d3d"
)
type result struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data []struct {
Content string `json:"content"`
} `json:"data"`
}
func init() { // 主函数
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "百科\n" +
"- 百度/百科/维基/wiki[关键字]",
})
en.OnRegex(`^(百度|维基|百科|wiki)\s*(.+)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
var es []byte
var err error
switch ctx.State["regex_matched"].([]string)[1] {
case "百度", "百科":
es, err = web.GetData(fmt.Sprintf(duURL, key, url.QueryEscape(ctx.State["regex_matched"].([]string)[2]))) // 将网站返回结果赋值
case "wiki", "维基":
es, err = web.GetData(fmt.Sprintf(wikiURL, key, url.QueryEscape(ctx.State["regex_matched"].([]string)[2]))) // 将网站返回结果赋值
}
if err != nil {
ctx.SendChain(message.Text("出现错误捏:", err))
return
}
var r result // r数组
err = json.Unmarshal(es, &r) // 填api返回结果struct地址
if err != nil {
ctx.SendChain(message.Text("出现错误捏:", err))
return
}
if r.Code == 0 && len(r.Data) > 0 {
ctx.SendChain(message.Text(r.Data[0].Content)) // 输出提取后的结果
} else {
ctx.SendChain(message.Text("API访问错误"))
}
})
}

View File

@@ -4,115 +4,51 @@ package baiduaudit
import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"github.com/Baidu-AIP/golang-sdk/aip/censor"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img/text"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
// 服务网址:https://console.bce.baidu.com/ai/?_=1665977657185#/ai/antiporn/overview/index
// 返回参数说明https://cloud.baidu.com/doc/ANTIPORN/s/Nk3h6xbb2
type baiduRes struct {
LogID int `json:"log_id"` // 请求唯一id
Conclusion string `json:"conclusion"` // 审核结果,可取值:合规、不合规、疑似、审核失败
ConclusionType int `json:"conclusionType"` // 审核结果类型可取值1.合规2.不合规3.疑似4.审核失败
Data []auditData `json:"data"`
ErrorCode int `json:"error_code"` // 错误提示码,失败才返回,成功不返回
ErrorMsg string `json:"error_msg"` // 错误提示信息,失败才返回,成功不返回
}
type auditData struct {
Type int `json:"type"` // 审核主类型11百度官方违禁词库、12文本反作弊、13:自定义文本黑名单、14:自定义文本白名单
SubType int `json:"subType"` // 审核子类型0:含多种类型具体看官方链接1:违禁违规、2:文本色情、3:敏感信息、4:恶意推广、5:低俗辱骂 6:恶意推广-联系方式、7:恶意推广-软文推广
Conclusion string `json:"conclusion"` // 审核结果,可取值:合规、不合规、疑似、审核失败
ConclusionType int `json:"conclusionType"` // 审核结果类型可取值1.合规2.不合规3.疑似4.审核失败
Msg string `json:"msg"` // 不合规项描述信息
Hits []hit `json:"hits"`
} // 不合规/疑似/命中白名单项详细信息。响应成功并且conclusion为疑似或不合规或命中白名单时才返回响应失败或conclusion为合规且未命中白名单时不返回。
type hit struct {
DatasetName string `json:"datasetName"` // 违规项目所属数据集名称
Words []string `json:"words"` // 送检文本命中词库的关键词备注建议参考新字段“wordHitPositions”包含信息更丰富关键词以及对应的位置及标签信息
Probability float64 `json:"probability,omitempty"` // 不合规项置信度
} // 送检文本违规原因的详细信息
type keyConfig struct {
Key1 string `json:"key1"` // 百度云服务内容审核key存储
Key2 string `json:"key2"` // 百度云服务内容审核key存储
Groups map[int64]group `json:"groups"` // 群配置存储
}
type group struct {
Enable EnableMark // 是否启用内容审核
TextAudit EnableMark // 文本检测
ImageAudit EnableMark // 图像检测
DMRemind EnableMark // 撤回提示
MoreRemind EnableMark // 详细违规提示
DMBAN EnableMark // 撤回后禁言
BANTimeAddEnable EnableMark // 禁言累加
BANTime int64 // 标准禁言时间,禁用累加,但开启禁言的的情况下采用该值
MaxBANTimeAddRange int64 // 最大禁言时间累加范围,最高禁言时间
BANTimeAddTime int64 // 禁言累加时间该值是开启禁累加功能后再次触发时根据被禁次数X该值计算出的禁言时间
WhiteListType [8]bool // 类型白名单,处于白名单类型的违规,不会被触发 0:含多种类型具体看官方链接1:违禁违规、2:文本色情、3:敏感信息、4:恶意推广、5:低俗辱骂 6:恶意推广-联系方式、7:恶意推广-软文推广
AuditHistory map[int64]auditHistory // 被封禁用户列表
}
// EnableMark 启用:●,禁用:○
type EnableMark bool
// String 打印启用状态
func (em EnableMark) String() string {
if em {
return "开启"
}
return "关闭"
}
type auditHistory struct {
Count int64 `json:"key2"` // 被禁次数
ResList []baiduRes `json:"reslist"` // 禁言原因
}
var bdcli *censor.ContentCensorClient // 百度云审核服务Client
var typetext = [8]string{
0: "默认违禁词库",
1: "违禁违规",
2: "文本色情",
3: "敏感信息",
4: "恶意推广",
5: "低俗辱骂",
6: "恶意推广-联系方式",
7: "恶意推广-软文推广",
} // 文本类型
var (
config keyConfig // 插件配置
configinit bool // 配置初始化
configpath string // 配置路径
bdcli *censor.ContentCensorClient // 百度云审核服务Client
txttyp = [...]string{
0: "默认违禁词库",
1: "违禁违规",
2: "文本色情",
3: "敏感信息",
4: "恶意推广",
5: "低俗辱骂",
6: "恶意推广-联系方式",
7: "恶意推广-软文推广",
} // 文本类型
config = newconfig() // 插件配置
)
func init() {
engine := control.Register("baiduaudit", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "百度内容审核",
Help: "##该功能来自百度内容审核需购买相关服务并创建app##\n" +
Help: "##该功能来自百度内容审核, 需购买相关服务, 并创建app##\n" +
"- 获取BDAKey\n" +
"- 配置BDAKey [API key] [Secret Key]\n" +
"- 开启/关闭内容审核\n" +
"- 开启/关闭撤回提示\n" +
"- 开启/关闭详细提示\n" +
"- 开启/关闭撤回禁言\n" +
"##禁言时间设置## 禁言时间计算方式为:禁言次数*每次禁言累加时间,当达到最大禁言时间时再次触发按最大禁言时间计算\n" +
"##禁言时间设置## 禁言时间计算方式为:禁言次数*每次禁言累加时间,当达到最大禁言时间时, 再次触发按最大禁言时间计算\n" +
"- 开启/关闭禁言累加\n" +
"- 设置撤回禁言时间[分钟默认:1]\n" +
"- 设置最大禁言时间[分钟默认:60,最大43200]\n" +
"- 设置每次累加时间[分钟默认:1]\n" +
"- 设置撤回禁言时间[分钟, 默认:1]\n" +
"- 设置最大禁言时间[分钟, 默认:60,最大43200]\n" +
"- 设置每次累加时间[分钟, 默认:1]\n" +
"##检测类型设置## 类型编号列表:[1:违禁违规、2:文本色情、3:敏感信息、4:恶意推广、5:低俗辱骂 6:恶意推广-联系方式、7:恶意推广-软文推广]\n" +
"- 查看检测类型\n" +
"- 查看检测配置\n" +
@@ -121,15 +57,19 @@ func init() {
"- 开启/关闭文本检测\n" +
"- 开启/关闭图像检测\n" +
"##测试功能##\n" +
"- 测试文本检测[文本内容]\n" +
"- 测试图像检测[图片]\n",
"- ^文本检测[文本内容]\n" +
"- ^图像检测[图片]\n",
PrivateDataFolder: "baiduaudit",
})
configpath = engine.DataFolder() + "config.json"
loadConfig()
if configinit {
configpath := engine.DataFolder() + "config.json"
err := config.load(configpath)
if err != nil {
logrus.Warnln("[baiduaudit] 加载配置错误:", err)
} else if config.Key1 != "" && config.Key2 != "" {
bdcli = censor.NewClient(config.Key1, config.Key2)
}
engine.OnFullMatch("获取BDAKey", zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("接口key创建网址:\n" +
@@ -138,28 +78,33 @@ func init() {
"https://console.bce.baidu.com/ai/?_=1665977657185#/ai/antiporn/overview/resource/getFree"))
})
engine.OnRegex("^查看检测(类型|配置)$", zero.AdminPermission, clientCheck).SetBlock(true).
engine.OnRegex("^查看检测(类型|配置)$", zero.AdminPermission, hasinit).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 获取群配置
group := getGroup(ctx.Event.GroupID)
var msgs string
group := config.groupof(ctx.Event.GroupID)
msg := ""
k1 := ctx.State["regex_matched"].([]string)[1]
if k1 == "类型" {
msgs += "本群检测类型:"
find := false
sb := strings.Builder{}
sb.WriteString("本群检测类型:")
found := false
// 遍历群检测类型名单
for i, v := range group.WhiteListType {
for i, v := range group.copyWhiteListType() {
if !v {
find = true
msgs += fmt.Sprint("\n", i, ".", typetext[i])
found = true
sb.WriteByte('\n')
sb.WriteString(strconv.Itoa(i))
sb.WriteByte('.')
sb.WriteString(txttyp[i])
}
}
if !find {
msgs += "无"
if !found {
sb.WriteString("无")
}
msg = sb.String()
} else {
// 生成配置文本
msgs = fmt.Sprintf("本群配置:\n"+
msg = fmt.Sprintf("本群配置:\n"+
"内容审核:%s\n"+
"-文本:%s\n"+
"-图像:%s\n"+
@@ -171,138 +116,145 @@ func init() {
"-每次累加时间:%v分钟\n"+
"-最大禁言时间:%v分钟", group.Enable, group.TextAudit, group.ImageAudit, group.DMRemind, group.MoreRemind, group.DMBAN, group.BANTimeAddEnable, group.BANTime, group.BANTimeAddTime, group.MaxBANTimeAddRange)
}
b, err := text.RenderToBase64(msgs, text.FontFile, 300, 20)
b, err := text.RenderToBase64(msg, text.FontFile, 300, 20)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Image("base64://" + binary.BytesToString(b)))
})
engine.OnRegex("^设置(不)?检测类型([01234567])$", zero.AdminPermission, clientCheck).SetBlock(true).
engine.OnRegex("^设置(不)?检测类型([0-7])$", zero.AdminPermission, hasinit).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
defer jsonSave(config, configpath)
k1 := ctx.State["regex_matched"].([]string)[1]
k2 := ctx.State["regex_matched"].([]string)[2]
group := getGroup(ctx.Event.GroupID)
group := config.groupof(ctx.Event.GroupID)
inputType, _ := strconv.Atoi(k2)
if k1 == "不" {
group.WhiteListType[inputType] = true // 不检测:则进入类型白名单
} else {
group.WhiteListType[inputType] = false // 检测:则退出白名单
group.setWhiteListType(inputType, k1 == "不")
err := config.saveto(configpath)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
config.Groups[ctx.Event.GroupID] = group
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("本群将%s检测%s类型内容", k1, typetext[inputType])))
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("本群将%s检测%s类型内容", k1, txttyp[inputType])))
})
engine.OnRegex("^设置(最大|每次|撤回)(累加|禁言)时间(\\d{1,5})$", zero.AdminPermission, clientCheck).SetBlock(true).
engine.OnRegex("^设置(最大|每次|撤回)(累加|禁言)时间(\\d{1,5})$", zero.AdminPermission, hasinit).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
defer jsonSave(config, configpath)
k1 := ctx.State["regex_matched"].([]string)[1]
k3 := ctx.State["regex_matched"].([]string)[3]
group := getGroup(ctx.Event.GroupID)
time, _ := strconv.ParseInt(k1, 10, 64)
switch k1 {
case "最大":
group.MaxBANTimeAddRange = time
case "每次":
group.BANTimeAddTime = time
case "撤回":
group.BANTime = time
config.groupof(ctx.Event.GroupID).set(func(g *group) {
switch k1 {
case "最大":
g.MaxBANTimeAddRange = time
case "每次":
g.BANTimeAddTime = time
case "撤回":
g.BANTime = time
}
})
err := config.saveto(configpath)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
config.Groups[ctx.Event.GroupID] = group
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("本群%s禁言累加时间已设置为%s", k3, k1)))
})
engine.OnRegex("^(开启|关闭)(内容审核|撤回提示|撤回禁言|禁言累加|详细提示|文本检测|图像检测)$", zero.AdminPermission, clientCheck).SetBlock(true).
engine.OnRegex("^(开启|关闭)(内容审核|撤回提示|撤回禁言|禁言累加|详细提示|文本检测|图像检测)$", zero.AdminPermission, hasinit).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
defer jsonSave(config, configpath)
k1 := ctx.State["regex_matched"].([]string)[1]
k2 := ctx.State["regex_matched"].([]string)[2]
isEnable := EnableMark(false)
group := getGroup(ctx.Event.GroupID)
if k1 == "开启" {
isEnable = true
isEnable := mark(k1 == "开启")
config.groupof(ctx.Event.GroupID).set(func(g *group) {
switch k2 {
case "内容审核":
g.Enable = isEnable
case "撤回提示":
g.DMRemind = isEnable
case "撤回禁言":
g.DMBAN = isEnable
case "禁言累加":
g.BANTimeAddEnable = isEnable
case "详细提示":
g.MoreRemind = isEnable
case "文本检测":
g.TextAudit = isEnable
case "图像检测":
g.ImageAudit = isEnable
}
})
err := config.saveto(configpath)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
switch k2 {
case "内容审核":
group.Enable = isEnable
case "撤回提示":
group.DMRemind = isEnable
case "撤回禁言":
group.DMBAN = isEnable
case "禁言累加":
group.BANTimeAddEnable = isEnable
case "详细提示":
group.MoreRemind = isEnable
case "文本检测":
group.TextAudit = isEnable
case "图像检测":
group.ImageAudit = isEnable
}
config.Groups[ctx.Event.GroupID] = group
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("本群%s已%s", k2, k1)))
})
engine.OnRegex(`^配置BDAKey\s(.*)\s(.*)$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
k1 := ctx.State["regex_matched"].([]string)[1]
k2 := ctx.State["regex_matched"].([]string)[2]
bdcli = censor.NewClient(k1, k2)
config.Key1 = k1
config.Key2 = k2
config.setkey(k1, k2)
if bdcli != nil {
jsonSave(config, configpath)
err := config.saveto(configpath)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("配置成功"))
}
})
engine.OnMessage().SetBlock(false).Handle(func(ctx *zero.Ctx) {
group, ok := config.Groups[ctx.Event.GroupID]
// 如果没该配置,或者审核功能未开启直接跳过
if !ok || !bool(group.Enable) {
engine.OnMessage(config.isgroupexist).SetBlock(false).Handle(func(ctx *zero.Ctx) {
group := config.groupof(ctx.Event.GroupID)
if !bool(group.Enable) {
return
}
var bdres baiduRes
var err error
for _, elem := range ctx.Event.Message {
switch elem.Type {
case "image":
if !group.ImageAudit {
return
if !group.ImageAudit || elem.Data["url"] == "" {
continue
}
res := bdcli.ImgCensorUrl(elem.Data["url"], nil)
bdres, err := jsonToBaiduRes(res)
bdres, err = parse2BaiduRes(res)
if err != nil {
ctx.SendChain(message.Text("Error:", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
return
continue
}
banCheck(ctx, bdres)
case "text":
if !group.TextAudit {
return
if !group.TextAudit || elem.Data["text"] == "" {
continue
}
res := bdcli.TextCensor(elem.Data["text"])
bdres, err := jsonToBaiduRes(res)
bdres, err = parse2BaiduRes(bdcli.TextCensor(elem.Data["text"]))
if err != nil {
ctx.SendChain(message.Text("Error:", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
return
continue
}
banCheck(ctx, bdres)
default:
continue
}
}
bdres.audit(ctx, configpath)
})
engine.OnPrefix("文本检测", clientCheck).SetBlock(false).
engine.OnPrefix("^文本检测", hasinit).SetBlock(false).
Handle(func(ctx *zero.Ctx) {
if bdcli == nil {
ctx.SendChain(message.Text("Key未配置"))
return
}
args := ctx.ExtractPlainText()
res := bdcli.TextCensor(args)
bdres, err := jsonToBaiduRes(res)
bdres, err := parse2BaiduRes(res)
if err != nil {
ctx.SendChain(message.Text("Error:", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
ctx.SendChain(message.Text("ERROR: ", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
return
}
group := getGroup(ctx.Event.GroupID)
ctx.SendChain(buildResp(bdres, group)...)
ctx.Send(config.groupof(ctx.Event.GroupID).reply(&bdres))
})
engine.OnPrefix("^图像检测", clientCheck).SetBlock(false).
engine.OnPrefix("^图像检测", hasinit).SetBlock(false).
Handle(func(ctx *zero.Ctx) {
var urls []string
for _, elem := range ctx.Event.Message {
@@ -316,105 +268,17 @@ func init() {
return
}
res := bdcli.ImgCensorUrl(urls[0], nil)
bdres, err := jsonToBaiduRes(res)
bdres, err := parse2BaiduRes(res)
if err != nil {
ctx.SendChain(message.Text("Error:", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
ctx.SendChain(message.Text("ERROR: ", bdres.ErrorMsg, "(", bdres.ErrorCode, ")"))
return
}
group := getGroup(ctx.Event.GroupID)
ctx.SendChain(buildResp(bdres, group)...)
ctx.Send(config.groupof(ctx.Event.GroupID).reply(&bdres))
})
}
// 禁言检测
func banCheck(ctx *zero.Ctx, bdres baiduRes) {
// 如果返回类型为2不合规0为合规3为疑似
if bdres.ConclusionType == 2 {
// 创建消息ID
mid := message.NewMessageIDFromInteger(ctx.Event.MessageID.(int64))
// 获取群配置
group := getGroup(ctx.Event.GroupID)
// 检测群配置里的不检测类型白名单,忽略掉不检测的违规类型
for i, b := range group.WhiteListType {
if i == bdres.Data[0].SubType && b {
return
}
}
// 生成回复文本
res := buildResp(bdres, group)
// 撤回消息
ctx.DeleteMessage(mid)
// 查看是否启用撤回后禁言
if group.DMBAN {
// 从历史违规记录中获取指定用户
user := group.getUser(ctx.Event.UserID)
// 用户违规次数自增
user.Count++
// 用户违规原因记录
user.ResList = append(user.ResList, bdres)
// 覆写该用户到群违规记录中
group.AuditHistory[ctx.Event.UserID] = user
// 覆写该群信息
config.Groups[ctx.Event.GroupID] = group
// 保存到json
jsonSave(config, configpath)
var bantime int64
// 查看是否开启禁言累加功能,并计算禁言时间
if group.BANTimeAddEnable {
bantime = user.Count * group.BANTimeAddTime * 60
} else {
bantime = group.BANTime * 60
}
// 执行禁言
ctx.SetGroupBan(ctx.Event.GroupID, ctx.Event.UserID, bantime)
}
// 查看是否开启撤回提示
if group.DMRemind {
res = append(res, message.At(ctx.Event.Sender.ID))
ctx.SendChain(res...)
}
}
}
// 获取群配置
func getGroup(groupID int64) group {
g, ok := config.Groups[groupID]
if ok {
return g
}
if config.Groups == nil {
config.Groups = make(map[int64]group)
}
g = group{
TextAudit: true,
ImageAudit: true,
BANTime: 1,
MaxBANTimeAddRange: 60,
BANTimeAddTime: 1,
WhiteListType: [8]bool{},
AuditHistory: map[int64]auditHistory{},
}
config.Groups[groupID] = g
return g
}
// 从群历史违规记录中获取用户
func (group *group) getUser(userID int64) auditHistory {
audit, ok := group.AuditHistory[userID]
if ok {
return audit
}
// 如果没有用户,则创建一个并返回
if group.AuditHistory == nil {
group.AuditHistory = make(map[int64]auditHistory)
}
audit = auditHistory{0, []baiduRes{}}
group.AuditHistory[userID] = audit
return audit
}
// 客户端是否初始化检测
func clientCheck(ctx *zero.Ctx) bool {
func hasinit(ctx *zero.Ctx) bool {
if bdcli == nil {
ctx.SendChain(message.Text("Key未配置"))
return false
@@ -422,79 +286,7 @@ func clientCheck(ctx *zero.Ctx) bool {
return true
}
// 加载JSON配置文件
func loadConfig() {
if file.IsExist(configpath) {
data, err := os.OpenFile(configpath, os.O_RDONLY, 0755)
if err != nil {
panic(err)
}
err = json.NewDecoder(data).Decode(&config)
if err != nil {
panic(err)
}
configinit = true
} else {
config = keyConfig{}
configinit = false
}
}
// 保存配置文件
func jsonSave(v keyConfig, path string) {
jsf, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
defer func(file *os.File) {
err := file.Close()
if err != nil {
fmt.Println(err)
}
}(jsf) // 结束时关闭句柄,释放资源
err := json.NewEncoder(jsf).Encode(v)
if err != nil {
fmt.Println(err)
}
}
// JSON反序列化
func jsonToBaiduRes(resjson string) (baiduRes, error) {
var bdres baiduRes
err := json.Unmarshal(binary.StringToBytes(resjson), &bdres)
return bdres, err
}
// 生成回复文本
func buildResp(bdres baiduRes, group group) []message.MessageSegment {
// 建立消息段
msgs := make([]message.MessageSegment, 0, 8)
// 生成简略审核结果回复
msgs = append(msgs, message.Text(bdres.Conclusion, "\n"))
// 查看是否开启详细审核内容提示,并确定审核内容值为疑似,或者不合规
if !group.MoreRemind {
return msgs
}
// 遍历返回的不合规数据,生成详细违规内容
for i, datum := range bdres.Data {
msgs = append(msgs, message.Text("[", i, "]:", datum.Msg, "\n"))
// 检查命中词条是否大于0
if len(datum.Hits) == 0 {
return msgs
}
// 遍历打印命中的违规词条
for _, hit := range datum.Hits {
if len(datum.Hits) == 0 {
return msgs
}
msgs = append(msgs, message.Text("("))
for i4, i3 := range hit.Words {
// 检查是否是最后一个要打印的词条,如果是则不加上逗号
if i4 != len(hit.Words)-1 {
msgs = append(msgs, message.Text(i3, ","))
} else {
msgs = append(msgs, message.Text(i3))
}
}
msgs = append(msgs, message.Text(")"))
}
}
return msgs
func parse2BaiduRes(resjson string) (bdres baiduRes, err error) {
err = json.Unmarshal(binary.StringToBytes(resjson), &bdres)
return
}

271
plugin/baiduaudit/model.go Normal file
View File

@@ -0,0 +1,271 @@
package baiduaudit
import (
"encoding/json"
"os"
"sync"
"sync/atomic"
"github.com/FloatTech/floatbox/file"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
// 服务网址:https://console.bce.baidu.com/ai/?_=1665977657185#/ai/antiporn/overview/index
// 返回参数说明https://cloud.baidu.com/doc/ANTIPORN/s/Nk3h6xbb2
type baiduRes struct {
mu sync.Mutex `json:"-"`
// LogID int `json:"log_id"` // 请求唯一id
Conclusion string `json:"conclusion"` // 审核结果, 可取值:合规、不合规、疑似、审核失败
ConclusionType int `json:"conclusionType"` // 审核结果类型, 可取值1.合规, 2.不合规, 3.疑似, 4.审核失败
Data []*auditData `json:"data"`
ErrorCode int `json:"error_code"` // 错误提示码, 失败才返回, 成功不返回
ErrorMsg string `json:"error_msg"` // 错误提示信息, 失败才返回, 成功不返回
}
// 禁言检测
func (bdres *baiduRes) audit(ctx *zero.Ctx, configpath string) {
bdres.mu.Lock()
defer bdres.mu.Unlock()
// 如果返回类型为2不合规, 0为合规, 3为疑似
if bdres.ConclusionType != 2 {
return
}
// 创建消息ID
mid := message.NewMessageIDFromInteger(ctx.Event.MessageID.(int64))
// 获取群配置
group := config.groupof(ctx.Event.GroupID)
// 检测群配置里的不检测类型白名单, 忽略掉不检测的违规类型
for i, b := range group.copyWhiteListType() {
if i == bdres.Data[0].SubType && b {
return
}
}
// 生成回复文本
res := group.reply(bdres)
// 撤回消息
ctx.DeleteMessage(mid)
// 查看是否启用撤回后禁言
if group.DMBAN {
// 从历史违规记录中获取指定用户
user := group.historyof(ctx.Event.UserID)
// 用户违规次数自增
atomic.AddInt64(&user.Count, 1)
user.mu.Lock()
// 用户违规原因记录
user.ResList = append(user.ResList, bdres)
user.mu.Unlock()
// 保存到json
err := config.saveto(configpath)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
}
var bantime int64
// 查看是否开启禁言累加功能, 并计算禁言时间
if group.BANTimeAddEnable {
bantime = atomic.LoadInt64(&user.Count) * group.BANTimeAddTime * 60
} else {
bantime = group.BANTime * 60
}
// 执行禁言
ctx.SetThisGroupBan(ctx.Event.UserID, bantime)
}
// 查看是否开启撤回提示
if group.DMRemind {
res = append(res, message.At(ctx.Event.Sender.ID))
ctx.Send(res)
}
}
type auditData struct {
// Type int `json:"type"` // 审核主类型, 11百度官方违禁词库、12文本反作弊、13:自定义文本黑名单、14:自定义文本白名单
SubType int `json:"subType"` // 审核子类型, 0:含多种类型, 具体看官方链接, 1:违禁违规、2:文本色情、3:敏感信息、4:恶意推广、5:低俗辱骂 6:恶意推广-联系方式、7:恶意推广-软文推广
// Conclusion string `json:"conclusion"` // 审核结果, 可取值:合规、不合规、疑似、审核失败
// ConclusionType int `json:"conclusionType"` // 审核结果类型, 可取值1.合规, 2.不合规, 3.疑似, 4.审核失败
Msg string `json:"msg"` // 不合规项描述信息
Hits []*hit `json:"hits"`
} // 不合规/疑似/命中白名单项详细信息.响应成功并且conclusion为疑似或不合规或命中白名单时才返回, 响应失败或conclusion为合规且未命中白名单时不返回.
type auditHistory struct {
mu sync.Mutex `json:"-"`
Count int64 `json:"key2"` // 被禁次数
ResList []*baiduRes `json:"reslist"` // 禁言原因
}
type hit struct {
// DatasetName string `json:"datasetName"` // 违规项目所属数据集名称
Words []string `json:"words"` // 送检文本命中词库的关键词备注建议参考新字段“wordHitPositions”, 包含信息更丰富:关键词以及对应的位置及标签信息)
// Probability float64 `json:"probability,omitempty"` // 不合规项置信度
} // 送检文本违规原因的详细信息
type keyConfig struct {
mu sync.Mutex `json:"-"`
Key1 string `json:"key1"` // 百度云服务内容审核key存储
Key2 string `json:"key2"` // 百度云服务内容审核key存储
Groups map[int64]*group `json:"groups"` // 群配置存储
}
func newconfig() (kc keyConfig) {
kc.Groups = make(map[int64]*group, 64)
return
}
func (kc *keyConfig) setkey(k1, k2 string) {
kc.mu.Lock()
defer kc.mu.Unlock()
kc.Key1 = k1
kc.Key2 = k2
}
// 加载JSON配置文件
func (kc *keyConfig) load(filename string) error {
if file.IsNotExist(filename) {
return nil
}
f, err := os.Open(filename)
if err != nil {
return err
}
kc.mu.Lock()
defer kc.mu.Unlock()
return json.NewDecoder(f).Decode(kc)
}
func (kc *keyConfig) isgroupexist(ctx *zero.Ctx) (ok bool) {
kc.mu.Lock()
defer kc.mu.Unlock()
_, ok = kc.Groups[ctx.Event.GroupID]
return
}
// 获取群配置
func (kc *keyConfig) groupof(groupID int64) *group {
kc.mu.Lock()
defer kc.mu.Unlock()
g, ok := kc.Groups[groupID]
if ok {
return g
}
g = &group{
TextAudit: true,
ImageAudit: true,
BANTime: 1,
MaxBANTimeAddRange: 60,
BANTimeAddTime: 1,
AuditHistory: map[int64]*auditHistory{},
}
kc.Groups[groupID] = g
return g
}
// 保存配置文件
func (kc *keyConfig) saveto(filename string) error {
kc.mu.Lock()
defer kc.mu.Unlock()
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
return json.NewEncoder(f).Encode(kc)
}
type group struct {
mu sync.Mutex
Enable mark // 是否启用内容审核
TextAudit mark // 文本检测
ImageAudit mark // 图像检测
DMRemind mark // 撤回提示
MoreRemind mark // 详细违规提示
DMBAN mark // 撤回后禁言
BANTimeAddEnable mark // 禁言累加
BANTime int64 // 标准禁言时间, 禁用累加, 但开启禁言的的情况下采用该值
MaxBANTimeAddRange int64 // 最大禁言时间累加范围, 最高禁言时间
BANTimeAddTime int64 // 禁言累加时间, 该值是开启禁累加功能后, 再次触发时, 根据被禁次数X该值计算出的禁言时间
WhiteListType [8]bool // 类型白名单, 处于白名单类型的违规, 不会被触发 0:含多种类型, 具体看官方链接, 1:违禁违规、2:文本色情、3:敏感信息、4:恶意推广、5:低俗辱骂 6:恶意推广-联系方式、7:恶意推广-软文推广
AuditHistory map[int64]*auditHistory // 被封禁用户列表
}
func (g *group) set(f func(g *group)) {
g.mu.Lock()
f(g)
g.mu.Unlock()
}
func (g *group) setWhiteListType(typ int, ok bool) {
g.mu.Lock()
defer g.mu.Unlock()
g.WhiteListType[typ] = ok
}
func (g *group) copyWhiteListType() [8]bool {
g.mu.Lock()
defer g.mu.Unlock()
return g.WhiteListType
}
// 从群历史违规记录中获取用户
func (g *group) historyof(userID int64) *auditHistory {
g.mu.Lock()
defer g.mu.Unlock()
audit, ok := g.AuditHistory[userID]
if ok {
return audit
}
// 如果没有用户, 则创建一个并返回
if g.AuditHistory == nil {
g.AuditHistory = make(map[int64]*auditHistory)
}
audit = &auditHistory{}
g.AuditHistory[userID] = audit
return audit
}
// 生成回复文本
func (g *group) reply(bdres *baiduRes) message.Message {
g.mu.Lock()
defer g.mu.Unlock()
// 建立消息段
msgs := make([]message.MessageSegment, 0, 8)
// 生成简略审核结果回复
msgs = append(msgs, message.Text(bdres.Conclusion, "\n"))
// 查看是否开启详细审核内容提示, 并确定审核内容值为疑似, 或者不合规
if !g.MoreRemind {
return msgs
}
// 遍历返回的不合规数据, 生成详细违规内容
for i, datum := range bdres.Data {
msgs = append(msgs, message.Text("[", i, "]:", datum.Msg, "\n"))
// 检查命中词条是否大于0
if len(datum.Hits) == 0 {
return msgs
}
// 遍历打印命中的违规词条
for _, hit := range datum.Hits {
if len(datum.Hits) == 0 {
return msgs
}
msgs = append(msgs, message.Text("("))
for i4, i3 := range hit.Words {
// 检查是否是最后一个要打印的词条, 如果是则不加上逗号
if i4 != len(hit.Words)-1 {
msgs = append(msgs, message.Text(i3, ","))
} else {
msgs = append(msgs, message.Text(i3))
}
}
msgs = append(msgs, message.Text(")"))
}
}
return msgs
}
type mark bool
// String 打印启用状态
func (em mark) String() string {
if em {
return "开启"
}
return "关闭"
}

View File

@@ -12,7 +12,7 @@ import (
)
func init() {
en := control.Register("base16384", &ctrl.Options[*zero.Ctx]{
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "base16384加解密",
Help: "- 加密xxx\n- 解密xxx\n- 用yyy加密xxx\n- 用yyy解密xxx",

View File

@@ -12,7 +12,7 @@ import (
)
func init() {
en := control.Register("base64gua", &ctrl.Options[*zero.Ctx]{
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "六十四卦加解密",
Help: "- 六十四卦加密xxx\n- 六十四卦解密xxx\n- 六十四卦用yyy加密xxx\n- 六十四卦用yyy解密xxx",

View File

@@ -12,7 +12,7 @@ import (
)
func init() {
en := control.Register("baseamasiro", &ctrl.Options[*zero.Ctx]{
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "天城文加解密",
Help: "- 天城文加密xxx\n- 天城文解密xxx\n- 天城文用yyy加密xxx\n- 天城文用yyy解密xxx",

View File

@@ -16,15 +16,14 @@ import (
"strconv"
"time"
"github.com/Coloured-glaze/gg"
bz "github.com/FloatTech/AnimeAPI/bilibili"
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/gg"
"github.com/FloatTech/imgfactory"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/text"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -49,7 +48,7 @@ var (
// 查成分的
func init() {
engine := control.Register("bilibili", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "b站查成分查弹幕",
Help: "- >vup info [xxx]\n" +
@@ -57,7 +56,7 @@ func init() {
"- 查成分 [xxx]\n" +
"- 查弹幕 [xxx]\n" +
"- 设置b站cookie b_ut=7;buvid3=0;i-wanna-go-back=-1;innersign=0;\n" +
"- 更新vup" +
"- 更新vup\n" +
"Tips: (412就是拦截的意思,建议私聊把cookie设全)\n",
PublicDataFolder: "Bilibili",
})
@@ -174,7 +173,7 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
back = img.Size(back, backX, backY).Im
back = imgfactory.Size(back, backX, backY).Image()
}
if len(vups) > 50 {
ctx.SendChain(message.Text(u.Name + "关注的up主太多了, 只展示前50个up"))
@@ -188,11 +187,11 @@ func init() {
canvas.DrawImage(back, 0, 0)
}
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
}
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
if err = canvas.ParseFontFace(data, fontSize); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
@@ -259,12 +258,15 @@ func init() {
f, err := os.Create(drawedFile)
if err != nil {
log.Errorln("[bilibili]", err)
data, cl := writer.ToBytes(canvas.Image())
data, err := imgfactory.ToBytes(canvas.Image())
if err != nil {
log.Errorln("[bilibili]", err)
return
}
ctx.SendChain(message.ImageBytes(data))
cl()
return
}
_, err = writer.WriteTo(canvas.Image(), f)
_, err = imgfactory.WriteTo(canvas.Image(), f)
_ = f.Close()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
@@ -318,15 +320,15 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
back = img.Size(back, backX, backY).Im
back = imgfactory.Size(back, backX, backY).Image()
}
canvas := gg.NewContext(100, 100)
fontSize := 50.0
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
}
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
if err = canvas.ParseFontFace(data, fontSize); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
@@ -335,17 +337,17 @@ func init() {
faceH := float64(510)
totalDanmuku := 0
for i := 0; i < len(danmaku.Data.Data); i++ {
totalDanmuku += len(danmaku.Data.Data[i].Danmakus) + 1
for i := 0; i < len(danmaku.Data.Data.Records); i++ {
totalDanmuku += len(danmaku.Data.Data.Records[i].Danmakus) + 1
}
cw := 10000
cw := 3000
mcw := float64(2000)
ch := 550 + len(danmaku.Data.Data)*int(faceH) + totalDanmuku*int(danmuH)
ch := 550 + len(danmaku.Data.Data.Records)*int(faceH) + totalDanmuku*int(danmuH)
canvas = gg.NewContext(cw, ch)
canvas.SetColor(color.White)
canvas.Clear()
canvas.SetColor(color.Black)
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
if err = canvas.ParseFontFace(data, fontSize); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
@@ -370,9 +372,9 @@ func init() {
canvas.DrawString("网页链接: "+fmt.Sprintf(bz.DanmakuURL, u.Mid), startWidth, 422.5)
var channelStart float64
channelStart = float64(550)
for i := 0; i < len(danmaku.Data.Data); i++ {
item := danmaku.Data.Data[i]
facePath = cachePath + strconv.Itoa(int(item.Channel.UID)) + "vupFace" + path.Ext(item.Channel.FaceURL)
for i := 0; i < len(danmaku.Data.Data.Records); i++ {
item := danmaku.Data.Data.Records[i]
facePath = cachePath + strconv.Itoa(item.Channel.UID) + "vupFace" + path.Ext(item.Channel.FaceURL)
if path.Ext(item.Channel.FaceURL) != ".webp" {
err = initFacePic(facePath, item.Channel.FaceURL)
if err != nil {
@@ -384,14 +386,14 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
back = img.Size(back, backX, backY).Im
back = imgfactory.Size(back, backX, backY).Image()
}
if back != nil {
canvas.DrawImage(back, facestart, int(channelStart))
}
canvas.SetRGB255(24, 144, 255)
canvas.DrawString("标题: "+item.Live.Title, startWidth, channelStart+fontH)
canvas.DrawString("主播: "+item.Channel.Name, startWidth, channelStart+fontH*2)
canvas.DrawString("主播: "+item.Channel.UName, startWidth, channelStart+fontH*2)
canvas.SetColor(color.Black)
canvas.DrawString("开始时间: "+time.UnixMilli(item.Live.StartDate).Format("2006-01-02 15:04:05"), startWidth, channelStart+fontH*3)
if item.Live.IsFinish {
@@ -409,8 +411,8 @@ func init() {
canvas.DrawString("直播时长: "+strconv.FormatFloat(float64(time.Now().UnixMilli()-item.Live.StartDate)/3600000.0, 'f', 1, 64)+"小时", startWidth, channelStart+fontH*5)
}
canvas.DrawString("弹幕数量: "+strconv.Itoa(int(item.Live.DanmakusCount)), startWidth, channelStart+fontH*6)
canvas.DrawString("观看次数: "+strconv.Itoa(int(item.Live.WatchCount)), startWidth, channelStart+fontH*7)
canvas.DrawString("弹幕数量: "+strconv.Itoa(item.Live.DanmakusCount), startWidth, channelStart+fontH*6)
canvas.DrawString("观看次数: "+strconv.Itoa(item.Live.WatchCount), startWidth, channelStart+fontH*7)
t := "收益:"
l, _ := canvas.MeasureString(t)
@@ -432,7 +434,7 @@ func init() {
canvas.DrawString(t, moveW, danmuNow)
moveW += l + dz
t = danItem.Name
t = danItem.UName
l, _ = canvas.MeasureString(t)
canvas.SetRGB255(24, 144, 255)
canvas.DrawString(t, moveW, danmuNow)
@@ -520,12 +522,15 @@ func init() {
f, err := os.Create(drawedFile)
if err != nil {
log.Errorln("[bilibili]", err)
data, cl := writer.ToBytes(nim)
data, err := imgfactory.ToBytes(nim)
if err != nil {
log.Errorln("[bilibili]", err)
return
}
ctx.SendChain(message.ImageBytes(data))
cl()
return
}
_, err = writer.WriteTo(nim, f)
_, err = imgfactory.WriteTo(nim, f)
_ = f.Close()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))

View File

@@ -76,11 +76,17 @@ func handleVideo(ctx *zero.Ctx) {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
summaryMsg, err := getVideoSummary(card)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
msg = append(msg, summaryMsg...)
ctx.SendChain(msg...)
}
func handleDynamic(ctx *zero.Ctx) {
msg, err := dynamicDetail(ctx.State["regex_matched"].([]string)[2])
msg, err := dynamicDetail(cfg, ctx.State["regex_matched"].([]string)[2])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return

View File

@@ -75,7 +75,7 @@ func updateVup() error {
if err != nil {
return err
}
gjson.Get(binary.BytesToString(data), "@this").ForEach(func(key, value gjson.Result) bool {
gjson.Get(binary.BytesToString(data), "@this").ForEach(func(_, value gjson.Result) bool {
mid := value.Get("mid").Int()
uname := value.Get("uname").String()
roomid := value.Get("roomid").Int()

View File

@@ -5,26 +5,26 @@ import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"strconv"
"time"
"github.com/pkg/errors"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
bz "github.com/FloatTech/AnimeAPI/bilibili"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img/text"
"github.com/pkg/errors"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
referer = "https://www.bilibili.com/"
infoURL = "https://api.bilibili.com/x/space/acc/info?mid=%v"
referer = "https://space.bilibili.com/%v"
infoURL = "https://api.bilibili.com/x/space/wbi/acc/info?mid=%v"
)
// bdb bilibili推送数据库
@@ -45,8 +45,10 @@ func init() {
"- 取消b站动态订阅[uid|name]\n" +
"- 取消b站直播订阅[uid|name]\n" +
"- b站推送列表\n" +
"Tips: 需要配合job一起使用, 全局只需要设置一个, 无视响应状态推送, 下为例子\n" +
"记录在\"@every 5m\"触发的指令)\n" +
"- [开启|关闭]艾特全体\n" +
"Tips: 需要先在 bilibili 插件中设置cookie\n" +
"需要配合 job 插件一起使用, 全局只需要设置一个, 无视响应状态推送, 下为例子\n" +
"记录在\"@every 5m\"触发的指令\n" +
"拉取b站推送",
PrivateDataFolder: "bilibilipush",
})
@@ -55,11 +57,28 @@ func init() {
dbpath := en.DataFolder()
dbfile := dbpath + "push.db"
bdb = initializePush(dbfile)
en.OnFullMatch(`开启艾特全体`, zero.UserOrGrpAdmin, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
if err := changeAtAll(gid, 1); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("已开启艾特全体Oo"))
})
en.OnFullMatch(`关闭艾特全体`, zero.UserOrGrpAdmin, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
if err := changeAtAll(gid, 0); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("已关闭艾特全体Oo"))
})
en.OnRegex(`^添加[B|b]站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
name, err := getName(buid)
if err != nil {
name, err := getName(buid, cfg)
if err != nil || name == "" {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
@@ -73,9 +92,10 @@ func init() {
}
ctx.SendChain(message.Text("已添加" + name + "的订阅"))
})
en.OnRegex(`^取消[B|b]站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
name, err := getName(buid)
name, err := getName(buid, cfg)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -92,7 +112,7 @@ func init() {
})
en.OnRegex(`^取消[B|b]站动态订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
name, err := getName(buid)
name, err := getName(buid, cfg)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -113,7 +133,7 @@ func init() {
if gid == 0 {
gid = -ctx.Event.UserID
}
name, err := getName(buid)
name, err := getName(buid, cfg)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -124,6 +144,7 @@ func init() {
}
ctx.SendChain(message.Text("已取消" + name + "的直播订阅"))
})
en.OnRegex(`^[B|b]站推送列表$`, zero.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
if gid == 0 {
@@ -170,19 +191,37 @@ func init() {
})
}
func changeAtAll(gid int64, b int) (err error) {
bpMap := map[string]any{
"group_id": gid,
"at_all": b,
}
return bdb.updateAtAll(bpMap)
}
// 取得uid的名字
func getName(buid int64) (name string, err error) {
func getName(buid int64, cookiecfg *bz.CookieConfig) (name string, err error) {
var ok bool
if name, ok = upMap[buid]; !ok {
var data []byte
data, err = web.RequestDataWith(web.NewDefaultClient(), fmt.Sprintf(infoURL, buid), "GET", referer, ua, nil)
data, err := web.RequestDataWithHeaders(web.NewDefaultClient(), bz.SignURL(fmt.Sprintf(infoURL, buid)), "GET", func(r *http.Request) error {
if cookiecfg != nil {
cookie := ""
cookie, err = cookiecfg.Load()
if err != nil {
return err
}
r.Header.Add("Cookie", cookie)
}
r.Header.Set("User-Agent", ua)
return nil
}, nil)
if err != nil {
return
return "", err
}
status := int(gjson.Get(binary.BytesToString(data), "code").Int())
if status != 0 {
err = errors.New(gjson.Get(binary.BytesToString(data), "message").String())
return
return "", err
}
name = gjson.Get(binary.BytesToString(data), "data.name").String()
bdb.insertBilibiliUp(buid, name)
@@ -231,8 +270,19 @@ func unsubscribeLive(buid, groupid int64) (err error) {
return bdb.insertOrUpdateLiveAndDynamic(bpMap)
}
func getUserDynamicCard(buid int64) (cardList []gjson.Result, err error) {
data, err := web.RequestDataWith(web.NewDefaultClient(), fmt.Sprintf(bz.SpaceHistoryURL, buid, 0), "GET", referer, ua, nil)
func getUserDynamicCard(buid int64, cookiecfg *bz.CookieConfig) (cardList []gjson.Result, err error) {
data, err := web.RequestDataWithHeaders(web.NewDefaultClient(), fmt.Sprintf(bz.SpaceHistoryURL, buid, 0), "GET", func(req *http.Request) error {
if cookiecfg != nil {
cookie := ""
cookie, err = cookiecfg.Load()
if err != nil {
return err
}
req.Header.Add("Cookie", cookie)
}
req.Header.Add("User-Agent", ua)
return nil
}, nil)
if err != nil {
return
}
@@ -258,12 +308,12 @@ func sendDynamic(ctx *zero.Ctx) error {
uids := bdb.getAllBuidByDynamic()
for _, buid := range uids {
time.Sleep(2 * time.Second)
cardList, err := getUserDynamicCard(buid)
cardList, err := getUserDynamicCard(buid, cfg)
if err != nil {
return err
}
if len(cardList) == 0 {
return errors.Errorf("%v的历史动态数为0", buid)
return nil
}
t, ok := lastTime[buid]
// 第一次先记录时间,啥也不做
@@ -348,6 +398,9 @@ func sendLive(ctx *zero.Ctx) error {
time.Sleep(time.Millisecond * 100)
switch {
case gid > 0:
if res := bdb.getAtAll(gid); res == 1 {
msg = append([]message.MessageSegment{message.AtAll()}, msg...)
}
ctx.SendGroupMessage(gid, msg)
case gid < 0:
ctx.SendPrivateMessage(-gid, msg)

View File

@@ -33,6 +33,15 @@ func (bilibiliup) TableName() string {
return "bilibili_up"
}
type bilibiliAt struct {
GroupID int64 `gorm:"column:group_id;primary_key" json:"group_id"`
AtAll int64 `gorm:"column:at_all;default:0" json:"at_all"`
}
func (bilibiliAt) TableName() string {
return "bilibili_at"
}
// initializePush 初始化bilibilipushdb数据库
func initializePush(dbpath string) *bilibilipushdb {
var err error
@@ -48,7 +57,7 @@ func initializePush(dbpath string) *bilibilipushdb {
if err != nil {
panic(err)
}
gdb.AutoMigrate(&bilibilipush{}).AutoMigrate(&bilibiliup{})
gdb.AutoMigrate(&bilibilipush{}).AutoMigrate(&bilibiliup{}).AutoMigrate(&bilibiliAt{})
return (*bilibilipushdb)(gdb)
}
@@ -130,6 +139,35 @@ func (bdb *bilibilipushdb) getAllPushByGroup(groupID int64) (bpl []bilibilipush)
return
}
func (bdb *bilibilipushdb) getAtAll(groupID int64) (res int64) {
db := (*gorm.DB)(bdb)
var bpl bilibiliAt
db.Model(&bilibilipush{}).Find(&bpl, "group_id = ?", groupID)
res = bpl.AtAll
return
}
func (bdb *bilibilipushdb) updateAtAll(bpMap map[string]any) (err error) {
db := (*gorm.DB)(bdb)
bp := bilibiliAt{}
data, err := json.Marshal(&bpMap)
if err != nil {
return
}
err = json.Unmarshal(data, &bp)
if err != nil {
return
}
if err = db.Model(&bilibiliAt{}).First(&bp, "group_id = ?", bp.GroupID).Error; err != nil {
if gorm.IsRecordNotFoundError(err) {
err = db.Model(&bilibiliAt{}).Create(&bp).Error
}
} else {
err = db.Model(&bilibiliAt{}).Where("group_id = ?", bp.GroupID).Update(bpMap).Error
}
return
}
func (bdb *bilibilipushdb) insertBilibiliUp(buid int64, name string) {
db := (*gorm.DB)(bdb)
bu := bilibiliup{

View File

@@ -2,10 +2,12 @@ package bilibili
import (
"encoding/json"
"fmt"
"time"
bz "github.com/FloatTech/AnimeAPI/bilibili"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/web"
"github.com/wdvxdr1123/ZeroBot/message"
)
@@ -253,8 +255,8 @@ func card2msg(dynamicCard *bz.DynamicCard, card *bz.Card, cType int) (msg []mess
}
// dynamicDetail 用动态id查动态信息
func dynamicDetail(dynamicIDStr string) (msg []message.MessageSegment, err error) {
dyc, err := bz.GetDynamicDetail(dynamicIDStr)
func dynamicDetail(cookiecfg *bz.CookieConfig, dynamicIDStr string) (msg []message.MessageSegment, err error) {
dyc, err := bz.GetDynamicDetail(cookiecfg, dynamicIDStr)
if err != nil {
return
}
@@ -321,6 +323,30 @@ func videoCard2msg(card bz.Card) (msg []message.MessageSegment, err error) {
msg = append(msg, message.Image(card.Pic))
msg = append(msg, message.Text("\n点赞: ", bz.HumanNum(card.Stat.Like), " 投币: ", bz.HumanNum(card.Stat.Coin), "\n",
"收藏: ", bz.HumanNum(card.Stat.Favorite), " 分享: ", bz.HumanNum(card.Stat.Share), "\n",
bz.VURL, card.BvID))
bz.VURL, card.BvID, "\n\n"))
return
}
// getVideoSummary AI视频总结
func getVideoSummary(card bz.Card) (msg []message.MessageSegment, err error) {
var (
data []byte
videoSummary bz.VideoSummary
)
data, err = web.GetData(bz.SignURL(fmt.Sprintf(bz.VideoSummaryURL, card.BvID, card.CID)))
if err != nil {
return
}
err = json.Unmarshal(data, &videoSummary)
msg = make([]message.MessageSegment, 0, 16)
msg = append(msg, message.Text("已为你生成视频总结\n\n"))
msg = append(msg, message.Text(videoSummary.Data.ModelResult.Summary, "\n\n"))
for _, v := range videoSummary.Data.ModelResult.Outline {
msg = append(msg, message.Text("● ", v.Title, "\n"))
for _, p := range v.PartOutline {
msg = append(msg, message.Text(fmt.Sprintf("%d:%d %s\n", p.Timestamp/60, p.Timestamp%60, p.Content)))
}
msg = append(msg, message.Text("\n"))
}
return
}

View File

@@ -15,35 +15,6 @@ func TestArticleInfo(t *testing.T) {
}
func TestDynamicDetail(t *testing.T) {
t.Log("cType = 1")
t.Log(dynamicDetail("642279068898689029"))
t.Log("cType = 2")
t.Log(dynamicDetail("642470680290394121"))
t.Log("cType = 2048")
t.Log(dynamicDetail("642277677329285174"))
t.Log("cType = 4")
t.Log(dynamicDetail("642154347357011968"))
t.Log("cType = 8")
t.Log(dynamicDetail("675892999274627104"))
t.Log("cType = 4308")
t.Log(dynamicDetail("668598718656675844"))
t.Log("cType = 64")
t.Log(dynamicDetail("675966082178088963"))
t.Log("cType = 256")
t.Log(dynamicDetail("599253048535707632"))
t.Log("cType = 4,投票类型")
t.Log(dynamicDetail("677231070435868704"))
}
func TestMemberCard(t *testing.T) {
card, err := bz.GetMemberCard(2)
if err != nil {
@@ -75,6 +46,14 @@ func TestVideoInfo(t *testing.T) {
t.Log(videoCard2msg(card))
}
func TestGetVideoSummary(t *testing.T) {
card, err := bz.GetVideoInfo("BV1mF411j7iU")
if err != nil {
t.Fatal(err)
}
t.Log(getVideoSummary(card))
}
func TestLiveRoomInfo(t *testing.T) {
card, err := bz.GetLiveRoomInfo("83171")
if err != nil {

View File

@@ -16,7 +16,7 @@ import (
)
func init() {
engine := control.Register("bookreview", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "哀伤雪刃推书书评",
Help: "- 书评[xxx]\n- 随机书评",
@@ -27,7 +27,7 @@ func init() {
db.DBPath = engine.DataFolder() + "bookreview.db"
// os.RemoveAll(dbpath)
_, _ = engine.GetLazyData("bookreview.db", true)
err := db.Open(time.Hour * 24)
err := db.Open(time.Hour)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false

View File

@@ -16,7 +16,7 @@ const throttle = 3 // 不可超过 9
var sm syncx.Map[int64, string]
func init() {
engine := control.Register("breakrepeat", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "打断复读",
Help: "- 打断" + strconv.Itoa(throttle) + "次以上复读\n",

View File

@@ -30,7 +30,7 @@ var (
)
func init() {
engine := control.Register("cangtoushi", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "藏头诗, 藏尾诗",
Help: "- 藏头诗[xxx]\n- 藏尾诗[xxx]",

View File

@@ -15,7 +15,7 @@ import (
var (
poke = rate.NewManager[int64](time.Minute*5, 8) // 戳一戳
engine = control.Register("chat", &ctrl.Options[*zero.Ctx]{
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "基础反应, 群空调",
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]",

183
plugin/chess/chess.go Normal file
View File

@@ -0,0 +1,183 @@
// Package chess 国际象棋
package chess
import (
"fmt"
"os"
"path"
"strconv"
"strings"
"time"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/single"
"github.com/wdvxdr1123/ZeroBot/message"
)
const helpString = `- 参与/创建一盘游戏:「下棋」(chess)
- 参与/创建一盘盲棋:「盲棋」(blind)
- 投降认输:「认输」 (resign)
- 请求、接受和棋:「和棋」 (draw)
- 走棋:!Nxf3 中英文感叹号均可,格式请参考“代数记谱法”(Algebraic notation)
- 中断对局:「中断」 (abort)(仅群主/管理员有效)
- 查看等级分排行榜:「排行榜」(ranking)
- 查看自己的等级分:「等级分」(rate)
- 清空等级分:「清空等级分 QQ号」(.clean.rate) (仅超管有效)`
var (
limit = ctxext.NewLimiterManager(time.Microsecond*2500, 1)
tempFileDir string
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "国际象棋",
Help: helpString,
PrivateDataFolder: "chess",
}).ApplySingle(single.New(
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
single.WithPostFn[int64](func(ctx *zero.Ctx) {
ctx.Send(
message.ReplyWithMessage(ctx.Event.MessageID,
message.Text("有操作正在执行, 请稍后再试..."),
),
)
}),
))
)
func init() {
// 初始化临时文件夹
tempFileDir = path.Join(engine.DataFolder(), "temp")
err := os.MkdirAll(tempFileDir, 0750)
if err != nil {
panic(err)
}
// 初始化数据库
dbFilePath := engine.DataFolder() + "chess.db"
initDatabase(dbFilePath)
// 注册指令
engine.OnFullMatchGroup([]string{"下棋", "chess"}, zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.Sender == nil {
return
}
userUin := ctx.Event.UserID
userName := ctx.Event.Sender.NickName
groupCode := ctx.Event.GroupID
replyMessage, err := game(groupCode, userUin, userName)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(replyMessage)
})
engine.OnFullMatchGroup([]string{"认输", "resign"}, zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
userUin := ctx.Event.UserID
groupCode := ctx.Event.GroupID
replyMessage, err := resign(groupCode, userUin)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(replyMessage)
})
engine.OnFullMatchGroup([]string{"和棋", "draw"}, zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
userUin := ctx.Event.UserID
groupCode := ctx.Event.GroupID
replyMessage, err := draw(groupCode, userUin)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(replyMessage)
})
engine.OnFullMatchGroup([]string{"中断", "abort"}, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
groupCode := ctx.Event.GroupID
replyMessage, err := abort(groupCode)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(replyMessage)
})
engine.OnFullMatchGroup([]string{"盲棋", "blind"}, zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.Sender == nil {
return
}
userUin := ctx.Event.UserID
userName := ctx.Event.Sender.NickName
groupCode := ctx.Event.GroupID
replyMessage, err := blindfold(groupCode, userUin, userName)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(replyMessage)
})
engine.OnRegex("^[!|]([0-8]|[R|N|B|Q|K|O|a-h|x]|[-|=|+])+$", zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
userUin := ctx.Event.UserID
groupCode := ctx.Event.GroupID
userMsgStr := ctx.State["regex_matched"].([]string)[0]
moveStr := strings.TrimPrefix(strings.TrimPrefix(userMsgStr, ""), "!")
replyMessage, err := play(groupCode, userUin, moveStr)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(replyMessage)
})
engine.OnFullMatchGroup([]string{"排行榜", "ranking"}).SetBlock(true).Limit(limit.LimitByUser).
Handle(func(ctx *zero.Ctx) {
replyMessage, err := getRanking()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(replyMessage)
})
engine.OnFullMatchGroup([]string{"等级分", "rate"}).SetBlock(true).Limit(limit.LimitByUser).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.Sender == nil {
return
}
userUin := ctx.Event.UserID
userName := ctx.Event.Sender.NickName
replyMessage, err := rate(userUin, userName)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(replyMessage)
})
engine.OnPrefixGroup([]string{"清空等级分", ".clean.rate"}, zero.SuperUserPermission).SetBlock(true).
Limit(limit.LimitByUser).
Handle(func(ctx *zero.Ctx) {
args := ctx.State["args"].(string)
playerUin, err := strconv.ParseInt(strings.TrimSpace(args), 10, 64)
if err != nil || playerUin <= 0 {
ctx.Send(fmt.Sprintf("解析失败「%s」不是正确的 QQ 号。", args))
return
}
replyMessage, err := cleanUserRate(playerUin)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(replyMessage)
})
}

637
plugin/chess/core.go Normal file
View File

@@ -0,0 +1,637 @@
package chess
import (
"bytes"
"context"
"errors"
"fmt"
"image/color"
"strconv"
"strings"
"time"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img/text"
"github.com/RomiChan/syncx"
"github.com/jinzhu/gorm"
resvg "github.com/kanrichan/resvg-go"
"github.com/notnil/chess"
cimage "github.com/notnil/chess/image"
"github.com/wdvxdr1123/ZeroBot/message"
)
const eloDefault = 500
var (
chessRoomMap syncx.Map[int64, *chessRoom]
errNotExist = errors.New("对局不存在, 发送「下棋」或「chess」可创建对局。")
)
type chessRoom struct {
chessGame *chess.Game
whitePlayer int64
whiteName string
blackPlayer int64
blackName string
drawPlayer int64
lastMoveTime int64
isBlindfold bool
whiteErr bool // 违例记录(盲棋用)
blackErr bool
}
// game 下棋
func game(groupCode, senderUin int64, senderName string) (message.Message, error) {
return createGame(false, groupCode, senderUin, senderName)
}
// blindfold 盲棋
func blindfold(groupCode, senderUin int64, senderName string) (message.Message, error) {
return createGame(true, groupCode, senderUin, senderName)
}
// abort 中断对局
func abort(groupCode int64) (message.Message, error) {
if room, ok := chessRoomMap.Load(groupCode); ok {
return abortGame(*room, groupCode, "对局已被管理员中断, 游戏结束。")
}
return nil, errNotExist
}
// draw 和棋
func draw(groupCode, senderUin int64) (msg message.Message, err error) {
msg = message.Message{message.At(senderUin)}
// 检查对局是否存在
room, ok := chessRoomMap.Load(groupCode)
if !ok {
return nil, errNotExist
}
// 检查消息发送者是否为对局中的玩家
if senderUin != room.whitePlayer && senderUin != room.blackPlayer {
return
}
// 处理和棋逻辑
room.lastMoveTime = time.Now().Unix()
if room.drawPlayer == 0 {
room.drawPlayer = senderUin
chessRoomMap.Store(groupCode, room)
msg = append(msg, message.Text("请求和棋, 发送「和棋」或「draw」接受和棋。走棋视为拒绝和棋。"))
return
}
if room.drawPlayer == senderUin {
return
}
err = room.chessGame.Draw(chess.DrawOffer)
if err != nil {
return
}
chessString := getChessString(*room)
eloString := ""
if len(room.chessGame.Moves()) > 4 {
// 若走子次数超过 4 认为是有效对局, 存入数据库
dbService := newDBService()
if err = dbService.createPGN(chessString, room.whitePlayer, room.blackPlayer, room.whiteName, room.blackName); err != nil {
return
}
whiteScore, blackScore := 0.5, 0.5
eloString, err = getELOString(*room, whiteScore, blackScore)
if err != nil {
return
}
}
msg = append(msg, message.Text("接受和棋, 游戏结束。\n", eloString, chessString))
chessRoomMap.Delete(groupCode)
return
}
// resign 认输
func resign(groupCode, senderUin int64) (msg message.Message, err error) {
msg = message.Message{message.At(senderUin)}
// 检查对局是否存在
room, ok := chessRoomMap.Load(groupCode)
if !ok {
return nil, errNotExist
}
// 检查是否是当前游戏玩家
if senderUin != room.whitePlayer && senderUin != room.blackPlayer {
return
}
// 如果对局未建立, 中断对局
if room.whitePlayer == 0 || room.blackPlayer == 0 {
chessRoomMap.Delete(groupCode)
msg = append(msg, message.Text("对局结束"))
return
}
// 计算认输方
var resignColor chess.Color
if senderUin == room.whitePlayer {
resignColor = chess.White
} else {
resignColor = chess.Black
}
if isAprilFoolsDay() {
if resignColor == chess.White {
resignColor = chess.Black
} else {
resignColor = chess.White
}
}
room.chessGame.Resign(resignColor)
chessString := getChessString(*room)
eloString := ""
if len(room.chessGame.Moves()) > 4 {
// 若走子次数超过 4 认为是有效对局, 存入数据库
dbService := newDBService()
if err = dbService.createPGN(chessString, room.whitePlayer, room.blackPlayer, room.whiteName, room.blackName); err != nil {
return
}
whiteScore, blackScore := 1.0, 1.0
if resignColor == chess.White {
whiteScore = 0.0
} else {
blackScore = 0.0
}
eloString, err = getELOString(*room, whiteScore, blackScore)
if err != nil {
return
}
}
msg = append(msg, message.Text("认输, 游戏结束。\n", eloString, chessString))
if isAprilFoolsDay() {
msg = append(msg, message.Text("对手认输, 游戏结束, 你胜利了。\n", eloString, chessString))
}
chessRoomMap.Delete(groupCode)
return
}
// play 走棋
func play(groupCode, senderUin int64, moveStr string) (msg message.Message, err error) {
msg = message.Message{message.At(senderUin)}
// 检查对局是否存在
room, ok := chessRoomMap.Load(groupCode)
if !ok {
return nil, errNotExist
}
// 不是对局中的玩家, 忽略消息
if (senderUin != room.whitePlayer) && (senderUin != room.blackPlayer) && !isAprilFoolsDay() {
return
}
// 对局未建立
if (room.whitePlayer == 0) || (room.blackPlayer == 0) {
msg = append(msg, message.Text("请等候其他玩家加入游戏。"))
return
}
// 需要对手走棋
if ((senderUin == room.whitePlayer) && (room.chessGame.Position().Turn() != chess.White)) || ((senderUin == room.blackPlayer) && (room.chessGame.Position().Turn() != chess.Black)) {
msg = append(msg, message.Text("请等待对手走棋。"))
return
}
room.lastMoveTime = time.Now().Unix()
// 走棋
if err = room.chessGame.MoveStr(moveStr); err != nil {
// 指令错误时检查
if !room.isBlindfold {
// 未开启盲棋, 提示指令错误
msg = append(msg, message.Text("移动「", moveStr, "」违规, 请检查, 格式请参考「代数记谱法」(Algebraic notation)。"))
return
}
// 开启盲棋, 判断违例情况
var currentPlayerColor chess.Color
if senderUin == room.whitePlayer {
currentPlayerColor = chess.White
} else {
currentPlayerColor = chess.Black
}
// 第一次违例, 提示
_flag := false
if (currentPlayerColor == chess.White) && !room.whiteErr {
room.whiteErr = true
chessRoomMap.Store(groupCode, room)
_flag = true
}
if (currentPlayerColor == chess.Black) && !room.blackErr {
room.blackErr = true
chessRoomMap.Store(groupCode, room)
_flag = true
}
if _flag {
msg = append(msg, message.Text("移动「", moveStr, "」违规, 再次违规会立即判负。"))
return
}
// 出现多次违例, 判负
room.chessGame.Resign(currentPlayerColor)
chessString := getChessString(*room)
msg = append(msg, message.Text("违规两次,游戏结束。\n", chessString))
chessRoomMap.Delete(groupCode)
return
}
// 走子之后, 视为拒绝和棋
if room.drawPlayer != 0 {
room.drawPlayer = 0
chessRoomMap.Store(groupCode, room)
}
// 生成棋盘图片
var boardImgEle message.MessageSegment
if !room.isBlindfold {
boardImgEle, err = getBoardElement(groupCode)
if err != nil {
return
}
}
// 检查游戏是否结束
if room.chessGame.Method() != chess.NoMethod {
whiteScore, blackScore := 0.5, 0.5
var msgBuilder strings.Builder
msgBuilder.WriteString("游戏结束, ")
switch room.chessGame.Method() {
case chess.FivefoldRepetition:
msgBuilder.WriteString("和棋, 因为五次重复走子。\n")
case chess.SeventyFiveMoveRule:
msgBuilder.WriteString("和棋, 因为七十五步规则。\n")
case chess.InsufficientMaterial:
msgBuilder.WriteString("和棋, 因为不可能将死。\n")
case chess.Stalemate:
msgBuilder.WriteString("和棋, 因为逼和(无子可动和棋)。\n")
case chess.Checkmate:
var winner string
if room.chessGame.Position().Turn() == chess.White {
whiteScore = 0.0
blackScore = 1.0
winner = "黑方"
} else {
whiteScore = 1.0
blackScore = 0.0
winner = "白方"
}
msgBuilder.WriteString(winner)
msgBuilder.WriteString("胜利, 因为将杀。\n")
case chess.NoMethod:
case chess.Resignation:
case chess.DrawOffer:
case chess.ThreefoldRepetition:
case chess.FiftyMoveRule:
default:
}
chessString := getChessString(*room)
eloString := ""
if len(room.chessGame.Moves()) > 4 {
// 若走子次数超过 4 认为是有效对局, 存入数据库
dbService := newDBService()
if err = dbService.createPGN(chessString, room.whitePlayer, room.blackPlayer, room.whiteName, room.blackName); err != nil {
return
}
// 仅有效对局才会计算等级分
eloString, err = getELOString(*room, whiteScore, blackScore)
if err != nil {
return
}
}
msgBuilder.WriteString(eloString)
msgBuilder.WriteString(chessString)
msg = append(msg, message.Text(msgBuilder.String()))
if !room.isBlindfold {
msg = append(msg, boardImgEle)
}
chessRoomMap.Delete(groupCode)
return
}
// 提示玩家继续游戏
var currentPlayer int64
if room.chessGame.Position().Turn() == chess.White {
currentPlayer = room.whitePlayer
} else {
currentPlayer = room.blackPlayer
}
msg = message.Message{message.At(currentPlayer), message.Text("对手已走子, 游戏继续。"), boardImgEle}
return
}
// rate 获取等级分
func rate(senderUin int64, senderName string) (msg message.Message, err error) {
rate := 0
dbService := newDBService()
rate, err = dbService.getELORateByUin(senderUin)
if err != nil {
if err != gorm.ErrRecordNotFound {
err = errors.New("无法获取等级分信息。")
return
}
err = errors.New("没有查找到等级分信息, 请至少进行一局对局。")
}
msg = append(msg, message.Text("玩家「", senderName, "」目前的等级分: ", rate))
return
}
// cleanUserRate 清空用户等级分
func cleanUserRate(senderUin int64) (msg message.Message, err error) {
dbService := newDBService()
err = dbService.cleanELOByUin(senderUin)
if err != nil {
if err != gorm.ErrRecordNotFound {
err = errors.New("无法清空等级分。")
return
}
err = errors.New("没有查找到等级分信息, 请检查用户 uid 是否正确。")
}
msg = append(msg, message.Text("已清空用户「", senderUin, "」的等级分。"))
return
}
// createGame 创建游戏
func createGame(isBlindfold bool, groupCode, senderUin int64, senderName string) (msg message.Message, err error) {
room, ok := chessRoomMap.Load(groupCode)
if !ok {
chessRoomMap.Store(groupCode, &chessRoom{
chessGame: chess.NewGame(),
whitePlayer: senderUin,
whiteName: senderName,
blackPlayer: 0,
blackName: "",
drawPlayer: 0,
lastMoveTime: time.Now().Unix(),
isBlindfold: isBlindfold,
whiteErr: false,
blackErr: false,
})
text := "已创建新的对局, 发送「下棋」或「chess」可加入对局。"
if isBlindfold {
text = "已创建新的盲棋对局, 发送「盲棋」或「blind」可加入对局。"
}
msg = append(msg, message.Text(text))
return
}
msg = message.Message{message.At(senderUin)}
if room.blackPlayer != 0 {
// 检测对局是否已存在超过 6 小时
if (time.Now().Unix() - room.lastMoveTime) > 21600 {
msg, err = abortGame(*room, groupCode, "对局已存在超过 6 小时, 游戏结束。")
msg = append(msg, message.Text("\n\n已有对局已被中断, 如需创建新对局请重新发送指令。"))
msg = append(msg, message.At(senderUin))
return
}
// 对局在进行
msg = append(msg, message.Text("对局已在进行中, 无法创建或加入对局, 当前对局玩家为: "))
if room.whitePlayer != 0 {
msg = append(msg, message.At(room.whitePlayer))
}
if room.blackPlayer != 0 {
msg = append(msg, message.At(room.blackPlayer))
}
msg = append(msg, message.Text(", 群主或管理员发送「中断」或「abort」可中断对局(自动判和)。"))
return
}
if senderUin == room.whitePlayer {
msg = append(msg, message.Text("请等候其他玩家加入游戏。"))
return
}
if room.isBlindfold && !isBlindfold {
msg = append(msg, message.Text("已创建盲棋对局, 请加入或等待盲棋对局结束之后创建普通对局。"))
return
}
if !room.isBlindfold && isBlindfold {
msg = append(msg, message.Text("已创建普通对局, 请加入或等待普通对局结束之后创建盲棋对局。"))
return
}
room.blackPlayer = senderUin
room.blackName = senderName
chessRoomMap.Store(groupCode, room)
var boardImgEle message.MessageSegment
if !room.isBlindfold {
boardImgEle, err = getBoardElement(groupCode)
if err != nil {
return
}
}
msg = append(msg, message.Text("黑棋已加入对局, 请白方下棋。"), message.At(room.whitePlayer))
if !isBlindfold {
msg = append(msg, boardImgEle)
}
return
}
// abortGame 中断游戏
func abortGame(room chessRoom, groupCode int64, hint string) (message.Message, error) {
var msg message.Message
err := room.chessGame.Draw(chess.DrawOffer)
if err != nil {
return nil, err
}
chessString := getChessString(room)
if len(room.chessGame.Moves()) > 4 {
dbService := newDBService()
if err := dbService.createPGN(chessString, room.whitePlayer, room.blackPlayer, room.whiteName, room.blackName); err != nil {
return nil, err
}
}
chessRoomMap.Delete(groupCode)
msg = append(msg, message.Text(hint))
if room.whitePlayer != 0 {
msg = append(msg, message.At(room.whitePlayer))
}
if room.blackPlayer != 0 {
msg = append(msg, message.At(room.blackPlayer))
}
msg = append(msg, message.Text("\n\n"+chessString))
return msg, nil
}
// getBoardElement 获取棋盘图片的消息内容
func getBoardElement(groupCode int64) (imgMsg message.MessageSegment, err error) {
fontdata, err := file.GetLazyData(text.GNUUnifontFontFile, control.Md5File, true)
if err != nil {
return
}
room, ok := chessRoomMap.Load(groupCode)
if !ok {
return imgMsg, errNotExist
}
// 获取高亮方块
highlightSquare := make([]chess.Square, 0, 2)
moves := room.chessGame.Moves()
if len(moves) != 0 {
lastMove := moves[len(moves)-1]
highlightSquare = append(highlightSquare, lastMove.S1())
highlightSquare = append(highlightSquare, lastMove.S2())
}
// 生成棋盘 svg 文件
buf := bytes.NewBuffer([]byte{})
fenStr := room.chessGame.FEN()
gameTurn := room.chessGame.Position().Turn()
pos := &chess.Position{}
if err = pos.UnmarshalText(binary.StringToBytes(fenStr)); err != nil {
return
}
yellow := color.RGBA{255, 255, 0, 1}
mark := cimage.MarkSquares(yellow, highlightSquare...)
board := pos.Board()
fromBlack := cimage.Perspective(gameTurn)
err = cimage.SVG(buf, board, fromBlack, mark)
if err != nil {
return
}
worker, err := resvg.NewDefaultWorker(context.Background())
if err != nil {
return
}
defer worker.Close()
tree, err := worker.NewTreeFromData(buf.Bytes(), &resvg.Options{
Dpi: 96,
FontFamily: "Unifont",
FontSize: 24.0,
})
if err != nil {
return
}
defer tree.Close()
fontdb, err := worker.NewFontDBDefault()
if err != nil {
return
}
defer fontdb.Close()
err = fontdb.LoadFontData(fontdata)
if err != nil {
return
}
err = tree.ConvertText(fontdb)
if err != nil {
return
}
pixmap, err := worker.NewPixmap(720, 720)
if err != nil {
return
}
defer pixmap.Close()
err = tree.Render(resvg.TransformFromScale(2, 2), pixmap)
if err != nil {
return
}
out, err := pixmap.EncodePNG()
if err != nil {
return
}
imgMsg = message.ImageBytes(out)
return imgMsg, nil
}
// getELOString 获得玩家等级分的文本内容
func getELOString(room chessRoom, whiteScore, blackScore float64) (string, error) {
if room.whitePlayer == 0 || room.blackPlayer == 0 {
return "", nil
}
var msgBuilder strings.Builder
msgBuilder.WriteString("玩家等级分: \n")
dbService := newDBService()
if err := updateELORate(room.whitePlayer, room.blackPlayer, room.whiteName, room.blackName, whiteScore, blackScore, dbService); err != nil {
return "", err
}
whiteRate, blackRate, err := getELORate(room.whitePlayer, room.blackPlayer, dbService)
if err != nil {
return "", err
}
msgBuilder.WriteString(room.whiteName)
msgBuilder.WriteString(": ")
msgBuilder.WriteString(strconv.Itoa(whiteRate))
msgBuilder.WriteString("\n")
msgBuilder.WriteString(room.blackName)
msgBuilder.WriteString(": ")
msgBuilder.WriteString(strconv.Itoa(blackRate))
msgBuilder.WriteString("\n\n")
return msgBuilder.String(), nil
}
// getRankingString 获取等级分排行榜的文本内容
func getRanking() (message.Message, error) {
dbService := newDBService()
eloList, err := dbService.getHighestRateList()
if err != nil {
return nil, err
}
var msgBuilder strings.Builder
msgBuilder.WriteString("当前等级分排行榜: \n\n")
for _, elo := range eloList {
msgBuilder.WriteString(elo.Name)
msgBuilder.WriteString(": ")
msgBuilder.WriteString(strconv.Itoa(elo.Rate))
msgBuilder.WriteString("\n")
}
return message.Message{message.Text(msgBuilder.String())}, nil
}
// updateELORate 更新 elo 等级分
// 当数据库中没有玩家的等级分信息时, 自动新建一条记录
func updateELORate(whiteUin, blackUin int64, whiteName, blackName string, whiteScore, blackScore float64, dbService *chessDBService) error {
whiteRate, err := dbService.getELORateByUin(whiteUin)
if err != nil {
if err != gorm.ErrRecordNotFound {
return err
}
// create white elo
if err := dbService.createELO(whiteUin, whiteName, eloDefault); err != nil {
return err
}
whiteRate = eloDefault
}
blackRate, err := dbService.getELORateByUin(blackUin)
if err != nil {
if err != gorm.ErrRecordNotFound {
return err
}
// create black elo
if err := dbService.createELO(blackUin, blackName, eloDefault); err != nil {
return err
}
blackRate = eloDefault
}
whiteRate, blackRate = calculateNewRate(whiteRate, blackRate, whiteScore, blackScore)
// 更新白棋玩家的 ELO 等级分
if err := dbService.updateELOByUin(whiteUin, whiteName, whiteRate); err != nil {
return err
}
// 更新黑棋玩家的 ELO 等级分
return dbService.updateELOByUin(blackUin, blackName, blackRate)
}
// getChessString 获取 PGN 字符串
func getChessString(room chessRoom) string {
game := room.chessGame
dataString := fmt.Sprintf("[Date \"%s\"]\n", time.Now().Format("2006-01-02"))
whiteString := fmt.Sprintf("[White \"%s\"]\n", room.whiteName)
blackString := fmt.Sprintf("[Black \"%s\"]\n", room.blackName)
chessString := game.String()
return dataString + whiteString + blackString + chessString
}
// getELORate 获取玩家的 ELO 等级分
func getELORate(whiteUin, blackUin int64, dbService *chessDBService) (whiteRate int, blackRate int, err error) {
whiteRate, err = dbService.getELORateByUin(whiteUin)
if err != nil {
return
}
blackRate, err = dbService.getELORateByUin(blackUin)
if err != nil {
return
}
return
}
// isAprilFoolsDay 判断当前时间是否为愚人节期间
func isAprilFoolsDay() bool {
now := time.Now()
return now.Month() == 4 && now.Day() == 1
}

100
plugin/chess/db.go Normal file
View File

@@ -0,0 +1,100 @@
package chess
import (
"os"
"github.com/jinzhu/gorm"
)
var chessDB *gorm.DB
// elo user elo info
type elo struct {
gorm.Model
Uin int64 `gorm:"unique_index"`
Name string
Rate int
}
// pgn chess pgn info
type pgn struct {
gorm.Model
Data string
WhiteUin int64
BlackUin int64
WhiteName string
BlackName string
}
// chessDBService 数据库服务
type chessDBService struct {
db *gorm.DB
}
// newDBService 创建数据库服务
func newDBService() *chessDBService {
return &chessDBService{
db: chessDB,
}
}
// initDatabase init database
func initDatabase(dbPath string) {
var err error
if _, err = os.Stat(dbPath); err != nil || os.IsNotExist(err) {
f, err := os.Create(dbPath)
if err != nil {
panic(err)
}
defer f.Close()
}
chessDB, err = gorm.Open("sqlite3", dbPath)
if err != nil {
panic(err)
}
chessDB.AutoMigrate(&elo{}, &pgn{})
}
// createELO 创建 ELO
func (s *chessDBService) createELO(uin int64, name string, rate int) error {
return s.db.Create(&elo{
Uin: uin,
Name: name,
Rate: rate,
}).Error
}
// getELORateByUin 获取 ELO 等级分
func (s *chessDBService) getELORateByUin(uin int64) (int, error) {
var elo elo
err := s.db.Select("rate").Where("uin = ?", uin).First(&elo).Error
return elo.Rate, err
}
// getHighestRateList 获取最高的等级分列表
func (s *chessDBService) getHighestRateList() ([]elo, error) {
var eloList []elo
err := s.db.Order("rate desc").Limit(10).Find(&eloList).Error
return eloList, err
}
// updateELOByUin 更新 ELO 等级分
func (s *chessDBService) updateELOByUin(uin int64, name string, rate int) error {
return s.db.Model(&elo{}).Where("uin = ?", uin).Update("name", name).Update("rate", rate).Error
}
// cleanELOByUin 清空用户 ELO 等级分
func (s *chessDBService) cleanELOByUin(uin int64) error {
return s.db.Model(&elo{}).Where("uin = ?", uin).Update("rate", 100).Error
}
// createPGN 创建 PGN
func (s *chessDBService) createPGN(data string, whiteUin int64, blackUin int64, whiteName string, blackName string) error {
return s.db.Create(&pgn{
Data: data,
WhiteUin: whiteUin,
BlackUin: blackUin,
WhiteName: whiteName,
BlackName: blackName,
}).Error
}

37
plugin/chess/elo.go Normal file
View File

@@ -0,0 +1,37 @@
package chess
import (
"math"
)
// calculateNewRate calculate new rate of the player
func calculateNewRate(whiteRate, blackRate int, whiteScore, blackScore float64) (int, int) {
k := getKFactor(whiteRate, blackRate)
exceptionWhite := calculateException(whiteRate, blackRate)
exceptionBlack := calculateException(blackRate, whiteRate)
whiteRate = calculateRate(whiteRate, whiteScore, exceptionWhite, k)
blackRate = calculateRate(blackRate, blackScore, exceptionBlack, k)
return whiteRate, blackRate
}
func calculateException(rate int, opponentRate int) float64 {
return 1.0 / (1.0 + math.Pow(10.0, float64(opponentRate-rate)/400.0))
}
func calculateRate(rate int, score float64, exception float64, k int) int {
newRate := int(math.Round(float64(rate) + float64(k)*(score-exception)))
if newRate < 1 {
newRate = 1
}
return newRate
}
func getKFactor(rateA, rateB int) int {
if rateA > 2400 && rateB > 2400 {
return 16
}
if rateA > 2100 && rateB > 2100 {
return 24
}
return 32
}

80
plugin/chess/elo_test.go Normal file
View File

@@ -0,0 +1,80 @@
package chess
import (
"math"
"testing"
)
func TestCalculateNewRate(t *testing.T) {
type args struct {
whiteRate int
blackRate int
whiteScore float64
blackScore float64
}
tests := []struct {
name string
args args
want int
want1 int
}{
{
name: "test1",
args: args{
whiteRate: 1613,
blackRate: 1573,
whiteScore: 0.5,
blackScore: 0.5,
},
want: 1611,
want1: 1575,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1 := calculateNewRate(tt.args.whiteRate, tt.args.blackRate, tt.args.whiteScore, tt.args.blackScore)
if got != tt.want {
t.Errorf("CalculateNewRate() got = %v, want %v", got, tt.want)
}
if got1 != tt.want1 {
t.Errorf("CalculateNewRate() got1 = %v, want %v", got1, tt.want1)
}
})
}
}
func Test_calculateException(t *testing.T) {
type args struct {
rate int
opponentRate int
}
tests := []struct {
name string
args args
want float64
}{
{
name: "test1",
args: args{
rate: 1613,
opponentRate: 1573,
},
want: 0.5573116,
},
{
name: "test2",
args: args{
rate: 1613,
opponentRate: 1613,
},
want: 0.5,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := calculateException(tt.args.rate, tt.args.opponentRate); math.Abs(got-tt.want) > 0.0001 {
t.Errorf("calculateException() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -13,7 +13,7 @@ import (
)
func init() {
engine := control.Register("choose", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "选择困难症帮手",
Help: "例: 选择可口可乐还是百事可乐\n" +

View File

@@ -14,7 +14,7 @@ import (
)
func init() {
en := control.Register("chouxianghua", &ctrl.Options[*zero.Ctx]{
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "翻译为抽象话",
Help: "- 抽象翻译xxx",
@@ -26,7 +26,7 @@ func init() {
db.DBPath = en.DataFolder() + "cxh.db"
// os.RemoveAll(dbpath)
_, _ = en.GetLazyData("cxh.db", true)
err := db.Open(time.Hour * 24)
err := db.Open(time.Hour)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false

View File

@@ -12,7 +12,7 @@ import (
func init() {
// 初始化engine
engine := control.Register("chrev", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "英文字符翻转",
Help: "例: 翻转 I love you",

View File

@@ -44,13 +44,16 @@ func init() {
return "", err
}
arr := gjson.Get(helper.BytesToString(data), "data.data").Array()
if len(arr) == 0 {
return "", errors.New("data is empty")
}
pic := arr[rand.Intn(len(arr))]
return pic.String(), nil
}, web.GetData, time.Minute)
if err != nil {
panic(err)
}
control.Register("coser", &ctrl.Options[*zero.Ctx]{
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "三次元coser",
Help: "- coser",

View File

@@ -16,7 +16,7 @@ import (
)
func init() {
engine := control.Register("cpstory", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "cp短打", // 这里也许有更好的名字
Help: "- 组cp[@xxx][@xxx]\n- 磕cp大老师 雪乃",
@@ -27,7 +27,7 @@ func init() {
db.DBPath = engine.DataFolder() + "cp.db"
// os.RemoveAll(dbpath)
_, _ = engine.GetLazyData("cp.db", true)
err := db.Open(time.Hour * 24)
err := db.Open(time.Hour)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
@@ -53,7 +53,7 @@ func init() {
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)
text = strings.ReplaceAll(text, cs.Shou, shou)
ctx.SendChain(message.Text(text))
})
engine.OnPrefix("磕cp", getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {

View File

@@ -21,7 +21,7 @@ const (
)
func init() {
engine := control.Register("curse", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Brief: "骂人反击",
Help: "- 骂我\n- 大力骂我",
@@ -35,7 +35,7 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
err = db.Open(time.Hour * 24)
err = db.Open(time.Hour)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false

View File

@@ -0,0 +1,37 @@
// Package dailynews 今日早报
package dailynews
import (
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const api = "http://dwz.2xb.cn/zaob"
func init() {
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "今日早报",
Help: "- 今日早报",
PrivateDataFolder: "dailynews",
})
engine.OnFullMatch(`今日早报`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
data, err := web.GetData(api)
if err != nil {
return
}
picURL := gjson.Get(binary.BytesToString(data), "imageUrl").String()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Image(picURL))
})
}

View File

@@ -7,7 +7,7 @@ import (
"strings"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/imgfactory"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -17,7 +17,7 @@ import (
)
func init() { // 插件主体
engine := control.Register("danbooru", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "二次元图片标签识别",
Help: "- 鉴赏图片[图片]",
@@ -39,7 +39,7 @@ func init() { // 插件主体
digest := md5.Sum(helper.StringToBytes(url))
f := cachefolder + hex.EncodeToString(digest[:])
if file.IsNotExist(f) {
_ = writer.SavePNG2Path(f, t)
_ = imgfactory.SavePNG2Path(f, t)
}
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image("file:///"+file.BOTPATH+"/"+f))}
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text("tags: ", strings.Join(st.tseq, ","))))

View File

@@ -3,16 +3,17 @@ package deepdanbooru
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"image"
"net/url"
"sort"
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/gg"
"github.com/FloatTech/imgfactory"
"github.com/FloatTech/zbputils/control"
imgutils "github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/text" // jpg png gif
_ "golang.org/x/image/webp" // webp
)
@@ -59,8 +60,12 @@ func tagurl(name, u string) (im image.Image, st *sorttags, err error) {
if err != nil {
return
}
if len(data) < 4 {
err = errors.New("data too short")
return
}
tags := make(map[string]float64)
err = json.Unmarshal(data, &tags)
err = json.Unmarshal(data[1:len(data)-1], &tags)
if err != nil {
return
}
@@ -76,11 +81,11 @@ func tagurl(name, u string) (im image.Image, st *sorttags, err error) {
st = newsorttags(tags)
sort.Sort(st)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
boldfd, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return
}
_, err = file.GetLazyData(text.ConsolasFontFile, control.Md5File, true)
consfd, err := file.GetLazyData(text.ConsolasFontFile, control.Md5File, true)
if err != nil {
return
}
@@ -94,19 +99,19 @@ func tagurl(name, u string) (im image.Image, st *sorttags, err error) {
return
}
img = imgutils.Limit(img, 1280, 720)
img = imgfactory.Limit(img, 1280, 720)
canvas := gg.NewContext(img.Bounds().Size().X, img.Bounds().Size().Y+int(float64(img.Bounds().Size().X)*0.2)+len(tags)*img.Bounds().Size().X/25)
canvas.SetRGB(1, 1, 1)
canvas.Clear()
canvas.DrawImage(img, 0, 0)
if err = canvas.LoadFontFace(text.BoldFontFile, float64(img.Bounds().Size().X)*0.1); err != nil {
if err = canvas.ParseFontFace(boldfd, float64(img.Bounds().Size().X)*0.1); err != nil {
return
}
canvas.SetRGB(0, 0, 0)
canvas.DrawString(name, float64(img.Bounds().Size().X)*0.02, float64(img.Bounds().Size().Y)+float64(img.Bounds().Size().X)*0.1)
i := float64(img.Bounds().Size().Y) + float64(img.Bounds().Size().X)*0.2
if err = canvas.LoadFontFace(text.ConsolasFontFile, float64(img.Bounds().Size().X)*0.04); err != nil {
if err = canvas.ParseFontFace(consfd, float64(img.Bounds().Size().X)*0.04); err != nil {
return
}
rate := float64(img.Bounds().Size().X) * 0.04

View File

@@ -12,7 +12,7 @@ import (
"github.com/FloatTech/ZeroBot-Plugin/plugin/diana/data"
)
var engine = control.Register("diana", &ctrl.Options[*zero.Ctx]{
var engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "嘉然相关", // 也许使用常用功能当Brief更好
Help: "- 小作文\n" +

View File

@@ -27,7 +27,7 @@ func LoadText(dbfile string) error {
if err != nil {
return err
}
err = db.Open(time.Hour * 24)
err = db.Open(time.Hour)
if err != nil {
return err
}

115
plugin/dish/dish.go Normal file
View File

@@ -0,0 +1,115 @@
// Package dish 程序员做饭指南zbp版数据来源Anduin2017/HowToCook
package dish
import (
"fmt"
"strings"
"time"
"github.com/sirupsen/logrus"
sql "github.com/FloatTech/sqlite"
ctrl "github.com/FloatTech/zbpctrl"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/wdvxdr1123/ZeroBot/message"
)
type dish struct {
ID uint32 `db:"id"`
Name string `db:"name"`
Materials string `db:"materials"`
Steps string `db:"steps"`
}
var (
db = &sql.Sqlite{}
initialized = false
)
func init() {
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "程序员做饭指南",
Help: "-怎么做[xxx]|烹饪[xxx]|随机菜谱|随便做点菜",
PublicDataFolder: "Dish",
})
db.DBPath = en.DataFolder() + "dishes.db"
if _, err := en.GetLazyData("dishes.db", true); err != nil {
logrus.Warnln("[dish]获取菜谱数据库文件失败")
} else if err = db.Open(time.Hour); err != nil {
logrus.Warnln("[dish]连接菜谱数据库失败")
} else if err = db.Create("dish", &dish{}); err != nil {
logrus.Warnln("[dish]同步菜谱数据表失败")
} else if count, err := db.Count("dish"); err != nil {
logrus.Warnln("[dish]统计菜谱数据失败")
} else {
logrus.Infoln("[dish]加载", count, "条菜谱")
initialized = true
}
if !initialized {
logrus.Warnln("[dish]插件未能成功初始化")
}
en.OnPrefixGroup([]string{"怎么做", "烹饪"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
if !initialized {
ctx.SendChain(message.Text("客官,本店暂未开业"))
return
}
name := ctx.NickName()
dishName := ctx.State["args"].(string)
if dishName == "" {
return
}
if strings.Contains(dishName, "'") ||
strings.Contains(dishName, "\"") ||
strings.Contains(dishName, "\\") ||
strings.Contains(dishName, ";") {
return
}
var d dish
if err := db.Find("dish", &d, fmt.Sprintf("WHERE name like %%%s%%", dishName)); err != nil {
return
}
ctx.SendChain(message.Text(fmt.Sprintf(
"已为客官%s找到%s的做法辣\n"+
"原材料:%s\n"+
"步骤:\n"+
"%s",
name, dishName, d.Materials, d.Steps),
))
})
en.OnPrefixGroup([]string{"随机菜谱", "随便做点菜"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
if !initialized {
ctx.SendChain(message.Text("客官,本店暂未开业"))
return
}
name := ctx.NickName()
var d dish
if err := db.Pick("dish", &d); err != nil {
ctx.SendChain(message.Text("小店好像出错了,暂时端不出菜来惹"))
logrus.Warnln("[dish]随机菜谱请求出错:" + err.Error())
return
}
ctx.SendChain(message.Text(fmt.Sprintf(
"已为客官%s送上%s的做法\n"+
"原材料:%s\n"+
"步骤:\n"+
"%s",
name, d.Name, d.Materials, d.Steps),
))
})
}

254
plugin/drawlots/main.go Normal file
View File

@@ -0,0 +1,254 @@
// Package drawlots 多功能抽签插件
package drawlots
import (
"bytes"
"errors"
"image"
"image/color"
"image/gif"
"math/rand"
"os"
"strconv"
"strings"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/imgfactory"
ctrl "github.com/FloatTech/zbpctrl"
control "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/text"
"github.com/fumiama/jieba/util/helper"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
type info struct {
lotsType string // 文件后缀
quantity int // 签数
}
var (
lotsList = func() map[string]info {
lotsList, err := getList()
if err != nil {
logrus.Infoln("[drawlots]加载失败:", err)
} else {
logrus.Infoln("[drawlots]加载", len(lotsList), "个抽签")
}
return lotsList
}()
en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "多功能抽签",
Help: "支持图包文件夹和gif抽签\n" +
"-------------\n" +
"- (刷新)抽签列表\n- 抽[签名]签\n- 看[gif签名]签\n- 加[签名]签[gif图片]\n- 删[gif签名]签",
PrivateDataFolder: "drawlots",
}).ApplySingle(ctxext.DefaultSingle)
datapath = file.BOTPATH + "/" + en.DataFolder()
)
func init() {
en.OnFullMatchGroup([]string{"抽签列表", "刷新抽签列表"}).SetBlock(true).Handle(func(ctx *zero.Ctx) {
var err error
lotsList, err = getList() // 刷新列表
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
messageText := &strings.Builder{}
messageText.WriteString(" 签 名 [ 类 型 ]----签数\n")
messageText.WriteString("———————————\n")
for name, fileInfo := range lotsList {
messageText.WriteString(name + "[" + fileInfo.lotsType + "]----" + strconv.Itoa(fileInfo.quantity) + "\n")
messageText.WriteString("----------\n")
}
textPic, err := text.RenderToBase64(messageText.String(), text.BoldFontFile, 400, 50)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Image("base64://" + helper.BytesToString(textPic)))
})
en.OnRegex(`^抽(.+)签$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
lotsType := ctx.State["regex_matched"].([]string)[1]
fileInfo, ok := lotsList[lotsType]
if !ok {
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("才...才没有", lotsType, "签这种东西啦")))
return
}
if fileInfo.lotsType == "folder" {
picPath, err := randFile(lotsType, 3)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("file:///"+picPath))
return
}
lotsImg, err := randGif(lotsType + "." + fileInfo.lotsType)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 生成图片
data, err := imgfactory.ToBytes(lotsImg)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.ImageBytes(data))
})
en.OnRegex(`^看(.+)签$`, zero.UserOrGrpAdmin).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
id := ctx.Event.MessageID
lotsName := ctx.State["regex_matched"].([]string)[1]
fileInfo, ok := lotsList[lotsName]
if !ok {
ctx.Send(message.ReplyWithMessage(id, message.Text("才...才没有", lotsName, "签这种东西啦")))
return
}
if fileInfo.lotsType == "folder" {
ctx.Send(message.ReplyWithMessage(id, message.Text("只能查看gif签哦~")))
return
}
ctx.Send(message.ReplyWithMessage(id, message.Image("file:///"+datapath+lotsName+"."+fileInfo.lotsType)))
})
en.OnRegex(`^加(.+)签.*`, zero.SuperUserPermission, zero.MustProvidePicture).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
id := ctx.Event.MessageID
lotsName := ctx.State["regex_matched"].([]string)[1]
if lotsName == "" {
ctx.Send(message.ReplyWithMessage(id, message.Text("请使用正确的指令形式哦~")))
return
}
picURL := ctx.State["image_url"].([]string)[0]
gifdata, err := web.GetData(picURL)
if err != nil {
return
}
im, err := gif.DecodeAll(bytes.NewReader(gifdata))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
fileName := datapath + "/" + lotsName + ".gif"
err = file.DownloadTo(picURL, fileName)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
lotsList[lotsName] = info{
lotsType: "gif",
quantity: len(im.Image),
}
ctx.Send(message.ReplyWithMessage(id, message.Text("成功!")))
})
en.OnRegex(`^删(.+)签$`, zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
id := ctx.Event.MessageID
lotsName := ctx.State["regex_matched"].([]string)[1]
fileInfo, ok := lotsList[lotsName]
if !ok {
ctx.Send(message.ReplyWithMessage(id, message.Text("才...才没有", lotsName, "签这种东西啦")))
return
}
if fileInfo.lotsType == "folder" {
ctx.Send(message.ReplyWithMessage(id, message.Text("为了防止误删图源,图包请手动移除哦~")))
return
}
err := os.Remove(datapath + lotsName + "." + fileInfo.lotsType)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
delete(lotsList, lotsName)
ctx.Send(message.ReplyWithMessage(id, message.Text("成功!")))
})
}
func getList() (list map[string]info, err error) {
list = make(map[string]info, 100)
files, err := os.ReadDir(datapath)
if err != nil {
return
}
if len(files) == 0 {
err = errors.New("什么签也没有哦~")
return
}
for _, lots := range files {
if lots.IsDir() {
files, _ := os.ReadDir(datapath + "/" + lots.Name())
list[lots.Name()] = info{
lotsType: "folder",
quantity: len(files),
}
continue
}
before, after, ok := strings.Cut(lots.Name(), ".")
if !ok || before == "" {
continue
}
file, err := os.Open(datapath + "/" + lots.Name())
if err != nil {
return nil, err
}
im, err := gif.DecodeAll(file)
_ = file.Close()
if err != nil {
return nil, err
}
list[before] = info{
lotsType: after,
quantity: len(im.Image),
}
}
return
}
func randFile(path string, indexMax int) (string, error) {
picPath := datapath + path
files, err := os.ReadDir(picPath)
if err != nil {
return "", err
}
if len(files) > 0 {
drawFile := files[rand.Intn(len(files))]
// 如果是文件夹就递归
if drawFile.IsDir() {
indexMax--
if indexMax <= 0 {
return "", errors.New("图包[" + path + "]存在太多非图片文件,请清理~")
}
return randFile(path, indexMax)
}
return picPath + "/" + drawFile.Name(), err
}
return "", errors.New("图包[" + path + "]不存在签内容!")
}
func randGif(gifName string) (image.Image, error) {
name := datapath + gifName
file, err := os.Open(name)
if err != nil {
return nil, err
}
im, err := gif.DecodeAll(file)
_ = file.Close()
if err != nil {
return nil, err
}
/*
firstImg, err := imgfactory.Load(name)
if err != nil {
return nil, err
}
v := im.Image[rand.Intn(len(im.Image))]
return imgfactory.Size(firstImg, firstImg.Bounds().Dx(), firstImg.Bounds().Dy()).InsertUpC(v, 0, 0, firstImg.Bounds().Dx()/2, firstImg.Bounds().Dy()/2).Clone().Image(),err
/*/
// 如果gif图片出现信息缺失请使用上面注释掉的代码把下面注释了(上面代码部分图存在bug)
v := im.Image[rand.Intn(len(im.Image))]
return imgfactory.NewFactoryBG(v.Rect.Dx(), v.Rect.Dy(), color.NRGBA{0, 0, 0, 255}).InsertUp(v, 0, 0, 0, 0).Clone().Image(), err
// */
}

View File

@@ -18,7 +18,7 @@ import (
)
func init() { // 插件主体
engine := control.Register("dress", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "女装",
Help: "女装\n" +

View File

@@ -33,14 +33,14 @@ var seaLocker sync.RWMutex
// We need a container to inject what we need :(
func init() {
en := control.Register("driftbottle", &ctrl.Options[*zero.Ctx]{
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "漂流瓶",
Help: "- @bot pick" + "- @bot throw xxx (xxx为投递内容)",
PrivateDataFolder: "driftbottle",
})
seaSide.DBPath = en.DataFolder() + "sea.db"
err := seaSide.Open(time.Hour * 24)
err := seaSide.Open(time.Hour)
if err != nil {
panic(err)
}

View File

@@ -17,7 +17,7 @@ import (
const bed = "https://www.gstatic.com/android/keyboard/emojikitchen/%d/u%x/u%x_u%x.png"
func init() {
control.Register("emojimix", &ctrl.Options[*zero.Ctx]{
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "合成emoji",
Help: "- [emoji][emoji]",

View File

@@ -15,7 +15,7 @@ import (
)
func init() {
engine := control.Register("event", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "好友申请和群聊邀请事件处理",
Help: "- [开启|关闭]自动同意[申请|邀请|主人]\n" +
@@ -39,8 +39,8 @@ func init() {
userid := ctx.Event.UserID
username := ctx.CardOrNickName(userid)
data := (storage)(c.GetData(-su))
groupname := ctx.GetThisGroupInfo(true).Name
groupid := ctx.Event.GroupID
groupname := ctx.GetGroupInfo(groupid, true).Name
logrus.Info("[event]收到来自[", username, "](", userid, ")的群聊邀请,群:[", groupname, "](", groupid, ")")
if data.isinviteon() || (!data.ismasteroff() && zero.SuperUserPermission(ctx)) {
ctx.SetGroupAddRequest(ctx.Event.Flag, "invite", true, "")

View File

@@ -2,7 +2,17 @@
package font
import (
"bytes"
"image"
"image/color"
"image/gif"
"math/rand"
"strings"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/gg"
"github.com/FloatTech/imgfactory"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -12,13 +22,13 @@ import (
)
func init() {
control.Register("font", &ctrl.Options[*zero.Ctx]{
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "渲染任意文字到图片",
Help: "- (用[字体])渲染文字xxx\n可选字体: [终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体]",
}).OnRegex(`^(用.+)?渲染文字([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
Help: "- (用[字体])渲染(抖动)文字xxx\n可选字体: [终末体|终末变体|紫罗兰体|樱酥体|Consolas体|粗苹方体|未来荧黑体|Gugi体|八丸体|Impact体|猫啃体|苹方体]",
}).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]
txt := ctx.State["regex_matched"].([]string)[3]
switch fnt {
case "用终末体":
fnt = text.SyumatuFontFile
@@ -30,16 +40,73 @@ func init() {
fnt = text.SakuraFontFile
case "用Consolas体":
fnt = text.ConsolasFontFile
case "用粗苹方体":
fnt = text.BoldFontFile
case "用未来荧黑体":
fnt = text.GlowSansFontFile
case "用Gugi体":
fnt = text.GugiRegularFontFile
case "用八丸体":
fnt = text.HachiMaruPopRegularFontFile
case "用Impact体":
fnt = text.ImpactFontFile
case "用猫啃体":
fnt = text.MaokenFontFile
case "用苹方体":
fallthrough
default:
fnt = text.FontFile
}
b, err := text.RenderToBase64(txt, fnt, 400, 20)
if ctx.State["regex_matched"].([]string)[2] == "" {
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)))
return
}
nilx, nily := 1.0, 8.0
s := []*image.NRGBA{}
strlist := strings.Split(txt, "\n")
data, err := file.GetLazyData(fnt, control.Md5File, true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Image("base64://" + binary.BytesToString(b)))
// 获得画布预计
testcov := gg.NewContext(1, 1)
if err = testcov.ParseFontFace(data, 30); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 取最长段
txt = ""
for _, v := range strlist {
if len([]rune(v)) > len([]rune(txt)) {
txt = v
}
}
w, h := testcov.MeasureString(txt)
for i := 0; i < 10; i++ {
cov := gg.NewContext(int(w+float64(len([]rune(txt)))*nilx)+40, int(h+nily)*len(strlist)+30)
cov.SetRGB(1, 1, 1)
cov.Clear()
if err = cov.ParseFontFace(data, 30); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
cov.SetColor(color.NRGBA{R: 0, G: 0, B: 0, A: 127})
for k, v := range strlist {
for kk, vv := range []rune(v) {
x, y := cov.MeasureString(string([]rune(v)[:kk]))
cov.DrawString(string(vv), x+float64(rand.Intn(5))+10+nilx, y+float64(rand.Intn(5))+15+float64(k)*(y+nily))
}
}
s = append(s, imgfactory.Size(cov.Image(), 0, 0).Image())
}
var buf bytes.Buffer
_ = gif.EncodeAll(&buf, imgfactory.MergeGif(5, s))
ctx.SendChain(message.ImageBytes(buf.Bytes()))
})
}

View File

@@ -11,7 +11,8 @@ import (
"os"
"strconv"
"github.com/Coloured-glaze/gg" // 注册了 jpg png gif
"github.com/FloatTech/gg" // 注册了 jpg png gif
"github.com/FloatTech/imgfactory"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -19,7 +20,6 @@ import (
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/math"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
@@ -32,8 +32,6 @@ const (
images = "data/Fortune/"
// 基础文件位置
omikujson = "data/Fortune/text.json"
// 字体文件位置
font = "data/Font/sakura.ttf"
// 生成图缓存位置
cache = images + "cache/"
)
@@ -45,11 +43,12 @@ var (
index = make(map[string]uint8)
// 签文
omikujis []map[string]string
fontdata []byte
)
func init() {
// 插件主体
en := control.Register("fortune", &ctrl.Options[*zero.Ctx]{
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "每日运势",
Help: "- 运势 | 抽签\n" +
@@ -100,10 +99,12 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
_, err = file.GetLazyData(font, control.Md5File, true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
if fontdata == nil {
fontdata, err = file.GetLazyData("data/Font/sakura.ttf", control.Md5File, true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
}
return true
},
@@ -150,7 +151,7 @@ func init() {
if err != nil {
return err
}
_, err = draw(background, title, text, f)
_, err = draw(background, fontdata, title, text, f)
_ = f.Close()
return err
}, ctxext.Send(ctx), ctxext.GetMessage(ctx))
@@ -189,19 +190,19 @@ func randimage(path string, ctx *zero.Ctx) (im image.Image, index int, err error
// @param title 签名
// @param text 签文
// @return 错误信息
func draw(back image.Image, title, txt string, f io.Writer) (int64, error) {
func draw(back image.Image, fontdata []byte, title, txt string, f io.Writer) (int64, error) {
canvas := gg.NewContext(back.Bounds().Size().Y, back.Bounds().Size().X)
canvas.DrawImage(back, 0, 0)
// 写标题
canvas.SetRGB(1, 1, 1)
if err := canvas.LoadFontFace(font, 45); err != nil {
if err := canvas.ParseFontFace(fontdata, 45); err != nil {
return -1, err
}
sw, _ := canvas.MeasureString(title)
canvas.DrawString(title, 140-sw/2, 112)
// 写正文
canvas.SetRGB(0, 0, 0)
if err := canvas.LoadFontFace(font, 23); err != nil {
if err := canvas.ParseFontFace(fontdata, 23); err != nil {
return -1, err
}
tw, th := canvas.MeasureString("测")
@@ -230,7 +231,7 @@ func draw(back image.Image, title, txt string, f io.Writer) (int64, error) {
}
}
}
return writer.WriteTo(canvas.Image(), f)
return imgfactory.WriteTo(canvas.Image(), f)
}
func offest(total, now int, distance float64) float64 {

View File

@@ -24,7 +24,7 @@ type joke struct {
var db = &sql.Sqlite{}
func init() {
en := control.Register("funny", &ctrl.Options[*zero.Ctx]{
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "讲个笑话",
Help: "- 讲个笑话[@xxx|qq号|人名] | 夸夸[@xxx|qq号|人名] ",
@@ -38,7 +38,7 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
err = db.Open(time.Hour * 24)
err = db.Open(time.Hour)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false

View File

@@ -14,8 +14,8 @@ import (
"sync/atomic"
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/process"
"github.com/FloatTech/imgfactory"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -35,7 +35,7 @@ var (
)
func init() {
engine := control.Register("genshin", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "原神模拟抽卡",
Help: "- 原神十连\n- 切换原神卡池",
@@ -100,7 +100,11 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
b, cl := writer.ToBytes(img)
b, err := imgfactory.ToBytes(img)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if mode {
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
message.Text("恭喜你抽到了: \n", str), message.ImageBytes(b)))
@@ -108,7 +112,6 @@ func init() {
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID,
message.Text("十连成功~"), message.ImageBytes(b)))
}
cl()
})
}

View File

@@ -7,7 +7,7 @@ import (
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/imgfactory"
"github.com/sirupsen/logrus"
)
@@ -97,10 +97,10 @@ func newContext(user int64) *context {
return c
}
func loadFirstFrames(paths []string, size int) (imgs []*img.Factory, err error) {
imgs = make([]*img.Factory, size)
func loadFirstFrames(paths []string, size int) (imgs []*imgfactory.Factory, err error) {
imgs = make([]*imgfactory.Factory, size)
for i := range imgs {
imgs[i], err = img.LoadFirstFrame(paths[i], 0, 0)
imgs[i], err = imgfactory.LoadFirstFrame(paths[i], 0, 0)
if err != nil {
return nil, err
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ import (
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/process"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/imgfactory"
)
func (cc *context) prepareLogos(s ...string) error {
@@ -27,17 +27,17 @@ func (cc *context) prepareLogos(s ...string) error {
}
func (cc *context) getLogo(w int, h int) (*image.NRGBA, error) {
frame, err := img.LoadFirstFrame(cc.headimgsdir[0], w, h)
frame, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], w, h)
if err != nil {
return nil, err
}
return frame.Circle(0).Im, nil
return frame.Circle(0).Image(), nil
}
func (cc *context) getLogo2(w int, h int) (*image.NRGBA, error) {
frame, err := img.LoadFirstFrame(cc.headimgsdir[1], w, h)
frame, err := imgfactory.LoadFirstFrame(cc.headimgsdir[1], w, h)
if err != nil {
return nil, err
}
return frame.Circle(0).Im, nil
return frame.Circle(0).Image(), nil
}

View File

@@ -8,11 +8,10 @@ import (
"strconv"
"sync"
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/gg"
"github.com/FloatTech/imgfactory"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/text"
)
@@ -36,11 +35,11 @@ func pa(cc *context, args ...string) (string, error) {
if err != nil {
return "", err
}
imgf, err := img.LoadFirstFrame(f, 0, 0)
imgf, err := imgfactory.LoadFirstFrame(f, 0, 0)
if err != nil {
return "", err
}
return "file:///" + name, writer.SavePNG2Path(name, imgf.InsertUp(tou, 100, 100, 0, 400).Im)
return "file:///" + name, imgfactory.SavePNG2Path(name, imgf.InsertUp(tou, 100, 100, 0, 400).Image())
}
// si 撕
@@ -51,8 +50,8 @@ func si(cc *context, args ...string) (string, error) {
if err != nil {
return "", err
}
im1 := img.Rotate(tou, 20, 380, 380)
im2 := img.Rotate(tou, -12, 380, 380)
im1 := imgfactory.Rotate(tou, 20, 380, 380)
im2 := imgfactory.Rotate(tou, -12, 380, 380)
if file.IsNotExist(datapath + "materials/si") {
err = os.MkdirAll(datapath+"materials/si", 0755)
if err != nil {
@@ -63,11 +62,11 @@ func si(cc *context, args ...string) (string, error) {
if err != nil {
return "", err
}
imgf, err := img.LoadFirstFrame(f, 0, 0)
imgf, err := imgfactory.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)
return "file:///" + name, imgfactory.SavePNG2Path(name, imgf.InsertBottom(im1.Image(), im1.W(), im1.H(), -3, 370).InsertBottom(im2.Image(), im2.W(), im2.H(), 653, 310).Image())
}
// flipV 上翻,下翻
@@ -75,12 +74,12 @@ func flipV(cc *context, args ...string) (string, error) {
_ = args
name := cc.usrdir + "FlipV.png"
// 加载图片
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
if err != nil {
return "", err
}
imgnrgba := im.FlipV().Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.FlipV().Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// flipH 左翻,右翻
@@ -88,12 +87,12 @@ func flipH(cc *context, args ...string) (string, error) {
_ = args
name := cc.usrdir + "FlipH.png"
// 加载图片
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
if err != nil {
return "", err
}
imgnrgba := im.FlipH().Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.FlipH().Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// invert 反色
@@ -101,12 +100,12 @@ func invert(cc *context, args ...string) (string, error) {
_ = args
name := cc.usrdir + "Invert.png"
// 加载图片
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
if err != nil {
return "", err
}
imgnrgba := im.Invert().Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.Invert().Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// blur 反色
@@ -114,12 +113,12 @@ func blur(cc *context, args ...string) (string, error) {
_ = args
name := cc.usrdir + "Blur.png"
// 加载图片
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
if err != nil {
return "", err
}
imgnrgba := im.Blur(10).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.Blur(10).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// grayscale 灰度
@@ -127,12 +126,12 @@ func grayscale(cc *context, args ...string) (string, error) {
_ = args
name := cc.usrdir + "Grayscale.png"
// 加载图片
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
if err != nil {
return "", err
}
imgnrgba := im.Grayscale().Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.Grayscale().Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// invertAndGrayscale 负片
@@ -140,12 +139,12 @@ func invertAndGrayscale(cc *context, args ...string) (string, error) {
_ = args
name := cc.usrdir + "InvertAndGrayscale.png"
// 加载图片
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
if err != nil {
return "", err
}
imgnrgba := im.Invert().Grayscale().Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.Invert().Grayscale().Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// convolve3x3 浮雕
@@ -153,32 +152,32 @@ func convolve3x3(cc *context, args ...string) (string, error) {
_ = args
name := cc.usrdir + "Convolve3x3.png"
// 加载图片
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
if err != nil {
return "", err
}
imgnrgba := im.Convolve3x3().Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.Relief().Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// rotate 旋转
func rotate(cc *context, args ...string) (string, error) {
name := cc.usrdir + "Rotate.png"
// 加载图片
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
if err != nil {
return "", err
}
r, _ := strconv.ParseFloat(args[0], 64)
imgnrgba := img.Rotate(im.Im, r, 0, 0).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgfactory.Rotate(im.Image(), r, 0, 0).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// deformation 变形
func deformation(cc *context, args ...string) (string, error) {
name := cc.usrdir + "Deformation.png"
// 加载图片
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 0, 0)
if err != nil {
return "", err
}
@@ -190,8 +189,8 @@ func deformation(cc *context, args ...string) (string, error) {
if err != nil {
return "", err
}
imgnrgba := img.Size(im.Im, w, h).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgfactory.Size(im.Image(), w, h).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// alike 你像个xxx一样
@@ -214,12 +213,12 @@ func alike(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Anyasuki.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 82, 69)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 82, 69)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertUp(im.Im, 0, 0, 136, 21).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertUp(im.Image(), 0, 0, 136, 21).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// marriage
@@ -242,12 +241,12 @@ func marriage(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Marriage.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 1080, 1080)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 1080, 1080)
if err != nil {
return "", err
}
imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 0, 0).InsertUp(imgs[1].Im, 0, 0, 800, 0).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.InsertUp(imgs[0].Image(), 0, 0, 0, 0).InsertUp(imgs[1].Image(), 0, 0, 800, 0).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// anyasuki 阿尼亚喜欢
@@ -275,14 +274,14 @@ func anyasuki(cc *context, args ...string) (string, error) {
return "", err
}
canvas := gg.NewContext(475, 540)
canvas.DrawImage(img.Size(face, 347, 267).Im, 82, 53)
canvas.DrawImage(imgfactory.Size(face, 347, 267).Image(), 82, 53)
canvas.DrawImage(back, 0, 0)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 30); err != nil {
if err = canvas.ParseFontFace(data, 30); err != nil {
return "", err
}
if args[0] == "" {
@@ -322,13 +321,13 @@ func alwaysLike(cc *context, args ...string) (string, error) {
}
canvas := gg.NewContext(830, 599)
canvas.DrawImage(back, 0, 0)
canvas.DrawImage(img.Size(face, 380, 380).Im, 44, 74)
canvas.DrawImage(imgfactory.Size(face, 380, 380).Image(), 44, 74)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 56); err != nil {
if err = canvas.ParseFontFace(data, 56); err != nil {
return "", err
}
if args[0] == "" {
@@ -363,12 +362,12 @@ func decentKiss(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "DecentKiss.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 589, 577)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 589, 577)
if err != nil {
return "", err
}
imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 0, 0).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.InsertUp(imgs[0].Image(), 0, 0, 0, 0).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// chinaFlag 国旗
@@ -391,12 +390,12 @@ func chinaFlag(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "ChinaFlag.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 410, 410)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 410, 410)
if err != nil {
return "", err
}
imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 0, 0).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.InsertUp(imgs[0].Image(), 0, 0, 0, 0).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// dontTouch 不要靠近
@@ -419,12 +418,12 @@ func dontTouch(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "DontTouch.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 410, 410)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 410, 410)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertUp(im.Im, 148, 148, 46, 238).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertUp(im.Image(), 148, 148, 46, 238).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// universal 万能表情 空白表情
@@ -436,13 +435,13 @@ func universal(cc *context, args ...string) (string, error) {
return "", err
}
canvas := gg.NewContext(500, 550)
canvas.DrawImage(img.Size(face, 500, 500).Im, 0, 0)
canvas.DrawImage(imgfactory.Size(face, 500, 500).Image(), 0, 0)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 40); err != nil {
if err = canvas.ParseFontFace(data, 40); err != nil {
return "", err
}
if args[0] == "" {
@@ -485,15 +484,15 @@ func interview(cc *context, args ...string) (string, error) {
return "", err
}
canvas := gg.NewContext(600, 300)
canvas.DrawImage(img.Size(face, 124, 124).Im, 100, 50)
canvas.DrawImage(imgfactory.Size(face, 124, 124).Image(), 100, 50)
canvas.DrawImage(huaji, 376, 50)
canvas.DrawImage(microphone, 300, 50)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 40); err != nil {
if err = canvas.ParseFontFace(data, 40); err != nil {
return "", err
}
if args[0] == "" {
@@ -527,12 +526,12 @@ func need(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Need.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 114, 114)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 114, 114)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 327, 232).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 327, 232).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// paint 这像画吗
@@ -555,12 +554,12 @@ func paint(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Paint.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 117, 135)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 117, 135)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 4, 0, 0).Im, 0, 0, 95, 107).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 4, 0, 0).Image(), 0, 0, 95, 107).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// painter 小画家
@@ -583,12 +582,12 @@ func painter(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Painter.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 240, 345)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 240, 345)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 125, 91).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 125, 91).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// perfect 完美
@@ -611,12 +610,12 @@ func perfect(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Perfect.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 310, 460)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 310, 460)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertUp(im.Im, 0, 0, 313, 64).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertUp(im.Image(), 0, 0, 313, 64).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// playGame 玩游戏
@@ -644,14 +643,14 @@ func playGame(cc *context, args ...string) (string, error) {
return "", err
}
canvas := gg.NewContext(526, 503)
canvas.DrawImage(img.Rotate(face, 10, 225, 160).Im, 161, 117)
canvas.DrawImage(imgfactory.Rotate(face, 10, 225, 160).Image(), 161, 117)
canvas.DrawImage(back, 0, 0)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 40); err != nil {
if err = canvas.ParseFontFace(data, 40); err != nil {
return "", err
}
if args[0] == "" {
@@ -685,12 +684,12 @@ func police(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Police.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 245, 245)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 245, 245)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 224, 46).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 224, 46).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// police1 警察
@@ -713,12 +712,12 @@ func police1(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Police1.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 60, 75)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 60, 75)
if err != nil {
return "", err
}
imgnrgba := imgs[1].InsertBottom(img.Rotate(im.Im, 16, 0, 0).Im, 0, 0, 37, 291).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[1].InsertBottom(imgfactory.Rotate(im.Image(), 16, 0, 0).Image(), 0, 0, 37, 291).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// prpr 舔 舔屏 prpr
@@ -741,12 +740,12 @@ func prpr(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Prpr.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 330, 330)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 330, 330)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 8, 0, 0).Im, 0, 0, 46, 264).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 8, 0, 0).Image(), 0, 0, 46, 264).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// safeSense 安全感
@@ -775,13 +774,13 @@ func safeSense(cc *context, args ...string) (string, error) {
}
canvas := gg.NewContext(430, 478)
canvas.DrawImage(back, 0, 0)
canvas.DrawImage(img.Size(face, 215, 343).Im, 215, 135)
canvas.DrawImage(imgfactory.Size(face, 215, 343).Image(), 215, 135)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 30); err != nil {
if err = canvas.ParseFontFace(data, 30); err != nil {
return "", err
}
if args[0] == "" {
@@ -817,12 +816,12 @@ func support(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Support.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 815, 815)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 815, 815)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 23, 0, 0).Im, 0, 0, -172, -17).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 23, 0, 0).Image(), 0, 0, -172, -17).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// thinkwhat 想什么
@@ -845,12 +844,12 @@ func thinkwhat(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Thinkwhat.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 530, 0).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 530, 0).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// wallpaper 墙纸
@@ -873,12 +872,12 @@ func wallpaper(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Wallpaper.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 775, 496)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 775, 496)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 260, 580).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 260, 580).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// whyatme 为什么at我
@@ -901,12 +900,12 @@ func whyatme(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Whyatme.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 265, 265)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 265, 265)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(im.Im, 0, 0, 42, 13).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(im.Image(), 0, 0, 42, 13).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// makeFriend 交个朋友
@@ -934,16 +933,16 @@ func makeFriend(cc *context, args ...string) (string, error) {
return "", err
}
canvas := gg.NewContext(1000, 1000)
canvas.DrawImage(img.Size(face, 1000, 1000).Im, 0, 0)
canvas.DrawImage(img.Rotate(face, 9, 250, 250).Im, 743, 845)
canvas.DrawImage(img.Rotate(face, 9, 55, 55).Im, 836, 722)
canvas.DrawImage(imgfactory.Size(face, 1000, 1000).Image(), 0, 0)
canvas.DrawImage(imgfactory.Rotate(face, 9, 250, 250).Image(), 743, 845)
canvas.DrawImage(imgfactory.Rotate(face, 9, 55, 55).Image(), 836, 722)
canvas.DrawImage(back, 0, 0)
canvas.SetColor(color.White)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 20); err != nil {
if err = canvas.ParseFontFace(data, 20); err != nil {
return "", err
}
if args[0] == "" {
@@ -978,12 +977,12 @@ func backToWork(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "BackToWork.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 220, 310)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 220, 310)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 25, 0, 0).Im, 0, 0, 56, 32).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 25, 0, 0).Image(), 0, 0, 56, 32).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// coupon 兑换券
@@ -1016,13 +1015,13 @@ func coupon(cc *context, args ...string) (string, error) {
canvas := gg.NewContext(500, 355)
canvas.DrawImage(back, 0, 0)
canvas.Rotate(gg.Radians(-22))
canvas.DrawImage(img.Size(face, 60, 60).Im, 100, 163)
canvas.DrawImage(imgfactory.Size(face, 60, 60).Image(), 100, 163)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 30); err != nil {
if err = canvas.ParseFontFace(data, 30); err != nil {
return "", err
}
if args[0] == "" {
@@ -1057,12 +1056,12 @@ func distracted(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "Distracted.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 500, 500)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 500, 500)
if err != nil {
return "", err
}
imgnrgba := im.InsertUp(imgs[0].Im, 0, 0, 140, 320).InsertUp(imgs[1].Im, 0, 0, 0, 0).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := im.InsertUp(imgs[0].Image(), 0, 0, 140, 320).InsertUp(imgs[1].Image(), 0, 0, 0, 0).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// throw 扔
@@ -1089,8 +1088,8 @@ func throw(cc *context, args ...string) (string, error) {
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertUpC(img.Rotate(face, float64(rand.Intn(360)), 143, 143).Im, 0, 0, 86, 249).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertUpC(imgfactory.Rotate(face, float64(rand.Intn(360)), 143, 143).Image(), 0, 0, 86, 249).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// 远离
@@ -1113,12 +1112,12 @@ func yuanli(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "yuanli.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(im.Im, 420, 420, 45, 90).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(im.Image(), 420, 420, 45, 90).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// 不是你老婆
@@ -1141,12 +1140,12 @@ func nowife(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "nowife.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 534, 493)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(im.Im, 400, 400, 112, 81).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(im.Image(), 400, 400, 112, 81).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// youer 你老婆
@@ -1175,13 +1174,13 @@ func youer(cc *context, args ...string) (string, error) {
}
canvas := gg.NewContext(690, 690)
canvas.DrawImage(back, 0, 0)
canvas.DrawImage(img.Size(tou, 350, 350).Im, 55, 165)
canvas.DrawImage(imgfactory.Size(tou, 350, 350).Image(), 55, 165)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 56); err != nil {
if err = canvas.ParseFontFace(data, 56); err != nil {
return "", err
}
if args[0] == "" {
@@ -1222,13 +1221,13 @@ func xiaotianshi(cc *context, args ...string) (string, error) {
}
canvas := gg.NewContext(522, 665)
canvas.DrawImage(back, 0, 0)
canvas.DrawImage(img.Size(face, 480, 480).Im, 20, 80)
canvas.DrawImage(imgfactory.Size(face, 480, 480).Image(), 20, 80)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 35); err != nil {
if err = canvas.ParseFontFace(data, 35); err != nil {
return "", err
}
if args[0] == "" {
@@ -1263,12 +1262,12 @@ func neko(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "neko.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 712, 949)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 712, 949)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 0, 0, 0).Im, 450, 450, 0, 170).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 0, 0, 0).Image(), 450, 450, 0, 170).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// 给我变
@@ -1292,12 +1291,12 @@ func bian(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "bian.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 640, 550)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 640, 550)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(img.Rotate(im.Im, 0, 0, 0).Im, 380, 380, 225, -20).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(imgfactory.Rotate(im.Image(), 0, 0, 0).Image(), 380, 380, 225, -20).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// van 玩一下
@@ -1326,13 +1325,13 @@ func van(cc *context, args ...string) (string, error) {
}
canvas := gg.NewContext(522, 665)
canvas.DrawImage(back, 0, 0)
canvas.DrawImage(img.Size(face, 480, 480).Im, 20, 80)
canvas.DrawImage(imgfactory.Size(face, 480, 480).Image(), 20, 80)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 35); err != nil {
if err = canvas.ParseFontFace(data, 35); err != nil {
return "", err
}
if args[0] == "" {
@@ -1367,12 +1366,12 @@ func eihei(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "eihei.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 690, 690)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 690, 690)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(im.Im, 450, 450, 121, 162).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(im.Image(), 450, 450, 121, 162).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// fanfa 犯法
@@ -1399,9 +1398,9 @@ func fanfa(cc *context, args ...string) (string, error) {
if err != nil {
return "", err
}
m1 := img.Rotate(face, 45, 110, 110)
imgnrgba := imgs[0].InsertUp(m1.Im, 0, 0, 125, 360).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
m1 := imgfactory.Rotate(face, 45, 110, 110)
imgnrgba := imgs[0].InsertUp(m1.Image(), 0, 0, 125, 360).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// huai 怀
@@ -1424,12 +1423,12 @@ func huai(cc *context, args ...string) (string, error) {
return "", err
}
name := cc.usrdir + "huai.png"
im, err := img.LoadFirstFrame(cc.headimgsdir[0], 640, 640)
im, err := imgfactory.LoadFirstFrame(cc.headimgsdir[0], 640, 640)
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(im.Im, 640, 640, 0, 0).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(im.Image(), 640, 640, 0, 0).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// haowan 好玩
@@ -1456,8 +1455,8 @@ func haowan(cc *context, args ...string) (string, error) {
if err != nil {
return "", err
}
imgnrgba := imgs[0].InsertBottom(face, 90, 90, 321, 172).Im
return "file:///" + name, writer.SavePNG2Path(name, imgnrgba)
imgnrgba := imgs[0].InsertBottom(face, 90, 90, 321, 172).Image()
return "file:///" + name, imgfactory.SavePNG2Path(name, imgnrgba)
}
// mengbi 蒙蔽
@@ -1486,14 +1485,14 @@ func mengbi(cc *context, args ...string) (string, error) {
}
canvas := gg.NewContext(1080, 1080)
canvas.DrawImage(back, 0, 0)
canvas.DrawImage(img.Size(face, 100, 100).Im, 392, 460)
canvas.DrawImage(img.Size(face, 100, 100).Im, 606, 443)
canvas.DrawImage(imgfactory.Size(face, 100, 100).Image(), 392, 460)
canvas.DrawImage(imgfactory.Size(face, 100, 100).Image(), 606, 443)
canvas.SetColor(color.Black)
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
data, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
return "", err
}
if err = canvas.LoadFontFace(text.BoldFontFile, 80); err != nil {
if err = canvas.ParseFontFace(data, 80); err != nil {
return "", err
}
if args[0] == "" {

View File

@@ -126,24 +126,25 @@ func init() { // 插件主体
for k := range cmdMap {
cmd = append(cmd, k)
}
en := control.Register("gif", &ctrl.Options[*zero.Ctx]{
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "制图",
Help: "下为制图命令: " +
"- 搓|-冲|-摸|-拍|-丢|-吃|-敲|-啃|-蹭|-爬|-撕|-灰度|-上翻|-下翻\n" +
"- 左翻|-右翻|-反色|-浮雕|- 打码|- 负片|- 转|- 变形|- \n" +
"- 结婚申请|结婚登记|- 阿尼亚喜欢XXX|- 像只|- 我永远喜欢XXX\n" +
"- 像样的亲亲|- 国旗|- 不要靠近|- 万能表情|-空白表情|- 采访\n" +
"- 需要|-你可能需要|- 这像画吗|- 小画家|- 完美|- 玩游戏|- 出警\n" +
"- 警察|- 舔|舔屏|prpr|- 安全感|- 精神支柱|- 想什么|- 墙纸\n" +
"- 为什么at我|- 交个朋友|- 打工人|-继续干活|- 兑换券|- 炖\n" +
"- 垃圾桶|- 垃圾|- |- 啾啾|- 2|- 听音乐|- 永远爱你|- 2拍\n" +
"- |- |- 打拳|- 滚|- 吸|- 嗦|- |- |- 紧贴|紧紧贴着|- 转\n" +
"- 抬棺|- 远离|- 我老婆|- 小天使XXX|- 你的XXX|- 不要看\n" +
"- 玩一下XXX|- 给我变|- 揍|- |- 膜拜|- 诶嘿|- 2蹭|- 你犯法了\n" +
"- 砰|- 注意力涣散|- 蒙蔽|- 踩|- 好玩|- 2转|- 踢球|- 2舔|\n" +
"- 可莉吃|- 胡桃啃|- 怀|- 一直(支持动图)\n" +
"例: 制图命令XXX[@用户|QQ号|图片]" +
Help: "下为制图命令:\n" +
"- 搓|- 冲|- 摸|-拍|- 丢|- 吃|- 敲|- 啃|- 蹭|- 爬|- 撕\n" +
"- 吸|- 嗦|- 扔|- 锤|- 紧贴|紧紧贴着|- 转|- 抬棺|- 远离\n" +
"- 揍|- 吞|- 膜拜|- 诶嘿|- 2蹭|- 你犯法了|- |- 注意力涣散\n" +
"- 2敲|- 听音乐|- 永远爱你|- 2拍|- 顶|- 捣|- 打拳|- 滚\n" +
"- 灰度|- 上翻|- 下翻|- 左翻|- 右翻|- 反色|- 浮雕|- 打码\n" +
"- 负片|- 旋转|- 变形|- 亲|- 结婚申请|结婚登记|- 阿尼亚喜欢XXX\n" +
"- 像只|- 我永远喜欢XXX|- 像样的亲亲|- 国旗|- 不要靠近\n" +
"- 蒙蔽|- |- 好玩|- 2转|- 踢球|- 2|- 可莉吃|- 胡桃啃|- 怀\n" +
"- 小画家|- 完美|- 玩游戏|- 出警|- 警察|- 舔|舔屏|prpr\n" +
"- 安全感|- 精神支柱|- 想什么|- 墙纸|- 为什么at我|- 交个朋友\n" +
"- 打工人|- 继续干活|- 兑换券|- |- 垃圾桶|- 垃圾|- |- 啾啾\n" +
"- 我老婆|- 小天使XXX|- 你的XXX|- 不要看|- 玩一下XXX|- 给我变\n" +
"- 万能表情|- 空白表情|- 采访|- 需要|- 你可能需要|- 这像画吗\n" +
"- 一直(支持动图)\n" +
"例: 制图命令XXX[@用户|QQ号|图片]\n" +
"Tips: XXX可以为限制长度的任何文字\n" +
"对Bot使用为 @Bot制图命令[XXX]@Bot",
PrivateDataFolder: "gif",

View File

@@ -18,7 +18,7 @@ import (
)
func init() { // 插件主体
control.Register("github", &ctrl.Options[*zero.Ctx]{
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "GitHub仓库搜索",
Help: "- >github [xxx]\n" +

View File

@@ -11,16 +11,28 @@ import (
"sync"
"time"
log "github.com/sirupsen/logrus"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/zbputils/ctxext"
"github.com/pkg/errors"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/liuzl/gocc"
)
var cuttime = [...]string{"00:00:05", "00:00:30", "00:01:00"} // 音乐切割时间点,可自行调节时间(时:分:秒)
var t2s *gocc.OpenCC
func init() {
// 初始化简繁体转换变量
var err1 error
t2s, err1 = gocc.New("t2s")
if err1 != nil {
log.Infof("[guessmusic]:%s", err1)
}
engine.OnRegex(`^(个人|团队)猜歌(-(.*))?$`, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
mode := ctx.State["regex_matched"].([]string)[3]
@@ -283,6 +295,11 @@ func cutMusic(musicName, pathOfMusic, outputPath string) (err error) {
// 数据匹配(结果信息,答题次数,提示次数,是否结束游戏)
func gameMatch(c *zero.Ctx, beginner int64, musicInfo []string, answerTimes, tickTimes int) (message.MessageSegment, int, int, bool) {
answer := strings.Replace(c.Event.Message.String(), "-", "", 1)
// 大小写,简繁体转换
answer = ConvertText(answer)
for i, element := range musicInfo {
musicInfo[i] = ConvertText(element)
}
switch {
case answer == "取消":
if c.Event.UserID == beginner {
@@ -314,3 +331,15 @@ func gameMatch(c *zero.Ctx, beginner int64, musicInfo []string, answerTimes, tic
}
}
}
// ConvertText 将传入字符串中的英文转为小写,繁体中文转为简体中文
func ConvertText(input string) string {
// 将字符串中的英文转为小写
toLower := strings.ToLower(input)
toLower, err := t2s.Convert(toLower)
if err != nil {
message.Text("简繁转换失败")
return toLower
}
return toLower
}

View File

@@ -9,6 +9,7 @@ import (
"time"
wyy "github.com/FloatTech/AnimeAPI/neteasemusic"
"github.com/FloatTech/imgfactory"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -18,10 +19,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
// 图片输出
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/process"
"github.com/FloatTech/gg"
"github.com/FloatTech/zbputils/img/text"
)
@@ -31,7 +31,7 @@ var (
// 用户数据
cfg config
// 插件主体
engine = control.Register("guessmusic", &ctrl.Options[*zero.Ctx]{
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "猜歌插件",
Help: "------bot主人指令------\n" +
@@ -406,18 +406,18 @@ func init() {
canvas.SetRGB(1, 1, 1) // 白色
canvas.Clear()
/***********下载字体,可以注销掉***********/
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
boldfd, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
}
_, err = file.GetLazyData(text.FontFile, control.Md5File, true)
fd, err := file.GetLazyData(text.FontFile, control.Md5File, true)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
}
/***********设置字体颜色为黑色***********/
canvas.SetRGB(0, 0, 0)
/***********设置字体大小,并获取字体高度用来定位***********/
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
if err = canvas.ParseFontFace(boldfd, fontSize); err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return
}
@@ -426,7 +426,7 @@ func init() {
canvas.DrawString("序号\t\t歌单名\t\t歌曲数量\t\t网易云歌单ID", 20, 50-h) // 放置在中间位置
canvas.DrawString("——————————————————————", 20, 70-h)
/***********设置字体大小,并获取字体高度用来定位***********/
if err = canvas.LoadFontFace(text.FontFile, fontSize); err != nil {
if err = canvas.ParseFontFace(fd, fontSize); err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return
}
@@ -446,11 +446,14 @@ func init() {
canvas.DrawString("当前设置的默认歌单为: "+dlist.Name, 80, float64(85+20*j)-h)
}
}
data, cl := writer.ToBytes(canvas.Image())
data, err := imgfactory.ToBytes(canvas.Image())
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return
}
if id := ctx.SendChain(message.ImageBytes(data)); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
cl()
})
engine.OnPrefix("设置猜歌默认歌单", zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
@@ -524,7 +527,7 @@ func getlist(pathOfMusic string) (list []listinfo, err error) {
// 遍历群文件
func getFileURLbyFileName(ctx *zero.Ctx, fileName string) (fileSearchName, fileURL string) {
filesOfGroup := ctx.GetThisGroupRootFiles(ctx.Event.GroupID)
filesOfGroup := ctx.GetThisGroupRootFiles()
files := filesOfGroup.Get("files").Array()
folders := filesOfGroup.Get("folders").Array()
// 遍历当前目录的文件名

View File

@@ -241,9 +241,9 @@ type listInfoOfAPI struct {
PublishTime int64 `json:"publishTime"`
Tns []string `json:"tns,omitempty"`
} `json:"tracks"`
VideoIds interface{} `json:"videoIds"`
VideoIDs interface{} `json:"videoIds"`
Videos interface{} `json:"videos"`
TrackIds []struct {
TrackIDs []struct {
ID int `json:"id"`
V int `json:"v"`
T int `json:"t"`

View File

@@ -66,7 +66,7 @@ func init() { // 插件主体
panic(err)
}
engine := control.Register("heisi", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "黑丝",
Help: "- 来点黑丝\n- 来点白丝\n- 来点jk\n- 来点巨乳\n- 来点足控\n- 来点网红",

174
plugin/hitokoto/hitokoto.go Normal file
View File

@@ -0,0 +1,174 @@
// Package hitokoto 一言
package hitokoto
import (
"math/rand"
"strconv"
"strings"
"time"
"github.com/FloatTech/floatbox/binary"
fcext "github.com/FloatTech/floatbox/ctxext"
ctrl "github.com/FloatTech/zbpctrl"
"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() { // 插件主体
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "一言",
Help: "- 一言[xxx]\n" +
"- 系列一言",
PublicDataFolder: "Hitokoto",
})
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
dbfile := engine.DataFolder() + "hitokoto.db"
_, err := engine.GetLazyData("hitokoto.db", false)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
hdb, err = initialize(dbfile)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
return true
})
engine.OnPrefix(`一言`, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女祈祷中..."))
args := ctx.State["args"].(string)
blist, err := hdb.getByKey(strings.TrimSpace(args))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if len(blist) == 0 {
ctx.SendChain(message.Text("ERROR: hitokoto empty"))
return
}
m := make(message.Message, 0, 10)
text := strings.Builder{}
if len(blist) <= 10 {
for _, b := range blist {
text.WriteString(b.Hitokoto)
text.WriteString("\n——")
text.WriteString(b.From)
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
text.Reset()
}
} else {
indexes := map[int]struct{}{}
for i := 0; i < 10; i++ {
ind := rand.Intn(len(blist))
if _, ok := indexes[ind]; ok {
i--
continue
}
indexes[ind] = struct{}{}
}
for k := range indexes {
b := blist[k]
text.WriteString(b.Hitokoto)
text.WriteString("\n——")
text.WriteString(b.From)
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
text.Reset()
}
}
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
})
engine.OnFullMatch(`系列一言`, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
recv, cancel := next.Repeat()
defer cancel()
results, err := hdb.getAllCategory()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
tex := strings.Builder{}
tex.WriteString("请输入系列一言序号\n")
for i, v := range results {
tex.WriteString(strconv.Itoa(i))
tex.WriteString(". ")
tex.WriteString(v.Category)
tex.WriteString("\n")
}
base64Str, err := text.RenderToBase64(tex.String(), text.FontFile, 400, 20)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Image("base64://" + binary.BytesToString(base64Str)))
for {
select {
case <-time.After(time.Second * 120):
ctx.SendChain(message.Text("系列一言指令过期"))
return
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 >= len(results) {
ctx.SendChain(message.Text("序号非法!"))
continue
}
ctx.SendChain(message.Text("请欣赏系列一言: ", results[num].Category))
hlist, err := hdb.getByCategory(results[num].Category)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if len(hlist) == 0 {
ctx.SendChain(message.Text("ERROR: hitokoto empty"))
return
}
m := make(message.Message, 0, 10)
text := strings.Builder{}
if len(hlist) <= 10 {
for _, b := range hlist {
text.WriteString(b.Hitokoto)
text.WriteString("\n——")
text.WriteString(b.From)
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
text.Reset()
}
} else {
indexes := map[int]struct{}{}
for i := 0; i < 10; i++ {
ind := rand.Intn(len(hlist))
if _, ok := indexes[ind]; ok {
i--
continue
}
indexes[ind] = struct{}{}
}
for k := range indexes {
b := hlist[k]
text.WriteString(b.Hitokoto)
text.WriteString("\n——")
text.WriteString(b.From)
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
text.Reset()
}
}
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
return
}
}
})
}

73
plugin/hitokoto/model.go Normal file
View File

@@ -0,0 +1,73 @@
package hitokoto
import (
"os"
"github.com/jinzhu/gorm"
)
// hdb 表情包数据库全局变量
var hdb *hitokotodb
// hitokotodb 表情包数据库
type hitokotodb gorm.DB
// initialize 初始化
func initialize(dbpath string) (db *hitokotodb, err error) {
if _, err = os.Stat(dbpath); err != nil || os.IsNotExist(err) {
// 生成文件
f, err := os.Create(dbpath)
if err != nil {
return nil, err
}
_ = f.Close()
}
gdb, err := gorm.Open("sqlite3", dbpath)
if err != nil {
return
}
gdb.AutoMigrate(&hitokoto{})
return (*hitokotodb)(gdb), nil
}
type hitokoto struct {
ID int `json:"id" gorm:"column:id;primary_key"`
Hitokoto string `json:"hitokoto" gorm:"column:hitokoto"`
Type string `json:"type" gorm:"column:type"`
From string `json:"from" gorm:"column:from"`
FromWho string `json:"from_who" gorm:"column:from_who"`
Creator string `json:"creator" gorm:"column:creator"`
CreatorUID int `json:"creator_uid" gorm:"column:creator_uid"`
Reviewer int `json:"reviewer" gorm:"column:reviewer"`
UUID string `json:"uuid" gorm:"column:uuid"`
CreatedAt string `json:"created_at" gorm:"column:created_at"`
Category string `json:"catogory" gorm:"column:category"`
}
// TableName 表名
func (hitokoto) TableName() string {
return "hitokoto"
}
func (hdb *hitokotodb) getByKey(key string) (b []hitokoto, err error) {
db := (*gorm.DB)(hdb)
err = db.Where("hitokoto like ?", "%"+key+"%").Find(&b).Error
return
}
type result struct {
Category string
Count int
}
func (hdb *hitokotodb) getAllCategory() (results []result, err error) {
db := (*gorm.DB)(hdb)
err = db.Table("hitokoto").Select("category, count(1) as count").Group("category").Scan(&results).Error
return
}
func (hdb *hitokotodb) getByCategory(category string) (h []hitokoto, err error) {
db := (*gorm.DB)(hdb)
err = db.Where("category = ?", category).Find(&h).Error
return
}

View File

@@ -41,7 +41,7 @@ const (
)
func init() {
engine := control.Register("hs", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "炉石搜卡",
Help: "- 搜卡[xxxx]\n" +

View File

@@ -19,7 +19,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
)
const bed = "https://gitcode.net/u011570312/OguraHyakuninIsshu/-/raw/master/"
const bed = "https://gitea.seku.su/fumiama/OguraHyakuninIsshu/raw/branch/master/"
type line struct {
番号, 歌人, 上の句, 下の句, 上の句ひらがな, 下の句ひらがな string
@@ -51,7 +51,7 @@ func (l *line) String() string {
var lines [100]*line
func init() {
engine := control.Register("hyaku", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "百人一首",
Help: "- 百人一首(随机发一首)\n" +

View File

@@ -11,7 +11,7 @@ import (
"regexp"
"strings"
"github.com/lucas-clemente/quic-go/http3"
"github.com/quic-go/quic-go/http3"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -62,7 +62,7 @@ type resultjson struct {
var hrefre = regexp.MustCompile(`<a href=".*">`)
func init() {
control.Register("imgfinder", &ctrl.Options[*zero.Ctx]{
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "关键字搜图",
Help: "- 来张 [xxx]",

View File

@@ -9,7 +9,7 @@ import (
)
func init() {
en := control.Register("inject", &ctrl.Options[*zero.Ctx]{
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "注入指令",
Help: "- run[CQ码]",

View File

@@ -23,7 +23,7 @@ const (
)
func init() {
engine := control.Register("jandan", &ctrl.Options[*zero.Ctx]{
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "煎蛋网无聊图",
Help: "- 来份[屌|弔|吊]图\n- 更新[屌|弔|吊]图\n",
@@ -33,7 +33,7 @@ func init() {
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = engine.DataFolder() + "pics.db"
_, _ = engine.GetLazyData("pics.db", false)
err := db.Open(time.Hour * 24)
err := db.Open(time.Hour)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false

View File

@@ -13,8 +13,8 @@ import (
)
const (
jiami1 = "http://ovooa.com/API/sho_u/?msg=%v" // 加密api地址
jiami2 = "http://ovooa.com/API/sho_u/?format=1&msg=%v" // 解密api地址
jiami1 = "http://ovooa.caonm.net/API/sho_u/?msg=%v" // 加密api地址
jiami2 = "http://ovooa.caonm.net/API/sho_u/?format=1&msg=%v" // 解密api地址
)
@@ -25,7 +25,7 @@ type nmd struct { // struct解析格式大概是
}
func init() { // 主函数
en := control.Register("jiami", &ctrl.Options[*zero.Ctx]{
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "兽语加解密",
Help: "兽语加解密\n" +

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