Compare commits

...

280 Commits

Author SHA1 Message Date
github-actions[bot]
109b7661b7 chore(lint): 改进代码样式 (#1151)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-03-30 23:50:57 +09:00
github-actions[bot]
8da52a2772 chore: bump deps (#1150)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2025-03-30 23:50:36 +09:00
yexiaoyu
7515983b55 插件:AnimeTrace 动画/Galgame识别 (#1141)
* 插件:AnimeTrace 动画/Galgame识别

* update: 插件:AnimeTrace 动画/Galgame识别
2025-03-30 23:48:49 +09:00
github-actions[bot]
7519ea548d chore: bump deps (#1149)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-03-30 23:47:42 +09:00
源文雨
6a55d9b279 🔖 v1.9.6 2025-03-30 23:47:12 +09:00
源文雨
d5227f1159 optimize(aichat): use config struct 2025-03-30 23:28:55 +09:00
源文雨
62e9fe69ed feat(aichat): add more funcs 2025-03-30 22:12:48 +09:00
源文雨
2df52161e5 feat(aichat): add OLLaMA & GenAI support 2025-03-30 21:36:31 +09:00
源文雨
a29f4cb1f9 feat(aichat): add sanitize 2025-03-29 17:07:14 +09:00
github-actions[bot]
6a747d2f9d chore(lint): 改进代码样式 (#1144)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-03-25 12:41:42 +09:00
源文雨
164c71a3a3 chore: remove dependabot 2025-03-25 12:35:46 +09:00
github-actions[bot]
3f1b0ad67b chore: bump deps (#1142)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-03-25 12:33:20 +09:00
github-actions[bot]
6c6699a5d6 chore(lint): 改进代码样式 (#1143)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-03-25 12:33:02 +09:00
RefactoringHero
e292b69ee5 feat: add plugin Minecraft 服务器状态查询 (#1135) 2025-03-25 12:30:40 +09:00
Nobody6825
e6e6dd4565 chore: pin nixpkgs to preserve dropped go_1_20 (#1139) 2025-03-08 19:33:09 +09:00
github-actions[bot]
28bfc3e71d chore: bump deps (#1133)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-22 22:05:07 +09:00
源文雨
d3975cf461 chore: update deps 2025-02-22 21:52:43 +09:00
源文雨
7430c41c1e fix(ci): deprecations 2025-02-22 15:42:03 +09:00
源文雨
dd1064db26 🔖 v1.9.5 2025-02-22 15:34:55 +09:00
github-actions[bot]
1167866b16 chore: bump deps (#1131)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-22 15:23:56 +09:00
github-actions[bot]
caed8eab0c chore(lint): 改进代码样式 (#1128)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-22 15:23:44 +09:00
dependabot[bot]
8d85334049 chore(deps): bump golang.org/x/image from 0.21.0 to 0.24.0 (#1109)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.21.0 to 0.24.0.
- [Commits](https://github.com/golang/image/compare/v0.21.0...v0.24.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-22 06:21:13 +00:00
dependabot[bot]
da89fb29ca chore(deps): bump golang.org/x/sys from 0.29.0 to 0.30.0 (#1111)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.29.0 to 0.30.0.
- [Commits](https://github.com/golang/sys/compare/v0.29.0...v0.30.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-22 15:18:17 +09:00
源文雨
e005621fbb doc: edit README 2025-02-22 15:11:59 +09:00
源文雨
511f04c6f9 feat(aichat): new template 2025-02-22 15:10:40 +09:00
github-actions[bot]
fb29619b9e chore: bump deps (#1125)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-22 13:13:36 +09:00
源文雨
325adf8911 feat(aichat): more compatibility 2025-02-22 01:50:19 +09:00
github-actions[bot]
b494390373 chore(lint): 改进代码样式 (#1124)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-20 02:01:45 +09:00
方柳煜
085e95cd48 optimize(mcfish): 更改插件规则 (#1122)
每日商店会固定刷新1初始木竿。该木竿价格也会随木竿的价格浮动。
2025-02-20 01:46:35 +09:00
github-actions[bot]
659f4e07c2 chore: bump deps (#1123)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-18 23:30:13 +09:00
源文雨
3abf6317de feat(aichat): add user name 2025-02-18 23:26:36 +09:00
源文雨
e8305c5886 optimize(thesaurus): cnfd. calc. 2025-02-17 23:45:16 +09:00
源文雨
71d029f7a0 fix(aichat): block chat at at 2025-02-17 23:39:41 +09:00
源文雨
dc899f55fe fix(aichat): load noreplyat 2025-02-17 23:38:21 +09:00
源文雨
8c11f48502 fix(thesaurus): cnfd. calc. 2025-02-17 23:31:11 +09:00
源文雨
e12ec697e6 chore: make lint happy 2025-02-17 23:20:16 +09:00
github-actions[bot]
b01d3a4f14 chore: bump deps (#1121)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-17 23:17:56 +09:00
源文雨
552c1a9a35 optimize(chat): avoid conflicts 2025-02-17 23:12:23 +09:00
源文雨
aacf720b88 🔖 v1.9.4 2025-02-15 18:39:55 +09:00
github-actions[bot]
832addc55e chore: bump deps (#1119)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-15 18:38:54 +09:00
源文雨
f7c5584016 fix(aichat): context 2025-02-15 18:36:25 +09:00
github-actions[bot]
df5ceb930f chore: bump deps (#1118)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-15 18:21:32 +09:00
源文雨
d4071f54f9 optimize(aichat): context 2025-02-15 18:19:38 +09:00
源文雨
ae859a1ece 🔖 v1.9.3 2025-02-15 12:51:58 +09:00
源文雨
112328a7f2 fix(aichat): some errors 2025-02-15 12:38:43 +09:00
源文雨
512561d8fd feat: add set sep 2025-02-15 02:06:25 +09:00
源文雨
f73bf5a270 feat(aichat): add temp setting 2025-02-15 02:02:53 +09:00
源文雨
3c7034e46c 🔖 v1.9.2 2025-02-14 23:10:52 +09:00
源文雨
2a848366f3 optimize(aichat): more replys 2025-02-14 22:48:47 +09:00
github-actions[bot]
549a8ce30b chore: bump deps (#1117)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-14 22:34:11 +09:00
源文雨
d00c4aec47 fix(sqlite): slice query 2025-02-14 22:31:25 +09:00
github-actions[bot]
4ef5b854bc chore: bump deps (#1114)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-14 21:43:30 +09:00
github-actions[bot]
41f02f34c2 chore(lint): 改进代码样式 (#1116)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-14 21:43:06 +09:00
源文雨
b9cf52404d fix(lint): make lint happy 2025-02-14 21:30:48 +09:00
源文雨
350e2e3907 chore: make lint happy 2025-02-14 17:30:05 +09:00
源文雨
a8b2587cee update deps 2025-02-14 17:27:10 +09:00
源文雨
735c3cdde1 feat: add plugin aichat 2025-02-14 17:23:00 +09:00
源文雨
24955dc4a7 fix(thesaurus): ingore empty seg 2025-02-01 16:13:43 +08:00
github-actions[bot]
b4eb61e36a chore(lint): 改进代码样式 (#1108)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-20 21:17:23 +09:00
宇~
70ebb03434 feat:使用niu包,添加新玩法牛牛拍卖行 (#1098) 2025-01-20 15:45:02 +09:00
源文雨
2c5596cd96 🔖 v1.9.1 (fix #1076) 2025-01-16 17:32:05 +09:00
github-actions[bot]
d6c13337d1 chore(lint): 改进代码样式 (#1106)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-16 16:29:35 +09:00
github-actions[bot]
eb2daf1827 chore: bump deps (#1105)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-16 16:29:04 +09:00
dependabot[bot]
c4d4bd9f40 chore(deps): bump github.com/antchfx/htmlquery from 1.3.3 to 1.3.4 (#1104)
Bumps [github.com/antchfx/htmlquery](https://github.com/antchfx/htmlquery) from 1.3.3 to 1.3.4.
- [Release notes](https://github.com/antchfx/htmlquery/releases)
- [Commits](https://github.com/antchfx/htmlquery/compare/v1.3.3...v1.3.4)

---
updated-dependencies:
- dependency-name: github.com/antchfx/htmlquery
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-16 16:26:56 +09:00
github-actions[bot]
fd1c8bf9b9 chore(lint): 改进代码样式 (#1101)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-14 17:40:12 +09:00
github-actions[bot]
7fef4b08c0 chore: bump deps (#1102)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-14 17:39:57 +09:00
dependabot[bot]
b04c244cab chore(deps): bump golang.org/x/sys from 0.26.0 to 0.29.0 (#1095)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.26.0 to 0.29.0.
- [Commits](https://github.com/golang/sys/compare/v0.26.0...v0.29.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 17:37:17 +09:00
vatebur
cfb98ca241 更新bilibili API和 钓鱼插件 (#1100) 2025-01-14 17:34:39 +09:00
莫思潋
885544077b fix(tarot): 使用Getlazydata获取数据 (#1097)
* fix(tarot): use GetLazyData

* fix(tarot): add cache folder & improve error handle

* refactor(tarot): no need for clean cache
2025-01-07 22:02:49 +09:00
starim00
fcb01c2c18 fix: 处理b站解析获取卡片失败的问题 (#1089)
Co-authored-by: hutiance <hutiance@newings.net.cn>
2025-01-06 14:10:20 +09:00
catboss
41d28b71bf fix: 塔罗牌Gitcode数据源仓库切换到经由镜像的GitHub源 (#1090) 2025-01-06 14:08:34 +09:00
vatebur
8fa91a13c3 fix:[mcfish]User purchases fish pole initialization (#1088)
修复用户第一次购买鱼竿的时候初始化错误
2025-01-03 22:30:50 +09:00
github-actions[bot]
696a0ac99c chore(lint): 改进代码样式 (#1083)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-18 00:32:12 +09:00
宇~
37818acee1 feat(manager): onregex -> pattern (#1082)
* feat(manager): onregex -> pattern

* delete nil
2024-12-15 00:51:45 +09:00
vatebur
38eae9375d chore:替换图片API地址 (#1077)
感谢大自然的馈赠
2024-12-05 14:48:49 +09:00
vatebur
c35fc543d3 [mcfish]数值调整,[score]调整逻辑 (#1074)
* chore:[mcfish]数值调整,[score]调整逻辑

* chore:[score]修正错误的文本
2024-12-04 01:25:52 +09:00
vatebur
2c8726dda3 [mcfish]修改钓鱼规则 (#1072)
* fix: 修复[mcfish]交易检测逻辑的bug

- 修复出售限制不更新的bug
- 修改商品价格浮动区间

* update:[mcfish]美西螈物品翻5倍

- 使用美西螈物品翻倍率3->5
- 移除不使用的函数checkIsFish

* fix: 修复[mcfish]交易检测对垃圾的处理
2024-11-30 16:06:32 +09:00
vatebur
83037f621c update: 重写[mcfish]交易检测逻辑 (#1070) 2024-11-29 00:41:19 +09:00
vatebur
6a2c7e8740 feat: 签到失败时使用本地图片#1067 (#1068)
* update:签到失败时使用本地图片#1067

1. 修改score插件提示词,对用户更友好。
2. 图片下载失败时,会使用本地图片。

> 如果用户网络一直不通,可能会一直用某张图片作为背景

* update:修改score抽取本地图片逻辑
2024-11-27 13:57:54 +09:00
Jiang-Red
9e8ae43b15 feat(qqwife): some onregex -> pattern (#1058) 2024-11-09 14:25:42 +09:00
源文雨
4ba0b36be1 chore: remove aireply due to 没人用 2024-11-07 14:48:43 +09:00
github-actions[bot]
9470977092 chore: bump deps (#1057)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-07 14:45:48 +09:00
源文雨
08d33fd74f chore: remove moegoe due to 没人用 2024-11-07 00:37:38 +09:00
源文雨
66a8ec91bc chore: update deps 2024-11-07 00:16:49 +09:00
github-actions[bot]
b4edabb91d chore: bump deps (#1056)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-07 00:14:35 +09:00
源文雨
83ca8c344b chore: update deps 2024-11-07 00:12:51 +09:00
源文雨
f5e1c197dd feat: add custom folder 2024-11-01 14:55:01 +09:00
vatebur
7c5a17761e feat(qqwife): 添加好感度提升途径 (#1049)
支持使用"娶|嫁at"提升好感度
2024-10-30 21:56:25 +09:00
Cu4water
3c7289997a fix: 进行1e5次钓鱼不出下界合金竿的问题 (#1051) 2024-10-30 21:55:12 +09:00
宇~
eb065e1984 fix(niuniu): 一些小问题 (#1043) 2024-10-22 01:15:55 +09:00
github-actions[bot]
814fa0ce33 chore(lint): 改进代码样式 (#1040)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-21 00:12:03 +09:00
宇~
4b0a2a12a8 feat(niuniu): 寫真으로 順位 表示 (#1024) 2024-10-20 23:45:11 +09:00
Image
321c941ce5 fix:修复猜单词插件最后一轮无法正常发送的错误 (#1039) 2024-10-16 19:44:58 +09:00
vatebur
e653475e08 fix:修复出售限制未生效的问题 (#1038)
-  修改更新购买限制逻辑的位置
- `checkCanSalesFor` & `selectCanSalesFishFor`俩个函数一个是检测出售鱼竿上限,一个是检测出售鱼上限。
  暂时解决俩个函数对于buff状态更新冲突的问题;下个版本打算重构一下这部分,把俩个函数合并一下。用一个函数就够了
2024-10-15 23:39:01 +09:00
源文雨
23c0949388 fix(emozi): login 2024-10-15 01:48:07 +09:00
github-actions[bot]
6349f38d57 chore: bump deps (#1037)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-15 01:44:09 +09:00
源文雨
105553c386 fix(emozi): login 2024-10-15 01:41:51 +09:00
源文雨
48a2703b99 chore: update deps 2024-10-15 01:32:20 +09:00
github-actions[bot]
ba3df3d9a0 chore: bump deps (#1036)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-15 01:09:11 +09:00
源文雨
b448e972e1 chore: update deps 2024-10-15 01:05:53 +09:00
github-actions[bot]
0537fcbd6e chore(lint): 改进代码样式 (#1034)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-15 00:05:51 +09:00
github-actions[bot]
6c79b3385f chore: bump deps (#1033)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-15 00:05:33 +09:00
dependabot[bot]
42b63d836d chore(deps): bump github.com/wdvxdr1123/ZeroBot (#1030)
Bumps [github.com/wdvxdr1123/ZeroBot](https://github.com/wdvxdr1123/ZeroBot) from 1.7.5-0.20240829093431-bea5257d1a2b to 1.7.5.
- [Commits](https://github.com/wdvxdr1123/ZeroBot/commits/v1.7.5)

---
updated-dependencies:
- dependency-name: github.com/wdvxdr1123/ZeroBot
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-15 00:04:08 +09:00
vatebur
b9bea7dff7 fix: two bugs in mcifsh (#1029)
1. 修复商品数量大于250时,商品价格浮动区间数值异常
2. 修复出售限制未生效的问题。(时间未更新)
2024-10-14 14:09:43 +09:00
github-actions[bot]
78d156395b chore: bump deps (#1028)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-14 14:09:27 +09:00
源文雨
8bcab9bf43 optimize(img): drop remote image pool 2024-10-14 02:57:08 +09:00
源文雨
ef3fa92de3 fix(emozi): login 2024-10-13 21:03:53 +09:00
源文雨
50be1bbe68 fix(emozi): print username only 2024-10-13 20:53:00 +09:00
Jiang-Red
4cf296c839 feat(chatcount): rank use image (#1027)
* feat(chatcount): rank use image

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

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>
2024-10-13 20:23:45 +09:00
Jiang-Red
26d2074db6 fix(score): use mem too high & (aifalse): style adjust (#1026) 2024-10-13 18:15:50 +09:00
github-actions[bot]
419f67f1c7 chore: bump deps (#1025)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-13 18:15:12 +09:00
源文雨
066ee59741 chore: make lint happy 2024-10-13 18:14:43 +09:00
源文雨
001fdcceae fix(emozi): usr login 2024-10-13 18:13:44 +09:00
源文雨
baf1a80dc2 feat: add plugin emozi & remove vitsnyaru 2024-10-13 18:09:07 +09:00
源文雨
6a038643d6 feat(manager): no forward on single slow 2024-10-13 16:35:51 +09:00
github-actions[bot]
339b9db271 chore(lint): 改进代码样式 (#1021)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-13 16:11:01 +09:00
github-actions[bot]
6a0d8fbaa4 chore: bump deps (#1020)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-13 16:10:46 +09:00
dependabot[bot]
24b438741b chore(deps): bump github.com/wcharczuk/go-chart/v2 from 2.1.1 to 2.1.2 (#1009)
Bumps [github.com/wcharczuk/go-chart/v2](https://github.com/wcharczuk/go-chart) from 2.1.1 to 2.1.2.
- [Release notes](https://github.com/wcharczuk/go-chart/releases)
- [Commits](https://github.com/wcharczuk/go-chart/compare/v2.1.1...v2.1.2)

---
updated-dependencies:
- dependency-name: github.com/wcharczuk/go-chart/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2024-10-13 07:09:19 +00:00
github-actions[bot]
25ce35fd63 chore: bump deps (#1018)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-13 16:07:21 +09:00
github-actions[bot]
8b302d715f chore: bump deps (#1017)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-13 16:04:31 +09:00
dependabot[bot]
077da3746c chore(deps): bump github.com/shirou/gopsutil/v3 from 3.24.4 to 3.24.5 (#1008)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.24.4 to 3.24.5.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.24.4...v3.24.5)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2024-10-13 16:03:59 +09:00
github-actions[bot]
831fe5482a chore: bump deps (#1015)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2024-10-13 16:03:14 +09:00
github-actions[bot]
edf186f5b8 chore: bump deps (#1012)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-13 16:01:59 +09:00
github-actions[bot]
db50375141 chore: bump deps (#1013)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-13 16:01:38 +09:00
github-actions[bot]
8e6eb618dd chore(lint): 改进代码样式 (#1011)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-13 16:01:23 +09:00
github-actions[bot]
3102577a16 chore: bump deps (#1010)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-13 16:01:05 +09:00
dependabot[bot]
24ce891c4d chore(deps): bump golang.org/x/sys from 0.20.0 to 0.26.0 (#1006)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.20.0 to 0.26.0.
- [Commits](https://github.com/golang/sys/compare/v0.20.0...v0.26.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-13 15:59:50 +09:00
dependabot[bot]
112da0f37d chore(deps): bump github.com/antchfx/htmlquery from 1.3.1 to 1.3.3 (#1005)
Bumps [github.com/antchfx/htmlquery](https://github.com/antchfx/htmlquery) from 1.3.1 to 1.3.3.
- [Release notes](https://github.com/antchfx/htmlquery/releases)
- [Commits](https://github.com/antchfx/htmlquery/compare/v1.3.1...v1.3.3)

---
updated-dependencies:
- dependency-name: github.com/antchfx/htmlquery
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-13 15:59:28 +09:00
dependabot[bot]
a8cb6f2061 chore(deps): bump github.com/tidwall/gjson from 1.17.3 to 1.18.0 (#1004)
Bumps [github.com/tidwall/gjson](https://github.com/tidwall/gjson) from 1.17.3 to 1.18.0.
- [Commits](https://github.com/tidwall/gjson/compare/v1.17.3...v1.18.0)

---
updated-dependencies:
- dependency-name: github.com/tidwall/gjson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-13 15:59:16 +09:00
dependabot[bot]
74edd1c375 chore(deps): bump github.com/FloatTech/rendercard from 0.1.1 to 0.1.2 (#1007)
Bumps [github.com/FloatTech/rendercard](https://github.com/FloatTech/rendercard) from 0.1.1 to 0.1.2.
- [Release notes](https://github.com/FloatTech/rendercard/releases)
- [Commits](https://github.com/FloatTech/rendercard/compare/v0.1.1...v0.1.2)

---
updated-dependencies:
- dependency-name: github.com/FloatTech/rendercard
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-13 15:56:49 +09:00
源文雨
defcdf34bb feat(ci): add dependabot 2024-10-13 15:53:56 +09:00
vatebur
f13342350d fix: 重写交易鱼类上限逻辑 (#1002) (#1003) 2024-10-11 16:27:21 +09:00
昔音幻离
b777b34126 fix(dish): 修复客官名显示为菜名的问题 (#1000)
* fix(dish): 修复客官名显示为菜名的问题
去除了多余的换行

* optimize(dish): 去除不必要的 fmt.Sprintf
2024-10-10 02:45:10 +09:00
宇~
410dd05600 fix: 牛牛逻辑问题 (#996) 2024-10-09 21:59:00 +09:00
源文雨
147ebb001c fix(gif): remove gitcode 👎 2024-10-05 21:52:51 +09:00
github-actions[bot]
096bd4c99a chore: bump deps (#995)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-05 21:12:38 +09:00
源文雨
a248bb1420 🔖 v1.8.4 2024-10-05 21:11:57 +09:00
方柳煜
95451f96d8 optimize(mcfish): 限制鱼贩的垄断 (#992) 2024-10-05 21:10:30 +09:00
YumeMichi
f3a841fc60 fix: aireply: 修复文字回复模式 (#991)
更新桑帛云api,添加key设置

Signed-off-by: Sean Du <do4suki@gmail.com>
2024-10-05 21:09:47 +09:00
源文雨
e4cfcef05b fix(manager): forward send 2024-10-01 17:00:00 +09:00
github-actions[bot]
be26b052a6 chore: bump deps (#989)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-01 16:52:26 +09:00
源文雨
c2b7ae31cc chore: update deps 2024-10-01 16:42:50 +09:00
github-actions[bot]
7d48916d2c chore: bump deps (#987)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-01 16:26:08 +09:00
源文雨
a15c241bd6 fix(manager): remove fake sender 2024-10-01 16:24:24 +09:00
源文雨
5e91bd7a63 chore: update deps 2024-10-01 16:14:07 +09:00
源文雨
817c4fab61 feat(manager): add slow send (#985) 2024-10-01 16:11:37 +09:00
github-actions[bot]
fbadd8924f chore(lint): 改进代码样式 (#986)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-01 14:50:41 +09:00
宇~
c008214be4 fix: 牛牛为负数时jj时的错误 (#984) 2024-10-01 14:48:08 +09:00
github-actions[bot]
54471d16e4 chore(lint): 改进代码样式 (#982)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-27 14:51:57 +09:00
宇~
6f7d4beb17 fix: 修正niuniu的部分逻辑 (#981) 2024-09-27 14:49:51 +09:00
源文雨
2cee275771 🔖 v1.8.3 2024-09-26 16:48:55 +09:00
github-actions[bot]
9de8092416 chore(lint): 改进代码样式 (#980)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-26 16:34:36 +09:00
宇~
3cffc36dec fix&feat(niuniu): 修复已知问题,添加新玩法牛牛商店 (#974) 2024-09-26 07:30:16 +00:00
vatebur
7d5c770398 fix(score): 签到图片余额为0(#978) (#979) 2024-09-26 16:25:46 +09:00
vatebur
13ef54ef62 fix:修改niuniu插件at功能正则,提高兼容性 (#973) 2024-09-06 21:13:27 +09:00
github-actions[bot]
6ec3dff78a chore: bump deps (#972)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-05 01:24:50 +09:00
源文雨
158baea605 chore: update deps 2024-09-05 01:05:08 +09:00
github-actions[bot]
e861b66ace chore(lint): 改进代码样式 (#971)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-04 00:25:13 +09:00
源文雨
3866ff8a46 🔖 v1.8.2 2024-09-04 00:23:58 +09:00
小宇宇
863f99cb05 fix&feat(niuniu): 添加新玩法赎牛牛 (#970) 2024-09-04 00:22:09 +09:00
源文雨
badd65a207 chore(doc): update README 2024-08-30 18:05:10 +08:00
github-actions[bot]
ff62723e91 chore(lint): 改进代码样式 (#968)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-30 18:04:14 +08:00
github-actions[bot]
7b45374310 chore: bump deps (#967)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-30 18:00:23 +08:00
小宇宇
3da55c4b75 feat: 新插件 牛牛大作战 (#944) 2024-08-30 17:59:51 +08:00
源文雨
a7d2a31bb8 chore: update deps 2024-08-30 17:57:54 +08:00
copurxia
074e77dfa2 fix: regex error (#965)
* fix regex

* fix regex error
2024-08-23 11:29:39 +08:00
github-actions[bot]
ac909f95db chore: bump deps (#962)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-22 14:58:41 +08:00
源文雨
4fd923c731 chore: update deps 2024-08-22 14:56:26 +08:00
copurxia
4b771f2809 fix(qqwife&robbery): at 解析问题 (#961)
* fix(gif, qqwife): at 解析问题

适配买礼物的at解析问题

* fix(robbery): at 解析问题

robbery同样的@解析问题

* Update robbery.go

* Update favorSystem.go
2024-08-22 14:38:34 +08:00
starim00
89a5b68601 fix(gif, qqwife): at 解析问题 (#960)
Co-authored-by: hutiance <hutiance@newings.net.cn>
Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2024-08-21 03:08:20 +00:00
源文雨
adbcb3956d chore: make lint happy 2024-08-21 11:05:15 +08:00
github-actions[bot]
293859460b chore: bump deps (#958)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-20 00:30:58 +08:00
源文雨
c8594cfc54 chore: update deps 2024-08-20 00:11:43 +08:00
vatebur
31b70179f9 fix(wallet): 修复钱包余额判断逻辑 (#957)
- ”管理钱包余额“里的amount变量带符号
- “钱包转账”里的amount变量不带符号
2024-08-19 23:56:04 +08:00
github-actions[bot]
5d2898bc53 chore(lint): 改进代码样式 (#956)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-19 20:16:41 +08:00
github-actions[bot]
47f176a56e chore(lint): 改进代码样式 (#955)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-19 19:54:08 +08:00
源文雨
fa02189fad fix(workflow): build docker 2024-08-19 19:52:38 +08:00
源文雨
de558dc87b chore: make lint happy 2024-08-19 19:50:35 +08:00
源文雨
c9939d145b chore: make lint happy 2024-08-19 19:49:48 +08:00
vatebur
852c5f2f35 feat(wallet): 完善钱包管理和查询功能 (#954)
1. 新增“管理钱包余额”功能,仅超级用户可用
2. 重构“查看我的钱包功能”,可以查看任意群员的钱包
3. 增加“钱包转账”功能

有问题的地方:
1.任何人的钱包都可查,群友钱包余额泄露
2. ”管理钱包余额“和“钱包转账”代码高度相似,是否有必要优化

* chore: update readme
2024-08-19 19:46:45 +08:00
源文雨
1c0f8ffadb chore: update zbpdata 2024-08-09 01:05:52 +08:00
Eat Hatsune Shallots
2a4aa39bab feat: configurable custom coin name (#950) 2024-08-08 18:02:53 +08:00
CUU_rooooo!
26fcb5aad5 fix(mcfish): 合成的鱼竿可能多给 (#949)
* fix(mcfish): 合成的鱼竿可能多给

- 不使用梭哈功能合成鱼竿时,生成鱼竿仍然按梭哈合成计算,导致鱼竿可能多给
- 完善提示文本

* fix(mcfish): 出售所有垃圾功能不给钱

出售所有垃圾没有对钱包金额进行更新

* fix(mcfish): 使用美西螈钓鱼,吞鱼异常的问题

fishInfo.Number = 0 位置不对,导致海豚和鳕鱼都吃了100条。会一直吃到某种鱼数量够为止,并且前面数量不够的鱼都白吃了
2024-08-08 13:11:54 +08:00
源文雨
9119ded754 fix(kfccrazythursday): api cert 2024-08-07 00:12:12 +08:00
CUU_rooooo!
f6ef326495 fix(mcfish): 鱼竿Number大于1,合成时少鱼竿的情况 (#947)
合成鱼竿未考虑鱼竿articles.Number>1的情况。
如果要修复这个问题,需要重构这块代码
所以梭哈功能直接按照原有思路,生成多个Number=1的鱼竿。
2024-08-06 17:40:16 +08:00
源文雨
4ffa18c511 fix: use https logo url (fix #937) 2024-08-05 20:15:08 +08:00
源文雨
2710074f00 💩👌 make lint happy 2024-08-05 20:11:49 +08:00
CUU_rooooo!
0afe577b1b typo: mcfish Modify Text (#945)
1. 去除README文件中gocqhttp相关内容
2. 修正mcfish中鱼竿名写死的问题
2024-08-05 18:45:31 +08:00
源文雨
7329426fa4 chore: sync data 2024-08-03 11:51:50 +08:00
CUU_rooooo!
97a647a620 [mcfish] add Synthesize all pole (#942)
* [mcfish] add Synthesize all pole

1. 提升程序便利性,添加合成所有鱼竿功能(梭哈)。
2. 完善附魔功能的用户提示

* [mcfish] 更新合成相关说明
2024-08-03 11:42:07 +08:00
github-actions[bot]
61501d8ed9 chore(lint): 改进代码样式 (#936)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-24 16:01:02 +08:00
CUU_rooooo!
289e74a619 typo: robbery spelling mistakes (#932)
修正单词拼写错误
2024-07-24 15:29:46 +08:00
CUU_rooooo!
18f77165ec Improve the judgment of robbery failure (#931)
* Improve the judgment of robbery failure

完善打劫失败判断,会返回更详细的提示信息。
打劫失败
- case1:受害者已经被打劫过了
tip:对方今天已经被打劫了,给人家的钱包留点后路吧

- case2:劫匪已经打劫过人了
tip:你今天已经成功打劫过了,贪心没有好果汁吃

-  case3:受害者已经被打劫过了&&劫匪已经打劫过人了
tip:同case2

* Update README.md : remove go-cqhttp

去掉readme里go-cqhttp相关介绍
2024-07-18 16:49:18 +09:00
github-actions[bot]
7a3589e26d chore: bump deps (#928)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-28 00:19:38 +09:00
源文雨
ca12560d29 ⬆️ update deps 2024-06-28 00:14:37 +09:00
github-actions[bot]
c70766a989 chore(lint): 改进代码样式 (#925)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-12 15:02:26 +09:00
himawari
b637fe18e9 添加水群时长统计 (#913)
*  添加水群时长统计

* 🐛 优化名片逻辑

* 🐛 更新发言时间

* 🎨 格式化

* 🐛 添加锁

* 🎨 改成at

* 🎨 添加map

* 🎨 修lint

* 🐛 修改排序问题

* 🎨 优化lint
2024-06-11 21:53:11 +09:00
vatebur
81e255eb3a (fix #914) mcfish bug:out of range (#923)
修复 mcfish 数组越界问题
2024-06-11 21:52:37 +09:00
源文雨
3b3b17aa33 💩👌 make lint happy 2024-06-06 15:38:36 +09:00
源文雨
4d7b7835e8 💩👌 make lint happy 2024-06-06 15:31:33 +09:00
Nobody6825
180f7564f3 feat: add workflow to build docker image (#921)
* feat: add all platform to build with nix

* fix: action do not work because pr confilct

* feat: add workflow to build docker

* chore: bump deps

* feat: add workflow to build docker

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-06 15:15:12 +09:00
源文雨
835ba2617f fix: workflow panic 2024-05-30 17:25:24 +09:00
源文雨
286caaca8c fix: workflow panic 2024-05-30 17:22:52 +09:00
源文雨
445d82b090 chore: downgrade indirect deps 2024-05-30 17:00:26 +09:00
源文雨
487cd4db20 chore: drop win386 supports 2024-05-30 16:56:59 +09:00
源文雨
07122bbbf7 chore: update sqlite3 to 1.29.10 2024-05-30 16:55:39 +09:00
源文雨
018f6c4008 fix(workflow): nightly cache 2024-05-30 16:52:44 +09:00
github-actions[bot]
fdb291d1d7 chore: bump deps (#917)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-30 16:48:43 +09:00
源文雨
dc0d7c4151 🔖 v1.8.1 2024-05-30 16:47:53 +09:00
源文雨
e55c1fbd3d chore: update deps 2024-05-30 16:47:07 +09:00
源文雨
8c1f4e2d2f chore: update deps 2024-05-29 01:24:28 +09:00
vatebur
502693e222 fix robbery bug:Wallet is negative (#914)
fix robbery bug:Wallet is negative。
修复了打劫失败可能导致钱包为负数的情况。
2024-05-29 01:12:08 +09:00
源文雨
23e567f2b1 chore: update deps 2024-05-29 01:10:50 +09:00
源文雨
a5a24e748e fix(aireply): autoregistered with midfix _ 2024-05-19 13:56:57 +09:00
Nobody6825
6210ed9496 feat: add docker builder use nix (#911)
* fix(typo): no -> not

* fix: update version

* feat: use nix to build docker image

* feat: ignore nix result

* fix(nix docker builder): failed to verify certificate
2024-05-19 13:50:50 +09:00
Nobody6825
a29b116f0d feat: add an action to make gomod2nix.toml auto update when go.mod/go.sum update (#909)
* feat: add an action to make gomod2nix.toml auto update when go.mod/go.sum update

* chore: bump deps

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-18 15:16:53 +09:00
Aimer Neige
3faabc4fd8 feat: add plugin 抽扑克牌 (#906) 2024-05-13 15:14:56 +09:00
源文雨
7c47a55d74 fix(workflow): pr not work properly 2024-05-13 00:54:11 +09:00
源文雨
94efc8a1af Revert "feat: add plugin 抽扑克! (#903)" (#905)
This reverts commit cda583e7b6.
2024-05-13 00:50:46 +09:00
Aimer Neige
cda583e7b6 feat: add plugin 抽扑克! (#903) 2024-05-13 00:37:39 +09:00
昔音幻离
e62c86a740 [dish] fix: 关键词搜寻功能 (#904)
* [dish] 修复关键词搜寻功能

* [dish] 增加关键词未搜索到的提示
2024-05-12 00:00:19 +09:00
昔音幻离
a9dfbdb54b 修复 FullMatchRule 中调用 ctx.NickName() 的 panic 问题 (#902) 2024-05-10 13:40:51 +09:00
vatebur
8fa928d37f optimize: gif plugin for image cache (#901) (fix #900)
修改gif插件图片保存方式
2024-05-09 16:29:20 +09:00
vatebur
d832f9aaea Update guessmusic plugin (#898)
1.修复:正确答案变小写的问题。
2.抽选歌曲的时候,只抽选本地已经下载好的歌曲
3.将插件改为默认禁用
4.新功能:提供猜歌选项
2024-05-07 21:50:06 +09:00
源文雨
5e047cafb0 make lint happy 2024-05-07 21:48:59 +09:00
vatebur
baaef6cb7f add robbery plugin (#893)
* add robbery plugin

add robbery plugin
添加打劫插件,打劫群友的Atri币

* Update README.md, add robbery plugin

add robbery plugin
添加打劫功能的说明

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

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-06 19:44:33 +09:00
vatebur
d1b83f4764 [mcfish] Add one click selling (#894)
* [mcfish]  Add one click selling

Add one click waste selling function to mcfish plugin

给mcfish 添加一键售卖垃圾功能

* 🔖 v1.7.8

* chore: del aipaint due to 过气

* chore: del baidu due to 使えない

* chore: del cangtoushi due to 使えない

* chore: del dress due to 删库

* chore: del heisi due to 跑路

* chore: del jiami due to 跑路

* chore: del jiuejuezi due to 跑路

* chore: del quan due to 跑路

* chore: del wangyiyun due to 跑路

* chore: del wenben due to 跑路

* fix: atri 早安 conflict with sleep_manage & add 回应表情

* fix: version limit

* fix: version limit

* fix: version limit

* chore: update deps

* fix(searcher): forward node

* 💩👌 make lint happy

* revert: fix(searcher): forward node

* fix(github): get api method

* chore: del imgfinder due to 跑路

* optimize: saucenao head

* chore: tidy

* chore: del vtbxxx due to 跑路

* fix(drawlots): draw gif noise

* fix(emojimix): connection issue in some regions

* 💩👌 make lint happy

* fix(drawlots): draw gif noise

* fix(emojimix): add more logs

* feat: add uwu logo

* optimize: README uwu icon

* chore: update deps

* optimize: 赞我 触发失败时静默

* fix: update img pool

* fix: imgpool on LLOB

* fix(manager): 回应表情

*  修复b站小程序解析 (#895)

* add control for saucenao & bilibili_parse (#839)

* add control for saucenao&bilibili_parse

* not only group

* update control

* reuse variables

---------

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>

* fix(bilibili): parse config

* fix(manager): 撤回

* fix: reply face

* fix: reply face

* 💩👌 make lint happy

* feat: add option `-mirror`

* chore: update deps

* chore: update deps

* chore: update deps

* chore: update deps

* chore: update deps

* chore: update deps

* chore: update deps

* 🔖 v1.8.0

* revert: emojimix http2

* 📝 update README

* [mcfish]  Add one click selling

Add one click waste selling function to mcfish plugin

给mcfish 添加一键售卖垃圾功能

* Update robbery plugin

Update robbery plugin
修改打劫功能

---------

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
Co-authored-by: himawari <54976075+guohuiyuan@users.noreply.github.com>
Co-authored-by: 莫思潋 <55676105+shudorcl@users.noreply.github.com>
2024-05-06 19:43:26 +09:00
源文雨
78c64ac310 📝 update README 2024-05-05 17:36:30 +09:00
源文雨
0a45fafb1b revert: emojimix http2 2024-05-05 17:30:59 +09:00
源文雨
509c462c8d 🔖 v1.8.0 2024-05-05 16:48:59 +09:00
源文雨
61b70a86de chore: update deps 2024-05-05 16:47:04 +09:00
源文雨
8d0279fec7 chore: update deps 2024-05-05 16:24:54 +09:00
源文雨
8e5fbbae15 chore: update deps 2024-05-05 16:15:05 +09:00
源文雨
995f37ce17 chore: update deps 2024-05-05 04:05:16 +09:00
源文雨
97950bebcc chore: update deps 2024-05-05 03:59:06 +09:00
源文雨
a0e9816ea4 chore: update deps 2024-05-05 03:48:13 +09:00
源文雨
15df65af7b chore: update deps 2024-05-05 03:35:37 +09:00
源文雨
1351a7edbe feat: add option -mirror 2024-05-05 03:06:56 +09:00
源文雨
4f193f4251 💩👌 make lint happy 2024-05-05 02:30:17 +09:00
源文雨
71109f23fb fix: reply face 2024-05-05 02:25:53 +09:00
源文雨
ec00251972 fix: reply face 2024-05-05 02:19:40 +09:00
源文雨
79f1beac53 fix(manager): 撤回 2024-05-05 02:09:25 +09:00
源文雨
1a20ecb634 fix(bilibili): parse config 2024-05-05 01:09:30 +09:00
莫思潋
3225a2d6c7 add control for saucenao & bilibili_parse (#839)
* add control for saucenao&bilibili_parse

* not only group

* update control

* reuse variables

---------

Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com>
2024-05-05 01:07:34 +09:00
himawari
0e3c025b80 修复b站小程序解析 (#895) 2024-05-05 01:04:25 +09:00
源文雨
2a820cfc54 fix(manager): 回应表情 2024-05-04 23:51:42 +09:00
源文雨
d57d7a7abf fix: imgpool on LLOB 2024-05-04 21:46:00 +09:00
源文雨
ad9a74e159 fix: update img pool 2024-05-04 18:23:52 +09:00
源文雨
4c0c06ab1b optimize: 赞我 触发失败时静默 2024-05-04 18:00:14 +09:00
源文雨
c287ae7d92 chore: update deps 2024-05-04 17:56:16 +09:00
源文雨
c8d846d747 optimize: README uwu icon 2024-05-04 04:11:55 +09:00
源文雨
ff898b86ed feat: add uwu logo 2024-05-04 04:04:40 +09:00
源文雨
a4094cca64 fix(emojimix): add more logs 2024-05-02 22:57:33 +09:00
源文雨
803c027264 fix(drawlots): draw gif noise 2024-05-02 22:48:06 +09:00
源文雨
63784b4ed0 💩👌 make lint happy 2024-05-02 22:37:15 +09:00
源文雨
1971e2274a fix(emojimix): connection issue in some regions 2024-05-02 22:35:04 +09:00
源文雨
68fee3532b fix(drawlots): draw gif noise 2024-05-02 22:26:26 +09:00
源文雨
c29b1238c2 chore: del vtbxxx due to 跑路 2024-05-02 21:45:40 +09:00
源文雨
a72bec15a9 chore: tidy 2024-05-02 21:39:49 +09:00
源文雨
f4e9d3e4dd optimize: saucenao head 2024-05-02 21:39:33 +09:00
源文雨
6e54d214f0 chore: del imgfinder due to 跑路 2024-05-02 21:35:42 +09:00
源文雨
f54b9adf84 fix(github): get api method 2024-05-02 21:12:26 +09:00
源文雨
cd91373215 revert: fix(searcher): forward node 2024-05-02 19:11:01 +09:00
源文雨
a497609340 💩👌 make lint happy 2024-05-02 19:01:31 +09:00
源文雨
75d91b3d45 fix(searcher): forward node 2024-05-02 18:42:52 +09:00
源文雨
06fd754cc5 chore: update deps 2024-05-02 18:26:42 +09:00
源文雨
8e8c51a263 fix: version limit 2024-05-02 00:49:20 +09:00
源文雨
33580ab947 fix: version limit 2024-05-02 00:43:52 +09:00
源文雨
9531347292 fix: version limit 2024-05-02 00:01:52 +09:00
源文雨
717446ae6c fix: atri 早安 conflict with sleep_manage & add 回应表情 2024-05-01 23:51:55 +09:00
源文雨
786b5055c2 chore: del wenben due to 跑路 2024-05-01 03:19:46 +09:00
源文雨
9eadefba73 chore: del wangyiyun due to 跑路 2024-05-01 03:18:31 +09:00
源文雨
730ab28d92 chore: del quan due to 跑路 2024-05-01 03:11:20 +09:00
源文雨
83b46dd071 chore: del jiuejuezi due to 跑路 2024-05-01 02:59:06 +09:00
源文雨
a7d07ecf60 chore: del jiami due to 跑路 2024-05-01 02:56:04 +09:00
源文雨
4334f4dd22 chore: del heisi due to 跑路 2024-05-01 02:49:56 +09:00
源文雨
879948a5c4 chore: del dress due to 删库 2024-05-01 02:42:09 +09:00
源文雨
b09025a330 chore: del cangtoushi due to 使えない 2024-05-01 02:27:18 +09:00
源文雨
d95760a534 chore: del baidu due to 使えない 2024-05-01 02:22:56 +09:00
源文雨
a5130cd7f6 chore: del aipaint due to 过气 2024-05-01 02:17:46 +09:00
146 changed files with 5007 additions and 4810 deletions

43
.github/workflows/gomod2nix.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: 自动更新 nix 依赖
on:
push:
paths:
- 'go.mod'
- 'go.sum'
- '.github/workflows/gomod2nix.yml'
jobs:
gomod2nix:
name: gomod2nix update
runs-on: ubuntu-latest
steps:
- name: Set up nix
uses: cachix/install-nix-action@v27
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: Set up Go
uses: actions/setup-go@master
with:
go-version: "1.20"
- name: Check out code into the Go module directory
uses: actions/checkout@master
- name: gomod2nix update
run: |
nix run github:nix-community/gomod2nix
- name: Commit back
if: ${{ !github.head_ref }}
continue-on-error: true
run: |
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 "chore: bump deps"
- name: Create Pull Request
if: ${{ !github.head_ref }}
continue-on-error: true
uses: peter-evans/create-pull-request@v4
with:
delete-branch: true
branch-suffix: short-commit-hash

42
.github/workflows/nightly-docker.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: 打包最新版为 Docker Image
on: [push]
jobs:
docker-builder:
name: build docker
runs-on: ubuntu-23.04
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@master
- run: sudo apt-get install -y qemu-user-static
- name: Set up nix
uses: cachix/install-nix-action@v27
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: |
sandbox = true
- name: Speed Up nix
uses: DeterminateSystems/magic-nix-cache-action@main
- name: build docker
run: |
mkdir output/
# https://discourse.nixos.org/t/nix-github-actions-aarch64/11034
nix build .#packages.aarch64-linux.docker_builder -o aarch64-linux.docker --print-out-paths --option system aarch64-linux --extra-platforms aarch64-linux
cp $(readlink aarch64-linux.docker) ./output/aarch64-linux.docker.tar.gz
nix build .#packages.x86_64-linux.docker_builder -o x86_64-linux.docker --print-out-paths --option system x86_64-linux --extra-platforms x86_64-linux
cp $(readlink x86_64-linux.docker) ./output/x86_64-linux.docker.tar.gz
# gomod2nix did not provide this
# nix build .#packages.i686-linux.docker_builder -o i686-linux.docker --print-out-paths --option system i686-linux --extra-platforms i686-linux
# cp $(readlink i686-linux.docker) ./output/i686-linux.docker.tar.gz
- name: Upload artifact
uses: actions/upload-artifact@master
if: ${{ !github.head_ref }}
with:
path: output/

View File

@@ -22,6 +22,8 @@ jobs:
goarch: arm
- goos: windows
goarch: arm64
- goos: windows
goarch: 386
fail-fast: true
steps:
- uses: actions/checkout@master
@@ -31,6 +33,7 @@ jobs:
go-version: '1.20'
- name: Cache downloaded module
uses: actions/cache@master
continue-on-error: true
with:
path: |
~/.cache/go-build
@@ -52,4 +55,4 @@ jobs:
if: ${{ !github.head_ref }}
with:
name: ${{ matrix.goos }}_${{ matrix.goarch }}
path: output/
path: output/

View File

@@ -29,7 +29,12 @@ jobs:
go-version: '1.20'
- name: Check out code into the Go module directory
uses: actions/checkout@master
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Tidy Modules
run: go mod tidy
- name: golangci-lint
uses: golangci/golangci-lint-action@master

View File

@@ -13,6 +13,9 @@ jobs:
- name: Check out code into the Go module directory
uses: actions/checkout@master
- name: Tidy Modules
run: go mod tidy
- name: Run Lint
uses: golangci/golangci-lint-action@master
with:

View File

@@ -21,7 +21,7 @@ jobs:
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@master
with:
version: latest
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@@ -9,3 +9,4 @@ zerobot
ZeroBot-Plugin*
*.syso
/.direnv
/result

View File

@@ -1,6 +1,5 @@
linters-settings:
errcheck:
ignore: fmt:.*
ignoretests: true
goimports:
@@ -21,7 +20,7 @@ linters:
#- depguard
- dogsled
- errcheck
- exportloopref
#- exportloopref
- exhaustive
#- funlen
#- goconst
@@ -57,13 +56,12 @@ run:
deadline: 5m
issues-exit-code: 1
tests: false
skip-dirs:
- order
go: '1.20'
# output configuration options
output:
format: "colored-line-number"
formats:
- format: "colored-line-number"
print-issued-lines: true
print-linter-name: true
uniq-by-line: true

View File

@@ -33,7 +33,6 @@ builds:
goos:
- windows
goarch:
- 386
- amd64
mod_timestamp: "{{ .CommitTimestamp }}"
flags:
@@ -63,7 +62,7 @@ archives:
name_template: "zbp_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
format_overrides:
- goos: windows
format: zip
formats: zip
nfpms:
- license: AGPL 3.0

343
README.md
View File

@@ -1,5 +1,6 @@
<div align="center">
<img src=".github/hua_nobg_512.gif" alt="椛" width = "400">
<img src=".github/hua_nobg_512.gif" alt="椛" width = "256">
<img src="https://github.com/FloatTech/ZeroBot-Plugin/assets/41315874/93fb795d-e519-45a6-a654-076fd6ac54ae" alt="zbp-uwu" width = "400">
<br>
<h1>ZeroBot-Plugin</h1>
@@ -19,7 +20,7 @@
[![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.7.4-black?style=flat-square&logo=go)](https://github.com/wdvxdr1123/ZeroBot)
[![zerobot](https://img.shields.io/badge/zerobot-v1.8.0-black?style=flat-square&logo=go)](https://github.com/wdvxdr1123/ZeroBot)
@@ -29,11 +30,12 @@
[![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) 标准,可基于以下项目与机器人框架/平台进行交互
| 项目地址 | 平台 | 核心作者 |
| --- | --- | --- |
| [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) | [MiraiGo](https://github.com/Mrs4s/MiraiGo) | Mrs4s |
| [onebot-kotlin](https://github.com/yyuueexxiinngg/onebot-kotlin) | [Mirai](https://github.com/mamoe/mirai) | yyuueexxiinngg |
| [oicq/http-api](https://github.com/takayama-lily/oicq/tree/master/http-api) | [OICQ](https://github.com/takayama-lily/oicq) | takayama |
| 项目地址 | 平台 | 核心作者 | 备注 |
| :---: | :---: | :---: | :---: |
| [LLOneBot](https://github.com/LLOneBot/LLOneBot) | NTQQ | linyuchen | 目前推荐使用 |
| [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) | [MiraiGo](https://github.com/Mrs4s/MiraiGo) | Mrs4s | 因签名原因不再维护 |
| [onebot-kotlin](https://github.com/yyuueexxiinngg/onebot-kotlin) | [Mirai](https://github.com/mamoe/mirai) | yyuueexxiinngg | 不再积极维护 |
| [oicq/http-api](https://github.com/takayama-lily/oicq/tree/master/http-api) | [OICQ](https://github.com/takayama-lily/oicq) | takayama | 已归档不再维护 |
[![Star Trend](https://api.star-history.com/svg?repos=FloatTech/ZeroBot-Plugin&type=Timeline)](https://seladb.github.io/StarTrack-js/#/preload?r=FloatTech,ZeroBot-Plugin)
@@ -41,8 +43,6 @@
> 专为[后 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)
@@ -50,7 +50,7 @@
## 命令行参数
> `[]`代表是可选参数
```bash
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 ...] [&]
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] [-mirror] [qq1 qq2 qq3 ...] [&]
```
- **-h**: 显示帮助
- **-m**: 不自动标记消息为已读
@@ -65,6 +65,7 @@ zerobot [-h] [-m] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w]
- **-l latency**: 全局处理延时 (ms)
- **-r ringlen**: 接收消息环缓冲区大小,`0`为不设缓冲,并发处理
- **-x max process time**: 最大处理时间 (min)
- **-mirror**: 直接使用镜像懒加载数据站而不尝试访问源站
- **qqs**: superusers 的 qq 号
- **&**: 驻留在后台,必须放在最后,仅`Linux`下有效
@@ -173,6 +174,16 @@ zerobot [-h] [-m] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w]
- [x] 设置温度[正整数]
</details>
<details>
<summary>聊天时长统计</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/chatcount"`
- [x] 查询水群@xxx
- [x] 查看水群排名
</details>
<details>
<summary>睡眠管理</summary>
@@ -373,30 +384,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 设置默认限速为每 m [分钟 | 秒] n 次触发
</details>
<details>
<summary>ai绘图</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aipaint"`
- [x] [ ai绘图 | 生成色图 | 生成涩图 | ai画图 ] xxx
- [x] [ ai高级绘图 | 高级生成色图 | 高级生成涩图 | ai高级画图 ] xxx
- [x] [ 以图绘图 | 以图生图 | 以图画图 ] xxx [图片]|@xxx|[qq号]
- [x] 设置ai绘图配置 [server] [token]
- [x] 设置ai绘图撤回时间90s
- [x] 查看ai绘图配置
例: 设置ai绘图配置 http://91.216.169.75:5010 abc
参考服务器 http://91.217.139.190:5010, http://91.216.169.75:5010, http://185.80.202.180:5010
通过 http://91.217.139.190:5010/token 获取token
</details>
<details>
<summary>AIWife</summary>
@@ -413,6 +400,18 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 支付宝到账 1
</details>
<details>
<summary>AnimeTrace 动画/Galgame识别</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/animetrace"`
基于[AnimeTrace](https://ai.animedb.cn/)API 的识图搜索插件
- [x] Gal识图 | Gal识图 [模型名]
- [x] 动漫识图 | 动漫识图 2 | 动漫识图 [模型名]
</details>
<details>
<summary>触发者撤回时也自动撤回</summary>
@@ -435,14 +434,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 用yyy解密xxx
</details>
<details>
<summary>百科</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu"`
- [x] 百度/百科/维基/wiki[xxx]
</details>
<details>
<summary>百度内容审核</summary>
@@ -572,16 +563,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 随机书评
</details>
<details>
<summary>藏头诗</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/cangtoushi"`
- [x] 藏头诗[xxx]
- [x] 藏尾诗[xxx]
</details>
<details>
<summary>选择困难症帮手</summary>
@@ -680,20 +661,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 删签[gif签名]
</details>
<details>
<summary>女装</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/dress"`
- [x] 女装
- [x] 男装
- [x] 随机女装
- [x] 随机男装
</details>
<details>
<summary>漂流瓶</summary>
@@ -712,6 +679,16 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] [emoji][emoji]
</details>
<details>
<summary>颜文字抽象转写</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/emozi"`
- [x] 抽象转写[文段]
- [x] 抽象还原[文段]
- [x] 抽象登录[用户名]
</details>
<details>
<summary>好友申请及群聊邀请事件处理</summary>
@@ -817,14 +794,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 下载歌单[网易云歌单链接/ID]到[歌单名称]
- [x] 解除绑定 [歌单名称]
</details>
<details>
<summary>黑丝</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/heisi"`
- [x] 来点黑丝/白丝/jk/巨乳/足控/网红
</details>
<details>
<summary>一言</summary>
@@ -857,14 +826,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 百人一首之n
</details>
<details>
<summary>关键字搜图</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/image_finder"`
- [x] 来张 [xxx]
</details>
<details>
<summary>注入指令</summary>
@@ -883,24 +844,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 更新[屌|弔|吊]图
</details>
<details>
<summary>兽语加密(嗷呜~)</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/jiami"`
- [x] 兽语加密xxx
- [x] 兽语解密xxx
</details>
<details>
<summary>小鸡词典</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/jikipedia"`
- [x] [查梗|小鸡词典][梗]
</details>
<details>
<summary>日语听力学习材料</summary>
@@ -915,14 +858,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 日语歌曲 xxx
</details>
<details>
<summary>绝绝子</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi"`
- [x] 喝奶茶绝绝子 | 绝绝子吃饭
</details>
<details>
<summary>疯狂星期四</summary>
@@ -995,7 +930,7 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 钓鱼商店
- [x] 购买xxx [数量]
- [x] 出售xxx [数量]
- [x] 出售[xxx [数量]|所有垃圾]
- [x] 钓鱼背包
- [x] 装备[xx竿|三叉戟|美西螈]
- [x] 附魔[诱钓|海之眷顾]
@@ -1028,12 +963,18 @@ print("run[CQ:image,file="+j["img"]+"]")
</details>
<details>
<summary>日韩 VITS 模型拟声</summary>
<summary>Minecraft服务器监控&订阅</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/moegoe"`
- [x] 让[派蒙|空|荧|阿贝多|枫原万叶|温迪|八重神子|纳西妲|钟离|诺艾尔|凝光|托马|北斗|莫娜|荒泷一斗|提纳里|芭芭拉|艾尔海森|雷电将军|赛诺|琴|班尼特|五郎|神里绫华|迪希雅|夜兰|辛焱|安柏|宵宫|云堇|妮露|烟绯|鹿野院平藏|凯亚|达达利亚|迪卢克|可莉|早柚|香菱|重云|刻晴|久岐忍|珊瑚宫心海|迪奥娜|戴因斯雷布|魈|神里绫人|丽莎|优菈|凯瑟琳|雷泽|菲谢尔|九条裟罗|甘雨|行秋|胡桃|迪娜泽黛|柯莱|申鹤|砂糖|萍姥姥|奥兹|罗莎莉亚|式大将|哲平|坎蒂丝|托克|留云借风真君|昆钧|塞琉斯|多莉|大肉丸|莱依拉|散兵|拉赫曼|杜拉夫|阿守|玛乔丽|纳比尔|海芭夏|九条镰治|阿娜耶|阿晃|阿扎尔|七七|博士|白术|埃洛伊|大慈树王|女士|丽塔|失落迷迭|缭乱星棘|伊甸|伏特加女孩|狂热蓝调|莉莉娅|萝莎莉娅|八重樱|八重霞|卡莲|第六夜想曲|卡萝尔|姬子|极地战刃|布洛妮娅|次生银翼|理之律者|迷城骇兔|希儿|魇夜星渊|黑希儿|帕朵菲莉丝|天元骑英|幽兰黛尔|德丽莎|月下初拥|朔夜观星|暮光骑士|明日香|李素裳|格蕾修|梅比乌斯|渡鸦|人之律者|爱莉希雅|爱衣|天穹游侠|琪亚娜|空之律者|薪炎之律者|云墨丹心|符华|识之律者|维尔薇|芽衣|雷之律者|阿波尼亚]说(中文)
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/minecraftobserver"`
- [x] mc服务器状态 [服务器IP/URI]
- [x] mc服务器添加订阅 [服务器IP/URI]
- [x] mc服务器取消订阅 [服务器IP/URI]
- [x] mc服务器订阅拉取 (需要插件定时任务配合使用,全局只需要设置一个)
- 使用job插件设置定时, 对话例子如下:
- 记录在"@every 1m"触发的指令
- (机器人回答:您的下一条指令将被记录,在@@every 1m时触发
- mc服务器订阅拉取
</details>
<details>
<summary>摸鱼</summary>
@@ -1096,22 +1037,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- 注:刷新文件夹较慢,请耐心等待刷新完成,会提示“成功”。
</details>
<details>
<summary>抽wife</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/nativewife"`
- [x] 抽wife[@xxx]
- [x] 添加wife[名字][图片]
- [x] 删除wife[名字]
- [x] [让 | 不让]所有人均可添加wife
- 注:不同群添加后不会重叠
</details>
<details>
<summary>拼音首字母释义工具</summary>
@@ -1130,6 +1055,40 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 搜索日语语法 [xxx]
</details>
<details>
<summary>牛牛大作战</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/niuniu" `
- [x] 打胶
- [x] 使用[道具名称]打胶
- [x] jj[@xxx]
- [x] 使用[道具名称]jj[@xxx]
- [x] 赎牛牛
- [x] 牛牛拍卖行
- [x] 出售牛牛
- [x] 牛牛商店
- [x] 牛牛背包
- [x] 注册牛牛
- [x] 注销牛牛
- [x] 牛子长度排行
- [x] 牛子深度排行
- [x] 查看我的牛牛
</details>
<details>
<summary>小说</summary>
@@ -1154,6 +1113,22 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 当图片属于非 neutral 类别时自动发送评价(默认禁用,启用输入 /启用 nsfwauto)
</details>
<details>
<summary>抽wife</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/nwife"`
- [x] 抽wife[@xxx]
- [x] 添加wife[名字][图片]
- [x] 删除wife[名字]
- [x] [让 | 不让]所有人均可添加wife
- 注:不同群添加后不会重叠
</details>
<details>
<summary>浅草寺求签</summary>
@@ -1164,6 +1139,14 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 解签
</details>
<details>
<summary>抽扑克</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/poker"`
- [x] 抽扑克牌
</details>
<details>
<summary>一群一天一夫一妻制群老婆</summary>
@@ -1196,18 +1179,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 重置花名册
</details>
<details>
<summary>权重查询</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/quan"`
- 来看看大家的账号分吧~据说越高越不容易封号哦
- [x] 权重查询+@xxx
- [x] 权重查询+QQ号(为空时匹配触发者QQ)
</details>
<details>
<summary>qq空间表白墙</summary>
@@ -1242,6 +1213,14 @@ print("run[CQ:image,file="+j["img"]+"]")
- 注:本插件来源于[tgbot](https://github.com/YukariChiba/tgbot/blob/main/modules/Reborn.py)
</details>
<details>
<summary>打劫</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/robbery"`
- [x] 打劫[对方Q号|@对方QQ]
</details>
<details>
<summary>在线代码运行</summary>
@@ -1362,14 +1341,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] >TL 你好
</details>
<details>
<summary>vits猫雷</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/vitsnyaru"`
- [x] 让猫雷说[xxxx]
</details>
<details>
<summary>vtb语录</summary>
@@ -1382,33 +1353,23 @@ 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>
- [x] 设置硬币名称[ATRI币]
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun"`
- [x] 管理钱包余额[+金额|-金额][@xxx]
- [x] 来份网易云热评
- [x] 查看我的钱包|查看钱包余额[@xxx]
- [x] 钱包转账[金额][@xxx]
- 注:仅超级用户能"管理钱包余额",
</details>
<details>
@@ -1437,20 +1398,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 警报
- [x] 每日特惠
</details>
<details>
<summary>天气/拼音查询-名言</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenben"`
- [x] xx天气
- [x] xx拼音
- [x] 每日情话/一言/鸡汤
- [x] 绕口令
</details>
<details>
<summary>百度文心AI</summary>
@@ -1616,6 +1563,25 @@ print("run[CQ:image,file="+j["img"]+"]")
### *低优先级*
<details>
<summary>OpenAI聊天</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aichat"`
- [x] 设置AI聊天触发概率10
- [x] 设置AI聊天温度80
- [x] 设置AI聊天接口类型[OpenAI|OLLaMA|GenAI]
- [x] 设置AI聊天(不)支持系统提示词
- [x] 设置AI聊天接口地址https://xxx
- [x] 设置AI聊天密钥xxx
- [x] 设置AI聊天模型名xxx
- [x] 查看AI聊天系统提示词
- [x] 重置AI聊天系统提示词
- [x] 设置AI聊天系统提示词xxx
- [x] 设置AI聊天分隔符`</think>`(留空则清除)
- [x] 设置AI聊天(不)响应AT
</details>
<details>
<summary>骂人</summary>
@@ -1627,19 +1593,7 @@ print("run[CQ:image,file="+j["img"]+"]")
</details>
<details>
<summary>人工智能回复</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply"`
- [x] @Bot 任意文本(任意一句话回复)
- [x] 设置文字回复模式[婧枫|沫沫|青云客|小爱|ChatGPT]
- [x] 设置 ChatGPT api key xxx
</details>
<details>
<summary>词典匹配回复</summary>
<summary>词典匹配回复, 仅@触发</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus"`
@@ -1660,8 +1614,7 @@ print("run[CQ:image,file="+j["img"]+"]")
### 1. 使用稳定版/测试版 (推荐)
可以前往[Release](https://github.com/FloatTech/ZeroBot-Plugin/releases)页面下载对应系统版本可执行文件,编译时开启了全部插件。您还可以选择 [gocqzbp](https://github.com/FloatTech/gocqzbp) 的 [Release](https://github.com/FloatTech/gocqzbp/releases) 或 [Package](https://github.com/FloatTech/gocqzbp/pkgs/container/gocqzbp),它是 [Mrs4s/go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 与本插件的合体。
可以前往[Release](https://github.com/FloatTech/ZeroBot-Plugin/releases)页面下载对应系统版本可执行文件,编译时开启了全部插件。
### 2. 本地直接运行
1. 下载安装最新 [Go](https://studygolang.com/dl) 环境

4
custom/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
!.gitignore
!doc.go
!plugin
*

2
custom/doc.go Normal file
View File

@@ -0,0 +1,2 @@
// Package custom 注册用户自定义插件于此
package custom

2
custom/plugin/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
!.gitignore
*

2
data

Submodule data updated: 9b983625ca...ca3652920a

View File

@@ -14,12 +14,12 @@
}:
buildGoApplication {
pname = "ZeroBot-Plugin";
version = "1.7.6";
version = "1.8.0";
pwd = ./.;
src = ./.;
# spec go version manually bcs
# https://github.com/nix-community/gomod2nix/blob/30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6/builder/default.nix#L130
# do no work
# do not work
go = pkgs.go_1_20;
modules = ./gomod2nix.toml;
}

20
flake.lock generated
View File

@@ -5,11 +5,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1705309234,
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
@@ -28,11 +28,11 @@
]
},
"locked": {
"lastModified": 1705314449,
"narHash": "sha256-yfQQ67dLejP0FLK76LKHbkzcQqNIrux6MFe32MMFGNQ=",
"lastModified": 1741396135,
"narHash": "sha256-wqmdLr7h4Bk8gyKutgaApJKOM8JVvywI5P48NuqJ9Jg=",
"owner": "nix-community",
"repo": "gomod2nix",
"rev": "30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6",
"rev": "0983848bf2a7ccbfe24d874065adb8fd0f23729b",
"type": "github"
},
"original": {
@@ -43,17 +43,17 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1705856552,
"narHash": "sha256-JXfnuEf5Yd6bhMs/uvM67/joxYKoysyE3M2k6T3eWbg=",
"lastModified": 1710843028,
"narHash": "sha256-CMbK45c4nSkGvayiEHFkGFH+doGPbgo3AWfecd2t1Fk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "612f97239e2cc474c13c9dafa0df378058c5ad8d",
"rev": "33c51330782cb486764eb598d5907b43dc87b4c2",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"rev": "33c51330782cb486764eb598d5907b43dc87b4c2",
"type": "github"
}
},

View File

@@ -1,7 +1,8 @@
{
description = " ZeroBot OneBot ";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# pin nixpkgs to preserve dropped go_1_20
inputs.nixpkgs.url = "github:NixOS/nixpkgs/33c51330782cb486764eb598d5907b43dc87b4c2";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.gomod2nix.url = "github:nix-community/gomod2nix";
inputs.gomod2nix.inputs.nixpkgs.follows = "nixpkgs";
@@ -12,8 +13,10 @@
nixpkgs,
flake-utils,
gomod2nix,
}: (
flake-utils.lib.eachDefaultSystem
}: let
allSystems = flake-utils.lib.allSystems;
in (
flake-utils.lib.eachSystem allSystems
(system: let
pkgs = nixpkgs.legacyPackages.${system};
@@ -22,11 +25,26 @@
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;});
packages = rec {
ZeroBot-Plugin =
(callPackage ./. {
inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
})
.overrideAttrs (_: {doCheck = false;});
default = ZeroBot-Plugin;
docker_builder = pkgs.dockerTools.buildLayeredImage {
name = "ZeroBot-Plugin";
tag = "latest";
contents = [
self.packages.${system}.ZeroBot-Plugin
pkgs.cacert
];
};
};
devShells.default = callPackage ./shell.nix {
inherit (gomod2nix.legacyPackages.${system}) mkGoEnv gomod2nix;
};

96
go.mod
View File

@@ -4,103 +4,97 @@ go 1.20
require (
github.com/Baidu-AIP/golang-sdk v1.1.1
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/AnimeAPI v1.7.1-0.20250217140215-4856397458c9
github.com/FloatTech/floatbox v0.0.0-20241106130736-5aea0a935024
github.com/FloatTech/gg v1.1.3
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.6.0
github.com/FloatTech/zbputils v1.7.1-0.20231107124514-083e678fbfe6
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
github.com/FloatTech/rendercard v0.2.0
github.com/FloatTech/sqlite v1.7.1
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562
github.com/FloatTech/zbpctrl v1.7.0
github.com/FloatTech/zbputils v1.7.2-0.20250330125231-d8be1c9d3b9c
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5
github.com/antchfx/htmlquery v1.2.5
github.com/Tnze/go-mc v1.20.2
github.com/antchfx/htmlquery v1.3.4
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/deepinfra v0.0.0-20250330125128-71ec2f7c085e
github.com/fumiama/go-base16384 v1.7.0
github.com/fumiama/go-registry v0.2.6
github.com/fumiama/go-registry v0.2.7
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/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4
github.com/fumiama/terasu v0.0.0-20241027183601-987ab91031ce
github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/google/uuid v1.6.0
github.com/jinzhu/gorm v1.9.16
github.com/jozsefsallai/gophersauce v1.0.1
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5
github.com/lithammer/fuzzysearch v1.1.5
github.com/lithammer/fuzzysearch v1.1.8
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/quic-go/quic-go v0.38.1
github.com/shirou/gopsutil/v3 v3.23.1
github.com/shirou/gopsutil/v3 v3.24.5
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.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
github.com/tidwall/gjson v1.18.0
github.com/wcharczuk/go-chart/v2 v2.1.2
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250330133859-27c25d9412b5
gitlab.com/gomidi/midi/v2 v2.1.7
golang.org/x/image v0.24.0
golang.org/x/sys v0.30.0
golang.org/x/text v0.22.0
gopkg.in/yaml.v3 v3.0.1
)
require (
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/antchfx/xpath v1.3.3 // indirect
github.com/dustin/go-humanize v1.0.1 // 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/go-simple-protobuf v0.2.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-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
github.com/google/uuid v1.3.0 // indirect
github.com/hajimehoshi/oto v0.7.1 // indirect
github.com/jfreymuth/oggvorbis v1.0.1 // indirect
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/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // 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/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/shoenig/go-m1cpu v0.1.6 // 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.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.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
modernc.org/sqlite v1.20.0 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
golang.org/x/exp/shiny v0.0.0-20250305212735-054e65f0b394 // indirect
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a // indirect
golang.org/x/net v0.33.0 // indirect
modernc.org/libc v1.61.0 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.33.1 // indirect
)
replace modernc.org/sqlite => github.com/fumiama/sqlite3 v1.20.0-with-win386
replace modernc.org/sqlite => github.com/fumiama/sqlite3 v1.29.10-simp
replace github.com/remyoudompheng/bigfft => github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b
replace modernc.org/libc => github.com/fumiama/libc v0.0.0-20240530081950-6f6d8586b5c5

293
go.sum
View File

@@ -1,45 +1,42 @@
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/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
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/AnimeAPI v1.7.1-0.20250217140215-4856397458c9 h1:tI9GgG8fdMK2WazFiEbMXAXjwMCckIfDaXbig9B6DdA=
github.com/FloatTech/AnimeAPI v1.7.1-0.20250217140215-4856397458c9/go.mod h1:XXG1eBJf+eeWacQx5azsQKL5Gg7jDYTFyyZGIa/56js=
github.com/FloatTech/floatbox v0.0.0-20241106130736-5aea0a935024 h1:mrvWpiwfRklt9AyiQjKgDGJjf4YL6FZ3yC+ydbkuF2o=
github.com/FloatTech/floatbox v0.0.0-20241106130736-5aea0a935024/go.mod h1:+P3hs+Cvl10/Aj3SNE96TuBvKAXCe+XD1pKphTZyiwk=
github.com/FloatTech/gg v1.1.3 h1:+GlL02lTKsxJQr4WCuNwVxC1/eBZrCvypCIBtxuOFb4=
github.com/FloatTech/gg v1.1.3/go.mod h1:/9oLP54CMfq4r+71XL26uaFTJ1uL1boAyX67680/1HE=
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.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/FloatTech/rendercard v0.2.0 h1:PBTZ2gCEy/dAEGSfWecrGTrWDYpiBJD1dVzNDDaOxh4=
github.com/FloatTech/rendercard v0.2.0/go.mod h1:Sbojcy1t3NfFz7/WicZRmR/uKFxNMYkKF8qHx69dxY0=
github.com/FloatTech/sqlite v1.7.1 h1:XKUY0+MNaRmvEIgRv7QLbl7PFVpUfQ72+XQg+no2Vq0=
github.com/FloatTech/sqlite v1.7.1/go.mod h1:/4tzfCGhrZnnjC1U8vcfwGQeF6eR649fhOsS3+Le0+s=
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562 h1:snfw7FNFym1eNnLrQ/VCf80LiQo9C7jHgrunZDwiRcY=
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
github.com/FloatTech/zbpctrl v1.7.0 h1:Hxo6EIhJo+pHjcQP9QgIJgluaT1pHH99zkk3njqTNMo=
github.com/FloatTech/zbpctrl v1.7.0/go.mod h1:xmM4dSwHA02Gei3ogCRiG+RTrw/7Z69PfrN5NYf8BPE=
github.com/FloatTech/zbputils v1.7.2-0.20250330125231-d8be1c9d3b9c h1:nIybmanPvQknseVOJ+s4/m3q7EZxtqMoTy3wiiZts6E=
github.com/FloatTech/zbputils v1.7.2-0.20250330125231-d8be1c9d3b9c/go.mod h1:ArZ0fMAcmPEIXOqDmfzbSx+oYH8sssApQnbCu694iS8=
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/syncx v0.0.0-20240418144900-b7402ffdebc7 h1:S/ferNiehVjNaBMNNBxUjLtVmP/YWD6Yh79RfPv4ehU=
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7/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/Tnze/go-mc v1.20.2 h1:arHCE/WxLCxY73C/4ZNLdOymRYtdwoXE05ohB7HVN6Q=
github.com/Tnze/go-mc v1.20.2/go.mod h1:geoRj2HsXSkB3FJBuhr7wCzXegRlzWsVXd7h7jiJ6aQ=
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=
github.com/antchfx/xpath v1.2.1 h1:qhp4EW6aCOVr5XIkT+l6LJ9ck/JsUH/yyauNgTQkBF8=
github.com/antchfx/xpath v1.2.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/antchfx/htmlquery v1.3.4 h1:Isd0srPkni2iNTWCwVj/72t7uCphFeor5Q8nCzj1jdQ=
github.com/antchfx/htmlquery v1.3.4/go.mod h1:K9os0BwIEmLAvTqaNSua8tXLWRWZpocZIH73OzWQbwM=
github.com/antchfx/xpath v1.3.3 h1:tmuPQa1Uye0Ym1Zn65vxPgfltWb/Lxu2jeqIGteJSRs=
github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI=
github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
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=
@@ -50,6 +47,8 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6RO
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 h1:BBade+JlV/f7JstZ4pitd4tHhpN+w+6I+LyOS7B4fyU=
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4/go.mod h1:H7chHJglrhPPzetLdzBleF8d22WYOv7UM/lEKYiwlKM=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
@@ -58,16 +57,16 @@ github.com/faiface/beep v1.1.0 h1:A2gWP6xf5Rh7RG/p9/VAW2jRSDEGQm5sbOb38sf5d4c=
github.com/faiface/beep v1.1.0/go.mod h1:6I8p6kK2q4opL/eWb+kAkk38ehnTunWeToJB+s51sT4=
github.com/fumiama/ahsai v0.1.0 h1:LXD61Kaj6kJHa3AEGsLIfKNzcgaVxg7JB72OR4yNNZ4=
github.com/fumiama/ahsai v0.1.0/go.mod h1:fFeNnqgo44i8FIaguK659aQryuZeFy+4klYLQu/rfdk=
github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b h1:Zt3pFQditAdWTHCOVkiloc9ZauBoWrb37guFV4iIRvE=
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/deepinfra v0.0.0-20250330125128-71ec2f7c085e h1:L/Z5N6UfpuqNIiPUrjSzmrnWj3mjd3auwl/2ctpGXNY=
github.com/fumiama/deepinfra v0.0.0-20250330125128-71ec2f7c085e/go.mod h1:wW05PQSn8mo1mZIoa6LBUE+3xIBjkoONvnfPTV5ZOhY=
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/go-registry v0.2.7 h1:tLEqgEpsiybQMqBv0dLHm5leia/z1DhajMupwnOHeNs=
github.com/fumiama/go-registry v0.2.7/go.mod h1:m+wp5fF8dYgVoFkBPZl+vlK90loymaJE0JCtocVQLEs=
github.com/fumiama/go-simple-protobuf v0.2.0 h1:ACyN1MAlu7pDR3EszWgzUeNP+IRsSHwH6V9JCJA5R5o=
github.com/fumiama/go-simple-protobuf v0.2.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=
@@ -76,10 +75,16 @@ 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=
github.com/fumiama/sqlite3 v1.20.0-with-win386/go.mod h1:Os58MHwYCcYZCy2PGChBrQtBAw5/LS1ZZOkfc+C/I7s=
github.com/fumiama/unibase2n v0.0.0-20221020155353-02876e777430 h1:XL4SnagpaVHYybnnj6whQxmt8Ps9/kaG6sCNn4X1GGA=
github.com/fumiama/unibase2n v0.0.0-20221020155353-02876e777430/go.mod h1:lEaZsT4FRSqcjnQ5q8y+mkenkzR/r1D3BJmfdp0vqDg=
github.com/fumiama/libc v0.0.0-20240530081950-6f6d8586b5c5 h1:jDxsIupsT84A6WHcs6kWbst+KqrRQ8/o0VyoFMnbBOA=
github.com/fumiama/libc v0.0.0-20240530081950-6f6d8586b5c5/go.mod h1:15P6ublJ9FJR8YQCGy8DeQ2Uwur7iW9Hserr/T3OFZE=
github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4 h1:zN9e09TYKXI1mNkuS6YbH+Sn+4k5tBir+ovhZZcRYAs=
github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4/go.mod h1:iZf1H/Jcw5gjOOFb4C5nlweJtViWc7uwUxRCe14pbYk=
github.com/fumiama/sqlite3 v1.29.10-simp h1:c5y3uKyU0q9t0/SyfynzYyuslQ5zP+5CD8e0yYY554A=
github.com/fumiama/sqlite3 v1.29.10-simp/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA=
github.com/fumiama/terasu v0.0.0-20241027183601-987ab91031ce h1:T6iDDU16rFyxV/FwfJJR6qcgkIlXJEIFlUTSmTD1h6s=
github.com/fumiama/terasu v0.0.0-20241027183601-987ab91031ce/go.mod h1:UVx8YP1jKKL1Cj+uy+OnQRM2Ih6U36Mqy9GSf7jabsI=
github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6 h1:LtDgr628eji8jRpjPCxsk7ibjcfi97QieZVCTjxLCBw=
github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6/go.mod h1:lEaZsT4FRSqcjnQ5q8y+mkenkzR/r1D3BJmfdp0vqDg=
github.com/gabriel-vasile/mimetype v1.0.4 h1:uBejfH8l3/2f+5vjl1e4xIaSyNEhRBZ5N/ij7ohpNd8=
github.com/gabriel-vasile/mimetype v1.0.4/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
@@ -87,36 +92,26 @@ 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-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=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/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.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=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hajimehoshi/go-mp3 v0.3.0/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto v0.7.1 h1:I7maFPz5MBCwiutOrz++DLdbr4rTzBsbBuV2VpgU9kk=
github.com/hajimehoshi/oto v0.7.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/icza/bitio v1.0.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A=
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA=
github.com/jfreymuth/oggvorbis v1.0.1 h1:NT0eXBgE2WHzu6RT/6zcb2H10Kxj6Fm3PccT0LE6bqw=
@@ -133,17 +128,10 @@ github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEk
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/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q=
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
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=
@@ -153,8 +141,8 @@ github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5/go.mod h1:7KaV9YIR92M1F
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/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-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
@@ -162,16 +150,14 @@ github.com/mewkiz/flac v1.0.7/go.mod h1:yU74UH277dBUpqxPouHSQIar3G1X/QIclVbFahSd
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2/go.mod h1:3E2FUC/qYUfM8+r9zAwpeHJzqRVVMIYnpzD/clwWxyA=
github.com/mroth/weightedrand v1.0.0 h1:V8JeHChvl2MP1sAoXq4brElOcza+jxLkRuwvtQu8L3E=
github.com/mroth/weightedrand v1.0.0/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
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/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=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -181,148 +167,157 @@ 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.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4=
github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
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.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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
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/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
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.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/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/wcharczuk/go-chart/v2 v2.1.2 h1:Y17/oYNuXwZg6TFag06qe8sBajwwsuvPiJJXcUcLL6E=
github.com/wcharczuk/go-chart/v2 v2.1.2/go.mod h1:Zi4hbaqlWpYajnXB2K22IUYVXRXaLfSGNNR7P4ukyyQ=
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250330133859-27c25d9412b5 h1:HsMcBsVpYuQv+W8pjX5WdwYROrFQP9c5Pbf4x4adDus=
github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250330133859-27c25d9412b5/go.mod h1:C86nQ0gIdAri4K2vg8IIQIslt08zzrKMcqYt8zhkx1M=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
gitlab.com/gomidi/midi/v2 v2.0.25 h1:dkzVBqbaFHjyWwP71MrQNX7IeRUIDonddmHbPpO/Ucg=
gitlab.com/gomidi/midi/v2 v2.0.25/go.mod h1:quTyMKSQ4Klevxu6gY4gy2USbeZra0fV5SalndmPfsY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
gitlab.com/gomidi/midi/v2 v2.1.7 h1:lIjVXH+bnGG04j/kUVOFILt0BQvBeGz8Kyz0l6aM830=
gitlab.com/gomidi/midi/v2 v2.1.7/go.mod h1:Cj6K9VH5GhYvPgL2JddxHBmZiP3nxKxB5XyTxiXvL9U=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-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/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/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
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-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/exp/shiny v0.0.0-20250305212735-054e65f0b394 h1:bFYqOIMdeiCEdzPJkLiOoMDzW/v3tjW4AA/RmUZYsL8=
golang.org/x/exp/shiny v0.0.0-20250305212735-054e65f0b394/go.mod h1:ygj7T6vSGhhm/9yTpOQQNvuAUFziTH7RUiH74EoE2C8=
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.3.0 h1:HTDXbdK9bjfSWkPzDJIw89W8CAtfFGduujWs33NLLsg=
golang.org/x/image v0.3.0/go.mod h1:fXd9211C/0VTlYuAcOhW8dY/RtEJqODXOWBDpmYBf+A=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f h1:kgfVkAEEQXXQ0qc6dH7n6y37NAYmTFmz0YRwrRjgxKw=
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
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/mobile v0.0.0-20231127183840-76ac6878050a h1:sYbmY3FwUWCBTodZL1S3JUuOvaW6kM2o+clDzzDNBWg=
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a/go.mod h1:Ede7gF0KGoHlj822RtphAHK1jLdrcuRBZg0sF1Q+SPc=
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/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-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.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
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=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
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/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
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/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
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/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/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
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.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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=
modernc.org/libc v1.21.5 h1:xBkU9fnHV+hvZuPSRszN0AXDG4M7nwPLwTWwkYcvLCI=
modernc.org/libc v1.21.5/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk=
modernc.org/ccgo/v4 v4.17.8 h1:yyWBf2ipA0Y9GGz/MmCmi3EFpKgeS7ICrAFes+suEbs=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=

View File

@@ -5,38 +5,41 @@ schema = 3
version = "v1.1.1"
hash = "sha256-hKshA0K92bKuK92mmtM0osVmqLJcSbeobeWSDpQoRCo="
[mod."github.com/FloatTech/AnimeAPI"]
version = "v1.7.1-0.20231017135344-aefd1d56e900"
hash = "sha256-YV9VQ7bA8R5g5dcAsbzS6MicVwDgMu08d9GF4uqXH7M="
version = "v1.7.1-0.20250217140215-4856397458c9"
hash = "sha256-7TkWoVslfzO/aTx+F7UwttrtBGGMMqe4GHN0aF4JUd0="
[mod."github.com/FloatTech/floatbox"]
version = "v0.0.0-20231107124407-e38535efa2a2"
hash = "sha256-B86GBuJAjeFjhAjNbBF6OO6DTH2/fpPkrdQynwX+sxg="
version = "v0.0.0-20241106130736-5aea0a935024"
hash = "sha256-hSKmkzpNZwXRo0qm4G+1lXkNzWMwV9leYlYLQuzWx3M="
[mod."github.com/FloatTech/gg"]
version = "v1.1.3-0.20230226151425-6ea91286ba08"
hash = "sha256-AeMzjMK1ZwFERb5xuNAV5PdHp7rzoT4ZF7kZ6Kj2/0s="
version = "v1.1.3"
hash = "sha256-7K/R2mKjUHVnoJ3b1wDObJ5Un2Htj59Y97G1Ja1tuPo="
[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="
version = "v0.2.0"
hash = "sha256-fgntEYGh2mEl618hM13kb0GGeQEXdP+lochYX8F2OXs="
[mod."github.com/FloatTech/sqlite"]
version = "v1.6.3"
hash = "sha256-zWPByEMi89ms67ubPg0fAPIRxfpBC2IRKc0iNVLqkPU="
version = "v1.7.1"
hash = "sha256-1x8xH5fFDlLts8YfzgO3vLF45Q7Ah+mYI6Wn8JG/qE0="
[mod."github.com/FloatTech/ttl"]
version = "v0.0.0-20220715042055-15612be72f5b"
hash = "sha256-vVQTn7f2dFPNrLqutWbeHMCpEdNi7uPxUzpphzaYPpM="
version = "v0.0.0-20240716161252-965925764562"
hash = "sha256-/XjfdVXEzYgeM+OYuyy76tf13lO91vCcwpjWgkRGteU="
[mod."github.com/FloatTech/zbpctrl"]
version = "v1.6.0"
hash = "sha256-2ZPGFvSgTWcPOo8+p8kmg590HY2b8v/L3674ba+b7+A="
version = "v1.7.0"
hash = "sha256-HDDnE0oktWJH1tkxuQwUUbeJhmVwY5fyc/vR72D2mkU="
[mod."github.com/FloatTech/zbputils"]
version = "v1.7.1-0.20231107124514-083e678fbfe6"
hash = "sha256-Bg3aAI8oDx71kWielITcK5Rg2H47/DQZX+4+dO5AtK4="
version = "v1.7.2-0.20250330125231-d8be1c9d3b9c"
hash = "sha256-v2ueCLEwy6oqF8HoxodDHcNOeDPzKn+7fiYSC2L2/e4="
[mod."github.com/RomiChan/syncx"]
version = "v0.0.0-20221202055724-5f842c53020e"
hash = "sha256-FbmvziRRDEzeXW17IQdyWMWsCVq4fvwKGjbFZqJKAMQ="
version = "v0.0.0-20240418144900-b7402ffdebc7"
hash = "sha256-L1j1vgiwqXpF9pjMoRRlrQUHzoULisw/01plaEAwxs4="
[mod."github.com/RomiChan/websocket"]
version = "v1.4.3-0.20220227141055-9b2c6168c9c5"
hash = "sha256-Adx+gvqB+CCoUXx7ebIaBDjVkav+wS5qZPmaqcApBWA="
[mod."github.com/Tnze/go-mc"]
version = "v1.20.2"
hash = "sha256-Nu4PXNxeARH0itm6yIIplFaywL2yQnPJFksmmuyIptI="
[mod."github.com/adamzy/cedar-go"]
version = "v0.0.0-20170805034717-80a9c64b256d"
hash = "sha256-N19KTxh70IUBqnchFuWkrJD8uuFOIVqv1iSuN3YFIT0="
@@ -44,11 +47,11 @@ schema = 3
version = "v0.0.0-20200320125537-f189e35d30ca"
hash = "sha256-ALeRuEJN9jHjGb4wNKJcxC59vVx8Tj7hHikEGkaZZ0s="
[mod."github.com/antchfx/htmlquery"]
version = "v1.2.5"
hash = "sha256-lkpdz+NNHadn0VIshszAZS5ZodOic0sp2d7VN6sIl/M="
version = "v1.3.4"
hash = "sha256-nrtIgRgdOvo0iIQyrhHOFKOmoT8e2gduUsct3f5zDNA="
[mod."github.com/antchfx/xpath"]
version = "v1.2.1"
hash = "sha256-ffHNkJiraDyjy6NsFDNTfqreiY+DER/93J/i11xUPw8="
version = "v1.3.3"
hash = "sha256-Ent9bgBTjKS8/61LKrIu/JcBI/Qsv6EEIojwsMjCgdY="
[mod."github.com/corona10/goimagehash"]
version = "v1.1.0"
hash = "sha256-HyS8nc7kUNnDaVBDzJ9Ym4pRs83YB4M2vHSRwfm6mr4="
@@ -58,6 +61,9 @@ schema = 3
[mod."github.com/disintegration/imaging"]
version = "v1.6.2"
hash = "sha256-pSeMTPvSkxlthh65LjNYYhPLvCZDkBgVgAGYWW0Aguo="
[mod."github.com/dustin/go-humanize"]
version = "v1.0.1"
hash = "sha256-yuvxYYngpfVkUg9yAmG99IUVmADTQA0tMbBXe0Fq0Mc="
[mod."github.com/ericpauley/go-quantize"]
version = "v0.0.0-20200331213906-ae555eb2afa4"
hash = "sha256-sMN6D7IlDpDqUWM8ppoE5Sdb7DvLAJaN6qAucBWJ3rs="
@@ -70,15 +76,18 @@ schema = 3
[mod."github.com/fumiama/cron"]
version = "v1.3.0"
hash = "sha256-/sN7X8dKXQgv8J+EDzVUB+o+AY9gBC8e1C6sYhaTy1k="
[mod."github.com/fumiama/deepinfra"]
version = "v0.0.0-20250330125128-71ec2f7c085e"
hash = "sha256-O7Om4mIcBB2zdVxaeKh7qHbiG83gVLP+f8vxSF17kCw="
[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="
version = "v0.2.7"
hash = "sha256-Rjl+z0Hlp2LMi8+pnFe5HrxctyHMi7UPiK33g/OgLdA="
[mod."github.com/fumiama/go-simple-protobuf"]
version = "v0.1.0"
hash = "sha256-itOBeIU4PRBANDP79eRWlCDNhNUnde6dgcpUlUbm0zU="
version = "v0.2.0"
hash = "sha256-2kULBi1sXsFDX2g/KRFmCGkwF60o/UXacNUbIYa/cvw="
[mod."github.com/fumiama/gofastTEA"]
version = "v0.0.10"
hash = "sha256-FOCbkXoS8s/K54yZbhX5pmaN/ouELnCHZoNS8a90VAg="
@@ -91,33 +100,30 @@ schema = 3
[mod."github.com/fumiama/jieba"]
version = "v0.0.0-20221203025406-36c17a10b565"
hash = "sha256-DvDx1pdldkdaSszrbadM/VwqT9TTSmWl6G6a+ysXYEM="
[mod."github.com/fumiama/slowdo"]
version = "v0.0.0-20241001074058-27c4fe5259a4"
hash = "sha256-rsV3MKRCSOBMIgJXFCGbCHRY2aBAb32ftU49hT3GjqY="
[mod."github.com/fumiama/terasu"]
version = "v0.0.0-20241027183601-987ab91031ce"
hash = "sha256-WiG5BD1Icwq61KpqkQdf6dl64jEhaDJb2zAQROqXwvc="
[mod."github.com/fumiama/unibase2n"]
version = "v0.0.0-20221020155353-02876e777430"
hash = "sha256-//vCLy5/vgId7m9WnRGqmh/wnglboiYz2YzQruIe97o="
version = "v0.0.0-20240530074540-ec743fd5a6d6"
hash = "sha256-I3xNzjrj5y0fy0dfa75V57GanfmHIHmubEn9/y0BBHw="
[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="
version = "v1.6.0"
hash = "sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw="
[mod."github.com/hajimehoshi/oto"]
version = "v0.7.1"
hash = "sha256-eRgbEbsziY5F0oI7wAe29FepZG7uGmq2M4deouDHcXI="
@@ -139,12 +145,9 @@ schema = 3
[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="
version = "v1.1.8"
hash = "sha256-aMMRcrlUc9CBiiNkcnWWn4hfNMNyVhrAt67kvP4D4Do="
[mod."github.com/liuzl/cedar-go"]
version = "v0.0.0-20170805034717-80a9c64b256d"
hash = "sha256-N19KTxh70IUBqnchFuWkrJD8uuFOIVqv1iSuN3YFIT0="
@@ -158,20 +161,20 @@ schema = 3
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="
version = "v0.0.20"
hash = "sha256-qhw9hWtU5wnyFyuMbKx+7RB8ckQaFQ8D+8GKPkN3HHQ="
[mod."github.com/mroth/weightedrand"]
version = "v1.0.0"
hash = "sha256-bP+yIaBUY5+oI455mNM8zh14z/SNPaQg44L3RJ0/v/c="
[mod."github.com/ncruces/go-strftime"]
version = "v0.1.9"
hash = "sha256-T0iw+UEckzueWHT88PkTnZZixyKCEa+DTLzIiiohuWY="
[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="
@@ -184,22 +187,15 @@ schema = 3
[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"
version = "v0.0.0-20230129092748-24d4a6f8daec"
hash = "sha256-vYmpyCE37eBYP/navhaLV4oX4/nu0Z/StAocLIFqrmM="
[mod."github.com/shirou/gopsutil/v3"]
version = "v3.23.1"
hash = "sha256-DYoN9o+PGrnYev7i+NISAKEqFdCKpimpi4s0FWmFpkY="
version = "v3.24.5"
hash = "sha256-tc+t1u7gf5A+Bd956dYeM8pGbxs9ezQHqKAKfLQLpuQ="
[mod."github.com/shoenig/go-m1cpu"]
version = "v0.1.6"
hash = "sha256-hT+JP30BBllsXosK/lo89HV/uxxPLsUyO3dRaDiLnCg="
[mod."github.com/sirupsen/logrus"]
version = "v1.9.3"
hash = "sha256-EnxsWdEUPYid+aZ9H4/iMTs1XMvCLbXZRDyvj89Ebms="
@@ -207,8 +203,8 @@ schema = 3
version = "v1.5.0"
hash = "sha256-fGdJM4LJrZA9jxHuYVo4EUQ3I1k0IVG3QQCBCgZkeZI="
[mod."github.com/tidwall/gjson"]
version = "v1.14.4"
hash = "sha256-3DS2YNL95wG0qSajgRtIABD32J+oblaKVk8LIw+KSOc="
version = "v1.18.0"
hash = "sha256-CO6hqDu8Y58Po6A01e5iTpwiUBQ5khUZsw7czaJHw0I="
[mod."github.com/tidwall/match"]
version = "v1.1.1"
hash = "sha256-M2klhPId3Q3T3VGkSbOkYl/2nLHnsG+yMbXkPkyrRdg="
@@ -216,69 +212,55 @@ schema = 3
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="
version = "v0.3.12"
hash = "sha256-91VBZNb3L2TZkEETF1AE4wnraLoGxKeofUbC5ZiWVHk="
[mod."github.com/tklauser/numcpus"]
version = "v0.6.0"
hash = "sha256-6jssTsP5L6yVl43tXfqDdgeI+tEkBp3BpiWwKXLTHAM="
version = "v0.6.1"
hash = "sha256-8eFcw4YI0w6+GPhU5xMMQjiio94q/O5PpNO3QsvXve0="
[mod."github.com/wcharczuk/go-chart/v2"]
version = "v2.1.0"
hash = "sha256-0s07aT7i3zMyVaS1hHO6SaCilVy39HwC8Po6wcENn9E="
version = "v2.1.2"
hash = "sha256-GXWWea/u6BezTsPPrWhTYiTetPP/YW6P+Sj4YdocPaM="
[mod."github.com/wdvxdr1123/ZeroBot"]
version = "v1.7.5-0.20231009162356-57f71b9f5258"
hash = "sha256-sIrH0WUDJeEGMD8FWh8UyrI3aHNN6NT7l+/isSl3ico="
version = "v1.8.2-0.20250330133859-27c25d9412b5"
hash = "sha256-gT3uFTg5E0Th3r1M1vLzr0QtOjbMusqEjD/ckoBdDFc="
[mod."github.com/yusufpapurcu/wmi"]
version = "v1.2.2"
hash = "sha256-Rno6F82JIeglBobQl6YKl3U6+FvWXmFavJlzpOJgoXI="
version = "v1.2.4"
hash = "sha256-N+YDBjOW59YOsZ2lRBVtFsEEi48KhNQRb63/0ZSU3bA="
[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="
version = "v2.1.7"
hash = "sha256-fbgxSMCk7PVII3sNEKuGWbN56fy3eM564Xb+lnYTxRQ="
[mod."golang.org/x/exp/shiny"]
version = "v0.0.0-20221126150942-6ab00d035af9"
hash = "sha256-+OAzuS+wyjOBSarGBuHjMeQV3vZzTbmF7CH8wnE7aA8="
version = "v0.0.0-20250305212735-054e65f0b394"
hash = "sha256-+xzaSlgRHFa+sGnQG90/72vcJMhletsob/L+KG24P/A="
[mod."golang.org/x/image"]
version = "v0.3.0"
hash = "sha256-d6/w/CwI5GRGjuOGA7L7x4rEPfcHAVV3ZzsKxKmMYR4="
version = "v0.24.0"
hash = "sha256-nhcznNf4ePM7d0Jy2Si0dpMt7KQfRF5Y5QzMpwFCAVg="
[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="
version = "v0.0.0-20231127183840-76ac6878050a"
hash = "sha256-GdXSvrqQiJX6pOqc2Yr8gG0ZWysEE81YRl5qkt3JCMA="
[mod."golang.org/x/net"]
version = "v0.10.0"
hash = "sha256-HkGiUYBZOBdOtt7mYo3N3swFjjAXzW++pG2JeWGJR9Q="
version = "v0.33.0"
hash = "sha256-9swkU9vp6IflUUqAzK+y8PytSmrKLuryidP3RmRfe0w="
[mod."golang.org/x/sys"]
version = "v0.8.0"
hash = "sha256-wLPPnoFkHM1HPUaFIfRyQZOJjrqXVZimB0nMySly7Xg="
version = "v0.30.0"
hash = "sha256-BuhWtwDkciVioc03rxty6G2vcZVnPX85lI7tgQOFVP8="
[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="
version = "v0.22.0"
hash = "sha256-kUwLNFk9K/YuWmO5/u2IshrmhT2CCuk+mAShSlTTeZo="
[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="
version = "v0.0.0-20240530081950-6f6d8586b5c5"
hash = "sha256-SJYYRaiDUmIbqy9l/IgiT/4VkFsPYsaslqGEowut34w="
replaced = "github.com/fumiama/libc"
[mod."modernc.org/mathutil"]
version = "v1.5.0"
hash = "sha256-5xM9HjjHf9sB0vLfN53PdGpT0qPF1+KI1/lgN0/4LQo="
version = "v1.6.0"
hash = "sha256-lfuEiS1odd2TWrTylnaGihSJ9myqKs3FLdpvd7PqTnE="
[mod."modernc.org/memory"]
version = "v1.4.0"
hash = "sha256-x78QWQ1H82eolL7JiG6eP6l4fHhRNyIlSryQKpibcBo="
version = "v1.8.0"
hash = "sha256-ucvPr73zg8LjvU+bcoIPKTgwgcon3U9VhKrLEMH81xg="
[mod."modernc.org/sqlite"]
version = "v1.20.0-with-win386"
hash = "sha256-ICV8xqeBvySJtmVV4DpqihUyRbXdaq11ba+UvMltFn8="
version = "v1.29.10-simp"
hash = "sha256-HCUVN6gZDG0g2WIsQ4ksqE1+XR1IjxvnqEBEU2MO1eE="
replaced = "github.com/fumiama/sqlite3"

View File

@@ -3,13 +3,13 @@
package banner
// Version ...
var Version = "v1.7.8"
var Version = "v1.9.6"
// Copyright ...
var Copyright = "© 2020 - 2024 FloatTech"
var Copyright = "© 2020 - 2025 FloatTech"
// Banner ...
var Banner = "* OneBot + ZeroBot + Golang\n" +
"* Version " + Version + " - 2024-04-30 17:51:12 +0900 JST\n" +
"* Version " + Version + " - 2025-03-30 23:46:38 +0900 JST\n" +
"* Copyright " + Copyright + ". All Rights Reserved.\n" +
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"

188
main.go
View File

@@ -34,6 +34,8 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat" // 基础词库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chatcount" // 聊天时长统计
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleepmanage" // 统计睡眠时间
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri" // ATRI词库
@@ -60,100 +62,92 @@ import (
// vvvvvvvvvvvvvv //
// vvvv //
_ "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/custom" // 自定义插件合集
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ahsai" // ahsai tts
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aifalse" // 服务器监控
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/alipayvoice" // 支付宝到账语音
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/animetrace" // AnimeTrace 动画/Galgame识别
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/autowithdraw" // 触发者撤回时也自动撤回
_ "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/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/driftbottle" // 漂流瓶
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/emojimix" // 合成emoji
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/emozi" // 颜文字抽象转写
_ "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/hitokoto" // 一言
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs" // 炉石
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hyaku" // 百人一首
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/inject" // 注入指令
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jandan" // 煎蛋网无聊图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jptingroom" // 日语听力学习材料
_ "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/minecraftobserver" // Minecraft服务器监控&订阅
_ "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/niuniu" // 牛牛大作战
_ "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/poker" // 抽扑克
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife" // 一群一天一夫一妻制群老婆
_ "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/robbery" // 打劫群友的ATRI币
_ "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/wallet" // 钱包
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wantquotes" // 据意查句
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/warframeapi" // warframeAPI插件
_ "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/wtf" // 鬼东西
@@ -175,9 +169,9 @@ import (
// vvvvvvvvvvvvvv //
// vvvv //
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/curse" // 骂人
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aichat" // AI聊天
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply" // 人工智能回复
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/curse" //
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
@@ -195,6 +189,7 @@ import (
// //
// //
// -----------------------以下为内置依赖,勿动------------------------ //
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/process"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
@@ -235,6 +230,7 @@ func init() {
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.BoolVar(&file.SkipOriginal, "mirror", false, "Use mirrored lazy data at first")
flag.Parse()

View File

@@ -1,285 +0,0 @@
package aireply
import (
"errors"
"strings"
"github.com/RomiChan/syncx"
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/lolimi"
"github.com/FloatTech/AnimeAPI/tts/ttscn"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
)
// 数据结构: [8 bits] [8 bits] [8 bits]
// [具体人物] [tts模式] [回复模式]
// defaultttsindexkey
// 数据结构: [8 bits] [8 bits]
// [具体人物] [tts模式]
// [tts模式]: 0~200 genshin 201 baidu 202 ttscn 203 lolimi
const (
baiduttsindex = 201 + iota
ttscnttsindex
lolimittsindex
)
// 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")
)
type replymode []string
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 r {
if s == name {
ok = true
index = int64(i)
break
}
}
if !ok {
return errors.New("no such mode")
}
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
return errors.New("no such plugin")
}
return m.SetData(gid, (m.GetData(gid)&^0xff)|(index&0xff))
}
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 {
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.NewLolimiAi(aireply.JingfengURL, aireply.JingfengBotName)
}
var ttsins = func() map[string]tts.TTS {
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, baiduttsindex-len(genshin.SoundList))...) // 0-200
s = append(s, extrattsname...) // 201 202 ...
return s
}()
type ttsmode syncx.Map[int64, int64]
func list(list []string, num int) string {
s := ""
for i, value := range list {
s += value
if (i+1)%num == 0 {
s += "\n"
} else {
s += " | "
}
}
return s
}
func newttsmode() *ttsmode {
t := &ttsmode{}
m, ok := control.Lookup("tts")
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, 0)
if ok {
index := m.GetData(defaultttsindexkey)
msk := index & 0xff
if msk >= 0 && (msk < int64(len(ttsModes))) {
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, index)
}
}
return t
}
func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, character int) error {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
_, ok := ttsins[name]
if !ok {
return errors.New("不支持设置语音人物" + name)
}
var index = int64(-1)
for i, s := range genshin.SoundList {
if s == name {
index = int64(i + 1)
break
}
}
if index == -1 {
switch name {
case extrattsname[0]:
index = baiduttsindex
case extrattsname[1]:
index = ttscnttsindex
case extrattsname[2]:
index = lolimittsindex
default:
return errors.New("语音人物" + name + "未注册index")
}
}
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
// 按原来的逻辑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) {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
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(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 extrattsname[0]:
id, sec, _ := strings.Cut(.k, ",")
ins = baidutts.NewBaiduTTS(int(i&0xff00)>>8, id, sec)
case extrattsname[1]:
var err error
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 := .k
if k != "" {
ins = genshin.NewGenshin(int(m-1), .k)
ttsins[mode] = ins
} else {
ins = lolimi.NewLolimi(int(i&0xff00) >> 8)
}
}
}
return ins, nil
}
func (t *ttsmode) resetSoundMode(ctx *zero.Ctx) error {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
// 只保留后面8位
(*syncx.Map[int64, int64])(t).Delete(gid)
return m.SetData(gid, (m.GetData(gid) & 0xff)) // 重置数据
}
func (t *ttsmode) setDefaultSoundMode(name string, character int) error {
_, ok := ttsins[name]
if !ok {
return errors.New("不支持设置语音人物" + name)
}
index := int64(-1)
for i, s := range genshin.SoundList {
if s == name {
index = int64(i + 1)
break
}
}
if index == -1 {
switch name {
case extrattsname[0]:
index = baiduttsindex
case extrattsname[1]:
index = ttscnttsindex
case extrattsname[2]:
index = lolimittsindex
default:
return errors.New("语音人物" + name + "未注册index")
}
}
m, ok := control.Lookup("tts")
if !ok {
return errors.New("[tts] service not found")
}
storeIndex := (index & 0xff) | ((int64(character) << 8) & 0xff00)
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, storeIndex)
return m.SetData(defaultttsindexkey, storeIndex)
}

View File

@@ -1,227 +0,0 @@
// Package aireply AI 回复
package aireply
import (
"os"
"regexp"
"strconv"
"strings"
"time"
"github.com/FloatTech/AnimeAPI/tts/genshin"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var replmd = replymode([]string{"婧枫", "沫沫", "青云客", "小爱", "ChatGPT"})
var ttsmd = newttsmode()
func init() { // 插件主体
ent := control.Register("tts", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Brief: "人工智能语音回复",
Help: "- @Bot 任意文本(任意一句话回复)\n" +
"- 设置语音模式[原神人物/百度/TTSCN/桑帛云] 数字(百度/TTSCN说话人/桑帛云)\n" +
"- 设置默认语音模式[原神人物/百度/TTSCN/桑帛云] 数字(百度/TTSCN说话人/桑帛云)\n" +
"- 恢复成默认语音模式\n" +
"- 设置语音回复模式[沫沫|婧枫|青云客|小爱|ChatGPT]\n" +
"- 设置原神语音 api key xxxxxx (key请加开发群获得)\n" +
"- 设置百度语音 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- 设置文字回复模式[婧枫|沫沫|青云客|小爱|ChatGPT]\n- 设置 ChatGPT api key xxx",
PrivateDataFolder: "aireply",
})
enr.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
aireply := replmd.getReplyMode(ctx)
reply := message.ParseMessageFromString(aireply.Talk(ctx.Event.UserID, ctx.ExtractPlainText(), zero.BotConfig.NickName[0]))
// 回复
time.Sleep(time.Second * 1)
reply = append(reply, message.Reply(ctx.Event.MessageID))
ctx.Send(reply)
})
setReplyMode := func(ctx *zero.Ctx) {
param := ctx.State["args"].(string)
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 := replmd.getReplyMode(ctx)
// 获取回复的文本
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 := ttsmd.getSoundMode(ctx)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
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(plainReply))
return
}
// 发送语音
if id := ctx.SendChain(message.Record(rec)); id.ID() == 0 {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(plainReply))
}
})
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
var err error
if num != "" {
n, err = strconv.Atoi(num)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
}
// 保存设置
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
}
banner := genshin.TestRecord[param]
if banner == "" {
banner = genshin.TestRecord["默认"]
}
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) {
param := ctx.State["regex_matched"].([]string)[1]
num := ctx.State["regex_matched"].([]string)[2]
n := 0
var err error
if num != "" {
n, err = strconv.Atoi(num)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
}
// 保存设置
err = ttsmd.setDefaultSoundMode(param, n)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功"))
})
ent.OnFullMatch("恢复成默认语音模式", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
err := ttsmd.resetSoundMode(ctx)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
// 设置验证
speaker, err := ttsmd.getSoundMode(ctx)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前为", speaker))
})
ent.OnRegex(`^设置原神语音\s*api\s*key\s*([0-9a-zA-Z-_]{54}==)$`, 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("设置成功"))
})
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
}
ctx.SendChain(message.Text("设置成功"))
})
}

View File

@@ -1,29 +0,0 @@
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)
}

96
plugin/aichat/cfg.go Normal file
View File

@@ -0,0 +1,96 @@
package aichat
import (
"strings"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/chat"
"github.com/fumiama/deepinfra"
"github.com/fumiama/deepinfra/model"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var cfg = newconfig()
type config struct {
ModelName string
Type int
SystemP string
API string
Key string
Separator string
NoReplyAT bool
NoSystemP bool
}
func newconfig() config {
return config{
ModelName: model.ModelDeepDeek,
SystemP: chat.SystemPrompt,
API: deepinfra.OpenAIDeepInfra,
}
}
func (c *config) isvalid() bool {
return c.ModelName != "" && c.API != "" && c.Key != ""
}
func ensureconfig(ctx *zero.Ctx) bool {
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
return false
}
if !cfg.isvalid() {
err := c.GetExtra(&cfg)
if err != nil {
logrus.Warnln("ERROR: get extra err:", err)
}
if !cfg.isvalid() {
cfg = newconfig()
}
}
return true
}
func newextrasetstr(ptr *string) func(ctx *zero.Ctx) {
return func(ctx *zero.Ctx) {
args := strings.TrimSpace(ctx.State["args"].(string))
if args == "" {
ctx.SendChain(message.Text("ERROR: empty args"))
return
}
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("ERROR: no such plugin"))
return
}
*ptr = args
err := c.SetExtra(&cfg)
if err != nil {
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
return
}
ctx.SendChain(message.Text("成功"))
}
}
func newextrasetbool(ptr *bool) func(ctx *zero.Ctx) {
return func(ctx *zero.Ctx) {
args := ctx.State["regex_matched"].([]string)
isno := args[1] == "不"
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("ERROR: no such plugin"))
return
}
*ptr = isno
err := c.SetExtra(&cfg)
if err != nil {
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
return
}
ctx.SendChain(message.Text("成功"))
}
}

258
plugin/aichat/main.go Normal file
View File

@@ -0,0 +1,258 @@
// Package aichat OpenAI聊天
package aichat
import (
"math/rand"
"strconv"
"strings"
"github.com/fumiama/deepinfra"
"github.com/fumiama/deepinfra/model"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/floatbox/process"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/chat"
"github.com/FloatTech/zbputils/control"
)
var (
// en data [8 temp] [8 rate] LSB
en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Extra: control.ExtraFromString("aichat"),
Brief: "OpenAI聊天",
Help: "- 设置AI聊天触发概率10\n" +
"- 设置AI聊天温度80\n" +
"- 设置AI聊天接口类型[OpenAI|OLLaMA|GenAI]\n" +
"- 设置AI聊天(不)支持系统提示词\n" +
"- 设置AI聊天接口地址https://xxx\n" +
"- 设置AI聊天密钥xxx\n" +
"- 设置AI聊天模型名xxx\n" +
"- 查看AI聊天系统提示词\n" +
"- 重置AI聊天系统提示词\n" +
"- 设置AI聊天系统提示词xxx\n" +
"- 设置AI聊天分隔符</think>(留空则清除)\n" +
"- 设置AI聊天(不)响应AT",
PrivateDataFolder: "aichat",
})
)
var apitypes = map[string]uint8{
"OpenAI": 0,
"OLLaMA": 1,
"GenAI": 2,
}
func init() {
en.OnMessage(ensureconfig, func(ctx *zero.Ctx) bool {
return ctx.ExtractPlainText() != "" &&
(!cfg.NoReplyAT || (cfg.NoReplyAT && !ctx.Event.IsToMe))
}).SetBlock(false).Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
return
}
rate := c.GetData(gid)
temp := (rate >> 8) & 0xff
rate &= 0xff
if !ctx.Event.IsToMe && rand.Intn(100) >= int(rate) {
return
}
if ctx.Event.IsToMe {
ctx.Block()
}
if cfg.Key == "" {
logrus.Warnln("ERROR: get extra err: empty key")
return
}
if temp <= 0 {
temp = 70 // default setting
}
if temp > 100 {
temp = 100
}
x := deepinfra.NewAPI(cfg.API, cfg.Key)
var mod model.Protocol
switch cfg.Type {
case 0:
mod = model.NewOpenAI(
cfg.ModelName, cfg.Separator,
float32(temp)/100, 0.9, 4096,
)
case 1:
mod = model.NewOLLaMA(
cfg.ModelName, cfg.Separator,
float32(temp)/100, 0.9, 4096,
)
case 2:
mod = model.NewGenAI(
cfg.ModelName,
float32(temp)/100, 0.9, 4096,
)
default:
logrus.Warnln("[aichat] unsupported AI type", cfg.Type)
return
}
data, err := x.Request(chat.Ask(mod, gid, cfg.SystemP, cfg.NoSystemP))
if err != nil {
logrus.Warnln("[aichat] post err:", err)
return
}
txt := chat.Sanitize(strings.Trim(data, "\n  "))
if len(txt) > 0 {
chat.Reply(gid, txt)
nick := zero.BotConfig.NickName[rand.Intn(len(zero.BotConfig.NickName))]
txt = strings.ReplaceAll(txt, "{name}", ctx.CardOrNickName(ctx.Event.UserID))
txt = strings.ReplaceAll(txt, "{me}", nick)
id := any(nil)
if ctx.Event.IsToMe {
id = ctx.Event.MessageID
}
for _, t := range strings.Split(txt, "{segment}") {
if t == "" {
continue
}
if id != nil {
id = ctx.SendChain(message.Reply(id), message.Text(t))
} else {
id = ctx.SendChain(message.Text(t))
}
process.SleepAbout1sTo2s()
}
}
})
en.OnPrefix("设置AI聊天触发概率", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
args := strings.TrimSpace(ctx.State["args"].(string))
if args == "" {
ctx.SendChain(message.Text("ERROR: empty args"))
return
}
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("ERROR: no such plugin"))
return
}
r, err := strconv.Atoi(args)
if err != nil {
ctx.SendChain(message.Text("ERROR: parse rate err: ", err))
return
}
if r > 100 {
r = 100
} else if r < 0 {
r = 0
}
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
val := c.GetData(gid) & (^0xff)
err = c.SetData(gid, val|int64(r&0xff))
if err != nil {
ctx.SendChain(message.Text("ERROR: set data err: ", err))
return
}
ctx.SendChain(message.Text("成功"))
})
en.OnPrefix("设置AI聊天温度", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
args := strings.TrimSpace(ctx.State["args"].(string))
if args == "" {
ctx.SendChain(message.Text("ERROR: empty args"))
return
}
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("ERROR: no such plugin"))
return
}
r, err := strconv.Atoi(args)
if err != nil {
ctx.SendChain(message.Text("ERROR: parse rate err: ", err))
return
}
if r > 100 {
r = 100
} else if r < 0 {
r = 0
}
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
val := c.GetData(gid) & (^0xff00)
err = c.SetData(gid, val|(int64(r&0xff)<<8))
if err != nil {
ctx.SendChain(message.Text("ERROR: set data err: ", err))
return
}
ctx.SendChain(message.Text("成功"))
})
en.OnPrefix("设置AI聊天接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
args := strings.TrimSpace(ctx.State["args"].(string))
if args == "" {
ctx.SendChain(message.Text("ERROR: empty args"))
return
}
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("ERROR: no such plugin"))
return
}
typ, ok := apitypes[args]
if !ok {
ctx.SendChain(message.Text("ERROR: 未知类型 ", args))
return
}
cfg.Type = int(typ)
err := c.SetExtra(&cfg)
if err != nil {
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
return
}
ctx.SendChain(message.Text("成功"))
})
en.OnPrefix("设置AI聊天接口地址", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(newextrasetstr(&cfg.API))
en.OnPrefix("设置AI聊天密钥", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(newextrasetstr(&cfg.Key))
en.OnPrefix("设置AI聊天模型名", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(newextrasetstr(&cfg.ModelName))
en.OnPrefix("设置AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(newextrasetstr(&cfg.SystemP))
en.OnFullMatch("查看AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(cfg.SystemP))
})
en.OnFullMatch("重置AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, 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
}
cfg.SystemP = chat.SystemPrompt
err := c.SetExtra(&cfg)
if err != nil {
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
return
}
ctx.SendChain(message.Text("成功"))
})
en.OnPrefix("设置AI聊天分隔符", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(newextrasetstr(&cfg.Separator))
en.OnRegex("^设置AI聊天(不)?响应AT$", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(newextrasetbool(&cfg.NoReplyAT))
en.OnRegex("^设置AI聊天(不)?支持系统提示词$", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(newextrasetbool(&cfg.NoSystemP))
}

View File

@@ -20,7 +20,6 @@ import (
"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"
@@ -41,7 +40,7 @@ import (
)
const (
backgroundURL = "https://iw233.cn/api.php?sort=mp"
backgroundURL = "https://pic.re/image"
referer = "https://weibo.com/"
)
@@ -184,7 +183,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string, botrunsta
return
}
data, err = web.GetData("http://q4.qlogo.cn/g?b=qq&nk=" + strconv.FormatInt(uid, 10) + "&s=640")
data, err = web.GetData("https://q4.qlogo.cn/g?b=qq&nk=" + strconv.FormatInt(uid, 10) + "&s=640")
if err != nil {
return
}
@@ -237,14 +236,17 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string, botrunsta
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.ClipPreserve()
titlecard.DrawImage(blurback, -70, -70)
titlecard.SetColor(colorswitch(140))
titlecard.FillPreserve()
titlecard.SetLineWidth(3)
titlecard.SetColor(colorswitch(100))
titlecard.StrokePreserve()
titlecard.SetColor(colorswitch(140))
titlecard.Fill()
titlecard.ResetClip()
titlecard.Stroke()
titlecard.DrawImage(avatarf.Circle(0).Image(), (titlecardh-avatarf.H())/2, (titlecardh-avatarf.H())/2)
@@ -288,20 +290,23 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string, botrunsta
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)
titleimg = titlecard.Image()
}()
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.ClipPreserve()
basiccard.DrawImage(blurback, -70, -70-titlecardh-40)
basiccard.SetColor(colorswitch(140))
basiccard.FillPreserve()
basiccard.SetLineWidth(3)
basiccard.SetColor(colorswitch(100))
basiccard.StrokePreserve()
basiccard.SetColor(colorswitch(140))
basiccard.Fill()
basiccard.ResetClip()
basiccard.Stroke()
bslen := len(basicstate)
for i, v := range basicstate {
@@ -361,20 +366,23 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string, botrunsta
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)
basicimg = basiccard.Image()
}()
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.ClipPreserve()
diskcard.DrawImage(blurback, -70, -70-titlecardh-40-basiccardh-40)
diskcard.SetColor(colorswitch(140))
diskcard.FillPreserve()
diskcard.SetLineWidth(3)
diskcard.SetColor(colorswitch(100))
diskcard.StrokePreserve()
diskcard.SetColor(colorswitch(140))
diskcard.Fill()
diskcard.ResetClip()
diskcard.Stroke()
err = diskcard.ParseFontFace(fontbyte, 32)
if err != nil {
@@ -427,6 +435,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string, botrunsta
}
diskcard.DrawRoundedRectangle(40, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+offset, float64(diskcard.W())-40-100, 50, 12)
diskcard.ClipPreserve()
diskcard.Fill()
colors := darkcolor
@@ -445,6 +454,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string, botrunsta
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.ResetClip()
diskcard.SetColor(fontcolorswitch())
@@ -456,20 +466,23 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string, botrunsta
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)
diskimg = diskcard.Image()
}()
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.ClipPreserve()
moreinfocard.DrawImage(blurback, -70, -70-titlecardh-40-basiccardh-40-diskcardh-40)
moreinfocard.SetColor(colorswitch(140))
moreinfocard.FillPreserve()
moreinfocard.SetLineWidth(3)
moreinfocard.SetColor(colorswitch(100))
moreinfocard.StrokePreserve()
moreinfocard.SetColor(colorswitch(140))
moreinfocard.Fill()
moreinfocard.ResetClip()
moreinfocard.Stroke()
err = moreinfocard.ParseFontFace(fontbyte, 32)
if err != nil {
@@ -488,7 +501,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string, botrunsta
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)
moreinfoimg = moreinfocard.Image()
}()
go func() {
defer wg.Done()
@@ -668,7 +681,7 @@ func diskstate() (stateinfo []*status, err error) {
func moreinfo(m *ctrl.Control[*zero.Ctx]) (stateinfo []*status, err error) {
var mems runtime.MemStats
runtime.ReadMemStats(&mems)
fmtmem := storagefmt(float64(mems.Sys))
fmtmem := storagefmt(float64(mems.Alloc))
hostinfo, err := host.Info()
if err != nil {

View File

@@ -1,224 +0,0 @@
// Package aipaint ai绘图
package aipaint
import (
"encoding/base64"
"encoding/json"
"fmt"
"net/url"
"os"
"regexp"
"strconv"
"strings"
"time"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
"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"
)
var (
datapath string
predictRe = regexp.MustCompile(`{"steps".+?}`)
// 参考host http://91.217.139.190:5010 http://91.216.169.75:5010
aipaintTxt2ImgURL = "/got_image?token=%v&tags=%v"
aipaintImg2ImgURL = "/got_image2image?token=%v&tags=%v"
cfg = newServerConfig("data/aipaint/config.json")
)
type result struct {
Steps int `json:"steps"`
Sampler string `json:"sampler"`
Seed int `json:"seed"`
Strength float64 `json:"strength"`
Noise float64 `json:"noise"`
Scale float64 `json:"scale"`
Uc string `json:"uc"`
}
func (r *result) String() string {
return fmt.Sprintf("steps: %v\nsampler: %v\nseed: %v\nstrength: %v\nnoise: %v\nscale: %v\nuc: %v\n", r.Steps, r.Sampler, r.Seed, r.Strength, r.Noise, r.Scale, r.Uc)
}
func init() { // 插件主体
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "ai绘图",
Help: "- [ ai绘图 | 生成色图 | 生成涩图 | ai画图 ] xxx\n" +
"- [ ai高级绘图 | 高级生成色图 | 高级生成涩图 | ai高级画图 ] [prompt]\n" +
"- 设置ai绘图配置 [server] [token]\n" +
"- 设置ai绘图撤回时间90s\n" +
"- 查看ai绘图配置\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" +
"[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" +
"参数与参数内容用:连接,每个参数之间用回车分割",
PrivateDataFolder: "aipaint",
})
datapath = file.BOTPATH + "/" + engine.DataFolder()
if file.IsNotExist(cfg.file) {
s := serverConfig{}
data, err := json.Marshal(s)
if err != nil {
panic(err)
}
err = os.WriteFile(cfg.file, data, 0666)
if err != nil {
panic(err)
}
}
engine.OnPrefixGroup([]string{`ai绘图`, `生成色图`, `生成涩图`, `ai画图`}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("少女祈祷中..."))
args := ctx.State["args"].(string)
data, err := web.GetData(cfg.BaseURL + fmt.Sprintf(aipaintTxt2ImgURL, cfg.Token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20")))))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
sendAiImg(ctx, data, cfg.Interval)
})
engine.OnPrefixGroup([]string{`ai高级绘图`, `高级生成色图`, `高级生成涩图`, `ai高级画图`}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
tags := make(map[string]string)
args := strings.Split(ctx.State["args"].(string), "\n")
if len(args) < 1 {
ctx.SendChain(message.Text("ERROR: 请输入正确的参数"))
return
}
for _, info := range args {
value := strings.Split(info, ":")
if len(value) > 1 {
if value[0] == "R18" && value[1] == "1" {
value[1] = "0"
ctx.SendChain(message.Text("不准涩涩! 已将R18设置为0. "))
}
tags[value[0]] = strings.Join(value[1:], ":")
}
}
ctx.SendChain(message.Text("少女祈祷中..."))
apiurl := "/got_image?token=" + cfg.Token
if _, ok := tags["tags"]; ok {
apiurl += "&tags=" + url.QueryEscape(strings.ReplaceAll(strings.TrimSpace(tags["tags"]), " ", "%20"))
}
if _, ok := tags["ntags"]; ok {
apiurl += "&ntags=" + url.QueryEscape(strings.ReplaceAll(strings.TrimSpace(tags["ntags"]), " ", "%20"))
}
if _, ok := tags["R18"]; ok {
apiurl += "&R18=" + url.QueryEscape(strings.TrimSpace(tags["R18"]))
}
if _, ok := tags["shape"]; ok {
apiurl += "&shape=" + url.QueryEscape(strings.TrimSpace(tags["shape"]))
}
if _, ok := tags["scale"]; ok {
apiurl += "&scale=" + url.QueryEscape(strings.TrimSpace(tags["scale"]))
}
if _, ok := tags["seed"]; ok {
apiurl += "&seed=" + url.QueryEscape(strings.TrimSpace(tags["seed"]))
}
if _, ok := tags["strength"]; ok {
apiurl += "&strength=" + url.QueryEscape(strings.TrimSpace(tags["strength"]))
}
if _, ok := tags["noise"]; ok {
apiurl += "&noise=" + url.QueryEscape(strings.TrimSpace(tags["noise"]))
}
data, err := web.GetData(cfg.BaseURL + apiurl)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
sendAiImg(ctx, data, cfg.Interval)
})
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()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
err = cfg.update(regexMatched[1], regexMatched[2], cfg.Interval)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
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) {
regexMatched := ctx.State["regex_matched"].([]string)
interval, err := strconv.Atoi(regexMatched[1])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
err = cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
err = cfg.update(cfg.BaseURL, cfg.Token, interval)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("成功设置撤回时间为", cfg.Interval, "s"))
})
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
}
ctx.SendChain(message.Text("base_url: ", cfg.BaseURL, "\ntoken: ", cfg.Token, "\ninterval: ", cfg.Interval))
})
}
func sendAiImg(ctx *zero.Ctx, data []byte, interval int) {
var loadData string
if predictRe.MatchString(binary.BytesToString(data)) {
loadData = predictRe.FindStringSubmatch(binary.BytesToString(data))[0]
}
var r result
if loadData != "" {
err := json.Unmarshal(binary.StringToBytes(loadData), &r)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
r.Uc, err = url.QueryUnescape(r.Uc)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
}
encodeStr := base64.StdEncoding.EncodeToString(data)
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image("base64://"+encodeStr))}
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(r.String())))
if mid := ctx.Send(m); mid.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
} else if interval > 0 {
go func(i message.MessageID) {
time.Sleep(time.Duration(interval) * time.Second)
ctx.DeleteMessage(i)
}(mid)
}
}

View File

@@ -1,56 +0,0 @@
package aipaint
import (
"encoding/json"
"errors"
"os"
"github.com/FloatTech/floatbox/file"
)
// 配置结构体
type serverConfig struct {
BaseURL string `json:"base_url"`
Token string `json:"token"`
Interval int `json:"interval"`
file string
}
func newServerConfig(file string) *serverConfig {
return &serverConfig{
file: file,
}
}
func (cfg *serverConfig) update(baseURL, token string, interval int) (err error) {
if baseURL != "" {
cfg.BaseURL = baseURL
}
if token != "" {
cfg.Token = token
}
cfg.Interval = interval
reader, err := os.Create(cfg.file)
if err != nil {
return err
}
defer reader.Close()
return json.NewEncoder(reader).Encode(cfg)
}
func (cfg *serverConfig) load() (err error) {
if cfg.BaseURL != "" && cfg.Token != "" && cfg.Interval != 0 {
return
}
if file.IsNotExist(cfg.file) {
err = errors.New("no server config")
return
}
reader, err := os.Open(cfg.file)
if err != nil {
return
}
defer reader.Close()
err = json.NewDecoder(reader).Decode(cfg)
return
}

View File

@@ -1,41 +0,0 @@
package aipaint
import (
"os"
"strconv"
"strings"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/process"
)
type context struct {
usrdir string
headimgsdir []string
}
func newContext(user int64) *context {
c := new(context)
c.usrdir = datapath + "users/" + strconv.FormatInt(user, 10) + `/`
_ = os.MkdirAll(c.usrdir, 0755)
c.headimgsdir = make([]string, 2)
c.headimgsdir[0] = c.usrdir + "0.gif"
c.headimgsdir[1] = c.usrdir + "1.gif"
return c
}
func (cc *context) prepareLogos(s ...string) error {
for i, v := range s {
_, err := strconv.Atoi(v)
if err != nil {
err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.usrdir+strconv.Itoa(i)+".gif")
} else {
err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif")
}
if err != nil {
return err
}
process.SleepAbout1sTo2s()
}
return nil
}

View File

@@ -1,88 +0,0 @@
// Package aipaint ai绘图
package aipaint
import (
"bytes"
"fmt"
"image"
"net/url"
"os"
"strconv"
"strings"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/imgfactory"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() { // 插件主体
engine := control.Register("img2img", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Brief: "以图绘图",
Help: "- [ 以图绘图 | 以图生图 | 以图画图 ] xxx [图片]|@xxx|[qq号]\n" +
"- 官方以图绘图api已失效 需要自建api 其他配置参数同ai绘图",
PrivateDataFolder: "img2img",
})
datapath = file.BOTPATH + "/" + engine.DataFolder()
engine.OnRegex(`^(以图绘图|以图生图|以图画图)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
c := newContext(ctx.Event.UserID)
list := ctx.State["regex_matched"].([]string)
err = c.prepareLogos(list[4]+list[5]+list[6], strconv.FormatInt(ctx.Event.UserID, 10))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
args := strings.TrimSuffix(strings.TrimPrefix(list[0], list[1]), list[2])
if args == "" {
ctx.SendChain(message.Text("ERROR: 以图绘图必须添加tag"))
return
}
ctx.SendChain(message.Text("少女祈祷中..."))
postURL := cfg.BaseURL + fmt.Sprintf(aipaintImg2ImgURL, cfg.Token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20"))))
f, err := os.Open(c.headimgsdir[0])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
defer f.Close()
img, _, err := image.Decode(f)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
imageShape := ""
switch {
case img.Bounds().Dx() > img.Bounds().Dy():
imageShape = "Landscape"
case img.Bounds().Dx() == img.Bounds().Dy():
imageShape = "Square"
default:
imageShape = "Portrait"
}
// 图片转base64
base64Bytes, err := imgfactory.ToBase64(img)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
data, err := web.PostData(postURL+"&shape="+imageShape, "text/plain", bytes.NewReader(base64Bytes))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
sendAiImg(ctx, data, cfg.Interval)
})
}

145
plugin/animetrace/main.go Normal file
View File

@@ -0,0 +1,145 @@
// Package animetrace AnimeTrace 动画/Galgame识别
package animetrace
import (
"bytes"
"encoding/base64"
"errors"
"fmt"
"image"
"image/jpeg"
"mime/multipart"
"strings"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/imgfactory"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/disintegration/imaging"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
engine := control.Register("animetrace", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "AnimeTrace 动画/Galgame识别插件",
Help: "- Gal识图\n- 动漫识图\n- 动漫识图 2\n- 动漫识图 [模型名]\n- Gal识图 [模型名]",
})
engine.OnPrefix("gal识图", zero.OnlyGroup, zero.MustProvidePicture).SetBlock(true).Handle(func(ctx *zero.Ctx) {
args := ctx.State["args"].(string)
var model string
switch strings.TrimSpace(args) {
case "":
model = "full_game_model_kira" // 默认使用的模型
default:
model = args // 自定义设置模型
}
processImageRecognition(ctx, model)
})
engine.OnPrefix("动漫识图", zero.OnlyGroup, zero.MustProvidePicture).SetBlock(true).Handle(func(ctx *zero.Ctx) {
args := ctx.State["args"].(string)
var model string
switch strings.TrimSpace(args) {
case "":
model = "anime_model_lovelive"
case "2":
model = "pre_stable"
default:
model = args
}
processImageRecognition(ctx, model)
})
}
// 处理图片识别
func processImageRecognition(ctx *zero.Ctx, model string) {
urls := ctx.State["image_url"].([]string)
if len(urls) == 0 {
return
}
imageData, err := imgfactory.Load(urls[0])
if err != nil {
ctx.Send(message.Text("下载图片失败: ", err))
return
}
// ctx.Send(message.Text(model))
respBody, err := createAndSendMultipartRequest("https://api.animetrace.com/v1/search", imageData, map[string]string{
"is_multi": "0",
"model": model,
"ai_detect": "0",
})
if err != nil {
ctx.Send(message.Text("识别请求失败: ", err))
return
}
code := gjson.Get(string(respBody), "code").Int()
if code != 0 {
ctx.Send(message.Text("错误: ", gjson.Get(string(respBody), "zh_message").String()))
return
}
dataArray := gjson.Get(string(respBody), "data").Array()
if len(dataArray) == 0 {
ctx.Send(message.Text("未识别到任何角色"))
return
}
var sk message.Message
sk = append(sk, ctxext.FakeSenderForwardNode(ctx, message.Text("共识别到 ", len(dataArray), " 个角色,可能是以下来源")))
for _, value := range dataArray {
boxArray := value.Get("box").Array()
imgWidth, imgHeight := imageData.Bounds().Dx(), imageData.Bounds().Dy() // 你可以从 `imageData.Bounds()` 获取
box := []int{
int(boxArray[0].Float() * float64(imgWidth)),
int(boxArray[1].Float() * float64(imgHeight)),
int(boxArray[2].Float() * float64(imgWidth)),
int(boxArray[3].Float() * float64(imgHeight)),
}
croppedImg := imaging.Crop(imageData, image.Rect(box[0], box[1], box[2], box[3]))
var buf bytes.Buffer
if err := imaging.Encode(&buf, croppedImg, imaging.JPEG, imaging.JPEGQuality(80)); err != nil {
ctx.Send(message.Text("图片编码失败: ", err))
continue
}
base64Str := base64.StdEncoding.EncodeToString(buf.Bytes())
var sb strings.Builder
value.Get("character").ForEach(func(_, character gjson.Result) bool {
sb.WriteString(fmt.Sprintf("《%s》的角色 %s\n", character.Get("work").String(), character.Get("character").String()))
return true
})
sk = append(sk, ctxext.FakeSenderForwardNode(ctx, message.Image("base64://"+base64Str), message.Text(sb.String())))
}
ctx.SendGroupForwardMessage(ctx.Event.GroupID, sk)
}
// 发送图片识别请求
func createAndSendMultipartRequest(url string, img image.Image, formFields map[string]string) ([]byte, error) {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
// 直接编码图片
part, err := writer.CreateFormFile("file", "image.jpg")
if err != nil {
return nil, errors.New("创建文件字段失败: " + err.Error())
}
if err := jpeg.Encode(part, img, &jpeg.Options{Quality: 80}); err != nil {
return nil, errors.New("图片编码失败: " + err.Error())
}
// 写入其他字段
for key, value := range formFields {
if err := writer.WriteField(key, value); err != nil {
return nil, errors.New("写入表单字段失败 (" + key + "): " + err.Error())
}
}
if err := writer.Close(); err != nil {
return nil, errors.New("关闭 multipart writer 失败: " + err.Error())
}
return web.PostData(url, writer.FormDataContentType(), body)
}

View File

@@ -30,7 +30,7 @@ var (
)
func newantidb(path string) (*antidb, error) {
db := &antidb{Sqlite: sqlite.Sqlite{DBPath: path}}
db := &antidb{Sqlite: sqlite.New(path)}
err := db.Open(bandur)
if err != nil {
return nil, err
@@ -46,7 +46,7 @@ func newantidb(path string) (*antidb, error) {
cache.Touch(nilbt.ID, -time.Since(t))
return nil
})
_ = db.Del("__bantime__", "WHERE time<="+strconv.FormatInt(time.Now().Add(time.Minute-bandur).Unix(), 10))
_ = db.Del("__bantime__", "WHERE time <= ?", strconv.FormatInt(time.Now().Add(time.Minute-bandur).Unix(), 10))
return db, nil
}

View File

@@ -19,7 +19,7 @@ import (
type datagetter func(string, bool) ([]byte, error)
func (dgtr datagetter) randImage(file ...string) message.MessageSegment {
func (dgtr datagetter) randImage(file ...string) message.Segment {
data, err := dgtr(file[rand.Intn(len(file))], true)
if err != nil {
return message.Text("ERROR: ", err)
@@ -27,7 +27,7 @@ func (dgtr datagetter) randImage(file ...string) message.MessageSegment {
return message.ImageBytes(data)
}
func (dgtr datagetter) randRecord(file ...string) message.MessageSegment {
func (dgtr datagetter) randRecord(file ...string) message.Segment {
data, err := dgtr(file[rand.Intn(len(file))], true)
if err != nil {
return message.Text("ERROR: ", err)
@@ -35,7 +35,7 @@ func (dgtr datagetter) randRecord(file ...string) message.MessageSegment {
return message.Record("base64://" + base64.StdEncoding.EncodeToString(data))
}
func randText(text ...string) message.MessageSegment {
func randText(text ...string) message.Segment {
return message.Text(text[rand.Intn(len(text))])
}
@@ -53,7 +53,7 @@ func init() { // 插件主体
Brief: "atri人格文本回复",
Help: "本插件基于 ATRI ,为 Golang 移植版\n" +
"- ATRI醒醒\n- ATRI睡吧\n- 萝卜子\n- 喜欢 | 爱你 | 爱 | suki | daisuki | すき | 好き | 贴贴 | 老婆 | 亲一个 | mua\n" +
"- 草你妈 | 操你妈 | 脑瘫 | 废柴 | fw | 废物 | 战斗 | 爬 | 爪巴 | sb | SB | 傻B\n- 早安 | 早哇 | 早上好 | ohayo | 哦哈哟 | お早う | 早好 | 早 | 早早早\n" +
"- 草你妈 | 操你妈 | 脑瘫 | 废柴 | fw | 废物 | 战斗 | 爬 | 爪巴 | sb | SB | 傻B\n- 早哇 | 早上好 | ohayo | 哦哈哟 | お早う | 早好 | 早 | 早早早\n" +
"- 中午好 | 午安 | 午好\n- 晚安 | oyasuminasai | おやすみなさい | 晚好 | 晚上好\n- 高性能 | 太棒了 | すごい | sugoi | 斯国一 | よかった\n" +
"- 没事 | 没关系 | 大丈夫 | 还好 | 不要紧 | 没出大问题 | 没伤到哪\n- 好吗 | 是吗 | 行不行 | 能不能 | 可不可以\n- 啊这\n- 我好了\n- | ? | ¿\n" +
"- 离谱\n- 答应我",
@@ -84,7 +84,7 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(dgtr.randImage("FN.jpg", "WQ.jpg", "WQ1.jpg"))
})
engine.OnFullMatchGroup([]string{"早安", "早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早", "早早早"}).SetBlock(true).
engine.OnFullMatchGroup([]string{"早哇", "早上好", "ohayo", "哦哈哟", "お早う", "早好", "早", "早早早"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
now := time.Now().Hour()
switch {

View File

@@ -1,61 +0,0 @@
// Package baidu 百度百科
package baidu
import (
"encoding/json"
"fmt"
"net/url"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
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

@@ -31,8 +31,6 @@ func (bdres *baiduRes) audit(ctx *zero.Ctx, configpath string) {
if bdres.ConclusionType != 2 {
return
}
// 创建消息ID
mid := message.NewMessageIDFromInteger(ctx.Event.MessageID.(int64))
// 获取群配置
group := config.groupof(ctx.Event.GroupID)
// 检测群配置里的不检测类型白名单, 忽略掉不检测的违规类型
@@ -44,7 +42,7 @@ func (bdres *baiduRes) audit(ctx *zero.Ctx, configpath string) {
// 生成回复文本
res := group.reply(bdres)
// 撤回消息
ctx.DeleteMessage(mid)
ctx.DeleteMessage(ctx.Event.MessageID)
// 查看是否启用撤回后禁言
if group.DMBAN {
// 从历史违规记录中获取指定用户
@@ -226,7 +224,7 @@ func (g *group) reply(bdres *baiduRes) message.Message {
g.mu.Lock()
defer g.mu.Unlock()
// 建立消息段
msgs := make([]message.MessageSegment, 0, 8)
msgs := make([]message.Segment, 0, 8)
// 生成简略审核结果回复
msgs = append(msgs, message.Text(bdres.Conclusion, "\n"))
// 查看是否开启详细审核内容提示, 并确定审核内容值为疑似, 或者不合规

View File

@@ -2,10 +2,15 @@
package bilibili
import (
"encoding/json"
"fmt"
"net/http"
"regexp"
"strings"
"time"
bz "github.com/FloatTech/AnimeAPI/bilibili"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -13,6 +18,11 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
enableHex = 0x10
unableHex = 0x7fffffff_fffffffd
)
var (
limit = ctxext.NewLimiterManager(time.Second*10, 1)
searchVideo = `bilibili.com\\?/video\\?/(?:av(\d+)|([bB][vV][0-9a-zA-Z]+))`
@@ -32,10 +42,11 @@ func init() {
Brief: "b站链接解析",
Help: "例:- t.bilibili.com/642277677329285174\n- bilibili.com/read/cv17134450\n- bilibili.com/video/BV13B4y1x7pS\n- live.bilibili.com/22603245 ",
})
en.OnRegex(`((b23|acg).tv|bili2233.cn)/[0-9a-zA-Z]+`).SetBlock(true).Limit(limit.LimitByGroup).
en.OnRegex(`((b23|acg).tv|bili2233.cn)\\?/[0-9a-zA-Z]+`).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
url := ctx.State["regex_matched"].([]string)[0]
realurl, err := bz.GetRealURL("https://" + url)
u := ctx.State["regex_matched"].([]string)[0]
u = strings.ReplaceAll(u, "\\", "")
realurl, err := bz.GetRealURL("https://" + u)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -55,6 +66,35 @@ func init() {
handleLive(ctx)
}
})
en.OnRegex(`^(开启|打开|启用|关闭|关掉|禁用)视频总结$`, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
if gid <= 0 {
// 个人用户设为负数
gid = -ctx.Event.UserID
}
option := ctx.State["regex_matched"].([]string)[1]
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
ctx.SendChain(message.Text("找不到服务!"))
return
}
data := c.GetData(ctx.Event.GroupID)
switch option {
case "开启", "打开", "启用":
data |= enableHex
case "关闭", "关掉", "禁用":
data &= unableHex
default:
return
}
err := c.SetData(gid, data)
if err != nil {
ctx.SendChain(message.Text("出错啦: ", err))
return
}
ctx.SendChain(message.Text("已", option, "视频总结"))
})
en.OnRegex(searchVideo).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleVideo)
en.OnRegex(searchDynamic).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleDynamic)
en.OnRegex(searchArticle).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleArticle)
@@ -76,12 +116,15 @@ 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
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok && c.GetData(ctx.Event.GroupID)&enableHex == enableHex {
summaryMsg, err := getVideoSummary(cfg, card)
if err != nil {
msg = append(msg, message.Text("ERROR: ", err))
} else {
msg = append(msg, summaryMsg...)
}
}
msg = append(msg, summaryMsg...)
ctx.SendChain(msg...)
}
@@ -111,3 +154,38 @@ func handleLive(ctx *zero.Ctx) {
}
ctx.SendChain(liveCard2msg(card)...)
}
// getVideoSummary AI视频总结
func getVideoSummary(cookiecfg *bz.CookieConfig, card bz.Card) (msg []message.Segment, err error) {
var (
data []byte
videoSummary bz.VideoSummary
)
data, err = web.RequestDataWithHeaders(web.NewDefaultClient(), bz.SignURL(fmt.Sprintf(bz.VideoSummaryURL, card.BvID, card.CID, card.Owner.Mid)), "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.Set("User-Agent", ua)
return nil
}, nil)
if err != nil {
return
}
err = json.Unmarshal(data, &videoSummary)
msg = make([]message.Segment, 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

@@ -388,7 +388,7 @@ func sendLive(ctx *zero.Ctx) error {
if lCover == "" {
lCover = value.Get("keyframe").String()
}
var msg []message.MessageSegment
var msg []message.Segment
msg = append(msg, message.Text(lName+" 正在直播:\n"))
msg = append(msg, message.Text(lTitle))
msg = append(msg, message.Image(lCover))
@@ -399,7 +399,7 @@ func sendLive(ctx *zero.Ctx) error {
switch {
case gid > 0:
if res := bdb.getAtAll(gid); res == 1 {
msg = append([]message.MessageSegment{message.AtAll()}, msg...)
msg = append([]message.Segment{message.AtAll()}, msg...)
}
ctx.SendGroupMessage(gid, msg)
case gid < 0:

View File

@@ -2,12 +2,10 @@ 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"
)
@@ -27,13 +25,13 @@ var (
)
// dynamicCard2msg 处理DynCard
func dynamicCard2msg(dynamicCard *bz.DynamicCard) (msg []message.MessageSegment, err error) {
func dynamicCard2msg(dynamicCard *bz.DynamicCard) (msg []message.Segment, err error) {
var (
card bz.Card
vote bz.Vote
cType int
)
msg = make([]message.MessageSegment, 0, 16)
msg = make([]message.Segment, 0, 16)
// 初始化结构体
err = json.Unmarshal(binary.StringToBytes(dynamicCard.Card), &card)
if err != nil {
@@ -52,7 +50,7 @@ func dynamicCard2msg(dynamicCard *bz.DynamicCard) (msg []message.MessageSegment,
msg = append(msg, message.Text(card.User.Uname, msgType[cType], "\n",
card.Item.Content, "\n",
"转发的内容: \n"))
var originMsg []message.MessageSegment
var originMsg []message.Segment
var co bz.Card
co, err = bz.LoadCardDetail(card.Origin)
if err != nil {
@@ -148,18 +146,18 @@ func dynamicCard2msg(dynamicCard *bz.DynamicCard) (msg []message.MessageSegment,
}
// card2msg cType=1, 2, 4, 8, 16, 64, 256, 2048, 4200, 4308时,处理Card字符串,cType为card类型
func card2msg(dynamicCard *bz.DynamicCard, card *bz.Card, cType int) (msg []message.MessageSegment, err error) {
func card2msg(dynamicCard *bz.DynamicCard, card *bz.Card, cType int) (msg []message.Segment, err error) {
var (
vote bz.Vote
)
msg = make([]message.MessageSegment, 0, 16)
msg = make([]message.Segment, 0, 16)
// 生成消息
switch cType {
case 1:
msg = append(msg, message.Text(card.User.Uname, msgType[cType], "\n",
card.Item.Content, "\n",
"转发的内容: \n"))
var originMsg []message.MessageSegment
var originMsg []message.Segment
var co bz.Card
co, err = bz.LoadCardDetail(card.Origin)
if err != nil {
@@ -255,7 +253,7 @@ func card2msg(dynamicCard *bz.DynamicCard, card *bz.Card, cType int) (msg []mess
}
// dynamicDetail 用动态id查动态信息
func dynamicDetail(cookiecfg *bz.CookieConfig, dynamicIDStr string) (msg []message.MessageSegment, err error) {
func dynamicDetail(cookiecfg *bz.CookieConfig, dynamicIDStr string) (msg []message.Segment, err error) {
dyc, err := bz.GetDynamicDetail(cookiecfg, dynamicIDStr)
if err != nil {
return
@@ -264,8 +262,8 @@ func dynamicDetail(cookiecfg *bz.CookieConfig, dynamicIDStr string) (msg []messa
}
// articleCard2msg 专栏转消息
func articleCard2msg(card bz.Card, defaultID string) (msg []message.MessageSegment) {
msg = make([]message.MessageSegment, 0, 16)
func articleCard2msg(card bz.Card, defaultID string) (msg []message.Segment) {
msg = make([]message.Segment, 0, 16)
for i := 0; i < len(card.OriginImageUrls); i++ {
msg = append(msg, message.Image(card.OriginImageUrls[i]))
}
@@ -276,8 +274,8 @@ func articleCard2msg(card bz.Card, defaultID string) (msg []message.MessageSegme
}
// liveCard2msg 直播卡片转消息
func liveCard2msg(card bz.RoomCard) (msg []message.MessageSegment) {
msg = make([]message.MessageSegment, 0, 16)
func liveCard2msg(card bz.RoomCard) (msg []message.Segment) {
msg = make([]message.Segment, 0, 16)
msg = append(msg, message.Image(card.RoomInfo.Keyframe))
msg = append(msg, message.Text("\n", card.RoomInfo.Title, "\n",
"主播: ", card.AnchorInfo.BaseInfo.Uname, "\n",
@@ -304,20 +302,22 @@ func liveCard2msg(card bz.RoomCard) (msg []message.MessageSegment) {
}
// videoCard2msg 视频卡片转消息
func videoCard2msg(card bz.Card) (msg []message.MessageSegment, err error) {
func videoCard2msg(card bz.Card) (msg []message.Segment, err error) {
var mCard bz.MemberCard
msg = make([]message.MessageSegment, 0, 16)
msg = make([]message.Segment, 0, 16)
mCard, err = bz.GetMemberCard(card.Owner.Mid)
if err != nil {
return
}
msg = append(msg, message.Text("标题: ", card.Title, "\n"))
if card.Rights.IsCooperation == 1 {
for i := 0; i < len(card.Staff); i++ {
msg = append(msg, message.Text(card.Staff[i].Title, ": ", card.Staff[i].Name, " 粉丝: ", bz.HumanNum(card.Staff[i].Follower), "\n"))
}
} else {
msg = append(msg, message.Text("UP主: ", card.Owner.Name, " 粉丝: ", bz.HumanNum(mCard.Fans), "\n"))
if err != nil {
err = nil
msg = append(msg, message.Text("UP主: ", card.Owner.Name, "\n"))
} else {
msg = append(msg, message.Text("UP主: ", card.Owner.Name, " 粉丝: ", bz.HumanNum(mCard.Fans), "\n"))
}
}
msg = append(msg, message.Text("播放: ", bz.HumanNum(card.Stat.View), " 弹幕: ", bz.HumanNum(card.Stat.Danmaku)))
msg = append(msg, message.Image(card.Pic))
@@ -326,27 +326,3 @@ func videoCard2msg(card bz.Card) (msg []message.MessageSegment, err error) {
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

@@ -46,14 +46,6 @@ 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

@@ -10,6 +10,7 @@ import (
"github.com/FloatTech/floatbox/binary"
fcext "github.com/FloatTech/floatbox/ctxext"
sql "github.com/FloatTech/sqlite"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img/text"
@@ -24,7 +25,7 @@ func init() {
})
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = engine.DataFolder() + "bookreview.db"
db = sql.New(engine.DataFolder() + "bookreview.db")
// os.RemoveAll(dbpath)
_, _ = engine.GetLazyData("bookreview.db", true)
err := db.Open(time.Hour)

View File

@@ -7,11 +7,11 @@ type book struct {
BookReview string `db:"bookreview"`
}
var db = &sql.Sqlite{}
var db sql.Sqlite
// 暂时随机选择一个书评
func getBookReviewByKeyword(keyword string) (b book) {
_ = db.Find("bookreview", &b, "where bookreview LIKE '%"+keyword+"%'")
_ = db.Find("bookreview", &b, "WHERE bookreview LIKE ?", "%"+keyword+"%")
return
}

View File

@@ -1,139 +0,0 @@
// Package cangtoushi 藏头诗
package cangtoushi
import (
"fmt"
"io"
"net/http"
"net/http/cookiejar"
"net/url"
"strings"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/antchfx/htmlquery"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
)
const (
loginURL = "https://www.shicimingju.com/cangtoushi/"
searchURL = "https://www.shicimingju.com/cangtoushi/index.html"
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
referer = "https://www.shicimingju.com/cangtoushi/index.html"
)
var (
gCurCookieJar *cookiejar.Jar
csrf string
)
func init() {
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "藏头诗, 藏尾诗",
Help: "- 藏头诗[xxx]\n- 藏尾诗[xxx]",
})
engine.OnRegex(`藏头诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
kw := ctx.State["regex_matched"].([]string)[1]
err := login()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
data, err := search(kw, "7", "0")
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
text, err := dealHTML(helper.BytesToString(data))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text(text))
})
engine.OnRegex(`藏尾诗\s?([一-龥]{3,10})$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
kw := ctx.State["regex_matched"].([]string)[1]
err := login()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
data, err := search(kw, "7", "2")
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
text, err := dealHTML(helper.BytesToString(data))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text(text))
})
}
func login() error {
gCurCookieJar, _ = cookiejar.New(nil)
client := &http.Client{
Jar: gCurCookieJar,
}
request, err := http.NewRequest("GET", loginURL, nil)
if err != nil {
return err
}
request.Header.Add("User-Agent", ua)
response, err := client.Do(request)
if err != nil {
return err
}
data, err := io.ReadAll(response.Body)
if err != nil {
return err
}
response.Body.Close()
doc, err := htmlquery.Parse(strings.NewReader(helper.BytesToString(data)))
if err != nil {
return err
}
csrf = htmlquery.SelectAttr(htmlquery.FindOne(doc, "//input[@name='_csrf']"), "value")
return nil
}
func search(kw, zishu, position string) (data []byte, err error) {
postStr := fmt.Sprintf("_csrf=%s&kw=%s&zishu=%s&position=%s", url.QueryEscape(csrf), url.QueryEscape(kw), zishu, position)
client := &http.Client{
Jar: gCurCookieJar,
}
request, err := http.NewRequest("POST", searchURL, strings.NewReader(postStr))
if err != nil {
return nil, err
}
request.Header.Add("Referer", referer)
request.Header.Add("User-Agent", ua)
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
response, err := client.Do(request)
if err != nil {
return nil, err
}
data, err = io.ReadAll(response.Body)
if err != nil {
return nil, err
}
response.Body.Close()
return
}
func dealHTML(data string) (text string, err error) {
doc, err := htmlquery.Parse(strings.NewReader(data))
if err != nil {
return "", err
}
text = htmlquery.InnerText(htmlquery.FindOne(doc, "//div[@class='card']/div[@class='card']"))
text = strings.ReplaceAll(text, " ", "")
text = strings.Replace(text, "\n", "", 1)
return text, nil
}

View File

@@ -0,0 +1,101 @@
// Package chatcount 聊天时长统计
package chatcount
import (
"fmt"
"image"
"net/http"
"strconv"
"sync"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/floatbox/file"
"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"
)
const (
rankSize = 10
)
func init() {
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "聊天时长统计",
Help: "- 查询水群@xxx\n- 查看水群排名",
PrivateDataFolder: "chatcount",
})
go func() {
ctdb = initialize(engine.DataFolder() + "chatcount.db")
}()
engine.OnMessage(zero.OnlyGroup).SetBlock(false).
Handle(func(ctx *zero.Ctx) {
remindTime, remindFlag := ctdb.updateChatTime(ctx.Event.GroupID, ctx.Event.UserID)
if remindFlag {
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("BOT提醒你今天已经水群%d分钟了", remindTime)))
}
})
engine.OnPrefix(`查询水群`, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
name := ctx.NickName()
todayTime, todayMessage, totalTime, totalMessage := ctdb.getChatTime(ctx.Event.GroupID, ctx.Event.UserID)
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(fmt.Sprintf("%s今天水了%d分%d秒发了%d条消息总计水了%d分%d秒发了%d条消息。", name, todayTime/60, todayTime%60, todayMessage, totalTime/60, totalTime%60, totalMessage)))
})
engine.OnFullMatch("查看水群排名", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
chatTimeList := ctdb.getChatRank(ctx.Event.GroupID)
if len(chatTimeList) == 0 {
ctx.SendChain(message.Text("ERROR: 没有水群数据"))
return
}
rankinfo := make([]*rendercard.RankInfo, len(chatTimeList))
wg := &sync.WaitGroup{}
wg.Add(len(chatTimeList))
for i := 0; i < len(chatTimeList) && i < rankSize; i++ {
go func(i int) {
defer wg.Done()
resp, err := http.Get("https://q4.qlogo.cn/g?b=qq&nk=" + strconv.FormatInt(chatTimeList[i].UserID, 10) + "&s=100")
if err != nil {
return
}
defer resp.Body.Close()
img, _, err := image.Decode(resp.Body)
if err != nil {
return
}
rankinfo[i] = &rendercard.RankInfo{
TopLeftText: ctx.CardOrNickName(chatTimeList[i].UserID),
BottomLeftText: "消息数: " + strconv.FormatInt(chatTimeList[i].TodayMessage, 10) + " 条",
RightText: strconv.FormatInt(chatTimeList[i].TodayTime/60, 10) + "分" + strconv.FormatInt(chatTimeList[i].TodayTime%60, 10) + "秒",
Avatar: img,
}
}(i)
}
wg.Wait()
fontbyte, err := file.GetLazyData(text.GlowSansFontFile, control.Md5File, true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
img, err := rendercard.DrawRankingCard(fontbyte, "今日水群排行榜", rankinfo)
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: 可能被风控了"))
}
})
}

225
plugin/chatcount/model.go Normal file
View File

@@ -0,0 +1,225 @@
package chatcount
import (
"fmt"
"os"
"sort"
"strconv"
"strings"
"sync"
"time"
"github.com/RomiChan/syncx"
"github.com/jinzhu/gorm"
)
const (
chatInterval = 300
)
var (
// ctdb 聊天时长数据库全局变量
ctdb *chattimedb
// l 水群提醒时间提醒段,单位分钟
l = newLeveler(60, 120, 180, 240, 300)
)
// chattimedb 聊天时长数据库结构体
type chattimedb struct {
// ctdb.userTimestampMap 每个人发言的时间戳 key=groupID_userID
userTimestampMap syncx.Map[string, int64]
// ctdb.userTodayTimeMap 每个人今日水群时间 key=groupID_userID
userTodayTimeMap syncx.Map[string, int64]
// ctdb.userTodayMessageMap 每个人今日水群次数 key=groupID_userID
userTodayMessageMap syncx.Map[string, int64]
// db 数据库
db *gorm.DB
// chatmu 读写添加锁
chatmu sync.Mutex
}
// initialize 初始化
func initialize(dbpath string) *chattimedb {
var err error
if _, err = os.Stat(dbpath); err != nil || os.IsNotExist(err) {
// 生成文件
f, err := os.Create(dbpath)
if err != nil {
return nil
}
defer f.Close()
}
gdb, err := gorm.Open("sqlite3", dbpath)
if err != nil {
panic(err)
}
gdb.AutoMigrate(&chatTime{})
return &chattimedb{
db: gdb,
}
}
// Close 关闭
func (ctdb *chattimedb) Close() error {
db := ctdb.db
return db.Close()
}
// chatTime 聊天时长,时间的单位都是秒
type chatTime struct {
ID uint `gorm:"primary_key"`
GroupID int64 `gorm:"column:group_id"`
UserID int64 `gorm:"column:user_id"`
TodayTime int64 `gorm:"-"`
TodayMessage int64 `gorm:"-"`
TotalTime int64 `gorm:"column:total_time;default:0"`
TotalMessage int64 `gorm:"column:total_message;default:0"`
}
// TableName 表名
func (chatTime) TableName() string {
return "chat_time"
}
// updateChatTime 更新发言时间,todayTime的单位是分钟
func (ctdb *chattimedb) updateChatTime(gid, uid int64) (remindTime int64, remindFlag bool) {
ctdb.chatmu.Lock()
defer ctdb.chatmu.Unlock()
db := ctdb.db
now := time.Now()
keyword := fmt.Sprintf("%v_%v", gid, uid)
ts, ok := ctdb.userTimestampMap.Load(keyword)
if !ok {
ctdb.userTimestampMap.Store(keyword, now.Unix())
ctdb.userTodayMessageMap.Store(keyword, 1)
return
}
lastTime := time.Unix(ts, 0)
todayTime, _ := ctdb.userTodayTimeMap.Load(keyword)
totayMessage, _ := ctdb.userTodayMessageMap.Load(keyword)
// 这个消息数是必须统计的
ctdb.userTodayMessageMap.Store(keyword, totayMessage+1)
st := chatTime{
GroupID: gid,
UserID: uid,
TotalTime: todayTime,
TotalMessage: totayMessage,
}
// 如果不是同一天把TotalTime,TotalMessage重置
if lastTime.YearDay() != now.YearDay() {
if err := db.Model(&st).Where("group_id = ? and user_id = ?", gid, uid).First(&st).Error; err != nil {
if gorm.IsRecordNotFoundError(err) {
db.Model(&st).Create(&st)
}
} else {
db.Model(&st).Where("group_id = ? and user_id = ?", gid, uid).Update(
map[string]any{
"total_time": st.TotalTime + todayTime,
"total_message": st.TotalMessage + totayMessage,
})
}
ctdb.userTimestampMap.Store(keyword, now.Unix())
ctdb.userTodayTimeMap.Delete(keyword)
ctdb.userTodayMessageMap.Delete(keyword)
return
}
userChatTime := int64(now.Sub(lastTime).Seconds())
// 当聊天时间在一定范围内的话,则计入时长
if userChatTime < chatInterval {
ctdb.userTodayTimeMap.Store(keyword, todayTime+userChatTime)
remindTime = (todayTime + userChatTime) / 60
remindFlag = l.level(int((todayTime+userChatTime)/60)) > l.level(int(todayTime/60))
}
ctdb.userTimestampMap.Store(keyword, now.Unix())
return
}
// getChatTime 获得用户聊天时长和消息次数,todayTime,totalTime的单位是秒,todayMessage,totalMessage单位是条数
func (ctdb *chattimedb) getChatTime(gid, uid int64) (todayTime, todayMessage, totalTime, totalMessage int64) {
ctdb.chatmu.Lock()
defer ctdb.chatmu.Unlock()
db := ctdb.db
st := chatTime{}
db.Model(&st).Where("group_id = ? and user_id = ?", gid, uid).First(&st)
keyword := fmt.Sprintf("%v_%v", gid, uid)
todayTime, _ = ctdb.userTodayTimeMap.Load(keyword)
todayMessage, _ = ctdb.userTodayMessageMap.Load(keyword)
totalTime = st.TotalTime
totalMessage = st.TotalMessage
return
}
// getChatRank 获得水群排名,时间单位为秒
func (ctdb *chattimedb) getChatRank(gid int64) (chatTimeList []chatTime) {
ctdb.chatmu.Lock()
defer ctdb.chatmu.Unlock()
chatTimeList = make([]chatTime, 0, 100)
keyList := make([]string, 0, 100)
ctdb.userTimestampMap.Range(func(key string, value int64) bool {
t := time.Unix(value, 0)
if strings.Contains(key, strconv.FormatInt(gid, 10)) && t.YearDay() == time.Now().YearDay() {
keyList = append(keyList, key)
}
return true
})
for _, v := range keyList {
_, a, _ := strings.Cut(v, "_")
uid, _ := strconv.ParseInt(a, 10, 64)
todayTime, _ := ctdb.userTodayTimeMap.Load(v)
todayMessage, _ := ctdb.userTodayMessageMap.Load(v)
chatTimeList = append(chatTimeList, chatTime{
GroupID: gid,
UserID: uid,
TodayTime: todayTime,
TodayMessage: todayMessage,
})
}
sort.Sort(sortChatTime(chatTimeList))
return
}
// leveler 结构体,包含一个 levelArray 字段
type leveler struct {
levelArray []int
}
// newLeveler 构造函数,用于创建 Leveler 实例
func newLeveler(levels ...int) *leveler {
return &leveler{
levelArray: levels,
}
}
// level 方法,封装了 getLevel 函数的逻辑
func (l *leveler) level(t int) int {
for i := len(l.levelArray) - 1; i >= 0; i-- {
if t >= l.levelArray[i] {
return i + 1
}
}
return 0
}
// sortChatTime chatTime排序数组
type sortChatTime []chatTime
// Len 实现 sort.Interface
func (a sortChatTime) Len() int {
return len(a)
}
// Less 实现 sort.Interface按 TodayTime 降序TodayMessage 降序
func (a sortChatTime) Less(i, j int) bool {
if a[i].TodayTime == a[j].TodayTime {
return a[i].TodayMessage > a[j].TodayMessage
}
return a[i].TodayTime > a[j].TodayTime
}
// Swap 实现 sort.Interface
func (a sortChatTime) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}

View File

@@ -235,7 +235,7 @@ func play(groupCode, senderUin int64, moveStr string) (msg message.Message, err
chessRoomMap.Store(groupCode, room)
}
// 生成棋盘图片
var boardImgEle message.MessageSegment
var boardImgEle message.Segment
if !room.isBlindfold {
boardImgEle, err = getBoardElement(groupCode)
if err != nil {
@@ -400,7 +400,7 @@ func createGame(isBlindfold bool, groupCode, senderUin int64, senderName string)
room.blackPlayer = senderUin
room.blackName = senderName
chessRoomMap.Store(groupCode, room)
var boardImgEle message.MessageSegment
var boardImgEle message.Segment
if !room.isBlindfold {
boardImgEle, err = getBoardElement(groupCode)
if err != nil {
@@ -442,7 +442,7 @@ func abortGame(room chessRoom, groupCode int64, hint string) (message.Message, e
}
// getBoardElement 获取棋盘图片的消息内容
func getBoardElement(groupCode int64) (imgMsg message.MessageSegment, err error) {
func getBoardElement(groupCode int64) (imgMsg message.Segment, err error) {
fontdata, err := file.GetLazyData(text.GNUUnifontFontFile, control.Md5File, true)
if err != nil {
return

View File

@@ -9,6 +9,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
fcext "github.com/FloatTech/floatbox/ctxext"
sql "github.com/FloatTech/sqlite"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
)
@@ -23,7 +24,7 @@ func init() {
en.OnRegex("^抽象翻译((\\s|[\\r\\n]|[\\p{Han}\\p{P}A-Za-z0-9])+)$",
fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = en.DataFolder() + "cxh.db"
db = sql.New(en.DataFolder() + "cxh.db")
// os.RemoveAll(dbpath)
_, _ = en.GetLazyData("cxh.db", true)
err := db.Open(time.Hour)

View File

@@ -11,11 +11,11 @@ type emoji struct {
Emoji string `db:"emoji"`
}
var db = &sql.Sqlite{}
var db sql.Sqlite
func getPinyinByWord(word string) string {
var p pinyin
_ = db.Find("pinyin", &p, "where word = '"+word+"'")
_ = db.Find("pinyin", &p, "WHERE word = ?", word)
return p.Pronun
}
@@ -25,6 +25,6 @@ func getPronunByDWord(w0, w1 rune) string {
func getEmojiByPronun(pronun string) string {
var e emoji
_ = db.Find("emoji", &e, "where pronunciation = '"+pronun+"'")
_ = db.Find("emoji", &e, "WHERE pronunciation = ?", pronun)
return e.Emoji
}

View File

@@ -23,7 +23,7 @@ import (
var (
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36"
coserURL = "http://ovooa.com/API/cosplay/api.php"
coserURL = "https://picture.yinux.workers.dev"
)
func init() {

View File

@@ -11,6 +11,7 @@ import (
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/math"
sql "github.com/FloatTech/sqlite"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
)
@@ -24,7 +25,7 @@ func init() {
})
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = engine.DataFolder() + "cp.db"
db = sql.New(engine.DataFolder() + "cp.db")
// os.RemoveAll(dbpath)
_, _ = engine.GetLazyData("cp.db", true)
err := db.Open(time.Hour)

View File

@@ -9,7 +9,7 @@ type cpstory struct {
Story string `db:"story"`
}
var db = &sql.Sqlite{}
var db sql.Sqlite
func getRandomCpStory() (cs cpstory) {
_ = db.Pick("cp_story", &cs)

View File

@@ -10,6 +10,7 @@ import (
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/process"
sql "github.com/FloatTech/sqlite"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -29,7 +30,7 @@ func init() {
})
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = engine.DataFolder() + "curse.db"
db = sql.New(engine.DataFolder() + "curse.db")
_, err := engine.GetLazyData("curse.db", true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))

View File

@@ -8,9 +8,9 @@ type curse struct {
Level string `db:"level"`
}
var db = &sql.Sqlite{}
var db sql.Sqlite
func getRandomCurseByLevel(level string) (c curse) {
_ = db.Find("curse", &c, "where level = '"+level+"' ORDER BY RANDOM() limit 1")
_ = db.Find("curse", &c, "WHERE level = ? ORDER BY RANDOM() limit 1", level)
return
}

View File

@@ -24,14 +24,11 @@ func init() {
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
}
picURL := gjson.Get(binary.BytesToString(data), "imageUrl").String()
ctx.SendChain(message.Image(picURL))
})
}

View File

@@ -23,7 +23,7 @@ type text struct {
// LoadText 加载小作文
func LoadText(dbfile string) error {
_, err := file.GetLazyData(dbfile, control.Md5File, false)
db.DBPath = dbfile
db = sql.New(dbfile)
if err != nil {
return err
}
@@ -63,7 +63,7 @@ func RandText() string {
// HentaiText 发大病
func HentaiText() string {
var t text
err := db.Find("text", &t, "where id = -3802576048116006195")
err := db.Find("text", &t, "WHERE id = -3802576048116006195")
if err != nil {
return err.Error()
}

View File

@@ -2,7 +2,6 @@
package dish
import (
"fmt"
"strings"
"time"
@@ -25,7 +24,7 @@ type dish struct {
}
var (
db = &sql.Sqlite{}
db sql.Sqlite
initialized = false
)
@@ -37,7 +36,7 @@ func init() {
PublicDataFolder: "Dish",
})
db.DBPath = en.DataFolder() + "dishes.db"
db = sql.New(en.DataFolder() + "dishes.db")
if _, err := en.GetLazyData("dishes.db", true); err != nil {
logrus.Warnln("[dish]获取菜谱数据库文件失败")
@@ -62,7 +61,7 @@ func init() {
return
}
name := ctx.NickName()
name := ctx.CardOrNickName(ctx.Event.UserID)
dishName := ctx.State["args"].(string)
if dishName == "" {
@@ -77,26 +76,25 @@ func init() {
}
var d dish
if err := db.Find("dish", &d, fmt.Sprintf("WHERE name like %%%s%%", dishName)); err != nil {
if err := db.Find("dish", &d, "WHERE name LIKE ?", "%"+dishName+"%"); err != nil {
ctx.SendChain(message.Text("客官,本店没有" + dishName))
return
}
ctx.SendChain(message.Text(fmt.Sprintf(
"已为客官%s找到%s的做法辣!\n"+
"原材料:%s\n"+
"步骤:\n"+
"%s",
name, dishName, d.Materials, d.Steps),
ctx.SendChain(message.Text(
"已为客官", name, "找到", d.Name, "的做法辣!\n",
"原材料:", d.Materials, "\n",
"步骤:", d.Steps,
))
})
en.OnPrefixGroup([]string{"随机菜谱", "随便做点菜"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
en.OnFullMatchGroup([]string{"随机菜谱", "随便做点菜"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
if !initialized {
ctx.SendChain(message.Text("客官,本店暂未开业"))
return
}
name := ctx.NickName()
name := ctx.CardOrNickName(ctx.Event.UserID)
var d dish
if err := db.Pick("dish", &d); err != nil {
ctx.SendChain(message.Text("小店好像出错了,暂时端不出菜来惹"))
@@ -104,12 +102,10 @@ func init() {
return
}
ctx.SendChain(message.Text(fmt.Sprintf(
"已为客官%s送上%s的做法:\n"+
"原材料:%s\n"+
"步骤:\n"+
"%s",
name, d.Name, d.Materials, d.Steps),
ctx.SendChain(message.Text(
"已为客官", name, "送上", d.Name, "的做法:\n",
"原材料:", d.Materials, "\n",
"步骤:", d.Steps,
))
})
}

View File

@@ -5,13 +5,15 @@ import (
"bytes"
"errors"
"image"
"image/color"
"image/draw"
"image/gif"
"io"
"math/rand"
"os"
"strconv"
"strings"
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/imgfactory"
@@ -89,7 +91,7 @@ func init() {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("file:///"+picPath))
return
}
lotsImg, err := randGif(lotsType + "." + fileInfo.lotsType)
lotsImg, err := randGif(lotsType+"."+fileInfo.lotsType, ctx.Event.UserID)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -228,27 +230,48 @@ func randFile(path string, indexMax int) (string, error) {
return "", errors.New("图包[" + path + "]不存在签内容!")
}
func randGif(gifName string) (image.Image, error) {
func randGif(gifName string, uid int64) (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
_, err = file.Seek(0, io.SeekStart)
if err != nil {
return nil, err
}
config, err := gif.DecodeConfig(file)
if err != nil {
return nil, err
}
_ = file.Close()
// https://zhuanlan.zhihu.com/p/27718135
rect := image.Rect(0, 0, config.Width, config.Height)
if rect.Min == rect.Max {
var maxP image.Point
for _, frame := range im.Image {
maxF := frame.Bounds().Max
if maxP.X < maxF.X {
maxP.X = maxF.X
}
if maxP.Y < maxF.Y {
maxP.Y = maxF.Y
}
}
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
// */
rect.Max = maxP
}
img := image.NewRGBA(rect)
b := fcext.RandSenderPerDayN(uid, len(im.Image)) + 1
a := 0
if b > 8 {
a = b - 8
}
for _, srcimg := range im.Image[a:b] {
draw.Draw(img, srcimg.Bounds(), srcimg, srcimg.Rect.Min, draw.Over)
}
return img, err
}

View File

@@ -1,39 +0,0 @@
package dress
import (
"fmt"
"github.com/FloatTech/floatbox/web"
"github.com/tidwall/gjson"
)
const (
dressURL = "http://www.yoooooooooo.com/gitdress"
male = "dress"
female = "girldress"
dressListURL = dressURL + "/%v/album/list.json"
dressDetailURL = dressURL + "/%v/album/%v/info.json"
dressImageURL = dressURL + "/%v/album/%v/%v-m.webp"
)
func dressList(sex string) (dressList []string, err error) {
data, err := web.GetData(fmt.Sprintf(dressListURL, sex))
if err != nil {
return
}
arr := gjson.ParseBytes(data).Get("@this").Array()
dressList = make([]string, len(arr))
for i, v := range arr {
dressList[i] = v.String()
}
return
}
func detail(sex, name string) (count int, err error) {
data, err := web.GetData(fmt.Sprintf(dressDetailURL, sex, name))
if err != nil {
return
}
count = int(gjson.ParseBytes(data).Get("@this.#").Int())
return
}

View File

@@ -1,113 +0,0 @@
// Package dress 女装
package dress
import (
"fmt"
"math/rand"
"strconv"
"strings"
"time"
"github.com/FloatTech/floatbox/binary"
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: "女装\n" +
"- 女装\n" +
"- 男装\n" +
"- 随机女装\n" +
"- 随机男装",
PrivateDataFolder: "dress",
})
engine.OnFullMatchGroup([]string{"女装", "男装"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
matched := ctx.State["matched"].(string)
sex := male
if matched == "男装" {
sex = female
}
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
recv, cancel := next.Repeat()
defer cancel()
nameList, err := dressList(sex)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
tex := "请输入" + matched + "序号\n"
for i, v := range nameList {
tex += fmt.Sprintf("%d. %s\n", i, v)
}
base64Str, err := text.RenderToBase64(tex, 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(matched, "指令过期"))
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(nameList) {
ctx.SendChain(message.Text("序号非法!"))
continue
}
name := nameList[num]
sendImage(ctx, sex, matched, name)
return
}
}
})
engine.OnFullMatchGroup([]string{"随机女装", "随机男装"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
matched := strings.TrimPrefix(ctx.State["matched"].(string), "随机")
sex := male
if matched == "男装" {
sex = female
}
nameList, err := dressList(sex)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
name := nameList[rand.Intn(len(nameList))]
sendImage(ctx, sex, matched, name)
})
}
func sendImage(ctx *zero.Ctx, sex, matched, name string) {
ctx.SendChain(message.Text("请欣赏", matched, ": ", name))
count, err := detail(sex, name)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
imageList := make([]string, count)
for i := range imageList {
imageList[i] = fmt.Sprintf(dressImageURL, sex, name, i+1)
}
m := message.Message{}
for _, v := range imageList {
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Image(v)))
}
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
}

View File

@@ -27,7 +27,7 @@ type sea struct {
Time string `db:"time"` // we need to know the current time,master>
}
var seaSide = &sql.Sqlite{}
var seaSide sql.Sqlite
var seaLocker sync.RWMutex
// We need a container to inject what we need :(
@@ -39,15 +39,15 @@ func init() {
Help: "- @bot pick" + "- @bot throw xxx (xxx为投递内容)",
PrivateDataFolder: "driftbottle",
})
seaSide.DBPath = en.DataFolder() + "sea.db"
seaSide = sql.New(en.DataFolder() + "sea.db")
err := seaSide.Open(time.Hour)
if err != nil {
panic(err)
}
_ = createChannel(seaSide)
_ = createChannel(&seaSide)
en.OnFullMatch("pick", zero.OnlyToMe, zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
be, err := fetchBottle(seaSide)
be, err := fetchBottle(&seaSide)
if err != nil {
ctx.SendChain(message.Text("ERR:", err))
}
@@ -75,7 +75,7 @@ func init() {
senderFormatTime,
ctx.CardOrNickName(ctx.Event.UserID),
rawMessageCallBack,
).throw(seaSide)
).throw(&seaSide)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return

View File

@@ -195,55 +195,3 @@ var emojis = map[rune]int64{
127819: 20210521, // 🍋 lemon
127818: 20211115, // 🍊 tangerine orange
}
var qqface = map[int]rune{
0: 128558, // 😮 face exhaling
1: 128556, // 😬 grimacing face
2: 128525, // 😍 smiling face with heart-eyes
4: 128526, // 😎 smiling face with sunglasses
5: 128557, // 😭 loudly crying face
6: 129402, // 🥺 pleading face
7: 129296, // 🤐 zipper-mouth face
8: 128554, // 😪 sleepy face
11: 128545, // 😡 pouting face
12: 128539, // 😛 face with tongue
13: 128513, // 😁 beaming face with smiling eyes
14: 128578, // 🙂 slightly smiling face
15: 128577, // 🙁 slightly frowning face
16: 128526, // 😎 smiling face with sunglasses
19: 129326, // 🤮 face vomiting throw
20: 129325, // 🤭 face with hand over mouth embarrassed
21: 128522, // 😊 smiling face with smiling eyes
23: 128533, // 😕 confused face
24: 128523, // 😋 face savoring food
27: 128531, // 😓 downcast face with sweat
28: 128516, // 😄 grinning face with smiling eyes
31: 129324, // 🤬 face with symbols on mouth
32: 129300, // 🤔 thinking face question hmmm
33: 129323, // 🤫 shushing face quiet whisper
34: 128565, // 😵 face with crossed-out eyes
35: 128547, // 😣 persevering face
37: 128128, // 💀 skull
46: 128055, // 🐷 pig face
53: 127874, // 🎂 birthday cake
59: 128169, // 💩 pile of poo
60: 9749, // ☕ hot beverage coffee cup tea
63: 127801, // 🌹 rose flower
66: 10084, // ❤ mending heart
67: 128148, // 💔 broken heart
69: 127873, // 🎁 wrapped-gift
74: 127774, // 🌞 sun with face
75: 127772, // 🌜 last quarter moon face
96: 128517, // 😅 grinning face with sweat
104: 129393, // 🥱 yawning face
109: 128535, // 😗 kissing face
110: 128562, // 😲 astonished face
111: 129402, // 🥺 pleading face
172: 128539, // 😛 face with tongue
182: 128514, // 😂 face with tears of joy
187: 128123, // 👻 ghost
247: 128567, // 😷 face with medical mask
272: 128579, // 🙃 upside-down face
320: 129395, // 🥳 partying face
325: 128561, // 😱 face screaming in fear
}

View File

@@ -79,7 +79,7 @@ func match(ctx *zero.Ctx) bool {
return false
}
func face2emoji(face message.MessageSegment) rune {
func face2emoji(face message.Segment) rune {
if face.Type == "text" {
r := []rune(face.Data["text"])
if len(r) != 1 {
@@ -94,7 +94,7 @@ func face2emoji(face message.MessageSegment) rune {
if err != nil {
return 0
}
if r, ok := qqface[id]; ok {
if r, ok := message.Emoji[id]; ok {
return r
}
return 0

118
plugin/emozi/main.go Normal file
View File

@@ -0,0 +1,118 @@
// Package emozi 颜文字抽象转写
package emozi
import (
"os"
"strconv"
"strings"
"sync"
"time"
"github.com/FloatTech/AnimeAPI/emozi"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "颜文字抽象转写",
Help: "- 抽象转写[文段]\n- 抽象还原[文段]\n- 抽象登录[用户名]",
PrivateDataFolder: "emozi",
})
usr := emozi.Anonymous()
data, err := os.ReadFile(en.DataFolder() + "user.txt")
refresh := func() {
go func() {
t := time.NewTicker(time.Hour)
defer t.Stop()
for range t.C {
if !usr.IsValid() {
time.Sleep(time.Second * 2)
err := usr.Login()
if err != nil {
logrus.Warnln("[emozi] 重新登录账号失败:", err)
}
}
}
}()
}
refresher := sync.Once{}
if err == nil {
arr := strings.Split(string(data), "\n")
if len(arr) >= 2 {
usr = emozi.NewUser(arr[0], arr[1])
err = usr.Login()
if err != nil {
logrus.Infoln("[emozi]", "以", arr[0], "身份登录失败:", err)
usr = emozi.Anonymous()
} else {
logrus.Infoln("[emozi]", "以", arr[0], "身份登录成功")
refresher.Do(refresh)
}
}
}
en.OnPrefix("抽象转写").Limit(ctxext.LimitByUser).SetBlock(true).Handle(func(ctx *zero.Ctx) {
txt := strings.TrimSpace(ctx.State["args"].(string))
out, chs, err := usr.Marshal(false, txt)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if len(chs) == 0 {
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(out)))
return
}
for i, c := range chs {
ch := ctx.Get("请选择第" + strconv.Itoa(i) + "个多音字(1~" + strconv.Itoa(c) + ")")
n, err := strconv.Atoi(ch)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if n < 1 || n > c {
ctx.SendChain(message.Text("ERROR: 输入越界"))
return
}
chs[i] = n - 1
}
out, _, err = usr.Marshal(false, txt, chs...)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(out)))
})
en.OnPrefix("抽象还原").Limit(ctxext.LimitByUser).SetBlock(true).Handle(func(ctx *zero.Ctx) {
txt := strings.TrimSpace(ctx.State["args"].(string))
out, err := usr.Unmarshal(false, txt)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(out)))
})
en.OnPrefix("抽象登录", zero.OnlyPrivate).Limit(ctxext.LimitByUser).SetBlock(true).Handle(func(ctx *zero.Ctx) {
name := strings.TrimSpace(ctx.State["args"].(string))
pswd := strings.TrimSpace(ctx.Get("请输入密码"))
newusr := emozi.NewUser(name, pswd)
err := newusr.Login()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
err = os.WriteFile(en.DataFolder()+"user.txt", []byte(name+"\n"+pswd), 0644)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
usr = newusr
refresher.Do(refresh)
ctx.SendChain(message.Text("成功"))
})
}

View File

@@ -146,7 +146,7 @@ func init() {
digest := md5.Sum(helper.StringToBytes(zipfile + strconv.Itoa(index) + title + text))
cachefile := cache + hex.EncodeToString(digest[:])
err = pool.SendImageFromPool(cachefile, cachefile, func() error {
err = pool.SendImageFromPool(cachefile, func(cachefile string) error {
f, err := os.Create(cachefile)
if err != nil {
return err
@@ -154,7 +154,7 @@ func init() {
_, err = draw(background, fontdata, title, text, f)
_ = f.Close()
return err
}, ctxext.Send(ctx), ctxext.GetMessage(ctx))
}, ctxext.Send(ctx))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return

View File

@@ -21,7 +21,7 @@ type joke struct {
Text string `db:"text"`
}
var db = &sql.Sqlite{}
var db sql.Sqlite
func init() {
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
@@ -32,7 +32,7 @@ func init() {
})
en.OnPrefixGroup([]string{"讲个笑话", "夸夸"}, fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = en.DataFolder() + "jokes.db"
db = sql.New(en.DataFolder() + "jokes.db")
_, err := en.GetLazyData("jokes.db", true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))

View File

@@ -20,7 +20,7 @@ func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
defer wg.Done()
target := datapath + `materials/` + name
if file.IsNotExist(target) {
data, err := web.RequestDataWith(web.NewTLS12Client(), `https://gitcode.net/m0_60838134/imagematerials/-/raw/main/`+name, "GET", "gitcode.net", web.RandUA(), nil)
data, err := web.GetData(`https://gitea.seku.su/fumiama/ImageMaterials/raw/branch/main/` + name)
if err != nil {
_ = os.Remove(target)
exit(err)
@@ -48,7 +48,7 @@ func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
func dlblock(name string) (string, error) {
target := datapath + `materials/` + name
if file.IsNotExist(target) {
data, err := web.RequestDataWith(web.NewTLS12Client(), `https://gitcode.net/m0_60838134/imagematerials/-/raw/main/`+name, "GET", "gitcode.net", web.RandUA(), nil)
data, err := web.GetData(`https://gitea.seku.su/fumiama/ImageMaterials/raw/branch/main/` + name)
if err != nil {
_ = os.Remove(target)
return "", err
@@ -87,13 +87,13 @@ func dlrange(prefix string, end int, wg *sync.WaitGroup, exit func(error)) []str
}
// 新的上下文
func newContext(user int64) *context {
func newContext(user int64, atUser int64) *context {
c := new(context)
c.usrdir = datapath + "users/" + strconv.FormatInt(user, 10) + `/`
c.usrdir = datapath + "users/" + strconv.FormatInt(atUser, 10) + `/`
_ = os.MkdirAll(c.usrdir, 0755)
c.headimgsdir = make([]string, 2)
c.headimgsdir[0] = c.usrdir + "0.gif"
c.headimgsdir[1] = c.usrdir + "1.gif"
c.headimgsdir[0] = datapath + "users/" + strconv.FormatInt(atUser, 10) + ".gif"
c.headimgsdir[1] = datapath + "users/" + strconv.FormatInt(user, 10) + ".gif"
return c
}

View File

@@ -14,9 +14,9 @@ func (cc *context) prepareLogos(s ...string) error {
for i, v := range s {
_, err := strconv.Atoi(v)
if err != nil {
err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.usrdir+strconv.Itoa(i)+".gif")
err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.headimgsdir[i])
} else {
err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif")
err = file.DownloadTo("https://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.headimgsdir[i])
}
if err != nil {
return err

View File

@@ -150,10 +150,11 @@ func init() { // 插件主体
PrivateDataFolder: "gif",
}).ApplySingle(ctxext.DefaultSingle)
datapath = file.BOTPATH + "/" + en.DataFolder()
en.OnRegex(`^(` + strings.Join(cmd, "|") + `)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`).
en.OnRegex(`^(` + strings.Join(cmd, "|") + `)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?qq=(\d{5,11})).*\].*|(\d+))$`).
SetBlock(true).Handle(func(ctx *zero.Ctx) {
c := newContext(ctx.Event.UserID)
list := ctx.State["regex_matched"].([]string)
atUserID, _ := strconv.ParseInt(list[4]+list[5]+list[6], 10, 64)
c := newContext(ctx.Event.UserID, atUserID)
err := c.prepareLogos(list[4]+list[5]+list[6], strconv.FormatInt(ctx.Event.UserID, 10))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))

View File

@@ -2,15 +2,14 @@
package github
import (
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/fumiama/terasu/http2"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -26,14 +25,14 @@ func init() { // 插件主体
}).OnRegex(`^>github\s(-.{1,10}? )?(.*)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 发送请求
header := http.Header{
"User-Agent": []string{"User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"},
}
api, _ := url.Parse("https://api.github.com/search/repositories")
api.RawQuery = url.Values{
"q": []string{ctx.State["regex_matched"].([]string)[2]},
}.Encode()
body, err := netGet(api.String(), header)
body, err := web.RequestDataWithHeaders(&http2.DefaultClient, api.String(), "GET", func(r *http.Request) error {
r.Header.Set("User-Agent", web.RandUA())
return nil
}, nil)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
}
@@ -96,36 +95,9 @@ func init() { // 插件主体
}
// notnull 如果传入文本为空,则返回默认值
func notnull(text string) string {
if text == "" {
return "None"
}
return text
}
// netGet 返回请求结果
func netGet(dest string, header http.Header) ([]byte, error) {
client := &http.Client{}
req, err := http.NewRequest("GET", dest, nil)
if err != nil {
return nil, err
}
req.Header = header
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if code := resp.StatusCode; code != 200 {
// 如果返回不是200则立刻抛出错误
errmsg := fmt.Sprintf("code %d", code)
return nil, errors.New(errmsg)
}
return body, nil
}

View File

@@ -246,11 +246,7 @@ func init() {
ctx.SendChain(message.Text(serviceErr, err))
return
}
if err == nil {
ctx.SendChain(message.Text("成功!"))
} else {
ctx.SendChain(message.Text(serviceErr, err))
}
ctx.SendChain(message.Text("成功!"))
})
// 下载歌曲到对应的歌单里面
engine.OnRegex(`^下载歌单\s*((https:\/\/music\.163\.com\/#\/playlist\?id=)?(\d+)|http:\/\/music\.163\.com\/playlist\/(\d+).*[^\s$])\s*到\s*(.*)$`, zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByGroup).

View File

@@ -109,6 +109,12 @@ func init() {
ctx.SendChain(message.Text(err))
return
}
// 猜歌环节-提供猜歌选项
files, err := os.ReadDir(pathOfMusic)
if err != nil {
return
}
getMusicSelect(ctx, files, musicName)
// 进行猜歌环节
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + "0.wav"))
var next *zero.FutureEvent
@@ -124,10 +130,10 @@ func init() {
after := time.NewTimer(120 * time.Second)
wg := sync.WaitGroup{}
var (
messageStr message.MessageSegment // 文本信息
tickCount = 0 // 音频数量
answerCount = 0 // 问答次数
win bool // 是否赢得游戏
messageStr message.Segment // 文本信息
tickCount = 0 // 音频数量
answerCount = 0 // 问答次数
win bool // 是否赢得游戏
)
for {
select {
@@ -221,26 +227,8 @@ func musicLottery(musicPath, listName string) (pathOfMusic, musicName string, er
}
return
}
// 进行随机抽取
if playlistID == 0 || !cfg.API {
musicName = getLocalMusic(files, 10)
} else {
switch rand.Intn(3) { // 三分二概率抽取API的
case 1:
musicName = getLocalMusic(files, 10)
default:
if cfg.APIURL == "" {
// 如果没有配置过API地址,尝试连接独角兽
musicName, err = downloadByOvooa(playlistID, pathOfMusic)
} else {
// 从API中抽取歌曲
musicName, err = drawByAPI(playlistID, pathOfMusic)
}
if err != nil {
musicName = getLocalMusic(files, 10)
}
}
}
// 只猜本地已经下好的歌曲
musicName = getLocalMusic(files, 10)
if musicName == "" {
err = errors.New("抽取歌曲轮空了,请重试")
}
@@ -293,17 +281,15 @@ 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) {
func gameMatch(c *zero.Ctx, beginner int64, musicInfo []string, answerTimes, tickTimes int) (message.Segment, 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 {
return message.Text("游戏已取消,猜歌答案是\n", musicInfo[len(musicInfo)-1], "\n\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true
return message.Text("游戏已取消,猜歌答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true
}
return message.Text("你无权限取消"), answerTimes, tickTimes, false
case answer == "提示":
@@ -312,11 +298,11 @@ func gameMatch(c *zero.Ctx, beginner int64, musicInfo []string, answerTimes, tic
return message.Text("已经没有提示了哦"), answerTimes, tickTimes, false
}
return message.Text("再听这段音频,要仔细听哦"), answerTimes, tickTimes, false
case strings.Contains(musicInfo[0], answer) || strings.EqualFold(musicInfo[0], answer):
case strings.Contains(ConvertText(musicInfo[0]), answer) || strings.EqualFold(ConvertText(musicInfo[0]), answer):
return message.Text("太棒了,你猜对歌曲名了!答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true
case strings.Contains(musicInfo[1], answer) || strings.EqualFold(musicInfo[1], answer):
case strings.Contains(ConvertText(musicInfo[1]), answer) || strings.EqualFold(ConvertText(musicInfo[1]), answer):
return message.Text("太棒了,你猜对歌手名了!答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true
case len(musicInfo) == 4 && (strings.Contains(musicInfo[2], answer) || strings.EqualFold(musicInfo[2], answer)):
case len(musicInfo) == 4 && (strings.Contains(ConvertText(musicInfo[2]), answer) || strings.EqualFold(ConvertText(musicInfo[2]), answer)):
return message.Text("太棒了,你猜对相关信息了!答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true
default:
answerTimes++
@@ -343,3 +329,39 @@ func ConvertText(input string) string {
}
return toLower
}
func getMusicSelect(ctx *zero.Ctx, files []fs.DirEntry, musicName string) {
// 生成音乐选项
var musicInfo []string
musicInfo = append(musicInfo, musicName)
for i := 1; i < 4; i++ {
musicInfo = append(musicInfo, getLocalMusic(files, 10))
for musicInfo[0] == musicInfo[i] {
musicInfo[i] = getLocalMusic(files, 10)
}
}
// 对调正确答案
j := rand.Intn(len(musicInfo))
musicInfo[0], musicInfo[j] = musicInfo[j], musicInfo[0]
musicNameSelect := "请选出正确歌曲:\n"
for i := 0; i < len(musicInfo); i++ {
// 解析歌曲信息
music := strings.Split(musicInfo[i], ".")
// 获取音乐后缀
musicType := music[len(music)-1]
if !strings.Contains(musictypelist, musicType) {
ctx.SendChain(message.Text("抽取到了歌曲:\n",
musicInfo[i], "\n该歌曲不是音乐后缀,请联系bot主人修改"))
}
// 获取音乐信息
musicInfo := strings.Split(strings.ReplaceAll(musicInfo[i], "."+musicType, ""), " - ")
infoNum := len(musicInfo)
if infoNum == 1 {
ctx.SendChain(message.Text("抽取到了歌曲:\n",
musicInfo[i], "\n该歌曲命名不符合命名规则,请联系bot主人修改"))
}
musicNameSelect += musicInfo[0] + " 歌手:" + musicInfo[1] + "\n"
}
ctx.SendChain(message.Text(musicNameSelect))
}

View File

@@ -32,7 +32,7 @@ var (
cfg config
// 插件主体
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
DisableOnDefault: true,
Brief: "猜歌插件",
Help: "------bot主人指令------\n" +
"- 设置猜歌歌库路径 [绝对路径]\n" +
@@ -535,7 +535,7 @@ func getFileURLbyFileName(ctx *zero.Ctx, fileName string) (fileSearchName, fileU
for _, fileNameOflist := range files {
if strings.Contains(fileNameOflist.Get("file_name").String(), fileName) {
fileSearchName = fileNameOflist.Get("file_name").String()
fileURL = ctx.GetThisGroupFileUrl(fileNameOflist.Get("busid").Int(), fileNameOflist.Get("file_id").String())
fileURL = ctx.GetThisGroupFileURL(fileNameOflist.Get("busid").Int(), fileNameOflist.Get("file_id").String())
return
}
}
@@ -561,7 +561,7 @@ func getFileURLbyfolderID(ctx *zero.Ctx, fileName, folderid string) (fileSearchN
for _, fileNameOflist := range files {
if strings.Contains(fileNameOflist.Get("file_name").String(), fileName) {
fileSearchName = fileNameOflist.Get("file_name").String()
fileURL = ctx.GetThisGroupFileUrl(fileNameOflist.Get("busid").Int(), fileNameOflist.Get("file_id").String())
fileURL = ctx.GetThisGroupFileURL(fileNameOflist.Get("busid").Int(), fileNameOflist.Get("file_id").String())
return
}
}

View File

@@ -1,119 +0,0 @@
// Package heisi 黑丝
package heisi
import (
"errors"
"math/rand"
"os"
"strconv"
"time"
"unsafe"
"github.com/FloatTech/AnimeAPI/setu"
fbctxext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/file"
"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"
)
var (
heisiPic []item
baisiPic []item
jkPic []item
jurPic []item
zukPic []item
mcnPic []item
fileList = [...]string{"heisi.bin", "baisi.bin", "jk.bin", "jur.bin", "zuk.bin", "mcn.bin"}
)
func init() { // 插件主体
p, err := setu.NewPool(setu.DefaultPoolDir,
func(s string) (string, error) {
if s != "黑丝" && s != "白丝" && s != "jk" && s != "巨乳" && s != "足控" && s != "网红" {
return "", errors.New("invalid call")
}
typ := setu.DefaultPoolDir + "/" + s
if file.IsNotExist(typ) {
err := os.MkdirAll(typ, 0755)
if err != nil {
return "", err
}
}
var pic item
switch s {
case "黑丝":
pic = heisiPic[rand.Intn(len(heisiPic))]
case "白丝":
pic = baisiPic[rand.Intn(len(baisiPic))]
case "jk":
pic = jkPic[rand.Intn(len(jkPic))]
case "巨乳":
pic = jurPic[rand.Intn(len(jurPic))]
case "足控":
pic = zukPic[rand.Intn(len(zukPic))]
case "网红":
pic = mcnPic[rand.Intn(len(mcnPic))]
}
return pic.String(), nil
}, func(s string) ([]byte, error) {
return web.RequestDataWith(web.NewTLS12Client(), s, "GET", "http://hs.heisiwu.com/", web.RandUA(), nil)
}, time.Minute)
if err != nil {
panic(err)
}
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "黑丝",
Help: "- 来点黑丝\n- 来点白丝\n- 来点jk\n- 来点巨乳\n- 来点足控\n- 来点网红",
PublicDataFolder: "Heisi",
})
engine.OnFullMatchGroup([]string{"来点黑丝", "来点白丝", "来点jk", "来点巨乳", "来点足控", "来点网红"}, zero.OnlyGroup, fbctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
for i, filePath := range fileList {
data, err := engine.GetLazyData(filePath, true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
if len(data)%10 != 0 {
ctx.SendChain(message.Text("ERROR: invalid data " + strconv.Itoa(i)))
return false
}
s := (*slice)(unsafe.Pointer(&data))
s.len /= 10
s.cap /= 10
switch i {
case 0:
heisiPic = *(*[]item)(unsafe.Pointer(s))
case 1:
baisiPic = *(*[]item)(unsafe.Pointer(s))
case 2:
jkPic = *(*[]item)(unsafe.Pointer(s))
case 3:
jurPic = *(*[]item)(unsafe.Pointer(s))
case 4:
zukPic = *(*[]item)(unsafe.Pointer(s))
case 5:
mcnPic = *(*[]item)(unsafe.Pointer(s))
}
}
return true
})).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
matched := ctx.State["matched"].(string)
pic, err := p.Roll(matched[3*2:])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image("file:///"+file.BOTPATH+"/"+pic))}
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
})
}

View File

@@ -1,48 +0,0 @@
package heisi
import (
"encoding/binary"
"encoding/hex"
"fmt"
"math/bits"
)
const (
template2021 = "http://hs.heisiwu.com/wp-content/uploads/%4d/%02d/%4d%02d16%06d-611a3%8s.jpg"
templategeneral = "http://hs.heisiwu.com/wp-content/uploads/%4d/%02d/%015x"
)
type item [10]byte
// String item to url
func (it item) String() string {
year, month := int((it[0]>>4)&0x0f), int(it[0]&0x0f)
year += 2021
if year == 2021 {
num := binary.BigEndian.Uint32(it[1:5])
dstr := hex.EncodeToString(it[5:9])
return fmt.Sprintf(template2021, year, month, year, month, num, dstr)
}
d := binary.BigEndian.Uint64(it[1:9])
isscaled := it[9]&0x80 > 0
num := int(it[9] & 0x7f)
trestore := fmt.Sprintf(templategeneral, year, month, d&0x0fffffff_ffffffff)
if num > 0 {
trestore += fmt.Sprintf("-%d", num)
}
if isscaled {
trestore += "-scaled"
}
d = bits.RotateLeft64(d, 4) & 0x0f
switch d {
case 0:
trestore += ".jpg"
case 1:
trestore += ".png"
case 2:
trestore += ".webp"
default:
return "invalid ext"
}
return trestore
}

View File

@@ -1,15 +0,0 @@
package heisi
import "unsafe"
// slice is the runtime representation of a slice.
// It cannot be used safely or portably and its representation may
// change in a later release.
//
// Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the
// data it references will not be garbage collected.
type slice struct {
data unsafe.Pointer
len int
cap int
}

View File

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

View File

@@ -6,7 +6,7 @@ import (
sql "github.com/FloatTech/sqlite"
)
var db = &sql.Sqlite{}
var db sql.Sqlite
var mu sync.RWMutex
type picture struct {

View File

@@ -10,6 +10,7 @@ import (
"github.com/FloatTech/floatbox/binary"
fcext "github.com/FloatTech/floatbox/ctxext"
sql "github.com/FloatTech/sqlite"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/antchfx/htmlquery"
@@ -31,7 +32,7 @@ func init() {
})
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = engine.DataFolder() + "pics.db"
db = sql.New(engine.DataFolder() + "pics.db")
_, _ = engine.GetLazyData("pics.db", false)
err := db.Open(time.Hour)
if err != nil {
@@ -95,7 +96,7 @@ func init() {
u := "https:" + v.Attr[0].Val
i := crc64.Checksum(binary.StringToBytes(u), crc64.MakeTable(crc64.ISO))
mu.RLock()
ok := db.CanFind("picture", "where id="+strconv.FormatUint(i, 10))
ok := db.CanFind("picture", "WHERE id = ?", i)
mu.RUnlock()
if !ok {
mu.Lock()

View File

@@ -1,65 +0,0 @@
// Package jiami 兽语加密与解密
package jiami
import (
"encoding/json"
"fmt"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
jiami1 = "http://ovooa.caonm.net/API/sho_u/?msg=%v" // 加密api地址
jiami2 = "http://ovooa.caonm.net/API/sho_u/?format=1&msg=%v" // 解密api地址
)
type nmd struct { // struct解析格式大概是
Data struct {
Message string
} `json:"data"`
}
func init() { // 主函数
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "兽语加解密",
Help: "兽语加解密\n" +
"- 兽语加密xxx\n- 兽语解密xxx",
})
en.OnRegex(`^兽语加密\s*(.+)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es, err := web.GetData(fmt.Sprintf(jiami1, str)) // 将网站返回结果赋值
if err != nil {
ctx.SendChain(message.Text("出现错误捏:", err))
return
}
var r nmd // r数组
err = json.Unmarshal(es, &r) // 填api返回结果struct地址
if err != nil {
ctx.SendChain(message.Text("出现错误捏:", err))
return
}
ctx.SendChain(message.Text(r.Data.Message)) // 输出提取后的结果
})
en.OnRegex(`^兽语解密\s*(.+)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es, err := web.GetData(fmt.Sprintf(jiami2, str)) // 将网站返回结果赋值
if err != nil {
ctx.SendChain(message.Text("出现错误捏:", err))
return
}
var n nmd // r数组
err = json.Unmarshal(es, &n) // 填api返回结果struct地址
if err != nil {
ctx.SendChain(message.Text("出现错误捏:", err))
return
}
ctx.SendChain(message.Text(n.Data.Message)) // 输出提取后的结果
})
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/FloatTech/floatbox/binary"
fcext "github.com/FloatTech/floatbox/ctxext"
sql "github.com/FloatTech/sqlite"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img/text"
@@ -26,7 +27,7 @@ func init() { // 插件主体
})
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = engine.DataFolder() + "item.db"
db = sql.New(engine.DataFolder() + "item.db")
_, err := engine.GetLazyData("item.db", true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))

View File

@@ -17,14 +17,16 @@ type item struct {
Datetime time.Time `db:"datetime"`
}
var db = &sql.Sqlite{}
var db sql.Sqlite
func getRandomAudioByCategory(category string) (t item) {
_ = db.Find("item", &t, "where category = '"+category+"' ORDER BY RANDOM() limit 1")
_ = db.Find("item", &t, "WHERE category = ? ORDER BY RANDOM() limit 1", category)
return
}
func getRandomAudioByCategoryAndKeyword(category string, keyword string) (t item) {
_ = db.Find("item", &t, "where category = '"+category+"' and (title like '%"+keyword+"%' or content like '%"+keyword+"%') ORDER BY RANDOM() limit 1")
_ = db.Find("item", &t,
"WHERE category = ? and (title LIKE ? OR content LIKE ?) ORDER BY RANDOM() limit 1",
category, "%"+keyword+"%", "%"+keyword+"%")
return
}

View File

@@ -1,71 +0,0 @@
// Package juejuezi 绝绝子
package juejuezi
import (
"fmt"
"io"
"net/http"
"strings"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
)
const (
juejueziURL = "https://www.offjuan.com/api/juejuezi/text"
referer = "https://juejuezi.offjuan.com/"
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
)
func init() {
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "绝绝子生成器",
Help: "例: 喝奶茶绝绝子\n绝绝子吃饭",
}).OnRegex("[\u4E00-\u9FA5]{0,10}绝绝子[\u4E00-\u9FA5]{0,10}").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
toDealStr := []rune(strings.ReplaceAll(ctx.ExtractPlainText(), "绝绝子", ""))
switch len(toDealStr) {
case 0, 1:
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("不要只输入绝绝子"))
case 2:
data, err := juejuezi(string(toDealStr[0]), string(toDealStr[1]))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text(gjson.Get(helper.BytesToString(data), "text").String()))
default:
params := ctx.GetWordSlices(string(toDealStr)).Get("slices").Array()
data, err := juejuezi(params[0].String(), params[1].String())
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text(gjson.Get(helper.BytesToString(data), "text").String()))
}
})
}
func juejuezi(verb, noun string) (data []byte, err error) {
juejueziStr := fmt.Sprintf("{\"verb\":\"%s\",\"noun\":\"%s\"}", verb, noun)
client := &http.Client{}
// 提交请求
request, err := http.NewRequest("POST", juejueziURL, strings.NewReader(juejueziStr))
if err != nil {
return nil, err
}
request.Header.Add("Referer", referer)
request.Header.Add("User-Agent", ua)
response, err := client.Do(request)
if err != nil {
return nil, err
}
data, err = io.ReadAll(response.Body)
response.Body.Close()
return
}

View File

@@ -11,7 +11,7 @@ import (
)
const (
crazyURL = "https://api.jixs.cc/api/wenan-fkxqs/index.php"
crazyURL = "http://api.jixs.cc/api/wenan-fkxqs/index.php"
)
func init() {

View File

@@ -18,7 +18,6 @@ import (
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
imagepool "github.com/FloatTech/zbputils/img/pool"
)
const (
@@ -68,18 +67,7 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err))
continue
}
name := imageurl[strings.LastIndex(imageurl, "/")+1 : len(imageurl)-4]
m, err := imagepool.GetImage(name)
if err != nil {
m.SetFile(imageurl)
_, _ = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
process.SleepAbout1sTo2s()
}
if err == nil {
queue <- m.String()
} else {
queue <- imageurl
}
queue <- imageurl
}
}()
select {

View File

@@ -18,7 +18,7 @@ import (
const gistraw = "https://gist.githubusercontent.com/%s/%s/raw/%s"
func checkNewUser(qq, gid int64, ghun, hash string) (bool, string) {
if db.CanFind("member", "where ghun="+ghun) {
if db.CanFind("member", "WHERE ghun = ?", ghun) {
return false, "该github用户已入群"
}
gidsum := md5.Sum(helper.StringToBytes(strconv.FormatInt(gid, 10)))

View File

@@ -4,6 +4,7 @@ package manager
import (
"fmt"
"math/rand"
"regexp"
"sort"
"strconv"
"strings"
@@ -35,6 +36,7 @@ const (
"- 修改名片@QQ XXX\n" +
"- 修改头衔@QQ XXX\n" +
"- 申请头衔 XXX\n" +
"- 对信息回复: 撤回\n" +
"- 踢出群聊@QQ\n" +
"- 退出群聊 1234@bot\n" +
"- 群聊转发 1234 XXX\n" +
@@ -48,19 +50,20 @@ const (
"- 列出所有提醒\n" +
"- 翻牌\n" +
"- 赞我\n" +
"- 对信息回复: 回应表情 [表情]\n" +
"- 设置欢迎语XXX 可选添加 [{at}] [{nickname}] [{avatar}] [{uid}] [{gid}] [{groupname}]\n" +
"- 测试欢迎语\n" +
"- 设置告别辞 参数同设置欢迎语\n" +
"- 测试告别辞\n" +
"- [开启 | 关闭]入群验证\n" +
"- 对信息回复:[设置 | 取消]精华\n" +
"- 对信息回复: [设置 | 取消]精华\n" +
"- 取消精华 [信息ID]\n" +
"- /精华列表\n" +
"Tips: {at}可在发送时艾特被欢迎者 {nickname}是被欢迎者名字 {avatar}是被欢迎者头像 {uid}是被欢迎者QQ号 {gid}是当前群群号 {groupname} 是当前群群名"
)
var (
db = &sql.Sqlite{}
db sql.Sqlite
clock timer.Clock
)
@@ -73,12 +76,12 @@ func init() { // 插件主体
})
go func() {
db.DBPath = engine.DataFolder() + "config.db"
db = sql.New(engine.DataFolder() + "config.db")
err := db.Open(time.Hour)
if err != nil {
panic(err)
}
clock = timer.NewClock(db)
clock = timer.NewClock(&db)
err = db.Create("welcome", &welcome{})
if err != nil {
panic(err)
@@ -153,10 +156,11 @@ func init() { // 插件主体
ctx.SendChain(message.Text("全员自闭结束~"))
})
// 禁言
engine.OnRegex(`^禁言.*?(\d+).*?\s(\d+)(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
engine.OnMessage(zero.NewPattern(nil).Text("^禁言").At().Text("(\\d+)\\s*(.*)").AsRule(), zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
duration := math.Str2Int64(ctx.State["regex_matched"].([]string)[2])
switch ctx.State["regex_matched"].([]string)[3] {
parsed := ctx.State[zero.KeyPattern].([]zero.PatternParsed)
duration := math.Str2Int64(parsed[2].Text()[1])
switch parsed[2].Text()[2] {
case "分钟":
//
case "小时":
@@ -170,8 +174,8 @@ func init() { // 插件主体
duration = 43199 // qq禁言最大时长为一个月
}
ctx.SetThisGroupBan(
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 要禁言的人的qq
duration*60, // 要禁言的时间(分钟)
math.Str2Int64(parsed[1].At()), // 要禁言的人的qq
duration*60, // 要禁言的时间(分钟)
)
ctx.SendChain(message.Text("小黑屋收留成功~"))
})
@@ -260,9 +264,7 @@ func init() { // 插件主体
engine.OnRegex(`^\[CQ:reply,id=(-?\d+)\].*撤回$`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 删除需要撤回的消息ID
ctx.DeleteMessage(message.NewMessageIDFromString(ctx.State["regex_matched"].([]string)[1]))
// 删除请求撤回的消息ID
// ctx.DeleteMessage(message.NewMessageIDFromInteger(ctx.Event.MessageID.(int64)))
ctx.DeleteMessage(ctx.State["regex_matched"].([]string)[1])
})
// 群聊转发
engine.OnRegex(`^群聊转发.*?(\d+)\s(.*)`, zero.SuperUserPermission).SetBlock(true).
@@ -397,18 +399,51 @@ func init() { // 插件主体
}
}
if !flag {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("不加好友不给赞!"))
// ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("不加好友不给赞!"))
return
}
ctx.SendLike(ctx.Event.UserID, 10)
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("给你赞了10下哦记得回我~"))
})
facere := regexp.MustCompile(`\[CQ:face,id=(\d+)\]`)
// 给消息回应表情
engine.OnRegex(`^\[CQ:reply,id=(-?\d+)\].*回应表情\s*(.+)\s*$`, zero.AdminPermission, zero.OnlyGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
msgid := ctx.State["regex_matched"].([]string)[1]
face := ctx.State["regex_matched"].([]string)[2]
if len(face) == 0 {
ctx.SendChain(message.Text("ERROR: 表情长度为 0"))
return
}
ids := facere.FindStringSubmatch(face)
id := rune(0)
if len(ids) == 2 && len(ids[1]) > 0 {
idi, err := strconv.Atoi(ids[1])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
id = rune(idi)
} else {
x := []rune(face)
if len(x) == 0 {
ctx.SendChain(message.Text("ERROR: 解析后表情长度为 0"))
return
}
id = x[0]
}
err := ctx.SetMessageEmojiLike(msgid, id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
})
// 入群欢迎
engine.OnNotice().SetBlock(false).
Handle(func(ctx *zero.Ctx) {
if ctx.Event.NoticeType == "group_increase" && ctx.Event.SelfID != ctx.Event.UserID {
var w welcome
err := db.Find("welcome", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
err := db.Find("welcome", &w, "WHERE gid = ?", ctx.Event.GroupID)
if err == nil {
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
} else {
@@ -460,12 +495,12 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
if ctx.Event.NoticeType == "group_decrease" {
var w welcome
err := db.Find("farewell", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
err := db.Find("farewell", &w, "WHERE gid = ?", ctx.Event.GroupID)
if err == nil {
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
collectsend(ctx, message.ParseMessageFromString(welcometocq(ctx, w.Msg))...)
} else {
userid := ctx.Event.UserID
ctx.SendChain(message.Text(ctx.CardOrNickName(userid), "(", userid, ")", "离开了我们..."))
collectsend(ctx, message.Text(ctx.CardOrNickName(userid), "(", userid, ")", "离开了我们..."))
}
}
})
@@ -489,7 +524,7 @@ func init() { // 插件主体
engine.OnFullMatch("测试欢迎语", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
var w welcome
err := db.Find("welcome", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
err := db.Find("welcome", &w, "WHERE gid = ?", ctx.Event.GroupID)
if err == nil {
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
} else {
@@ -516,7 +551,7 @@ func init() { // 插件主体
engine.OnFullMatch("测试告别辞", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
var w welcome
err := db.Find("farewell", &w, "where gid = "+strconv.FormatInt(ctx.Event.GroupID, 10))
err := db.Find("farewell", &w, "WHERE gid = ?", ctx.Event.GroupID)
if err == nil {
ctx.SendGroupMessage(ctx.Event.GroupID, message.ParseMessageFromString(welcometocq(ctx, w.Msg)))
} else {
@@ -615,7 +650,7 @@ func init() { // 插件主体
if rsp.RetCode == 0 {
ctx.SendChain(message.Text(option, "成功"))
} else {
ctx.SendChain(message.Text(option, "失败, 信息: ", rsp.Msg, "解释: ", rsp.Wording))
ctx.SendChain(message.Text(option, "失败, 信息: ", rsp.Message, "解释: ", rsp.Wording))
}
})
engine.OnCommand("精华列表", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
@@ -639,7 +674,7 @@ func init() { // 插件主体
time.Unix(info.Get("operator_time").Int(), 0).Format("2006/01/02 15:04:05"),
))),
)
msgData := ctx.GetMessage(message.NewMessageIDFromInteger(info.Get("message_id").Int())).Elements
msgData := ctx.GetMessage(info.Get("message_id").Int()).Elements
if msgData != nil {
msg = append(msg,
message.CustomNode(info.Get("sender_nick").String(), info.Get("sender_id").Int(), msgData),
@@ -664,19 +699,19 @@ func init() { // 插件主体
if rsp.RetCode == 0 {
ctx.SendChain(message.Text("取消成功"))
} else {
ctx.SendChain(message.Text("取消失败, 信息: ", rsp.Msg, "解释: ", rsp.Wording))
ctx.SendChain(message.Text("取消失败, 信息: ", rsp.Message, "解释: ", rsp.Wording))
}
})
}
// 传入 ctx 和 welcome格式string 返回cq格式string 使用方法:welcometocq(ctx,w.Msg)
func welcometocq(ctx *zero.Ctx, welcome string) string {
uid := strconv.FormatInt(ctx.Event.UserID, 10) // 用户id
nickname := ctx.CardOrNickName(ctx.Event.UserID) // 用户昵称
at := "[CQ:at,qq=" + uid + "]" // at用户
avatar := "[CQ:image,file=" + "http://q4.qlogo.cn/g?b=qq&nk=" + uid + "&s=640]" // 用户头像
gid := strconv.FormatInt(ctx.Event.GroupID, 10) // 群id
groupname := ctx.GetThisGroupInfo(true).Name // 群名
uid := strconv.FormatInt(ctx.Event.UserID, 10) // 用户id
nickname := ctx.CardOrNickName(ctx.Event.UserID) // 用户昵称
at := "[CQ:at,qq=" + uid + "]" // at用户
avatar := "[CQ:image,file=" + "https://q4.qlogo.cn/g?b=qq&nk=" + uid + "&s=640]" // 用户头像
gid := strconv.FormatInt(ctx.Event.GroupID, 10) // 群id
groupname := ctx.GetThisGroupInfo(true).Name // 群名
cqstring := strings.ReplaceAll(welcome, "{at}", at)
cqstring = strings.ReplaceAll(cqstring, "{nickname}", nickname)
cqstring = strings.ReplaceAll(cqstring, "{avatar}", avatar)

46
plugin/manager/slow.go Normal file
View File

@@ -0,0 +1,46 @@
package manager
import (
"time"
"github.com/RomiChan/syncx"
"github.com/fumiama/slowdo"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var slowsenders = syncx.Map[int64, *syncx.Lazy[*slowdo.Job[*zero.Ctx, message.Segment]]]{}
func collectsend(ctx *zero.Ctx, msgs ...message.Segment) {
id := ctx.Event.GroupID
if id == 0 {
// only support group
return
}
lazy, _ := slowsenders.LoadOrStore(id, &syncx.Lazy[*slowdo.Job[*zero.Ctx, message.Segment]]{
Init: func() *slowdo.Job[*zero.Ctx, message.Segment] {
x, err := slowdo.NewJob(time.Second*5, ctx, func(ctx *zero.Ctx, msg []message.Segment) {
if len(msg) == 1 {
ctx.Send(msg)
return
}
m := make(message.Message, len(msg))
for i, item := range msg {
m[i] = message.CustomNode(
zero.BotConfig.NickName[0],
ctx.Event.SelfID,
message.Message{item})
}
ctx.SendGroupForwardMessage(id, m)
})
if err != nil {
panic(err)
}
return x
},
})
job := lazy.Get()
for _, msg := range msgs {
job.Add(msg)
}
}

View File

@@ -96,12 +96,12 @@ func GetFilledTimer(dateStrs []string, botqq, grp int64, matchDateOnly bool) *Ti
if len(minuteStr) == 3 {
minuteStr = []rune{minuteStr[0], minuteStr[2]} // 去除中间的十
}
min := chineseNum2Int(minuteStr)
if min < -1 || min > 59 { // 分钟非法
minute := chineseNum2Int(minuteStr)
if minute < -1 || minute > 59 { // 分钟非法
t.Alert = "分钟非法!"
return &t
}
t.SetMinute(min)
t.SetMinute(minute)
if !matchDateOnly {
urlStr := dateStrs[5]
if urlStr != "" { // 是图片url

View File

@@ -22,7 +22,7 @@ func (t *Timer) InsertInto(db *sql.Sqlite) error {
/*
func getTimerFrom(db *sql.Sqlite, id uint32) (t Timer, err error) {
err = db.Find("timer", &t, "where id = "+strconv.Itoa(int(id)))
err = db.Find("timer", &t, "WHERE id = "+strconv.Itoa(int(id)))
return
}
*/

View File

@@ -2,7 +2,6 @@
package timer
import (
"strconv"
"strings"
"sync"
"time"
@@ -29,7 +28,7 @@ type Clock struct {
var (
// @全体成员
atall = message.MessageSegment{
atall = message.Segment{
Type: "at",
Data: map[string]string{
"qq": "all",
@@ -133,7 +132,7 @@ func (c *Clock) CancelTimer(key uint32) bool {
}
c.timersmu.Lock()
delete(*c.timers, key) // 避免重复取消
e := c.db.Del("timer", "where id = "+strconv.Itoa(int(key)))
e := c.db.Del("timer", "WHERE id = ?", key)
c.timersmu.Unlock()
return e == nil
}

View File

@@ -25,8 +25,8 @@ func TestNextWakeTime(t *testing.T) {
}
func TestClock(t *testing.T) {
db := &sql.Sqlite{DBPath: "test.db"}
c := NewClock(db)
db := sql.New("test.db")
c := NewClock(&db)
c.AddTimerIntoDB(GetFilledTimer([]string{"", "12", "-1", "12", "0", "", "test"}, 0, 0, false))
t.Log(c.ListTimers(0))
t.Fail()

View File

@@ -44,10 +44,10 @@ func (t *Timer) Hour() (h int) {
}
// Minute 6bits
func (t *Timer) Minute() (min int) {
min = int(t.En1Month4Day5Week3Hour5Min6 & 0x00003f)
if min == 0b111111 {
min = -1
func (t *Timer) Minute() (m int) {
m = int(t.En1Month4Day5Week3Hour5Min6 & 0x00003f)
if m == 0b111111 {
m = -1
}
return
}
@@ -82,6 +82,6 @@ func (t *Timer) SetHour(h int) {
}
// SetMinute ...
func (t *Timer) SetMinute(min int) {
t.En1Month4Day5Week3Hour5Min6 = (int32(min) & 0x00003f) | (t.En1Month4Day5Week3Hour5Min6 & 0xffffc0)
func (t *Timer) SetMinute(m int) {
t.En1Month4Day5Week3Hour5Min6 = (int32(m) & 0x00003f) | (t.En1Month4Day5Week3Hour5Min6 & 0xffffc0)
}

View File

@@ -59,7 +59,7 @@ func init() {
for {
select {
case <-time.After(time.Second * 120):
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("等待超时,取消钓鱼")))
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("等待超时,取消购买")))
return
case e := <-recv:
nextcmd := e.Event.Message.String()
@@ -69,7 +69,7 @@ func init() {
}
money := wallet.GetWalletOf(uid)
if money < 100 {
ctx.SendChain(message.Text("你钱包当前只有", money, "ATRI币,无法完成支付"))
ctx.SendChain(message.Text("你钱包当前只有", money, wallet.GetWalletName(), ",无法完成支付"))
return
}
err = wallet.InsertWalletOf(uid, -100)
@@ -129,12 +129,12 @@ func init() {
fishNumber *= 3
}
} else {
fishNmaes, err := dbdata.pickFishFor(uid, fishNumber)
fishNames, err := dbdata.pickFishFor(uid, fishNumber*3)
if err != nil {
ctx.SendChain(message.Text("[ERROR at fish.go.5.1]:", err))
return
}
if len(fishNmaes) == 0 {
if len(fishNames) == 0 {
equipInfo.Durable = 0
err = dbdata.updateUserEquip(equipInfo)
if err != nil {
@@ -143,14 +143,14 @@ func init() {
ctx.SendChain(message.Text("美西螈因为没吃到鱼,钓鱼时一直没回来,你失去了美西螈"))
return
}
msg = "(美西螈吃掉了"
msg = "(美西螈掉落翻5倍吃3倍鱼\n吃掉了"
fishNumber = 0
for name, number := range fishNmaes {
for name, number := range fishNames {
fishNumber += number
msg += strconv.Itoa(number) + name + ""
msg += strconv.Itoa(number) + name + " "
}
msg += ")"
fishNumber /= 2
fishNumber /= 3
}
waitTime := 120 / (equipInfo.Induce + 1)
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你开始去钓鱼了,请耐心等待鱼上钩(预计要", time.Second*time.Duration(waitTime), ")"))
@@ -267,8 +267,8 @@ func init() {
thingName = "金竿"
case dice >= probabilities["钻石竿"].Min && dice < probabilities["钻石竿"].Max:
thingName = "钻石竿"
case dice >= probabilities["下界合金竿竿竿"].Min && dice < probabilities["下界合金竿竿竿"].Max:
thingName = "下界合金竿竿竿"
case dice >= probabilities["下界合金竿"].Min && dice < probabilities["下界合金竿"].Max:
thingName = "下界合金竿"
default:
thingName = "木竿"
}
@@ -323,7 +323,7 @@ func init() {
newThing = thingInfo[0]
}
if equipInfo.Equip == "美西螈" && thingName != "美西螈" {
number += 2
number += 4
}
newThing.Number += number
}

View File

@@ -6,6 +6,7 @@ import (
"math/rand"
"os"
"strconv"
"strings"
"sync"
"time"
@@ -20,15 +21,15 @@ import (
)
type fishdb struct {
db *sql.Sqlite
sync.RWMutex
db sql.Sqlite
}
// FishLimit 钓鱼次数上限
const FishLimit = 50
// version 规则版本号
const version = "5.4.2"
const version = "5.6.2"
// 各物品信息
type jsonInfo struct {
@@ -121,39 +122,31 @@ var (
durationList = make(map[string]int, 50) // 装备耐久分布
discountList = make(map[string]int, 50) // 价格波动信息
enchantLevel = []string{"0", "", "Ⅱ", "Ⅲ"}
dbdata = &fishdb{
db: &sql.Sqlite{},
}
dbdata fishdb
)
var (
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "钓鱼",
Help: "一款钓鱼模拟器\n----------指令----------\n" +
"- 钓鱼看板/钓鱼商店\n- 购买xxx\n- 购买xxx [数量]\n- 出售xxx\n- 出售xxx [数量]\n" +
"- 钓鱼背包\n- 装备[xx竿|三叉戟|美西螈]\n- 附魔[诱钓|海之眷顾]\n- 修复鱼竿\n- 合成[xx竿|三叉戟]\n- 消除[绑定|宝藏]诅咒\n- 消除[绑定|宝藏]诅咒 [数量]\n" +
"- 进行钓鱼\n- 进行n次钓鱼\n- 当前装备概率明细\n" +
"规则V" + version + ":\n" +
"1.每日的商店价格是波动的!!如何最大化收益自己考虑一下喔\n" +
"2.装备信息:\n-> 木竿 : 耐久上限:30 均价:100 上钩概率:0.7%\n-> 铁竿 : 耐久上限:50 均价:300 上钩概率:0.2%\n-> 金竿 : 耐久上限:70 均价700 上钩概率:0.06%\n" +
"-> 钻石竿 : 耐久上限:100 均价1500 上钩概率:0.03%\n-> 下界合金竿 : 耐久上限:150 均价3100 上钩概率:0.01%\n-> 三叉戟 : 可使1次钓鱼视为3次钓鱼. 耐久上限:300 均价4000 只能合成、修复和交易\n" +
"3.附魔书信息:\n-> 诱钓 : 减少上钩时间. 均价:1000, 上钩概率:0.25%\n-> 海之眷顾 : 增加宝藏上钩概率. 均价:2500, 上钩概率:0.10%\n" +
"4.稀有物品:\n-> 唱片 : 出售物品时使用该物品使价格翻倍. 均价:3000, 上钩概率:0.01%\n" +
"-> 美西螈 : 可装备,获得隐形[钓鱼佬]buff,并让钓到除鱼竿和美西螈外的物品数量变成3,无耐久上限.不可修复/附魔,每次钓鱼消耗两任意鱼类物品. 均价:3000, 上钩概率:0.01%\n" +
"-> 海豚 : 使空竿概率变成垃圾概率. 均价:1000, 上钩概率:0.19%\n" +
"-> 宝藏诅咒 : 无法交易,每一层就会增加购买时10%价格和减少出售时10%价格(超过10层会变为倒贴钱). 上钩概率:0.25%\n-> 净化书 : 用于消除宝藏诅咒. 均价:5000, 上钩概率:0.19%\n" +
"5.鱼类信息:\n-> 鳕鱼 : 均价:10 上钩概率:0.69%\n-> 鲑鱼 : 均价:50 上钩概率:0.2%\n-> 热带鱼 : 均价:100 上钩概率:0.06%\n-> 河豚 : 均价:300 上钩概率:0.03%\n-> 鹦鹉螺 : 均价:500 上钩概率:0.01%\n-> 墨鱼 : 均价:500 上钩概率:0.01%\n" +
"6.垃圾:\n-> 均价:10 上钩概率:30%\n" +
"7.物品BUFF:\n-> 钓鱼佬 : 当背包名字含有'鱼'的物品数量超过100时激活,钓到物品概率提高至90%\n-> 修复大师 : 当背包鱼竿数量超过10时激活,修复物品时耐久百分百继承\n" +
"8.合成:\n-> 铁竿 : 3x木竿\n-> 金竿 : 3x铁竿\n-> 钻石竿 : 3x金竿\n-> 下界合金竿 : 3x钻石竿\n-> 三叉戟 : 3x下界合金竿\n注:合成成功率90%,继承附魔等级合/3的等级\n" +
"9.杂项:\n-> 无装备的情况下,每人最多可以购买3次100块钱的鱼竿\n-> 默认状态钓鱼上钩概率为60%(理论值!!!)\n-> 附魔的鱼竿会因附魔变得昂贵,每个附魔最高3级\n-> 三叉戟不算鱼竿,修复时可直接满耐久\n" +
"-> 鱼竿数量大于50的不能买东西;\n 鱼竿数量大于30的不能钓鱼;\n 每购/售10次鱼竿获得1层宝藏诅咒;\n 每购买20次物品将获得3次价格减半福利;\n 每钓鱼75次获得1本净化书;\n" +
" 每天最多只可出售5个鱼竿和购买15次物品;",
Help: "一款钓鱼模拟器,规则:V" + version +
"\n----------指令----------\n" +
"- 钓鱼背包\n" +
"- 进行钓鱼 / 进行n次钓鱼\n" +
"- 修复鱼竿\n" +
"- 钓鱼商店 / 钓鱼看板\n" +
"- 购买xxx / 购买xxx [数量]\n- 出售xxx / 出售xxx [数量]\n" +
"- 消除[绑定|宝藏]诅咒 / 消除[绑定|宝藏]诅咒 [数量]\n" +
"- 装备[xx竿|三叉戟|美西螈]\n" +
"- 附魔[诱钓|海之眷顾]\n" +
"- 合成[xx竿|三叉戟]\n" +
"- 出售所有垃圾\n" +
"- 当前装备概率明细\n" +
"- 查看钓鱼规则\n",
PublicDataFolder: "McFish",
}).ApplySingle(ctxext.DefaultSingle)
getdb = fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
dbdata.db.DBPath = engine.DataFolder() + "fishdata.db"
dbdata.db = sql.New(engine.DataFolder() + "fishdata.db")
err := dbdata.db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("[ERROR at main.go.1]:", err))
@@ -208,7 +201,7 @@ func init() {
Min: probableList[2],
Max: probableList[3],
}
min := make(map[string]int, 4)
minMap := make(map[string]int, 4)
for _, info := range articlesInfo.ArticleInfo {
switch {
case info.Type == "pole" || info.Name == "美西螈":
@@ -228,10 +221,10 @@ func init() {
durationList[info.Name] = info.Durable
}
probabilities[info.Name] = probabilityLimit{
Min: min[info.Type],
Max: min[info.Type] + info.Probability,
Min: minMap[info.Type],
Max: minMap[info.Type] + info.Probability,
}
min[info.Type] += info.Probability
minMap[info.Type] += info.Probability
}
// }()
}
@@ -245,7 +238,7 @@ func (sql *fishdb) updateFishInfo(uid int64, number int) (residue int, err error
if err != nil {
return 0, err
}
_ = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
_ = sql.db.Find("fishState", &userInfo, "WHERE ID = ?", uid)
if time.Unix(userInfo.Duration, 0).Day() != time.Now().Day() {
userInfo.Fish = 0
userInfo.Duration = time.Now().Unix()
@@ -278,7 +271,7 @@ func (sql *fishdb) updateCurseFor(uid int64, info string, number int) (err error
changeCheck := false
add := 0
buffName := "宝藏诅咒"
_ = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
_ = sql.db.Find("fishState", &userInfo, "WHERE ID = ?", uid)
if info == "fish" {
userInfo.Bless += number
for userInfo.Bless >= 75 {
@@ -306,7 +299,7 @@ func (sql *fishdb) updateCurseFor(uid int64, info string, number int) (err error
Name: buffName,
Type: "treasure",
}
_ = sql.db.Find(table, &thing, "where Name = '"+buffName+"'")
_ = sql.db.Find(table, &thing, "WHERE Name = ?", buffName)
thing.Number += add
return sql.db.Insert(table, &thing)
}
@@ -325,10 +318,10 @@ func (sql *fishdb) checkEquipFor(uid int64) (ok bool, err error) {
if err != nil {
return false, err
}
if !sql.db.CanFind("fishState", "where ID = "+strconv.FormatInt(uid, 10)) {
if !sql.db.CanFind("fishState", "WHERE ID = ?", uid) {
return true, nil
}
err = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
err = sql.db.Find("fishState", &userInfo, "WHERE ID = ?", uid)
if err != nil {
return false, err
}
@@ -346,10 +339,7 @@ func (sql *fishdb) setEquipFor(uid int64) (err error) {
if err != nil {
return err
}
_ = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
if err != nil {
return err
}
_ = sql.db.Find("fishState", &userInfo, "WHERE ID = ?", uid)
userInfo.Equip++
return sql.db.Insert("fishState", &userInfo)
}
@@ -362,10 +352,10 @@ func (sql *fishdb) getUserEquip(uid int64) (userInfo equip, err error) {
if err != nil {
return
}
if !sql.db.CanFind("equips", "where ID = "+strconv.FormatInt(uid, 10)) {
if !sql.db.CanFind("equips", "WHERE ID = ?", uid) {
return
}
err = sql.db.Find("equips", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
err = sql.db.Find("equips", &userInfo, "WHERE ID = ?", uid)
return
}
@@ -378,7 +368,7 @@ func (sql *fishdb) updateUserEquip(userInfo equip) (err error) {
return
}
if userInfo.Durable == 0 {
return sql.db.Del("equips", "where ID = "+strconv.FormatInt(userInfo.ID, 10))
return sql.db.Del("equips", "WHERE ID = ?", userInfo.ID)
}
return sql.db.Insert("equips", &userInfo)
}
@@ -400,29 +390,29 @@ func (sql *fishdb) pickFishFor(uid int64, number int) (fishNames map[string]int,
if count == 0 {
return
}
if !sql.db.CanFind(name, "where Type is 'fish'") {
if !sql.db.CanFind(name, "WHERE Type = 'fish'") {
return
}
fishInfo := article{}
k := 0
for i := number * 2; i > 0 && k < len(fishList); {
_ = sql.db.Find(name, &fishInfo, "where Name is '"+fishList[k]+"'")
for i := number; i > 0 && k < len(fishList); {
_ = sql.db.Find(name, &fishInfo, "WHERE Name = ?", fishList[k])
if fishInfo.Number <= 0 {
k++
continue
}
if fishInfo.Number < i {
k++
fishInfo.Number = 0
i -= fishInfo.Number
fishNames[fishInfo.Name] += fishInfo.Number
fishInfo.Number = 0
} else {
fishNames[fishInfo.Name] += i
fishInfo.Number -= i
i = 0
}
if fishInfo.Number <= 0 {
err = sql.db.Del(name, "where Duration = "+strconv.FormatInt(fishInfo.Duration, 10))
err = sql.db.Del(name, "WHERE Duration = ?", fishInfo.Duration)
} else {
err = sql.db.Insert(name, &fishInfo)
}
@@ -477,13 +467,13 @@ func (sql *fishdb) getUserThingInfo(uid int64, thing string) (thingInfos []artic
if count == 0 {
return
}
if !sql.db.CanFind(name, "where Name = '"+thing+"'") {
if !sql.db.CanFind(name, "WHERE Name = ?", thing) {
return
}
err = sql.db.FindFor(name, &userInfo, "where Name = '"+thing+"'", func() error {
err = sql.db.FindFor(name, &userInfo, "WHERE Name = ?", func() error {
thingInfos = append(thingInfos, userInfo)
return nil
})
}, thing)
return
}
@@ -497,7 +487,7 @@ func (sql *fishdb) updateUserThingInfo(uid int64, userInfo article) (err error)
return
}
if userInfo.Number == 0 {
return sql.db.Del(name, "where Duration = "+strconv.FormatInt(userInfo.Duration, 10))
return sql.db.Del(name, "WHERE Duration = ?", userInfo.Duration)
}
return sql.db.Insert(name, &userInfo)
}
@@ -519,14 +509,34 @@ func (sql *fishdb) getNumberFor(uid int64, thing string) (number int, err error)
if count == 0 {
return
}
if !sql.db.CanFind(name, "where Name glob '*"+thing+"*'") {
if !sql.db.CanFind(name, "WHERE Name glob ?", "*"+thing+"*") {
return
}
info := article{}
err = sql.db.FindFor(name, &info, "where Name glob '*"+thing+"*'", func() error {
err = sql.db.FindFor(name, &info, "WHERE Name glob ?", func() error {
number += info.Number
return nil
})
}, "*"+thing+"*")
return
}
// 获取用户的某类物品信息
func (sql *fishdb) getUserTypeInfo(uid int64, thingType string) (thingInfos []article, err error) {
name := strconv.FormatInt(uid, 10) + "Pack"
sql.Lock()
defer sql.Unlock()
userInfo := article{}
err = sql.db.Create(name, &userInfo)
if err != nil {
return
}
if !sql.db.CanFind(name, "WHERE Type = ?", thingType) {
return
}
err = sql.db.FindFor(name, &userInfo, "WHERE Type = ?", func() error {
thingInfos = append(thingInfos, userInfo)
return nil
}, thingType)
return
}
@@ -542,8 +552,12 @@ func (sql *fishdb) refreshStroeInfo() (ok bool, err error) {
if err != nil {
return false, err
}
err = sql.db.Create("store", &store{})
if err != nil {
return false, err
}
lastTime := storeDiscount{}
_ = sql.db.Find("stroeDiscount", &lastTime, "where Name = 'lastTime'")
_ = sql.db.Find("stroeDiscount", &lastTime, "WHERE Name = 'lastTime'")
refresh := false
timeNow := time.Now().Day()
if timeNow != lastTime.Discount {
@@ -566,12 +580,18 @@ func (sql *fishdb) refreshStroeInfo() (ok bool, err error) {
Name: name,
Discount: thingDiscount,
}
thingInfo := store{}
_ = sql.db.Find("store", &thingInfo, "WHERE Name = ?", name)
if thingInfo.Number > 150 {
// 控制价格浮动区间: -10%到10%
thing.Discount = 90 + rand.Intn(20)
}
err = sql.db.Insert("stroeDiscount", &thing)
if err != nil {
return
}
default:
_ = sql.db.Find("stroeDiscount", &thing, "where Name = '"+name+"'")
_ = sql.db.Find("stroeDiscount", &thing, "WHERE Name = ?", name)
}
if thing.Discount != 0 {
discountList[name] = thing.Discount
@@ -580,21 +600,17 @@ func (sql *fishdb) refreshStroeInfo() (ok bool, err error) {
}
}
thing := store{}
oldThing := []store{}
_ = sql.db.FindFor("stroeDiscount", &thing, "where type = 'pole'", func() error {
var oldThing []store
_ = sql.db.FindFor("stroeDiscount", &thing, "WHERE type = 'pole'", func() error {
if time.Since(time.Unix(thing.Duration, 0)) > 24 {
oldThing = append(oldThing, thing)
}
return nil
})
for _, info := range oldThing {
_ = sql.db.Del("stroeDiscount", "where Duration = "+strconv.FormatInt(info.Duration, 10))
_ = sql.db.Del("stroeDiscount", "WHERE Duration = ?", info.Duration)
}
if refresh {
err = sql.db.Create("store", &store{})
if err != nil {
return
}
// 每天调控1种鱼
fish := fishList[rand.Intn(len(fishList))]
thingInfo := store{
@@ -603,21 +619,25 @@ func (sql *fishdb) refreshStroeInfo() (ok bool, err error) {
Type: "fish",
Price: priceList[fish] * discountList[fish] / 100,
}
_ = sql.db.Find("store", &thingInfo, "where Name = '"+fish+"'")
thingInfo.Number += (100 - discountList[fish])
_ = sql.db.Find("store", &thingInfo, "WHERE Name = ?", fish)
thingInfo.Number += 100 - discountList[fish]
if thingInfo.Number < 1 {
thingInfo.Number = 100
}
_ = sql.db.Insert("store", &thingInfo)
// 每天上架20本净化书
// 每天上架1木竿
thingInfo = store{
Duration: time.Now().Unix(),
Name: "净化书",
Type: "article",
Price: priceList["净化书"] * discountList["净化书"] / 100,
Name: "初始木竿",
Type: "pole",
Price: priceList["木竿"] + priceList["木竿"]*discountList["木竿"]/100,
Other: "30/0/0/0",
}
_ = sql.db.Find("store", &thingInfo, "WHERE Name = '初始木竿'")
thingInfo.Number++
if thingInfo.Number > 5 {
thingInfo.Number = 1
}
_ = sql.db.Find("store", &thingInfo, "where Name = '净化书'")
thingInfo.Number = 20
_ = sql.db.Insert("store", &thingInfo)
}
return true, nil
@@ -662,13 +682,13 @@ func (sql *fishdb) getStoreThingInfo(thing string) (thingInfos []store, err erro
if count == 0 {
return
}
if !sql.db.CanFind("store", "where Name = '"+thing+"'") {
if !sql.db.CanFind("store", "WHERE Name = ?", thing) {
return
}
err = sql.db.FindFor("store", &thingInfo, "where Name = '"+thing+"'", func() error {
err = sql.db.FindFor("store", &thingInfo, "WHERE Name = ?", func() error {
thingInfos = append(thingInfos, thingInfo)
return nil
})
}, thing)
return
}
@@ -687,10 +707,10 @@ func (sql *fishdb) checkStoreFor(thing store, number int) (ok bool, err error) {
if count == 0 {
return false, nil
}
if !sql.db.CanFind("store", "where Duration = "+strconv.FormatInt(thing.Duration, 10)) {
if !sql.db.CanFind("store", "WHERE Duration = ?", thing.Duration) {
return false, nil
}
err = sql.db.Find("store", &thing, "where Duration = "+strconv.FormatInt(thing.Duration, 10))
err = sql.db.Find("store", &thing, "WHERE Duration = ?", thing.Duration)
if err != nil {
return
}
@@ -709,7 +729,7 @@ func (sql *fishdb) updateStoreInfo(thingInfo store) (err error) {
return
}
if thingInfo.Number == 0 {
return sql.db.Del("store", "where Duration = "+strconv.FormatInt(thingInfo.Duration, 10))
return sql.db.Del("store", "WHERE Duration = ?", thingInfo.Duration)
}
return sql.db.Insert("store", &thingInfo)
}
@@ -723,7 +743,7 @@ func (sql *fishdb) updateBuyTimeFor(uid int64, add int) (err error) {
if err != nil {
return err
}
_ = sql.db.Find("buff", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
_ = sql.db.Find("buff", &userInfo, "WHERE ID = ?", uid)
userInfo.BuyTimes += add
if userInfo.BuyTimes > 20 {
userInfo.BuyTimes -= 20
@@ -742,7 +762,7 @@ func (sql *fishdb) useCouponAt(uid int64, times int) (int, error) {
if err != nil {
return useTimes, err
}
_ = sql.db.Find("buff", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
_ = sql.db.Find("buff", &userInfo, "WHERE ID = ?", uid)
if userInfo.Coupon > 0 {
useTimes = math.Min(userInfo.Coupon, times)
userInfo.Coupon -= useTimes
@@ -750,27 +770,66 @@ func (sql *fishdb) useCouponAt(uid int64, times int) (int, error) {
return useTimes, sql.db.Insert("buff", &userInfo)
}
// 检测上限
func (sql *fishdb) checkCanSalesFor(uid int64, sales bool) (int, error) {
residue := 0
// 买卖上限检测
func (sql *fishdb) checkCanSalesFor(uid int64, saleName string, salesNum int) (int, error) {
sql.Lock()
defer sql.Unlock()
userInfo := buffInfo{ID: uid}
err := sql.db.Create("buff", &userInfo)
if err != nil {
return residue, err
return salesNum, err
}
_ = sql.db.Find("buff", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
_ = sql.db.Find("buff", &userInfo, "WHERE ID = ?", uid)
if time.Now().Day() != time.Unix(userInfo.Duration, 0).Day() {
userInfo.Duration = time.Now().Unix()
userInfo.SalesPole = 0
userInfo.BuyTing = 0
err := sql.db.Insert("buff", &userInfo)
if err != nil {
return salesNum, err
}
}
if sales && userInfo.SalesPole < 5 {
residue = 5 - userInfo.SalesPole
userInfo.SalesPole++
} else if userInfo.BuyTing < 15 {
residue = 15 - userInfo.SalesPole
userInfo.SalesPole++
if strings.Contains(saleName, "竿") {
if userInfo.SalesPole >= 10 {
salesNum = -1
}
} else if !checkIsWaste(saleName) {
maxSales := 30 - userInfo.BuyTing
if maxSales < 0 {
salesNum = 0
}
if salesNum > maxSales {
salesNum = maxSales
}
}
return residue, sql.db.Insert("buff", &userInfo)
return salesNum, err
}
// 更新买卖鱼上限假定sales变量已经在 checkCanSalesFor 进行了防护
func (sql *fishdb) updateCanSalesFor(uid int64, saleName string, sales int) error {
sql.Lock()
defer sql.Unlock()
userInfo := buffInfo{ID: uid}
err := sql.db.Create("buff", &userInfo)
if err != nil {
return err
}
_ = sql.db.Find("buff", &userInfo, "WHERE ID = ?", uid)
if strings.Contains(saleName, "竿") {
userInfo.SalesPole++
} else if !checkIsWaste(saleName) {
userInfo.BuyTing += sales
}
return sql.db.Insert("buff", &userInfo)
}
// 检测物品是否是垃圾
func checkIsWaste(thing string) bool {
for _, v := range wasteList {
if v == thing {
return true
}
}
return false
}

View File

@@ -42,9 +42,9 @@ func init() {
}
ctx.SendChain(message.ImageBytes(pic))
})
engine.OnRegex(`^消除绑定诅咒(\d*)$`, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
engine.OnRegex(`^消除(绑定|宝藏)诅咒(\d*)$`, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID
number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[1])
number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[2])
if number == 0 {
number = 1
}
@@ -171,6 +171,31 @@ func init() {
msg = append(msg, message.Text("-----------"))
ctx.Send(msg)
})
engine.OnFullMatch("查看钓鱼规则", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
msg := "一款钓鱼模拟器\n----------指令----------\n" +
"- 钓鱼看板/钓鱼商店\n- 购买xxx\n- 购买xxx [数量]\n- 出售xxx\n- 出售xxx [数量]\n- 出售所有垃圾\n" +
"- 钓鱼背包\n- 装备[xx竿|三叉戟|美西螈]\n- 附魔[诱钓|海之眷顾]\n- 修复鱼竿\n- 合成[xx竿|三叉戟]\n- 消除[绑定|宝藏]诅咒\n- 消除[绑定|宝藏]诅咒 [数量]\n" +
"- 进行钓鱼\n- 进行n次钓鱼\n- " +
"当前装备概率明细\n" +
"规则V" + version + ":\n" +
"1.每日的商店价格是波动的!!如何最大化收益自己考虑一下喔\n" +
"2.装备信息:\n-> 木竿 : 耐久上限:30 均价:100 上钩概率:0.7%\n-> 铁竿 : 耐久上限:50 均价:300 上钩概率:0.2%\n-> 金竿 : 耐久上限:70 均价700 上钩概率:0.06%\n" +
"-> 钻石竿 : 耐久上限:100 均价1500 上钩概率:0.03%\n-> 下界合金竿 : 耐久上限:150 均价3100 上钩概率:0.01%\n-> 三叉戟 : 可使1次钓鱼视为3次钓鱼. 耐久上限:300 均价4000 只能合成、修复和交易\n" +
"3.附魔书信息:\n-> 诱钓 : 减少上钩时间. 均价:1000, 上钩概率:0.25%\n-> 海之眷顾 : 增加宝藏上钩概率. 均价:2500, 上钩概率:0.10%\n" +
"4.稀有物品:\n-> 唱片 : 出售物品时使用该物品使价格翻倍. 均价:3000, 上钩概率:0.01%\n" +
"-> 美西螈 : 可装备,获得隐形[钓鱼佬]buff,并让钓到除鱼竿和美西螈外的物品数量变成5,无耐久上限.不可修复/附魔,每次钓鱼消耗3条鱼. 均价:3000, 上钩概率:0.01%\n" +
"-> 海豚 : 使空竿概率变成垃圾概率. 均价:1000, 上钩概率:0.19%\n" +
"-> 宝藏诅咒 : 无法交易,每一层就会增加购买时10%价格和减少出售时10%价格(超过10层会变为倒贴钱). 上钩概率:0.25%\n-> 净化书 : 用于消除宝藏诅咒. 均价:5000, 上钩概率:0.19%\n" +
"5.鱼类信息:\n-> 鳕鱼 : 均价:10 上钩概率:0.69%\n-> 鲑鱼 : 均价:50 上钩概率:0.2%\n-> 热带鱼 : 均价:100 上钩概率:0.06%\n-> 河豚 : 均价:300 上钩概率:0.03%\n-> 鹦鹉螺 : 均价:500 上钩概率:0.01%\n-> 墨鱼 : 均价:500 上钩概率:0.01%\n" +
"6.垃圾:\n-> 均价:10 上钩概率:30%\n" +
"7.物品BUFF:\n-> 钓鱼佬 : 当背包名字含有'鱼'的物品数量超过100时激活,钓到物品概率提高至90%\n-> 修复大师 : 当背包鱼竿数量超过10时激活,修复物品时耐久百分百继承\n" +
"8.合成:\n-> 铁竿 : 3x木竿\n-> 金竿 : 3x铁竿\n-> 钻石竿 : 3x金竿\n-> 下界合金竿 : 3x钻石竿\n-> 三叉戟 : 3x下界合金竿\n注:合成成功率90%(包括梭哈),合成鱼竿的附魔等级=(附魔等级合/合成鱼竿数量)\n" +
"9.杂项:\n-> 无装备的情况下,每人最多可以购买3次100块钱的鱼竿,商店每日会上架1木竿\n-> 默认状态钓鱼上钩概率为60%(理论值!!!)\n-> 附魔的鱼竿会因附魔变得昂贵,每个附魔最高3级\n-> 三叉戟不算鱼竿,修复时可直接满耐久\n" +
"-> 鱼竿数量大于50的不能买东西;\n 鱼竿数量大于30的不能钓鱼;\n 每购/售10次鱼竿获得1层宝藏诅咒;\n 每购买20次物品将获得3次价格减半福利;\n 每钓鱼75次获得1本净化书;\n" +
" 每天可交易鱼竿10个购买物品30件垃圾除外."
ctx.Send(msg)
})
}
func drawPackImage(uid int64, equipInfo equip, articles []article) (imagePicByte []byte, err error) {

View File

@@ -63,7 +63,10 @@ func init() {
msg = append(msg, message.Text("[", i, "] ", info.Equip, " : 耐", info.Durable, "/修", info.Maintenance,
"/诱", enchantLevel[info.Induce], "/眷顾", enchantLevel[info.Favor], "\n"))
}
msg = append(msg, message.Text("————————\n输入对应序号进行装备,或回复“取消”取消"))
msg = append(msg, message.Text("————————\n"))
msg = append(msg, message.Text("- 输入对应序号进行装备\n"))
msg = append(msg, message.Text("- 输入“取消”终止本次操作\n"))
msg = append(msg, message.Text("- 鱼竿数量请使用钓鱼背包查看"))
ctx.Send(msg)
// 等待用户下一步选择
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
@@ -316,13 +319,15 @@ func init() {
case "诱钓":
equipInfo.Induce++
if equipInfo.Induce > 3 {
equipInfo.Induce = 3
ctx.SendChain(message.Text("诱钓等级已达到上限,你浪费了一本附魔书"))
return
}
number = equipInfo.Induce
case "海之眷顾":
equipInfo.Favor++
if equipInfo.Favor > 3 {
equipInfo.Favor = 3
ctx.SendChain(message.Text("海之眷顾等级已达到上限,你浪费了一本附魔书"))
return
}
number = equipInfo.Favor
default:
@@ -356,12 +361,12 @@ func init() {
ctx.SendChain(message.Text("[ERROR at pole.go.10]:", err))
return
}
max := len(articles)
if max < 3 {
maxCount := len(articles)
if maxCount < 3 {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你的合成材料不足"))
return
}
poles := make([]equip, 0, max)
poles := make([]equip, 0, maxCount)
for _, info := range articles {
poleInfo := strings.Split(info.Other, "/")
durable, _ := strconv.Atoi(poleInfo[0])
@@ -386,10 +391,13 @@ func init() {
msg = append(msg, message.Text("[", i, "] ", info.Equip, " : 耐", info.Durable, "/修", info.Maintenance,
"/诱", enchantLevel[info.Induce], "/眷顾", enchantLevel[info.Favor], "\n"))
}
msg = append(msg, message.Text("————————\n输入3个序号进行合成(用空格分割),或回复“取消”取消"))
msg = append(msg, message.Text("————————\n"))
msg = append(msg, message.Text("- 输入3个序号进行合成(用空格分割)\n"))
msg = append(msg, message.Text("- 输入“取消”,终止本次合成\n"))
msg = append(msg, message.Text("- 输入“梭哈“,合成所有鱼竿"))
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, msg...))
// 等待用户下一步选择
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+ \d+ \d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(梭哈|取消|\d+ \d+ \d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
defer cancel()
for {
select {
@@ -410,6 +418,14 @@ func init() {
)
return
}
if nextcmd == "梭哈" {
// len(list)取3的倍数表示能够用于合成鱼竿的最大数量note此处未对article.Number>1的情况做处理
for i := 3; i < (len(articles)/3)*3; i++ {
list = append(list, i)
}
check = true
break
}
chooseList := strings.Split(nextcmd, " ")
first, err := strconv.Atoi(chooseList[0])
if err != nil {
@@ -431,8 +447,8 @@ func init() {
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("[0]请输入正确的序号\n", list))
continue
}
if first > max || second > max || third > max {
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("[", max, "]请输入正确的序号\n", list))
if first >= maxCount || second >= maxCount || third >= maxCount {
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("[", maxCount, "]请输入正确的序号\n", list))
continue
}
check = true
@@ -442,6 +458,7 @@ func init() {
}
}
}
upgradeNum := len(list)
favorLevel := 0
induceLevel := 0
for _, index := range list {
@@ -463,7 +480,7 @@ func init() {
)
return
}
attribute := strconv.Itoa(durationList[thingName]) + "/0/" + strconv.Itoa(induceLevel/3) + "/" + strconv.Itoa(favorLevel/3)
attribute := strconv.Itoa(durationList[thingName]) + "/0/" + strconv.Itoa(induceLevel/upgradeNum) + "/" + strconv.Itoa(favorLevel/upgradeNum)
newthing := article{
Duration: time.Now().Unix(),
Type: "pole",
@@ -471,14 +488,19 @@ func init() {
Number: 1,
Other: attribute,
}
err = dbdata.updateUserThingInfo(uid, newthing)
if err != nil {
ctx.SendChain(message.Text("[ERROR at pole.go.12]:", err))
return
// 代码未对article.Number>1的情况做处理直接生成多个Number=1的鱼竿
for i := 0; i < upgradeNum/3; i++ {
// 使用时间戳作为主键,增加固定值避免主键冲突
newthing.Duration += int64(i * 10)
err = dbdata.updateUserThingInfo(uid, newthing)
if err != nil {
ctx.SendChain(message.Text("[ERROR at pole.go.12]:", err))
return
}
}
ctx.Send(
message.ReplyWithMessage(ctx.Event.MessageID,
message.Text(thingName, "合成成功", list, "\n属性: ", attribute),
message.Text("成功合成:", upgradeNum/3, "", thingName, "\n属性: ", attribute),
),
)
})

View File

@@ -70,21 +70,24 @@ func init() {
engine.OnRegex(`^出售(`+strings.Join(thingList, "|")+`)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID
thingName := ctx.State["regex_matched"].([]string)[1]
if strings.Contains(thingName, "竿") {
times, err := dbdata.checkCanSalesFor(uid, true)
if err != nil {
ctx.SendChain(message.Text("[ERROR at store.go.75]:", err))
return
}
if times <= 0 {
ctx.SendChain(message.Text("出售次数已达到上限,明天再来售卖吧"))
return
}
}
number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[2])
if number == 0 || strings.Contains(thingName, "竿") {
number = 1
}
// 检测物品交易次数
if strings.Contains(thingName, "竿") {
number, err := dbdata.checkCanSalesFor(uid, thingName, number)
if err != nil {
ctx.SendChain(message.Text("[ERROR,查询购买资质失败]:", err))
return
}
if number <= 0 {
ctx.SendChain(message.Text("一天只能交易10把鱼竿,明天再来售卖吧"))
return
}
}
articles, err := dbdata.getUserThingInfo(uid, thingName)
if err != nil {
ctx.SendChain(message.Text("[ERROR at store.go.5]:", err))
@@ -107,7 +110,7 @@ func init() {
"[", i, "]", info.Name, " 数量: ", info.Number, "\n"))
}
}
msg = append(msg, message.Text("————————\n输入对应序号进行装备,或回复“取消”取消"))
msg = append(msg, message.Text("————————\n输入对应序号进行出售,或回复“取消”取消"))
ctx.Send(msg)
// 等待用户下一步选择
sell := false
@@ -157,7 +160,9 @@ func init() {
maintenance, _ := strconv.Atoi(poleInfo[1])
induceLevel, _ := strconv.Atoi(poleInfo[2])
favorLevel, _ := strconv.Atoi(poleInfo[3])
pice = (priceList[thingName] - (durationList[thingName] - durable) - maintenance*2 + induceLevel*600 + favorLevel*1800) * discountList[thingName] / 100
pice = (priceList[thingName] - (durationList[thingName] - durable) - maintenance*2 +
induceLevel*600*discountList["诱钓"]/100 +
favorLevel*1800*discountList["海之眷顾"]/100) * discountList[thingName] / 100
} else {
pice = priceList[thingName] * discountList[thingName] / 100
}
@@ -169,7 +174,7 @@ func init() {
for {
select {
case <-time.After(time.Second * 60):
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("等待超时,取消钓鱼")))
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("等待超时,取消出售")))
return
case e := <-recv:
nextcmd := e.Event.Message.String()
@@ -304,10 +309,98 @@ func init() {
logrus.Warnln(err)
}
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("出售成功,你赚到了", pice*number, msg)))
// 更新交易限制
err = dbdata.updateCanSalesFor(uid, thingName, number)
if err != nil {
ctx.SendChain(message.Text("[ERROR,记录鱼类交易数量失败,此次交易不记录]:", err))
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("成功出售", thingName, "", number, "个", ",你赚到了", pice*number, msg)))
})
engine.OnRegex(`^购买(`+strings.Join(thingList, "|")+`)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) {
engine.OnRegex(`^出售所有垃圾`, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID
articles, err := dbdata.getUserTypeInfo(uid, "waste")
if err != nil {
ctx.SendChain(message.Text("[ERROR]:获取背包信息错误", err))
return
}
if len(articles) == 0 {
ctx.SendChain(message.Text("你的背包不存在该物品"))
return
}
if len(articles) > 1 {
msg := make(message.Message, 0, 3+len(articles))
msg = append(msg, message.Reply(ctx.Event.MessageID), message.Text("找到以下物品:\n"))
for i, info := range articles {
msg = append(msg, message.Text(
"[", i, "]", info.Name, " 数量: ", info.Number, "\n"))
}
ctx.Send(msg)
}
pice := 0
for _, info := range articles {
pice += (priceList[info.Name] * discountList[info.Name] / 100) * info.Number * 8 / 10
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("是否接受回收站将以", pice, "收购全部垃圾", "?\n回答\"是\"或\"否\"")))
// 等待用户下一步选择
recv, cancel1 := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(是|否)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
defer cancel1()
buy := false
for {
select {
case <-time.After(time.Second * 60):
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("等待超时,取消出售垃圾")))
return
case e := <-recv:
nextcmd := e.Event.Message.String()
if nextcmd == "否" {
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("已取消出售")))
return
}
buy = true
}
if buy {
break
}
}
msg := ""
curse, err := dbdata.getNumberFor(uid, "宝藏诅咒")
if err != nil {
ctx.SendChain(message.Text("[ERROR at store.go.9.3]:", err))
return
}
if curse != 0 {
msg = "\n(你身上绑定了" + strconv.Itoa(curse) + "层诅咒)"
pice = pice * (100 - 10*curse) / 100
}
for _, info := range articles {
info.Number = 0
err = dbdata.updateUserThingInfo(uid, info)
if err != nil {
ctx.SendChain(message.Text("[ERROR at store.go.6]:", err))
return
}
}
err = wallet.InsertWalletOf(uid, pice)
if err != nil {
ctx.SendChain(message.Text("[ERROR出售垃圾失败回收站卷款跑路了]:", err))
return
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("出售成功,你赚到了", pice, msg)))
})
engine.OnRegex(`^购买(`+strings.Join(thingList, "|")+`|初始木竿)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID
thingName := ctx.State["regex_matched"].([]string)[1]
number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[2])
if number == 0 || strings.Contains(thingName, "竿") {
number = 1
}
numberOfPole, err := dbdata.getNumberFor(uid, "竿")
if err != nil {
ctx.SendChain(message.Text("[ERROR at store.go.9.3]:", err))
@@ -317,20 +410,24 @@ func init() {
ctx.SendChain(message.Text("你有", numberOfPole, "支鱼竿,大于50支的玩家不允许购买东西"))
return
}
buytimes, err := dbdata.checkCanSalesFor(uid, false)
// 检测物品交易次数
number, err = dbdata.checkCanSalesFor(uid, thingName, number)
if err != nil {
ctx.SendChain(message.Text("[ERROR at store.go.75]:", err))
return
}
if buytimes <= 0 {
ctx.SendChain(message.Text("出售次数已达到上限,明天再来购买吧"))
if number <= 0 {
var msg string
if strings.Contains(thingName, "竿") {
msg = "一天只能交易10把鱼竿,明天再来购买吧"
} else {
msg = "一天只能购买30次物品明天再来吧~"
}
ctx.SendChain(message.Text(msg))
return
}
thingName := ctx.State["regex_matched"].([]string)[1]
number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[2])
if number == 0 {
number = 1
}
thingInfos, err := dbdata.getStoreThingInfo(thingName)
if err != nil {
ctx.SendChain(message.Text("[ERROR at store.go.11]:", err))
@@ -372,7 +469,12 @@ func init() {
maintenance, _ := strconv.Atoi(poleInfo[1])
induceLevel, _ := strconv.Atoi(poleInfo[2])
favorLevel, _ := strconv.Atoi(poleInfo[3])
thingPice := (priceList[info.Name] - (durationList[info.Name] - durable) - maintenance*2 + induceLevel*600 + favorLevel*1800) * discountList[info.Name] / 100
thingPice := (priceList[info.Name] - (durationList[info.Name] - durable) - maintenance*2 +
induceLevel*600*discountList["诱钓"]/100 +
favorLevel*1800*discountList["海之眷顾"]/100) * discountList[info.Name] / 100
if strings.Contains(thingName, "初始木竿") {
thingPice = priceList["木竿"] + priceList["木竿"]*discountList["木竿"]/100
}
pice = append(pice, thingPice)
} else {
thingPice := priceList[info.Name] * discountList[info.Name] / 100
@@ -391,7 +493,7 @@ func init() {
"[", i, "]", info.Name, " 数量:", info.Number, " 价格:", pice[i], "\n"))
}
}
msg = append(msg, message.Text("————————\n输入对应序号进行装备,或回复“取消”取消"))
msg = append(msg, message.Text("————————\n输入对应序号进行购买,或回复“取消”取消"))
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, msg...))
// 等待用户下一步选择
sell := false
@@ -519,6 +621,9 @@ func init() {
Number: 1,
Other: thing.Other,
}
if thingName == "初始木竿" {
newCommodity.Name = "木竿"
}
} else {
things, err1 := dbdata.getUserThingInfo(uid, thingName)
if err1 != nil {
@@ -546,6 +651,11 @@ func init() {
logrus.Warnln(err)
}
}
// 更新交易限制
err = dbdata.updateCanSalesFor(uid, thingName, number)
if err != nil {
ctx.SendChain(message.Text("[ERROR,记录鱼类交易数量失败,此次交易不记录]:", err))
}
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你用", price, "购买了", number, thingName)))
})
}
@@ -690,6 +800,9 @@ func drawStroeInfoImage(stroeInfo []store) (picImage image.Image, err error) {
induceLevel, _ := strconv.Atoi(poleInfo[2])
favorLevel, _ := strconv.Atoi(poleInfo[3])
pice = (priceList[info.Name] - (durationList[info.Name] - durable) - maintenance*2 + induceLevel*600 + favorLevel*1800) * discountList[info.Name] / 100
if strings.Contains(name, "初始木竿") {
pice = priceList["木竿"] + priceList["木竿"]*discountList["木竿"]/100
}
} else {
pice = priceList[info.Name] * discountList[info.Name] / 100
}

View File

@@ -229,7 +229,7 @@ func init() {
return path.Ext(ctx.Event.File.Name) == ".mid"
}).SetBlock(false).Limit(ctxext.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
fileURL := ctx.GetThisGroupFileUrl(ctx.Event.File.BusID, ctx.Event.File.ID)
fileURL := ctx.GetThisGroupFileURL(ctx.Event.File.BusID, ctx.Event.File.ID)
data, err := web.GetData(fileURL)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
@@ -242,12 +242,12 @@ func init() {
}
for i := 0; i < int(s.NumTracks()); i++ {
midStr := mid2txt(data, i)
fileName := strings.ReplaceAll(cachePath+"/"+ctx.Event.File.Name, ".mid", fmt.Sprintf("-%d.txt", i))
err := os.WriteFile(fileName, binary.StringToBytes(midStr), 0666)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
fileName := strings.ReplaceAll(cachePath+"/"+ctx.Event.File.Name, ".mid", fmt.Sprintf("-%d.txt", i))
_ = os.WriteFile(fileName, binary.StringToBytes(midStr), 0666)
ctx.UploadThisGroupFile(file.BOTPATH+"/"+fileName, filepath.Base(fileName), "")
}
})
@@ -255,7 +255,7 @@ func init() {
return path.Ext(ctx.Event.File.Name) == ".txt" && strings.Contains(ctx.Event.File.Name, "midi制作")
}).SetBlock(false).Limit(ctxext.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
fileURL := ctx.GetThisGroupFileUrl(ctx.Event.File.BusID, ctx.Event.File.ID)
fileURL := ctx.GetThisGroupFileURL(ctx.Event.File.BusID, ctx.Event.File.ID)
data, err := web.GetData(fileURL)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))

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