mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-06 23:30:20 +00:00
Compare commits
182 Commits
v1.7.0-bet
...
v1.7.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bab5c4c308 | ||
|
|
e0891200af | ||
|
|
b050b5d5b5 | ||
|
|
2ff164c2df | ||
|
|
cab917d054 | ||
|
|
dfe6d347a5 | ||
|
|
5c6af1af61 | ||
|
|
d7cdfb1544 | ||
|
|
cf0e87ab9a | ||
|
|
0a33224571 | ||
|
|
dd878f7dfe | ||
|
|
ac52c9cfca | ||
|
|
ece68dae9b | ||
|
|
6c20f22548 | ||
|
|
6f2c9f7fc0 | ||
|
|
b8858f0acd | ||
|
|
9c65383a7c | ||
|
|
a006b30392 | ||
|
|
54c67e30f4 | ||
|
|
61168adb2e | ||
|
|
73b879a6f4 | ||
|
|
a5d2e3dfc3 | ||
|
|
0ea804fc86 | ||
|
|
17bfa2a35c | ||
|
|
ff3d1d1de3 | ||
|
|
3a31802735 | ||
|
|
a514bde4e6 | ||
|
|
7f90ba278a | ||
|
|
2e77703571 | ||
|
|
192eef2bbb | ||
|
|
73ecc47e4c | ||
|
|
714df78ea2 | ||
|
|
f4f50acb1d | ||
|
|
8c24194772 | ||
|
|
844b727859 | ||
|
|
148f271586 | ||
|
|
b062198fae | ||
|
|
1c57a64002 | ||
|
|
13bb760f9f | ||
|
|
6c1257184b | ||
|
|
b0463b3cb4 | ||
|
|
1bb8e8b058 | ||
|
|
209b2e8a1f | ||
|
|
0c55c743f7 | ||
|
|
ba7c6cb0a0 | ||
|
|
d3e587f935 | ||
|
|
36190a4f6a | ||
|
|
54d9486c06 | ||
|
|
fe6130872b | ||
|
|
5e41c15d88 | ||
|
|
e776d02d98 | ||
|
|
cc39d0fdb4 | ||
|
|
1456bed668 | ||
|
|
8d2da4199d | ||
|
|
50e75b2257 | ||
|
|
a6e82d578a | ||
|
|
5b6ab7e20d | ||
|
|
23fea2dae9 | ||
|
|
97c1985479 | ||
|
|
035ed3bd13 | ||
|
|
3e04445cac | ||
|
|
f0078bb23f | ||
|
|
1a8ebe02fb | ||
|
|
de986d8be8 | ||
|
|
ab7daa6bdc | ||
|
|
0bf3253cbb | ||
|
|
21269ee835 | ||
|
|
df927d0b7f | ||
|
|
6a3456f4b0 | ||
|
|
db1d583a37 | ||
|
|
146ea6812e | ||
|
|
99b14e183a | ||
|
|
cb52bf6af7 | ||
|
|
a534c9efbd | ||
|
|
7ac397373d | ||
|
|
73c6f4795e | ||
|
|
598efe182c | ||
|
|
a9bb078079 | ||
|
|
673c715d2f | ||
|
|
dbda1b466d | ||
|
|
b7e21fc111 | ||
|
|
6bff62b91b | ||
|
|
5485cc3be9 | ||
|
|
ba0ef37b74 | ||
|
|
9676b26de0 | ||
|
|
30f60bc7e9 | ||
|
|
9dade7f3e8 | ||
|
|
f043fbf0c0 | ||
|
|
e75814e3b3 | ||
|
|
245b50ba94 | ||
|
|
16e5b84e5c | ||
|
|
26e4b3c513 | ||
|
|
986e50705d | ||
|
|
38b11bb8c9 | ||
|
|
0357405cdf | ||
|
|
7f264964c2 | ||
|
|
c8dcdbb0b2 | ||
|
|
ebcd3cdef2 | ||
|
|
eb43f84d34 | ||
|
|
5931e03c00 | ||
|
|
aaf659f6d4 | ||
|
|
f4add826ff | ||
|
|
0d8157e2f8 | ||
|
|
283667cfe5 | ||
|
|
6403614fa8 | ||
|
|
bdcb833217 | ||
|
|
278d7e0cf9 | ||
|
|
821f8d4949 | ||
|
|
436838d2f8 | ||
|
|
30301f1aba | ||
|
|
df1d71b9b2 | ||
|
|
0315718ab7 | ||
|
|
971c179227 | ||
|
|
1c0270fda0 | ||
|
|
5463945b6c | ||
|
|
8eb058fb26 | ||
|
|
33e5b0286f | ||
|
|
296fd60cd7 | ||
|
|
667c9fbcca | ||
|
|
3d8d0ad107 | ||
|
|
f35a89e401 | ||
|
|
c5c63d0b64 | ||
|
|
3e15754031 | ||
|
|
c1e37b293c | ||
|
|
8edc3f6de6 | ||
|
|
416cb3f2b8 | ||
|
|
8050f12d51 | ||
|
|
292fc311d6 | ||
|
|
28cb0491f7 | ||
|
|
1bad611018 | ||
|
|
d49224fd50 | ||
|
|
2324837052 | ||
|
|
35f8458d67 | ||
|
|
8a6b7f65c7 | ||
|
|
7b1d2b7eaa | ||
|
|
7ced79c6bb | ||
|
|
e224bf9252 | ||
|
|
2b1caafa16 | ||
|
|
c1702c5d5e | ||
|
|
5c8ead8b1d | ||
|
|
635eb9832a | ||
|
|
f1e49dc02e | ||
|
|
573c942a9d | ||
|
|
e8b61b39f0 | ||
|
|
ed26d31326 | ||
|
|
76dbf5a4b6 | ||
|
|
f1ea658c7d | ||
|
|
2964986ee5 | ||
|
|
52ef28cd6a | ||
|
|
df4c0438a2 | ||
|
|
864f92a728 | ||
|
|
6ea50cf8b7 | ||
|
|
d66dd9b7fa | ||
|
|
4a15326977 | ||
|
|
b4a1f93993 | ||
|
|
0c8dfb3f9c | ||
|
|
1aa11879dc | ||
|
|
14c596be1f | ||
|
|
309afecadd | ||
|
|
f465e78460 | ||
|
|
aa5c324592 | ||
|
|
1a0575af64 | ||
|
|
587d3967ef | ||
|
|
d693f988bb | ||
|
|
500dcaa9ed | ||
|
|
1376803b07 | ||
|
|
68386910c4 | ||
|
|
1734f1f7d4 | ||
|
|
86b87c2b4e | ||
|
|
e9eb4c5602 | ||
|
|
6474b36ccd | ||
|
|
107149892c | ||
|
|
f1dba97922 | ||
|
|
bc3c4303be | ||
|
|
f7a61ed0ee | ||
|
|
107b38e2f5 | ||
|
|
0d85fa04e1 | ||
|
|
1d8f5a7869 | ||
|
|
5e93368e57 | ||
|
|
56e931665e | ||
|
|
e5b2b369e3 | ||
|
|
58cf08fc39 |
20
.github/workflows/pull.yml
vendored
20
.github/workflows/pull.yml
vendored
@@ -1,6 +1,24 @@
|
||||
name: PullLint
|
||||
on: [ pull_request ]
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [assigned, opened, synchronize, reopened]
|
||||
jobs:
|
||||
# This workflow closes invalid PR
|
||||
close-pr:
|
||||
name: closepr
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
permissions: write-all
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
- name: Close PR if commit message contains ".go"
|
||||
if: contains(github.event.pull_request.title, '.go')
|
||||
uses: superbrothers/close-pull-request@v3
|
||||
with:
|
||||
# Optional. Post a issue comment just before closing a pull request.
|
||||
comment: "非法PR. 请`fork`后修改自己的仓库, 而不是向主仓库提交更改. 如果您确信您的PR是为了给主仓库新增功能或修复bug, 请更改默认PR标题. **注意**: 如果您再次触发本提示, 则有可能导致账号被封禁."
|
||||
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
4
.github/workflows/push.yml
vendored
4
.github/workflows/push.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: golangci-lint
|
||||
- name: Run Lint
|
||||
uses: golangci/golangci-lint-action@master
|
||||
with:
|
||||
version: latest
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
git config --local user.name 'github-actions[bot]'
|
||||
git config --local user.email '41898282+github-actions[bot]@users.noreply.github.com'
|
||||
git add --all
|
||||
git commit -m "🎨 改进代码样式"
|
||||
git commit -m "chore(lint): 改进代码样式"
|
||||
|
||||
- name: Create Pull Request
|
||||
if: ${{ !github.head_ref }}
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,3 +8,4 @@ nohup.out
|
||||
zerobot
|
||||
ZeroBot-Plugin*
|
||||
*.syso
|
||||
/.direnv
|
||||
|
||||
@@ -18,7 +18,7 @@ linters:
|
||||
fast: false
|
||||
enable:
|
||||
- bodyclose
|
||||
- depguard
|
||||
#- depguard
|
||||
- dogsled
|
||||
- errcheck
|
||||
- exportloopref
|
||||
|
||||
@@ -66,7 +66,7 @@ archives:
|
||||
format: zip
|
||||
|
||||
nfpms:
|
||||
- license: GPL 3.0
|
||||
- license: AGPL 3.0
|
||||
homepage: https://github.com/FloatTech/ZeroBot-Plugin
|
||||
file_name_template: "zbp_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||
formats:
|
||||
|
||||
254
README.md
254
README.md
@@ -15,11 +15,17 @@
|
||||
[](https://github.com/takayama-lily/oicq)
|
||||
[](https://github.com/mamoe/mirai)
|
||||
|
||||
|
||||
|
||||
[](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin)
|
||||
[](https://t.me/zerobotplugin)
|
||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||
|
||||
|
||||
|
||||
[](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
|
||||
[](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
|
||||
[](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
|
||||
[](https://pd.qq.com/s/fjkx81mnr)
|
||||
[](https://t.me/zerobotplugin)
|
||||
|
||||
本项目符合 [OneBot](https://github.com/howmanybots/onebot) 标准,可基于以下项目与机器人框架/平台进行交互
|
||||
@@ -33,6 +39,8 @@
|
||||
|
||||
</div>
|
||||
|
||||
> 专为[后 go-cqhttp 时代](https://github.com/Mrs4s/go-cqhttp/issues/2471)开发迁移的`类zbp`新机器人现已出炉,基于官方api,稳定不风控: [NanoBot-Plugin](https://github.com/FloatTech/NanoBot-Plugin)
|
||||
|
||||
> 如果您不知道什么是 [OneBot](https://github.com/howmanybots/onebot) 或不希望运行多个程序,还可以直接前往 [gocqzbp](https://github.com/FloatTech/gocqzbp) 的 [Release](https://github.com/FloatTech/gocqzbp/releases) 页面下载单一可执行文件或前往 [Packages](https://github.com/FloatTech/gocqzbp/pkgs/container/gocqzbp) 页面使用`docker`,运行后按提示登录即可。
|
||||
|
||||
> 如果您对开发插件感兴趣,欢迎加入[ZeroBot-Plugin-Playground](https://github.com/FloatTech/ZeroBot-Plugin-Playground)
|
||||
@@ -42,9 +50,10 @@
|
||||
## 命令行参数
|
||||
> `[]`代表是可选参数
|
||||
```bash
|
||||
zerobot [-h] [-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] [qq1 qq2 qq3 ...] [&]
|
||||
```
|
||||
- **-h**: 显示帮助
|
||||
- **-m**: 不自动标记消息为已读
|
||||
- **-n nickname**: 设置默认昵称,默认为`椛椛`
|
||||
- **-t token**: 设置`AccessToken`,默认为空
|
||||
- **-u url**: 设置`Url`,默认为`ws://127.0.0.1:6700`
|
||||
@@ -62,27 +71,17 @@ zerobot [-h] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w] [-c|s
|
||||
默认配置文件格式如下。当选择从配置文件加载时,将忽略相应命令行参数。
|
||||
```json
|
||||
{
|
||||
"zero": {
|
||||
"nickname": [
|
||||
"椛椛",
|
||||
"ATRI",
|
||||
"atri",
|
||||
"亚托莉",
|
||||
"アトリ"
|
||||
],
|
||||
"command_prefix": "/",
|
||||
"super_users": [],
|
||||
"ring_len": 4096,
|
||||
"latency": 233000000,
|
||||
"max_process_time": 240000000000
|
||||
},
|
||||
"ws": [
|
||||
{
|
||||
"Url": "ws://127.0.0.1:6700",
|
||||
"AccessToken": ""
|
||||
}
|
||||
],
|
||||
"wss": null
|
||||
"zero": {
|
||||
"nickname": ["椛椛", "ATRI", "atri", "亚托莉", "アトリ"],
|
||||
"command_prefix": "/",
|
||||
"super_users": [],
|
||||
"ring_len": 4096,
|
||||
"latency": 233000000,
|
||||
"max_process_time": 240000000000,
|
||||
"mark_message": true
|
||||
},
|
||||
"ws": [{ "Url": "ws://127.0.0.1:6700", "AccessToken": "" }],
|
||||
"wss": null
|
||||
}
|
||||
```
|
||||
|
||||
@@ -243,6 +242,8 @@ zerobot [-h] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w] [-c|s
|
||||
- [x] 列出所有提醒
|
||||
|
||||
- [x] 翻牌
|
||||
|
||||
- [x] 赞我
|
||||
|
||||
- [x] [开启 | 关闭]入群验证
|
||||
|
||||
@@ -436,11 +437,11 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>百度一下</summary>
|
||||
<summary>百科</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu"`
|
||||
|
||||
- [x] 百度下[xxx]
|
||||
- [x] 百度/百科/维基/wiki[xxx]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -559,7 +560,7 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] b站推送列表
|
||||
|
||||
- [x] 拉取b站推送 (使用job执行定时任务------记录在"@every 10s"触发的指令)
|
||||
- [x] 拉取b站推送 (使用job执行定时任务------记录在"@every 5m"触发的指令)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -571,14 +572,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 随机书评
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>打断复读</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/breakrepeat"`
|
||||
|
||||
- [x] (打断三次以上的复读)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>藏头诗</summary>
|
||||
@@ -659,6 +652,16 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 教你一篇小作文[作文]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>程序员做饭指南</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/dish"`
|
||||
|
||||
- [x] 怎么做 | 烹饪[菜名]
|
||||
|
||||
- [x] 随机菜谱 | 随便做点菜
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>多功能抽签</summary>
|
||||
@@ -727,7 +730,8 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/font"`
|
||||
|
||||
- [x] (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体])渲染文字xxx
|
||||
- [x] (用[终末体|终末变体|紫罗兰体|樱酥体|Consolas体|粗苹方体|未来荧黑体|Gugi体|八丸体|Impact体|猫啃体|苹方体])渲染(抖动)文字xxx
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>每日运势</summary>
|
||||
@@ -957,6 +961,24 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
来份萝莉
|
||||
```
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>桑帛云 API</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolimi"`
|
||||
|
||||
- [x] 随机妹子
|
||||
|
||||
- [x] 随机绕口令
|
||||
|
||||
- [x] 颜值鉴定[图片]
|
||||
|
||||
- [x] 随机情话
|
||||
|
||||
- [x] 发病 嘉然
|
||||
|
||||
- [x] 让[嘉然|塔菲|东雪莲|懒羊羊|科比|孙笑川|陈泽|丁真|空|荧|派蒙|纳西妲|阿贝多|温迪|枫原万叶|钟离|荒泷一斗|八重神子|艾尔海森|提纳里|迪希雅|卡维|宵宫|莱依拉|赛诺|诺艾尔|托马|凝光|莫娜|北斗|神里绫华|雷电将军|芭芭拉|鹿野院平藏|五郎|迪奥娜|凯亚|安柏|班尼特|琴|柯莱|夜兰|妮露|辛焱|珐露珊|魈|香菱|达达利亚|砂糖|早柚|云堇|刻晴|丽莎|迪卢克|烟绯|重云|珊瑚宫心海|胡桃|可莉|流浪者|久岐忍|神里绫人|甘雨|戴因斯雷布|优菈|菲谢尔|行秋|白术|九条裟罗|雷泽|申鹤|迪娜泽黛|凯瑟琳|多莉|坎蒂丝|萍姥姥|罗莎莉亚|留云借风真君|绮良良|瑶瑶|七七|奥兹|米卡|夏洛蒂|埃洛伊|博士|女士|大慈树王|三月七|娜塔莎|希露瓦|虎克|克拉拉|丹恒|希儿|布洛妮娅|瓦尔特|杰帕德|佩拉|姬子|艾丝妲|白露|星|穹|桑博|伦纳德|停云|罗刹|卡芙卡|彦卿|史瓦罗|螺丝咕姆|阿兰|银狼|素裳|丹枢|黑塔|景元|帕姆|可可利亚|半夏|符玄|公输师傅|奥列格|青雀|大毫|青镞|费斯曼|绿芙蓉|镜流|信使|丽塔|失落迷迭|缭乱星棘|伊甸|伏特加女孩|狂热蓝调|莉莉娅|萝莎莉娅|八重樱|八重霞|卡莲|第六夜想曲|卡萝尔|姬子|极地战刃|布洛妮娅|次生银翼|理之律者|真理之律者|迷城骇兔|希儿|魇夜星渊|黑希儿|帕朵菲莉丝|天元骑英|幽兰黛尔|德丽莎|月下初拥|朔夜观星|暮光骑士|明日香|李素裳|格蕾修|梅比乌斯|渡鸦|人之律者|爱莉希雅|爱衣|天穹游侠|琪亚娜|空之律者|终焉之律者|薪炎之律者|云墨丹心|符华|识之律者|维尔薇|始源之律者|芽衣|雷之律者|苏莎娜|阿波尼亚|陆景和|莫弈|夏彦|左然]说我测尼玛
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>MagicPrompt-Stable-Diffusion吟唱提示</summary>
|
||||
@@ -965,6 +987,23 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 吟唱提示[xxxx]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>钓鱼模拟器</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/mcfish"`
|
||||
|
||||
- [x] 钓鱼商店
|
||||
- [x] 购买xxx [数量]
|
||||
- [x] 出售xxx [数量]
|
||||
- [x] 钓鱼背包
|
||||
- [x] 装备[xx竿|三叉戟|美西螈]
|
||||
- [x] 附魔[诱钓|海之眷顾]
|
||||
- [x] 修复鱼竿
|
||||
- [x] 合成[xx竿|三叉戟]
|
||||
- [x] 进行钓鱼
|
||||
- [x] 进行n次钓鱼
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>简易midi音乐制作</summary>
|
||||
@@ -993,10 +1032,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/moegoe"`
|
||||
|
||||
- [x] 让[宁宁|爱瑠|芳乃|茉子|丛雨|小春|七海]说(日语)
|
||||
|
||||
- [x] 让[수아|미미르|아린|연화|유화|선배]说(韩语)
|
||||
|
||||
- [x] 让[派蒙|空|荧|阿贝多|枫原万叶|温迪|八重神子|纳西妲|钟离|诺艾尔|凝光|托马|北斗|莫娜|荒泷一斗|提纳里|芭芭拉|艾尔海森|雷电将军|赛诺|琴|班尼特|五郎|神里绫华|迪希雅|夜兰|辛焱|安柏|宵宫|云堇|妮露|烟绯|鹿野院平藏|凯亚|达达利亚|迪卢克|可莉|早柚|香菱|重云|刻晴|久岐忍|珊瑚宫心海|迪奥娜|戴因斯雷布|魈|神里绫人|丽莎|优菈|凯瑟琳|雷泽|菲谢尔|九条裟罗|甘雨|行秋|胡桃|迪娜泽黛|柯莱|申鹤|砂糖|萍姥姥|奥兹|罗莎莉亚|式大将|哲平|坎蒂丝|托克|留云借风真君|昆钧|塞琉斯|多莉|大肉丸|莱依拉|散兵|拉赫曼|杜拉夫|阿守|玛乔丽|纳比尔|海芭夏|九条镰治|阿娜耶|阿晃|阿扎尔|七七|博士|白术|埃洛伊|大慈树王|女士|丽塔|失落迷迭|缭乱星棘|伊甸|伏特加女孩|狂热蓝调|莉莉娅|萝莎莉娅|八重樱|八重霞|卡莲|第六夜想曲|卡萝尔|姬子|极地战刃|布洛妮娅|次生银翼|理之律者|迷城骇兔|希儿|魇夜星渊|黑希儿|帕朵菲莉丝|天元骑英|幽兰黛尔|德丽莎|月下初拥|朔夜观星|暮光骑士|明日香|李素裳|格蕾修|梅比乌斯|渡鸦|人之律者|爱莉希雅|爱衣|天穹游侠|琪亚娜|空之律者|薪炎之律者|云墨丹心|符华|识之律者|维尔薇|芽衣|雷之律者|阿波尼亚]说(中文)
|
||||
|
||||
</details>
|
||||
@@ -1231,14 +1266,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 设置 saucenao api key [apikey]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>叔叔的AI二次元图片放大</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/scale"`
|
||||
|
||||
- [x] 放大图片[图片]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>签到得分</summary>
|
||||
@@ -1247,6 +1274,7 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 签到
|
||||
- [x] 获得签到背景[@xxx] | 获得签到背景
|
||||
- [x] 设置签到预设(0~3)
|
||||
- [x] 查看等级排名
|
||||
- 注:跨群排行
|
||||
- [x] 查看我的钱包
|
||||
@@ -1279,10 +1307,26 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 卖萌[@xxx]
|
||||
|
||||
- [x] 抽老婆[@xxx]
|
||||
- [x] 今日老婆[@xxx]
|
||||
|
||||
- [x] 黄油角色[@xxx]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>steam</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/steam"`
|
||||
|
||||
- [x] steam[添加|删除]订阅xxxxx
|
||||
|
||||
- [x] steam查询订阅
|
||||
|
||||
- [x] steam绑定 api key xxxxxxx
|
||||
|
||||
- [x] 查看apikey
|
||||
|
||||
- [x] 拉取steam订阅 (使用job执行定时任务------记录在"@every 1m"触发的指令)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>抽塔罗牌</summary>
|
||||
@@ -1366,7 +1410,17 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 来份网易云热评
|
||||
|
||||
</details>
|
||||
</details>
|
||||
<details>
|
||||
<summary>据意查句</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wantquotes"`
|
||||
|
||||
- [x] 据意查句 大海
|
||||
|
||||
- [x] 登录据意查句
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>星际战甲</summary>
|
||||
|
||||
@@ -1443,19 +1497,11 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>月幕galgame图</summary>
|
||||
<summary>抽老婆</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal"`
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wife"`
|
||||
|
||||
- [x] 随机galCG
|
||||
|
||||
- [x] 随机gal表情包
|
||||
|
||||
- [x] galCG[xxx]
|
||||
|
||||
- [x] gal表情包[xxx]
|
||||
|
||||
- [x] 更新gal
|
||||
- [x] 抽老婆
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -1479,6 +1525,18 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 团队七阶猜单词
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>鬼东西</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf"`
|
||||
|
||||
- [x] 鬼东西列表
|
||||
|
||||
- [x] 查询鬼东西[序号][@xxx]
|
||||
|
||||
- 注:由于需要科学,默认注释。
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>一些游戏王插件</summary>
|
||||
@@ -1504,26 +1562,55 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>词典匹配回复</summary>
|
||||
<summary>月幕galgame图</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus"`
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal"`
|
||||
|
||||
- [x] 切换[kimo|傲娇|可爱]词库
|
||||
- [x] 设置词库触发概率0.x (0<x<9)
|
||||
- [x] 随机galCG
|
||||
|
||||
- 注:由于占用资源较大,默认注释。
|
||||
- [x] 随机gal表情包
|
||||
|
||||
- [x] galCG[xxx]
|
||||
|
||||
- [x] gal表情包[xxx]
|
||||
|
||||
- [x] 更新gal
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>鬼东西</summary>
|
||||
<summary>遇见API</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf"`
|
||||
|
||||
- [x] 鬼东西列表
|
||||
|
||||
- [x] 查询鬼东西[序号][@xxx]
|
||||
|
||||
- 注:由于需要科学,默认注释。
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/yujn"`
|
||||
|
||||
- [x] 小姐姐视频
|
||||
- [x] 小姐姐视频2
|
||||
- [x] 黑丝视频
|
||||
- [x] 白丝视频
|
||||
- [x] 欲梦视频
|
||||
- [x] 甜妹视频
|
||||
- [x] 双倍快乐
|
||||
- [x] 纯情女高
|
||||
- [x] 萝莉视频
|
||||
- [x] 玉足视频
|
||||
- [x] 帅哥视频
|
||||
- [x] 热舞视频
|
||||
- [x] 吊带视频
|
||||
- [x] 汉服视频
|
||||
- [x] 极品狱卒
|
||||
- [x] 清纯视频
|
||||
- [x] 快手变装
|
||||
- [x] 抖音变装
|
||||
- [x] 萌娃视频
|
||||
- [x] 穿搭视频
|
||||
- [x] 完美身材
|
||||
- [x] 御姐撒娇
|
||||
- [x] 绿茶语音
|
||||
- [x] 怼人语音
|
||||
- [x] 随机骚话
|
||||
- [x] 随机污句子
|
||||
- [x] 随机美句
|
||||
- [x] 土味情话
|
||||
- [x] 让[lulu]说我测尼玛
|
||||
|
||||
</details>
|
||||
|
||||
@@ -1546,10 +1633,27 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] @Bot 任意文本(任意一句话回复)
|
||||
|
||||
- [x] 设置回复模式[青云客 | 小爱 | ChatGPT]
|
||||
- [x] 设置文字回复模式[婧枫|沫沫|青云客|小爱|ChatGPT]
|
||||
|
||||
- [x] 设置 ChatGPT api key xxx
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>词典匹配回复</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus"`
|
||||
|
||||
- [x] 切换[kimo|傲娇|可爱]词库
|
||||
- [x] 设置词库触发概率0.x (0<x<9)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>打断复读</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/breakrepeat"`
|
||||
|
||||
- [x] (打断三次以上的复读)
|
||||
|
||||
</details>
|
||||
|
||||
## 三种使用方法,推荐第一种
|
||||
|
||||
@@ -79,7 +79,7 @@ func init() {
|
||||
logrus.Warnln("VT100设置失败, 将以无色模式输出")
|
||||
}
|
||||
|
||||
err = setConsoleTitle("ZeroBot-Blugin " + banner.Version + " " + banner.Copyright)
|
||||
err = setConsoleTitle("ZeroBot-Plugin " + banner.Version + " " + banner.Copyright)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
2
data
2
data
Submodule data updated: b9848c9a4e...9b983625ca
25
default.nix
Normal file
25
default.nix
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
pkgs ? (
|
||||
let
|
||||
inherit (builtins) fetchTree fromJSON readFile;
|
||||
inherit ((fromJSON (readFile ./flake.lock)).nodes) nixpkgs gomod2nix;
|
||||
in
|
||||
import (fetchTree nixpkgs.locked) {
|
||||
overlays = [
|
||||
(import "${fetchTree gomod2nix.locked}/overlay.nix")
|
||||
];
|
||||
}
|
||||
),
|
||||
buildGoApplication ? pkgs.buildGoApplication,
|
||||
}:
|
||||
buildGoApplication {
|
||||
pname = "ZeroBot-Plugin";
|
||||
version = "1.7.6";
|
||||
pwd = ./.;
|
||||
src = ./.;
|
||||
# spec go version manually bcs
|
||||
# https://github.com/nix-community/gomod2nix/blob/30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6/builder/default.nix#L130
|
||||
# do no work
|
||||
go = pkgs.go_1_20;
|
||||
modules = ./gomod2nix.toml;
|
||||
}
|
||||
85
flake.lock
generated
Normal file
85
flake.lock
generated
Normal file
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1705309234,
|
||||
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gomod2nix": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1705314449,
|
||||
"narHash": "sha256-yfQQ67dLejP0FLK76LKHbkzcQqNIrux6MFe32MMFGNQ=",
|
||||
"owner": "nix-community",
|
||||
"repo": "gomod2nix",
|
||||
"rev": "30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "gomod2nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1705856552,
|
||||
"narHash": "sha256-JXfnuEf5Yd6bhMs/uvM67/joxYKoysyE3M2k6T3eWbg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "612f97239e2cc474c13c9dafa0df378058c5ad8d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"gomod2nix": "gomod2nix",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
36
flake.nix
Normal file
36
flake.nix
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
description = "基于 ZeroBot 的 OneBot 插件";
|
||||
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||
inputs.gomod2nix.url = "github:nix-community/gomod2nix";
|
||||
inputs.gomod2nix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.gomod2nix.inputs.flake-utils.follows = "flake-utils";
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
gomod2nix,
|
||||
}: (
|
||||
flake-utils.lib.eachDefaultSystem
|
||||
(system: let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
|
||||
# The current default sdk for macOS fails to compile go projects, so we use a newer one for now.
|
||||
# This has no effect on other platforms.
|
||||
callPackage = pkgs.darwin.apple_sdk_11_0.callPackage or pkgs.callPackage;
|
||||
in {
|
||||
# doCheck will fail at write files
|
||||
packages.default =
|
||||
(callPackage ./. {
|
||||
inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
|
||||
})
|
||||
.overrideAttrs (_: {doCheck = false;});
|
||||
devShells.default = callPackage ./shell.nix {
|
||||
inherit (gomod2nix.legacyPackages.${system}) mkGoEnv gomod2nix;
|
||||
};
|
||||
formatter = pkgs.alejandra;
|
||||
})
|
||||
);
|
||||
}
|
||||
48
go.mod
48
go.mod
@@ -4,15 +4,15 @@ go 1.20
|
||||
|
||||
require (
|
||||
github.com/Baidu-AIP/golang-sdk v1.1.1
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230312042320-53aa800c2c58
|
||||
github.com/FloatTech/floatbox v0.0.0-20230312033609-f3826d7c8d00
|
||||
github.com/FloatTech/gg v1.1.2
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230215052637-9f7b05520ca9
|
||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20240423052513-58ad4b85322a
|
||||
github.com/FloatTech/floatbox v0.0.0-20240304064110-78a83f1af9a6
|
||||
github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef
|
||||
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9
|
||||
github.com/FloatTech/sqlite v1.5.7
|
||||
github.com/FloatTech/sqlite v1.6.3
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230301071613-f2c5c97cec88
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230312042148-dd8632bf31f5
|
||||
github.com/FloatTech/zbpctrl v1.6.0
|
||||
github.com/FloatTech/zbputils v1.7.1-0.20231107124514-083e678fbfe6
|
||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5
|
||||
github.com/antchfx/htmlquery v1.2.5
|
||||
@@ -21,7 +21,7 @@ require (
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/fumiama/ahsai v0.1.0
|
||||
github.com/fumiama/cron v1.3.0
|
||||
github.com/fumiama/go-base16384 v1.6.4
|
||||
github.com/fumiama/go-base16384 v1.7.0
|
||||
github.com/fumiama/go-registry v0.2.6
|
||||
github.com/fumiama/gotracemoe v0.0.3
|
||||
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565
|
||||
@@ -29,23 +29,28 @@ require (
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/jozsefsallai/gophersauce v1.0.1
|
||||
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5
|
||||
github.com/lithammer/fuzzysearch v1.1.5
|
||||
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5
|
||||
github.com/mroth/weightedrand v1.0.0
|
||||
github.com/notnil/chess v1.9.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/quic-go/quic-go v0.32.0
|
||||
github.com/quic-go/quic-go v0.38.1
|
||||
github.com/shirou/gopsutil/v3 v3.23.1
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/tidwall/gjson v1.14.4
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.10
|
||||
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.4.0
|
||||
golang.org/x/text v0.6.0
|
||||
golang.org/x/sys v0.8.0
|
||||
golang.org/x/text v0.9.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/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/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
|
||||
github.com/faiface/beep v1.1.0 // indirect
|
||||
@@ -54,7 +59,7 @@ require (
|
||||
github.com/fumiama/imgsz v0.0.2 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.0.4 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
@@ -64,18 +69,19 @@ require (
|
||||
github.com/jfreymuth/vorbis v1.0.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/liuzl/cedar-go v0.0.0-20170805034717-80a9c64b256d // indirect
|
||||
github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||
github.com/pkumza/numcn v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/tetratelabs/wazero v1.5.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||
@@ -85,9 +91,9 @@ require (
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9 // indirect
|
||||
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/net v0.4.0 // indirect
|
||||
golang.org/x/tools v0.2.0 // 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
|
||||
|
||||
102
go.sum
102
go.sum
@@ -2,29 +2,33 @@ github.com/Baidu-AIP/golang-sdk v1.1.1 h1:RQsAmgDSAkiq22I6n7XJ2t3afgzFeqjY46FGhv
|
||||
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.6.1-0.20230312042320-53aa800c2c58 h1:26/j1fmDkBwk1UwRqMDV8+IC9HMz+9xbncK/Mx3t2YQ=
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230312042320-53aa800c2c58/go.mod h1:A+qtDCzq4rtwEcxzB1boBX8wjHxYWTFyafxiq0sNZyA=
|
||||
github.com/FloatTech/floatbox v0.0.0-20230312033609-f3826d7c8d00 h1:KvQd0IaJqBPkc4mpyldX9UcRVlUPVazlcmS79LU0pJ8=
|
||||
github.com/FloatTech/floatbox v0.0.0-20230312033609-f3826d7c8d00/go.mod h1:0l1xHjcTlONupyOY5lB5PY6kFWFMHQh89e1Zqm5QZlo=
|
||||
github.com/FloatTech/gg v1.1.2 h1:YolgOYg3uDHc1+g0bLtt6QuRA/pvLn+b9IBCIhOOX88=
|
||||
github.com/FloatTech/gg v1.1.2/go.mod h1:uzPzAeT35egARdRuu+1oyjU3CmTwCceoq3Vvje7LpcI=
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230215052637-9f7b05520ca9 h1:Havq0z/N79KeD50L7ms+Hv8F4Sw98Dt8lXM8jECp04o=
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230215052637-9f7b05520ca9/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs=
|
||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20240423052513-58ad4b85322a h1:K+1RAkIBb+3kkSxSkSTdTugSIsXJXrjEbwuv/BwUsP8=
|
||||
github.com/FloatTech/AnimeAPI v1.7.1-0.20240423052513-58ad4b85322a/go.mod h1:bNHsYcUd1+Y5Al3CR6tdzKxcc0XLivXjmUsL9xG6sSw=
|
||||
github.com/FloatTech/floatbox v0.0.0-20240304064110-78a83f1af9a6 h1:Vaj8ulVbN8vTD4W7aj+BYeT6x8iKFneDnkgBCezomDY=
|
||||
github.com/FloatTech/floatbox v0.0.0-20240304064110-78a83f1af9a6/go.mod h1:TeTlp+hTxpJti4JSdmUqzxGEr4wUBOVct9YWBepilpc=
|
||||
github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08 h1:dPLeoiTVSBlgls+66EB/UJ2e38BaASmBN5nANaycSBU=
|
||||
github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08/go.mod h1:uzPzAeT35egARdRuu+1oyjU3CmTwCceoq3Vvje7LpcI=
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef h1:CJbK/2FRwPuZpeb6M4sWK2d7oXDnBEGhpkQuQrgc91A=
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs=
|
||||
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9 h1:hffajvmQFfP68U6wUwHemPuuwCUoss+SEFfoLYwbGwE=
|
||||
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9/go.mod h1:NBFPhWae4hqVMeG8ELBBnUQkKce3nDjkljVn6PdiUNs=
|
||||
github.com/FloatTech/sqlite v1.5.7 h1:Bvo4LSojcZ6dVtbHrkqvt6z4v8e+sj0G5PSUIvdawsk=
|
||||
github.com/FloatTech/sqlite v1.5.7/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY=
|
||||
github.com/FloatTech/sqlite v1.6.3 h1:MQkqBNlkPuCoKQQgoNLuTL/2Ci3tBTFAnVYBdD0Wy4M=
|
||||
github.com/FloatTech/sqlite v1.6.3/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY=
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw=
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230301071613-f2c5c97cec88 h1:jdTWiYXGtYZhxIn9oGYkObNVa8GtJvki+ihsoMlLJPs=
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230301071613-f2c5c97cec88/go.mod h1:8IRMtcWhK4S8QdpStJqXQZtIBgAqUH72Imq3BQ45TWg=
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230312042148-dd8632bf31f5 h1:/Zm5n+2bIpL5how66638nA0NIy+OQOgiCQuEgDYodpQ=
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230312042148-dd8632bf31f5/go.mod h1:0xorZ1IN/UYFCUyUGwHyfA4azQHvDjk0M3F4Mh+gFss=
|
||||
github.com/FloatTech/zbpctrl v1.6.0 h1:BWg9aRR4bUCmNNKj6GPH0TmzFRWYImIi6rQcQTTYRs4=
|
||||
github.com/FloatTech/zbpctrl v1.6.0/go.mod h1:i3GGM5K4HiDsXzvmXQSYoH1QT3tsSaAHjRzHwKGsHG0=
|
||||
github.com/FloatTech/zbputils v1.7.1-0.20231107124514-083e678fbfe6 h1:EMdvLnt6i5dSFloLD1klOM8bdoFZqTtILcMCciOpcMo=
|
||||
github.com/FloatTech/zbputils v1.7.1-0.20231107124514-083e678fbfe6/go.mod h1:4oXgjQ6bGosAF4GbuL/keAhTrGWOV369X5X0ISFebmw=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA=
|
||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5 h1:bBmmB7he0iVN4m5mcehfheeRUEer/Avo4ujnxI3uCqs=
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5/go.mod h1:0UcFaCkhp6vZw6l5Dpq0Dp673CoF9GdvA8lTfst0GiU=
|
||||
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d h1:ir/IFJU5xbja5UaBEQLjcvn7aAU01nqU/NUyOBEU+ew=
|
||||
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d/go.mod h1:PRWNwWq0yifz6XDPZu48aSld8BWwBfr2JKB2bGWiEd4=
|
||||
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca h1:kWzLcty5V2rzOqJM7Tp/MfSX0RMSI1x4IOLApEefYxA=
|
||||
github.com/ajstarks/svgo v0.0.0-20200320125537-f189e35d30ca/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/antchfx/htmlquery v1.2.5 h1:1lXnx46/1wtv1E/kzmH8vrfMuUKYgkdDBA9pIdMJnk4=
|
||||
github.com/antchfx/htmlquery v1.2.5/go.mod h1:2MCVBzYVafPBmKbrmwB9F5xdd+IEgRY61ci2oOsOQVw=
|
||||
@@ -58,8 +62,8 @@ github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b h1:Zt3pFQditAdWTHCO
|
||||
github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
|
||||
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
|
||||
github.com/fumiama/go-base16384 v1.6.4 h1:rYDRwD/th2cG4U7QLokpzmST1cCxZGXtHmolOUePt5o=
|
||||
github.com/fumiama/go-base16384 v1.6.4/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
||||
github.com/fumiama/go-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=
|
||||
@@ -83,13 +87,14 @@ github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebK
|
||||
github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
|
||||
github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
|
||||
github.com/go-audio/wav v1.0.0/go.mod h1:3yoReyQOsiARkvPl3ERCi8JFjihzG6WhjYpZCf5zAWE=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
@@ -99,7 +104,7 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
@@ -126,6 +131,8 @@ github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
|
||||
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM=
|
||||
github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg=
|
||||
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5 h1:BXnB1Gz4y/zwQh+ZFNy7rgd+ZfMOrwRr4uZSHEI+ieY=
|
||||
github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5/go.mod h1:c9+VS9GaommgIOzNWb5ze4lYwfT8BZ2UDyGiuQTT7yc=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
@@ -137,6 +144,12 @@ 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/liuzl/cedar-go v0.0.0-20170805034717-80a9c64b256d h1:qSmEGTgjkESUX5kPMSGJ4pcBUtYVDdkNzMrjQyvRvp0=
|
||||
github.com/liuzl/cedar-go v0.0.0-20170805034717-80a9c64b256d/go.mod h1:x7SghIWwLVcJObXbjK7S2ENsT1cAcdJcPl7dRaSFog0=
|
||||
github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d h1:hTRDIpJ1FjS9ULJuEzu69n3qTgc18eI+ztw/pJv47hs=
|
||||
github.com/liuzl/da v0.0.0-20180704015230-14771aad5b1d/go.mod h1:7xD3p0XnHvJFQ3t/stEJd877CSIMkH/fACVWen5pYnc=
|
||||
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5 h1:wnbHIeP1UX8ClYEWKGnw66PfYvReCHu9G5lXSte3Sqc=
|
||||
github.com/liuzl/gocc v0.0.0-20231231122217-0372e1059ca5/go.mod h1:7KaV9YIR92M1FpbczAcfYQ3UZ5ayT27pNtunDmXvLBo=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
@@ -151,9 +164,11 @@ github.com/mroth/weightedrand v1.0.0 h1:V8JeHChvl2MP1sAoXq4brElOcza+jxLkRuwvtQu8
|
||||
github.com/mroth/weightedrand v1.0.0/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
||||
github.com/notnil/chess v1.9.0 h1:YMxR5kUVjtwcuFptGU0/3q7eG3MSHQNbg0VUekvRKV0=
|
||||
github.com/notnil/chess v1.9.0/go.mod h1:cRuJUIBFq9Xki05TWHJxHYkC+fFpq45IWwk94DdlCrA=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
@@ -168,29 +183,27 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF
|
||||
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-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||
github.com/quic-go/quic-go v0.32.0 h1:lY02md31s1JgPiiyfqJijpu/UX/Iun304FI3yUqX7tA=
|
||||
github.com/quic-go/quic-go v0.32.0/go.mod h1:/fCsKANhQIeD5l76c2JFU+07gVE3KaA0FP+0zMWwfwo=
|
||||
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/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tetratelabs/wazero v1.5.0 h1:Yz3fZHivfDiZFUXnWMPUoiW7s8tC1sjdBtlJn08qYa0=
|
||||
github.com/tetratelabs/wazero v1.5.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
|
||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
@@ -203,8 +216,8 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm
|
||||
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.10 h1:exmPWNjWtOMLgLQW/svQDybExRJAfDkjpE3S2U6fBOY=
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.10/go.mod h1:y29UIOy0RD3P+0meDNIWRhcJF3jtWPN9xP9hgt/AJAU=
|
||||
github.com/wdvxdr1123/ZeroBot v1.7.5-0.20240410141841-6970df23ca54 h1:s7k0Pf4RoeCUHe9rlVsg0mqAH3WO7xLMhe9qih/CxnE=
|
||||
github.com/wdvxdr1123/ZeroBot v1.7.5-0.20240410141841-6970df23ca54/go.mod h1:y29UIOy0RD3P+0meDNIWRhcJF3jtWPN9xP9hgt/AJAU=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
@@ -241,8 +254,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -254,8 +267,8 @@ golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -277,23 +290,25 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
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 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
|
||||
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -302,7 +317,6 @@ google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175
|
||||
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.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
284
gomod2nix.toml
Normal file
284
gomod2nix.toml
Normal file
@@ -0,0 +1,284 @@
|
||||
schema = 3
|
||||
|
||||
[mod]
|
||||
[mod."github.com/Baidu-AIP/golang-sdk"]
|
||||
version = "v1.1.1"
|
||||
hash = "sha256-hKshA0K92bKuK92mmtM0osVmqLJcSbeobeWSDpQoRCo="
|
||||
[mod."github.com/FloatTech/AnimeAPI"]
|
||||
version = "v1.7.1-0.20231017135344-aefd1d56e900"
|
||||
hash = "sha256-YV9VQ7bA8R5g5dcAsbzS6MicVwDgMu08d9GF4uqXH7M="
|
||||
[mod."github.com/FloatTech/floatbox"]
|
||||
version = "v0.0.0-20231107124407-e38535efa2a2"
|
||||
hash = "sha256-B86GBuJAjeFjhAjNbBF6OO6DTH2/fpPkrdQynwX+sxg="
|
||||
[mod."github.com/FloatTech/gg"]
|
||||
version = "v1.1.3-0.20230226151425-6ea91286ba08"
|
||||
hash = "sha256-AeMzjMK1ZwFERb5xuNAV5PdHp7rzoT4ZF7kZ6Kj2/0s="
|
||||
[mod."github.com/FloatTech/imgfactory"]
|
||||
version = "v0.2.2-0.20230413152719-e101cc3606ef"
|
||||
hash = "sha256-2okFyPQSYIxrc8hxICsbjEM9xq25a3I2A4wmDIYFCg8="
|
||||
[mod."github.com/FloatTech/rendercard"]
|
||||
version = "v0.0.10-0.20230223064326-45d29fa4ede9"
|
||||
hash = "sha256-Zn8agmyWWEC2QQfIBa60jlQrEap9Bps+z1Ekay6Y0cg="
|
||||
[mod."github.com/FloatTech/sqlite"]
|
||||
version = "v1.6.3"
|
||||
hash = "sha256-zWPByEMi89ms67ubPg0fAPIRxfpBC2IRKc0iNVLqkPU="
|
||||
[mod."github.com/FloatTech/ttl"]
|
||||
version = "v0.0.0-20220715042055-15612be72f5b"
|
||||
hash = "sha256-vVQTn7f2dFPNrLqutWbeHMCpEdNi7uPxUzpphzaYPpM="
|
||||
[mod."github.com/FloatTech/zbpctrl"]
|
||||
version = "v1.6.0"
|
||||
hash = "sha256-2ZPGFvSgTWcPOo8+p8kmg590HY2b8v/L3674ba+b7+A="
|
||||
[mod."github.com/FloatTech/zbputils"]
|
||||
version = "v1.7.1-0.20231107124514-083e678fbfe6"
|
||||
hash = "sha256-Bg3aAI8oDx71kWielITcK5Rg2H47/DQZX+4+dO5AtK4="
|
||||
[mod."github.com/RomiChan/syncx"]
|
||||
version = "v0.0.0-20221202055724-5f842c53020e"
|
||||
hash = "sha256-FbmvziRRDEzeXW17IQdyWMWsCVq4fvwKGjbFZqJKAMQ="
|
||||
[mod."github.com/RomiChan/websocket"]
|
||||
version = "v1.4.3-0.20220227141055-9b2c6168c9c5"
|
||||
hash = "sha256-Adx+gvqB+CCoUXx7ebIaBDjVkav+wS5qZPmaqcApBWA="
|
||||
[mod."github.com/adamzy/cedar-go"]
|
||||
version = "v0.0.0-20170805034717-80a9c64b256d"
|
||||
hash = "sha256-N19KTxh70IUBqnchFuWkrJD8uuFOIVqv1iSuN3YFIT0="
|
||||
[mod."github.com/ajstarks/svgo"]
|
||||
version = "v0.0.0-20200320125537-f189e35d30ca"
|
||||
hash = "sha256-ALeRuEJN9jHjGb4wNKJcxC59vVx8Tj7hHikEGkaZZ0s="
|
||||
[mod."github.com/antchfx/htmlquery"]
|
||||
version = "v1.2.5"
|
||||
hash = "sha256-lkpdz+NNHadn0VIshszAZS5ZodOic0sp2d7VN6sIl/M="
|
||||
[mod."github.com/antchfx/xpath"]
|
||||
version = "v1.2.1"
|
||||
hash = "sha256-ffHNkJiraDyjy6NsFDNTfqreiY+DER/93J/i11xUPw8="
|
||||
[mod."github.com/corona10/goimagehash"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-HyS8nc7kUNnDaVBDzJ9Ym4pRs83YB4M2vHSRwfm6mr4="
|
||||
[mod."github.com/davidscholberg/go-durationfmt"]
|
||||
version = "v0.0.0-20170122144659-64843a2083d3"
|
||||
hash = "sha256-0rdbpBf3AAjMpxvVEGFb2ImgB2i7vdEhIwCyqJs1iHE="
|
||||
[mod."github.com/disintegration/imaging"]
|
||||
version = "v1.6.2"
|
||||
hash = "sha256-pSeMTPvSkxlthh65LjNYYhPLvCZDkBgVgAGYWW0Aguo="
|
||||
[mod."github.com/ericpauley/go-quantize"]
|
||||
version = "v0.0.0-20200331213906-ae555eb2afa4"
|
||||
hash = "sha256-sMN6D7IlDpDqUWM8ppoE5Sdb7DvLAJaN6qAucBWJ3rs="
|
||||
[mod."github.com/faiface/beep"]
|
||||
version = "v1.1.0"
|
||||
hash = "sha256-66qAbnJjUjhXofxlGCa6G1+vjQcSTyN/POCZvYzHaQo="
|
||||
[mod."github.com/fumiama/ahsai"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-lSoos+SFjALcL0ZYPsbOb8wntwn2fcubvSsz0YKgL9c="
|
||||
[mod."github.com/fumiama/cron"]
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-/sN7X8dKXQgv8J+EDzVUB+o+AY9gBC8e1C6sYhaTy1k="
|
||||
[mod."github.com/fumiama/go-base16384"]
|
||||
version = "v1.7.0"
|
||||
hash = "sha256-vTAsBBYe2ISzb2Nba5E96unodZSkhMcqo6hbwR01nz8="
|
||||
[mod."github.com/fumiama/go-registry"]
|
||||
version = "v0.2.6"
|
||||
hash = "sha256-DgkdYYWsCs/bBrIiCHK4tPInv8pTy5/AqwHmI5UPTo8="
|
||||
[mod."github.com/fumiama/go-simple-protobuf"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-itOBeIU4PRBANDP79eRWlCDNhNUnde6dgcpUlUbm0zU="
|
||||
[mod."github.com/fumiama/gofastTEA"]
|
||||
version = "v0.0.10"
|
||||
hash = "sha256-FOCbkXoS8s/K54yZbhX5pmaN/ouELnCHZoNS8a90VAg="
|
||||
[mod."github.com/fumiama/gotracemoe"]
|
||||
version = "v0.0.3"
|
||||
hash = "sha256-O3cDkVXu5NG1ZtzubxhH+S91zfgu4uH1L+OiSGYSNXQ="
|
||||
[mod."github.com/fumiama/imgsz"]
|
||||
version = "v0.0.2"
|
||||
hash = "sha256-eYUjP1TKWUrsY++rzg4rezOvmvmjADZFBizIIDHnZtY="
|
||||
[mod."github.com/fumiama/jieba"]
|
||||
version = "v0.0.0-20221203025406-36c17a10b565"
|
||||
hash = "sha256-DvDx1pdldkdaSszrbadM/VwqT9TTSmWl6G6a+ysXYEM="
|
||||
[mod."github.com/fumiama/unibase2n"]
|
||||
version = "v0.0.0-20221020155353-02876e777430"
|
||||
hash = "sha256-//vCLy5/vgId7m9WnRGqmh/wnglboiYz2YzQruIe97o="
|
||||
[mod."github.com/gabriel-vasile/mimetype"]
|
||||
version = "v1.0.4"
|
||||
hash = "sha256-5hl9zBo3nkPt8dZfcLoOix8lAKLm3qIkWhopoS4V34E="
|
||||
[mod."github.com/go-ole/go-ole"]
|
||||
version = "v1.2.6"
|
||||
hash = "sha256-+oxitLeJxYF19Z6g+6CgmCHJ1Y5D8raMi2Cb3M6nXCs="
|
||||
[mod."github.com/go-task/slim-sprig"]
|
||||
version = "v0.0.0-20230315185526-52ccab3ef572"
|
||||
hash = "sha256-D6NjCQbcYC53NdwzyAm4i9M1OjTJIVu4EIt3AD/Vxfg="
|
||||
[mod."github.com/golang/freetype"]
|
||||
version = "v0.0.0-20170609003504-e2365dfdc4a0"
|
||||
hash = "sha256-AHAFBd20/tqxohkWyQkui2bUef9i1HWYgk9LOIFErvA="
|
||||
[mod."github.com/golang/groupcache"]
|
||||
version = "v0.0.0-20210331224755-41bb18bfe9da"
|
||||
hash = "sha256-7Gs7CS9gEYZkbu5P4hqPGBpeGZWC64VDwraSKFF+VR0="
|
||||
[mod."github.com/golang/mock"]
|
||||
version = "v1.6.0"
|
||||
hash = "sha256-fWdnMQisRbiRzGT3ISrUHovquzLRHWvcv1JEsJFZRno="
|
||||
[mod."github.com/google/pprof"]
|
||||
version = "v0.0.0-20210407192527-94a9f03dee38"
|
||||
hash = "sha256-ryvI75ePFCfy0qvAhEFbtB/c/Er7nvLwm7CVASBRhsI="
|
||||
[mod."github.com/google/uuid"]
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-QoR55eBtA94T2tBszyxfDtO7/pjZZSGb5vm7U0Xhs0Y="
|
||||
[mod."github.com/hajimehoshi/oto"]
|
||||
version = "v0.7.1"
|
||||
hash = "sha256-eRgbEbsziY5F0oI7wAe29FepZG7uGmq2M4deouDHcXI="
|
||||
[mod."github.com/jfreymuth/oggvorbis"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-DpkiTLxAA/iCoiylpNRvMzvaDWtK+U4UMJYNnnCmJMU="
|
||||
[mod."github.com/jfreymuth/vorbis"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-6kTol+g3NnZ3MazD786fvraw7ydUf0RWNBzHpzgN9Jk="
|
||||
[mod."github.com/jinzhu/gorm"]
|
||||
version = "v1.9.16"
|
||||
hash = "sha256-qKEwgNE8NxcX1uzT20LwC1TKVmve/nIy+oxdAKlxAuc="
|
||||
[mod."github.com/jinzhu/inflection"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-3h3pHib5MaCXKyKLIMyQnSptDJ16kPjCOQPoEBoQsZg="
|
||||
[mod."github.com/jozsefsallai/gophersauce"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-29DsfnGmK51DPunR/leRBKCcokN/yLoB7S2HxCsqtgY="
|
||||
[mod."github.com/kanrichan/resvg-go"]
|
||||
version = "v0.0.2-0.20231001163256-63db194ca9f5"
|
||||
hash = "sha256-plRZ3yhyCafCXmAD4vnFUoCTRsHmLp7Jn9gFKcEKbds="
|
||||
[mod."github.com/kr/pretty"]
|
||||
version = "v0.3.1"
|
||||
hash = "sha256-DlER7XM+xiaLjvebcIPiB12oVNjyZHuJHoRGITzzpKU="
|
||||
[mod."github.com/lithammer/fuzzysearch"]
|
||||
version = "v1.1.5"
|
||||
hash = "sha256-2vJLR4z5o3ch9q4tV7NT5RnfNxEdYspjI8YxQao2A6w="
|
||||
[mod."github.com/liuzl/cedar-go"]
|
||||
version = "v0.0.0-20170805034717-80a9c64b256d"
|
||||
hash = "sha256-N19KTxh70IUBqnchFuWkrJD8uuFOIVqv1iSuN3YFIT0="
|
||||
[mod."github.com/liuzl/da"]
|
||||
version = "v0.0.0-20180704015230-14771aad5b1d"
|
||||
hash = "sha256-J43kwDFmB6LzDhS3Ig/4ddZUTXz1cKztbTA3hILScs8="
|
||||
[mod."github.com/liuzl/gocc"]
|
||||
version = "v0.0.0-20231231122217-0372e1059ca5"
|
||||
hash = "sha256-Dr1xDbO+eR4Y/EpPgQ/S6g6C5etRFKWr8de77skcJR8="
|
||||
[mod."github.com/lufia/plan9stats"]
|
||||
version = "v0.0.0-20211012122336-39d0f177ccd0"
|
||||
hash = "sha256-thb+rkDx5IeWMgw5/5jgu5gZ+6RjJAUXeMgSkJHhRlA="
|
||||
[mod."github.com/mattn/go-isatty"]
|
||||
version = "v0.0.16"
|
||||
hash = "sha256-YMaPZvShDfA98vqw1+zWWl7M1IT4nHPGBrAt7kHo8Iw="
|
||||
[mod."github.com/mroth/weightedrand"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-bP+yIaBUY5+oI455mNM8zh14z/SNPaQg44L3RJ0/v/c="
|
||||
[mod."github.com/nfnt/resize"]
|
||||
version = "v0.0.0-20180221191011-83c6a9932646"
|
||||
hash = "sha256-yvPV+HlDOyJsiwAcVHQkmtw8DHSXyw+cXHkigXm8rAA="
|
||||
[mod."github.com/notnil/chess"]
|
||||
version = "v1.9.0"
|
||||
hash = "sha256-2bHp/H5hBE/hPMT1HLOBqMaCZ/DYWJMDri26O9Yzoms="
|
||||
[mod."github.com/onsi/ginkgo/v2"]
|
||||
version = "v2.9.5"
|
||||
hash = "sha256-3HO85y+nGsg92NEg3OOYXy5GxB59Yl1idF5sBZnyIi4="
|
||||
[mod."github.com/pbnjay/memory"]
|
||||
version = "v0.0.0-20210728143218-7b4eea64cf58"
|
||||
hash = "sha256-QI+F1oPLOOtwNp8+m45OOoSfYFs3QVjGzE0rFdpF/IA="
|
||||
[mod."github.com/pkg/errors"]
|
||||
version = "v0.9.1"
|
||||
hash = "sha256-mNfQtcrQmu3sNg/7IwiieKWOgFQOVVe2yXgKBpe/wZw="
|
||||
[mod."github.com/pkumza/numcn"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-cPxqj5tb10+MurN1Lehkk/v8KjaxXpL08+pVgL4x4Hg="
|
||||
[mod."github.com/power-devops/perfstat"]
|
||||
version = "v0.0.0-20210106213030-5aafc221ea8c"
|
||||
hash = "sha256-ywykDYuqcMt0TvZOz1l9Z6Z2JMTYQw8cP2fT8AtpmX4="
|
||||
[mod."github.com/quic-go/qpack"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-QWIumzmHD94DlNp9G3AQf9QCtF+Kv0pShT1+FH7/I/c="
|
||||
[mod."github.com/quic-go/qtls-go1-20"]
|
||||
version = "v0.3.3"
|
||||
hash = "sha256-YiT0g2gUxaZgJlQqQDkQqJme44LYHdzErHVEbY3bIa0="
|
||||
[mod."github.com/quic-go/quic-go"]
|
||||
version = "v0.38.1"
|
||||
hash = "sha256-CC1E4sLcoMA1Jb9QdiVBaBq9GNUmxAPGBz3f/SJaHDY="
|
||||
[mod."github.com/remyoudompheng/bigfft"]
|
||||
version = "v0.0.0-20211011143303-6e0bfa3c836b"
|
||||
hash = "sha256-SHwiLdLvGHYnbWm+03ddYc2550RdFdx/VadJfZyQEKA="
|
||||
replaced = "github.com/fumiama/bigfft"
|
||||
[mod."github.com/shirou/gopsutil/v3"]
|
||||
version = "v3.23.1"
|
||||
hash = "sha256-DYoN9o+PGrnYev7i+NISAKEqFdCKpimpi4s0FWmFpkY="
|
||||
[mod."github.com/sirupsen/logrus"]
|
||||
version = "v1.9.3"
|
||||
hash = "sha256-EnxsWdEUPYid+aZ9H4/iMTs1XMvCLbXZRDyvj89Ebms="
|
||||
[mod."github.com/tetratelabs/wazero"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-fGdJM4LJrZA9jxHuYVo4EUQ3I1k0IVG3QQCBCgZkeZI="
|
||||
[mod."github.com/tidwall/gjson"]
|
||||
version = "v1.14.4"
|
||||
hash = "sha256-3DS2YNL95wG0qSajgRtIABD32J+oblaKVk8LIw+KSOc="
|
||||
[mod."github.com/tidwall/match"]
|
||||
version = "v1.1.1"
|
||||
hash = "sha256-M2klhPId3Q3T3VGkSbOkYl/2nLHnsG+yMbXkPkyrRdg="
|
||||
[mod."github.com/tidwall/pretty"]
|
||||
version = "v1.2.0"
|
||||
hash = "sha256-esRQGsn2Ee/CiySlwyuOICSLdqUkH4P7u8qXszos8Yc="
|
||||
[mod."github.com/tklauser/go-sysconf"]
|
||||
version = "v0.3.11"
|
||||
hash = "sha256-io8s7PJi4OX+wXkCm+v5pKy4yiqA/RE/I4ksy6mKX30="
|
||||
[mod."github.com/tklauser/numcpus"]
|
||||
version = "v0.6.0"
|
||||
hash = "sha256-6jssTsP5L6yVl43tXfqDdgeI+tEkBp3BpiWwKXLTHAM="
|
||||
[mod."github.com/wcharczuk/go-chart/v2"]
|
||||
version = "v2.1.0"
|
||||
hash = "sha256-0s07aT7i3zMyVaS1hHO6SaCilVy39HwC8Po6wcENn9E="
|
||||
[mod."github.com/wdvxdr1123/ZeroBot"]
|
||||
version = "v1.7.5-0.20231009162356-57f71b9f5258"
|
||||
hash = "sha256-sIrH0WUDJeEGMD8FWh8UyrI3aHNN6NT7l+/isSl3ico="
|
||||
[mod."github.com/yusufpapurcu/wmi"]
|
||||
version = "v1.2.2"
|
||||
hash = "sha256-Rno6F82JIeglBobQl6YKl3U6+FvWXmFavJlzpOJgoXI="
|
||||
[mod."gitlab.com/gomidi/midi/v2"]
|
||||
version = "v2.0.25"
|
||||
hash = "sha256-3oTPzuPX1hNd+6/5kRUcMfMztvQa2UWHPppp8OPiP90="
|
||||
[mod."golang.org/x/crypto"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-PvHIbuooDItiNyQEi8kKgybkc0o95B0aeMd9awVGFCY="
|
||||
[mod."golang.org/x/exp"]
|
||||
version = "v0.0.0-20221205204356-47842c84f3db"
|
||||
hash = "sha256-HWHDTTbsKZp1bMN06ZKluiLt8Yfjtnf1XhR9GWp4rQk="
|
||||
[mod."golang.org/x/exp/shiny"]
|
||||
version = "v0.0.0-20221126150942-6ab00d035af9"
|
||||
hash = "sha256-+OAzuS+wyjOBSarGBuHjMeQV3vZzTbmF7CH8wnE7aA8="
|
||||
[mod."golang.org/x/image"]
|
||||
version = "v0.3.0"
|
||||
hash = "sha256-d6/w/CwI5GRGjuOGA7L7x4rEPfcHAVV3ZzsKxKmMYR4="
|
||||
[mod."golang.org/x/mobile"]
|
||||
version = "v0.0.0-20201217150744-e6ae53a27f4f"
|
||||
hash = "sha256-NdxlpSJhVpmE/T84HHoPtQ1GPCvDNkbNzNTYa5HEEYE="
|
||||
[mod."golang.org/x/mod"]
|
||||
version = "v0.10.0"
|
||||
hash = "sha256-g0T2wz+K0nhPWdVQJRGGqEqzlTHMBahv+9C3y090eIM="
|
||||
[mod."golang.org/x/net"]
|
||||
version = "v0.10.0"
|
||||
hash = "sha256-HkGiUYBZOBdOtt7mYo3N3swFjjAXzW++pG2JeWGJR9Q="
|
||||
[mod."golang.org/x/sys"]
|
||||
version = "v0.8.0"
|
||||
hash = "sha256-wLPPnoFkHM1HPUaFIfRyQZOJjrqXVZimB0nMySly7Xg="
|
||||
[mod."golang.org/x/text"]
|
||||
version = "v0.9.0"
|
||||
hash = "sha256-tkhDeMsSQZr3jo7vmKehWs3DvWetwXR0IB+DCLbQ4nk="
|
||||
[mod."golang.org/x/tools"]
|
||||
version = "v0.9.1"
|
||||
hash = "sha256-6jvh0cvdVMvGBceeBxWFj0+bFvboB8wuIYPHabxrST0="
|
||||
[mod."gopkg.in/check.v1"]
|
||||
version = "v1.0.0-20201130134442-10cb98267c6c"
|
||||
hash = "sha256-VlIpM2r/OD+kkyItn6vW35dyc0rtkJufA93rjFyzncs="
|
||||
[mod."gopkg.in/yaml.v3"]
|
||||
version = "v3.0.1"
|
||||
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="
|
||||
[mod."modernc.org/libc"]
|
||||
version = "v1.21.5"
|
||||
hash = "sha256-q2ZMb7TY1mp/Ia6e/I+44mrmpUBHErW4Q6/lPXpep28="
|
||||
[mod."modernc.org/mathutil"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-5xM9HjjHf9sB0vLfN53PdGpT0qPF1+KI1/lgN0/4LQo="
|
||||
[mod."modernc.org/memory"]
|
||||
version = "v1.4.0"
|
||||
hash = "sha256-x78QWQ1H82eolL7JiG6eP6l4fHhRNyIlSryQKpibcBo="
|
||||
[mod."modernc.org/sqlite"]
|
||||
version = "v1.20.0-with-win386"
|
||||
hash = "sha256-ICV8xqeBvySJtmVV4DpqihUyRbXdaq11ba+UvMltFn8="
|
||||
replaced = "github.com/fumiama/sqlite3"
|
||||
@@ -3,13 +3,13 @@
|
||||
package banner
|
||||
|
||||
// Version ...
|
||||
var Version = "v1.7.0-beta4"
|
||||
var Version = "v1.7.8"
|
||||
|
||||
// Copyright ...
|
||||
var Copyright = "© 2020 - 2023 FloatTech"
|
||||
var Copyright = "© 2020 - 2024 FloatTech"
|
||||
|
||||
// Banner ...
|
||||
var Banner = "* OneBot + ZeroBot + Golang\n" +
|
||||
"* Version " + Version + " - 2023-03-12 12:28:19 +0800 CST\n" +
|
||||
"* Version " + Version + " - 2024-04-30 17:51:12 +0900 JST\n" +
|
||||
"* Copyright " + Copyright + ". All Rights Reserved.\n" +
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
||||
|
||||
@@ -27,7 +27,7 @@ var Banner = "* OneBot + ZeroBot + Golang\n" +
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
||||
`
|
||||
|
||||
const timeformat = `2006-01-02 15:04:05 +0800 CST`
|
||||
const timeformat = `2006-01-02 15:04:05 +0900 JST`
|
||||
|
||||
func main() {
|
||||
f, err := os.Create("banner/banner.go")
|
||||
|
||||
5
kanban/version_less_than_1.21.go
Normal file
5
kanban/version_less_than_1.21.go
Normal file
@@ -0,0 +1,5 @@
|
||||
//go:build go1.21
|
||||
|
||||
package kanban
|
||||
|
||||
const Error int = "请使用小于1.21版本的Go"
|
||||
57
main.go
57
main.go
@@ -34,7 +34,7 @@ import (
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat" // 基础词库
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleep_manage" // 统计睡眠时间
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleepmanage" // 统计睡眠时间
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri" // ATRI词库
|
||||
|
||||
@@ -61,19 +61,20 @@ import (
|
||||
// vvvv //
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ahsai" // ahsai tts
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_false" // 服务器监控
|
||||
_ "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/b14" // base16384加解密
|
||||
_ "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/book_review" // 哀伤雪刃吧推书记录
|
||||
_ "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" // 英文字符翻转
|
||||
@@ -82,9 +83,10 @@ import (
|
||||
_ "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/drift_bottle" // 漂流瓶
|
||||
_ "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" // 渲染任意文字到图片
|
||||
@@ -98,7 +100,7 @@ import (
|
||||
_ "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/image_finder" // 关键字搜图
|
||||
_ "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" // 兽语加密
|
||||
@@ -106,18 +108,20 @@ import (
|
||||
_ "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/moyu_calendar" // 摸鱼人日历
|
||||
_ "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/nativewife" // 本地老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nbnhhsh" // 拼音首字母缩写释义工具
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nihongo" // 日语语法学习
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/novel" // 铅笔小说网搜索
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nsfw" // nsfw图片识别
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/nwife" // 本地老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/omikuji" // 浅草寺求签
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife" // 一群一天一夫一妻制群老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/quan" // QQ权重查询
|
||||
@@ -126,29 +130,31 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/reborn" // 投胎
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode" // 在线运行代码
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/saucenao" // 以图搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/scale" // 叔叔的AI二次元图片放大
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/score" // 分数
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/setutime" // 来份涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shadiao" // 沙雕app
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shindan" // 测定
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/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/vtb_quotation" // vtb语录
|
||||
_ "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/wenxinAI" // 百度文心AI画图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count" // 聊天热词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinvilg" // 百度文心AI画图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wife" // 抽老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordcount" // 聊天热词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ygo" // 游戏王相关插件
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/yujn" // 遇见API
|
||||
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wtf" // 鬼东西
|
||||
|
||||
// ^^^^ //
|
||||
@@ -173,6 +179,8 @@ import (
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply" // 人工智能回复
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/thesaurus" // 词典匹配回复
|
||||
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/breakrepeat" // 打断复读
|
||||
|
||||
// ^^^^ //
|
||||
@@ -226,6 +234,7 @@ func init() {
|
||||
late := flag.Uint("l", 233, "Response latency (ms).")
|
||||
rsz := flag.Uint("r", 4096, "Receiving buffer ring size.")
|
||||
maxpt := flag.Uint("x", 4, "Max process time (min).")
|
||||
markmsg := flag.Bool("m", false, "Don't mark message as read automatically")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
@@ -233,13 +242,12 @@ func init() {
|
||||
fmt.Println("Usage:")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(0)
|
||||
} else {
|
||||
if *d && !*w {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if *w {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
}
|
||||
}
|
||||
if *d && !*w {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if *w {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
}
|
||||
|
||||
for _, s := range flag.Args() {
|
||||
@@ -254,6 +262,9 @@ func init() {
|
||||
// sus = append(sus, 12345678)
|
||||
// sus = append(sus, 87654321)
|
||||
|
||||
// 启用 webui
|
||||
// go webctrl.RunGui(*g)
|
||||
|
||||
if *runcfg != "" {
|
||||
f, err := os.Open(*runcfg)
|
||||
if err != nil {
|
||||
@@ -283,6 +294,7 @@ func init() {
|
||||
RingLen: *rsz,
|
||||
Latency: time.Duration(*late) * time.Millisecond,
|
||||
MaxProcessTime: time.Duration(*maxpt) * time.Minute,
|
||||
MarkMessage: !*markmsg,
|
||||
Driver: []zero.Driver{config.W[0]},
|
||||
}
|
||||
|
||||
@@ -299,9 +311,6 @@ func init() {
|
||||
logrus.Infoln("[main] 配置文件已保存到", *save)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// 启用 webui
|
||||
// go webctrl.RunGui(*g)
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -309,7 +318,7 @@ func main() {
|
||||
rand.Seed(time.Now().UnixNano()) //nolint: staticcheck
|
||||
}
|
||||
// 帮助
|
||||
zero.OnFullMatchGroup([]string{"/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).
|
||||
zero.OnFullMatchGroup([]string{"help", "/help", ".help", "菜单"}, zero.OnlyToMe).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text(banner.Banner, "\n管理发送\"/服务列表\"查看 bot 功能\n发送\"/用法name\"查看功能用法"))
|
||||
})
|
||||
|
||||
@@ -27,7 +27,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("ahsai", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "フリーテキスト音声合成",
|
||||
Help: "- 使[伊織弓鶴|紲星あかり|結月ゆかり|京町セイカ|東北きりたん|東北イタコ|ついなちゃん標準語|ついなちゃん関西弁|音街ウナ|琴葉茜|吉田くん|民安ともえ|桜乃そら|月読アイ|琴葉葵|東北ずん子|月読ショウタ|水奈瀬コウ]说(日语)",
|
||||
|
||||
@@ -2,58 +2,76 @@ package aireply
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/RomiChan/syncx"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/aireply"
|
||||
"github.com/FloatTech/AnimeAPI/tts"
|
||||
"github.com/FloatTech/AnimeAPI/tts/baidutts"
|
||||
"github.com/FloatTech/AnimeAPI/tts/genshin"
|
||||
"github.com/FloatTech/AnimeAPI/tts/mockingbird"
|
||||
"github.com/FloatTech/AnimeAPI/tts/lolimi"
|
||||
"github.com/FloatTech/AnimeAPI/tts/ttscn"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
)
|
||||
|
||||
// 数据结构: [4 bits] [4 bits] [8 bits] [8 bits]
|
||||
// [拟声鸟模式] [百度模式] [tts模式] [回复模式]
|
||||
// 数据结构: [8 bits] [8 bits] [8 bits]
|
||||
// [具体人物] [tts模式] [回复模式]
|
||||
|
||||
// defaultttsindexkey
|
||||
// 数据结构: [4 bits] [4 bits] [8 bits]
|
||||
// [拟声鸟模式] [百度模式] [tts模式]
|
||||
// 数据结构: [8 bits] [8 bits]
|
||||
// [具体人物] [tts模式]
|
||||
|
||||
// [tts模式]: 0~63 genshin 64 baidu 65 mockingbird
|
||||
// [tts模式]: 0~200 genshin 201 baidu 202 ttscn 203 lolimi
|
||||
|
||||
const (
|
||||
lastgsttsindex = 63 + iota
|
||||
baiduttsindex
|
||||
mockingbirdttsindex
|
||||
baiduttsindex = 201 + iota
|
||||
ttscnttsindex
|
||||
lolimittsindex
|
||||
)
|
||||
|
||||
// extrattsname is the tts other than genshin vits
|
||||
var extrattsname = []string{"百度", "拟声鸟"}
|
||||
var extrattsname = []string{"百度", "TTSCN", "桑帛云"}
|
||||
|
||||
const (
|
||||
defaultttsindexkey = -2905
|
||||
gsapikeyextragrp = -1
|
||||
chatgptapikeyextragrp = -2
|
||||
)
|
||||
|
||||
type replymode struct {
|
||||
APIKey string // APIKey is for chatgpt
|
||||
replyModes []string `json:"-"`
|
||||
var ttscnspeakers = [...]string{
|
||||
"晓晓(女 - 年轻人)",
|
||||
"云扬(男 - 年轻人)",
|
||||
"晓辰(女 - 年轻人 - 抖音热门)",
|
||||
"晓涵(女 - 年轻人)",
|
||||
"晓墨(女 - 年轻人)",
|
||||
"晓秋(女 - 中年人)",
|
||||
"晓睿(女 - 老年)",
|
||||
"晓双(女 - 儿童)",
|
||||
"晓萱(女 - 年轻人)",
|
||||
"晓颜(女 - 年轻人)",
|
||||
"晓悠(女 - 儿童)",
|
||||
"云希(男 - 年轻人 - 抖音热门)",
|
||||
"云野(男 - 中年人)",
|
||||
"晓梦(女 - 年轻人)",
|
||||
"晓伊(女 - 儿童)",
|
||||
"晓甄(女 - 年轻人)",
|
||||
}
|
||||
|
||||
func (r *replymode) setReplyMode(ctx *zero.Ctx, name string) error {
|
||||
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.replyModes {
|
||||
for i, s := range r {
|
||||
if s == name {
|
||||
ok = true
|
||||
index = int64(i)
|
||||
@@ -67,10 +85,10 @@ func (r *replymode) setReplyMode(ctx *zero.Ctx, name string) error {
|
||||
if !ok {
|
||||
return errors.New("no such plugin")
|
||||
}
|
||||
return m.SetData(gid, (m.GetData(index)&^0xff)|(index&0xff))
|
||||
return m.SetData(gid, (m.GetData(gid)&^0xff)|(index&0xff))
|
||||
}
|
||||
|
||||
func (r *replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply {
|
||||
func (r replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
@@ -79,37 +97,26 @@ func (r *replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply {
|
||||
if ok {
|
||||
switch m.GetData(gid) & 0xff {
|
||||
case 0:
|
||||
return aireply.NewQYK(aireply.QYKURL, aireply.QYKBotName)
|
||||
return aireply.NewLolimiAi(aireply.JingfengURL, aireply.JingfengBotName)
|
||||
case 1:
|
||||
return aireply.NewXiaoAi(aireply.XiaoAiURL, aireply.XiaoAiBotName)
|
||||
return aireply.NewLolimiAi(aireply.MomoURL, aireply.MomoBotName)
|
||||
case 2:
|
||||
k := r.getAPIKey(ctx)
|
||||
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.NewQYK(aireply.QYKURL, aireply.QYKBotName)
|
||||
return aireply.NewLolimiAi(aireply.JingfengURL, aireply.JingfengBotName)
|
||||
}
|
||||
}
|
||||
return aireply.NewQYK(aireply.QYKURL, aireply.QYKBotName)
|
||||
}
|
||||
|
||||
func (r *replymode) getAPIKey(ctx *zero.Ctx) string {
|
||||
if r.APIKey == "" {
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
_ = m.Manager.GetExtra(chatgptapikeyextragrp, &r)
|
||||
logrus.Debugln("[tts] get api key:", r.APIKey)
|
||||
}
|
||||
return r.APIKey
|
||||
}
|
||||
|
||||
func (r *replymode) setAPIKey(m *ctrl.Control[*zero.Ctx], key string) error {
|
||||
r.APIKey = key
|
||||
_ = m.Manager.Response(chatgptapikeyextragrp)
|
||||
return m.Manager.SetExtra(chatgptapikeyextragrp, r)
|
||||
return aireply.NewLolimiAi(aireply.JingfengURL, aireply.JingfengBotName)
|
||||
}
|
||||
|
||||
var ttsins = func() map[string]tts.TTS {
|
||||
m := make(map[string]tts.TTS, 128)
|
||||
m := make(map[string]tts.TTS, 512)
|
||||
for _, mode := range append(genshin.SoundList[:], extrattsname...) {
|
||||
m[mode] = nil
|
||||
}
|
||||
@@ -117,15 +124,12 @@ var ttsins = func() map[string]tts.TTS {
|
||||
}()
|
||||
|
||||
var ttsModes = func() []string {
|
||||
s := append(genshin.SoundList[:], make([]string, 64-len(genshin.SoundList))...) // 0-63
|
||||
s = append(s, extrattsname...) // 64 65 ...
|
||||
s := append(genshin.SoundList[:], make([]string, baiduttsindex-len(genshin.SoundList))...) // 0-200
|
||||
s = append(s, extrattsname...) // 201 202 ...
|
||||
return s
|
||||
}()
|
||||
|
||||
type ttsmode struct {
|
||||
APIKey string // APIKey is for genshin vits
|
||||
mode syncx.Map[int64, int64] `json:"-"` // mode grp index
|
||||
}
|
||||
type ttsmode syncx.Map[int64, int64]
|
||||
|
||||
func list(list []string, num int) string {
|
||||
s := ""
|
||||
@@ -143,34 +147,18 @@ func list(list []string, num int) string {
|
||||
func newttsmode() *ttsmode {
|
||||
t := &ttsmode{}
|
||||
m, ok := control.Lookup("tts")
|
||||
t.mode = syncx.Map[int64, int64]{}
|
||||
t.mode.Store(defaultttsindexkey, 0)
|
||||
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, 0)
|
||||
if ok {
|
||||
index := m.GetData(defaultttsindexkey)
|
||||
msk := index & 0xff
|
||||
if msk >= 0 && (msk < int64(len(genshin.SoundList)) || msk == baiduttsindex || msk == mockingbirdttsindex) {
|
||||
t.mode.Store(defaultttsindexkey, index)
|
||||
if msk >= 0 && (msk < int64(len(ttsModes))) {
|
||||
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, index)
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *ttsmode) getAPIKey(ctx *zero.Ctx) string {
|
||||
if t.APIKey == "" {
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
_ = m.Manager.GetExtra(gsapikeyextragrp, &t)
|
||||
logrus.Debugln("[tts] get api key:", t.APIKey)
|
||||
}
|
||||
return url.QueryEscape(t.APIKey)
|
||||
}
|
||||
|
||||
func (t *ttsmode) setAPIKey(m *ctrl.Control[*zero.Ctx], key string) error {
|
||||
t.APIKey = key
|
||||
_ = m.Manager.Response(gsapikeyextragrp)
|
||||
return m.Manager.SetExtra(gsapikeyextragrp, t)
|
||||
}
|
||||
|
||||
func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, baiduper, mockingsynt int) error {
|
||||
func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, character int) error {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
@@ -182,7 +170,7 @@ func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, baiduper, mockingsynt
|
||||
var index = int64(-1)
|
||||
for i, s := range genshin.SoundList {
|
||||
if s == name {
|
||||
index = int64(i)
|
||||
index = int64(i + 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -191,14 +179,18 @@ func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, baiduper, mockingsynt
|
||||
case extrattsname[0]:
|
||||
index = baiduttsindex
|
||||
case extrattsname[1]:
|
||||
index = mockingbirdttsindex
|
||||
index = ttscnttsindex
|
||||
case extrattsname[2]:
|
||||
index = lolimittsindex
|
||||
default:
|
||||
return errors.New("语音人物" + name + "未注册index")
|
||||
}
|
||||
}
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
t.mode.Store(gid, index)
|
||||
return m.SetData(gid, (m.GetData(gid)&^0xffff00)|((index<<8)&0xff00)|((int64(baiduper)<<16)&0x0f0000)|((int64(mockingsynt)<<20)&0xf00000))
|
||||
// 按原来的逻辑map存的是前16位
|
||||
storeIndex := (m.GetData(gid) &^ 0xffff00) | ((index << 8) & 0xff00) | ((int64(character) << 16) & 0xff0000)
|
||||
(*syncx.Map[int64, int64])(t).Store(gid, (storeIndex>>8)&0xffff)
|
||||
return m.SetData(gid, storeIndex)
|
||||
}
|
||||
|
||||
func (t *ttsmode) getSoundMode(ctx *zero.Ctx) (tts.TTS, error) {
|
||||
@@ -206,14 +198,18 @@ func (t *ttsmode) getSoundMode(ctx *zero.Ctx) (tts.TTS, error) {
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
i, ok := t.mode.Load(gid)
|
||||
i, ok := (*syncx.Map[int64, int64])(t).Load(gid)
|
||||
if !ok {
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
i = m.GetData(gid) >> 8
|
||||
}
|
||||
m := i & 0xff
|
||||
if m < 0 || (m >= int64(len(genshin.SoundList)) && m != baiduttsindex && m != mockingbirdttsindex) {
|
||||
i, _ = t.mode.Load(defaultttsindexkey)
|
||||
if m <= 0 || (m >= int64(len(ttsModes))) {
|
||||
i, _ = (*syncx.Map[int64, int64])(t).Load(defaultttsindexkey)
|
||||
if i == 0 {
|
||||
i = ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).GetData(defaultttsindexkey)
|
||||
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, i)
|
||||
}
|
||||
m = i & 0xff
|
||||
}
|
||||
mode := ttsModes[m]
|
||||
@@ -221,20 +217,23 @@ func (t *ttsmode) getSoundMode(ctx *zero.Ctx) (tts.TTS, error) {
|
||||
if !ok || ins == nil {
|
||||
switch mode {
|
||||
case extrattsname[0]:
|
||||
ins = baidutts.NewBaiduTTS(int(i&0x0f00) >> 8)
|
||||
id, sec, _ := strings.Cut(百.k, ",")
|
||||
ins = baidutts.NewBaiduTTS(int(i&0xff00)>>8, id, sec)
|
||||
case extrattsname[1]:
|
||||
var err error
|
||||
ins, err = mockingbird.NewMockingBirdTTS(int(i&0xf000) >> 12)
|
||||
ins, err = ttscn.NewTTSCN("中文(普通话,简体)", ttscnspeakers[int(i&0xff00)>>8], ttscn.KBRates[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case extrattsname[2]:
|
||||
ins = lolimi.NewLolimi(int(i&0xff00) >> 8)
|
||||
default: // 原神
|
||||
k := t.getAPIKey(ctx)
|
||||
k := 原.k
|
||||
if k != "" {
|
||||
ins = genshin.NewGenshin(int(m), t.getAPIKey(ctx))
|
||||
ins = genshin.NewGenshin(int(m-1), 原.k)
|
||||
ttsins[mode] = ins
|
||||
} else {
|
||||
return nil, errors.New("no valid speaker")
|
||||
ins = lolimi.NewLolimi(int(i&0xff00) >> 8)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,11 +246,12 @@ func (t *ttsmode) resetSoundMode(ctx *zero.Ctx) error {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
index := m.GetData(defaultttsindexkey)
|
||||
return m.SetData(gid, (m.GetData(gid)&0xff)|((index&^0xff)<<8)) // 重置数据
|
||||
// 只保留后面8位
|
||||
(*syncx.Map[int64, int64])(t).Delete(gid)
|
||||
return m.SetData(gid, (m.GetData(gid) & 0xff)) // 重置数据
|
||||
}
|
||||
|
||||
func (t *ttsmode) setDefaultSoundMode(name string, baiduper, mockingsynt int) error {
|
||||
func (t *ttsmode) setDefaultSoundMode(name string, character int) error {
|
||||
_, ok := ttsins[name]
|
||||
if !ok {
|
||||
return errors.New("不支持设置语音人物" + name)
|
||||
@@ -259,7 +259,7 @@ func (t *ttsmode) setDefaultSoundMode(name string, baiduper, mockingsynt int) er
|
||||
index := int64(-1)
|
||||
for i, s := range genshin.SoundList {
|
||||
if s == name {
|
||||
index = int64(i)
|
||||
index = int64(i + 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -268,7 +268,9 @@ func (t *ttsmode) setDefaultSoundMode(name string, baiduper, mockingsynt int) er
|
||||
case extrattsname[0]:
|
||||
index = baiduttsindex
|
||||
case extrattsname[1]:
|
||||
index = mockingbirdttsindex
|
||||
index = ttscnttsindex
|
||||
case extrattsname[2]:
|
||||
index = lolimittsindex
|
||||
default:
|
||||
return errors.New("语音人物" + name + "未注册index")
|
||||
}
|
||||
@@ -277,6 +279,7 @@ func (t *ttsmode) setDefaultSoundMode(name string, baiduper, mockingsynt int) er
|
||||
if !ok {
|
||||
return errors.New("[tts] service not found")
|
||||
}
|
||||
t.mode.Store(defaultttsindexkey, index)
|
||||
return m.SetData(defaultttsindexkey, (index&0xff)|((int64(baiduper)<<8)&0x0f00)|((int64(mockingsynt)<<12)&0xf000))
|
||||
storeIndex := (index & 0xff) | ((int64(character) << 8) & 0xff00)
|
||||
(*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, storeIndex)
|
||||
return m.SetData(defaultttsindexkey, storeIndex)
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/tts/genshin"
|
||||
@@ -15,9 +17,7 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var replmd = replymode{
|
||||
replyModes: []string{"青云客", "小爱", "ChatGPT"},
|
||||
}
|
||||
var replmd = replymode([]string{"婧枫", "沫沫", "青云客", "小爱", "ChatGPT"})
|
||||
|
||||
var ttsmd = newttsmode()
|
||||
|
||||
@@ -26,17 +26,21 @@ func init() { // 插件主体
|
||||
DisableOnDefault: true,
|
||||
Brief: "人工智能语音回复",
|
||||
Help: "- @Bot 任意文本(任意一句话回复)\n" +
|
||||
"- 设置语音模式[原神人物/百度/拟声鸟] 数字(百度/拟声鸟模式)\n" +
|
||||
"- 设置默认语音模式[原神人物/百度/拟声鸟] 数字(百度/拟声鸟模式)\n" +
|
||||
"- 设置语音模式[原神人物/百度/TTSCN/桑帛云] 数字(百度/TTSCN说话人/桑帛云)\n" +
|
||||
"- 设置默认语音模式[原神人物/百度/TTSCN/桑帛云] 数字(百度/TTSCN说话人/桑帛云)\n" +
|
||||
"- 恢复成默认语音模式\n" +
|
||||
"- 设置语音回复模式[沫沫|婧枫|青云客|小爱|ChatGPT]\n" +
|
||||
"- 设置原神语音 api key xxxxxx (key请加开发群获得)\n" +
|
||||
"当前适用的原神人物含有以下:\n" + list(genshin.SoundList[:], 5),
|
||||
"- 设置百度语音 api id xxxxxx secret xxxxxx (请自行获得)\n" +
|
||||
"当前适用的原神人物含有以下: \n" + list(genshin.SoundList[:], 5) +
|
||||
"\n当前适用的TTSCN人物含有以下(以数字顺序代表): \n" + list(ttscnspeakers[:], 5),
|
||||
PrivateDataFolder: "tts",
|
||||
})
|
||||
|
||||
enr := control.Register("aireply", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "人工智能回复",
|
||||
Help: "- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客|小爱|ChatGPT]\n- 设置 ChatGPT api key xxx",
|
||||
Help: "- @Bot 任意文本(任意一句话回复)\n- 设置文字回复模式[婧枫|沫沫|青云客|小爱|ChatGPT]\n- 设置 ChatGPT api key xxx",
|
||||
PrivateDataFolder: "aireply",
|
||||
})
|
||||
|
||||
@@ -46,15 +50,10 @@ func init() { // 插件主体
|
||||
reply := message.ParseMessageFromString(aireply.Talk(ctx.Event.UserID, ctx.ExtractPlainText(), zero.BotConfig.NickName[0]))
|
||||
// 回复
|
||||
time.Sleep(time.Second * 1)
|
||||
if zero.OnlyPublic(ctx) {
|
||||
reply = append(reply, message.Reply(ctx.Event.MessageID))
|
||||
ctx.Send(reply)
|
||||
return
|
||||
}
|
||||
reply = append(reply, message.Reply(ctx.Event.MessageID))
|
||||
ctx.Send(reply)
|
||||
})
|
||||
|
||||
enr.OnPrefix("设置回复模式", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
setReplyMode := func(ctx *zero.Ctx) {
|
||||
param := ctx.State["args"].(string)
|
||||
err := replmd.setReplyMode(ctx, param)
|
||||
if err != nil {
|
||||
@@ -62,10 +61,10 @@ func init() { // 插件主体
|
||||
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 := replmd.setAPIKey(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), ctx.State["regex_matched"].([]string)[1])
|
||||
err := ཆཏ.set(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
@@ -74,13 +73,32 @@ func init() { // 插件主体
|
||||
})
|
||||
|
||||
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 := r.TalkPlain(ctx.Event.UserID, msg, zero.BotConfig.NickName[0])
|
||||
reply := message.ParseMessageFromString(r.TalkPlain(ctx.Event.UserID, msg, zero.BotConfig.NickName[0]))
|
||||
// 过滤掉文字消息
|
||||
filterMsg := make([]message.MessageSegment, 0, len(reply))
|
||||
sb := strings.Builder{}
|
||||
for _, v := range reply {
|
||||
if v.Type != "text" {
|
||||
filterMsg = append(filterMsg, v)
|
||||
} else {
|
||||
sb.WriteString(v.Data["text"])
|
||||
}
|
||||
}
|
||||
// 纯文本
|
||||
plainReply := sb.String()
|
||||
plainReply = strings.ReplaceAll(plainReply, "\n", "")
|
||||
// 获取语音
|
||||
speaker, err := ttsmd.getSoundMode(ctx)
|
||||
if err != nil {
|
||||
@@ -88,22 +106,27 @@ func init() { // 插件主体
|
||||
return
|
||||
}
|
||||
rec, err := speaker.Speak(ctx.Event.UserID, func() string {
|
||||
if !endpre.MatchString(reply) {
|
||||
return reply + "。"
|
||||
if !endpre.MatchString(plainReply) {
|
||||
return plainReply + "。"
|
||||
}
|
||||
return reply
|
||||
return plainReply
|
||||
})
|
||||
// 发送前面的图片
|
||||
if len(filterMsg) != 0 {
|
||||
filterMsg = append(filterMsg, message.Reply(ctx.Event.MessageID))
|
||||
ctx.Send(filterMsg)
|
||||
}
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(plainReply))
|
||||
return
|
||||
}
|
||||
// 发送语音
|
||||
if id := ctx.SendChain(message.Record(rec)); id.ID() == 0 {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(plainReply))
|
||||
}
|
||||
})
|
||||
|
||||
ent.OnRegex(`^设置语音模式\s*([\S\D]*)\s*(\d*)$`, zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
ent.OnPrefix("设置语音回复模式", zero.AdminPermission).SetBlock(true).Handle(setReplyMode)
|
||||
ent.OnRegex(`^设置语音模式\s*([\S\D]*)\s+(\d*)$`, zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
num := ctx.State["regex_matched"].([]string)[2]
|
||||
n := 0
|
||||
@@ -116,37 +139,39 @@ func init() { // 插件主体
|
||||
}
|
||||
}
|
||||
// 保存设置
|
||||
logrus.Debugln("[tts] t.setSoundMode( ctx", param, n, n, ")")
|
||||
err = ttsmd.setSoundMode(ctx, param, n, n)
|
||||
logrus.Debugln("[tts] t.setSoundMode( ctx", param, n, ")")
|
||||
err = ttsmd.setSoundMode(ctx, param, n)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
}
|
||||
if banner, ok := genshin.TestRecord[param]; ok {
|
||||
logrus.Debugln("[tts] banner:", banner, "get sound mode...")
|
||||
// 设置验证
|
||||
speaker, err := 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)
|
||||
banner := genshin.TestRecord[param]
|
||||
if banner == "" {
|
||||
banner = genshin.TestRecord["默认"]
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功"))
|
||||
logrus.Debugln("[tts] banner:", banner, "get sound mode...")
|
||||
// 设置验证
|
||||
speaker, err := ttsmd.getSoundMode(ctx)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[tts] got sound mode, speaking...")
|
||||
rec, err := speaker.Speak(ctx.Event.UserID, func() string { return banner })
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("无法发送测试语音,请重试。"))
|
||||
return
|
||||
}
|
||||
logrus.Debugln("[tts] sending...")
|
||||
if id := ctx.SendChain(message.Record(rec).Add("cache", 0)); id.ID() == 0 {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("无法发送测试语音,请重试。"))
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Second * 2)
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前为", speaker))
|
||||
})
|
||||
|
||||
ent.OnRegex(`^设置默认语音模式\s*([\S\D]*)\s*(\d*)$`, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
ent.OnRegex(`^设置默认语音模式\s*([\S\D]*)\s+(\d*)$`, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
param := ctx.State["regex_matched"].([]string)[1]
|
||||
num := ctx.State["regex_matched"].([]string)[2]
|
||||
n := 0
|
||||
@@ -159,7 +184,7 @@ func init() { // 插件主体
|
||||
}
|
||||
}
|
||||
// 保存设置
|
||||
err = ttsmd.setDefaultSoundMode(param, n, n)
|
||||
err = ttsmd.setDefaultSoundMode(param, n)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
|
||||
return
|
||||
@@ -183,7 +208,16 @@ func init() { // 插件主体
|
||||
})
|
||||
|
||||
ent.OnRegex(`^设置原神语音\s*api\s*key\s*([0-9a-zA-Z-_]{54}==)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
err := ttsmd.setAPIKey(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), ctx.State["regex_matched"].([]string)[1])
|
||||
err := 原.set(ctx.State["regex_matched"].([]string)[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("设置成功"))
|
||||
})
|
||||
|
||||
ent.OnRegex(`^设置百度语音\s*api\s*id\s*(.*)\s*secret\s*(.*)\s*$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
err := 百.set(ctx.State["regex_matched"].([]string)[1] + "," + ctx.State["regex_matched"].([]string)[2])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
|
||||
29
plugin/ai_reply/model.go
Normal file
29
plugin/ai_reply/model.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package aireply
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
)
|
||||
|
||||
type apikeystore struct {
|
||||
k string
|
||||
p string
|
||||
}
|
||||
|
||||
func newapikeystore(p string) (s apikeystore) {
|
||||
s.p = p
|
||||
if file.IsExist(p) {
|
||||
data, err := os.ReadFile(p)
|
||||
if err == nil {
|
||||
s.k = binary.BytesToString(data)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *apikeystore) set(k string) error {
|
||||
s.k = k
|
||||
return os.WriteFile(s.p, binary.StringToBytes(k), 0644)
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"math"
|
||||
"runtime"
|
||||
"strconv"
|
||||
@@ -45,13 +46,16 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
boottime = time.Now()
|
||||
bgdata *[]byte
|
||||
bgcount uintptr
|
||||
boottime = time.Now()
|
||||
bgdata *[]byte
|
||||
bgcount uintptr
|
||||
isday bool
|
||||
lightcolor = [3][4]uint8{{255, 70, 0, 255}, {255, 165, 0, 255}, {145, 240, 145, 255}}
|
||||
darkcolor = [3][4]uint8{{215, 50, 0, 255}, {205, 135, 0, 255}, {115, 200, 115, 255}}
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("aifalse", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "自检, 全局限速",
|
||||
Help: "- 查询计算机当前活跃度: [检查身体 | 自检 | 启动自检 | 系统状态]\n" +
|
||||
@@ -70,7 +74,26 @@ func init() { // 插件主体
|
||||
}
|
||||
engine.OnFullMatchGroup([]string{"检查身体", "自检", "启动自检", "系统状态"}, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
img, err := drawstatus(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), ctx.Event.SelfID, zero.BotConfig.NickName[0])
|
||||
now := time.Now().Hour()
|
||||
isday = now > 7 && now < 19
|
||||
|
||||
botrunstatus := ctx.CallAction("get_status", zero.Params{}).Data
|
||||
botverisoninfo := ctx.GetVersionInfo()
|
||||
sb := &strings.Builder{}
|
||||
sb.WriteString("在线(")
|
||||
sb.WriteString(botverisoninfo.Get("app_name").String())
|
||||
sb.WriteString("-")
|
||||
sb.WriteString(botverisoninfo.Get("app_version").String())
|
||||
sb.WriteString(") | 收")
|
||||
sb.WriteString(botrunstatus.Get("stat").Get("message_received").String())
|
||||
sb.WriteString(" | 发")
|
||||
sb.WriteString(botrunstatus.Get("stat").Get("message_sent").String())
|
||||
sb.WriteString(" | 群")
|
||||
sb.WriteString(strconv.Itoa(len(ctx.GetGroupList().Array())))
|
||||
sb.WriteString(" | 好友")
|
||||
sb.WriteString(strconv.Itoa(len(ctx.GetFriendList().Array())))
|
||||
|
||||
img, err := drawstatus(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), ctx.Event.SelfID, zero.BotConfig.NickName[0], sb.String())
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
@@ -122,7 +145,7 @@ func init() { // 插件主体
|
||||
})
|
||||
}
|
||||
|
||||
func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg image.Image, err error) {
|
||||
func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string, botrunstatus string) (sendimg image.Image, err error) {
|
||||
diskstate, err := diskstate()
|
||||
if err != nil {
|
||||
return
|
||||
@@ -187,6 +210,19 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
back = imgfactory.Size(back, int(bw*cw/bw), int(bh*cw/bw)).Image()
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
}
|
||||
var blurback image.Image
|
||||
bwg := &sync.WaitGroup{}
|
||||
bwg.Add(1)
|
||||
go func() {
|
||||
defer bwg.Done()
|
||||
blurback = imaging.Blur(canvas.Image(), 8)
|
||||
}()
|
||||
|
||||
if !isday {
|
||||
canvas.SetRGBA255(0, 0, 0, 50)
|
||||
canvas.DrawRectangle(0, 0, cw, ch)
|
||||
canvas.Fill()
|
||||
}
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(5)
|
||||
@@ -200,14 +236,14 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
titlecard := gg.NewContext(cardw, titlecardh)
|
||||
|
||||
titlecard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70)
|
||||
bwg.Wait()
|
||||
titlecard.DrawImage(blurback, -70, -70)
|
||||
|
||||
titlecard.DrawRoundedRectangle(1, 1, float64(titlecard.W()-1*2), float64(titlecardh-1*2), 16)
|
||||
titlecard.SetLineWidth(3)
|
||||
titlecard.SetRGBA255(255, 255, 255, 100)
|
||||
titlecard.SetColor(colorswitch(100))
|
||||
titlecard.StrokePreserve()
|
||||
titlecard.SetRGBA255(255, 255, 255, 140)
|
||||
titlecard.SetColor(colorswitch(140))
|
||||
titlecard.Fill()
|
||||
|
||||
titlecard.DrawImage(avatarf.Circle(0).Image(), (titlecardh-avatarf.H())/2, (titlecardh-avatarf.H())/2)
|
||||
@@ -218,7 +254,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
}
|
||||
fw, _ := titlecard.MeasureString(botname)
|
||||
|
||||
titlecard.SetRGBA255(30, 30, 30, 255)
|
||||
titlecard.SetColor(fontcolorswitch())
|
||||
|
||||
titlecard.DrawStringAnchored(botname, float64(titlecardh)+fw/2, float64(titlecardh)*0.5/2, 0.5, 0.5)
|
||||
|
||||
@@ -226,20 +262,24 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
titlecard.SetRGBA255(30, 30, 30, 180)
|
||||
titlecard.SetColor(fontcolorswitch())
|
||||
|
||||
titlecard.NewSubPath()
|
||||
titlecard.MoveTo(float64(titlecardh), float64(titlecardh)/2)
|
||||
titlecard.LineTo(float64(titlecard.W()-titlecardh), float64(titlecardh)/2)
|
||||
titlecard.Stroke()
|
||||
|
||||
fw, _ = titlecard.MeasureString(botrunstatus)
|
||||
|
||||
titlecard.DrawStringAnchored(botrunstatus, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.25/2), 0.5, 0.5)
|
||||
|
||||
brt, err := botruntime()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fw, _ = titlecard.MeasureString(brt)
|
||||
|
||||
titlecard.DrawStringAnchored(brt, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.25/2), 0.5, 0.5)
|
||||
titlecard.DrawStringAnchored(brt, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.5/2), 0.5, 0.5)
|
||||
|
||||
bs, err := botstatus()
|
||||
if err != nil {
|
||||
@@ -247,37 +287,45 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
}
|
||||
fw, _ = titlecard.MeasureString(bs)
|
||||
|
||||
titlecard.DrawStringAnchored(bs, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.5/2), 0.5, 0.5)
|
||||
titlecard.DrawStringAnchored(bs, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.75/2), 0.5, 0.5)
|
||||
titleimg = rendercard.Fillet(titlecard.Image(), 16)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
basiccard := gg.NewContext(cardw, basiccardh)
|
||||
|
||||
basiccard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70-titlecardh-40)
|
||||
bwg.Wait()
|
||||
basiccard.DrawImage(blurback, -70, -70-titlecardh-40)
|
||||
|
||||
basiccard.DrawRoundedRectangle(1, 1, float64(basiccard.W()-1*2), float64(basiccardh-1*2), 16)
|
||||
basiccard.SetLineWidth(3)
|
||||
basiccard.SetRGBA255(255, 255, 255, 100)
|
||||
basiccard.SetColor(colorswitch(100))
|
||||
basiccard.StrokePreserve()
|
||||
basiccard.SetRGBA255(255, 255, 255, 140)
|
||||
basiccard.SetColor(colorswitch(140))
|
||||
basiccard.Fill()
|
||||
|
||||
bslen := len(basicstate)
|
||||
for i, v := range basicstate {
|
||||
offset := float64(i) * ((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1) + 200)
|
||||
|
||||
basiccard.SetRGBA255(235, 235, 235, 255)
|
||||
basiccard.SetRGBA255(57, 57, 57, 255)
|
||||
if isday {
|
||||
basiccard.SetRGBA255(235, 235, 235, 255)
|
||||
}
|
||||
basiccard.DrawCircle((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 100)
|
||||
basiccard.Fill()
|
||||
|
||||
colors := darkcolor
|
||||
if isday {
|
||||
colors = lightcolor
|
||||
}
|
||||
|
||||
switch {
|
||||
case v.precent > 90:
|
||||
basiccard.SetRGBA255(255, 70, 0, 255)
|
||||
basiccard.SetColor(slice2color(colors[0]))
|
||||
case v.precent > 70:
|
||||
basiccard.SetRGBA255(255, 165, 0, 255)
|
||||
basiccard.SetColor(slice2color(colors[1]))
|
||||
default:
|
||||
basiccard.SetRGBA255(145, 240, 145, 255)
|
||||
basiccard.SetColor(slice2color(colors[2]))
|
||||
}
|
||||
|
||||
basiccard.NewSubPath()
|
||||
@@ -285,7 +333,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
basiccard.DrawEllipticalArc((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 100, 100, -0.5*math.Pi, -0.5*math.Pi+2*v.precent*0.01*math.Pi)
|
||||
basiccard.Fill()
|
||||
|
||||
basiccard.SetRGBA255(255, 255, 255, 255)
|
||||
basiccard.SetColor(colorswitch(255))
|
||||
basiccard.DrawCircle((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 80)
|
||||
basiccard.Fill()
|
||||
|
||||
@@ -297,7 +345,8 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
basiccard.SetRGBA255(213, 213, 213, 255)
|
||||
basiccard.DrawStringAnchored(strconv.FormatFloat(v.precent, 'f', 0, 64)+"%", (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 0.5, 0.5)
|
||||
|
||||
basiccard.SetRGBA255(30, 30, 30, 255)
|
||||
basiccard.SetColor(fontcolorswitch())
|
||||
|
||||
_, fw := basiccard.MeasureString(v.name)
|
||||
basiccard.DrawStringAnchored(v.name, (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200+15+basiccard.FontHeight()/2, 0.5, 0.5)
|
||||
|
||||
@@ -305,7 +354,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
basiccard.SetRGBA255(30, 30, 30, 180)
|
||||
basiccard.SetColor(fontcolorswitch())
|
||||
|
||||
textoffsety := basiccard.FontHeight() + 10
|
||||
for k, s := range v.text {
|
||||
@@ -317,13 +366,14 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
diskcard := gg.NewContext(cardw, diskcardh)
|
||||
diskcard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70-titlecardh-40-basiccardh-40)
|
||||
bwg.Wait()
|
||||
diskcard.DrawImage(blurback, -70, -70-titlecardh-40-basiccardh-40)
|
||||
|
||||
diskcard.DrawRoundedRectangle(1, 1, float64(diskcard.W()-1*2), float64(diskcardh-1*2), 16)
|
||||
diskcard.SetLineWidth(3)
|
||||
diskcard.SetRGBA255(255, 255, 255, 100)
|
||||
diskcard.SetColor(colorswitch(100))
|
||||
diskcard.StrokePreserve()
|
||||
diskcard.SetRGBA255(255, 255, 255, 140)
|
||||
diskcard.SetColor(colorswitch(140))
|
||||
diskcard.Fill()
|
||||
|
||||
err = diskcard.ParseFontFace(fontbyte, 32)
|
||||
@@ -333,23 +383,33 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
|
||||
dslen := len(diskstate)
|
||||
if dslen == 1 {
|
||||
diskcard.SetRGBA255(192, 192, 192, 255)
|
||||
diskcard.SetRGBA255(57, 57, 57, 255)
|
||||
if isday {
|
||||
diskcard.SetRGBA255(192, 192, 192, 255)
|
||||
}
|
||||
diskcard.DrawRoundedRectangle(40, 40, float64(diskcard.W())-40-100, 50, 12)
|
||||
diskcard.ClipPreserve()
|
||||
diskcard.Fill()
|
||||
|
||||
colors := darkcolor
|
||||
if isday {
|
||||
colors = lightcolor
|
||||
}
|
||||
|
||||
switch {
|
||||
case diskstate[0].precent > 90:
|
||||
diskcard.SetRGBA255(255, 70, 0, 255)
|
||||
diskcard.SetColor(slice2color(colors[0]))
|
||||
case diskstate[0].precent > 70:
|
||||
diskcard.SetRGBA255(255, 165, 0, 255)
|
||||
diskcard.SetColor(slice2color(colors[1]))
|
||||
default:
|
||||
diskcard.SetRGBA255(145, 240, 145, 255)
|
||||
diskcard.SetColor(slice2color(colors[2]))
|
||||
}
|
||||
|
||||
diskcard.DrawRoundedRectangle(40, 40, (float64(diskcard.W())-40-100)*diskstate[0].precent*0.01, 50, 12)
|
||||
diskcard.Fill()
|
||||
diskcard.ResetClip()
|
||||
|
||||
diskcard.SetRGBA255(30, 30, 30, 255)
|
||||
diskcard.SetColor(fontcolorswitch())
|
||||
|
||||
fw, _ := diskcard.MeasureString(diskstate[0].name)
|
||||
fw1, _ := diskcard.MeasureString(diskstate[0].text[0])
|
||||
@@ -361,23 +421,32 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
for i, v := range diskstate {
|
||||
offset := float64(i)*(50+20) - 20
|
||||
|
||||
diskcard.SetRGBA255(192, 192, 192, 255)
|
||||
diskcard.SetRGBA255(57, 57, 57, 255)
|
||||
if isday {
|
||||
diskcard.SetRGBA255(192, 192, 192, 255)
|
||||
}
|
||||
|
||||
diskcard.DrawRoundedRectangle(40, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+offset, float64(diskcard.W())-40-100, 50, 12)
|
||||
diskcard.Fill()
|
||||
|
||||
colors := darkcolor
|
||||
if isday {
|
||||
colors = lightcolor
|
||||
}
|
||||
|
||||
switch {
|
||||
case v.precent > 90:
|
||||
diskcard.SetRGBA255(255, 70, 0, 255)
|
||||
diskcard.SetColor(slice2color(colors[0]))
|
||||
case v.precent > 70:
|
||||
diskcard.SetRGBA255(255, 165, 0, 255)
|
||||
diskcard.SetColor(slice2color(colors[1]))
|
||||
default:
|
||||
diskcard.SetRGBA255(145, 240, 145, 255)
|
||||
diskcard.SetColor(slice2color(colors[2]))
|
||||
}
|
||||
|
||||
diskcard.DrawRoundedRectangle(40, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+offset, (float64(diskcard.W())-40-100)*v.precent*0.01, 50, 12)
|
||||
diskcard.Fill()
|
||||
|
||||
diskcard.SetRGBA255(30, 30, 30, 255)
|
||||
diskcard.SetColor(fontcolorswitch())
|
||||
|
||||
fw, _ := diskcard.MeasureString(v.name)
|
||||
fw1, _ := diskcard.MeasureString(v.text[0])
|
||||
@@ -392,14 +461,14 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
moreinfocard := gg.NewContext(cardw, moreinfocardh)
|
||||
|
||||
moreinfocard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70-titlecardh-40-basiccardh-40-diskcardh-40)
|
||||
bwg.Wait()
|
||||
moreinfocard.DrawImage(blurback, -70, -70-titlecardh-40-basiccardh-40-diskcardh-40)
|
||||
|
||||
moreinfocard.DrawRoundedRectangle(1, 1, float64(moreinfocard.W()-1*2), float64(moreinfocard.H()-1*2), 16)
|
||||
moreinfocard.SetLineWidth(3)
|
||||
moreinfocard.SetRGBA255(255, 255, 255, 100)
|
||||
moreinfocard.SetColor(colorswitch(100))
|
||||
moreinfocard.StrokePreserve()
|
||||
moreinfocard.SetRGBA255(255, 255, 255, 140)
|
||||
moreinfocard.SetColor(colorswitch(140))
|
||||
moreinfocard.Fill()
|
||||
|
||||
err = moreinfocard.ParseFontFace(fontbyte, 32)
|
||||
@@ -411,7 +480,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
for i, v := range moreinfo {
|
||||
offset := float64(i)*(20+moreinfocard.FontHeight()) - 20
|
||||
|
||||
moreinfocard.SetRGBA255(30, 30, 30, 255)
|
||||
moreinfocard.SetColor(fontcolorswitch())
|
||||
|
||||
fw, _ := moreinfocard.MeasureString(v.name)
|
||||
fw1, _ := moreinfocard.MeasureString(v.text[0])
|
||||
@@ -430,7 +499,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
shadow.Stroke()
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40), float64(cardw), float64(basiccardh), 16)
|
||||
shadow.Stroke()
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40), float64(cardw), float64(basiccardh), 16)
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40), float64(cardw), float64(diskcardh), 16)
|
||||
shadow.Stroke()
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40+diskcardh+40), float64(cardw), float64(moreinfocardh), 16)
|
||||
shadow.Stroke()
|
||||
@@ -489,6 +558,8 @@ func botstatus() (string, error) {
|
||||
t.WriteString(runtime.Version())
|
||||
t.WriteString(" | ")
|
||||
t.WriteString(cases.Title(language.English).String(hostinfo.OS))
|
||||
t.WriteString(" ")
|
||||
t.WriteString(runtime.GOARCH)
|
||||
return t.String(), nil
|
||||
}
|
||||
|
||||
@@ -499,7 +570,7 @@ type status struct {
|
||||
}
|
||||
|
||||
func basicstate() (stateinfo [3]*status, err error) {
|
||||
percent, err := cpu.Percent(time.Second, false)
|
||||
percent, err := cpu.Percent(time.Second, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -507,7 +578,15 @@ func basicstate() (stateinfo [3]*status, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cores := strconv.Itoa(int(cpuinfo[0].Cores)) + " Core"
|
||||
cpucore, err := cpu.Counts(false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cputhread, err := cpu.Counts(true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cores := strconv.Itoa(cpucore) + "C" + strconv.Itoa(cputhread) + "T"
|
||||
times := "最大 " + strconv.FormatFloat(cpuinfo[0].Mhz/1000, 'f', 1, 64) + "Ghz"
|
||||
|
||||
stateinfo[0] = &status{
|
||||
@@ -587,6 +666,10 @@ 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))
|
||||
|
||||
hostinfo, err := host.Info()
|
||||
if err != nil {
|
||||
return
|
||||
@@ -595,12 +678,32 @@ func moreinfo(m *ctrl.Control[*zero.Ctx]) (stateinfo []*status, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
count := len(m.Manager.M)
|
||||
stateinfo = []*status{
|
||||
{name: "OS", text: []string{hostinfo.Platform}},
|
||||
{name: "CPU", text: []string{cpuinfo[0].ModelName}},
|
||||
{name: "CPU", text: []string{strings.TrimSpace(cpuinfo[0].ModelName)}},
|
||||
{name: "Version", text: []string{hostinfo.PlatformVersion}},
|
||||
{name: "Plugin", text: []string{"共 " + strconv.Itoa(count) + " 个"}},
|
||||
{name: "Memory", text: []string{"已用 " + fmtmem}},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func colorswitch(a uint8) color.Color {
|
||||
if isday {
|
||||
return color.NRGBA{255, 255, 255, a}
|
||||
}
|
||||
return color.NRGBA{0, 0, 0, a}
|
||||
}
|
||||
|
||||
func fontcolorswitch() color.Color {
|
||||
if isday {
|
||||
return color.NRGBA{30, 30, 30, 255}
|
||||
}
|
||||
return color.NRGBA{235, 235, 235, 255}
|
||||
}
|
||||
|
||||
func slice2color(c [4]uint8) color.Color {
|
||||
return color.NRGBA{c[0], c[1], c[2], c[3]}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ func (r *result) String() string {
|
||||
}
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("aipaint", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "ai绘图",
|
||||
Help: "- [ ai绘图 | 生成色图 | 生成涩图 | ai画图 ] xxx\n" +
|
||||
|
||||
@@ -17,7 +17,7 @@ const (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
control.Register("aiwife", &ctrl.Options[*zero.Ctx]{
|
||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "ai随机生成老婆",
|
||||
Help: "- waifu | 随机waifu",
|
||||
|
||||
@@ -16,7 +16,7 @@ const (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("alipayvoice", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "支付宝到账语音",
|
||||
Help: "- 支付宝到账 1",
|
||||
|
||||
@@ -38,7 +38,7 @@ func onDel(uid int64, _ struct{}) {
|
||||
}
|
||||
|
||||
func init() {
|
||||
engine := control.Register("antiabuse", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "违禁词检测",
|
||||
Help: "- /[添加|删除|查看]违禁词",
|
||||
@@ -70,7 +70,7 @@ func init() {
|
||||
if err := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).Manager.DoBlock(uid); err == nil {
|
||||
t := time.Now().Unix()
|
||||
cache.Set(uid, struct{}{})
|
||||
ctx.SetGroupBan(gid, uid, int64(bandur.Minutes()))
|
||||
ctx.SetThisGroupBan(uid, int64(bandur.Minutes()))
|
||||
ctx.SendChain(message.Text("检测到违禁词, 已封禁/屏蔽", bandur))
|
||||
db.Lock()
|
||||
defer db.Unlock()
|
||||
|
||||
@@ -40,7 +40,7 @@ func randText(text ...string) message.MessageSegment {
|
||||
}
|
||||
|
||||
// isAtriSleeping 凌晨0点到6点,ATRI 在睡觉,不回应任何请求
|
||||
func isAtriSleeping(ctx *zero.Ctx) bool {
|
||||
func isAtriSleeping(*zero.Ctx) bool {
|
||||
if now := time.Now().Hour(); now >= 1 && now < 6 {
|
||||
return false
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func isAtriSleeping(ctx *zero.Ctx) bool {
|
||||
}
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("atri", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "atri人格文本回复",
|
||||
Help: "本插件基于 ATRI ,为 Golang 移植版\n" +
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("autowithdraw", &ctrl.Options[*zero.Ctx]{
|
||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "触发者撤回时也自动撤回",
|
||||
Help: "- 撤回一条消息\n",
|
||||
|
||||
@@ -1,27 +1,61 @@
|
||||
// Package baidu 百度一下
|
||||
// Package baidu 百度百科
|
||||
package baidu
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("baidu", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "不会百度吗",
|
||||
Help: "- 百度下[xxx]",
|
||||
}).OnPrefix("百度下").SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
txt := ctx.State["args"].(string)
|
||||
if txt != "" {
|
||||
ctx.SendChain(message.Text("https://buhuibaidu.me/?s=" + url.QueryEscape(txt)))
|
||||
}
|
||||
})
|
||||
const (
|
||||
duURL = "https://api.a20safe.com/api.php?api=21&key=%s&text=%s" // api地址
|
||||
wikiURL = "https://api.a20safe.com/api.php?api=23&key=%s&text=%s"
|
||||
key = "7d06a110e9e20a684e02934549db1d3d"
|
||||
)
|
||||
|
||||
type result struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data []struct {
|
||||
Content string `json:"content"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func init() { // 主函数
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "百科\n" +
|
||||
"- 百度/百科/维基/wiki[关键字]",
|
||||
})
|
||||
en.OnRegex(`^(百度|维基|百科|wiki)\s*(.+)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
var es []byte
|
||||
var err error
|
||||
switch ctx.State["regex_matched"].([]string)[1] {
|
||||
case "百度", "百科":
|
||||
es, err = web.GetData(fmt.Sprintf(duURL, key, url.QueryEscape(ctx.State["regex_matched"].([]string)[2]))) // 将网站返回结果赋值
|
||||
case "wiki", "维基":
|
||||
es, err = web.GetData(fmt.Sprintf(wikiURL, key, url.QueryEscape(ctx.State["regex_matched"].([]string)[2]))) // 将网站返回结果赋值
|
||||
}
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("出现错误捏:", err))
|
||||
return
|
||||
}
|
||||
var r result // r数组
|
||||
err = json.Unmarshal(es, &r) // 填api返回结果,struct地址
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("出现错误捏:", err))
|
||||
return
|
||||
}
|
||||
if r.Code == 0 && len(r.Data) > 0 {
|
||||
ctx.SendChain(message.Text(r.Data[0].Content)) // 输出提取后的结果
|
||||
} else {
|
||||
ctx.SendChain(message.Text("API访问错误"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("baiduaudit", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "百度内容审核",
|
||||
Help: "##该功能来自百度内容审核, 需购买相关服务, 并创建app##\n" +
|
||||
|
||||
@@ -68,7 +68,7 @@ func (bdres *baiduRes) audit(ctx *zero.Ctx, configpath string) {
|
||||
bantime = group.BANTime * 60
|
||||
}
|
||||
// 执行禁言
|
||||
ctx.SetGroupBan(ctx.Event.GroupID, ctx.Event.UserID, bantime)
|
||||
ctx.SetThisGroupBan(ctx.Event.UserID, bantime)
|
||||
}
|
||||
// 查看是否开启撤回提示
|
||||
if group.DMRemind {
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("base16384", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "base16384加解密",
|
||||
Help: "- 加密xxx\n- 解密xxx\n- 用yyy加密xxx\n- 用yyy解密xxx",
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("base64gua", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "六十四卦加解密",
|
||||
Help: "- 六十四卦加密xxx\n- 六十四卦解密xxx\n- 六十四卦用yyy加密xxx\n- 六十四卦用yyy解密xxx",
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("baseamasiro", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "天城文加解密",
|
||||
Help: "- 天城文加密xxx\n- 天城文解密xxx\n- 天城文用yyy加密xxx\n- 天城文用yyy解密xxx",
|
||||
|
||||
@@ -48,7 +48,7 @@ var (
|
||||
|
||||
// 查成分的
|
||||
func init() {
|
||||
engine := control.Register("bilibili", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "b站查成分查弹幕",
|
||||
Help: "- >vup info [xxx]\n" +
|
||||
@@ -56,7 +56,7 @@ func init() {
|
||||
"- 查成分 [xxx]\n" +
|
||||
"- 查弹幕 [xxx]\n" +
|
||||
"- 设置b站cookie b_ut=7;buvid3=0;i-wanna-go-back=-1;innersign=0;\n" +
|
||||
"- 更新vup" +
|
||||
"- 更新vup\n" +
|
||||
"Tips: (412就是拦截的意思,建议私聊把cookie设全)\n",
|
||||
PublicDataFolder: "Bilibili",
|
||||
})
|
||||
@@ -337,12 +337,12 @@ func init() {
|
||||
faceH := float64(510)
|
||||
|
||||
totalDanmuku := 0
|
||||
for i := 0; i < len(danmaku.Data.Data); i++ {
|
||||
totalDanmuku += len(danmaku.Data.Data[i].Danmakus) + 1
|
||||
for i := 0; i < len(danmaku.Data.Data.Records); i++ {
|
||||
totalDanmuku += len(danmaku.Data.Data.Records[i].Danmakus) + 1
|
||||
}
|
||||
cw := 3000
|
||||
mcw := float64(2000)
|
||||
ch := 550 + len(danmaku.Data.Data)*int(faceH) + totalDanmuku*int(danmuH)
|
||||
ch := 550 + len(danmaku.Data.Data.Records)*int(faceH) + totalDanmuku*int(danmuH)
|
||||
canvas = gg.NewContext(cw, ch)
|
||||
canvas.SetColor(color.White)
|
||||
canvas.Clear()
|
||||
@@ -372,9 +372,9 @@ func init() {
|
||||
canvas.DrawString("网页链接: "+fmt.Sprintf(bz.DanmakuURL, u.Mid), startWidth, 422.5)
|
||||
var channelStart float64
|
||||
channelStart = float64(550)
|
||||
for i := 0; i < len(danmaku.Data.Data); i++ {
|
||||
item := danmaku.Data.Data[i]
|
||||
facePath = cachePath + strconv.Itoa(int(item.Channel.UID)) + "vupFace" + path.Ext(item.Channel.FaceURL)
|
||||
for i := 0; i < len(danmaku.Data.Data.Records); i++ {
|
||||
item := danmaku.Data.Data.Records[i]
|
||||
facePath = cachePath + strconv.Itoa(item.Channel.UID) + "vupFace" + path.Ext(item.Channel.FaceURL)
|
||||
if path.Ext(item.Channel.FaceURL) != ".webp" {
|
||||
err = initFacePic(facePath, item.Channel.FaceURL)
|
||||
if err != nil {
|
||||
@@ -393,7 +393,7 @@ func init() {
|
||||
}
|
||||
canvas.SetRGB255(24, 144, 255)
|
||||
canvas.DrawString("标题: "+item.Live.Title, startWidth, channelStart+fontH)
|
||||
canvas.DrawString("主播: "+item.Channel.Name, startWidth, channelStart+fontH*2)
|
||||
canvas.DrawString("主播: "+item.Channel.UName, startWidth, channelStart+fontH*2)
|
||||
canvas.SetColor(color.Black)
|
||||
canvas.DrawString("开始时间: "+time.UnixMilli(item.Live.StartDate).Format("2006-01-02 15:04:05"), startWidth, channelStart+fontH*3)
|
||||
if item.Live.IsFinish {
|
||||
@@ -411,8 +411,8 @@ func init() {
|
||||
|
||||
canvas.DrawString("直播时长: "+strconv.FormatFloat(float64(time.Now().UnixMilli()-item.Live.StartDate)/3600000.0, 'f', 1, 64)+"小时", startWidth, channelStart+fontH*5)
|
||||
}
|
||||
canvas.DrawString("弹幕数量: "+strconv.Itoa(int(item.Live.DanmakusCount)), startWidth, channelStart+fontH*6)
|
||||
canvas.DrawString("观看次数: "+strconv.Itoa(int(item.Live.WatchCount)), startWidth, channelStart+fontH*7)
|
||||
canvas.DrawString("弹幕数量: "+strconv.Itoa(item.Live.DanmakusCount), startWidth, channelStart+fontH*6)
|
||||
canvas.DrawString("观看次数: "+strconv.Itoa(item.Live.WatchCount), startWidth, channelStart+fontH*7)
|
||||
|
||||
t := "收益:"
|
||||
l, _ := canvas.MeasureString(t)
|
||||
@@ -434,7 +434,7 @@ func init() {
|
||||
canvas.DrawString(t, moveW, danmuNow)
|
||||
moveW += l + dz
|
||||
|
||||
t = danItem.Name
|
||||
t = danItem.UName
|
||||
l, _ = canvas.MeasureString(t)
|
||||
canvas.SetRGB255(24, 144, 255)
|
||||
canvas.DrawString(t, moveW, danmuNow)
|
||||
|
||||
@@ -76,11 +76,17 @@ func handleVideo(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
summaryMsg, err := getVideoSummary(card)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
msg = append(msg, summaryMsg...)
|
||||
ctx.SendChain(msg...)
|
||||
}
|
||||
|
||||
func handleDynamic(ctx *zero.Ctx) {
|
||||
msg, err := dynamicDetail(ctx.State["regex_matched"].([]string)[2])
|
||||
msg, err := dynamicDetail(cfg, ctx.State["regex_matched"].([]string)[2])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
|
||||
@@ -75,7 +75,7 @@ func updateVup() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gjson.Get(binary.BytesToString(data), "@this").ForEach(func(key, value gjson.Result) bool {
|
||||
gjson.Get(binary.BytesToString(data), "@this").ForEach(func(_, value gjson.Result) bool {
|
||||
mid := value.Get("mid").Int()
|
||||
uname := value.Get("uname").String()
|
||||
roomid := value.Get("roomid").Int()
|
||||
|
||||
@@ -9,23 +9,22 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
bz "github.com/FloatTech/AnimeAPI/bilibili"
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
|
||||
referer = "https://www.bilibili.com/"
|
||||
infoURL = "https://api.bilibili.com/x/space/acc/info?mid=%v"
|
||||
referer = "https://space.bilibili.com/%v"
|
||||
infoURL = "https://api.bilibili.com/x/space/wbi/acc/info?mid=%v"
|
||||
)
|
||||
|
||||
// bdb bilibili推送数据库
|
||||
@@ -46,8 +45,10 @@ func init() {
|
||||
"- 取消b站动态订阅[uid|name]\n" +
|
||||
"- 取消b站直播订阅[uid|name]\n" +
|
||||
"- b站推送列表\n" +
|
||||
"Tips: 需要配合job一起使用, 全局只需要设置一个, 无视响应状态推送, 下为例子\n" +
|
||||
"记录在\"@every 5m\"触发的指令)\n" +
|
||||
"- [开启|关闭]艾特全体\n" +
|
||||
"Tips: 需要先在 bilibili 插件中设置cookie\n" +
|
||||
"需要配合 job 插件一起使用, 全局只需要设置一个, 无视响应状态推送, 下为例子\n" +
|
||||
"记录在\"@every 5m\"触发的指令\n" +
|
||||
"拉取b站推送",
|
||||
PrivateDataFolder: "bilibilipush",
|
||||
})
|
||||
@@ -56,11 +57,28 @@ func init() {
|
||||
dbpath := en.DataFolder()
|
||||
dbfile := dbpath + "push.db"
|
||||
bdb = initializePush(dbfile)
|
||||
en.OnFullMatch(`开启艾特全体`, zero.UserOrGrpAdmin, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
if err := changeAtAll(gid, 1); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("已开启艾特全体Oo"))
|
||||
})
|
||||
|
||||
en.OnFullMatch(`关闭艾特全体`, zero.UserOrGrpAdmin, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
if err := changeAtAll(gid, 0); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("已关闭艾特全体Oo"))
|
||||
})
|
||||
|
||||
en.OnRegex(`^添加[B|b]站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||
name, err := getName(buid)
|
||||
if err != nil {
|
||||
name, err := getName(buid, cfg)
|
||||
if err != nil || name == "" {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
@@ -74,9 +92,10 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Text("已添加" + name + "的订阅"))
|
||||
})
|
||||
|
||||
en.OnRegex(`^取消[B|b]站订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||
name, err := getName(buid)
|
||||
name, err := getName(buid, cfg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
@@ -93,7 +112,7 @@ func init() {
|
||||
})
|
||||
en.OnRegex(`^取消[B|b]站动态订阅\s?(.{1,25})$`, zero.UserOrGrpAdmin, getPara).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
buid, _ := strconv.ParseInt(ctx.State["uid"].(string), 10, 64)
|
||||
name, err := getName(buid)
|
||||
name, err := getName(buid, cfg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
@@ -114,7 +133,7 @@ func init() {
|
||||
if gid == 0 {
|
||||
gid = -ctx.Event.UserID
|
||||
}
|
||||
name, err := getName(buid)
|
||||
name, err := getName(buid, cfg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
@@ -125,6 +144,7 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Text("已取消" + name + "的直播订阅"))
|
||||
})
|
||||
|
||||
en.OnRegex(`^[B|b]站推送列表$`, zero.UserOrGrpAdmin).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
gid := ctx.Event.GroupID
|
||||
if gid == 0 {
|
||||
@@ -171,31 +191,37 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
func changeAtAll(gid int64, b int) (err error) {
|
||||
bpMap := map[string]any{
|
||||
"group_id": gid,
|
||||
"at_all": b,
|
||||
}
|
||||
return bdb.updateAtAll(bpMap)
|
||||
}
|
||||
|
||||
// 取得uid的名字
|
||||
func getName(buid int64) (name string, err error) {
|
||||
func getName(buid int64, cookiecfg *bz.CookieConfig) (name string, err error) {
|
||||
var ok bool
|
||||
if name, ok = upMap[buid]; !ok {
|
||||
var data []byte
|
||||
data, err = web.RequestDataWithHeaders(web.NewDefaultClient(), fmt.Sprintf(infoURL, buid), "GET", func(r *http.Request) error {
|
||||
r.Header.Set("refer", referer)
|
||||
r.Header.Set("user-agent", ua)
|
||||
cookie := ""
|
||||
if cfg != nil {
|
||||
cookie, err = cfg.Load()
|
||||
data, err := web.RequestDataWithHeaders(web.NewDefaultClient(), bz.SignURL(fmt.Sprintf(infoURL, buid)), "GET", func(r *http.Request) error {
|
||||
if cookiecfg != nil {
|
||||
cookie := ""
|
||||
cookie, err = cookiecfg.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Header.Add("Cookie", cookie)
|
||||
}
|
||||
r.Header.Set("cookie", cookie)
|
||||
r.Header.Set("User-Agent", ua)
|
||||
return nil
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return
|
||||
return "", err
|
||||
}
|
||||
status := int(gjson.Get(binary.BytesToString(data), "code").Int())
|
||||
if status != 0 {
|
||||
err = errors.New(gjson.Get(binary.BytesToString(data), "message").String())
|
||||
return
|
||||
return "", err
|
||||
}
|
||||
name = gjson.Get(binary.BytesToString(data), "data.name").String()
|
||||
bdb.insertBilibiliUp(buid, name)
|
||||
@@ -244,8 +270,19 @@ func unsubscribeLive(buid, groupid int64) (err error) {
|
||||
return bdb.insertOrUpdateLiveAndDynamic(bpMap)
|
||||
}
|
||||
|
||||
func getUserDynamicCard(buid int64) (cardList []gjson.Result, err error) {
|
||||
data, err := web.RequestDataWith(web.NewDefaultClient(), fmt.Sprintf(bz.SpaceHistoryURL, buid, 0), "GET", referer, ua, nil)
|
||||
func getUserDynamicCard(buid int64, cookiecfg *bz.CookieConfig) (cardList []gjson.Result, err error) {
|
||||
data, err := web.RequestDataWithHeaders(web.NewDefaultClient(), fmt.Sprintf(bz.SpaceHistoryURL, buid, 0), "GET", func(req *http.Request) error {
|
||||
if cookiecfg != nil {
|
||||
cookie := ""
|
||||
cookie, err = cookiecfg.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Add("Cookie", cookie)
|
||||
}
|
||||
req.Header.Add("User-Agent", ua)
|
||||
return nil
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -271,12 +308,12 @@ func sendDynamic(ctx *zero.Ctx) error {
|
||||
uids := bdb.getAllBuidByDynamic()
|
||||
for _, buid := range uids {
|
||||
time.Sleep(2 * time.Second)
|
||||
cardList, err := getUserDynamicCard(buid)
|
||||
cardList, err := getUserDynamicCard(buid, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(cardList) == 0 {
|
||||
return errors.Errorf("%v的历史动态数为0", buid)
|
||||
return nil
|
||||
}
|
||||
t, ok := lastTime[buid]
|
||||
// 第一次先记录时间,啥也不做
|
||||
@@ -361,6 +398,9 @@ func sendLive(ctx *zero.Ctx) error {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
switch {
|
||||
case gid > 0:
|
||||
if res := bdb.getAtAll(gid); res == 1 {
|
||||
msg = append([]message.MessageSegment{message.AtAll()}, msg...)
|
||||
}
|
||||
ctx.SendGroupMessage(gid, msg)
|
||||
case gid < 0:
|
||||
ctx.SendPrivateMessage(-gid, msg)
|
||||
|
||||
@@ -33,6 +33,15 @@ func (bilibiliup) TableName() string {
|
||||
return "bilibili_up"
|
||||
}
|
||||
|
||||
type bilibiliAt struct {
|
||||
GroupID int64 `gorm:"column:group_id;primary_key" json:"group_id"`
|
||||
AtAll int64 `gorm:"column:at_all;default:0" json:"at_all"`
|
||||
}
|
||||
|
||||
func (bilibiliAt) TableName() string {
|
||||
return "bilibili_at"
|
||||
}
|
||||
|
||||
// initializePush 初始化bilibilipushdb数据库
|
||||
func initializePush(dbpath string) *bilibilipushdb {
|
||||
var err error
|
||||
@@ -48,7 +57,7 @@ func initializePush(dbpath string) *bilibilipushdb {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
gdb.AutoMigrate(&bilibilipush{}).AutoMigrate(&bilibiliup{})
|
||||
gdb.AutoMigrate(&bilibilipush{}).AutoMigrate(&bilibiliup{}).AutoMigrate(&bilibiliAt{})
|
||||
return (*bilibilipushdb)(gdb)
|
||||
}
|
||||
|
||||
@@ -130,6 +139,35 @@ func (bdb *bilibilipushdb) getAllPushByGroup(groupID int64) (bpl []bilibilipush)
|
||||
return
|
||||
}
|
||||
|
||||
func (bdb *bilibilipushdb) getAtAll(groupID int64) (res int64) {
|
||||
db := (*gorm.DB)(bdb)
|
||||
var bpl bilibiliAt
|
||||
db.Model(&bilibilipush{}).Find(&bpl, "group_id = ?", groupID)
|
||||
res = bpl.AtAll
|
||||
return
|
||||
}
|
||||
|
||||
func (bdb *bilibilipushdb) updateAtAll(bpMap map[string]any) (err error) {
|
||||
db := (*gorm.DB)(bdb)
|
||||
bp := bilibiliAt{}
|
||||
data, err := json.Marshal(&bpMap)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &bp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = db.Model(&bilibiliAt{}).First(&bp, "group_id = ?", bp.GroupID).Error; err != nil {
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
err = db.Model(&bilibiliAt{}).Create(&bp).Error
|
||||
}
|
||||
} else {
|
||||
err = db.Model(&bilibiliAt{}).Where("group_id = ?", bp.GroupID).Update(bpMap).Error
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (bdb *bilibilipushdb) insertBilibiliUp(buid int64, name string) {
|
||||
db := (*gorm.DB)(bdb)
|
||||
bu := bilibiliup{
|
||||
|
||||
@@ -2,10 +2,12 @@ package bilibili
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
bz "github.com/FloatTech/AnimeAPI/bilibili"
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
@@ -253,8 +255,8 @@ func card2msg(dynamicCard *bz.DynamicCard, card *bz.Card, cType int) (msg []mess
|
||||
}
|
||||
|
||||
// dynamicDetail 用动态id查动态信息
|
||||
func dynamicDetail(dynamicIDStr string) (msg []message.MessageSegment, err error) {
|
||||
dyc, err := bz.GetDynamicDetail(dynamicIDStr)
|
||||
func dynamicDetail(cookiecfg *bz.CookieConfig, dynamicIDStr string) (msg []message.MessageSegment, err error) {
|
||||
dyc, err := bz.GetDynamicDetail(cookiecfg, dynamicIDStr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -321,6 +323,30 @@ func videoCard2msg(card bz.Card) (msg []message.MessageSegment, err error) {
|
||||
msg = append(msg, message.Image(card.Pic))
|
||||
msg = append(msg, message.Text("\n点赞: ", bz.HumanNum(card.Stat.Like), " 投币: ", bz.HumanNum(card.Stat.Coin), "\n",
|
||||
"收藏: ", bz.HumanNum(card.Stat.Favorite), " 分享: ", bz.HumanNum(card.Stat.Share), "\n",
|
||||
bz.VURL, card.BvID))
|
||||
bz.VURL, card.BvID, "\n\n"))
|
||||
return
|
||||
}
|
||||
|
||||
// getVideoSummary AI视频总结
|
||||
func getVideoSummary(card bz.Card) (msg []message.MessageSegment, err error) {
|
||||
var (
|
||||
data []byte
|
||||
videoSummary bz.VideoSummary
|
||||
)
|
||||
data, err = web.GetData(bz.SignURL(fmt.Sprintf(bz.VideoSummaryURL, card.BvID, card.CID)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &videoSummary)
|
||||
msg = make([]message.MessageSegment, 0, 16)
|
||||
msg = append(msg, message.Text("已为你生成视频总结\n\n"))
|
||||
msg = append(msg, message.Text(videoSummary.Data.ModelResult.Summary, "\n\n"))
|
||||
for _, v := range videoSummary.Data.ModelResult.Outline {
|
||||
msg = append(msg, message.Text("● ", v.Title, "\n"))
|
||||
for _, p := range v.PartOutline {
|
||||
msg = append(msg, message.Text(fmt.Sprintf("%d:%d %s\n", p.Timestamp/60, p.Timestamp%60, p.Content)))
|
||||
}
|
||||
msg = append(msg, message.Text("\n"))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -15,35 +15,6 @@ func TestArticleInfo(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestDynamicDetail(t *testing.T) {
|
||||
t.Log("cType = 1")
|
||||
t.Log(dynamicDetail("642279068898689029"))
|
||||
|
||||
t.Log("cType = 2")
|
||||
t.Log(dynamicDetail("642470680290394121"))
|
||||
|
||||
t.Log("cType = 2048")
|
||||
t.Log(dynamicDetail("642277677329285174"))
|
||||
|
||||
t.Log("cType = 4")
|
||||
t.Log(dynamicDetail("642154347357011968"))
|
||||
|
||||
t.Log("cType = 8")
|
||||
t.Log(dynamicDetail("675892999274627104"))
|
||||
|
||||
t.Log("cType = 4308")
|
||||
t.Log(dynamicDetail("668598718656675844"))
|
||||
|
||||
t.Log("cType = 64")
|
||||
t.Log(dynamicDetail("675966082178088963"))
|
||||
|
||||
t.Log("cType = 256")
|
||||
t.Log(dynamicDetail("599253048535707632"))
|
||||
|
||||
t.Log("cType = 4,投票类型")
|
||||
t.Log(dynamicDetail("677231070435868704"))
|
||||
}
|
||||
|
||||
func TestMemberCard(t *testing.T) {
|
||||
card, err := bz.GetMemberCard(2)
|
||||
if err != nil {
|
||||
@@ -75,6 +46,14 @@ func TestVideoInfo(t *testing.T) {
|
||||
t.Log(videoCard2msg(card))
|
||||
}
|
||||
|
||||
func TestGetVideoSummary(t *testing.T) {
|
||||
card, err := bz.GetVideoInfo("BV1mF411j7iU")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(getVideoSummary(card))
|
||||
}
|
||||
|
||||
func TestLiveRoomInfo(t *testing.T) {
|
||||
card, err := bz.GetLiveRoomInfo("83171")
|
||||
if err != nil {
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("bookreview", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "哀伤雪刃推书书评",
|
||||
Help: "- 书评[xxx]\n- 随机书评",
|
||||
@@ -27,7 +27,7 @@ func init() {
|
||||
db.DBPath = engine.DataFolder() + "bookreview.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = engine.GetLazyData("bookreview.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
err := db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
@@ -16,7 +16,7 @@ const throttle = 3 // 不可超过 9
|
||||
var sm syncx.Map[int64, string]
|
||||
|
||||
func init() {
|
||||
engine := control.Register("breakrepeat", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "打断复读",
|
||||
Help: "- 打断" + strconv.Itoa(throttle) + "次以上复读\n",
|
||||
|
||||
@@ -30,7 +30,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("cangtoushi", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "藏头诗, 藏尾诗",
|
||||
Help: "- 藏头诗[xxx]\n- 藏尾诗[xxx]",
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
var (
|
||||
poke = rate.NewManager[int64](time.Minute*5, 8) // 戳一戳
|
||||
engine = control.Register("chat", &ctrl.Options[*zero.Ctx]{
|
||||
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "基础反应, 群空调",
|
||||
Help: "chat\n- [BOT名字]\n- [戳一戳BOT]\n- 空调开\n- 空调关\n- 群温度\n- 设置温度[正整数]",
|
||||
|
||||
183
plugin/chess/chess.go
Normal file
183
plugin/chess/chess.go
Normal file
@@ -0,0 +1,183 @@
|
||||
// Package chess 国际象棋
|
||||
package chess
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const helpString = `- 参与/创建一盘游戏:「下棋」(chess)
|
||||
- 参与/创建一盘盲棋:「盲棋」(blind)
|
||||
- 投降认输:「认输」 (resign)
|
||||
- 请求、接受和棋:「和棋」 (draw)
|
||||
- 走棋:!Nxf3 中英文感叹号均可,格式请参考“代数记谱法”(Algebraic notation)
|
||||
- 中断对局:「中断」 (abort)(仅群主/管理员有效)
|
||||
- 查看等级分排行榜:「排行榜」(ranking)
|
||||
- 查看自己的等级分:「等级分」(rate)
|
||||
- 清空等级分:「清空等级分 QQ号」(.clean.rate) (仅超管有效)`
|
||||
|
||||
var (
|
||||
limit = ctxext.NewLimiterManager(time.Microsecond*2500, 1)
|
||||
tempFileDir string
|
||||
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "国际象棋",
|
||||
Help: helpString,
|
||||
PrivateDataFolder: "chess",
|
||||
}).ApplySingle(single.New(
|
||||
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||||
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("有操作正在执行, 请稍后再试..."),
|
||||
),
|
||||
)
|
||||
}),
|
||||
))
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 初始化临时文件夹
|
||||
tempFileDir = path.Join(engine.DataFolder(), "temp")
|
||||
err := os.MkdirAll(tempFileDir, 0750)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// 初始化数据库
|
||||
dbFilePath := engine.DataFolder() + "chess.db"
|
||||
initDatabase(dbFilePath)
|
||||
// 注册指令
|
||||
engine.OnFullMatchGroup([]string{"下棋", "chess"}, zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.Sender == nil {
|
||||
return
|
||||
}
|
||||
userUin := ctx.Event.UserID
|
||||
userName := ctx.Event.Sender.NickName
|
||||
groupCode := ctx.Event.GroupID
|
||||
replyMessage, err := game(groupCode, userUin, userName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(replyMessage)
|
||||
})
|
||||
|
||||
engine.OnFullMatchGroup([]string{"认输", "resign"}, zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
userUin := ctx.Event.UserID
|
||||
groupCode := ctx.Event.GroupID
|
||||
replyMessage, err := resign(groupCode, userUin)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(replyMessage)
|
||||
})
|
||||
|
||||
engine.OnFullMatchGroup([]string{"和棋", "draw"}, zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
userUin := ctx.Event.UserID
|
||||
groupCode := ctx.Event.GroupID
|
||||
replyMessage, err := draw(groupCode, userUin)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(replyMessage)
|
||||
})
|
||||
|
||||
engine.OnFullMatchGroup([]string{"中断", "abort"}, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
groupCode := ctx.Event.GroupID
|
||||
replyMessage, err := abort(groupCode)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(replyMessage)
|
||||
})
|
||||
|
||||
engine.OnFullMatchGroup([]string{"盲棋", "blind"}, zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.Sender == nil {
|
||||
return
|
||||
}
|
||||
userUin := ctx.Event.UserID
|
||||
userName := ctx.Event.Sender.NickName
|
||||
groupCode := ctx.Event.GroupID
|
||||
replyMessage, err := blindfold(groupCode, userUin, userName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(replyMessage)
|
||||
})
|
||||
|
||||
engine.OnRegex("^[!|!]([0-8]|[R|N|B|Q|K|O|a-h|x]|[-|=|+])+$", zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
userUin := ctx.Event.UserID
|
||||
groupCode := ctx.Event.GroupID
|
||||
userMsgStr := ctx.State["regex_matched"].([]string)[0]
|
||||
moveStr := strings.TrimPrefix(strings.TrimPrefix(userMsgStr, "!"), "!")
|
||||
replyMessage, err := play(groupCode, userUin, moveStr)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(replyMessage)
|
||||
})
|
||||
|
||||
engine.OnFullMatchGroup([]string{"排行榜", "ranking"}).SetBlock(true).Limit(limit.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
replyMessage, err := getRanking()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(replyMessage)
|
||||
})
|
||||
|
||||
engine.OnFullMatchGroup([]string{"等级分", "rate"}).SetBlock(true).Limit(limit.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if ctx.Event.Sender == nil {
|
||||
return
|
||||
}
|
||||
userUin := ctx.Event.UserID
|
||||
userName := ctx.Event.Sender.NickName
|
||||
replyMessage, err := rate(userUin, userName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(replyMessage)
|
||||
})
|
||||
|
||||
engine.OnPrefixGroup([]string{"清空等级分", ".clean.rate"}, zero.SuperUserPermission).SetBlock(true).
|
||||
Limit(limit.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
args := ctx.State["args"].(string)
|
||||
playerUin, err := strconv.ParseInt(strings.TrimSpace(args), 10, 64)
|
||||
if err != nil || playerUin <= 0 {
|
||||
ctx.Send(fmt.Sprintf("解析失败「%s」不是正确的 QQ 号。", args))
|
||||
return
|
||||
}
|
||||
replyMessage, err := cleanUserRate(playerUin)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(replyMessage)
|
||||
})
|
||||
}
|
||||
637
plugin/chess/core.go
Normal file
637
plugin/chess/core.go
Normal file
@@ -0,0 +1,637 @@
|
||||
package chess
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
|
||||
"github.com/RomiChan/syncx"
|
||||
"github.com/jinzhu/gorm"
|
||||
resvg "github.com/kanrichan/resvg-go"
|
||||
"github.com/notnil/chess"
|
||||
cimage "github.com/notnil/chess/image"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const eloDefault = 500
|
||||
|
||||
var (
|
||||
chessRoomMap syncx.Map[int64, *chessRoom]
|
||||
errNotExist = errors.New("对局不存在, 发送「下棋」或「chess」可创建对局。")
|
||||
)
|
||||
|
||||
type chessRoom struct {
|
||||
chessGame *chess.Game
|
||||
whitePlayer int64
|
||||
whiteName string
|
||||
blackPlayer int64
|
||||
blackName string
|
||||
drawPlayer int64
|
||||
lastMoveTime int64
|
||||
isBlindfold bool
|
||||
whiteErr bool // 违例记录(盲棋用)
|
||||
blackErr bool
|
||||
}
|
||||
|
||||
// game 下棋
|
||||
func game(groupCode, senderUin int64, senderName string) (message.Message, error) {
|
||||
return createGame(false, groupCode, senderUin, senderName)
|
||||
}
|
||||
|
||||
// blindfold 盲棋
|
||||
func blindfold(groupCode, senderUin int64, senderName string) (message.Message, error) {
|
||||
return createGame(true, groupCode, senderUin, senderName)
|
||||
}
|
||||
|
||||
// abort 中断对局
|
||||
func abort(groupCode int64) (message.Message, error) {
|
||||
if room, ok := chessRoomMap.Load(groupCode); ok {
|
||||
return abortGame(*room, groupCode, "对局已被管理员中断, 游戏结束。")
|
||||
}
|
||||
return nil, errNotExist
|
||||
}
|
||||
|
||||
// draw 和棋
|
||||
func draw(groupCode, senderUin int64) (msg message.Message, err error) {
|
||||
msg = message.Message{message.At(senderUin)}
|
||||
// 检查对局是否存在
|
||||
room, ok := chessRoomMap.Load(groupCode)
|
||||
if !ok {
|
||||
return nil, errNotExist
|
||||
}
|
||||
// 检查消息发送者是否为对局中的玩家
|
||||
if senderUin != room.whitePlayer && senderUin != room.blackPlayer {
|
||||
return
|
||||
}
|
||||
// 处理和棋逻辑
|
||||
room.lastMoveTime = time.Now().Unix()
|
||||
if room.drawPlayer == 0 {
|
||||
room.drawPlayer = senderUin
|
||||
chessRoomMap.Store(groupCode, room)
|
||||
msg = append(msg, message.Text("请求和棋, 发送「和棋」或「draw」接受和棋。走棋视为拒绝和棋。"))
|
||||
return
|
||||
}
|
||||
if room.drawPlayer == senderUin {
|
||||
return
|
||||
}
|
||||
err = room.chessGame.Draw(chess.DrawOffer)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
chessString := getChessString(*room)
|
||||
eloString := ""
|
||||
if len(room.chessGame.Moves()) > 4 {
|
||||
// 若走子次数超过 4 认为是有效对局, 存入数据库
|
||||
dbService := newDBService()
|
||||
if err = dbService.createPGN(chessString, room.whitePlayer, room.blackPlayer, room.whiteName, room.blackName); err != nil {
|
||||
return
|
||||
}
|
||||
whiteScore, blackScore := 0.5, 0.5
|
||||
eloString, err = getELOString(*room, whiteScore, blackScore)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
msg = append(msg, message.Text("接受和棋, 游戏结束。\n", eloString, chessString))
|
||||
chessRoomMap.Delete(groupCode)
|
||||
return
|
||||
}
|
||||
|
||||
// resign 认输
|
||||
func resign(groupCode, senderUin int64) (msg message.Message, err error) {
|
||||
msg = message.Message{message.At(senderUin)}
|
||||
// 检查对局是否存在
|
||||
room, ok := chessRoomMap.Load(groupCode)
|
||||
if !ok {
|
||||
return nil, errNotExist
|
||||
}
|
||||
// 检查是否是当前游戏玩家
|
||||
if senderUin != room.whitePlayer && senderUin != room.blackPlayer {
|
||||
return
|
||||
}
|
||||
// 如果对局未建立, 中断对局
|
||||
if room.whitePlayer == 0 || room.blackPlayer == 0 {
|
||||
chessRoomMap.Delete(groupCode)
|
||||
msg = append(msg, message.Text("对局结束"))
|
||||
return
|
||||
}
|
||||
// 计算认输方
|
||||
var resignColor chess.Color
|
||||
if senderUin == room.whitePlayer {
|
||||
resignColor = chess.White
|
||||
} else {
|
||||
resignColor = chess.Black
|
||||
}
|
||||
if isAprilFoolsDay() {
|
||||
if resignColor == chess.White {
|
||||
resignColor = chess.Black
|
||||
} else {
|
||||
resignColor = chess.White
|
||||
}
|
||||
}
|
||||
room.chessGame.Resign(resignColor)
|
||||
chessString := getChessString(*room)
|
||||
eloString := ""
|
||||
if len(room.chessGame.Moves()) > 4 {
|
||||
// 若走子次数超过 4 认为是有效对局, 存入数据库
|
||||
dbService := newDBService()
|
||||
if err = dbService.createPGN(chessString, room.whitePlayer, room.blackPlayer, room.whiteName, room.blackName); err != nil {
|
||||
return
|
||||
}
|
||||
whiteScore, blackScore := 1.0, 1.0
|
||||
if resignColor == chess.White {
|
||||
whiteScore = 0.0
|
||||
} else {
|
||||
blackScore = 0.0
|
||||
}
|
||||
eloString, err = getELOString(*room, whiteScore, blackScore)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
msg = append(msg, message.Text("认输, 游戏结束。\n", eloString, chessString))
|
||||
if isAprilFoolsDay() {
|
||||
msg = append(msg, message.Text("对手认输, 游戏结束, 你胜利了。\n", eloString, chessString))
|
||||
}
|
||||
chessRoomMap.Delete(groupCode)
|
||||
return
|
||||
}
|
||||
|
||||
// play 走棋
|
||||
func play(groupCode, senderUin int64, moveStr string) (msg message.Message, err error) {
|
||||
msg = message.Message{message.At(senderUin)}
|
||||
// 检查对局是否存在
|
||||
room, ok := chessRoomMap.Load(groupCode)
|
||||
if !ok {
|
||||
return nil, errNotExist
|
||||
}
|
||||
// 不是对局中的玩家, 忽略消息
|
||||
if (senderUin != room.whitePlayer) && (senderUin != room.blackPlayer) && !isAprilFoolsDay() {
|
||||
return
|
||||
}
|
||||
// 对局未建立
|
||||
if (room.whitePlayer == 0) || (room.blackPlayer == 0) {
|
||||
msg = append(msg, message.Text("请等候其他玩家加入游戏。"))
|
||||
return
|
||||
}
|
||||
// 需要对手走棋
|
||||
if ((senderUin == room.whitePlayer) && (room.chessGame.Position().Turn() != chess.White)) || ((senderUin == room.blackPlayer) && (room.chessGame.Position().Turn() != chess.Black)) {
|
||||
msg = append(msg, message.Text("请等待对手走棋。"))
|
||||
return
|
||||
}
|
||||
room.lastMoveTime = time.Now().Unix()
|
||||
// 走棋
|
||||
if err = room.chessGame.MoveStr(moveStr); err != nil {
|
||||
// 指令错误时检查
|
||||
if !room.isBlindfold {
|
||||
// 未开启盲棋, 提示指令错误
|
||||
msg = append(msg, message.Text("移动「", moveStr, "」违规, 请检查, 格式请参考「代数记谱法」(Algebraic notation)。"))
|
||||
return
|
||||
}
|
||||
// 开启盲棋, 判断违例情况
|
||||
var currentPlayerColor chess.Color
|
||||
if senderUin == room.whitePlayer {
|
||||
currentPlayerColor = chess.White
|
||||
} else {
|
||||
currentPlayerColor = chess.Black
|
||||
}
|
||||
// 第一次违例, 提示
|
||||
_flag := false
|
||||
if (currentPlayerColor == chess.White) && !room.whiteErr {
|
||||
room.whiteErr = true
|
||||
chessRoomMap.Store(groupCode, room)
|
||||
_flag = true
|
||||
}
|
||||
if (currentPlayerColor == chess.Black) && !room.blackErr {
|
||||
room.blackErr = true
|
||||
chessRoomMap.Store(groupCode, room)
|
||||
_flag = true
|
||||
}
|
||||
if _flag {
|
||||
msg = append(msg, message.Text("移动「", moveStr, "」违规, 再次违规会立即判负。"))
|
||||
return
|
||||
}
|
||||
// 出现多次违例, 判负
|
||||
room.chessGame.Resign(currentPlayerColor)
|
||||
chessString := getChessString(*room)
|
||||
msg = append(msg, message.Text("违规两次,游戏结束。\n", chessString))
|
||||
|
||||
chessRoomMap.Delete(groupCode)
|
||||
return
|
||||
}
|
||||
// 走子之后, 视为拒绝和棋
|
||||
if room.drawPlayer != 0 {
|
||||
room.drawPlayer = 0
|
||||
chessRoomMap.Store(groupCode, room)
|
||||
}
|
||||
// 生成棋盘图片
|
||||
var boardImgEle message.MessageSegment
|
||||
if !room.isBlindfold {
|
||||
boardImgEle, err = getBoardElement(groupCode)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
// 检查游戏是否结束
|
||||
if room.chessGame.Method() != chess.NoMethod {
|
||||
whiteScore, blackScore := 0.5, 0.5
|
||||
var msgBuilder strings.Builder
|
||||
msgBuilder.WriteString("游戏结束, ")
|
||||
switch room.chessGame.Method() {
|
||||
case chess.FivefoldRepetition:
|
||||
msgBuilder.WriteString("和棋, 因为五次重复走子。\n")
|
||||
case chess.SeventyFiveMoveRule:
|
||||
msgBuilder.WriteString("和棋, 因为七十五步规则。\n")
|
||||
case chess.InsufficientMaterial:
|
||||
msgBuilder.WriteString("和棋, 因为不可能将死。\n")
|
||||
case chess.Stalemate:
|
||||
msgBuilder.WriteString("和棋, 因为逼和(无子可动和棋)。\n")
|
||||
case chess.Checkmate:
|
||||
var winner string
|
||||
if room.chessGame.Position().Turn() == chess.White {
|
||||
whiteScore = 0.0
|
||||
blackScore = 1.0
|
||||
winner = "黑方"
|
||||
} else {
|
||||
whiteScore = 1.0
|
||||
blackScore = 0.0
|
||||
winner = "白方"
|
||||
}
|
||||
msgBuilder.WriteString(winner)
|
||||
msgBuilder.WriteString("胜利, 因为将杀。\n")
|
||||
case chess.NoMethod:
|
||||
case chess.Resignation:
|
||||
case chess.DrawOffer:
|
||||
case chess.ThreefoldRepetition:
|
||||
case chess.FiftyMoveRule:
|
||||
default:
|
||||
}
|
||||
chessString := getChessString(*room)
|
||||
eloString := ""
|
||||
if len(room.chessGame.Moves()) > 4 {
|
||||
// 若走子次数超过 4 认为是有效对局, 存入数据库
|
||||
dbService := newDBService()
|
||||
if err = dbService.createPGN(chessString, room.whitePlayer, room.blackPlayer, room.whiteName, room.blackName); err != nil {
|
||||
return
|
||||
}
|
||||
// 仅有效对局才会计算等级分
|
||||
eloString, err = getELOString(*room, whiteScore, blackScore)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
msgBuilder.WriteString(eloString)
|
||||
msgBuilder.WriteString(chessString)
|
||||
msg = append(msg, message.Text(msgBuilder.String()))
|
||||
if !room.isBlindfold {
|
||||
msg = append(msg, boardImgEle)
|
||||
}
|
||||
|
||||
chessRoomMap.Delete(groupCode)
|
||||
return
|
||||
}
|
||||
// 提示玩家继续游戏
|
||||
var currentPlayer int64
|
||||
if room.chessGame.Position().Turn() == chess.White {
|
||||
currentPlayer = room.whitePlayer
|
||||
} else {
|
||||
currentPlayer = room.blackPlayer
|
||||
}
|
||||
msg = message.Message{message.At(currentPlayer), message.Text("对手已走子, 游戏继续。"), boardImgEle}
|
||||
return
|
||||
}
|
||||
|
||||
// rate 获取等级分
|
||||
func rate(senderUin int64, senderName string) (msg message.Message, err error) {
|
||||
rate := 0
|
||||
dbService := newDBService()
|
||||
rate, err = dbService.getELORateByUin(senderUin)
|
||||
if err != nil {
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
err = errors.New("无法获取等级分信息。")
|
||||
return
|
||||
}
|
||||
err = errors.New("没有查找到等级分信息, 请至少进行一局对局。")
|
||||
}
|
||||
msg = append(msg, message.Text("玩家「", senderName, "」目前的等级分: ", rate))
|
||||
return
|
||||
}
|
||||
|
||||
// cleanUserRate 清空用户等级分
|
||||
func cleanUserRate(senderUin int64) (msg message.Message, err error) {
|
||||
dbService := newDBService()
|
||||
err = dbService.cleanELOByUin(senderUin)
|
||||
if err != nil {
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
err = errors.New("无法清空等级分。")
|
||||
return
|
||||
}
|
||||
err = errors.New("没有查找到等级分信息, 请检查用户 uid 是否正确。")
|
||||
}
|
||||
msg = append(msg, message.Text("已清空用户「", senderUin, "」的等级分。"))
|
||||
return
|
||||
}
|
||||
|
||||
// createGame 创建游戏
|
||||
func createGame(isBlindfold bool, groupCode, senderUin int64, senderName string) (msg message.Message, err error) {
|
||||
room, ok := chessRoomMap.Load(groupCode)
|
||||
if !ok {
|
||||
chessRoomMap.Store(groupCode, &chessRoom{
|
||||
chessGame: chess.NewGame(),
|
||||
whitePlayer: senderUin,
|
||||
whiteName: senderName,
|
||||
blackPlayer: 0,
|
||||
blackName: "",
|
||||
drawPlayer: 0,
|
||||
lastMoveTime: time.Now().Unix(),
|
||||
isBlindfold: isBlindfold,
|
||||
whiteErr: false,
|
||||
blackErr: false,
|
||||
})
|
||||
text := "已创建新的对局, 发送「下棋」或「chess」可加入对局。"
|
||||
if isBlindfold {
|
||||
text = "已创建新的盲棋对局, 发送「盲棋」或「blind」可加入对局。"
|
||||
}
|
||||
msg = append(msg, message.Text(text))
|
||||
return
|
||||
}
|
||||
msg = message.Message{message.At(senderUin)}
|
||||
if room.blackPlayer != 0 {
|
||||
// 检测对局是否已存在超过 6 小时
|
||||
if (time.Now().Unix() - room.lastMoveTime) > 21600 {
|
||||
msg, err = abortGame(*room, groupCode, "对局已存在超过 6 小时, 游戏结束。")
|
||||
msg = append(msg, message.Text("\n\n已有对局已被中断, 如需创建新对局请重新发送指令。"))
|
||||
msg = append(msg, message.At(senderUin))
|
||||
return
|
||||
}
|
||||
// 对局在进行
|
||||
msg = append(msg, message.Text("对局已在进行中, 无法创建或加入对局, 当前对局玩家为: "))
|
||||
if room.whitePlayer != 0 {
|
||||
msg = append(msg, message.At(room.whitePlayer))
|
||||
}
|
||||
if room.blackPlayer != 0 {
|
||||
msg = append(msg, message.At(room.blackPlayer))
|
||||
}
|
||||
msg = append(msg, message.Text(", 群主或管理员发送「中断」或「abort」可中断对局(自动判和)。"))
|
||||
return
|
||||
}
|
||||
if senderUin == room.whitePlayer {
|
||||
msg = append(msg, message.Text("请等候其他玩家加入游戏。"))
|
||||
return
|
||||
}
|
||||
if room.isBlindfold && !isBlindfold {
|
||||
msg = append(msg, message.Text("已创建盲棋对局, 请加入或等待盲棋对局结束之后创建普通对局。"))
|
||||
return
|
||||
}
|
||||
if !room.isBlindfold && isBlindfold {
|
||||
msg = append(msg, message.Text("已创建普通对局, 请加入或等待普通对局结束之后创建盲棋对局。"))
|
||||
return
|
||||
}
|
||||
room.blackPlayer = senderUin
|
||||
room.blackName = senderName
|
||||
chessRoomMap.Store(groupCode, room)
|
||||
var boardImgEle message.MessageSegment
|
||||
if !room.isBlindfold {
|
||||
boardImgEle, err = getBoardElement(groupCode)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
msg = append(msg, message.Text("黑棋已加入对局, 请白方下棋。"), message.At(room.whitePlayer))
|
||||
if !isBlindfold {
|
||||
msg = append(msg, boardImgEle)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// abortGame 中断游戏
|
||||
func abortGame(room chessRoom, groupCode int64, hint string) (message.Message, error) {
|
||||
var msg message.Message
|
||||
err := room.chessGame.Draw(chess.DrawOffer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chessString := getChessString(room)
|
||||
if len(room.chessGame.Moves()) > 4 {
|
||||
dbService := newDBService()
|
||||
if err := dbService.createPGN(chessString, room.whitePlayer, room.blackPlayer, room.whiteName, room.blackName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
chessRoomMap.Delete(groupCode)
|
||||
msg = append(msg, message.Text(hint))
|
||||
if room.whitePlayer != 0 {
|
||||
msg = append(msg, message.At(room.whitePlayer))
|
||||
}
|
||||
if room.blackPlayer != 0 {
|
||||
msg = append(msg, message.At(room.blackPlayer))
|
||||
}
|
||||
msg = append(msg, message.Text("\n\n"+chessString))
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// getBoardElement 获取棋盘图片的消息内容
|
||||
func getBoardElement(groupCode int64) (imgMsg message.MessageSegment, err error) {
|
||||
fontdata, err := file.GetLazyData(text.GNUUnifontFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
room, ok := chessRoomMap.Load(groupCode)
|
||||
if !ok {
|
||||
return imgMsg, errNotExist
|
||||
}
|
||||
// 获取高亮方块
|
||||
highlightSquare := make([]chess.Square, 0, 2)
|
||||
moves := room.chessGame.Moves()
|
||||
if len(moves) != 0 {
|
||||
lastMove := moves[len(moves)-1]
|
||||
highlightSquare = append(highlightSquare, lastMove.S1())
|
||||
highlightSquare = append(highlightSquare, lastMove.S2())
|
||||
}
|
||||
// 生成棋盘 svg 文件
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
fenStr := room.chessGame.FEN()
|
||||
gameTurn := room.chessGame.Position().Turn()
|
||||
pos := &chess.Position{}
|
||||
if err = pos.UnmarshalText(binary.StringToBytes(fenStr)); err != nil {
|
||||
return
|
||||
}
|
||||
yellow := color.RGBA{255, 255, 0, 1}
|
||||
mark := cimage.MarkSquares(yellow, highlightSquare...)
|
||||
board := pos.Board()
|
||||
fromBlack := cimage.Perspective(gameTurn)
|
||||
err = cimage.SVG(buf, board, fromBlack, mark)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
worker, err := resvg.NewDefaultWorker(context.Background())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer worker.Close()
|
||||
|
||||
tree, err := worker.NewTreeFromData(buf.Bytes(), &resvg.Options{
|
||||
Dpi: 96,
|
||||
FontFamily: "Unifont",
|
||||
FontSize: 24.0,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer tree.Close()
|
||||
|
||||
fontdb, err := worker.NewFontDBDefault()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer fontdb.Close()
|
||||
|
||||
err = fontdb.LoadFontData(fontdata)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = tree.ConvertText(fontdb)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pixmap, err := worker.NewPixmap(720, 720)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer pixmap.Close()
|
||||
|
||||
err = tree.Render(resvg.TransformFromScale(2, 2), pixmap)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
out, err := pixmap.EncodePNG()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
imgMsg = message.ImageBytes(out)
|
||||
return imgMsg, nil
|
||||
}
|
||||
|
||||
// getELOString 获得玩家等级分的文本内容
|
||||
func getELOString(room chessRoom, whiteScore, blackScore float64) (string, error) {
|
||||
if room.whitePlayer == 0 || room.blackPlayer == 0 {
|
||||
return "", nil
|
||||
}
|
||||
var msgBuilder strings.Builder
|
||||
msgBuilder.WriteString("玩家等级分: \n")
|
||||
dbService := newDBService()
|
||||
if err := updateELORate(room.whitePlayer, room.blackPlayer, room.whiteName, room.blackName, whiteScore, blackScore, dbService); err != nil {
|
||||
return "", err
|
||||
}
|
||||
whiteRate, blackRate, err := getELORate(room.whitePlayer, room.blackPlayer, dbService)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
msgBuilder.WriteString(room.whiteName)
|
||||
msgBuilder.WriteString(": ")
|
||||
msgBuilder.WriteString(strconv.Itoa(whiteRate))
|
||||
msgBuilder.WriteString("\n")
|
||||
msgBuilder.WriteString(room.blackName)
|
||||
msgBuilder.WriteString(": ")
|
||||
msgBuilder.WriteString(strconv.Itoa(blackRate))
|
||||
msgBuilder.WriteString("\n\n")
|
||||
return msgBuilder.String(), nil
|
||||
}
|
||||
|
||||
// getRankingString 获取等级分排行榜的文本内容
|
||||
func getRanking() (message.Message, error) {
|
||||
dbService := newDBService()
|
||||
eloList, err := dbService.getHighestRateList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var msgBuilder strings.Builder
|
||||
msgBuilder.WriteString("当前等级分排行榜: \n\n")
|
||||
for _, elo := range eloList {
|
||||
msgBuilder.WriteString(elo.Name)
|
||||
msgBuilder.WriteString(": ")
|
||||
msgBuilder.WriteString(strconv.Itoa(elo.Rate))
|
||||
msgBuilder.WriteString("\n")
|
||||
}
|
||||
return message.Message{message.Text(msgBuilder.String())}, nil
|
||||
}
|
||||
|
||||
// updateELORate 更新 elo 等级分
|
||||
// 当数据库中没有玩家的等级分信息时, 自动新建一条记录
|
||||
func updateELORate(whiteUin, blackUin int64, whiteName, blackName string, whiteScore, blackScore float64, dbService *chessDBService) error {
|
||||
whiteRate, err := dbService.getELORateByUin(whiteUin)
|
||||
if err != nil {
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
return err
|
||||
}
|
||||
// create white elo
|
||||
if err := dbService.createELO(whiteUin, whiteName, eloDefault); err != nil {
|
||||
return err
|
||||
}
|
||||
whiteRate = eloDefault
|
||||
}
|
||||
blackRate, err := dbService.getELORateByUin(blackUin)
|
||||
if err != nil {
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
return err
|
||||
}
|
||||
// create black elo
|
||||
if err := dbService.createELO(blackUin, blackName, eloDefault); err != nil {
|
||||
return err
|
||||
}
|
||||
blackRate = eloDefault
|
||||
}
|
||||
whiteRate, blackRate = calculateNewRate(whiteRate, blackRate, whiteScore, blackScore)
|
||||
// 更新白棋玩家的 ELO 等级分
|
||||
if err := dbService.updateELOByUin(whiteUin, whiteName, whiteRate); err != nil {
|
||||
return err
|
||||
}
|
||||
// 更新黑棋玩家的 ELO 等级分
|
||||
return dbService.updateELOByUin(blackUin, blackName, blackRate)
|
||||
}
|
||||
|
||||
// getChessString 获取 PGN 字符串
|
||||
func getChessString(room chessRoom) string {
|
||||
game := room.chessGame
|
||||
dataString := fmt.Sprintf("[Date \"%s\"]\n", time.Now().Format("2006-01-02"))
|
||||
whiteString := fmt.Sprintf("[White \"%s\"]\n", room.whiteName)
|
||||
blackString := fmt.Sprintf("[Black \"%s\"]\n", room.blackName)
|
||||
chessString := game.String()
|
||||
|
||||
return dataString + whiteString + blackString + chessString
|
||||
}
|
||||
|
||||
// getELORate 获取玩家的 ELO 等级分
|
||||
func getELORate(whiteUin, blackUin int64, dbService *chessDBService) (whiteRate int, blackRate int, err error) {
|
||||
whiteRate, err = dbService.getELORateByUin(whiteUin)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
blackRate, err = dbService.getELORateByUin(blackUin)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// isAprilFoolsDay 判断当前时间是否为愚人节期间
|
||||
func isAprilFoolsDay() bool {
|
||||
now := time.Now()
|
||||
return now.Month() == 4 && now.Day() == 1
|
||||
}
|
||||
100
plugin/chess/db.go
Normal file
100
plugin/chess/db.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package chess
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
var chessDB *gorm.DB
|
||||
|
||||
// elo user elo info
|
||||
type elo struct {
|
||||
gorm.Model
|
||||
Uin int64 `gorm:"unique_index"`
|
||||
Name string
|
||||
Rate int
|
||||
}
|
||||
|
||||
// pgn chess pgn info
|
||||
type pgn struct {
|
||||
gorm.Model
|
||||
Data string
|
||||
WhiteUin int64
|
||||
BlackUin int64
|
||||
WhiteName string
|
||||
BlackName string
|
||||
}
|
||||
|
||||
// chessDBService 数据库服务
|
||||
type chessDBService struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// newDBService 创建数据库服务
|
||||
func newDBService() *chessDBService {
|
||||
return &chessDBService{
|
||||
db: chessDB,
|
||||
}
|
||||
}
|
||||
|
||||
// initDatabase init database
|
||||
func initDatabase(dbPath string) {
|
||||
var err error
|
||||
if _, err = os.Stat(dbPath); err != nil || os.IsNotExist(err) {
|
||||
f, err := os.Create(dbPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
}
|
||||
chessDB, err = gorm.Open("sqlite3", dbPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
chessDB.AutoMigrate(&elo{}, &pgn{})
|
||||
}
|
||||
|
||||
// createELO 创建 ELO
|
||||
func (s *chessDBService) createELO(uin int64, name string, rate int) error {
|
||||
return s.db.Create(&elo{
|
||||
Uin: uin,
|
||||
Name: name,
|
||||
Rate: rate,
|
||||
}).Error
|
||||
}
|
||||
|
||||
// getELORateByUin 获取 ELO 等级分
|
||||
func (s *chessDBService) getELORateByUin(uin int64) (int, error) {
|
||||
var elo elo
|
||||
err := s.db.Select("rate").Where("uin = ?", uin).First(&elo).Error
|
||||
return elo.Rate, err
|
||||
}
|
||||
|
||||
// getHighestRateList 获取最高的等级分列表
|
||||
func (s *chessDBService) getHighestRateList() ([]elo, error) {
|
||||
var eloList []elo
|
||||
err := s.db.Order("rate desc").Limit(10).Find(&eloList).Error
|
||||
return eloList, err
|
||||
}
|
||||
|
||||
// updateELOByUin 更新 ELO 等级分
|
||||
func (s *chessDBService) updateELOByUin(uin int64, name string, rate int) error {
|
||||
return s.db.Model(&elo{}).Where("uin = ?", uin).Update("name", name).Update("rate", rate).Error
|
||||
}
|
||||
|
||||
// cleanELOByUin 清空用户 ELO 等级分
|
||||
func (s *chessDBService) cleanELOByUin(uin int64) error {
|
||||
return s.db.Model(&elo{}).Where("uin = ?", uin).Update("rate", 100).Error
|
||||
}
|
||||
|
||||
// createPGN 创建 PGN
|
||||
func (s *chessDBService) createPGN(data string, whiteUin int64, blackUin int64, whiteName string, blackName string) error {
|
||||
return s.db.Create(&pgn{
|
||||
Data: data,
|
||||
WhiteUin: whiteUin,
|
||||
BlackUin: blackUin,
|
||||
WhiteName: whiteName,
|
||||
BlackName: blackName,
|
||||
}).Error
|
||||
}
|
||||
37
plugin/chess/elo.go
Normal file
37
plugin/chess/elo.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package chess
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// calculateNewRate calculate new rate of the player
|
||||
func calculateNewRate(whiteRate, blackRate int, whiteScore, blackScore float64) (int, int) {
|
||||
k := getKFactor(whiteRate, blackRate)
|
||||
exceptionWhite := calculateException(whiteRate, blackRate)
|
||||
exceptionBlack := calculateException(blackRate, whiteRate)
|
||||
whiteRate = calculateRate(whiteRate, whiteScore, exceptionWhite, k)
|
||||
blackRate = calculateRate(blackRate, blackScore, exceptionBlack, k)
|
||||
return whiteRate, blackRate
|
||||
}
|
||||
|
||||
func calculateException(rate int, opponentRate int) float64 {
|
||||
return 1.0 / (1.0 + math.Pow(10.0, float64(opponentRate-rate)/400.0))
|
||||
}
|
||||
|
||||
func calculateRate(rate int, score float64, exception float64, k int) int {
|
||||
newRate := int(math.Round(float64(rate) + float64(k)*(score-exception)))
|
||||
if newRate < 1 {
|
||||
newRate = 1
|
||||
}
|
||||
return newRate
|
||||
}
|
||||
|
||||
func getKFactor(rateA, rateB int) int {
|
||||
if rateA > 2400 && rateB > 2400 {
|
||||
return 16
|
||||
}
|
||||
if rateA > 2100 && rateB > 2100 {
|
||||
return 24
|
||||
}
|
||||
return 32
|
||||
}
|
||||
80
plugin/chess/elo_test.go
Normal file
80
plugin/chess/elo_test.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package chess
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCalculateNewRate(t *testing.T) {
|
||||
type args struct {
|
||||
whiteRate int
|
||||
blackRate int
|
||||
whiteScore float64
|
||||
blackScore float64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want int
|
||||
want1 int
|
||||
}{
|
||||
{
|
||||
name: "test1",
|
||||
args: args{
|
||||
whiteRate: 1613,
|
||||
blackRate: 1573,
|
||||
whiteScore: 0.5,
|
||||
blackScore: 0.5,
|
||||
},
|
||||
want: 1611,
|
||||
want1: 1575,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, got1 := calculateNewRate(tt.args.whiteRate, tt.args.blackRate, tt.args.whiteScore, tt.args.blackScore)
|
||||
if got != tt.want {
|
||||
t.Errorf("CalculateNewRate() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
if got1 != tt.want1 {
|
||||
t.Errorf("CalculateNewRate() got1 = %v, want %v", got1, tt.want1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_calculateException(t *testing.T) {
|
||||
type args struct {
|
||||
rate int
|
||||
opponentRate int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want float64
|
||||
}{
|
||||
{
|
||||
name: "test1",
|
||||
args: args{
|
||||
rate: 1613,
|
||||
opponentRate: 1573,
|
||||
},
|
||||
want: 0.5573116,
|
||||
},
|
||||
{
|
||||
name: "test2",
|
||||
args: args{
|
||||
rate: 1613,
|
||||
opponentRate: 1613,
|
||||
},
|
||||
want: 0.5,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := calculateException(tt.args.rate, tt.args.opponentRate); math.Abs(got-tt.want) > 0.0001 {
|
||||
t.Errorf("calculateException() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("choose", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "选择困难症帮手",
|
||||
Help: "例: 选择可口可乐还是百事可乐\n" +
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("chouxianghua", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "翻译为抽象话",
|
||||
Help: "- 抽象翻译xxx",
|
||||
@@ -26,7 +26,7 @@ func init() {
|
||||
db.DBPath = en.DataFolder() + "cxh.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = en.GetLazyData("cxh.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
err := db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
func init() {
|
||||
// 初始化engine
|
||||
engine := control.Register("chrev", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "英文字符翻转",
|
||||
Help: "例: 翻转 I love you",
|
||||
|
||||
@@ -53,7 +53,7 @@ func init() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
control.Register("coser", &ctrl.Options[*zero.Ctx]{
|
||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "三次元coser",
|
||||
Help: "- coser",
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("cpstory", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "cp短打", // 这里也许有更好的名字
|
||||
Help: "- 组cp[@xxx][@xxx]\n- 磕cp大老师 雪乃",
|
||||
@@ -27,7 +27,7 @@ func init() {
|
||||
db.DBPath = engine.DataFolder() + "cp.db"
|
||||
// os.RemoveAll(dbpath)
|
||||
_, _ = engine.GetLazyData("cp.db", true)
|
||||
err := db.Open(time.Hour * 24)
|
||||
err := db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
@@ -21,7 +21,7 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("curse", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: true,
|
||||
Brief: "骂人反击",
|
||||
Help: "- 骂我\n- 大力骂我",
|
||||
@@ -35,7 +35,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
err = db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
const api = "http://dwz.2xb.cn/zaob"
|
||||
|
||||
func init() {
|
||||
engine := control.Register("dailynews", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "今日早报",
|
||||
Help: "- 今日早报",
|
||||
@@ -29,7 +29,7 @@ func init() {
|
||||
}
|
||||
picURL := gjson.Get(binary.BytesToString(data), "imageUrl").String()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image(picURL))
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("danbooru", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "二次元图片标签识别",
|
||||
Help: "- 鉴赏图片[图片]",
|
||||
|
||||
@@ -3,6 +3,7 @@ package deepdanbooru
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"net/url"
|
||||
@@ -59,8 +60,12 @@ func tagurl(name, u string) (im image.Image, st *sorttags, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(data) < 4 {
|
||||
err = errors.New("data too short")
|
||||
return
|
||||
}
|
||||
tags := make(map[string]float64)
|
||||
err = json.Unmarshal(data, &tags)
|
||||
err = json.Unmarshal(data[1:len(data)-1], &tags)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/FloatTech/ZeroBot-Plugin/plugin/diana/data"
|
||||
)
|
||||
|
||||
var engine = control.Register("diana", &ctrl.Options[*zero.Ctx]{
|
||||
var engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "嘉然相关", // 也许使用常用功能当Brief更好
|
||||
Help: "- 小作文\n" +
|
||||
|
||||
@@ -27,7 +27,7 @@ func LoadText(dbfile string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
err = db.Open(time.Hour)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
115
plugin/dish/dish.go
Normal file
115
plugin/dish/dish.go
Normal file
@@ -0,0 +1,115 @@
|
||||
// Package dish 程序员做饭指南zbp版,数据来源Anduin2017/HowToCook
|
||||
package dish
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
type dish struct {
|
||||
ID uint32 `db:"id"`
|
||||
Name string `db:"name"`
|
||||
Materials string `db:"materials"`
|
||||
Steps string `db:"steps"`
|
||||
}
|
||||
|
||||
var (
|
||||
db = &sql.Sqlite{}
|
||||
initialized = false
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "程序员做饭指南",
|
||||
Help: "-怎么做[xxx]|烹饪[xxx]|随机菜谱|随便做点菜",
|
||||
PublicDataFolder: "Dish",
|
||||
})
|
||||
|
||||
db.DBPath = en.DataFolder() + "dishes.db"
|
||||
|
||||
if _, err := en.GetLazyData("dishes.db", true); err != nil {
|
||||
logrus.Warnln("[dish]获取菜谱数据库文件失败")
|
||||
} else if err = db.Open(time.Hour); err != nil {
|
||||
logrus.Warnln("[dish]连接菜谱数据库失败")
|
||||
} else if err = db.Create("dish", &dish{}); err != nil {
|
||||
logrus.Warnln("[dish]同步菜谱数据表失败")
|
||||
} else if count, err := db.Count("dish"); err != nil {
|
||||
logrus.Warnln("[dish]统计菜谱数据失败")
|
||||
} else {
|
||||
logrus.Infoln("[dish]加载", count, "条菜谱")
|
||||
initialized = true
|
||||
}
|
||||
|
||||
if !initialized {
|
||||
logrus.Warnln("[dish]插件未能成功初始化")
|
||||
}
|
||||
|
||||
en.OnPrefixGroup([]string{"怎么做", "烹饪"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
if !initialized {
|
||||
ctx.SendChain(message.Text("客官,本店暂未开业"))
|
||||
return
|
||||
}
|
||||
|
||||
name := ctx.NickName()
|
||||
dishName := ctx.State["args"].(string)
|
||||
|
||||
if dishName == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.Contains(dishName, "'") ||
|
||||
strings.Contains(dishName, "\"") ||
|
||||
strings.Contains(dishName, "\\") ||
|
||||
strings.Contains(dishName, ";") {
|
||||
return
|
||||
}
|
||||
|
||||
var d dish
|
||||
if err := db.Find("dish", &d, fmt.Sprintf("WHERE name like %%%s%%", dishName)); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.SendChain(message.Text(fmt.Sprintf(
|
||||
"已为客官%s找到%s的做法辣!\n"+
|
||||
"原材料:%s\n"+
|
||||
"步骤:\n"+
|
||||
"%s",
|
||||
name, dishName, d.Materials, d.Steps),
|
||||
))
|
||||
})
|
||||
|
||||
en.OnPrefixGroup([]string{"随机菜谱", "随便做点菜"}).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
if !initialized {
|
||||
ctx.SendChain(message.Text("客官,本店暂未开业"))
|
||||
return
|
||||
}
|
||||
|
||||
name := ctx.NickName()
|
||||
var d dish
|
||||
if err := db.Pick("dish", &d); err != nil {
|
||||
ctx.SendChain(message.Text("小店好像出错了,暂时端不出菜来惹"))
|
||||
logrus.Warnln("[dish]随机菜谱请求出错:" + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
ctx.SendChain(message.Text(fmt.Sprintf(
|
||||
"已为客官%s送上%s的做法:\n"+
|
||||
"原材料:%s\n"+
|
||||
"步骤:\n"+
|
||||
"%s",
|
||||
name, d.Name, d.Materials, d.Steps),
|
||||
))
|
||||
})
|
||||
}
|
||||
@@ -2,8 +2,10 @@
|
||||
package drawlots
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/gif"
|
||||
"math/rand"
|
||||
"os"
|
||||
@@ -11,6 +13,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
@@ -37,10 +40,12 @@ var (
|
||||
}
|
||||
return lotsList
|
||||
}()
|
||||
en = control.Register("drawlots", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "多功能抽签",
|
||||
Help: "支持图包文件夹和gif抽签\n-------------\n- (刷新)抽签列表\n- 抽[签名]签\n- 看签[gif签名]\n- 加签[签名][gif图片]\n- 删签[gif签名]",
|
||||
en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "多功能抽签",
|
||||
Help: "支持图包文件夹和gif抽签\n" +
|
||||
"-------------\n" +
|
||||
"- (刷新)抽签列表\n- 抽[签名]签\n- 看[gif签名]签\n- 加[签名]签[gif图片]\n- 删[gif签名]签",
|
||||
PrivateDataFolder: "drawlots",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
datapath = file.BOTPATH + "/" + en.DataFolder()
|
||||
@@ -48,9 +53,10 @@ var (
|
||||
|
||||
func init() {
|
||||
en.OnFullMatchGroup([]string{"抽签列表", "刷新抽签列表"}).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
lotsList, err := getList() // 刷新列表
|
||||
var err error
|
||||
lotsList, err = getList() // 刷新列表
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
messageText := &strings.Builder{}
|
||||
@@ -62,7 +68,7 @@ func init() {
|
||||
}
|
||||
textPic, err := text.RenderToBase64(messageText.String(), text.BoldFontFile, 400, 50)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + helper.BytesToString(textPic)))
|
||||
@@ -77,7 +83,7 @@ func init() {
|
||||
if fileInfo.lotsType == "folder" {
|
||||
picPath, err := randFile(lotsType, 3)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("file:///"+picPath))
|
||||
@@ -85,20 +91,20 @@ func init() {
|
||||
}
|
||||
lotsImg, err := randGif(lotsType + "." + fileInfo.lotsType)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 生成图片
|
||||
data, err := imgfactory.ToBytes(lotsImg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.ImageBytes(data))
|
||||
})
|
||||
en.OnPrefix("看签", zero.UserOrGrpAdmin).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^看(.+)签$`, zero.UserOrGrpAdmin).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.Event.MessageID
|
||||
lotsName := strings.TrimSpace(ctx.State["args"].(string))
|
||||
lotsName := ctx.State["regex_matched"].([]string)[1]
|
||||
fileInfo, ok := lotsList[lotsName]
|
||||
if !ok {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("才...才没有", lotsName, "签这种东西啦")))
|
||||
@@ -110,28 +116,27 @@ func init() {
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Image("file:///"+datapath+lotsName+"."+fileInfo.lotsType)))
|
||||
})
|
||||
en.OnPrefix("加签", zero.SuperUserPermission, zero.MustProvidePicture).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^加(.+)签.*`, zero.SuperUserPermission, zero.MustProvidePicture).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.Event.MessageID
|
||||
lotsName := strings.TrimSpace(ctx.State["args"].(string))
|
||||
lotsName := ctx.State["regex_matched"].([]string)[1]
|
||||
if lotsName == "" {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("请使用正确的指令形式哦~")))
|
||||
return
|
||||
}
|
||||
picURL := ctx.State["image_url"].([]string)[0]
|
||||
err := file.DownloadTo(picURL, datapath+"/"+lotsName+".gif")
|
||||
gifdata, err := web.GetData(picURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
file, err := os.Open(datapath + "/" + lotsName + ".gif")
|
||||
im, err := gif.DecodeAll(bytes.NewReader(gifdata))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
im, err := gif.DecodeAll(file)
|
||||
_ = file.Close()
|
||||
fileName := datapath + "/" + lotsName + ".gif"
|
||||
err = file.DownloadTo(picURL, fileName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
lotsList[lotsName] = info{
|
||||
@@ -140,9 +145,9 @@ func init() {
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("成功!")))
|
||||
})
|
||||
en.OnPrefix("删签", zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^删(.+)签$`, zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.Event.MessageID
|
||||
lotsName := strings.TrimSpace(ctx.State["args"].(string))
|
||||
lotsName := ctx.State["regex_matched"].([]string)[1]
|
||||
fileInfo, ok := lotsList[lotsName]
|
||||
if !ok {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("才...才没有", lotsName, "签这种东西啦")))
|
||||
@@ -154,7 +159,7 @@ func init() {
|
||||
}
|
||||
err := os.Remove(datapath + lotsName + "." + fileInfo.lotsType)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
delete(lotsList, lotsName)
|
||||
@@ -240,10 +245,10 @@ func randGif(gifName string) (image.Image, error) {
|
||||
return nil, err
|
||||
}
|
||||
v := im.Image[rand.Intn(len(im.Image))]
|
||||
return imgfactory.Size(firstImg, firstImg.Bounds().Max.X, firstImg.Bounds().Max.Y).InsertUpC(v, 0, 0, firstImg.Bounds().Max.X/2, firstImg.Bounds().Max.Y/2).Clone().Image(),err
|
||||
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.Size(v, v.Bounds().Max.X, v.Bounds().Max.Y).Image(), err
|
||||
return imgfactory.NewFactoryBG(v.Rect.Dx(), v.Rect.Dy(), color.NRGBA{0, 0, 0, 255}).InsertUp(v, 0, 0, 0, 0).Clone().Image(), err
|
||||
// */
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("dress", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "女装",
|
||||
Help: "女装\n" +
|
||||
|
||||
@@ -33,14 +33,14 @@ var seaLocker sync.RWMutex
|
||||
// We need a container to inject what we need :(
|
||||
|
||||
func init() {
|
||||
en := control.Register("driftbottle", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "漂流瓶",
|
||||
Help: "- @bot pick" + "- @bot throw xxx (xxx为投递内容)",
|
||||
PrivateDataFolder: "driftbottle",
|
||||
})
|
||||
seaSide.DBPath = en.DataFolder() + "sea.db"
|
||||
err := seaSide.Open(time.Hour * 24)
|
||||
err := seaSide.Open(time.Hour)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
const bed = "https://www.gstatic.com/android/keyboard/emojikitchen/%d/u%x/u%x_u%x.png"
|
||||
|
||||
func init() {
|
||||
control.Register("emojimix", &ctrl.Options[*zero.Ctx]{
|
||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "合成emoji",
|
||||
Help: "- [emoji][emoji]",
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("event", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "好友申请和群聊邀请事件处理",
|
||||
Help: "- [开启|关闭]自动同意[申请|邀请|主人]\n" +
|
||||
@@ -39,8 +39,8 @@ func init() {
|
||||
userid := ctx.Event.UserID
|
||||
username := ctx.CardOrNickName(userid)
|
||||
data := (storage)(c.GetData(-su))
|
||||
groupname := ctx.GetThisGroupInfo(true).Name
|
||||
groupid := ctx.Event.GroupID
|
||||
groupname := ctx.GetGroupInfo(groupid, true).Name
|
||||
logrus.Info("[event]收到来自[", username, "](", userid, ")的群聊邀请,群:[", groupname, "](", groupid, ")")
|
||||
if data.isinviteon() || (!data.ismasteroff() && zero.SuperUserPermission(ctx)) {
|
||||
ctx.SetGroupAddRequest(ctx.Event.Flag, "invite", true, "")
|
||||
|
||||
@@ -2,7 +2,17 @@
|
||||
package font
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/gif"
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/gg"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
@@ -12,13 +22,13 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("font", &ctrl.Options[*zero.Ctx]{
|
||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "渲染任意文字到图片",
|
||||
Help: "- (用[字体])渲染文字xxx\n可选字体: [终末体|终末变体|紫罗兰体|樱酥体|Consolas体|苹方体]",
|
||||
}).OnRegex(`^(用.+)?渲染文字([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
Help: "- (用[字体])渲染(抖动)文字xxx\n可选字体: [终末体|终末变体|紫罗兰体|樱酥体|Consolas体|粗苹方体|未来荧黑体|Gugi体|八丸体|Impact体|猫啃体|苹方体]",
|
||||
}).OnRegex(`^(用.+)?渲染(抖动)?文字([\s\S]+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
fnt := ctx.State["regex_matched"].([]string)[1]
|
||||
txt := ctx.State["regex_matched"].([]string)[2]
|
||||
txt := ctx.State["regex_matched"].([]string)[3]
|
||||
switch fnt {
|
||||
case "用终末体":
|
||||
fnt = text.SyumatuFontFile
|
||||
@@ -30,16 +40,73 @@ func init() {
|
||||
fnt = text.SakuraFontFile
|
||||
case "用Consolas体":
|
||||
fnt = text.ConsolasFontFile
|
||||
case "用粗苹方体":
|
||||
fnt = text.BoldFontFile
|
||||
case "用未来荧黑体":
|
||||
fnt = text.GlowSansFontFile
|
||||
case "用Gugi体":
|
||||
fnt = text.GugiRegularFontFile
|
||||
case "用八丸体":
|
||||
fnt = text.HachiMaruPopRegularFontFile
|
||||
case "用Impact体":
|
||||
fnt = text.ImpactFontFile
|
||||
case "用猫啃体":
|
||||
fnt = text.MaokenFontFile
|
||||
case "用苹方体":
|
||||
fallthrough
|
||||
default:
|
||||
fnt = text.FontFile
|
||||
}
|
||||
b, err := text.RenderToBase64(txt, fnt, 400, 20)
|
||||
if ctx.State["regex_matched"].([]string)[2] == "" {
|
||||
b, err := text.RenderToBase64(txt, fnt, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(b)))
|
||||
return
|
||||
}
|
||||
nilx, nily := 1.0, 8.0
|
||||
s := []*image.NRGBA{}
|
||||
strlist := strings.Split(txt, "\n")
|
||||
data, err := file.GetLazyData(fnt, control.Md5File, true)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(b)))
|
||||
// 获得画布预计
|
||||
testcov := gg.NewContext(1, 1)
|
||||
if err = testcov.ParseFontFace(data, 30); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 取最长段
|
||||
txt = ""
|
||||
for _, v := range strlist {
|
||||
if len([]rune(v)) > len([]rune(txt)) {
|
||||
txt = v
|
||||
}
|
||||
}
|
||||
w, h := testcov.MeasureString(txt)
|
||||
for i := 0; i < 10; i++ {
|
||||
cov := gg.NewContext(int(w+float64(len([]rune(txt)))*nilx)+40, int(h+nily)*len(strlist)+30)
|
||||
cov.SetRGB(1, 1, 1)
|
||||
cov.Clear()
|
||||
if err = cov.ParseFontFace(data, 30); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
cov.SetColor(color.NRGBA{R: 0, G: 0, B: 0, A: 127})
|
||||
for k, v := range strlist {
|
||||
for kk, vv := range []rune(v) {
|
||||
x, y := cov.MeasureString(string([]rune(v)[:kk]))
|
||||
cov.DrawString(string(vv), x+float64(rand.Intn(5))+10+nilx, y+float64(rand.Intn(5))+15+float64(k)*(y+nily))
|
||||
}
|
||||
}
|
||||
s = append(s, imgfactory.Size(cov.Image(), 0, 0).Image())
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
_ = gif.EncodeAll(&buf, imgfactory.MergeGif(5, s))
|
||||
ctx.SendChain(message.ImageBytes(buf.Bytes()))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ var (
|
||||
|
||||
func init() {
|
||||
// 插件主体
|
||||
en := control.Register("fortune", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "每日运势",
|
||||
Help: "- 运势 | 抽签\n" +
|
||||
|
||||
@@ -24,7 +24,7 @@ type joke struct {
|
||||
var db = &sql.Sqlite{}
|
||||
|
||||
func init() {
|
||||
en := control.Register("funny", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "讲个笑话",
|
||||
Help: "- 讲个笑话[@xxx|qq号|人名] | 夸夸[@xxx|qq号|人名] ",
|
||||
@@ -38,7 +38,7 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
err = db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
@@ -35,7 +35,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("genshin", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "原神模拟抽卡",
|
||||
Help: "- 原神十连\n- 切换原神卡池",
|
||||
|
||||
@@ -19,7 +19,7 @@ func mo(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "摸.gif"
|
||||
// name := cc.usrdir + "摸.gif"
|
||||
c := dlrange("mo", 5, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -44,7 +44,8 @@ func mo(cc *context, value ...string) (string, error) {
|
||||
imgs[3].InsertBottom(tou, 85, 75, 27, 37).Image(),
|
||||
imgs[4].InsertBottom(tou, 90, 70, 22, 42).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(1, mo))
|
||||
g := imgfactory.MergeGif(1, mo)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// cuo 搓
|
||||
@@ -53,7 +54,7 @@ func cuo(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "搓.gif"
|
||||
// name := cc.usrdir + "搓.gif"
|
||||
c := dlrange("cuo", 5, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -82,7 +83,8 @@ func cuo(cc *context, value ...string) (string, error) {
|
||||
imgs[3].InsertBottomC(m3.Image(), 0, 0, 75, 130).Image(),
|
||||
imgs[4].InsertBottomC(m4.Image(), 0, 0, 75, 130).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(5, cuo))
|
||||
g := imgfactory.MergeGif(5, cuo)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// qiao 敲
|
||||
@@ -91,7 +93,7 @@ func qiao(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "敲.gif"
|
||||
// name := cc.usrdir + "敲.gif"
|
||||
c := dlrange("qiao", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -113,7 +115,8 @@ func qiao(cc *context, value ...string) (string, error) {
|
||||
imgs[0].InsertUp(tou, 40, 33, 57, 52).Image(),
|
||||
imgs[1].InsertUp(tou, 38, 36, 58, 50).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(1, qiao))
|
||||
g := imgfactory.MergeGif(1, qiao)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// chi 吃
|
||||
@@ -122,7 +125,7 @@ func chi(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "吃.gif"
|
||||
// name := cc.usrdir + "吃.gif"
|
||||
c := dlrange("chi", 3, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -145,7 +148,8 @@ func chi(cc *context, value ...string) (string, error) {
|
||||
imgs[1].InsertBottom(tou, 0, 0, 1, 38).Image(),
|
||||
imgs[2].InsertBottom(tou, 0, 0, 1, 38).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(1, chi))
|
||||
g := imgfactory.MergeGif(1, chi)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// ceng 蹭
|
||||
@@ -154,7 +158,7 @@ func ceng(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "蹭.gif"
|
||||
// name := cc.usrdir + "蹭.gif"
|
||||
c := dlrange("ceng", 6, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -184,7 +188,8 @@ func ceng(cc *context, value ...string) (string, error) {
|
||||
imgs[4].InsertUp(tou, 75, 77, 56, 110).InsertUp(imgfactory.Rotate(tou2, -66, 132, 80).Image(), 0, 0, 78, 40).Image(),
|
||||
imgs[5].InsertUp(tou, 75, 77, 62, 102).InsertUp(tou2, 71, 100, 110, 94).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(8, ceng))
|
||||
g := imgfactory.MergeGif(8, ceng)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// ken 啃
|
||||
@@ -193,7 +198,7 @@ func ken(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "啃.gif"
|
||||
// name := cc.usrdir + "啃.gif"
|
||||
c := dlrange("ken", 16, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -229,7 +234,8 @@ func ken(cc *context, value ...string) (string, error) {
|
||||
imgs[14].Image(),
|
||||
imgs[15].Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, ken))
|
||||
g := imgfactory.MergeGif(7, ken)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// pai 拍
|
||||
@@ -238,7 +244,7 @@ func pai(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "拍.gif"
|
||||
// name := cc.usrdir + "拍.gif"
|
||||
c := dlrange("pai", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -260,7 +266,8 @@ func pai(cc *context, value ...string) (string, error) {
|
||||
imgs[0].InsertUp(tou, 0, 0, 1, 47).Image(),
|
||||
imgs[1].InsertUp(tou, 0, 0, 1, 67).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(1, pai))
|
||||
g := imgfactory.MergeGif(1, pai)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// xqe 冲
|
||||
@@ -269,7 +276,7 @@ func xqe(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "冲.gif"
|
||||
// name := cc.usrdir + "冲.gif"
|
||||
c := dlrange("xqe", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -291,7 +298,8 @@ func xqe(cc *context, value ...string) (string, error) {
|
||||
imgs[0].InsertUp(tou, 30, 30, 15, 53).Image(),
|
||||
imgs[1].InsertUp(tou, 30, 30, 40, 53).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(1, chong))
|
||||
g := imgfactory.MergeGif(1, chong)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// diu 丢
|
||||
@@ -300,7 +308,7 @@ func diu(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "丢.gif"
|
||||
// name := cc.usrdir + "丢.gif"
|
||||
c := dlrange("diu", 8, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -328,7 +336,8 @@ func diu(cc *context, value ...string) (string, error) {
|
||||
imgs[6].InsertUp(tou, 35, 35, 259, 31).Image(),
|
||||
imgs[7].InsertUp(tou, 175, 175, -50, 220).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, diu))
|
||||
g := imgfactory.MergeGif(7, diu)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// kiss 亲
|
||||
@@ -338,7 +347,7 @@ func kiss(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 13
|
||||
name := cc.usrdir + "Kiss.gif"
|
||||
// name := cc.usrdir + "Kiss.gif"
|
||||
c := dlrange("kiss", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -367,7 +376,8 @@ func kiss(cc *context, value ...string) (string, error) {
|
||||
kiss[i] = imgs[i].InsertUp(tou, 50, 50, userLocs[i][0], userLocs[i][1]).
|
||||
InsertUp(tou2, 40, 40, selfLocs[i][0], selfLocs[i][1]).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, kiss))
|
||||
g := imgfactory.MergeGif(7, kiss)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// garbage 垃圾 垃圾桶
|
||||
@@ -377,7 +387,7 @@ func garbage(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 25
|
||||
name := cc.usrdir + "Garbage.gif"
|
||||
// name := cc.usrdir + "Garbage.gif"
|
||||
c := dlrange("garbage", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -400,7 +410,8 @@ func garbage(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
garbage[i] = imgs[i].InsertBottom(im.Image(), 0, 0, locs[i][0], locs[i][1]).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, garbage))
|
||||
g := imgfactory.MergeGif(7, garbage)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// thump 捶
|
||||
@@ -410,7 +421,7 @@ func thump(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 4
|
||||
name := cc.usrdir + "Thump.gif"
|
||||
// name := cc.usrdir + "Thump.gif"
|
||||
c := dlrange("thump", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -433,7 +444,8 @@ func thump(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
thump[i] = imgs[i].InsertBottom(im.Image(), locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, thump))
|
||||
g := imgfactory.MergeGif(7, thump)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// jiujiu 啾啾
|
||||
@@ -443,7 +455,7 @@ func jiujiu(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "Jiujiu.gif"
|
||||
// name := cc.usrdir + "Jiujiu.gif"
|
||||
c := dlrange("jiujiu", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -465,7 +477,8 @@ func jiujiu(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
jiujiu[i] = imgs[i].InsertBottom(im.Image(), 0, 0, 0, 0).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, jiujiu))
|
||||
g := imgfactory.MergeGif(7, jiujiu)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// knock 2敲
|
||||
@@ -475,7 +488,7 @@ func knock(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "Knock.gif"
|
||||
// name := cc.usrdir + "Knock.gif"
|
||||
c := dlrange("knock", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -498,7 +511,8 @@ func knock(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
knock[i] = imgs[i].InsertBottom(im.Image(), locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, knock))
|
||||
g := imgfactory.MergeGif(7, knock)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// 听音乐 listenMusic
|
||||
@@ -508,7 +522,7 @@ func listenMusic(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 1
|
||||
name := cc.usrdir + "ListenMusic.gif"
|
||||
// name := cc.usrdir + "ListenMusic.gif"
|
||||
c := dlrange("listen_music", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -530,7 +544,8 @@ func listenMusic(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < 36; i++ {
|
||||
listenmusic[i] = imgs[0].InsertBottomC(imgfactory.Rotate(face, float64(-i*10), 215, 215).Image(), 0, 0, 207, 207).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, listenmusic))
|
||||
g := imgfactory.MergeGif(7, listenmusic)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// loveYou 永远爱你
|
||||
@@ -540,7 +555,7 @@ func loveYou(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 2
|
||||
name := cc.usrdir + "LoveYou.gif"
|
||||
// name := cc.usrdir + "LoveYou.gif"
|
||||
c := dlrange("love_you", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -563,7 +578,8 @@ func loveYou(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
loveyou[i] = imgs[i].InsertBottom(im.Image(), locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, loveyou))
|
||||
g := imgfactory.MergeGif(7, loveyou)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// pat 2拍
|
||||
@@ -573,7 +589,7 @@ func pat(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 10
|
||||
name := cc.usrdir + "Pat.gif"
|
||||
// name := cc.usrdir + "Pat.gif"
|
||||
c := dlrange("pat", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -605,7 +621,8 @@ func pat(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < len(pat); i++ {
|
||||
pat[i] = p[seq[i]]
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, pat))
|
||||
g := imgfactory.MergeGif(7, pat)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// jackUp 顶
|
||||
@@ -615,7 +632,7 @@ func jackUp(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 23
|
||||
name := cc.usrdir + "JackUp.gif"
|
||||
// name := cc.usrdir + "JackUp.gif"
|
||||
c := dlrange("play", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -648,7 +665,8 @@ func jackUp(cc *context, value ...string) (string, error) {
|
||||
play = append(play, p[0:8]...)
|
||||
play = append(play, p[12:18]...)
|
||||
play = append(play, p[18:23]...)
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, play))
|
||||
g := imgfactory.MergeGif(7, play)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// pound 捣
|
||||
@@ -658,7 +676,7 @@ func pound(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "Pound.gif"
|
||||
// name := cc.usrdir + "Pound.gif"
|
||||
c := dlrange("pound", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -681,7 +699,8 @@ func pound(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
pound[i] = imgs[i].InsertBottom(im.Image(), locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, pound))
|
||||
g := imgfactory.MergeGif(7, pound)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// punch 打拳
|
||||
@@ -691,7 +710,7 @@ func punch(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 13
|
||||
name := cc.usrdir + "Punch.gif"
|
||||
// name := cc.usrdir + "Punch.gif"
|
||||
c := dlrange("punch", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -714,7 +733,8 @@ func punch(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
punch[i] = imgs[i].InsertBottom(im.Image(), 0, 0, locs[i][0], locs[i][1]-15).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, punch))
|
||||
g := imgfactory.MergeGif(7, punch)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// roll 滚
|
||||
@@ -724,7 +744,7 @@ func roll(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 8
|
||||
name := cc.usrdir + "roll.gif"
|
||||
// name := cc.usrdir + "roll.gif"
|
||||
c := dlrange("roll", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -747,7 +767,8 @@ func roll(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
roll[i] = imgs[i].InsertBottomC(imgfactory.Rotate(im.Image(), float64(locs[i][2]), 0, 0).Image(), 0, 0, locs[i][0]+105, locs[i][1]+105).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, roll))
|
||||
g := imgfactory.MergeGif(7, roll)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// suck 吸 嗦
|
||||
@@ -757,7 +778,7 @@ func suck(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 12
|
||||
name := cc.usrdir + "Suck.gif"
|
||||
// name := cc.usrdir + "Suck.gif"
|
||||
c := dlrange("suck", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -780,7 +801,8 @@ func suck(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
suck[i] = imgs[i].InsertBottom(im.Image(), locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, suck))
|
||||
g := imgfactory.MergeGif(7, suck)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// hammer 锤
|
||||
@@ -790,7 +812,7 @@ func hammer(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 7
|
||||
name := cc.usrdir + "Hammer.gif"
|
||||
// name := cc.usrdir + "Hammer.gif"
|
||||
c := dlrange("hammer", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -813,7 +835,8 @@ func hammer(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
hammer[i] = imgs[i].InsertBottom(im.Image(), locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, hammer))
|
||||
g := imgfactory.MergeGif(7, hammer)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// tightly 紧贴 紧紧贴着
|
||||
@@ -823,7 +846,7 @@ func tightly(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 20
|
||||
name := cc.usrdir + "Tightly.gif"
|
||||
// name := cc.usrdir + "Tightly.gif"
|
||||
c := dlrange("tightly", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -846,13 +869,14 @@ func tightly(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
tightly[i] = imgs[i].InsertBottom(im.Image(), locs[i][2], locs[i][3], locs[i][0], locs[i][1]).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, tightly))
|
||||
g := imgfactory.MergeGif(7, tightly)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// turn 转
|
||||
func turn(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
name := cc.usrdir + "Turn.gif"
|
||||
// name := cc.usrdir + "Turn.gif"
|
||||
face, err := cc.getLogo(0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -865,7 +889,8 @@ func turn(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < 36; i++ {
|
||||
turn[i] = imgfactory.Size(canvas.Image(), 0, 0).InsertUpC(imgfactory.Rotate(face, float64(10*i), 250, 250).Image(), 0, 0, 125, 125).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, turn))
|
||||
g := imgfactory.MergeGif(7, turn)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// taiguan 抬棺
|
||||
@@ -874,7 +899,7 @@ func taiguan(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "taiguan.gif"
|
||||
// name := cc.usrdir + "taiguan.gif"
|
||||
c := dlrange("taiguan", 20, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -914,7 +939,8 @@ func taiguan(cc *context, value ...string) (string, error) {
|
||||
imgs[18].InsertUp(tou, 85, 85, 170, 65).Image(),
|
||||
imgs[19].InsertUp(tou, 85, 85, 175, 65).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, taiguan))
|
||||
g := imgfactory.MergeGif(7, taiguan)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// zou 揍
|
||||
@@ -923,7 +949,7 @@ func zou(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "zou.gif"
|
||||
// name := cc.usrdir + "zou.gif"
|
||||
c := dlrange("zou", 3, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -950,7 +976,8 @@ func zou(cc *context, value ...string) (string, error) {
|
||||
imgs[1].InsertUp(tou, 40, 40, 98, 138).InsertUp(tou2, 55, 55, 101, 45).Image(),
|
||||
imgs[2].InsertUp(tou, 40, 40, 89, 140).InsertUp(tou2, 55, 55, 99, 40).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(8, zou))
|
||||
g := imgfactory.MergeGif(8, zou)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// ci 吞
|
||||
@@ -959,7 +986,7 @@ func ci(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "ci.gif"
|
||||
// name := cc.usrdir + "ci.gif"
|
||||
c := dlrange("ci", 26, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -1005,7 +1032,8 @@ func ci(cc *context, value ...string) (string, error) {
|
||||
imgs[24].Image(),
|
||||
imgs[25].Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, ci))
|
||||
g := imgfactory.MergeGif(7, ci)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// worship 膜拜
|
||||
@@ -1014,7 +1042,7 @@ func worship(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "worship.gif"
|
||||
// name := cc.usrdir + "worship.gif"
|
||||
c := dlrange("worship", 9, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -1043,7 +1071,8 @@ func worship(cc *context, value ...string) (string, error) {
|
||||
imgs[7].InsertBottom(face, 140, 140, 0, 0).Image(),
|
||||
imgs[8].InsertBottom(face, 140, 140, 0, 0).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, worship))
|
||||
g := imgfactory.MergeGif(7, worship)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// 2ceng 2蹭
|
||||
@@ -1052,7 +1081,7 @@ func ceng2(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "ceng2.gif"
|
||||
// name := cc.usrdir + "ceng2.gif"
|
||||
c := dlrange("ceng2", 4, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -1076,7 +1105,8 @@ func ceng2(cc *context, value ...string) (string, error) {
|
||||
imgs[2].InsertBottom(tou, 175, 175, 78, 263).Image(),
|
||||
imgs[3].InsertBottom(tou, 175, 175, 78, 263).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, ceng2))
|
||||
g := imgfactory.MergeGif(7, ceng2)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// dun 炖
|
||||
@@ -1085,7 +1115,7 @@ func dun(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "dun.gif"
|
||||
// name := cc.usrdir + "dun.gif"
|
||||
c := dlrange("dun", 5, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -1110,7 +1140,8 @@ func dun(cc *context, value ...string) (string, error) {
|
||||
imgs[3].InsertBottom(tou, 80, 80, 85, 45).Image(),
|
||||
imgs[4].InsertBottom(tou, 80, 80, 85, 45).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, dun))
|
||||
g := imgfactory.MergeGif(7, dun)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// push 滚高清重置版 过渡
|
||||
@@ -1120,7 +1151,7 @@ func push(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 16
|
||||
name := cc.usrdir + "push.gif"
|
||||
// name := cc.usrdir + "push.gif"
|
||||
c := dlrange("push", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -1142,7 +1173,8 @@ func push(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
push[i] = imgs[i].InsertUpC(imgfactory.Rotate(tou, float64(-22*i), 280, 280).Image(), 0, 0, 523, 291).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, push))
|
||||
g := imgfactory.MergeGif(7, push)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// peng 砰
|
||||
@@ -1151,7 +1183,7 @@ func peng(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "peng.gif"
|
||||
// name := cc.usrdir + "peng.gif"
|
||||
c := dlrange("peng", 25, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -1200,7 +1232,8 @@ func peng(cc *context, value ...string) (string, error) {
|
||||
imgs[23].InsertUp(m4.Image(), 0, 0, 89, 159).Image(),
|
||||
imgs[24].InsertUp(m4.Image(), 0, 0, 86, 160).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(8, peng))
|
||||
g := imgfactory.MergeGif(8, peng)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// klee 可莉吃
|
||||
@@ -1210,7 +1243,7 @@ func klee(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 31
|
||||
name := cc.usrdir + "klee.gif"
|
||||
// name := cc.usrdir + "klee.gif"
|
||||
c := dlrange("klee", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -1233,7 +1266,8 @@ func klee(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
klee[i] = imgs[i].InsertBottom(im.Image(), 0, 0, locs[i][0], locs[i][1]).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, klee))
|
||||
g := imgfactory.MergeGif(7, klee)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// hutaoken 胡桃啃
|
||||
@@ -1242,7 +1276,7 @@ func hutaoken(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "hutaoken.gif"
|
||||
// name := cc.usrdir + "hutaoken.gif"
|
||||
c := dlrange("hutaoken", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -1264,7 +1298,8 @@ func hutaoken(cc *context, value ...string) (string, error) {
|
||||
imgs[0].InsertBottom(tou, 98, 101, 108, 234).Image(),
|
||||
imgs[1].InsertBottom(tou, 96, 100, 108, 237).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(8, hutaoken))
|
||||
g := imgfactory.MergeGif(8, hutaoken)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// lick 2舔
|
||||
@@ -1273,7 +1308,7 @@ func lick(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "lick.gif"
|
||||
// name := cc.usrdir + "lick.gif"
|
||||
c := dlrange("lick", 2, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -1295,7 +1330,8 @@ func lick(cc *context, value ...string) (string, error) {
|
||||
imgs[0].InsertUp(tou, 44, 44, 10, 138).Image(),
|
||||
imgs[1].InsertUp(tou, 44, 44, 10, 138).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(8, lick))
|
||||
g := imgfactory.MergeGif(8, lick)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// tiqiu 踢球
|
||||
@@ -1305,7 +1341,7 @@ func tiqiu(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 15
|
||||
name := cc.usrdir + "tiqiu.gif"
|
||||
// name := cc.usrdir + "tiqiu.gif"
|
||||
c := dlrange("tiqiu", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -1328,7 +1364,8 @@ func tiqiu(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
tiqiu[i] = imgs[i].InsertUpC(imgfactory.Rotate(tou, float64(-24*i), 0, 0).Image(), 0, 0, locs[i][0]+38, locs[i][1]+38).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, tiqiu))
|
||||
g := imgfactory.MergeGif(7, tiqiu)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// cai 踩
|
||||
@@ -1337,7 +1374,7 @@ func cai(cc *context, value ...string) (string, error) {
|
||||
var wg sync.WaitGroup
|
||||
var errwg error
|
||||
var m sync.Mutex
|
||||
name := cc.usrdir + "cai.gif"
|
||||
// name := cc.usrdir + "cai.gif"
|
||||
c := dlrange("cai", 5, &wg, func(e error) {
|
||||
m.Lock()
|
||||
errwg = e
|
||||
@@ -1363,7 +1400,8 @@ func cai(cc *context, value ...string) (string, error) {
|
||||
imgs[3].InsertBottom(tou, 85, 76, 52, 203).Image(),
|
||||
imgs[4].InsertBottom(tou, 88, 82, 49, 198).Image(),
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, cai))
|
||||
g := imgfactory.MergeGif(7, cai)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// whir 2转
|
||||
@@ -1373,7 +1411,7 @@ func whirl(cc *context, value ...string) (string, error) {
|
||||
var err error
|
||||
var m sync.Mutex
|
||||
piclen := 15
|
||||
name := cc.usrdir + "whirl.gif"
|
||||
// name := cc.usrdir + "whirl.gif"
|
||||
c := dlrange("whirl", piclen, &wg, func(e error) {
|
||||
m.Lock()
|
||||
err = e
|
||||
@@ -1395,7 +1433,8 @@ func whirl(cc *context, value ...string) (string, error) {
|
||||
for i := 0; i < piclen; i++ {
|
||||
whirl[i] = imgs[i].InsertUpC(imgfactory.Rotate(tou, float64(-24*i), 145, 145).Image(), 0, 0, 115, 89).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(7, whirl))
|
||||
g := imgfactory.MergeGif(7, whirl)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
// always 一直
|
||||
@@ -1403,8 +1442,8 @@ func alwaysDoGif(cc *context, value ...string) (string, error) {
|
||||
_ = value
|
||||
var err error
|
||||
var face []*imgfactory.Factory
|
||||
name := cc.usrdir + "AlwaysDo.gif"
|
||||
face, err = imgfactory.LoadAllFrames(cc.headimgsdir[0], 500, 500)
|
||||
// name := cc.usrdir + "AlwaysDo.gif"
|
||||
face, err = imgfactory.LoadAllTrueFrames(cc.headimgsdir[0], 500, 500)
|
||||
if err != nil {
|
||||
// 载入失败尝试载入第一帧
|
||||
face = nil
|
||||
@@ -1438,11 +1477,12 @@ func alwaysDoGif(cc *context, value ...string) (string, error) {
|
||||
canvas := gg.NewContext(500, 600)
|
||||
canvas.DrawImage(f.Image(), 0, 0)
|
||||
canvas.SetColor(color.Black)
|
||||
// _ = canvas.ParseFontFace(data, 40)
|
||||
_ = canvas.ParseFontFace(data, 40)
|
||||
canvas.DrawString(arg, 280-l, 560)
|
||||
canvas.DrawImage(imgfactory.Size(f.Image(), 90, 90).Image(), 280, 505)
|
||||
canvas.DrawString("吗", 370, 560)
|
||||
turn[i] = imgfactory.Size(canvas.Image(), 0, 0).Image()
|
||||
}
|
||||
return "file:///" + name, imgfactory.SaveGIF2Path(name, imgfactory.MergeGif(8, turn))
|
||||
g := imgfactory.MergeGif(8, turn)
|
||||
return imgfactory.GIF2Base64(g)
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ func init() { // 插件主体
|
||||
for k := range cmdMap {
|
||||
cmd = append(cmd, k)
|
||||
}
|
||||
en := control.Register("gif", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "制图",
|
||||
Help: "下为制图命令:\n" +
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
control.Register("github", &ctrl.Options[*zero.Ctx]{
|
||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "GitHub仓库搜索",
|
||||
Help: "- >github [xxx]\n" +
|
||||
|
||||
@@ -11,16 +11,28 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/pkg/errors"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
|
||||
"github.com/liuzl/gocc"
|
||||
)
|
||||
|
||||
var cuttime = [...]string{"00:00:05", "00:00:30", "00:01:00"} // 音乐切割时间点,可自行调节时间(时:分:秒)
|
||||
var t2s *gocc.OpenCC
|
||||
|
||||
func init() {
|
||||
// 初始化简繁体转换变量
|
||||
var err1 error
|
||||
t2s, err1 = gocc.New("t2s")
|
||||
if err1 != nil {
|
||||
log.Infof("[guessmusic]:%s", err1)
|
||||
}
|
||||
|
||||
engine.OnRegex(`^(个人|团队)猜歌(-(.*))?$`, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
mode := ctx.State["regex_matched"].([]string)[3]
|
||||
@@ -283,6 +295,11 @@ func cutMusic(musicName, pathOfMusic, outputPath string) (err error) {
|
||||
// 数据匹配(结果信息,答题次数,提示次数,是否结束游戏)
|
||||
func gameMatch(c *zero.Ctx, beginner int64, musicInfo []string, answerTimes, tickTimes int) (message.MessageSegment, int, int, bool) {
|
||||
answer := strings.Replace(c.Event.Message.String(), "-", "", 1)
|
||||
// 大小写,简繁体转换
|
||||
answer = ConvertText(answer)
|
||||
for i, element := range musicInfo {
|
||||
musicInfo[i] = ConvertText(element)
|
||||
}
|
||||
switch {
|
||||
case answer == "取消":
|
||||
if c.Event.UserID == beginner {
|
||||
@@ -314,3 +331,15 @@ func gameMatch(c *zero.Ctx, beginner int64, musicInfo []string, answerTimes, tic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertText 将传入字符串中的英文转为小写,繁体中文转为简体中文
|
||||
func ConvertText(input string) string {
|
||||
// 将字符串中的英文转为小写
|
||||
toLower := strings.ToLower(input)
|
||||
toLower, err := t2s.Convert(toLower)
|
||||
if err != nil {
|
||||
message.Text("简繁转换失败")
|
||||
return toLower
|
||||
}
|
||||
return toLower
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ var (
|
||||
// 用户数据
|
||||
cfg config
|
||||
// 插件主体
|
||||
engine = control.Register("guessmusic", &ctrl.Options[*zero.Ctx]{
|
||||
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "猜歌插件",
|
||||
Help: "------bot主人指令------\n" +
|
||||
@@ -527,7 +527,7 @@ func getlist(pathOfMusic string) (list []listinfo, err error) {
|
||||
|
||||
// 遍历群文件
|
||||
func getFileURLbyFileName(ctx *zero.Ctx, fileName string) (fileSearchName, fileURL string) {
|
||||
filesOfGroup := ctx.GetThisGroupRootFiles(ctx.Event.GroupID)
|
||||
filesOfGroup := ctx.GetThisGroupRootFiles()
|
||||
files := filesOfGroup.Get("files").Array()
|
||||
folders := filesOfGroup.Get("folders").Array()
|
||||
// 遍历当前目录的文件名
|
||||
|
||||
@@ -241,9 +241,9 @@ type listInfoOfAPI struct {
|
||||
PublishTime int64 `json:"publishTime"`
|
||||
Tns []string `json:"tns,omitempty"`
|
||||
} `json:"tracks"`
|
||||
VideoIds interface{} `json:"videoIds"`
|
||||
VideoIDs interface{} `json:"videoIds"`
|
||||
Videos interface{} `json:"videos"`
|
||||
TrackIds []struct {
|
||||
TrackIDs []struct {
|
||||
ID int `json:"id"`
|
||||
V int `json:"v"`
|
||||
T int `json:"t"`
|
||||
|
||||
@@ -66,7 +66,7 @@ func init() { // 插件主体
|
||||
panic(err)
|
||||
}
|
||||
|
||||
engine := control.Register("heisi", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "黑丝",
|
||||
Help: "- 来点黑丝\n- 来点白丝\n- 来点jk\n- 来点巨乳\n- 来点足控\n- 来点网红",
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("hitokoto", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "一言",
|
||||
Help: "- 一言[xxx]\n" +
|
||||
|
||||
@@ -41,7 +41,7 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("hs", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "炉石搜卡",
|
||||
Help: "- 搜卡[xxxx]\n" +
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const bed = "https://gitcode.net/u011570312/OguraHyakuninIsshu/-/raw/master/"
|
||||
const bed = "https://gitea.seku.su/fumiama/OguraHyakuninIsshu/raw/branch/master/"
|
||||
|
||||
type line struct {
|
||||
番号, 歌人, 上の句, 下の句, 上の句ひらがな, 下の句ひらがな string
|
||||
@@ -51,7 +51,7 @@ func (l *line) String() string {
|
||||
var lines [100]*line
|
||||
|
||||
func init() {
|
||||
engine := control.Register("hyaku", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "百人一首",
|
||||
Help: "- 百人一首(随机发一首)\n" +
|
||||
|
||||
@@ -62,7 +62,7 @@ type resultjson struct {
|
||||
var hrefre = regexp.MustCompile(`<a href=".*">`)
|
||||
|
||||
func init() {
|
||||
control.Register("imgfinder", &ctrl.Options[*zero.Ctx]{
|
||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "关键字搜图",
|
||||
Help: "- 来张 [xxx]",
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("inject", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "注入指令",
|
||||
Help: "- run[CQ码]",
|
||||
|
||||
@@ -23,7 +23,7 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("jandan", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "煎蛋网无聊图",
|
||||
Help: "- 来份[屌|弔|吊]图\n- 更新[屌|弔|吊]图\n",
|
||||
@@ -33,7 +33,7 @@ func init() {
|
||||
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
db.DBPath = engine.DataFolder() + "pics.db"
|
||||
_, _ = engine.GetLazyData("pics.db", false)
|
||||
err := db.Open(time.Hour * 24)
|
||||
err := db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
jiami1 = "http://ovooa.com/API/sho_u/?msg=%v" // 加密api地址
|
||||
jiami2 = "http://ovooa.com/API/sho_u/?format=1&msg=%v" // 解密api地址
|
||||
jiami1 = "http://ovooa.caonm.net/API/sho_u/?msg=%v" // 加密api地址
|
||||
jiami2 = "http://ovooa.caonm.net/API/sho_u/?format=1&msg=%v" // 解密api地址
|
||||
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ type nmd struct { // struct解析格式大概是
|
||||
}
|
||||
|
||||
func init() { // 主函数
|
||||
en := control.Register("jiami", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "兽语加解密",
|
||||
Help: "兽语加解密\n" +
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("jptingroom", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "日语听力学习材料",
|
||||
Help: "- 随机日语听力\n" +
|
||||
@@ -32,7 +32,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
err = db.Open(time.Hour * 24)
|
||||
err = db.Open(time.Hour)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
|
||||
@@ -23,7 +23,7 @@ const (
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("juejuezi", &ctrl.Options[*zero.Ctx]{
|
||||
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "绝绝子生成器",
|
||||
Help: "例: 喝奶茶绝绝子\n绝绝子吃饭",
|
||||
|
||||
@@ -2,20 +2,20 @@
|
||||
package kfccrazythursday
|
||||
|
||||
import (
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
crazyURL = "https://www.iculture.cc/demo/CrazyThursday/api/kfc.php"
|
||||
crazyURL = "https://api.jixs.cc/api/wenan-fkxqs/index.php"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("kfccrazythursday", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "疯狂星期四",
|
||||
Help: "疯狂星期四\n",
|
||||
@@ -26,6 +26,6 @@ func init() {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text(gjson.ParseBytes(data).Get("@this.0.content").String()))
|
||||
ctx.SendChain(message.Text(binary.BytesToString(data)))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
en := control.Register("lolicon", &ctrl.Options[*zero.Ctx]{
|
||||
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "随机图片",
|
||||
Help: "- 随机图片\n" +
|
||||
@@ -115,5 +115,5 @@ func getimgurl(url string) (string, error) {
|
||||
if imageurl = json.Get("data.0.urls.original").Str; imageurl == "" {
|
||||
return "", errors.New("未找到相关内容, 换个tag试试吧")
|
||||
}
|
||||
return strings.ReplaceAll(imageurl, "i.pixiv.cat", "i.pixiv.re"), nil
|
||||
return imageurl, nil
|
||||
}
|
||||
|
||||
112
plugin/lolimi/lolimi.go
Normal file
112
plugin/lolimi/lolimi.go
Normal file
@@ -0,0 +1,112 @@
|
||||
// Package lolimi 来源于 https://api.lolimi.cn/ 的接口
|
||||
package lolimi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/tts/lolimi"
|
||||
"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/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
lolimiURL = "https://api.lolimi.cn"
|
||||
raoURL = lolimiURL + "/API/rao/api.php"
|
||||
yanURL = lolimiURL + "/API/yan/?url=%v"
|
||||
xjjURL = lolimiURL + "/API/tup/xjj.php"
|
||||
qingURL = lolimiURL + "/API/qing/api.php"
|
||||
fabingURL = lolimiURL + "/API/fabing/fb.php?name=%v"
|
||||
)
|
||||
|
||||
var (
|
||||
engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "桑帛云 API",
|
||||
Help: "- 让[嘉然|塔菲|东雪莲|懒羊羊|科比|孙笑川|陈泽|丁真|空|荧|派蒙|纳西妲|阿贝多|温迪|枫原万叶|钟离|荒泷一斗|八重神子|艾尔海森|提纳里|迪希雅|卡维|宵宫|莱依拉|赛诺|诺艾尔|托马|凝光|莫娜|北斗|神里绫华|雷电将军|芭芭拉|鹿野院平藏|五郎|迪奥娜|凯亚|安柏|班尼特|琴|柯莱|夜兰|妮露|辛焱|珐露珊|魈|香菱|达达利亚|砂糖|早柚|云堇|刻晴|丽莎|迪卢克|烟绯|重云|珊瑚宫心海|胡桃|可莉|流浪者|久岐忍|神里绫人|甘雨|戴因斯雷布|优菈|菲谢尔|行秋|白术|九条裟罗|雷泽|申鹤|迪娜泽黛|凯瑟琳|多莉|坎蒂丝|萍姥姥|罗莎莉亚|留云借风真君|绮良良|瑶瑶|七七|奥兹|米卡|夏洛蒂|埃洛伊|博士|女士|大慈树王|三月七|娜塔莎|希露瓦|虎克|克拉拉|丹恒|希儿|布洛妮娅|瓦尔特|杰帕德|佩拉|姬子|艾丝妲|白露|星|穹|桑博|伦纳德|停云|罗刹|卡芙卡|彦卿|史瓦罗|螺丝咕姆|阿兰|银狼|素裳|丹枢|黑塔|景元|帕姆|可可利亚|半夏|符玄|公输师傅|奥列格|青雀|大毫|青镞|费斯曼|绿芙蓉|镜流|信使|丽塔|失落迷迭|缭乱星棘|伊甸|伏特加女孩|狂热蓝调|莉莉娅|萝莎莉娅|八重樱|八重霞|卡莲|第六夜想曲|卡萝尔|姬子|极地战刃|布洛妮娅|次生银翼|理之律者|真理之律者|迷城骇兔|希儿|魇夜星渊|黑希儿|帕朵菲莉丝|天元骑英|幽兰黛尔|德丽莎|月下初拥|朔夜观星|暮光骑士|明日香|李素裳|格蕾修|梅比乌斯|渡鸦|人之律者|爱莉希雅|爱衣|天穹游侠|琪亚娜|空之律者|终焉之律者|薪炎之律者|云墨丹心|符华|识之律者|维尔薇|始源之律者|芽衣|雷之律者|苏莎娜|阿波尼亚|陆景和|莫弈|夏彦|左然]说我测尼玛\n- 随机绕口令\n- 颜值鉴定[图片]\n" +
|
||||
"- 随机妹子\n- 随机情话\n- 发病 嘉然\n\n说明: 颜值鉴定只能鉴定三次元图片",
|
||||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine.OnFullMatch("随机妹子").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Image(xjjURL))
|
||||
})
|
||||
engine.OnFullMatch("随机绕口令").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
data, err := web.GetData(raoURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(gjson.Get(binary.BytesToString(data), "data.Msg").String()))
|
||||
})
|
||||
engine.OnFullMatch("随机情话").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
data, err := web.GetData(qingURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(binary.BytesToString(data)))
|
||||
})
|
||||
engine.OnPrefix(`发病`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
name := ctx.NickName()
|
||||
data, err := web.GetData(fmt.Sprintf(fabingURL, url.QueryEscape(name)))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(gjson.Get(binary.BytesToString(data), "data").String()))
|
||||
})
|
||||
engine.OnKeywordGroup([]string{"颜值鉴定"}, zero.MustProvidePicture).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
list := ctx.State["image_url"].([]string)
|
||||
if len(list) > 0 {
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
data, err := web.GetData(fmt.Sprintf(yanURL, url.QueryEscape(list[0])))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
assessment := gjson.Get(binary.BytesToString(data), "data.text").String()
|
||||
if assessment == "" {
|
||||
ctx.SendChain(message.Text("ERROR: 请输入正确的图片"))
|
||||
return
|
||||
}
|
||||
var text strings.Builder // 创建一个strings.Builder实例
|
||||
text.WriteString("评价: ")
|
||||
text.WriteString(assessment) // 添加评估信息
|
||||
|
||||
for i := 0; i <= 2; i++ {
|
||||
key := gjson.Get(binary.BytesToString(data), "data.grade.key"+strconv.Itoa(i)).String()
|
||||
score := gjson.Get(binary.BytesToString(data), "data.grade.score"+strconv.Itoa(i)).String()
|
||||
if key != "" {
|
||||
text.WriteString("\n")
|
||||
text.WriteString(key)
|
||||
text.WriteString(": ")
|
||||
text.WriteString(score)
|
||||
}
|
||||
}
|
||||
|
||||
ctx.SendChain(message.Text(text.String())) // 发送构建好的字符串
|
||||
}
|
||||
})
|
||||
engine.OnRegex("^让(嘉然|塔菲|东雪莲|懒羊羊|科比|孙笑川|陈泽|丁真|空|荧|派蒙|纳西妲|阿贝多|温迪|枫原万叶|钟离|荒泷一斗|八重神子|艾尔海森|提纳里|迪希雅|卡维|宵宫|莱依拉|赛诺|诺艾尔|托马|凝光|莫娜|北斗|神里绫华|雷电将军|芭芭拉|鹿野院平藏|五郎|迪奥娜|凯亚|安柏|班尼特|琴|柯莱|夜兰|妮露|辛焱|珐露珊|魈|香菱|达达利亚|砂糖|早柚|云堇|刻晴|丽莎|迪卢克|烟绯|重云|珊瑚宫心海|胡桃|可莉|流浪者|久岐忍|神里绫人|甘雨|戴因斯雷布|优菈|菲谢尔|行秋|白术|九条裟罗|雷泽|申鹤|迪娜泽黛|凯瑟琳|多莉|坎蒂丝|萍姥姥|罗莎莉亚|留云借风真君|绮良良|瑶瑶|七七|奥兹|米卡|夏洛蒂|埃洛伊|博士|女士|大慈树王|三月七|娜塔莎|希露瓦|虎克|克拉拉|丹恒|希儿|布洛妮娅|瓦尔特|杰帕德|佩拉|姬子|艾丝妲|白露|星|穹|桑博|伦纳德|停云|罗刹|卡芙卡|彦卿|史瓦罗|螺丝咕姆|阿兰|银狼|素裳|丹枢|黑塔|景元|帕姆|可可利亚|半夏|符玄|公输师傅|奥列格|青雀|大毫|青镞|费斯曼|绿芙蓉|镜流|信使|丽塔|失落迷迭|缭乱星棘|伊甸|伏特加女孩|狂热蓝调|莉莉娅|萝莎莉娅|八重樱|八重霞|卡莲|第六夜想曲|卡萝尔|姬子|极地战刃|布洛妮娅|次生银翼|理之律者|真理之律者|迷城骇兔|希儿|魇夜星渊|黑希儿|帕朵菲莉丝|天元骑英|幽兰黛尔|德丽莎|月下初拥|朔夜观星|暮光骑士|明日香|李素裳|格蕾修|梅比乌斯|渡鸦|人之律者|爱莉希雅|爱衣|天穹游侠|琪亚娜|空之律者|终焉之律者|薪炎之律者|云墨丹心|符华|识之律者|维尔薇|始源之律者|芽衣|雷之律者|苏莎娜|阿波尼亚|陆景和|莫弈|夏彦|左然)说([\\s\u4e00-\u9fa5\u3040-\u309F\u30A0-\u30FF\\w\\p{P}\u3000-\u303F\uFF00-\uFFEF]+)$").Limit(ctxext.LimitByGroup).Handle(func(ctx *zero.Ctx) {
|
||||
name := ctx.State["regex_matched"].([]string)[1]
|
||||
msg := ctx.State["regex_matched"].([]string)[2]
|
||||
ctx.SendChain(message.Text("少女祈祷中......"))
|
||||
recordURL, err := lolimi.TTS(name, msg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Record(recordURL))
|
||||
})
|
||||
}
|
||||
@@ -23,7 +23,7 @@ const (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("magicprompt", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "MagicPrompt-Stable-Diffusion吟唱提示",
|
||||
Help: "- 吟唱提示 xxx",
|
||||
|
||||
@@ -47,6 +47,7 @@ const (
|
||||
"- 取消在\"cron\"的提醒\n" +
|
||||
"- 列出所有提醒\n" +
|
||||
"- 翻牌\n" +
|
||||
"- 赞我\n" +
|
||||
"- 设置欢迎语XXX 可选添加 [{at}] [{nickname}] [{avatar}] [{uid}] [{gid}] [{groupname}]\n" +
|
||||
"- 测试欢迎语\n" +
|
||||
"- 设置告别辞 参数同设置欢迎语\n" +
|
||||
@@ -64,7 +65,7 @@ var (
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("manager", &ctrl.Options[*zero.Ctx]{
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "群管插件",
|
||||
Help: hint,
|
||||
@@ -73,7 +74,7 @@ func init() { // 插件主体
|
||||
|
||||
go func() {
|
||||
db.DBPath = engine.DataFolder() + "config.db"
|
||||
err := db.Open(time.Hour * 24)
|
||||
err := db.Open(time.Hour)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -95,13 +96,11 @@ func init() { // 插件主体
|
||||
// 升为管理
|
||||
engine.OnRegex(`^升为管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupAdmin(
|
||||
ctx.Event.GroupID,
|
||||
ctx.SetThisGroupAdmin(
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
|
||||
true,
|
||||
)
|
||||
nickname := ctx.GetGroupMemberInfo( // 被升为管理的人的昵称
|
||||
ctx.Event.GroupID,
|
||||
nickname := ctx.GetThisGroupMemberInfo( // 被升为管理的人的昵称
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被升为管理的人的qq
|
||||
false,
|
||||
).Get("nickname").Str
|
||||
@@ -110,13 +109,11 @@ func init() { // 插件主体
|
||||
// 取消管理
|
||||
engine.OnRegex(`^取消管理.*?(\d+)`, zero.OnlyGroup, zero.SuperUserPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupAdmin(
|
||||
ctx.Event.GroupID,
|
||||
ctx.SetThisGroupAdmin(
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
|
||||
false,
|
||||
)
|
||||
nickname := ctx.GetGroupMemberInfo( // 被取消管理的人的昵称
|
||||
ctx.Event.GroupID,
|
||||
nickname := ctx.GetThisGroupMemberInfo( // 被取消管理的人的昵称
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被取消管理的人的qq
|
||||
false,
|
||||
).Get("nickname").Str
|
||||
@@ -125,13 +122,11 @@ func init() { // 插件主体
|
||||
// 踢出群聊
|
||||
engine.OnRegex(`^踢出群聊.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupKick(
|
||||
ctx.Event.GroupID,
|
||||
ctx.SetThisGroupKick(
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
|
||||
false,
|
||||
)
|
||||
nickname := ctx.GetGroupMemberInfo( // 被踢出群聊的人的昵称
|
||||
ctx.Event.GroupID,
|
||||
nickname := ctx.GetThisGroupMemberInfo( // 被踢出群聊的人的昵称
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被踢出群聊的人的qq
|
||||
false,
|
||||
).Get("nickname").Str
|
||||
@@ -148,19 +143,13 @@ func init() { // 插件主体
|
||||
// 开启全体禁言
|
||||
engine.OnRegex(`^开启全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupWholeBan(
|
||||
ctx.Event.GroupID,
|
||||
true,
|
||||
)
|
||||
ctx.SetThisGroupWholeBan(true)
|
||||
ctx.SendChain(message.Text("全员自闭开始~"))
|
||||
})
|
||||
// 解除全员禁言
|
||||
engine.OnRegex(`^解除全员禁言$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupWholeBan(
|
||||
ctx.Event.GroupID,
|
||||
false,
|
||||
)
|
||||
ctx.SetThisGroupWholeBan(false)
|
||||
ctx.SendChain(message.Text("全员自闭结束~"))
|
||||
})
|
||||
// 禁言
|
||||
@@ -180,8 +169,7 @@ func init() { // 插件主体
|
||||
if duration >= 43200 {
|
||||
duration = 43199 // qq禁言最大时长为一个月
|
||||
}
|
||||
ctx.SetGroupBan(
|
||||
ctx.Event.GroupID,
|
||||
ctx.SetThisGroupBan(
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 要禁言的人的qq
|
||||
duration*60, // 要禁言的时间(分钟)
|
||||
)
|
||||
@@ -190,8 +178,7 @@ func init() { // 插件主体
|
||||
// 解除禁言
|
||||
engine.OnRegex(`^解除禁言.*?(\d+)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SetGroupBan(
|
||||
ctx.Event.GroupID,
|
||||
ctx.SetThisGroupBan(
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 要解除禁言的人的qq
|
||||
0,
|
||||
)
|
||||
@@ -214,8 +201,7 @@ func init() { // 插件主体
|
||||
if duration >= 43200 {
|
||||
duration = 43199 // qq禁言最大时长为一个月
|
||||
}
|
||||
ctx.SetGroupBan(
|
||||
ctx.Event.GroupID,
|
||||
ctx.SetThisGroupBan(
|
||||
ctx.Event.UserID,
|
||||
duration*60, // 要自闭的时间(分钟)
|
||||
)
|
||||
@@ -228,8 +214,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("名字太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupCard(
|
||||
ctx.Event.GroupID,
|
||||
ctx.SetThisGroupCard(
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群名片的人
|
||||
ctx.State["regex_matched"].([]string)[2], // 修改成的群名片
|
||||
)
|
||||
@@ -246,8 +231,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("头衔太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupSpecialTitle(
|
||||
ctx.Event.GroupID,
|
||||
ctx.SetThisGroupSpecialTitle(
|
||||
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
|
||||
sptitle, // 修改成的群头衔
|
||||
)
|
||||
@@ -264,8 +248,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("头衔太长啦!"))
|
||||
return
|
||||
}
|
||||
ctx.SetGroupSpecialTitle(
|
||||
ctx.Event.GroupID,
|
||||
ctx.SetThisGroupSpecialTitle(
|
||||
ctx.Event.UserID, // 被修改群头衔的人
|
||||
sptitle, // 修改成的群头衔
|
||||
)
|
||||
@@ -402,6 +385,24 @@ func init() { // 插件主体
|
||||
),
|
||||
)
|
||||
})
|
||||
// 给好友点赞
|
||||
engine.OnFullMatch("赞我").SetBlock(true).Limit(ctxext.LimitByUser).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
list := ctx.GetFriendList().Array()
|
||||
flag := false
|
||||
for _, v := range list {
|
||||
if ctx.Event.UserID == v.Get("user_id").Int() {
|
||||
flag = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !flag {
|
||||
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下哦,记得回我~"))
|
||||
})
|
||||
// 入群欢迎
|
||||
engine.OnNotice().SetBlock(false).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
@@ -445,7 +446,7 @@ func init() { // 插件主体
|
||||
case <-time.After(time.Minute):
|
||||
cancel()
|
||||
ctx.SendChain(message.Text("拜拜啦~"))
|
||||
ctx.SetGroupKick(ctx.Event.GroupID, uid, false)
|
||||
ctx.SetThisGroupKick(uid, false)
|
||||
case <-recv:
|
||||
cancel()
|
||||
ctx.SendChain(message.Text("答对啦~"))
|
||||
@@ -594,7 +595,7 @@ func init() { // 插件主体
|
||||
if ok {
|
||||
ctx.SetGroupAddRequest(ctx.Event.Flag, "add", true, "")
|
||||
process.SleepAbout1sTo2s()
|
||||
ctx.SetGroupCard(ctx.Event.GroupID, ctx.Event.UserID, ghun)
|
||||
ctx.SetThisGroupCard(ctx.Event.UserID, ghun)
|
||||
} else {
|
||||
ctx.SetGroupAddRequest(ctx.Event.Flag, "add", false, reason)
|
||||
}
|
||||
@@ -618,7 +619,7 @@ func init() { // 插件主体
|
||||
}
|
||||
})
|
||||
engine.OnCommand("精华列表", zero.OnlyGroup, zero.AdminPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
list := ctx.GetGroupEssenceMessageList(ctx.Event.GroupID).Array()
|
||||
list := ctx.GetThisGroupEssenceMessageList().Array()
|
||||
msg := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text("本群精华列表:"))}
|
||||
n := len(list)
|
||||
if n > 30 {
|
||||
@@ -675,7 +676,7 @@ func welcometocq(ctx *zero.Ctx, welcome string) string {
|
||||
at := "[CQ:at,qq=" + uid + "]" // at用户
|
||||
avatar := "[CQ:image,file=" + "http://q4.qlogo.cn/g?b=qq&nk=" + uid + "&s=640]" // 用户头像
|
||||
gid := strconv.FormatInt(ctx.Event.GroupID, 10) // 群id
|
||||
groupname := ctx.GetGroupInfo(ctx.Event.GroupID, true).Name // 群名
|
||||
groupname := ctx.GetThisGroupInfo(true).Name // 群名
|
||||
cqstring := strings.ReplaceAll(welcome, "{at}", at)
|
||||
cqstring = strings.ReplaceAll(cqstring, "{nickname}", nickname)
|
||||
cqstring = strings.ReplaceAll(cqstring, "{avatar}", avatar)
|
||||
|
||||
@@ -155,7 +155,7 @@ func (t *Timer) judgeHM() {
|
||||
if t.SelfID != 0 {
|
||||
t.sendmsg(t.GrpID, zero.GetBot(t.SelfID))
|
||||
} else {
|
||||
zero.RangeBot(func(id int64, ctx *zero.Ctx) (_ bool) {
|
||||
zero.RangeBot(func(_ int64, ctx *zero.Ctx) (_ bool) {
|
||||
t.sendmsg(t.GrpID, ctx)
|
||||
return
|
||||
})
|
||||
|
||||
370
plugin/mcfish/fish.go
Normal file
370
plugin/mcfish/fish.go
Normal file
@@ -0,0 +1,370 @@
|
||||
// Package mcfish 钓鱼模拟器
|
||||
package mcfish
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/wallet"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine.OnRegex(`^进行(([1-5]\d|[1-9])次)?钓鱼$`, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
numberOfPole, err := dbdata.getNumberFor(uid, "竿")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.9.3]:", err))
|
||||
return
|
||||
}
|
||||
if numberOfPole > 30 {
|
||||
ctx.SendChain(message.Text("你有", numberOfPole, "支鱼竿,大于30支的玩家不允许钓鱼"))
|
||||
return
|
||||
}
|
||||
fishNumber := 1
|
||||
info := ctx.State["regex_matched"].([]string)[2]
|
||||
if info != "" {
|
||||
number, err := strconv.Atoi(info)
|
||||
if err != nil || number > FishLimit {
|
||||
ctx.SendChain(message.Text("请输入正确的次数"))
|
||||
return
|
||||
}
|
||||
fishNumber = number
|
||||
}
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.2]:", err))
|
||||
return
|
||||
}
|
||||
if equipInfo == (equip{}) {
|
||||
ok, err := dbdata.checkEquipFor(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.2.1]:", err))
|
||||
return
|
||||
}
|
||||
if !ok {
|
||||
ctx.SendChain(message.At(uid), message.Text("请装备鱼竿后钓鱼", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你尚未装备鱼竿,是否花费100购买鱼竿?\n回答\"是\"或\"否\""))
|
||||
// 等待用户下一步选择
|
||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(是|否)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel()
|
||||
buy := false
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
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
|
||||
}
|
||||
money := wallet.GetWalletOf(uid)
|
||||
if money < 100 {
|
||||
ctx.SendChain(message.Text("你钱包当前只有", money, "ATRI币,无法完成支付"))
|
||||
return
|
||||
}
|
||||
err = wallet.InsertWalletOf(uid, -100)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.3]:", err))
|
||||
return
|
||||
}
|
||||
equipInfo = equip{
|
||||
ID: uid,
|
||||
Equip: "木竿",
|
||||
Durable: 30,
|
||||
}
|
||||
err = dbdata.updateUserEquip(equipInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.4]:", err))
|
||||
return
|
||||
}
|
||||
err = dbdata.setEquipFor(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.4]:", err))
|
||||
return
|
||||
}
|
||||
buy = true
|
||||
}
|
||||
if buy {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if equipInfo.Durable < fishNumber {
|
||||
fishNumber = equipInfo.Durable
|
||||
}
|
||||
residue, err := dbdata.updateFishInfo(uid, fishNumber)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.1]:", err))
|
||||
return
|
||||
}
|
||||
if residue == 0 {
|
||||
ctx.SendChain(message.Text("今天你已经进行", FishLimit, "次钓鱼了.\n游戏虽好,但请不要沉迷。"))
|
||||
return
|
||||
}
|
||||
fishNumber = residue
|
||||
msg := ""
|
||||
if equipInfo.Equip != "美西螈" {
|
||||
equipInfo.Durable -= fishNumber
|
||||
err = dbdata.updateUserEquip(equipInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5]:", err))
|
||||
return
|
||||
}
|
||||
if equipInfo.Durable < 10 && equipInfo.Durable > 0 {
|
||||
msg = "(你的鱼竿耐久仅剩" + strconv.Itoa(equipInfo.Durable) + ")"
|
||||
} else if equipInfo.Durable <= 0 {
|
||||
msg = "(你的鱼竿已销毁)"
|
||||
}
|
||||
if equipInfo.Equip == "三叉戟" {
|
||||
fishNumber *= 3
|
||||
}
|
||||
} else {
|
||||
fishNmaes, err := dbdata.pickFishFor(uid, fishNumber)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5.1]:", err))
|
||||
return
|
||||
}
|
||||
if len(fishNmaes) == 0 {
|
||||
equipInfo.Durable = 0
|
||||
err = dbdata.updateUserEquip(equipInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5]:", err))
|
||||
}
|
||||
ctx.SendChain(message.Text("美西螈因为没吃到鱼,钓鱼时一直没回来,你失去了美西螈"))
|
||||
return
|
||||
}
|
||||
msg = "(美西螈吃掉了"
|
||||
fishNumber = 0
|
||||
for name, number := range fishNmaes {
|
||||
fishNumber += number
|
||||
msg += strconv.Itoa(number) + name + "、"
|
||||
}
|
||||
msg += ")"
|
||||
fishNumber /= 2
|
||||
}
|
||||
waitTime := 120 / (equipInfo.Induce + 1)
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你开始去钓鱼了,请耐心等待鱼上钩(预计要", time.Second*time.Duration(waitTime), ")"))
|
||||
timer := time.NewTimer(time.Second * time.Duration(rand.Intn(waitTime)+1))
|
||||
for {
|
||||
<-timer.C
|
||||
timer.Stop()
|
||||
break
|
||||
}
|
||||
// 钓到鱼的范围
|
||||
number, err := dbdata.getNumberFor(uid, "鱼")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5.1]:", err))
|
||||
return
|
||||
}
|
||||
number2, err := dbdata.getNumberFor(uid, "海豚")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5.1]:", err))
|
||||
return
|
||||
}
|
||||
if number > 100 || equipInfo.Equip == "美西螈" { // 放大概率
|
||||
probabilities["treasure"] = probabilityLimit{
|
||||
Min: 0,
|
||||
Max: 2,
|
||||
}
|
||||
probabilities["pole"] = probabilityLimit{
|
||||
Min: 2,
|
||||
Max: 10,
|
||||
}
|
||||
probabilities["fish"] = probabilityLimit{
|
||||
Min: 10,
|
||||
Max: 45,
|
||||
}
|
||||
probabilities["waste"] = probabilityLimit{
|
||||
Min: 45,
|
||||
Max: 90,
|
||||
}
|
||||
}
|
||||
if number2 != 0 {
|
||||
info := probabilities["waste"]
|
||||
info.Max = 100
|
||||
probabilities["waste"] = info
|
||||
}
|
||||
for name, info := range probabilities {
|
||||
switch name {
|
||||
case "treasure":
|
||||
info.Max += equipInfo.Favor
|
||||
probabilities[name] = info
|
||||
case "pole":
|
||||
info.Min += equipInfo.Favor
|
||||
info.Max += equipInfo.Favor * 2
|
||||
probabilities[name] = info
|
||||
case "fish":
|
||||
info.Min += equipInfo.Favor * 2
|
||||
info.Max += equipInfo.Favor * 3
|
||||
probabilities[name] = info
|
||||
case "waste":
|
||||
info.Min += equipInfo.Favor * 3
|
||||
probabilities[name] = info
|
||||
}
|
||||
}
|
||||
// 钓鱼结算
|
||||
picName := ""
|
||||
thingNameList := make(map[string]int)
|
||||
for i := fishNumber; i > 0; i-- {
|
||||
thingName := ""
|
||||
typeOfThing := ""
|
||||
number := 1
|
||||
dice := rand.Intn(100)
|
||||
switch {
|
||||
case dice >= probabilities["waste"].Min && dice < probabilities["waste"].Max: // 垃圾
|
||||
typeOfThing = "waste"
|
||||
thingName = wasteList[rand.Intn(len(wasteList))]
|
||||
picName = thingName
|
||||
case dice >= probabilities["treasure"].Min && dice < probabilities["treasure"].Max: // 宝藏
|
||||
dice = rand.Intn(100)
|
||||
switch {
|
||||
case dice >= probabilities["美西螈"].Min && dice < probabilities["美西螈"].Max:
|
||||
typeOfThing = "pole"
|
||||
picName = "美西螈"
|
||||
thingName = "美西螈"
|
||||
case dice >= probabilities["唱片"].Min && dice < probabilities["唱片"].Max:
|
||||
typeOfThing = "article"
|
||||
picName = "唱片"
|
||||
thingName = "唱片"
|
||||
case dice >= probabilities["海之眷顾"].Min && dice < probabilities["海之眷顾"].Max:
|
||||
typeOfThing = "article"
|
||||
picName = "book"
|
||||
thingName = "海之眷顾"
|
||||
case dice >= probabilities["净化书"].Min && dice < probabilities["净化书"].Max:
|
||||
typeOfThing = "article"
|
||||
picName = "book"
|
||||
thingName = "净化书"
|
||||
case dice >= probabilities["宝藏诅咒"].Min && dice < probabilities["宝藏诅咒"].Max:
|
||||
typeOfThing = "article"
|
||||
picName = "book"
|
||||
thingName = "宝藏诅咒"
|
||||
case dice >= probabilities["海豚"].Min && dice < probabilities["海豚"].Max:
|
||||
typeOfThing = "fish"
|
||||
picName = "海豚"
|
||||
thingName = "海豚"
|
||||
default:
|
||||
typeOfThing = "article"
|
||||
picName = "book"
|
||||
thingName = "诱钓"
|
||||
}
|
||||
case dice >= probabilities["pole"].Min && dice < probabilities["pole"].Max: // 宝藏
|
||||
typeOfThing = "pole"
|
||||
dice := rand.Intn(100)
|
||||
switch {
|
||||
case dice >= probabilities["铁竿"].Min && dice < probabilities["铁竿"].Max:
|
||||
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 = "木竿"
|
||||
}
|
||||
picName = thingName
|
||||
case dice >= probabilities["fish"].Min && dice < probabilities["fish"].Max:
|
||||
typeOfThing = "fish"
|
||||
dice = rand.Intn(100)
|
||||
switch {
|
||||
case dice >= probabilities["墨鱼"].Min && dice < probabilities["墨鱼"].Max:
|
||||
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 = "热带鱼"
|
||||
case dice >= probabilities["河豚"].Min && dice < probabilities["河豚"].Max:
|
||||
thingName = "河豚"
|
||||
default:
|
||||
thingName = "鹦鹉螺"
|
||||
}
|
||||
picName = thingName
|
||||
default:
|
||||
thingNameList["赛博空气"]++
|
||||
}
|
||||
if thingName != "" {
|
||||
newThing := article{}
|
||||
if strings.Contains(thingName, "竿") {
|
||||
info := strconv.Itoa(rand.Intn(durationList[thingName])+1) +
|
||||
"/" + strconv.Itoa(rand.Intn(10)) + "/" +
|
||||
strconv.Itoa(rand.Intn(3)) + "/" + strconv.Itoa(rand.Intn(2))
|
||||
newThing = article{
|
||||
Duration: time.Now().Unix()*100 + int64(i),
|
||||
Type: typeOfThing,
|
||||
Name: thingName,
|
||||
Number: number,
|
||||
Other: info,
|
||||
}
|
||||
} else {
|
||||
thingInfo, err := dbdata.getUserThingInfo(uid, thingName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.6]:", err))
|
||||
return
|
||||
}
|
||||
if len(thingInfo) == 0 {
|
||||
newThing = article{
|
||||
Duration: time.Now().Unix()*100 + int64(i),
|
||||
Type: typeOfThing,
|
||||
Name: thingName,
|
||||
}
|
||||
} else {
|
||||
newThing = thingInfo[0]
|
||||
}
|
||||
if equipInfo.Equip == "美西螈" && thingName != "美西螈" {
|
||||
number += 2
|
||||
}
|
||||
newThing.Number += number
|
||||
}
|
||||
err = dbdata.updateUserThingInfo(uid, newThing)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.7]:", err))
|
||||
return
|
||||
}
|
||||
thingNameList[thingName] += number
|
||||
}
|
||||
}
|
||||
err = dbdata.updateCurseFor(uid, "fish", fishNumber)
|
||||
if err != nil {
|
||||
logrus.Warnln(err)
|
||||
}
|
||||
if len(thingNameList) == 1 {
|
||||
thingName := ""
|
||||
numberOfFish := 0
|
||||
for name, number := range thingNameList {
|
||||
thingName = name
|
||||
numberOfFish = number
|
||||
}
|
||||
if picName != "" {
|
||||
pic, err := engine.GetLazyData(picName+".png", false)
|
||||
if err != nil {
|
||||
logrus.Warnln("[mcfish]error:", err)
|
||||
ctx.SendChain(message.At(uid), message.Text("恭喜你钓到了", numberOfFish, thingName, "\n", msg))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.At(uid), message.Text("恭喜你钓到了", numberOfFish, thingName, "\n", msg), message.ImageBytes(pic))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.At(uid), message.Text("恭喜你钓到了", numberOfFish, thingName, "\n", msg))
|
||||
return
|
||||
}
|
||||
msgInfo := make(message.Message, 0, 3+len(thingNameList))
|
||||
msgInfo = append(msgInfo, message.Reply(ctx.Event.MessageID), message.Text("你进行了", fishNumber, "次钓鱼,结果如下:\n"))
|
||||
for name, number := range thingNameList {
|
||||
msgInfo = append(msgInfo, message.Text(name, " : ", number, "\n"))
|
||||
}
|
||||
msgInfo = append(msgInfo, message.Text(msg))
|
||||
ctx.Send(msgInfo)
|
||||
})
|
||||
}
|
||||
776
plugin/mcfish/main.go
Normal file
776
plugin/mcfish/main.go
Normal file
@@ -0,0 +1,776 @@
|
||||
// Package mcfish 钓鱼模拟器
|
||||
package mcfish
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
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"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
type fishdb struct {
|
||||
db *sql.Sqlite
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// FishLimit 钓鱼次数上限
|
||||
const FishLimit = 50
|
||||
|
||||
// version 规则版本号
|
||||
const version = "5.4.2"
|
||||
|
||||
// 各物品信息
|
||||
type jsonInfo struct {
|
||||
ZoneInfo []zoneInfo `json:"分类"` // 区域概率
|
||||
ArticleInfo []articleInfo `json:"物品"` // 物品信息
|
||||
}
|
||||
type zoneInfo struct {
|
||||
Name string `json:"类型"` // 类型
|
||||
Probability int `json:"概率[0-100)"` // 概率
|
||||
}
|
||||
type articleInfo struct {
|
||||
Name string `json:"名称"` // 名称
|
||||
Type string `json:"类型"` // 类型
|
||||
Probability int `json:"概率[0-100),omitempty"` // 概率
|
||||
Durable int `json:"耐久上限,omitempty"` // 耐久
|
||||
Price int `json:"价格"` // 价格
|
||||
}
|
||||
|
||||
type probabilityLimit struct {
|
||||
Min int
|
||||
Max int
|
||||
}
|
||||
|
||||
type equip struct {
|
||||
ID int64 // 用户
|
||||
Equip string // 装备名称
|
||||
Durable int // 耐久
|
||||
Maintenance int // 维修次数
|
||||
Induce int // 诱钓等级
|
||||
Favor int // 眷顾等级
|
||||
}
|
||||
|
||||
type article struct {
|
||||
Duration int64
|
||||
Name string
|
||||
Number int
|
||||
Other string // 耐久/维修次数/诱钓/眷顾
|
||||
Type string
|
||||
}
|
||||
|
||||
type store struct {
|
||||
Duration int64
|
||||
Name string
|
||||
Number int
|
||||
Price int
|
||||
Other string // 耐久/维修次数/诱钓/眷顾
|
||||
Type string
|
||||
}
|
||||
|
||||
type fishState struct {
|
||||
ID int64
|
||||
Duration int64
|
||||
Fish int
|
||||
Equip int
|
||||
Curse int // 功德--(x)
|
||||
Bless int // 功德++(x)
|
||||
}
|
||||
|
||||
type storeDiscount struct {
|
||||
Name string
|
||||
Discount int
|
||||
}
|
||||
|
||||
// buff状态记录
|
||||
// buff0: 优惠卷
|
||||
type buffInfo struct {
|
||||
ID int64
|
||||
Duration int64
|
||||
BuyTimes int `db:"Buff0"` // 购买次数
|
||||
Coupon int `db:"Buff1"` // 优惠卷
|
||||
SalesPole int `db:"Buff2"` // 卖鱼竿上限
|
||||
BuyTing int `db:"Buff3"` // 购买上限
|
||||
Buff4 int `db:"Buff4"` // 暂定
|
||||
Buff5 int `db:"Buff5"` // 暂定
|
||||
Buff6 int `db:"Buff6"` // 暂定
|
||||
Buff7 int `db:"Buff7"` // 暂定
|
||||
Buff8 int `db:"Buff8"` // 暂定
|
||||
Buff9 int `db:"Buff9"` // 暂定
|
||||
}
|
||||
|
||||
var (
|
||||
articlesInfo = jsonInfo{} // 物品信息
|
||||
thingList = make([]string, 0, 100) // 竿列表
|
||||
poleList = make([]string, 0, 10) // 竿列表
|
||||
fishList = make([]string, 0, 10) // 鱼列表
|
||||
treasureList = make([]string, 0, 10) // 鱼列表
|
||||
wasteList = make([]string, 0, 10) // 垃圾列表
|
||||
probabilities = make(map[string]probabilityLimit, 50) // 概率分布
|
||||
priceList = make(map[string]int, 50) // 价格分布
|
||||
durationList = make(map[string]int, 50) // 装备耐久分布
|
||||
discountList = make(map[string]int, 50) // 价格波动信息
|
||||
enchantLevel = []string{"0", "Ⅰ", "Ⅱ", "Ⅲ"}
|
||||
dbdata = &fishdb{
|
||||
db: &sql.Sqlite{},
|
||||
}
|
||||
)
|
||||
|
||||
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次物品;",
|
||||
PublicDataFolder: "McFish",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
getdb = fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
dbdata.db.DBPath = engine.DataFolder() + "fishdata.db"
|
||||
err := dbdata.db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at main.go.1]:", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
// go func() {
|
||||
_, err := engine.GetLazyData("articlesInfo.json", false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
reader, err := os.Open(engine.DataFolder() + "articlesInfo.json")
|
||||
if err == nil {
|
||||
err = json.NewDecoder(reader).Decode(&articlesInfo)
|
||||
}
|
||||
if err == nil {
|
||||
err = reader.Close()
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
probableList := make([]int, 4)
|
||||
for _, info := range articlesInfo.ZoneInfo {
|
||||
switch info.Name {
|
||||
case "treasure":
|
||||
probableList[0] = info.Probability
|
||||
case "pole":
|
||||
probableList[1] = info.Probability
|
||||
case "fish":
|
||||
probableList[2] = info.Probability
|
||||
case "waste":
|
||||
probableList[3] = info.Probability
|
||||
}
|
||||
}
|
||||
probabilities["treasure"] = probabilityLimit{
|
||||
Min: 0,
|
||||
Max: probableList[0],
|
||||
}
|
||||
probabilities["pole"] = probabilityLimit{
|
||||
Min: probableList[0],
|
||||
Max: probableList[1],
|
||||
}
|
||||
probabilities["fish"] = probabilityLimit{
|
||||
Min: probableList[1],
|
||||
Max: probableList[2],
|
||||
}
|
||||
probabilities["waste"] = probabilityLimit{
|
||||
Min: probableList[2],
|
||||
Max: probableList[3],
|
||||
}
|
||||
min := make(map[string]int, 4)
|
||||
for _, info := range articlesInfo.ArticleInfo {
|
||||
switch {
|
||||
case info.Type == "pole" || info.Name == "美西螈":
|
||||
poleList = append(poleList, info.Name)
|
||||
case info.Type == "fish" || info.Name == "海豚":
|
||||
fishList = append(fishList, info.Name)
|
||||
case info.Type == "waste":
|
||||
wasteList = append(wasteList, info.Name)
|
||||
case info.Type == "treasure":
|
||||
treasureList = append(treasureList, info.Name)
|
||||
}
|
||||
if info.Name != "宝藏诅咒" {
|
||||
thingList = append(thingList, info.Name)
|
||||
priceList[info.Name] = info.Price
|
||||
}
|
||||
if info.Durable != 0 {
|
||||
durationList[info.Name] = info.Durable
|
||||
}
|
||||
probabilities[info.Name] = probabilityLimit{
|
||||
Min: min[info.Type],
|
||||
Max: min[info.Type] + info.Probability,
|
||||
}
|
||||
min[info.Type] += info.Probability
|
||||
}
|
||||
// }()
|
||||
}
|
||||
|
||||
// 更新上限信息
|
||||
func (sql *fishdb) updateFishInfo(uid int64, number int) (residue int, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := fishState{ID: uid}
|
||||
err = sql.db.Create("fishState", &userInfo)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
_ = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
if time.Unix(userInfo.Duration, 0).Day() != time.Now().Day() {
|
||||
userInfo.Fish = 0
|
||||
userInfo.Duration = time.Now().Unix()
|
||||
}
|
||||
if userInfo.Fish >= FishLimit {
|
||||
return 0, nil
|
||||
}
|
||||
residue = number
|
||||
if userInfo.Fish+number > FishLimit {
|
||||
residue = FishLimit - userInfo.Fish
|
||||
number = residue
|
||||
}
|
||||
userInfo.Fish += number
|
||||
err = sql.db.Insert("fishState", &userInfo)
|
||||
return
|
||||
}
|
||||
|
||||
// 更新诅咒
|
||||
func (sql *fishdb) updateCurseFor(uid int64, info string, number int) (err error) {
|
||||
if number < 1 {
|
||||
return
|
||||
}
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := fishState{ID: uid}
|
||||
err = sql.db.Create("fishState", &userInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
changeCheck := false
|
||||
add := 0
|
||||
buffName := "宝藏诅咒"
|
||||
_ = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
if info == "fish" {
|
||||
userInfo.Bless += number
|
||||
for userInfo.Bless >= 75 {
|
||||
add++
|
||||
changeCheck = true
|
||||
buffName = "净化书"
|
||||
userInfo.Bless -= 75
|
||||
}
|
||||
} else {
|
||||
userInfo.Curse += number
|
||||
for userInfo.Curse >= 10 {
|
||||
add++
|
||||
changeCheck = true
|
||||
userInfo.Curse -= 10
|
||||
}
|
||||
}
|
||||
err = sql.db.Insert("fishState", &userInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if changeCheck {
|
||||
table := strconv.FormatInt(uid, 10) + "Pack"
|
||||
thing := article{
|
||||
Duration: time.Now().Unix(),
|
||||
Name: buffName,
|
||||
Type: "treasure",
|
||||
}
|
||||
_ = sql.db.Find(table, &thing, "where Name = '"+buffName+"'")
|
||||
thing.Number += add
|
||||
return sql.db.Insert(table, &thing)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/************************装备相关函数***********************/
|
||||
/*********************************************************/
|
||||
|
||||
func (sql *fishdb) checkEquipFor(uid int64) (ok bool, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := fishState{ID: uid}
|
||||
err = sql.db.Create("fishState", &userInfo)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !sql.db.CanFind("fishState", "where ID = "+strconv.FormatInt(uid, 10)) {
|
||||
return true, nil
|
||||
}
|
||||
err = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if userInfo.Equip > 3 {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (sql *fishdb) setEquipFor(uid int64) (err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := fishState{ID: uid}
|
||||
err = sql.db.Create("fishState", &userInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = sql.db.Find("fishState", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userInfo.Equip++
|
||||
return sql.db.Insert("fishState", &userInfo)
|
||||
}
|
||||
|
||||
// 获取装备信息
|
||||
func (sql *fishdb) getUserEquip(uid int64) (userInfo equip, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create("equips", &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !sql.db.CanFind("equips", "where ID = "+strconv.FormatInt(uid, 10)) {
|
||||
return
|
||||
}
|
||||
err = sql.db.Find("equips", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
return
|
||||
}
|
||||
|
||||
// 更新装备信息
|
||||
func (sql *fishdb) updateUserEquip(userInfo equip) (err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create("equips", &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if userInfo.Durable == 0 {
|
||||
return sql.db.Del("equips", "where ID = "+strconv.FormatInt(userInfo.ID, 10))
|
||||
}
|
||||
return sql.db.Insert("equips", &userInfo)
|
||||
}
|
||||
|
||||
func (sql *fishdb) pickFishFor(uid int64, number int) (fishNames map[string]int, err error) {
|
||||
fishNames = make(map[string]int, 6)
|
||||
name := strconv.FormatInt(uid, 10) + "Pack"
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := article{}
|
||||
err = sql.db.Create(name, &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
if !sql.db.CanFind(name, "where Type is '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]+"'")
|
||||
if fishInfo.Number <= 0 {
|
||||
k++
|
||||
continue
|
||||
}
|
||||
if fishInfo.Number < i {
|
||||
k++
|
||||
fishInfo.Number = 0
|
||||
i -= fishInfo.Number
|
||||
fishNames[fishInfo.Name] += fishInfo.Number
|
||||
} 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))
|
||||
} else {
|
||||
err = sql.db.Insert(name, &fishInfo)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/************************背包相关函数***********************/
|
||||
/*********************************************************/
|
||||
|
||||
// 获取用户背包信息
|
||||
func (sql *fishdb) getUserPack(uid int64) (thingInfos []article, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := article{}
|
||||
err = sql.db.Create(strconv.FormatInt(uid, 10)+"Pack", &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count(strconv.FormatInt(uid, 10) + "Pack")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
err = sql.db.FindFor(strconv.FormatInt(uid, 10)+"Pack", &userInfo, "ORDER by Type, Name, Other ASC", func() error {
|
||||
thingInfos = append(thingInfos, userInfo)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户物品信息
|
||||
func (sql *fishdb) getUserThingInfo(uid int64, thing 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
|
||||
}
|
||||
count, err := sql.db.Count(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
if !sql.db.CanFind(name, "where Name = '"+thing+"'") {
|
||||
return
|
||||
}
|
||||
err = sql.db.FindFor(name, &userInfo, "where Name = '"+thing+"'", func() error {
|
||||
thingInfos = append(thingInfos, userInfo)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 更新用户物品信息
|
||||
func (sql *fishdb) updateUserThingInfo(uid int64, userInfo article) (err error) {
|
||||
name := strconv.FormatInt(uid, 10) + "Pack"
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create(name, &userInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if userInfo.Number == 0 {
|
||||
return sql.db.Del(name, "where Duration = "+strconv.FormatInt(userInfo.Duration, 10))
|
||||
}
|
||||
return sql.db.Insert(name, &userInfo)
|
||||
}
|
||||
|
||||
// 获取某关键字的数量
|
||||
func (sql *fishdb) getNumberFor(uid int64, thing string) (number int, 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
|
||||
}
|
||||
count, err := sql.db.Count(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
if !sql.db.CanFind(name, "where Name glob '*"+thing+"*'") {
|
||||
return
|
||||
}
|
||||
info := article{}
|
||||
err = sql.db.FindFor(name, &info, "where Name glob '*"+thing+"*'", func() error {
|
||||
number += info.Number
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/************************商店相关函数***********************/
|
||||
/*********************************************************/
|
||||
|
||||
// 刷新商店信息
|
||||
func (sql *fishdb) refreshStroeInfo() (ok bool, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create("stroeDiscount", &storeDiscount{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
lastTime := storeDiscount{}
|
||||
_ = sql.db.Find("stroeDiscount", &lastTime, "where Name = 'lastTime'")
|
||||
refresh := false
|
||||
timeNow := time.Now().Day()
|
||||
if timeNow != lastTime.Discount {
|
||||
lastTime = storeDiscount{
|
||||
Name: "lastTime",
|
||||
Discount: timeNow,
|
||||
}
|
||||
err = sql.db.Insert("stroeDiscount", &lastTime)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
refresh = true
|
||||
}
|
||||
for _, name := range thingList {
|
||||
thing := storeDiscount{}
|
||||
switch refresh {
|
||||
case true:
|
||||
thingDiscount := 50 + rand.Intn(150)
|
||||
thing = storeDiscount{
|
||||
Name: name,
|
||||
Discount: thingDiscount,
|
||||
}
|
||||
err = sql.db.Insert("stroeDiscount", &thing)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
_ = sql.db.Find("stroeDiscount", &thing, "where Name = '"+name+"'")
|
||||
}
|
||||
if thing.Discount != 0 {
|
||||
discountList[name] = thing.Discount
|
||||
} else {
|
||||
discountList[name] = 100
|
||||
}
|
||||
}
|
||||
thing := store{}
|
||||
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))
|
||||
}
|
||||
if refresh {
|
||||
err = sql.db.Create("store", &store{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 每天调控1种鱼
|
||||
fish := fishList[rand.Intn(len(fishList))]
|
||||
thingInfo := store{
|
||||
Duration: time.Now().Unix(),
|
||||
Name: fish,
|
||||
Type: "fish",
|
||||
Price: priceList[fish] * discountList[fish] / 100,
|
||||
}
|
||||
_ = 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本净化书
|
||||
thingInfo = store{
|
||||
Duration: time.Now().Unix(),
|
||||
Name: "净化书",
|
||||
Type: "article",
|
||||
Price: priceList["净化书"] * discountList["净化书"] / 100,
|
||||
}
|
||||
_ = sql.db.Find("store", &thingInfo, "where Name = '净化书'")
|
||||
thingInfo.Number = 20
|
||||
_ = sql.db.Insert("store", &thingInfo)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 获取商店信息
|
||||
func (sql *fishdb) getStoreInfo() (thingInfos []store, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
thingInfo := store{}
|
||||
err = sql.db.Create("store", &thingInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count("store")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
err = sql.db.FindFor("store", &thingInfo, "ORDER by Type, Name, Price ASC", func() error {
|
||||
thingInfos = append(thingInfos, thingInfo)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 获取商店物品信息
|
||||
func (sql *fishdb) getStoreThingInfo(thing string) (thingInfos []store, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
thingInfo := store{}
|
||||
err = sql.db.Create("store", &thingInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count("store")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return
|
||||
}
|
||||
if !sql.db.CanFind("store", "where Name = '"+thing+"'") {
|
||||
return
|
||||
}
|
||||
err = sql.db.FindFor("store", &thingInfo, "where Name = '"+thing+"'", func() error {
|
||||
thingInfos = append(thingInfos, thingInfo)
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 获取商店物品信息
|
||||
func (sql *fishdb) checkStoreFor(thing store, number int) (ok bool, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create("store", &thing)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
count, err := sql.db.Count("store")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if count == 0 {
|
||||
return false, nil
|
||||
}
|
||||
if !sql.db.CanFind("store", "where Duration = "+strconv.FormatInt(thing.Duration, 10)) {
|
||||
return false, nil
|
||||
}
|
||||
err = sql.db.Find("store", &thing, "where Duration = "+strconv.FormatInt(thing.Duration, 10))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if thing.Number < number {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// 更新商店信息
|
||||
func (sql *fishdb) updateStoreInfo(thingInfo store) (err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
err = sql.db.Create("store", &thingInfo)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if thingInfo.Number == 0 {
|
||||
return sql.db.Del("store", "where Duration = "+strconv.FormatInt(thingInfo.Duration, 10))
|
||||
}
|
||||
return sql.db.Insert("store", &thingInfo)
|
||||
}
|
||||
|
||||
// 更新购买次数
|
||||
func (sql *fishdb) updateBuyTimeFor(uid int64, add int) (err 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 = "+strconv.FormatInt(uid, 10))
|
||||
userInfo.BuyTimes += add
|
||||
if userInfo.BuyTimes > 20 {
|
||||
userInfo.BuyTimes -= 20
|
||||
userInfo.Coupon = 3
|
||||
}
|
||||
return sql.db.Insert("buff", &userInfo)
|
||||
}
|
||||
|
||||
// 使用优惠卷
|
||||
func (sql *fishdb) useCouponAt(uid int64, times int) (int, error) {
|
||||
useTimes := -1
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := buffInfo{ID: uid}
|
||||
err := sql.db.Create("buff", &userInfo)
|
||||
if err != nil {
|
||||
return useTimes, err
|
||||
}
|
||||
_ = sql.db.Find("buff", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
if userInfo.Coupon > 0 {
|
||||
useTimes = math.Min(userInfo.Coupon, times)
|
||||
userInfo.Coupon -= useTimes
|
||||
}
|
||||
return useTimes, sql.db.Insert("buff", &userInfo)
|
||||
}
|
||||
|
||||
// 检测上限
|
||||
func (sql *fishdb) checkCanSalesFor(uid int64, sales bool) (int, error) {
|
||||
residue := 0
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
userInfo := buffInfo{ID: uid}
|
||||
err := sql.db.Create("buff", &userInfo)
|
||||
if err != nil {
|
||||
return residue, err
|
||||
}
|
||||
_ = sql.db.Find("buff", &userInfo, "where ID = "+strconv.FormatInt(uid, 10))
|
||||
if time.Now().Day() != time.Unix(userInfo.Duration, 0).Day() {
|
||||
userInfo.SalesPole = 0
|
||||
userInfo.BuyTing = 0
|
||||
}
|
||||
if sales && userInfo.SalesPole < 5 {
|
||||
residue = 5 - userInfo.SalesPole
|
||||
userInfo.SalesPole++
|
||||
} else if userInfo.BuyTing < 15 {
|
||||
residue = 15 - userInfo.SalesPole
|
||||
userInfo.SalesPole++
|
||||
}
|
||||
return residue, sql.db.Insert("buff", &userInfo)
|
||||
}
|
||||
517
plugin/mcfish/pack.go
Normal file
517
plugin/mcfish/pack.go
Normal file
@@ -0,0 +1,517 @@
|
||||
// Package mcfish 钓鱼模拟器
|
||||
package mcfish
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/FloatTech/AnimeAPI/wallet"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/math"
|
||||
"github.com/FloatTech/gg"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
"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.OnFullMatch("钓鱼背包", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pack.go.1]:", err))
|
||||
return
|
||||
}
|
||||
articles, err := dbdata.getUserPack(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pack.go.2]:", err))
|
||||
return
|
||||
}
|
||||
pic, err := drawPackImage(uid, equipInfo, articles)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pack.go.3]:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.ImageBytes(pic))
|
||||
})
|
||||
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])
|
||||
if number == 0 {
|
||||
number = 1
|
||||
}
|
||||
number1, err := dbdata.getNumberFor(uid, "宝藏诅咒")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.3.1]:", err))
|
||||
return
|
||||
}
|
||||
if number1 == 0 {
|
||||
ctx.SendChain(message.Text("你没有绑定任何诅咒"))
|
||||
return
|
||||
}
|
||||
if number1 < number {
|
||||
number = number1
|
||||
}
|
||||
number2, err := dbdata.getNumberFor(uid, "净化书")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.3.2]:", err))
|
||||
return
|
||||
}
|
||||
if number2 < number {
|
||||
ctx.SendChain(message.Text("你没有足够的解除诅咒的道具"))
|
||||
return
|
||||
}
|
||||
articles, err := dbdata.getUserThingInfo(uid, "净化书")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.3.3]:", err))
|
||||
return
|
||||
}
|
||||
articles[0].Number -= number
|
||||
err = dbdata.updateUserThingInfo(uid, articles[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.3.4]:", err))
|
||||
return
|
||||
}
|
||||
articles, err = dbdata.getUserThingInfo(uid, "宝藏诅咒")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("消除失败,净化书销毁了\n[ERROR at store.go.3.5]:", err))
|
||||
return
|
||||
}
|
||||
articles[0].Number -= number
|
||||
err = dbdata.updateUserThingInfo(uid, articles[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at store.go.3.5]:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("消除成功"))
|
||||
})
|
||||
engine.OnFullMatch("当前装备概率明细", getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pack.go.1]:", err))
|
||||
return
|
||||
}
|
||||
number, err := dbdata.getNumberFor(uid, "鱼")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5.1]:", err))
|
||||
return
|
||||
}
|
||||
msg := make(message.Message, 0, 20+len(thingList))
|
||||
msg = append(msg, message.At(uid), message.Text("\n大类概率:\n"))
|
||||
probableList := make([]int, 4)
|
||||
for _, info := range articlesInfo.ZoneInfo {
|
||||
switch info.Name {
|
||||
case "treasure":
|
||||
probableList[0] = info.Probability
|
||||
case "pole":
|
||||
probableList[1] = info.Probability
|
||||
case "fish":
|
||||
probableList[2] = info.Probability
|
||||
case "waste":
|
||||
probableList[3] = info.Probability
|
||||
}
|
||||
}
|
||||
if number > 100 || equipInfo.Equip == "美西螈" { // 放大概率
|
||||
probableList = []int{2, 8, 35, 45}
|
||||
}
|
||||
if equipInfo.Favor > 0 {
|
||||
probableList[0] += equipInfo.Favor
|
||||
probableList[1] += equipInfo.Favor
|
||||
probableList[2] += equipInfo.Favor
|
||||
probableList[3] -= equipInfo.Favor * 3
|
||||
}
|
||||
probable := probableList[0]
|
||||
msg = append(msg, message.Text("宝藏 : ", probableList[0], "%\n"))
|
||||
probable += probableList[1]
|
||||
msg = append(msg, message.Text("鱼竿 : ", probableList[1], "%\n"))
|
||||
probable += probableList[2]
|
||||
msg = append(msg, message.Text("鱼类 : ", probableList[2], "%\n"))
|
||||
probable += probableList[3]
|
||||
msg = append(msg, message.Text("垃圾 : ", probableList[3], "%\n"))
|
||||
msg = append(msg, message.Text("合计 : ", probable, "%\n"))
|
||||
msg = append(msg, message.Text("-----------\n宝藏概率:\n"))
|
||||
for _, name := range treasureList {
|
||||
msg = append(msg, message.Text(name, " : ",
|
||||
strconv.FormatFloat(float64(probabilities[name].Max-probabilities[name].Min)*float64(probableList[0])/100, 'f', 2, 64),
|
||||
"%\n"))
|
||||
}
|
||||
msg = append(msg, message.Text("-----------\n鱼竿概率:\n"))
|
||||
for _, name := range poleList {
|
||||
if name != "美西螈" {
|
||||
msg = append(msg, message.Text(name, " : ",
|
||||
strconv.FormatFloat(float64(probabilities[name].Max-probabilities[name].Min)*float64(probableList[1])/100, 'f', 2, 64),
|
||||
"%\n"))
|
||||
} else if name == "美西螈" {
|
||||
msg = append(msg, message.Text(name, " : ",
|
||||
strconv.FormatFloat(float64(probabilities[name].Max-probabilities[name].Min)*float64(probableList[0])/100, 'f', 2, 64),
|
||||
"%\n"))
|
||||
}
|
||||
}
|
||||
msg = append(msg, message.Text("-----------\n鱼类概率:\n"))
|
||||
for _, name := range fishList {
|
||||
if name != "海豚" {
|
||||
msg = append(msg, message.Text(name, " : ",
|
||||
strconv.FormatFloat(float64(probabilities[name].Max-probabilities[name].Min)*float64(probableList[2])/100, 'f', 2, 64),
|
||||
"%\n"))
|
||||
} else if name == "海豚" {
|
||||
msg = append(msg, message.Text(name, " : ",
|
||||
strconv.FormatFloat(float64(probabilities[name].Max-probabilities[name].Min)*float64(probableList[0])/100, 'f', 2, 64),
|
||||
"%\n"))
|
||||
}
|
||||
}
|
||||
msg = append(msg, message.Text("-----------"))
|
||||
ctx.Send(msg)
|
||||
})
|
||||
}
|
||||
|
||||
func drawPackImage(uid int64, equipInfo equip, articles []article) (imagePicByte []byte, err error) {
|
||||
fontdata, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
equipBlock image.Image // 装备信息
|
||||
packBlock image.Image // 背包信息
|
||||
)
|
||||
wg.Add(1)
|
||||
// 绘制ID
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if equipInfo == (equip{}) {
|
||||
equipBlock, err = drawEquipEmptyBlock(fontdata)
|
||||
} else {
|
||||
equipBlock, err = drawEquipInfoBlock(equipInfo, fontdata)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
wg.Add(1)
|
||||
// 绘制基本信息
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if len(articles) == 0 {
|
||||
packBlock, err = drawArticleEmptyBlock(fontdata)
|
||||
} else {
|
||||
packBlock, err = drawArticleInfoBlock(uid, articles, fontdata)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
wg.Wait()
|
||||
if equipBlock == nil || packBlock == nil {
|
||||
err = errors.New("生成图片失败,数据缺失")
|
||||
return
|
||||
}
|
||||
// 计算图片高度
|
||||
backDX := 1020
|
||||
backDY := 10 + equipBlock.Bounds().Dy() + 10 + packBlock.Bounds().Dy() + 10
|
||||
canvas := gg.NewContext(backDX, backDY)
|
||||
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, float64(backDX), float64(backDY))
|
||||
canvas.SetRGBA255(150, 150, 150, 255)
|
||||
canvas.Fill()
|
||||
canvas.DrawRectangle(10, 10, float64(backDX-20), float64(backDY-20))
|
||||
canvas.SetRGBA255(255, 255, 255, 255)
|
||||
canvas.Fill()
|
||||
|
||||
canvas.DrawImage(equipBlock, 10, 10)
|
||||
canvas.DrawImage(packBlock, 10, 10+equipBlock.Bounds().Dy()+10)
|
||||
|
||||
return imgfactory.ToBytes(canvas.Image())
|
||||
}
|
||||
|
||||
// 绘制装备栏区域
|
||||
func drawEquipEmptyBlock(fontdata []byte) (image.Image, error) {
|
||||
canvas := gg.NewContext(1000, 300)
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||||
canvas.SetRGBA255(255, 255, 255, 150)
|
||||
canvas.Fill()
|
||||
// 边框框
|
||||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
canvas.SetColor(color.Black)
|
||||
err := canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textW, textH := canvas.MeasureString("装备信息")
|
||||
canvas.DrawString("装备信息", 10, 10+textH)
|
||||
canvas.DrawLine(10, textH*1.2, textW, textH*1.2)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
if err = canvas.ParseFontFace(fontdata, 50); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.DrawString("没有装备任何鱼竿", 50, 10+textH*2+50)
|
||||
return canvas.Image(), nil
|
||||
}
|
||||
func drawEquipInfoBlock(equipInfo equip, fontdata []byte) (image.Image, error) {
|
||||
canvas := gg.NewContext(1, 1)
|
||||
err := canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, titleH := canvas.MeasureString("装备信息")
|
||||
err = canvas.ParseFontFace(fontdata, 50)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, textH := canvas.MeasureString("装备信息")
|
||||
|
||||
backDY := math.Max(int(10+titleH*2+(textH*2)*4+10), 300)
|
||||
|
||||
canvas = gg.NewContext(1000, backDY)
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, 1000, float64(backDY))
|
||||
canvas.SetRGBA255(255, 255, 255, 150)
|
||||
canvas.Fill()
|
||||
// 边框框
|
||||
canvas.DrawRectangle(0, 0, 1000, float64(backDY))
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
getAvatar, err := engine.GetLazyData(equipInfo.Equip+".png", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
equipPic, _, err := image.Decode(bytes.NewReader(getAvatar))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
picDy := float64(backDY) - 10 - titleH*2
|
||||
equipPic = imgfactory.Size(equipPic, int(picDy)-10, int(picDy)-10).Image()
|
||||
canvas.DrawImage(equipPic, 10, 10+int(titleH)*2)
|
||||
|
||||
// 放字
|
||||
canvas.SetColor(color.Black)
|
||||
if err = canvas.ParseFontFace(fontdata, 100); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
titleW, titleH := canvas.MeasureString("装备信息")
|
||||
canvas.DrawString("装备信息", 10, 10+titleH*1.2)
|
||||
canvas.DrawLine(10, titleH*1.6, titleW, titleH*1.6)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
textDx := picDy + 10
|
||||
textDy := 10 + titleH*2
|
||||
if err = canvas.ParseFontFace(fontdata, 75); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textW, textH := canvas.MeasureString(equipInfo.Equip)
|
||||
canvas.DrawStringAnchored(equipInfo.Equip, textDx+textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
|
||||
textDy += textH * 1.5
|
||||
if err = canvas.ParseFontFace(fontdata, 50); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textW, textH = canvas.MeasureString("维修次数")
|
||||
durable := strconv.Itoa(equipInfo.Durable)
|
||||
valueW, _ := canvas.MeasureString("100")
|
||||
barW := 1000 - textDx - textW - 10 - valueW - 10
|
||||
|
||||
canvas.DrawStringAnchored("装备耐久", textDx+textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawRectangle(textDx+textW+5, textDy, barW, textH*1.2)
|
||||
canvas.SetRGB255(150, 150, 150)
|
||||
canvas.Fill()
|
||||
canvas.SetRGB255(0, 0, 0)
|
||||
durableW := barW * float64(equipInfo.Durable) / float64(durationList[equipInfo.Equip])
|
||||
canvas.DrawRectangle(textDx+textW+5, textDy, durableW, textH*1.2)
|
||||
canvas.SetRGB255(102, 102, 102)
|
||||
canvas.Fill()
|
||||
canvas.SetColor(color.Black)
|
||||
canvas.DrawStringAnchored(durable, textDx+textW+5+barW+5+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
|
||||
textDy += textH * 2
|
||||
maintenance := strconv.Itoa(equipInfo.Maintenance)
|
||||
canvas.DrawStringAnchored("维修次数", textDx+textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawRectangle(textDx+textW+5, textDy, barW, textH*1.2)
|
||||
canvas.SetRGB255(150, 150, 150)
|
||||
canvas.Fill()
|
||||
canvas.SetRGB255(0, 0, 0)
|
||||
canvas.DrawRectangle(textDx+textW+5, textDy, barW*float64(equipInfo.Maintenance)/10, textH*1.2)
|
||||
canvas.SetRGB255(102, 102, 102)
|
||||
canvas.Fill()
|
||||
canvas.SetColor(color.Black)
|
||||
canvas.DrawStringAnchored(maintenance, textDx+textW+5+barW+5+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
|
||||
textDy += textH * 3
|
||||
canvas.DrawString(" 附魔: 诱钓"+enchantLevel[equipInfo.Induce]+" 海之眷顾"+enchantLevel[equipInfo.Favor], textDx, textDy)
|
||||
return canvas.Image(), nil
|
||||
}
|
||||
|
||||
// 绘制背包信息区域
|
||||
func drawArticleEmptyBlock(fontdata []byte) (image.Image, error) {
|
||||
canvas := gg.NewContext(1000, 300)
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||||
canvas.SetRGBA255(255, 255, 255, 150)
|
||||
canvas.Fill()
|
||||
// 边框框
|
||||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
canvas.SetColor(color.Black)
|
||||
err := canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textW, textH := canvas.MeasureString("背包信息")
|
||||
canvas.DrawString("背包信息", 10, 10+textH*1.2)
|
||||
canvas.DrawLine(10, textH*1.6, textW, textH*1.6)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
if err = canvas.ParseFontFace(fontdata, 50); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.DrawStringAnchored("背包没有存放任何东西", 500, 10+textH*2+50, 0.5, 0)
|
||||
return canvas.Image(), nil
|
||||
}
|
||||
func drawArticleInfoBlock(uid int64, articles []article, fontdata []byte) (image.Image, error) {
|
||||
canvas := gg.NewContext(1, 1)
|
||||
err := canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
titleW, titleH := canvas.MeasureString("背包信息")
|
||||
front := 45.0
|
||||
err = canvas.ParseFontFace(fontdata, front)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, textH := canvas.MeasureString("高度")
|
||||
|
||||
nameWOfFiest := 0.0
|
||||
nameWOfSecond := 0.0
|
||||
for i, info := range articles {
|
||||
textW, _ := canvas.MeasureString(info.Name + "(" + info.Other + ")")
|
||||
if i%2 == 0 && textW > nameWOfFiest {
|
||||
nameWOfFiest = textW
|
||||
} else if textW > nameWOfSecond {
|
||||
nameWOfSecond = textW
|
||||
}
|
||||
}
|
||||
valueW, _ := canvas.MeasureString("10000")
|
||||
|
||||
if (10+nameWOfFiest+10+valueW+10)+(10+nameWOfSecond+10+valueW+10) > 980 {
|
||||
front = 32.0
|
||||
err = canvas.ParseFontFace(fontdata, front)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, textH = canvas.MeasureString("高度")
|
||||
|
||||
nameWOfFiest = 0
|
||||
nameWOfSecond = 0
|
||||
for i, info := range articles {
|
||||
textW, _ := canvas.MeasureString(info.Name + "(" + info.Other + ")")
|
||||
if i%2 == 0 && textW > nameWOfFiest {
|
||||
nameWOfFiest = textW
|
||||
} else if textW > nameWOfSecond {
|
||||
nameWOfSecond = textW
|
||||
}
|
||||
}
|
||||
valueW, _ = canvas.MeasureString("10000")
|
||||
}
|
||||
wallW := (980 - (10 + nameWOfFiest + 10 + valueW + 10) - (10 + nameWOfSecond + 10 + valueW + 10)) / 2
|
||||
backY := math.Max(10+int(titleH*1.6)+10+int(textH*2)*(math.Ceil(len(articles), 2)+1), 500)
|
||||
canvas = gg.NewContext(1000, backY)
|
||||
// 画底色
|
||||
canvas.DrawRectangle(0, 0, 1000, float64(backY))
|
||||
canvas.SetRGBA255(255, 255, 255, 150)
|
||||
canvas.Fill()
|
||||
// 边框框
|
||||
canvas.DrawRectangle(0, 0, 1000, float64(backY))
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
// 放字
|
||||
canvas.SetColor(color.Black)
|
||||
err = canvas.ParseFontFace(fontdata, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.DrawString("背包信息", 10, 10+titleH*1.2)
|
||||
canvas.DrawLine(10, titleH*1.6, titleW, titleH*1.6)
|
||||
canvas.SetLineWidth(3)
|
||||
canvas.SetRGBA255(0, 0, 0, 255)
|
||||
canvas.Stroke()
|
||||
|
||||
textDy := 10 + titleH*1.7
|
||||
if err = canvas.ParseFontFace(fontdata, front); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canvas.SetColor(color.Black)
|
||||
numberOfFish := 0
|
||||
numberOfEquip := 0
|
||||
canvas.DrawStringAnchored("名称", wallW+20+nameWOfFiest/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored("数量", wallW+20+nameWOfFiest+10+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored("名称", wallW+20+nameWOfFiest+10+valueW+10+10+nameWOfSecond/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored("数量", wallW+20+nameWOfFiest+10+valueW+10+10+nameWOfSecond+10+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
textDy += textH * 2
|
||||
for i, info := range articles {
|
||||
name := info.Name
|
||||
if info.Other != "" {
|
||||
if strings.Contains(info.Name, "竿") {
|
||||
numberOfEquip++
|
||||
}
|
||||
name += "(" + info.Other + ")"
|
||||
} else if strings.Contains(name, "鱼") {
|
||||
numberOfFish += info.Number
|
||||
}
|
||||
valueStr := strconv.Itoa(info.Number)
|
||||
if i%2 == 0 {
|
||||
if i != 0 {
|
||||
textDy += textH * 2
|
||||
}
|
||||
canvas.DrawStringAnchored(name, wallW+20+nameWOfFiest/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored(valueStr, wallW+20+nameWOfFiest+10+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
} else {
|
||||
canvas.DrawStringAnchored(name, wallW+20+nameWOfFiest+10+valueW+10+10+nameWOfSecond/2, textDy+textH/2, 0.5, 0.5)
|
||||
canvas.DrawStringAnchored(valueStr, wallW+20+nameWOfFiest+10+valueW+10+10+nameWOfSecond+10+valueW/2, textDy+textH/2, 0.5, 0.5)
|
||||
}
|
||||
}
|
||||
if err = canvas.ParseFontFace(fontdata, 30); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
textDy = 10
|
||||
text := "钱包余额: " + strconv.Itoa(wallet.GetWalletOf(uid))
|
||||
textW, textH := canvas.MeasureString(text)
|
||||
w, _ := canvas.MeasureString("维修大师[已激活]")
|
||||
if w > textW {
|
||||
textW = w
|
||||
}
|
||||
canvas.DrawStringAnchored(text, 980-textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
textDy += textH * 1.5
|
||||
if numberOfFish > 100 {
|
||||
canvas.DrawStringAnchored("钓鱼佬[已激活]", 980-textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
textDy += textH * 1.5
|
||||
}
|
||||
if numberOfEquip > 10 {
|
||||
canvas.DrawStringAnchored("维修大师[已激活]", 980-textW/2, textDy+textH/2, 0.5, 0.5)
|
||||
}
|
||||
return canvas.Image(), nil
|
||||
}
|
||||
485
plugin/mcfish/pole.go
Normal file
485
plugin/mcfish/pole.go
Normal file
@@ -0,0 +1,485 @@
|
||||
// Package mcfish 钓鱼模拟器
|
||||
package mcfish
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine.OnRegex(`^装备(`+strings.Join(poleList, "|")+`)$`, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.1]:", err))
|
||||
return
|
||||
}
|
||||
thingName := ctx.State["regex_matched"].([]string)[1]
|
||||
articles, err := dbdata.getUserThingInfo(uid, thingName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.2]:", err))
|
||||
return
|
||||
}
|
||||
if len(articles) == 0 {
|
||||
ctx.SendChain(message.Text("你的背包不存在该物品"))
|
||||
return
|
||||
}
|
||||
poles := make([]equip, 0, len(articles))
|
||||
if thingName != "美西螈" {
|
||||
for _, info := range articles {
|
||||
poleInfo := strings.Split(info.Other, "/")
|
||||
durable, _ := strconv.Atoi(poleInfo[0])
|
||||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||||
poles = append(poles, equip{
|
||||
ID: uid,
|
||||
Equip: info.Name,
|
||||
Durable: durable,
|
||||
Maintenance: maintenance,
|
||||
Induce: induceLevel,
|
||||
Favor: favorLevel,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
poles = append(poles, equip{
|
||||
ID: uid,
|
||||
Equip: thingName,
|
||||
Durable: 999,
|
||||
})
|
||||
}
|
||||
check := false
|
||||
index := 0
|
||||
if len(poles) > 1 {
|
||||
msg := make(message.Message, 0, 3+len(articles))
|
||||
msg = append(msg, message.Reply(ctx.Event.MessageID), message.Text("找到以下鱼竿:\n"))
|
||||
for i, info := range poles {
|
||||
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输入对应序号进行装备,或回复“取消”取消"))
|
||||
ctx.Send(msg)
|
||||
// 等待用户下一步选择
|
||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
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
|
||||
}
|
||||
index, err = strconv.Atoi(nextcmd)
|
||||
if err != nil || index > len(articles)-1 {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入正确的序号"))
|
||||
continue
|
||||
}
|
||||
check = true
|
||||
}
|
||||
if check {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
newEquipInfo := poles[index]
|
||||
packEquip := articles[index]
|
||||
packEquip.Number--
|
||||
err = dbdata.updateUserThingInfo(uid, packEquip)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.3]:", err))
|
||||
return
|
||||
}
|
||||
err = dbdata.updateUserEquip(newEquipInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.3.1]:", err))
|
||||
return
|
||||
}
|
||||
oldthing := article{}
|
||||
if equipInfo != (equip{}) && equipInfo.Equip != "美西螈" {
|
||||
oldthing = article{
|
||||
Duration: time.Now().Unix(),
|
||||
Type: "pole",
|
||||
Name: equipInfo.Equip,
|
||||
Number: 1,
|
||||
Other: strconv.Itoa(equipInfo.Durable) + "/" + strconv.Itoa(equipInfo.Maintenance) + "/" + strconv.Itoa(equipInfo.Induce) + "/" + strconv.Itoa(equipInfo.Favor),
|
||||
}
|
||||
} else if equipInfo.Equip == "美西螈" {
|
||||
articles, err = dbdata.getUserThingInfo(uid, "美西螈")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.3.2]:", err))
|
||||
return
|
||||
}
|
||||
if len(articles) == 0 {
|
||||
oldthing = article{
|
||||
Duration: time.Now().Unix(),
|
||||
Type: "pole",
|
||||
Name: equipInfo.Equip,
|
||||
Number: 1,
|
||||
}
|
||||
} else {
|
||||
oldthing = articles[0]
|
||||
oldthing.Number++
|
||||
}
|
||||
}
|
||||
err = dbdata.updateUserThingInfo(uid, oldthing)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.4]:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("装备成功"),
|
||||
),
|
||||
)
|
||||
})
|
||||
engine.OnFullMatchGroup([]string{"修复鱼竿", "维修鱼竿"}, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.5]:", err))
|
||||
return
|
||||
}
|
||||
if equipInfo.Equip == "" || equipInfo.Equip == "美西螈" {
|
||||
ctx.SendChain(message.Text("仅能修复装备中的鱼竿"))
|
||||
return
|
||||
}
|
||||
if equipInfo.Maintenance >= 10 {
|
||||
ctx.SendChain(message.Text("装备的鱼竿已经达到修复上限"))
|
||||
return
|
||||
}
|
||||
articles, err := dbdata.getUserThingInfo(uid, equipInfo.Equip)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.6]:", err))
|
||||
return
|
||||
}
|
||||
if len(articles) == 0 {
|
||||
ctx.SendChain(message.Text("你的背包不存在相同鱼竿进行修复"))
|
||||
return
|
||||
}
|
||||
poles := make([]equip, 0, len(articles))
|
||||
for _, info := range articles {
|
||||
poleInfo := strings.Split(info.Other, "/")
|
||||
durable, _ := strconv.Atoi(poleInfo[0])
|
||||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||||
poles = append(poles, equip{
|
||||
ID: uid,
|
||||
Equip: info.Name,
|
||||
Durable: durable,
|
||||
Maintenance: maintenance,
|
||||
Induce: induceLevel,
|
||||
Favor: favorLevel,
|
||||
})
|
||||
}
|
||||
index := 0
|
||||
check := false
|
||||
if len(articles) > 1 {
|
||||
msg := make(message.Message, 0, 3+len(articles))
|
||||
msg = append(msg, message.Text("找到以下鱼竿:\n"))
|
||||
for i, info := range poles {
|
||||
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输入对应序号进行修复,或回复“取消”取消"))
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, msg...))
|
||||
// 等待用户下一步选择
|
||||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
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
|
||||
}
|
||||
index, err = strconv.Atoi(nextcmd)
|
||||
if err != nil || index > len(articles)-1 {
|
||||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入正确的序号"))
|
||||
continue
|
||||
}
|
||||
check = true
|
||||
}
|
||||
if check {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
newEquipInfo := poles[index]
|
||||
number, err := dbdata.getNumberFor(uid, "竿")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at fish.go.5.1]:", err))
|
||||
return
|
||||
}
|
||||
if number <= 10 {
|
||||
number = 8
|
||||
} else {
|
||||
number = 10
|
||||
}
|
||||
equipInfo.Durable += newEquipInfo.Durable * number / 10
|
||||
if equipInfo.Durable > durationList[equipInfo.Equip] || equipInfo.Equip == "三叉戟" {
|
||||
equipInfo.Durable = durationList[equipInfo.Equip]
|
||||
}
|
||||
msg := ""
|
||||
if newEquipInfo.Induce != 0 && rand.Intn(100) < 50 {
|
||||
equipInfo.Induce += newEquipInfo.Induce
|
||||
if equipInfo.Induce > 3 {
|
||||
equipInfo.Induce = 3
|
||||
}
|
||||
msg += ",诱钓等级提升至" + enchantLevel[equipInfo.Induce]
|
||||
}
|
||||
if newEquipInfo.Favor != 0 && rand.Intn(100) < 50 {
|
||||
equipInfo.Favor += newEquipInfo.Favor
|
||||
if equipInfo.Favor > 3 {
|
||||
equipInfo.Favor = 3
|
||||
}
|
||||
msg += ",海之眷顾等级提升至" + enchantLevel[equipInfo.Favor]
|
||||
}
|
||||
thingInfo := articles[index]
|
||||
thingInfo.Number = 0
|
||||
err = dbdata.updateUserThingInfo(uid, thingInfo)
|
||||
if err == nil {
|
||||
equipInfo.Maintenance++
|
||||
err = dbdata.updateUserEquip(equipInfo)
|
||||
}
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.7]:", err))
|
||||
return
|
||||
}
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("鱼竿修复成功,耐久提高至", equipInfo.Durable, msg),
|
||||
),
|
||||
)
|
||||
})
|
||||
engine.OnRegex(`^附魔(诱钓|海之眷顾)$`, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
equipInfo, err := dbdata.getUserEquip(uid)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.7]:", err))
|
||||
return
|
||||
}
|
||||
if equipInfo.Equip == "" || equipInfo.Equip == "美西螈" {
|
||||
ctx.SendChain(message.Text("仅可对装备中的进行附魔"))
|
||||
return
|
||||
}
|
||||
book := ctx.State["regex_matched"].([]string)[1]
|
||||
books, err := dbdata.getUserThingInfo(uid, book)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.8]:", err))
|
||||
return
|
||||
}
|
||||
if len(books) == 0 {
|
||||
ctx.SendChain(message.Text("你的背包不存在", book, "进行附魔"))
|
||||
return
|
||||
}
|
||||
bookInfo := books[0]
|
||||
bookInfo.Number--
|
||||
err = dbdata.updateUserThingInfo(uid, bookInfo)
|
||||
number := 0
|
||||
if err == nil {
|
||||
if rand.Intn(100) > 50 {
|
||||
ctx.SendChain(message.Text("附魔失败了"))
|
||||
return
|
||||
}
|
||||
switch book {
|
||||
case "诱钓":
|
||||
equipInfo.Induce++
|
||||
if equipInfo.Induce > 3 {
|
||||
equipInfo.Induce = 3
|
||||
}
|
||||
number = equipInfo.Induce
|
||||
case "海之眷顾":
|
||||
equipInfo.Favor++
|
||||
if equipInfo.Favor > 3 {
|
||||
equipInfo.Favor = 3
|
||||
}
|
||||
number = equipInfo.Favor
|
||||
default:
|
||||
ctx.SendChain(message.Text("附魔失败了"))
|
||||
return
|
||||
}
|
||||
err = dbdata.updateUserEquip(equipInfo)
|
||||
}
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.9]:", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("附魔成功,", book, "等级提高至", enchantLevel[number]))
|
||||
})
|
||||
engine.OnRegex(`^合成(.+竿|三叉戟)$`, getdb).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
uid := ctx.Event.UserID
|
||||
thingList := []string{"木竿", "铁竿", "金竿", "钻石竿", "下界合金竿", "三叉戟"}
|
||||
thingName := ctx.State["regex_matched"].([]string)[1]
|
||||
indexOfMaterial := -1
|
||||
for i, name := range thingList {
|
||||
if thingName == name {
|
||||
indexOfMaterial = (i - 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
if indexOfMaterial < 0 {
|
||||
return
|
||||
}
|
||||
articles, err := dbdata.getUserThingInfo(uid, thingList[indexOfMaterial])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.10]:", err))
|
||||
return
|
||||
}
|
||||
max := len(articles)
|
||||
if max < 3 {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你的合成材料不足"))
|
||||
return
|
||||
}
|
||||
poles := make([]equip, 0, max)
|
||||
for _, info := range articles {
|
||||
poleInfo := strings.Split(info.Other, "/")
|
||||
durable, _ := strconv.Atoi(poleInfo[0])
|
||||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||||
poles = append(poles, equip{
|
||||
ID: uid,
|
||||
Equip: info.Name,
|
||||
Durable: durable,
|
||||
Maintenance: maintenance,
|
||||
Induce: induceLevel,
|
||||
Favor: favorLevel,
|
||||
})
|
||||
}
|
||||
list := []int{0, 1, 2}
|
||||
check := false
|
||||
if len(articles) > 3 {
|
||||
msg := make(message.Message, 0, 3+len(articles))
|
||||
msg = append(msg, message.Text("找到以下鱼竿:\n"))
|
||||
for i, info := range poles {
|
||||
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个序号进行合成(用空格分割),或回复“取消”取消"))
|
||||
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()
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
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
|
||||
}
|
||||
chooseList := strings.Split(nextcmd, " ")
|
||||
first, err := strconv.Atoi(chooseList[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.11.1]:", err))
|
||||
return
|
||||
}
|
||||
second, err := strconv.Atoi(chooseList[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.11.2]:", err))
|
||||
return
|
||||
}
|
||||
third, err := strconv.Atoi(chooseList[2])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.11.3]:", err))
|
||||
return
|
||||
}
|
||||
list = []int{first, second, third}
|
||||
if first == second || first == third || second == third {
|
||||
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))
|
||||
continue
|
||||
}
|
||||
check = true
|
||||
}
|
||||
if check {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
favorLevel := 0
|
||||
induceLevel := 0
|
||||
for _, index := range list {
|
||||
thingInfo := articles[index]
|
||||
thingInfo.Number = 0
|
||||
err = dbdata.updateUserThingInfo(uid, thingInfo)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[ERROR at pole.go.12]:", err))
|
||||
return
|
||||
}
|
||||
favorLevel += poles[index].Favor
|
||||
induceLevel += poles[index].Induce
|
||||
}
|
||||
if rand.Intn(100) >= 90 {
|
||||
ctx.Send(
|
||||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||||
message.Text("合成失败,材料已销毁"),
|
||||
),
|
||||
)
|
||||
return
|
||||
}
|
||||
attribute := strconv.Itoa(durationList[thingName]) + "/0/" + strconv.Itoa(induceLevel/3) + "/" + strconv.Itoa(favorLevel/3)
|
||||
newthing := article{
|
||||
Duration: time.Now().Unix(),
|
||||
Type: "pole",
|
||||
Name: thingName,
|
||||
Number: 1,
|
||||
Other: attribute,
|
||||
}
|
||||
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),
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user