Compare commits

...

69 Commits

Author SHA1 Message Date
源文雨
235ced0b78 🔖 v1.5.1 2022-10-16 12:59:24 +08:00
源文雨
3339b6a16f fix runcode 2022-10-15 14:12:36 +08:00
weigui404
c08e3dfe4a Update setu_geter.go (#452) 2022-10-15 10:23:24 +08:00
himawari
894cf41d37 🎨 优化鉴赏图片, 文本重用 (#451) 2022-10-14 20:47:34 +08:00
源文雨
55aa869b1a update deps 2022-10-14 14:30:05 +08:00
himawari
42b18619c3 Feature jptingroom (#448) 2022-10-14 13:58:52 +08:00
himawari
b0c57dfec5 Feature aipaint (#450) 2022-10-14 13:57:42 +08:00
himawari
bdbcf2a5f8 Feature alipayvoice (#449)
*  添加支付宝到账

*  添加readme
2022-10-14 13:53:20 +08:00
源文雨
7807e68519 add plugin Heisi 2022-10-13 11:13:43 +08:00
方柳煜
4cd81cb2e9 更新QQ音乐点歌API,修复猜歌panic (#444) 2022-10-12 23:45:31 +08:00
方柳煜
dc34a33346 修复tts默认语音设置不成功问题 (#445)
* Update main.go

* Update ai_tts.go
2022-10-12 23:43:52 +08:00
方柳煜
2922854f96 百度文心AI画图插件 (#442) 2022-10-12 16:44:05 +08:00
源文雨
29c85442ff update deps 2022-10-11 23:43:21 +08:00
源文雨
048cbf51ca update deps 2022-10-11 13:56:25 +08:00
方柳煜
467dd2ea65 猜歌插件更改为本地猜歌 (#439) 2022-10-11 00:06:50 +08:00
源文雨
aef678be5c Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-10-10 10:12:35 +08:00
源文雨
77f7567b29 fix: nwife dup slash & genshin vits 2022-10-10 10:12:23 +08:00
MoeMagicMango
c3c0685d3a fix:换成网易云官方的api (#440) 2022-10-09 23:12:09 +08:00
源文雨
c4c3f79c8c 💩👌 make lint happy 2022-10-08 10:57:01 +08:00
源文雨
9cb54a34da 🎨 优化bilibili 2022-10-07 12:21:20 +08:00
源文雨
519ae62760 fix breakrepeat shuffle 2022-10-07 10:49:55 +08:00
方柳煜
6971da1abc fix #433 修复重置之后第一个人娶群友不登记问题 (#435)
* Update command.go

* Update function.go

* Update command.go

* Update function.go
2022-10-07 10:26:23 +08:00
源文雨
5f3054d344 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-10-05 17:19:47 +08:00
源文雨
5b586a7402 💩👌 make lint happy 2022-10-05 17:18:51 +08:00
方柳煜
f2ff66ec1d 修复qqwife bug,优化程序 (#432)
* Update command.go

* Update function.go

* Update command.go
2022-10-05 17:18:02 +08:00
源文雨
92b9bab76a edit README 2022-10-05 12:23:29 +08:00
源文雨
4609985b79 优化代码结构 2022-10-05 12:09:09 +08:00
源文雨
6cf14fc7dd 🔖 v1.5.1-beta5 2022-10-04 22:19:11 +08:00
源文雨
053363f781 优化代码结构 2022-10-04 22:18:20 +08:00
源文雨
e319bd61f1 fix baseamasiro 2022-10-04 21:15:54 +08:00
源文雨
baad83172f fix gitcode 图床 2022-10-04 17:54:43 +08:00
源文雨
4b288a59b9 🐛 hyaku 2022-10-04 16:39:18 +08:00
源文雨
a2ada0b67e 🔥🐛 fix lazy data & add base天城文 2022-10-03 23:22:40 +08:00
莫思潋
97fea6a93a fix: []message.MessageSegment->message.Message (#429) 2022-10-03 19:54:39 +08:00
源文雨
145a9fb0b1 fix 64gua 2022-10-02 11:11:05 +08:00
源文雨
202d5e41a1 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-10-01 23:46:37 +08:00
源文雨
a64bead5e6 base64卦加解密 2022-10-01 23:46:28 +08:00
DreamZero
f9b84f8cb1 fix lolicon panic and more plugin use forward (#426)
* fix lolicon panic and more plugin use forward

* add back lolicon imgpool

* 带tag不使用缓存
2022-09-26 18:07:56 +08:00
方柳煜
76e0c13f89 好感度需发“重置所有花名册”才能使用 (#423)
* Update function.go

* Update command.go
2022-09-23 11:11:19 +08:00
源文雨
f9319c2a27 优化 breakrepeat 2022-09-22 11:14:24 +08:00
源文雨
295c50a0ae 调整 breakrepeat 优先级为最低 2022-09-22 10:55:44 +08:00
源文雨
942f5abbe4 🔖 v1.5.1-beta4 2022-09-22 10:49:59 +08:00
源文雨
965df40476 ⬆️ update deps 2022-09-22 10:47:11 +08:00
方柳煜
11f7f07009 扩展插件功能 (#422) 2022-09-22 10:40:26 +08:00
源文雨
76cd2afbd3 🔥 优化服务图片,删除服务详情 2022-09-21 13:55:52 +08:00
源文雨
00d07cb7af fix 2022-09-21 12:50:58 +08:00
源文雨
3234c18718 fix tts 2022-09-21 11:49:30 +08:00
源文雨
d48285c450 job 支持分群打印触发指令 2022-09-21 10:07:12 +08:00
源文雨
98ea387254 job cron 增加别名 2022-09-19 23:18:12 +08:00
源文雨
fb80ff3b74 🐛 优化 ban 2022-09-19 20:57:03 +08:00
源文雨
41e0cf8424 🐛 fix ban 2022-09-19 20:12:57 +08:00
源文雨
1bcd321477 🐛 fix ban 2022-09-19 19:49:29 +08:00
源文雨
b0482ee84b fix go.sum 2022-09-17 20:59:55 +08:00
源文雨
404f4041a9 🐛 fix b14 panic on some platform 2022-09-17 20:49:53 +08:00
源文雨
f6d6375667 🐛 fix b14 panic on some platform 2022-09-17 20:44:15 +08:00
源文雨
04acf4af49 Merge branch 'master' of https://github.com/FloatTech/ZeroBot-Plugin 2022-09-17 18:04:09 +08:00
源文雨
df6957cfb6 🔖 v1.5.1-beta3 2022-09-17 18:03:50 +08:00
himawari
d3ab1e1560 Refactor image (#419) 2022-09-17 14:53:25 +08:00
源文雨
598a255e34 make lint happy 2022-09-17 14:50:29 +08:00
源文雨
b4418fda55 🐛 fix 2022-09-17 14:42:26 +08:00
源文雨
3f26dde791 fix: /ban 2022-09-17 14:36:55 +08:00
MoeMagicMango
14d81411b1 Optimize: 更换经常出问题的iw233接口为MoeHu (#412) 2022-09-17 13:43:38 +08:00
莫思潋
4b667835f9 fix: 小鸡词典 (#410)
* - 调整触发器符合说明
- 减少查不到信息的情况
- 增加图片

* typo: imgURL

* - 改用foreach
- 增加被jikipedia封禁的提示

* 对于bilibili,在readme种引入了一键获取cookie工具

* 顺lint心意
2022-09-16 10:10:21 +08:00
莫思潋
002f971882 feat: 小鸡词典查梗 (#408) 2022-09-12 20:04:35 +08:00
源文雨
99a8fcd73a disable commit back 2022-09-12 20:02:39 +08:00
源文雨
3705da38b7 update deps 2022-09-12 19:58:46 +08:00
源文雨
32afee62c5 🐛 ban 人有时失灵 2022-09-12 19:21:46 +08:00
方柳煜
a5ecb4bf7d 修改tts指令使用权限,防止泛用滥用 (#400)
* 修改指令权限,防止泛用

* Update ai_tts.go

* Update ai_tts.go

* Update ai_tts.go
2022-09-12 18:53:53 +08:00
源文雨
1a424ebcd0 优化显示 2022-09-11 22:43:56 +08:00
67 changed files with 3587 additions and 2549 deletions

View File

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

View File

@@ -8,7 +8,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@master
with:
go-version: 1.18
go-version: 1.19
- name: Check out code into the Go module directory
uses: actions/checkout@master

View File

@@ -8,7 +8,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@master
with:
go-version: 1.18
go-version: 1.19
- name: Check out code into the Go module directory
uses: actions/checkout@master
@@ -17,12 +17,3 @@ jobs:
uses: golangci/golangci-lint-action@master
with:
version: latest
args: --issues-exit-code=0
- name: Commit back
continue-on-error: true
run: |
git config --local user.name 'github-actions[bot]'
git config --local user.email '41898282+github-actions[bot]@users.noreply.github.com'
git add --all
git commit -m "🎨 改进代码样式"
git push

View File

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

View File

@@ -62,7 +62,7 @@ run:
tests: false
skip-dirs:
- order
go: '1.18'
go: '1.19'
# output configuration options
output:

178
README.md
View File

@@ -250,7 +250,7 @@ zerobot [-c config.json] [-h] [-s config.json] [-t token] [-u url] [-n nickname]
- [x] 取消以"完全匹配关键词"触发的(代表我执行的)指令
- [x] 记录在"cron"触发的指令
- [x] 记录在"cron"触发的(别名xxx的)指令
- [x] 取消在"cron"触发的指令
@@ -346,6 +346,24 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 设置默认限速为每 m [分钟 | 秒] n 次触发
</details>
<details>
<summary>ai绘图</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aipaint"`
- [x] [ ai绘图 | 生成色图 | 生成涩图 | ai画图 ] xxx
- [x] [ 以图绘图 | 以图生图 | 以图画图 ] xxx [图片]|@xxx|[qq号]
- [ ] 设置ai绘图配置 [server] [token]
例1: 设置ai绘图配置 http://91.216.169.75:5010 abc
例2: 设置ai绘图配置 http://91.217.139.190:5010 abc
通过 http://91.217.139.190:5010/token 获取token
</details>
<details>
<summary>AIWife</summary>
@@ -354,6 +372,14 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] waifu | 随机waifu(从[100000个AI生成的waifu](https://www.thiswaifudoesnotexist.net/)中随机一位)
</details>
<details>
<summary>支付宝到账语音</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/alipayvoice"`
- [x] 支付宝到账 1
</details>
<details>
<summary>base16384加解密</summary>
@@ -376,6 +402,34 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 百度下[xxx]
</details>
<details>
<summary>base64卦加解密</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/base64gua"`
- [x] 六十四卦加密xxx
- [x] 六十四卦解密xxx
- [x] 六十四卦用yyy加密xxx
- [x] 六十四卦用yyy解密xxx
</details>
<details>
<summary>base天城文加解密</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/baseamasiro"`
- [x] 天城文加密xxx
- [x] 天城文解密xxx
- [x] 天城文用yyy加密xxx
- [x] 天城文用yyy解密xxx
</details>
<details>
<summary>bilibili</summary>
@@ -390,8 +444,10 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 查弹幕 [xxx] 2 (最后一个参数是页码)
- [x] 设置b站cookie SESSDATA=82da790d,1663822823,06ecf\*31 (最好把cookie设全)
- [x] 设置b站cookie b_ut=7;buvid3=0;i-wanna-go-back=-1;innersign=0; (最好把cookie设全)
获取Cookie可以使用[这个工具](https://github.com/XiaoMiku01/login_bili_go)
- [x] 更新vup
</details>
@@ -448,14 +504,6 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 藏尾诗[xxx]
</details>
<details>
<summary>英文字符翻转</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/char_reverser"`
- [x] 翻转 [英文字符串]
</details>
<details>
<summary>选择困难症帮手</summary>
@@ -472,6 +520,14 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 抽象翻译[xxx]
</details>
<details>
<summary>英文字符翻转</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/chrev"`
- [x] 翻转 I love you
</details>
<details>
<summary>coser</summary>
@@ -532,14 +588,26 @@ print("run[CQ:image,file="+j["img"]+"]")
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife"`
- 引入好感度系统,好感度越高,自由恋爱成功率越高
- [x] 设置CD为xx小时
- [x] 允许/禁止自由恋爱
- [x] 允许/禁止牛头人
- [x] 娶群友
- [x] (娶|嫁)[@对方QQ]
- [x] 当[对方Q号|@对方QQ]的小三
- [x] 做媒 @攻方QQ @受方QQ
- [x] 群老婆列表
- [x] 重置花名册
</details>
<details>
<summary>合成emoji</summary>
@@ -635,31 +703,43 @@ print("run[CQ:image,file="+j["img"]+"]")
- 猜歌插件该插件依赖ffmpeg
- [x] 设置猜歌缓存歌库路径 [绝对路径]
- 因为API不可抗因素更改为了本地猜歌但仍支持歌曲下载VIP歌曲无法下载黑胶可以
- [x] 设置猜歌[本地/Api] [true/false]
- [x] 设置猜歌歌库路径 [绝对路径]
- [x] 登录网易云
- [x] 猜歌[开启/关闭][歌单/歌词]自动下载
- 不登陆也能用API有几率返回400
- 现只有歌词指令有效
- [x] 添加歌单 [网易云歌单ID] [歌单名称]
- [ ] 添加歌单 [网易云歌单链接/ID] [歌单名称]
- 注:[歌单名称]可为空,默认原标题
- [x] 下载歌曲 [歌曲名称/网易云歌曲ID] [歌单名称]
- [x] 删除歌单 [网易云歌单ID/API歌单名称]
- [x] 删除歌单 [网易云歌单ID/歌单名称]
- [x] 获取歌单列表
-删除网易云歌单ID仅只是解除绑定删除歌单名称是将本地数据全部删除
- [x] [网易云歌单ID/API歌单名称]歌单信息
- [x] 设置猜歌默认歌单 [歌单名称]
- [x] 歌单列表
- [x] [个人/团队]猜歌
- 注:默认歌库为网易云ACG动画榜
- 注:默认歌库为歌单列表第一个,如果设置了默认歌单变为指定的歌单
- 可在后面添加[-歌单名称]进行指定歌单猜歌
- 可在“[个人/团队]猜歌指令”后面添加[-歌单名称]进行指定歌单猜歌
- 歌单的歌曲命名规则为:歌名 - 歌手 - 其他(歌曲出处之类)
- 猜歌内容必须以[-]开头才会识别
- 本地歌曲命名规则为:\n歌名 - 歌手 - 其他(歌曲出处之类)
</details>
<details>
<summary>黑丝</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/heisi"`
- [x] 来点黑丝/白丝/jk/巨乳/足控/网红
</details>
<details>
@@ -709,6 +789,28 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 更新[屌|弔|吊]图
</details>
<details>
<summary>小鸡词典</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/jikipedia"`
- [x] [查梗|小鸡词典][梗]
</details>
<details>
<summary>日语听力学习材料</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/jptingroom"`
- [x] 随机日语听力
- [x] 随机日语歌曲
- [x] 日语听力 xxx
- [x] 日语歌曲 xxx
</details>
<details>
<summary>绝绝子</summary>
@@ -723,7 +825,9 @@ print("run[CQ:image,file="+j["img"]+"]")
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon"`
- [x] 来份萝莉
- [x] 随机图片
- [x] 随机图片 萝莉|少女
- [x] 设置随机图片地址[http...]
@@ -903,11 +1007,11 @@ print("run[CQ:image,file="+j["img"]+"]")
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode"`
- [x] > runcode [language] help
- [x] >runcode [language] help
- [x] > runcode [language] [code block]
- [x] >runcode [language] [code block]
- [x] > runcoderaw [language] [code block]
- [x] >runcoderaw [language] [code block]
</details>
<details>
@@ -919,6 +1023,8 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 搜图[P站图片ID]
- [x] 设置 saucenao api key [apikey]
</details>
<details>
<summary>叔叔的AI二次元图片放大</summary>
@@ -1027,6 +1133,26 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 来份网易云热评
</details>
<details>
<summary>百度文心AI画图</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinAI"`
- 基于百度文心的免费AI画图插件(因为是免费的,图片质量你懂的)
- key申请链接https://wenxin.baidu.com/moduleApi/key
- [x] 为[自己/本群/QQ号/群+群号]设置AI画图key [API Key] [Secret Key]
-“为10086设置AI画图key 123 456”“为群10010设置AI画图key 789 101”
- [x] [bot名称]画几张[图片描述]的[图片类型][图片尺寸]
- 指令示例:
- 椛椛帮我画几张金凤凰背景绚烂高饱和古风仙境高清4K古风的油画方图
</details>
<details>
<summary>月幕galgame图</summary>

2
data

Submodule data updated: 5ce4b48c12...7bc1828db5

61
go.mod
View File

@@ -1,53 +1,54 @@
module github.com/FloatTech/ZeroBot-Plugin
go 1.18
go 1.19
require (
github.com/Coloured-glaze/gg v1.3.4
github.com/FloatTech/AnimeAPI v1.5.1-0.20220901132657-2585bbc03bf6
github.com/FloatTech/floatbox v0.0.0-20220822040527-f059031fec44
github.com/FloatTech/sqlite v0.3.3
github.com/FloatTech/AnimeAPI v1.5.2-0.20221015060924-fe2f85a3cf45
github.com/FloatTech/floatbox v0.0.0-20221011153549-68005767c531
github.com/FloatTech/sqlite v0.5.0
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
github.com/FloatTech/zbpctrl v1.4.1-0.20220715042842-93f081cb0133
github.com/FloatTech/zbputils v1.5.1-0.20220906163359-77457cb8fb65
github.com/FloatTech/zbpctrl v1.5.2-0.20221011153929-4834c6911511
github.com/FloatTech/zbputils v1.5.1-0.20221011154037-734498125e07
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c
github.com/antchfx/htmlquery v1.2.5
github.com/corona10/goimagehash v1.0.3
github.com/corona10/goimagehash v1.1.0
github.com/fumiama/ahsai v0.1.0
github.com/fumiama/cron v1.3.0
github.com/fumiama/go-base16384 v1.5.5
github.com/fumiama/go-base16384 v1.6.1
github.com/fumiama/go-registry v0.1.6
github.com/fumiama/gofastTEA v0.0.10
github.com/fumiama/gotracemoe v0.0.3
github.com/fumiama/sqlite3 v1.14.6
github.com/fumiama/unibase2n v0.0.0-20221003115227-e7db987de949
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/jinzhu/gorm v1.9.16
github.com/jozsefsallai/gophersauce v1.0.1
github.com/lucas-clemente/quic-go v0.27.2
github.com/lucas-clemente/quic-go v0.29.0
github.com/mroth/weightedrand v0.4.1
github.com/pkg/errors v0.9.1
github.com/pkumza/numcn v1.0.0
github.com/shirou/gopsutil/v3 v3.22.3
github.com/shirou/gopsutil/v3 v3.22.8
github.com/sirupsen/logrus v1.9.0
github.com/tidwall/gjson v1.14.2
github.com/tidwall/gjson v1.14.3
github.com/wcharczuk/go-chart/v2 v2.1.0
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220715040337-ef4327320c40
gitlab.com/gomidi/midi/v2 v2.0.17
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20221011153413-16c9a77ce4f0
gitlab.com/gomidi/midi/v2 v2.0.25
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69
)
require (
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc // indirect
github.com/antchfx/xpath v1.2.1 // indirect
github.com/cheekybits/genny v1.0.0 // indirect
github.com/disintegration/imaging v1.6.2 // indirect
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
github.com/faiface/beep v1.1.0 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/fumiama/gofastTEA v0.0.10 // 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/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hajimehoshi/oto v0.7.1 // indirect
github.com/jfreymuth/oggvorbis v1.0.1 // indirect
@@ -55,10 +56,9 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/marten-seemann/qpack v0.2.1 // indirect
github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.4 // indirect
@@ -69,17 +69,18 @@ require (
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8 // indirect
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6 // indirect
golang.org/x/mod v0.4.2 // indirect
golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48 // indirect
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/exp/shiny v0.0.0-20221004215720-b9f4876ce741 // indirect
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.1 // indirect
golang.org/x/tools v0.1.10 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
modernc.org/libc v1.16.19 // indirect
modernc.org/mathutil v1.4.1 // indirect
modernc.org/memory v1.1.1 // indirect
modernc.org/libc v1.19.0 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.4.0 // indirect
)

294
go.sum
View File

@@ -1,48 +1,31 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Coloured-glaze/gg v1.3.4 h1:l31zIF/HaVwkzjrj+A56RGQoSKyKuR1IWtIrqXGFStI=
github.com/Coloured-glaze/gg v1.3.4/go.mod h1:Ih5NLNNDHOy3RJbB0EPqGTreIzq/H02TGThIagh8HJg=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/FloatTech/AnimeAPI v1.5.1-0.20220901132657-2585bbc03bf6 h1:B4KmWFHA6zXjyvcubwV8MrxbKGLAudiVUGyxE9KojTc=
github.com/FloatTech/AnimeAPI v1.5.1-0.20220901132657-2585bbc03bf6/go.mod h1:R8jADxRo02AEuV6kOm+IcBGm7p/jqzngxOzK4y9EJRI=
github.com/FloatTech/floatbox v0.0.0-20220822040527-f059031fec44 h1:gnNO7tpxXpTuLuqIK9ekZScvDKt3jwHR+/rkDU838Nw=
github.com/FloatTech/floatbox v0.0.0-20220822040527-f059031fec44/go.mod h1:hK2HTQddBomA/sY2oD7VeW0GA5BxlIoYqcAOnamw1EU=
github.com/FloatTech/sqlite v0.3.3 h1:cSlpv+DcIehqaUG2YyjW0Twh396FoGsybpEpFZnX3Jg=
github.com/FloatTech/sqlite v0.3.3/go.mod h1:i33d92OtR8jcp5fBUvQtospf27+MkfUxnGwnZ95E/dA=
github.com/FloatTech/AnimeAPI v1.5.2-0.20221015060924-fe2f85a3cf45 h1:XbNlD0irJELgdR304TvqmFrxdH7hsxA/Ah9xLHFP3eQ=
github.com/FloatTech/AnimeAPI v1.5.2-0.20221015060924-fe2f85a3cf45/go.mod h1:RgcMDA1S7C81bq7HQjygMEEo+EXwAlsutvKMv7DafgY=
github.com/FloatTech/floatbox v0.0.0-20221011153549-68005767c531 h1:Z0yn6LFhEyC12hj+TBXc2P7/kWlCd/jlwv4JFndgpnw=
github.com/FloatTech/floatbox v0.0.0-20221011153549-68005767c531/go.mod h1:4tfIeB74L1RzhNp3nNjaTw8m3IEnc+q/k6k/MhL07ks=
github.com/FloatTech/sqlite v0.5.0 h1:U7J5Omc534PqmH6csfu+ypCo3DS8L91l5lTsxUu3b/U=
github.com/FloatTech/sqlite v0.5.0/go.mod h1:i33d92OtR8jcp5fBUvQtospf27+MkfUxnGwnZ95E/dA=
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.4.1-0.20220715042842-93f081cb0133 h1:nP9NI4I+vtwAbiU7wCJwjuzCzMZ/yJYg8h3667HGnv0=
github.com/FloatTech/zbpctrl v1.4.1-0.20220715042842-93f081cb0133/go.mod h1:72BnjyBwQWUC8mqM9dPk5ZrjxXCilQCVp+jfgHATNdw=
github.com/FloatTech/zbputils v1.5.1-0.20220906163359-77457cb8fb65 h1:ztINgRoUNLQBOJ8g0IVNdkf1DrRUioRoSIflqvPSOao=
github.com/FloatTech/zbputils v1.5.1-0.20220906163359-77457cb8fb65/go.mod h1:ZT91eCYR6y1HbLRTO5EB7o8K7qEPbCsX7vjhYIuMijc=
github.com/FloatTech/zbpctrl v1.5.2-0.20221011153929-4834c6911511 h1:i2+JjTRR7gW8n1KivMKj3NEsCEEllYp8jneeOyg1Lz0=
github.com/FloatTech/zbpctrl v1.5.2-0.20221011153929-4834c6911511/go.mod h1:TC5RkmSwKJvkDV+7vlTpcY+rnviB5gBq6JNOKnfZXHc=
github.com/FloatTech/zbputils v1.5.1-0.20221011154037-734498125e07 h1:nG1q2NJZPehyV0xk88WHtqgwsOohkEDMFu/8v9rN1/o=
github.com/FloatTech/zbputils v1.5.1-0.20221011154037-734498125e07/go.mod h1:UYuWZBInYdGZOXxEazrvaJE8nYGRB4xxoaacX6nKosk=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c h1:cNPOdTNiVwxLpROLjXCgbIPvdkE+BwvxDvgmdYmWx6Q=
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c/go.mod h1:KqZzu7slNKROh3TSYEH/IUMG6f4M+1qubZ5e52QypsE=
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc h1:AAx50/fb/xS4lvsdQg+bFbGvqSDhyV1MF+p2PLCamZ0=
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc/go.mod h1:OMmITAib6POA37xCichWM0aRnoVpSMZO1rB/G01wrr0=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antchfx/htmlquery v1.2.5 h1:1lXnx46/1wtv1E/kzmH8vrfMuUKYgkdDBA9pIdMJnk4=
github.com/antchfx/htmlquery v1.2.5/go.mod h1:2MCVBzYVafPBmKbrmwB9F5xdd+IEgRY61ci2oOsOQVw=
github.com/antchfx/xpath v1.2.1 h1:qhp4EW6aCOVr5XIkT+l6LJ9ck/JsUH/yyauNgTQkBF8=
github.com/antchfx/xpath v1.2.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/corona10/goimagehash v1.0.3 h1:NZM518aKLmoNluluhfHGxT3LGOnrojrxhGn63DR/CZA=
github.com/corona10/goimagehash v1.0.3/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
github.com/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI=
github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -58,8 +41,6 @@ github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DP
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/faiface/beep v1.1.0 h1:A2gWP6xf5Rh7RG/p9/VAW2jRSDEGQm5sbOb38sf5d4c=
github.com/faiface/beep v1.1.0/go.mod h1:6I8p6kK2q4opL/eWb+kAkk38ehnTunWeToJB+s51sT4=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@@ -67,8 +48,8 @@ github.com/fumiama/ahsai v0.1.0 h1:LXD61Kaj6kJHa3AEGsLIfKNzcgaVxg7JB72OR4yNNZ4=
github.com/fumiama/ahsai v0.1.0/go.mod h1:fFeNnqgo44i8FIaguK659aQryuZeFy+4klYLQu/rfdk=
github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
github.com/fumiama/go-base16384 v1.5.5 h1:gsJW5GVfD0gV18/DnntWU4vDnaCvT5ysK0m2jkCqhU0=
github.com/fumiama/go-base16384 v1.5.5/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
github.com/fumiama/go-base16384 v1.6.1 h1:4yb4JgmBJDnQtq3XGXXdLrVwEnRpjhMUt4eAcsNeA30=
github.com/fumiama/go-base16384 v1.6.1/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
github.com/fumiama/go-registry v0.1.6 h1:Ee/tXCCIR/xt8celhbbw0W/xDMdhAXLwy2YFBB/LWFk=
github.com/fumiama/go-registry v0.1.6/go.mod h1:dIUVbiOgfk9oZcsgwDvNLC72i+ctibVukSXR/9bLviI=
github.com/fumiama/gofastTEA v0.0.10 h1:JJJ+brWD4kie+mmK2TkspDXKzqq0IjXm89aGYfoGhhQ=
@@ -77,70 +58,47 @@ github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
github.com/fumiama/sqlite3 v1.14.6 h1:+e+iygyiDXQJVi7xeXIviBvR7hAc5y20WA9hRwfKn10=
github.com/fumiama/sqlite3 v1.14.6/go.mod h1:Xx9a2/OtHuy9pBjow0N+bE/RhNeZ7zZz5xh25vqbA5A=
github.com/fumiama/unibase2n v0.0.0-20221003115227-e7db987de949 h1:VAzR8aoS2SCEBmRF9rqCPyXgXoP8mZ1viNL4mLWUg0Q=
github.com/fumiama/unibase2n v0.0.0-20221003115227-e7db987de949/go.mod h1:lEaZsT4FRSqcjnQ5q8y+mkenkzR/r1D3BJmfdp0vqDg=
github.com/gabriel-vasile/mimetype v1.0.4 h1:uBejfH8l3/2f+5vjl1e4xIaSyNEhRBZ5N/ij7ohpNd8=
github.com/gabriel-vasile/mimetype v1.0.4/go.mod h1:6CDPel/o/3/s4+bp6kIbsWATq8pmgOisOPG40CJa6To=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-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-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-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/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hajimehoshi/go-mp3 v0.3.0/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto v0.7.1 h1:I7maFPz5MBCwiutOrz++DLdbr4rTzBsbBuV2VpgU9kk=
@@ -148,7 +106,6 @@ github.com/hajimehoshi/oto v0.7.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6Ee
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/icza/bitio v1.0.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A=
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jfreymuth/oggvorbis v1.0.1 h1:NT0eXBgE2WHzu6RT/6zcb2H10Kxj6Fm3PccT0LE6bqw=
github.com/jfreymuth/oggvorbis v1.0.1/go.mod h1:NqS+K+UXKje0FUYUPosyQ+XTVvjmVjps1aEZH1sumIk=
github.com/jfreymuth/vorbis v1.0.0 h1:SmDf783s82lIjGZi8EGUUaS7YxPHgRj4ZXW/h7rUi7U=
@@ -161,47 +118,30 @@ github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jozsefsallai/gophersauce v1.0.1 h1:BA3ovtQRrAb1qYU9JoRLbDHpxnDunlNcEkEfhCvDDCM=
github.com/jozsefsallai/gophersauce v1.0.1/go.mod h1:YVEI7djliMTmZ1Vh01YPF8bUHi+oKhe3yXgKf1T49vg=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lucas-clemente/quic-go v0.27.2 h1:zsMwwniyybb8B/UDNXRSYee7WpQJVOcjQEGgpw2ikXs=
github.com/lucas-clemente/quic-go v0.27.2/go.mod h1:vXgO/11FBSKM+js1NxoaQ/bPtVFYfB7uxhfHXyMhl1A=
github.com/lucas-clemente/quic-go v0.29.0 h1:Vw0mGTfmWqGzh4jx/kMymsIkFK6rErFVmg+t9RLrnZE=
github.com/lucas-clemente/quic-go v0.29.0/go.mod h1:CTcNfLYJS2UuRNB+zcNlgvkjBhxX6Hm3WUxxAQx2mgE=
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs=
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ=
github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk=
github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ=
github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s=
github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM=
github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
github.com/marten-seemann/qtls-go1-19 v0.1.0 h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK5df3GufyYYU=
github.com/marten-seemann/qtls-go1-19 v0.1.0/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mewkiz/flac v1.0.7/go.mod h1:yU74UH277dBUpqxPouHSQIar3G1X/QIclVbFahSd1pU=
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2/go.mod h1:3E2FUC/qYUfM8+r9zAwpeHJzqRVVMIYnpzD/clwWxyA=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mroth/weightedrand v0.4.1 h1:rHcbUBopmi/3x4nnrvwGJBhX9d0vk+KgoLUZeDP6YyI=
github.com/mroth/weightedrand v0.4.1/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@@ -210,14 +150,11 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -227,51 +164,21 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil/v3 v3.22.3 h1:UebRzEomgMpv61e3hgD1tGooqX5trFbdU/ehphbHd00=
github.com/shirou/gopsutil/v3 v3.22.3/go.mod h1:D01hZJ4pVHPpCTZ3m3T2+wDF2YAGfd+H4ifUguaQzHM=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/shirou/gopsutil/v3 v3.22.8 h1:a4s3hXogo5mE2PfdfJIonDbstO/P+9JszdfhAHSzD9Y=
github.com/shirou/gopsutil/v3 v3.22.8/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
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 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/tidwall/gjson v1.14.2 h1:6BBkirS0rAHjumnjHF6qgy5d2YAJ1TLIaFE2lzfOLqo=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
@@ -280,57 +187,52 @@ github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03O
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220715040337-ef4327320c40 h1:j+cmfkjc8WcBKiOsvMzcIgAuPhiTs7FBeiRn/QLVFhA=
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20220715040337-ef4327320c40/go.mod h1:LJ+VOf523i3IrykuLK53UEeWqnAclRL5d2wGT4sS4Zk=
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20221011153413-16c9a77ce4f0 h1:IKWX0c7b3URoFDt5ezD6wa0AZIQ0EY0GbPVhYfuzXug=
github.com/wdvxdr1123/ZeroBot v1.5.2-0.20221011153413-16c9a77ce4f0/go.mod h1:shG/ruauisKaVcov4amrFJtkeDl7nl+Q00IXB2PqFsc=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
gitlab.com/gomidi/midi/v2 v2.0.17 h1:kf16wNwFFOskl0trvarOwMuZUQICdIGn37LP9QqIRuo=
gitlab.com/gomidi/midi/v2 v2.0.17/go.mod h1:quTyMKSQ4Klevxu6gY4gy2USbeZra0fV5SalndmPfsY=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
gitlab.com/gomidi/midi/v2 v2.0.25 h1:dkzVBqbaFHjyWwP71MrQNX7IeRUIDonddmHbPpO/Ucg=
gitlab.com/gomidi/midi/v2 v2.0.25/go.mod h1:quTyMKSQ4Klevxu6gY4gy2USbeZra0fV5SalndmPfsY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8 h1:idBdZTd9UioThJp8KpM/rTSinK/ChZFBE43/WtIy8zg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
golang.org/x/exp/shiny v0.0.0-20221004215720-b9f4876ce741 h1:b7y8iQCnzOE0NhgpMj2yHw17Us+lhXxFbdzKlTpqm5I=
golang.org/x/exp/shiny v0.0.0-20221004215720-b9f4876ce741/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8=
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539 h1:/eM0PCrQI2xd471rI+snWuu251/+/jpBpZqir2mPdnU=
golang.org/x/image v0.0.0-20220722155232-062f8c9fd539/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6 h1:vyLBGJPIl9ZYbcQFM2USFmJBK6KI+t+z6jL0lbwjrnc=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f h1:kgfVkAEEQXXQ0qc6dH7n6y37NAYmTFmz0YRwrRjgxKw=
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -340,27 +242,15 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48 h1:N9Vc/rorQUDes6B9CNdIxAn5jODGj2wzfrei2x4wNj4=
golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -369,7 +259,6 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -378,87 +267,55 @@ golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 h1:9vYwv7OjYaky/tlAeD7C4oC9EsPTlaFl1H2jS++V+ME=
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc=
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-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.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
@@ -561,19 +418,18 @@ modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34=
modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ=
modernc.org/libc v1.14.5/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
modernc.org/libc v1.16.19 h1:S8flPn5ZeXx6iw/8yNa986hwTQDrY8RXU7tObZuAozo=
modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
modernc.org/libc v1.19.0 h1:bXyVhGQg6KIClTr8FMVIDPl7jtbcs7aS5WP7vLDaxPs=
modernc.org/libc v1.19.0/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU=
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

View File

@@ -2,21 +2,17 @@ package kanban
import (
"fmt"
"strings"
"github.com/fumiama/go-registry"
)
var (
info = [...]string{
"* OneBot + ZeroBot + Golang",
"* Version 1.5.1-beta2 - 2022-09-11 10:32:06 +0800 CST",
"* Copyright © 2020 - 2022 FloatTech. All Rights Reserved.",
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
}
// Banner ...
Banner = strings.Join(info[:], "\n")
reg = registry.NewRegReader("reilia.fumiama.top:32664", "fumiama")
Banner = "* OneBot + ZeroBot + Golang\n" +
"* Version 1.5.1 - 2022-10-16 12:58:18 +0800 CST\n" +
"* Copyright © 2020 - 2022 FloatTech. All Rights Reserved.\n" +
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
reg = registry.NewRegReader("reilia.fumiama.top:32664", "fumiama")
)
// PrintBanner ...

View File

@@ -1,6 +1,12 @@
// Package kanban 打印版本信息
package kanban
import (
"sync"
)
var once sync.Once
func init() {
PrintBanner()
once.Do(PrintBanner)
}

14
main.go
View File

@@ -60,16 +60,19 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ahsai" // ahsai tts
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_false" // 服务器监控
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aipaint" // ai绘图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/alipayvoice" // 支付宝到账语音
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/b14" // base16384加解密
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu" // 百度一下
_ "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/breakrepeat" // 打断复读
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cangtoushi" // 藏头诗
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/char_reverser" // 英文字符翻转
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/choose" // 选择困难症帮手
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chouxianghua" // 说抽象话
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chrev" // 英文字符翻转
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/coser" // 三次元小姐姐
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/cpstory" // cp短打
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/danbooru" // DeepDanbooru二次元图标签识别
@@ -85,11 +88,14 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/gif" // 制图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/github" // 搜索GitHub仓库
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/guessmusic" // 猜歌
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/heisi" // 黑丝
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs" // 炉石
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hyaku" // 百人一首
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/image_finder" // 关键字搜图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/inject" // 注入指令
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jandan" // 煎蛋网无聊图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jikipedia" // 小鸡词典
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/jptingroom" // 日语听力学习材料
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/juejuezi" // 绝绝子生成器
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/lolicon" // lolicon 随机图片
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/midicreate" // 简易midi音乐制作
@@ -119,6 +125,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/translation" // 翻译
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtb_quotation" // vtb语录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun" // 网易云音乐热评
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinAI" // 百度文心AI画图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count" // 聊天热词
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wordle" // 猜单词
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ymgal" // 月幕galgame
@@ -147,6 +154,8 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ai_reply" // 人工智能回复
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/breakrepeat" // 打断复读
// ^^^^ //
// ^^^^^^^^^^^^^^ //
// ^^^^^^^低优先级区^^^^^^^ //
@@ -193,7 +202,6 @@ func init() {
flag.Parse()
if *h {
kanban.PrintBanner()
fmt.Println("Usage:")
flag.PrintDefaults()
os.Exit(0)

View File

@@ -1,28 +1,18 @@
package aireply
import (
"fmt"
"net/url"
"errors"
"regexp"
"strconv"
"sync"
"time"
"github.com/pkumza/numcn"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/AnimeAPI/aireply"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
)
const (
ttsServiceName = "tts"
cnapi = "http://233366.proxy.nscc-gz.cn:8888?speaker=%s&text=%s"
// testString = "这是测试语言......"
cnapi = "https://genshin.azurewebsites.net/api/speak?format=mp3&id=%d&text=%s"
)
// 每个角色的测试文案
@@ -95,10 +85,54 @@ var (
}
)
type ttsInstances struct {
/*************************************************************
*******************************AIreply************************
*************************************************************/
func setReplyMode(ctx *zero.Ctx, name string) error {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
var ok bool
var index int64
for i, s := range replyModes {
if s == name {
ok = true
index = int64(i)
break
}
}
if !ok {
return errors.New("no such mode")
}
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
return errors.New("no such plugin")
}
return m.SetData(gid, index)
}
func getReplyMode(ctx *zero.Ctx) (name string) {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
index := m.GetData(gid)
if int(index) < len(replyModes) {
return replyModes[index]
}
}
return "青云客"
}
/*************************************************************
***********************tts************************************
*************************************************************/
type ttsmode struct {
sync.RWMutex
defaultSoundMode string
soundMode []string
mode map[int64]int64
}
func list(list []string, num int) string {
@@ -114,146 +148,91 @@ func list(list []string, num int) string {
return s
}
func init() {
tts := &ttsInstances{
defaultSoundMode: "派蒙",
soundMode: soundList[:],
func newttsmode() *ttsmode {
tts := &ttsmode{}
tts.Lock()
defer tts.Unlock()
m, ok := control.Lookup(ttsServiceName)
tts.mode = make(map[int64]int64, 2*len(soundList))
tts.mode[-2905] = 1
if ok {
index := m.GetData(-2905)
if index > 0 && index < int64(len(soundList)) {
tts.mode[-2905] = index
}
}
engine := control.Register(ttsServiceName, &ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Help: "语音回复(大家一起来炼丹)\n" +
"- @Bot 任意文本(任意一句话回复)\n" +
"- 设置语音模式[原神人物]\n" +
"- 设置默认语音模式[原神人物]\n" +
"当前适用的原神人物含有以下:\n" + list(soundList[:], 5),
})
engine.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
msg := ctx.ExtractPlainText()
// 获取回复模式
r := aireply.NewAIReply(getReplyMode(ctx))
// 获取回复的文本
reply := r.TalkPlain(msg, zero.BotConfig.NickName[0])
// 获取角色
name := tts.getSoundMode(ctx)
if _, ok := testRecord[name]; !ok {
ctx.SendChain(message.Text("配置的语言人物数据丢失!请重新设置语言人物。"))
return
}
// 获取语言
record := message.Record(fmt.Sprintf(cnapi, url.QueryEscape(name), url.QueryEscape(
// 将数字转文字
re.ReplaceAllStringFunc(reply, func(s string) string {
f, err := strconv.ParseFloat(s, 64)
if err != nil {
log.Errorln("[tts]:", err)
return s
}
return numcn.EncodeFromFloat64(f)
}),
))).Add("cache", 0)
if record.Data == nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
}
// 发送语音
if ID := ctx.SendChain(record); ID.ID() == 0 {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
}
})
engine.OnRegex(`^设置语音模式(.*)$`, func(ctx *zero.Ctx) bool {
param := ctx.State["regex_matched"].([]string)[1]
if _, ok := testRecord[param]; !ok {
return false
}
return true
}).SetBlock(true).Handle(func(ctx *zero.Ctx) {
param := ctx.State["regex_matched"].([]string)[1]
// 保存设置
err := tts.setSoundMode(ctx, param)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
// 设置验证
name := tts.getSoundMode(ctx)
if _, ok := testRecord[name]; !ok {
ctx.SendChain(message.Text("配置的语言人物数据丢失!请重新设置语言人物。"))
return
}
record := message.Record(fmt.Sprintf(cnapi, url.QueryEscape(name), url.QueryEscape(testRecord[name]))).Add("cache", 0)
if ID := ctx.SendChain(record); 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("设置成功,默认模式为", name))
})
engine.OnRegex(`^设置默认语音模式(.*)$`, func(ctx *zero.Ctx) bool {
param := ctx.State["regex_matched"].([]string)[1]
if _, ok := testRecord[param]; !ok {
return false
}
return true
}).SetBlock(true).Handle(func(ctx *zero.Ctx) {
param := ctx.State["regex_matched"].([]string)[1]
// 保存设置
tts.setDefaultSoundMode(param)
// 设置验证
name := tts.defaultSoundMode
record := message.Record(fmt.Sprintf(cnapi, url.QueryEscape(name), url.QueryEscape(testRecord[name]))).Add("cache", 0)
if ID := ctx.SendChain(record); 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("设置成功,默认模式为", name))
})
return tts
}
func (tts *ttsInstances) setSoundMode(ctx *zero.Ctx, name string) error {
func (tts *ttsmode) setSoundMode(ctx *zero.Ctx, name string) error {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
var index int64
tts.RLock()
for i, s := range tts.soundMode {
for i, s := range soundList {
if s == name {
index = int64(i)
index = int64(i + 1)
break
}
}
tts.RUnlock()
if index == 0 {
return errors.New("不支持设置语音人物" + name)
}
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
tts.Lock()
defer tts.Unlock()
tts.mode[gid] = index
return m.SetData(gid, index)
}
func (tts *ttsInstances) getSoundMode(ctx *zero.Ctx) (name string) {
func (tts *ttsmode) getSoundMode(ctx *zero.Ctx) int64 {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
tts.RLock()
defer tts.RUnlock()
index := m.GetData(gid)
if int(index) < len(tts.soundMode) {
return tts.soundMode[index]
}
tts.Lock()
defer tts.Unlock()
i, ok := tts.mode[gid]
if !ok {
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
i = m.GetData(gid)
}
return tts.defaultSoundMode
if i <= 0 || i >= int64(len(soundList)) {
i = tts.mode[-2905]
}
return i - 1
}
func (tts *ttsInstances) setDefaultSoundMode(name string) {
func (tts *ttsmode) resetSoundMode(ctx *zero.Ctx) error {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
tts.Lock()
defer tts.Unlock()
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
tts.mode[gid] = 0
return m.SetData(gid, 0) // 重置数据
}
func (tts *ttsmode) setDefaultSoundMode(name string) error {
var index int64
tts.RLock()
for i, s := range tts.soundMode {
for i, s := range soundList {
if s == name {
index = int64(i)
index = int64(i + 1)
break
}
}
tts.defaultSoundMode = tts.soundMode[index]
tts.RUnlock()
if index == 0 {
return errors.New("不支持设置语音人物" + name)
}
tts.Lock()
defer tts.Unlock()
m, ok := control.Lookup(ttsServiceName)
if !ok {
return errors.New("[tts] service not found")
}
tts.mode[-2905] = index
return m.SetData(-2905, index)
}

View File

@@ -2,31 +2,48 @@
package aireply
import (
"errors"
"fmt"
"net/url"
"strconv"
"time"
"github.com/FloatTech/AnimeAPI/aireply"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/pkumza/numcn"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
replyServiceName = "aireply"
ttsServiceName = "tts"
)
var replyModes = [...]string{"青云客", "小爱"}
func init() { // 插件主体
engine := control.Register(replyServiceName, &ctrl.Options[*zero.Ctx]{
enOftts := control.Register(ttsServiceName, &ctrl.Options[*zero.Ctx]{
DisableOnDefault: true,
Help: "语音回复(大家一起来炼丹)\n" +
"- @Bot 任意文本(任意一句话回复)\n" +
"- 设置语音模式[原神人物]\n" +
"- 设置默认语音模式[原神人物]\n" +
"- 恢复成默认语音模式\n" +
"当前适用的原神人物含有以下:\n" + list(soundList[:], 5),
})
tts := newttsmode()
enOfreply := control.Register(replyServiceName, &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "人工智能回复\n" +
"- @Bot 任意文本(任意一句话回复)\n- 设置回复模式[青云客|小爱]",
})
// 回复 @和包括名字
engine.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
/*************************************************************
*******************************AIreply************************
*************************************************************/
enOfreply.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
aireply := aireply.NewAIReply(getReplyMode(ctx))
reply := message.ParseMessageFromString(aireply.Talk(ctx.ExtractPlainText(), zero.BotConfig.NickName[0]))
@@ -39,53 +56,95 @@ func init() { // 插件主体
}
ctx.Send(reply)
})
engine.OnPrefix(`设置回复模式`).SetBlock(true).
enOfreply.OnPrefix("设置回复模式", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
param := ctx.State["args"].(string)
err := setReplyMode(ctx, param)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功"))
})
/*************************************************************
***********************tts************************************
*************************************************************/
enOftts.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
param := ctx.State["args"].(string)
err := setReplyMode(ctx, param)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
msg := ctx.ExtractPlainText()
// 获取回复模式
r := aireply.NewAIReply(getReplyMode(ctx))
// 获取回复的文本
reply := r.TalkPlain(msg, zero.BotConfig.NickName[0])
// 获取语音
index := tts.getSoundMode(ctx)
record := message.Record(fmt.Sprintf(cnapi, index, url.QueryEscape(
// 将数字转文字
re.ReplaceAllStringFunc(reply, func(s string) string {
f, err := strconv.ParseFloat(s, 64)
if err != nil {
log.Errorln("[tts]:", err)
return s
}
return numcn.EncodeFromFloat64(f)
}),
))).Add("cache", 0)
// 发送语音
if ID := ctx.SendChain(record); ID.ID() == 0 {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功"))
})
}
func setReplyMode(ctx *zero.Ctx, name string) error {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
var ok bool
var index int64
for i, s := range replyModes {
if s == name {
ok = true
index = int64(i)
break
enOftts.OnRegex(`^设置语音模式(.*)$`, zero.AdminPermission, func(ctx *zero.Ctx) bool {
param := ctx.State["regex_matched"].([]string)[1]
if _, ok := testRecord[param]; !ok {
return false
}
}
if !ok {
return errors.New("no such mode")
}
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if !ok {
return errors.New("no such plugin")
}
return m.SetData(gid, index)
}
func getReplyMode(ctx *zero.Ctx) (name string) {
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
m, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
if ok {
index := m.GetData(gid)
if int(index) < len(replyModes) {
return replyModes[index]
return true
}).SetBlock(true).Handle(func(ctx *zero.Ctx) {
param := ctx.State["regex_matched"].([]string)[1]
// 保存设置
err := tts.setSoundMode(ctx, param)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
}
return "青云客"
// 设置验证
i := tts.getSoundMode(ctx)
if _, ok := testRecord[soundList[i]]; !ok {
ctx.SendChain(message.Text("配置的语音人物数据丢失!请重新设置语音人物。"))
return
}
record := message.Record(fmt.Sprintf(cnapi, i, url.QueryEscape(testRecord[soundList[i]]))).Add("cache", 0)
if ID := ctx.SendChain(record); 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("设置成功"))
})
enOftts.OnRegex(`^设置默认语音模式(.*)$`, zero.SuperUserPermission, func(ctx *zero.Ctx) bool {
param := ctx.State["regex_matched"].([]string)[1]
if _, ok := testRecord[param]; !ok {
return false
}
return true
}).SetBlock(true).Handle(func(ctx *zero.Ctx) {
param := ctx.State["regex_matched"].([]string)[1]
// 保存设置
err := tts.setDefaultSoundMode(param)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功"))
})
enOftts.OnFullMatch("恢复成默认语音模式", zero.AdminPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
err := tts.resetSoundMode(ctx)
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(err))
return
}
// 设置验证
index := tts.getSoundMode(ctx)
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("设置成功,当前为", soundList[index]))
})
}

167
plugin/aipaint/aipaint.go Normal file
View File

@@ -0,0 +1,167 @@
// Package aipaint ai绘图
package aipaint
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"image"
"net/url"
"os"
"regexp"
"strconv"
"strings"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var (
datapath string
predictRe = regexp.MustCompile(`{"steps".+?}`)
// 参考host http://91.217.139.190:5010 http://91.216.169.75:5010
aipaintTxt2ImgURL = "/got_image?token=%v&tags=%v"
aipaintImg2ImgURL = "/got_image2image?token=%v&tags=%v"
cfg = newServerConfig("data/aipaint/config.json")
)
type result struct {
Steps int `json:"steps"`
Sampler string `json:"sampler"`
Seed int `json:"seed"`
Strength float64 `json:"strength"`
Noise float64 `json:"noise"`
Scale float64 `json:"scale"`
Uc string `json:"uc"`
}
func (r *result) String() string {
return fmt.Sprintf("steps: %v\nsampler: %v\nseed: %v\nstrength: %v\nnoise: %v\nscale: %v\nuc: %v\n", r.Steps, r.Sampler, r.Seed, r.Strength, r.Noise, r.Scale, r.Uc)
}
func init() { // 插件主体
engine := control.Register("aipaint", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "ai绘图\n" +
"- [ ai绘图 | 生成色图 | 生成涩图 | ai画图 ] xxx\n" +
"- [ 以图绘图 | 以图生图 | 以图画图 ] xxx [图片]|@xxx|[qq号]\n" +
"- 设置ai绘图配置 [server] [token]\n" +
"例1: 设置ai绘图配置 http://91.216.169.75:5010 abc\n" +
"例2: 设置ai绘图配置 http://91.217.139.190:5010 abc\n" +
"通过 http://91.217.139.190:5010/token 获取token",
PrivateDataFolder: "aipaint",
})
datapath = file.BOTPATH + "/" + engine.DataFolder()
engine.OnPrefixGroup([]string{`ai绘图`, `生成色图`, `生成涩图`, `ai画图`}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
server, token, err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("少女祈祷中..."))
args := ctx.State["args"].(string)
data, err := web.GetData(server + fmt.Sprintf(aipaintTxt2ImgURL, token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20")))))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
sendAiImg(ctx, data)
})
engine.OnRegex(`^(以图绘图|以图生图|以图画图)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
server, token, err := cfg.load()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
c := newContext(ctx.Event.UserID)
list := ctx.State["regex_matched"].([]string)
err = c.prepareLogos(list[4]+list[5]+list[6], strconv.FormatInt(ctx.Event.UserID, 10))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
args := strings.TrimSuffix(strings.TrimPrefix(list[0], list[1]), list[2])
if args == "" {
ctx.SendChain(message.Text("ERROR: 以图绘图必须添加tag"))
return
}
ctx.SendChain(message.Text("少女祈祷中..."))
postURL := server + fmt.Sprintf(aipaintImg2ImgURL, token, url.QueryEscape(strings.TrimSpace(strings.ReplaceAll(args, " ", "%20"))))
f, err := os.Open(c.headimgsdir[0])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
defer f.Close()
img, _, err := image.Decode(f)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
imageShape := ""
switch {
case img.Bounds().Dx() > img.Bounds().Dy():
imageShape = "Landscape"
case img.Bounds().Dx() == img.Bounds().Dy():
imageShape = "Square"
default:
imageShape = "Portrait"
}
// 图片转base64
base64Bytes, err := writer.ToBase64(img)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
data, err := web.PostData(postURL+"&shape="+imageShape, "text/plain", bytes.NewReader(base64Bytes))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
sendAiImg(ctx, data)
})
engine.OnRegex(`^设置ai绘图配置\s(.*[^\s$])\s(.+)$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
regexMatched := ctx.State["regex_matched"].([]string)
err := cfg.save(regexMatched[1], regexMatched[2])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("成功设置server为", regexMatched[1], ", token为", regexMatched[2]))
})
}
func sendAiImg(ctx *zero.Ctx, data []byte) {
var loadData string
if predictRe.MatchString(binary.BytesToString(data)) {
loadData = predictRe.FindStringSubmatch(binary.BytesToString(data))[0]
}
var r result
if loadData != "" {
err := json.Unmarshal(binary.StringToBytes(loadData), &r)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
}
encodeStr := base64.StdEncoding.EncodeToString(data)
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image("base64://"+encodeStr))}
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(r.String())))
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
}

54
plugin/aipaint/config.go Normal file
View File

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

39
plugin/aipaint/context.go Normal file
View File

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

View File

@@ -0,0 +1,32 @@
// Package alipayvoice 支付宝到账语音
package alipayvoice
import (
"fmt"
"strings"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
alipayvoiceURL = "https://mm.cqu.cc/share/zhifubaodaozhang/mp3/%v.mp3"
)
func init() { // 插件主体
engine := control.Register("alipayvoice", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "支付宝到账语音\n" +
"- 支付宝到账 1",
PrivateDataFolder: "alipayvoice",
})
// 开启
engine.OnPrefix(`支付宝到账`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
args := ctx.State["args"].(string)
ctx.SendChain(message.Record(fmt.Sprintf(alipayvoiceURL, strings.TrimSpace(args))))
})
}

View File

@@ -2,12 +2,10 @@
package b14coder
import (
"unsafe"
"github.com/FloatTech/floatbox/crypto"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
base14 "github.com/fumiama/go-base16384"
tea "github.com/fumiama/gofastTEA"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
@@ -42,7 +40,7 @@ func init() {
en.OnRegex(`^用(.+)加密\s*(.+)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := getea(key)
t := crypto.GetTEA(key)
es, err := base14.UTF16BE2UTF8(base14.Encode(t.Encrypt(helper.StringToBytes(str))))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(es)))
@@ -53,7 +51,7 @@ func init() {
en.OnRegex(`^用(.+)解密\s*([一-踀]+[㴁-㴆]?)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := getea(key)
t := crypto.GetTEA(key)
es, err := base14.UTF82UTF16BE(helper.StringToBytes(str))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(t.Decrypt(base14.Decode(es)))))
@@ -62,15 +60,3 @@ func init() {
}
})
}
func getea(key string) tea.TEA {
kr := []rune(key)
if len(kr) > 4 {
kr = kr[:4]
} else {
for len(kr) < 4 {
kr = append(kr, rune(4-len(kr)))
}
}
return *(*tea.TEA)(*(*unsafe.Pointer)(unsafe.Pointer(&kr)))
}

62
plugin/base64gua/main.go Normal file
View File

@@ -0,0 +1,62 @@
// Package base64gua base64卦 与 tea 加解密
package base64gua
import (
"github.com/FloatTech/floatbox/crypto"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/fumiama/unibase2n"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
)
func init() {
en := control.Register("base64gua", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "base64gua加解密\n" +
"- 六十四卦加密xxx\n- 六十四卦解密xxx\n- 六十四卦用yyy加密xxx\n- 六十四卦用yyy解密xxx",
})
en.OnRegex(`^六十四卦加密\s*(.+)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es := unibase2n.Base64Gua.EncodeString(str)
if es != "" {
ctx.SendChain(message.Text(es))
} else {
ctx.SendChain(message.Text("加密失败!"))
}
})
en.OnRegex(`^六十四卦解密\s*([䷀-䷿]+[☰☱]?)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es := unibase2n.Base64Gua.DecodeString(str)
if es != "" {
ctx.SendChain(message.Text(es))
} else {
ctx.SendChain(message.Text("解密失败!"))
}
})
en.OnRegex(`^六十四卦用(.+)加密\s*(.+)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := crypto.GetTEA(key)
es, err := unibase2n.UTF16BE2UTF8(unibase2n.Base64Gua.Encode(t.Encrypt(helper.StringToBytes(str))))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(es)))
} else {
ctx.SendChain(message.Text("加密失败!"))
}
})
en.OnRegex(`^六十四卦用(.+)解密\s*([䷀-䷿]+[☰☱]?)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := crypto.GetTEA(key)
es, err := unibase2n.UTF82UTF16BE(helper.StringToBytes(str))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(t.Decrypt(unibase2n.Base64Gua.Decode(es)))))
} else {
ctx.SendChain(message.Text("解密失败!"))
}
})
}

View File

@@ -0,0 +1,62 @@
// Package baseamasiro base天城文 与 tea 加解密
package baseamasiro
import (
"github.com/FloatTech/floatbox/crypto"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/fumiama/unibase2n"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
)
func init() {
en := control.Register("baseamasiro", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "base天城文加解密\n" +
"- 天城文加密xxx\n- 天城文解密xxx\n- 天城文用yyy加密xxx\n- 天城文用yyy解密xxx",
})
en.OnRegex(`^天城文加密\s*(.+)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es := unibase2n.BaseDevanagari.EncodeString(str)
if es != "" {
ctx.SendChain(message.Text(es))
} else {
ctx.SendChain(message.Text("加密失败!"))
}
})
en.OnRegex(`^天城文解密\s*([ऀ-ॿ]+[-৫]?)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
str := ctx.State["regex_matched"].([]string)[1]
es := unibase2n.BaseDevanagari.DecodeString(str)
if es != "" {
ctx.SendChain(message.Text(es))
} else {
ctx.SendChain(message.Text("解密失败!"))
}
})
en.OnRegex(`^天城文用(.+)加密\s*(.+)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := crypto.GetTEA(key)
es, err := unibase2n.UTF16BE2UTF8(unibase2n.BaseDevanagari.Encode(t.Encrypt(helper.StringToBytes(str))))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(es)))
} else {
ctx.SendChain(message.Text("加密失败!"))
}
})
en.OnRegex(`^天城文用(.+)解密\s*([ऀ-ॿ]+[-৫]?)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
key, str := ctx.State["regex_matched"].([]string)[1], ctx.State["regex_matched"].([]string)[2]
t := crypto.GetTEA(key)
es, err := unibase2n.UTF82UTF16BE(helper.StringToBytes(str))
if err == nil {
ctx.SendChain(message.Text(helper.BytesToString(t.Decrypt(unibase2n.BaseDevanagari.Decode(es)))))
} else {
ctx.SendChain(message.Text("解密失败!"))
}
})
}

View File

@@ -1,144 +0,0 @@
package bilibili
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"strconv"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/web"
"github.com/tidwall/gjson"
)
var (
errNeedCookie = errors.New("该api需要设置b站cookie请发送命令设置cookie例如\"设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31\"")
)
// searchUser 查找b站用户
func searchUser(keyword string) (r []searchResult, err error) {
client := &http.Client{}
req, err := http.NewRequest("GET", fmt.Sprintf(searchUserURL, keyword), nil)
if err != nil {
return
}
err = reflushBilibiliCookie()
if err != nil {
return
}
req.Header.Add("cookie", cfg.BilibiliCookie)
res, err := client.Do(req)
if err != nil {
return
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
s := fmt.Sprintf("status code: %d", res.StatusCode)
err = errors.New(s)
return
}
var sd searchData
err = json.NewDecoder(res.Body).Decode(&sd)
if err != nil {
return
}
r = sd.Data.Result
return
}
// getVtbDetail 查找vtb信息
func getVtbDetail(uid string) (result vtbDetail, err error) {
data, err := web.GetData(fmt.Sprintf(vtbDetailURL, uid))
if err != nil {
return
}
if err = json.Unmarshal(data, &result); err != nil {
return
}
return
}
// getMemberCard 获取b站个人详情
func getMemberCard(uid interface{}) (result memberCard, err error) {
data, err := web.GetData(fmt.Sprintf(memberCardURL, uid))
if err != nil {
return
}
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("card").Raw), &result)
if err != nil {
return
}
return
}
// getMedalwall 用b站uid获得牌子
func getMedalwall(uid string) (result []medal, err error) {
client := &http.Client{}
req, err := http.NewRequest("GET", fmt.Sprintf(medalwallURL, uid), nil)
if err != nil {
return
}
err = reflushBilibiliCookie()
if err != nil {
return
}
req.Header.Add("cookie", cfg.BilibiliCookie)
res, err := client.Do(req)
if err != nil {
return
}
defer res.Body.Close()
var md medalData
err = json.NewDecoder(res.Body).Decode(&md)
if err != nil {
return
}
if md.Code == -101 {
err = errNeedCookie
return
}
if md.Code != 0 {
err = errors.New(md.Message)
}
result = md.Data.List
return
}
// getArticleInfo 用id查专栏信息
func getArticleInfo(id string) (card Card, err error) {
var data []byte
data, err = web.GetData(fmt.Sprintf(articleInfoURL, id))
if err != nil {
return
}
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("data").Raw), &card)
return
}
// getLiveRoomInfo 用直播间id查直播间信息
func getLiveRoomInfo(roomID string) (card roomCard, err error) {
var data []byte
data, err = web.GetData(fmt.Sprintf(liveRoomInfoURL, roomID))
if err != nil {
return
}
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("data").Raw), &card)
return
}
// getVideoInfo 用av或bv查视频信息
func getVideoInfo(id string) (card Card, err error) {
var data []byte
_, err = strconv.Atoi(id)
if err == nil {
data, err = web.GetData(fmt.Sprintf(videoInfoURL, id, ""))
} else {
data, err = web.GetData(fmt.Sprintf(videoInfoURL, "", id))
}
if err != nil {
return
}
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("data").Raw), &card)
return
}

View File

@@ -17,6 +17,7 @@ import (
"time"
"github.com/Coloured-glaze/gg"
bz "github.com/FloatTech/AnimeAPI/bilibili"
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
@@ -40,8 +41,7 @@ var (
4: "进入直播间",
5: "标题变动",
}
cfgFile = "data/Bilibili/config.json"
cfg config
cfg = bz.NewCookieConfig("data/Bilibili/config.json")
)
// 查成分的
@@ -53,7 +53,7 @@ func init() {
"- >user info [xxx]\n" +
"- 查成分 [xxx]\n" +
"- 查弹幕 [xxx]\n" +
"- 设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31\n" +
"- 设置b站cookie b_ut=7;buvid3=0;i-wanna-go-back=-1;innersign=0;\n" +
"- 更新vup",
PublicDataFolder: "Bilibili",
})
@@ -73,7 +73,7 @@ func init() {
engine.OnRegex(`^>user info\s?(.{1,25})$`, getPara).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
id := ctx.State["uid"].(string)
card, err := getMemberCard(id)
card, err := bz.GetMemberCard(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -92,7 +92,7 @@ func init() {
Handle(func(ctx *zero.Ctx) {
id := ctx.State["uid"].(string)
// 获取详情
fo, err := getVtbDetail(id)
fo, err := bz.GetVtbDetail(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -120,7 +120,7 @@ func init() {
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
return
}
u, err := getMemberCard(id)
u, err := bz.GetMemberCard(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -131,13 +131,13 @@ func init() {
return
}
vupLen := len(vups)
medals, err := getMedalwall(id)
sort.Sort(medalSlice(medals))
medals, err := bz.GetMedalWall(cfg, id)
sort.Sort(bz.MedalSorter(medals))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
}
frontVups := make([]vup, 0)
medalMap := make(map[int64]medal)
medalMap := make(map[int64]bz.Medal)
for _, v := range medals {
up := vup{
Mid: v.Mid,
@@ -173,7 +173,7 @@ func init() {
back = img.Size(back, backX, backY).Im
}
if len(vups) > 50 {
ctx.SendChain(message.Text(u.Name + "关注的up主太多了只展示前50个up"))
ctx.SendChain(message.Text(u.Name + "关注的up主太多了, 只展示前50个up"))
vups = vups[:50]
}
canvas := gg.NewContext(1500, int(500*(1.1+float64(len(vups))/3)))
@@ -275,19 +275,19 @@ func init() {
if pagenum == "" {
pagenum = "0"
}
u, err := getMemberCard(id)
u, err := bz.GetMemberCard(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
var danmaku danmakusuki
var danmaku bz.Danmakusuki
tr := &http.Transport{
DisableKeepAlives: true,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
data, err := web.RequestDataWith(client, fmt.Sprintf(danmakuAPI, id, pagenum), "GET", "", web.RandUA())
data, err := web.RequestDataWith(client, fmt.Sprintf(bz.DanmakuAPI, id, pagenum), "GET", "", web.RandUA())
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -363,7 +363,7 @@ func init() {
canvas.DrawString(u.Mid, 900+n, 122.5)
canvas.DrawString(fmt.Sprintf("粉丝:%d 关注:%d", u.Fans, u.Attention), startWidth, 222.5)
canvas.DrawString(fmt.Sprintf("页码:[%d/%d]", danmaku.Data.PageNum, (danmaku.Data.Total-1)/5), startWidth, 322.5)
canvas.DrawString("网页链接: "+fmt.Sprintf(danmakuURL, u.Mid), startWidth, 422.5)
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++ {
@@ -527,7 +527,7 @@ func init() {
engine.OnRegex(`^设置b站cookie?\s+(.*)$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
cookie := ctx.State["regex_matched"].([]string)[1]
err := setBilibiliCookie(cookie)
err := cfg.Set(cookie)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -571,7 +571,7 @@ func int2rbg(t int64) (int64, int64, int64) {
func getPara(ctx *zero.Ctx) bool {
keyword := ctx.State["regex_matched"].([]string)[1]
if !re.MatchString(keyword) {
searchRes, err := searchUser(keyword)
searchRes, err := bz.SearchUser(cfg, keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
@@ -582,7 +582,7 @@ func getPara(ctx *zero.Ctx) bool {
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
recv, cancel := next.Repeat()
defer cancel()
ctx.SendChain(message.Text("输入为纯数字请选择查询uid还是用户名输入对应序号:\n0. 查询uid\n1. 查询用户名"))
ctx.SendChain(message.Text("输入为纯数字, 请选择查询uid还是用户名, 输入对应序号:\n0. 查询uid\n1. 查询用户名"))
for {
select {
case <-time.After(time.Second * 10):
@@ -604,7 +604,7 @@ func getPara(ctx *zero.Ctx) bool {
ctx.State["uid"] = keyword
return true
} else if num == 1 {
searchRes, err := searchUser(keyword)
searchRes, err := bz.SearchUser(cfg, keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false

View File

@@ -5,6 +5,7 @@ import (
"regexp"
"time"
bz "github.com/FloatTech/AnimeAPI/bilibili"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -34,7 +35,7 @@ func init() {
en.OnRegex(`((b23|acg).tv|bili2233.cn)/[0-9a-zA-Z]+`).SetBlock(true).Limit(limit.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
url := ctx.State["regex_matched"].([]string)[0]
realurl, err := getrealurl("https://" + url)
realurl, err := bz.GetRealUrl("https://" + url)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -65,7 +66,7 @@ func handleVideo(ctx *zero.Ctx) {
if id == "" {
id = ctx.State["regex_matched"].([]string)[2]
}
card, err := getVideoInfo(id)
card, err := bz.GetVideoInfo(id)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -88,7 +89,7 @@ func handleDynamic(ctx *zero.Ctx) {
}
func handleArticle(ctx *zero.Ctx) {
card, err := getArticleInfo(ctx.State["regex_matched"].([]string)[1])
card, err := bz.GetArticleInfo(ctx.State["regex_matched"].([]string)[1])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -97,7 +98,7 @@ func handleArticle(ctx *zero.Ctx) {
}
func handleLive(ctx *zero.Ctx) {
card, err := getLiveRoomInfo(ctx.State["regex_matched"].([]string)[1])
card, err := bz.GetLiveRoomInfo(ctx.State["regex_matched"].([]string)[1])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return

View File

@@ -1,12 +1,9 @@
package bilibili
import (
"encoding/json"
"errors"
"os"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
_ "github.com/fumiama/sqlite3" // use sql
"github.com/jinzhu/gorm"
@@ -92,32 +89,3 @@ func updateVup() error {
}
return nil
}
func setBilibiliCookie(cookie string) (err error) {
cfg = config{
BilibiliCookie: cookie,
}
return saveConfig(cfg)
}
func reflushBilibiliCookie() (err error) {
if file.IsNotExist(cfgFile) {
err = errors.New("未初始化配置")
return
}
reader, err := os.Open(cfgFile)
if err != nil {
return
}
defer reader.Close()
return json.NewDecoder(reader).Decode(&cfg)
}
func saveConfig(cfg config) (err error) {
reader, err := os.Create(cfgFile)
if err != nil {
return err
}
defer reader.Close()
return json.NewEncoder(reader).Encode(&cfg)
}

View File

@@ -13,6 +13,7 @@ import (
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"
@@ -191,7 +192,7 @@ func getName(buid int64) (name string, err error) {
// subscribe 订阅
func subscribe(buid, groupid int64) (err error) {
bpMap := map[string]interface{}{
bpMap := map[string]any{
"bilibili_uid": buid,
"group_id": groupid,
"live_disable": 0,
@@ -202,7 +203,7 @@ func subscribe(buid, groupid int64) (err error) {
// unsubscribe 取消订阅
func unsubscribe(buid, groupid int64) (err error) {
bpMap := map[string]interface{}{
bpMap := map[string]any{
"bilibili_uid": buid,
"group_id": groupid,
"live_disable": 1,
@@ -212,7 +213,7 @@ func unsubscribe(buid, groupid int64) (err error) {
}
func unsubscribeDynamic(buid, groupid int64) (err error) {
bpMap := map[string]interface{}{
bpMap := map[string]any{
"bilibili_uid": buid,
"group_id": groupid,
"dynamic_disable": 1,
@@ -221,7 +222,7 @@ func unsubscribeDynamic(buid, groupid int64) (err error) {
}
func unsubscribeLive(buid, groupid int64) (err error) {
bpMap := map[string]interface{}{
bpMap := map[string]any{
"bilibili_uid": buid,
"group_id": groupid,
"live_disable": 1,
@@ -230,7 +231,7 @@ func unsubscribeLive(buid, groupid int64) (err error) {
}
func getUserDynamicCard(buid int64) (cardList []gjson.Result, err error) {
data, err := web.RequestDataWith(web.NewDefaultClient(), fmt.Sprintf(spaceHistoryURL, buid, 0), "GET", referer, ua)
data, err := web.RequestDataWith(web.NewDefaultClient(), fmt.Sprintf(bz.SpaceHistoryURL, buid, 0), "GET", referer, ua)
if err != nil {
return
}
@@ -239,13 +240,13 @@ func getUserDynamicCard(buid int64) (cardList []gjson.Result, err error) {
}
func getLiveList(uids ...int64) (string, error) {
m := make(map[string]interface{})
m := make(map[string]any)
m["uids"] = uids
b, err := json.Marshal(m)
if err != nil {
return "", err
}
data, err := web.PostData(liveListURL, "application/json", bytes.NewReader(b))
data, err := web.PostData(bz.LiveListURL, "application/json", bytes.NewReader(b))
if err != nil {
return "", err
}
@@ -276,7 +277,12 @@ func sendDynamic(ctx *zero.Ctx) error {
m, ok := control.Lookup(serviceName)
if ok {
groupList := bdb.getAllGroupByBuidAndDynamic(buid)
msg, err := dynamicCard2msg(cardList[i].Raw, 0)
dc, err := bz.LoadDynamicDetail(cardList[i].Raw)
if err != nil {
err = errors.Errorf("动态%v的解析有问题,%v", cardList[i].Get("desc.dynamic_id_str"), err)
return err
}
msg, err := dynamicCard2msg(&dc)
if err != nil {
err = errors.Errorf("动态%v的解析有问题,%v", cardList[i].Get("desc.dynamic_id_str"), err)
return err
@@ -324,7 +330,7 @@ func sendLive(ctx *zero.Ctx) error {
if roomID == 0 {
roomID = value.Get("room_id").Int()
}
lURL := liveURL + strconv.FormatInt(roomID, 10)
lURL := bz.LiveURL + strconv.FormatInt(roomID, 10)
lName := value.Get("uname").String()
lTitle := value.Get("title").String()
lCover := value.Get("cover_from_user").String()

View File

@@ -54,7 +54,7 @@ func initializePush(dbpath string) *bilibilipushdb {
}
// insertOrUpdateLiveAndDynamic 插入或更新数据库
func (bdb *bilibilipushdb) insertOrUpdateLiveAndDynamic(bpMap map[string]interface{}) (err error) {
func (bdb *bilibilipushdb) insertOrUpdateLiveAndDynamic(bpMap map[string]any) (err error) {
db := (*gorm.DB)(bdb)
bp := bilibilipush{}
data, err := json.Marshal(&bpMap)

View File

@@ -2,18 +2,15 @@ package bilibili
import (
"encoding/json"
"errors"
"fmt"
"time"
bz "github.com/FloatTech/AnimeAPI/bilibili"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/web"
"github.com/tidwall/gjson"
"github.com/wdvxdr1123/ZeroBot/message"
)
var (
typeMsg = map[int]string{
msgType = map[int]string{
1: "转发了动态",
2: "有图营业",
4: "无图营业",
@@ -27,66 +24,56 @@ var (
}
)
// dynamicCard2msg cType=0时,处理DynCard字符串,cType=1, 2, 4, 8, 16, 64, 256, 2048, 4200, 4308时,处理Card字符串,cType为card类型
func dynamicCard2msg(str string, cType int) (msg []message.MessageSegment, err error) {
// dynamicCard2msg 处理DynCard
func dynamicCard2msg(dynamicCard *bz.DynamicCard) (msg []message.MessageSegment, err error) {
var (
dynamicCard dynamicCard
card Card
vote Vote
card bz.Card
vote bz.Vote
cType int
)
msg = make([]message.MessageSegment, 0, 16)
// 初始化结构体
switch cType {
case 0:
err = json.Unmarshal(binary.StringToBytes(str), &dynamicCard)
if err != nil {
return
}
err = json.Unmarshal(binary.StringToBytes(dynamicCard.Card), &card)
if err != nil {
return
}
if dynamicCard.Extension.Vote != "" {
err = json.Unmarshal(binary.StringToBytes(dynamicCard.Extension.Vote), &vote)
if err != nil {
return
}
}
cType = dynamicCard.Desc.Type
case 1, 2, 4, 8, 16, 64, 256, 2048, 4200, 4308:
err = json.Unmarshal(binary.StringToBytes(str), &card)
if err != nil {
return
}
default:
err = errors.New("只有0, 1, 2, 4, 8, 16, 64, 256, 2048, 4200, 4308模式")
err = json.Unmarshal(binary.StringToBytes(dynamicCard.Card), &card)
if err != nil {
return
}
if dynamicCard.Extension.Vote != "" {
err = json.Unmarshal(binary.StringToBytes(dynamicCard.Extension.Vote), &vote)
if err != nil {
return
}
}
cType = dynamicCard.Desc.Type
// 生成消息
switch cType {
case 1:
msg = append(msg, message.Text(card.User.Uname, typeMsg[cType], "\n",
msg = append(msg, message.Text(card.User.Uname, msgType[cType], "\n",
card.Item.Content, "\n",
"转发的内容: \n"))
var originMsg []message.MessageSegment
originMsg, err = dynamicCard2msg(card.Origin, card.Item.OrigType)
var co bz.Card
co, err = bz.LoadCardDetail(card.Origin)
if err != nil {
return
}
originMsg, err = card2msg(dynamicCard, &co, card.Item.OrigType)
if err != nil {
return
}
msg = append(msg, originMsg...)
case 2:
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Item.Description))
for i := 0; i < len(card.Item.Pictures); i++ {
msg = append(msg, message.Image(card.Item.Pictures[i].ImgSrc))
}
case 4:
msg = append(msg, message.Text(card.User.Uname, "在", time.Unix(int64(card.Item.Timestamp), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
msg = append(msg, message.Text(card.User.Uname, "在", time.Unix(int64(card.Item.Timestamp), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Item.Content, "\n"))
if dynamicCard.Extension.Vote != "" {
msg = append(msg, message.Text("【投票】", vote.Desc, "\n",
"截止日期: ", time.Unix(int64(vote.Endtime), 0).Format("2006-01-02 15:04:05"), "\n",
"参与人数: ", humanNum(vote.JoinNum), "\n",
"参与人数: ", bz.HumanNum(vote.JoinNum), "\n",
"投票选项( 最多选择", vote.ChoiceCnt, "项 )\n"))
for i := 0; i < len(vote.Options); i++ {
msg = append(msg, message.Text("- ", vote.Options[i].Idx, ". ", vote.Options[i].Desc, "\n"))
@@ -96,18 +83,18 @@ func dynamicCard2msg(str string, cType int) (msg []message.MessageSegment, err e
}
}
case 8:
msg = append(msg, message.Text(card.Owner.Name, "在", time.Unix(int64(card.Pubdate), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
msg = append(msg, message.Text(card.Owner.Name, "在", time.Unix(int64(card.Pubdate), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Title))
msg = append(msg, message.Image(card.Pic))
msg = append(msg, message.Text(card.Desc, "\n",
card.ShareSubtitle, "\n",
"视频链接: ", card.ShortLink, "\n"))
case 16:
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Item.Description))
msg = append(msg, message.Image(card.Item.Cover.Default))
case 64:
msg = append(msg, message.Text(card.Author.(map[string]interface{})["name"], "在", time.Unix(int64(card.PublishTime), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
msg = append(msg, message.Text(card.Author.(map[string]any)["name"], "在", time.Unix(int64(card.PublishTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Title, "\n",
card.Summary))
for i := 0; i < len(card.ImageUrls); i++ {
@@ -117,7 +104,7 @@ func dynamicCard2msg(str string, cType int) (msg []message.MessageSegment, err e
msg = append(msg, message.Text("文章链接: https://www.bilibili.com/read/cv", card.ID, "\n"))
}
case 256:
msg = append(msg, message.Text(card.Upper, "在", time.Unix(int64(card.Ctime), 0).Format("2006-01-02 15:04:05"), typeMsg[cType], "\n",
msg = append(msg, message.Text(card.Upper, "在", time.Unix(int64(card.Ctime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Title))
msg = append(msg, message.Image(card.Cover))
msg = append(msg, message.Text(card.Intro, "\n"))
@@ -126,7 +113,7 @@ func dynamicCard2msg(str string, cType int) (msg []message.MessageSegment, err e
}
case 2048:
msg = append(msg, message.Text(card.User.Uname, typeMsg[cType], "\n",
msg = append(msg, message.Text(card.User.Uname, msgType[cType], "\n",
card.Vest.Content, "\n",
card.Sketch.Title, "\n",
card.Sketch.DescText, "\n"))
@@ -134,7 +121,7 @@ func dynamicCard2msg(str string, cType int) (msg []message.MessageSegment, err e
msg = append(msg, message.Text("分享链接: ", card.Sketch.TargetURL, "\n"))
case 4308:
if dynamicCard.Desc.UserProfile.Info.Uname != "" {
msg = append(msg, message.Text(dynamicCard.Desc.UserProfile.Info.Uname, typeMsg[cType], "\n"))
msg = append(msg, message.Text(dynamicCard.Desc.UserProfile.Info.Uname, msgType[cType], "\n"))
}
msg = append(msg, message.Image(card.LivePlayInfo.Cover))
msg = append(msg, message.Text("\n", card.LivePlayInfo.Title, "\n",
@@ -153,35 +140,141 @@ func dynamicCard2msg(str string, cType int) (msg []message.MessageSegment, err e
msg = append(msg, message.Text("动态id: ", dynamicCard.Desc.DynamicIDStr, "未知动态类型: ", cType, "\n"))
}
if dynamicCard.Desc.DynamicIDStr != "" {
msg = append(msg, message.Text("动态链接: ", tURL, dynamicCard.Desc.DynamicIDStr))
msg = append(msg, message.Text("动态链接: ", bz.TURL, dynamicCard.Desc.DynamicIDStr))
}
return
}
// card2msg cType=1, 2, 4, 8, 16, 64, 256, 2048, 4200, 4308时,处理Card字符串,cType为card类型
func card2msg(dynamicCard *bz.DynamicCard, card *bz.Card, cType int) (msg []message.MessageSegment, err error) {
var (
vote bz.Vote
)
msg = make([]message.MessageSegment, 0, 16)
// 生成消息
switch cType {
case 1:
msg = append(msg, message.Text(card.User.Uname, msgType[cType], "\n",
card.Item.Content, "\n",
"转发的内容: \n"))
var originMsg []message.MessageSegment
var co bz.Card
co, err = bz.LoadCardDetail(card.Origin)
if err != nil {
return
}
originMsg, err = card2msg(dynamicCard, &co, card.Item.OrigType)
if err != nil {
return
}
msg = append(msg, originMsg...)
case 2:
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Item.Description))
for i := 0; i < len(card.Item.Pictures); i++ {
msg = append(msg, message.Image(card.Item.Pictures[i].ImgSrc))
}
case 4:
msg = append(msg, message.Text(card.User.Uname, "在", time.Unix(int64(card.Item.Timestamp), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Item.Content, "\n"))
if dynamicCard.Extension.Vote != "" {
msg = append(msg, message.Text("【投票】", vote.Desc, "\n",
"截止日期: ", time.Unix(int64(vote.Endtime), 0).Format("2006-01-02 15:04:05"), "\n",
"参与人数: ", bz.HumanNum(vote.JoinNum), "\n",
"投票选项( 最多选择", vote.ChoiceCnt, "项 )\n"))
for i := 0; i < len(vote.Options); i++ {
msg = append(msg, message.Text("- ", vote.Options[i].Idx, ". ", vote.Options[i].Desc, "\n"))
if vote.Options[i].ImgURL != "" {
msg = append(msg, message.Image(vote.Options[i].ImgURL))
}
}
}
case 8:
msg = append(msg, message.Text(card.Owner.Name, "在", time.Unix(int64(card.Pubdate), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Title))
msg = append(msg, message.Image(card.Pic))
msg = append(msg, message.Text(card.Desc, "\n",
card.ShareSubtitle, "\n",
"视频链接: ", card.ShortLink, "\n"))
case 16:
msg = append(msg, message.Text(card.User.Name, "在", time.Unix(int64(card.Item.UploadTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Item.Description))
msg = append(msg, message.Image(card.Item.Cover.Default))
case 64:
msg = append(msg, message.Text(card.Author.(map[string]any)["name"], "在", time.Unix(int64(card.PublishTime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Title, "\n",
card.Summary))
for i := 0; i < len(card.ImageUrls); i++ {
msg = append(msg, message.Image(card.ImageUrls[i]))
}
if card.ID != 0 {
msg = append(msg, message.Text("文章链接: https://www.bilibili.com/read/cv", card.ID, "\n"))
}
case 256:
msg = append(msg, message.Text(card.Upper, "在", time.Unix(int64(card.Ctime), 0).Format("2006-01-02 15:04:05"), msgType[cType], "\n",
card.Title))
msg = append(msg, message.Image(card.Cover))
msg = append(msg, message.Text(card.Intro, "\n"))
if card.ID != 0 {
msg = append(msg, message.Text("音频链接: https://www.bilibili.com/audio/au", card.ID, "\n"))
}
case 2048:
msg = append(msg, message.Text(card.User.Uname, msgType[cType], "\n",
card.Vest.Content, "\n",
card.Sketch.Title, "\n",
card.Sketch.DescText, "\n"))
msg = append(msg, message.Image(card.Sketch.CoverURL))
msg = append(msg, message.Text("分享链接: ", card.Sketch.TargetURL, "\n"))
case 4308:
if dynamicCard.Desc.UserProfile.Info.Uname != "" {
msg = append(msg, message.Text(dynamicCard.Desc.UserProfile.Info.Uname, msgType[cType], "\n"))
}
msg = append(msg, message.Image(card.LivePlayInfo.Cover))
msg = append(msg, message.Text("\n", card.LivePlayInfo.Title, "\n",
"房间号: ", card.LivePlayInfo.RoomID, "\n",
"分区: ", card.LivePlayInfo.ParentAreaName))
if card.LivePlayInfo.ParentAreaName != card.LivePlayInfo.AreaName {
msg = append(msg, message.Text("-", card.LivePlayInfo.AreaName))
}
if card.LivePlayInfo.LiveStatus == 0 {
msg = append(msg, message.Text("未开播 \n"))
} else {
msg = append(msg, message.Text("直播中 ", card.LivePlayInfo.WatchedShow, "\n"))
}
msg = append(msg, message.Text("直播链接: ", card.LivePlayInfo.Link))
default:
msg = append(msg, message.Text("动态id: ", dynamicCard.Desc.DynamicIDStr, "未知动态类型: ", cType, "\n"))
}
if dynamicCard.Desc.DynamicIDStr != "" {
msg = append(msg, message.Text("动态链接: ", bz.TURL, dynamicCard.Desc.DynamicIDStr))
}
return
}
// dynamicDetail 用动态id查动态信息
func dynamicDetail(dynamicIDStr string) (msg []message.MessageSegment, err error) {
var data []byte
data, err = web.GetData(fmt.Sprintf(dynamicDetailURL, dynamicIDStr))
dyc, err := bz.GetDynamicDetail(dynamicIDStr)
if err != nil {
return
}
return dynamicCard2msg(gjson.ParseBytes(data).Get("data.card").Raw, 0)
return dynamicCard2msg(&dyc)
}
// articleCard2msg 专栏转消息
func articleCard2msg(card Card, defaultID string) (msg []message.MessageSegment) {
func articleCard2msg(card bz.Card, defaultID string) (msg []message.MessageSegment) {
msg = make([]message.MessageSegment, 0, 16)
for i := 0; i < len(card.OriginImageUrls); i++ {
msg = append(msg, message.Image(card.OriginImageUrls[i]))
}
msg = append(msg, message.Text("\n", card.Title, "\n", "UP主: ", card.AuthorName, "\n",
"阅读: ", humanNum(card.Stats.View), " 评论: ", humanNum(card.Stats.Reply), "\n",
cvURL, defaultID))
"阅读: ", bz.HumanNum(card.Stats.View), " 评论: ", bz.HumanNum(card.Stats.Reply), "\n",
bz.CVURL, defaultID))
return
}
// liveCard2msg 直播卡片转消息
func liveCard2msg(card roomCard) (msg []message.MessageSegment) {
func liveCard2msg(card bz.RoomCard) (msg []message.MessageSegment) {
msg = make([]message.MessageSegment, 0, 16)
msg = append(msg, message.Image(card.RoomInfo.Keyframe))
msg = append(msg, message.Text("\n", card.RoomInfo.Title, "\n",
@@ -197,37 +290,37 @@ func liveCard2msg(card roomCard) (msg []message.MessageSegment) {
if card.RoomInfo.LiveStatus == 0 {
msg = append(msg, message.Text("未开播 \n"))
} else {
msg = append(msg, message.Text("直播中 ", humanNum(card.RoomInfo.Online), "人气\n"))
msg = append(msg, message.Text("直播中 ", bz.HumanNum(card.RoomInfo.Online), "人气\n"))
}
if card.RoomInfo.ShortID != 0 {
msg = append(msg, message.Text("直播间链接: ", lURL, card.RoomInfo.ShortID))
msg = append(msg, message.Text("直播间链接: ", bz.LURL, card.RoomInfo.ShortID))
} else {
msg = append(msg, message.Text("直播间链接: ", lURL, card.RoomInfo.RoomID))
msg = append(msg, message.Text("直播间链接: ", bz.LURL, card.RoomInfo.RoomID))
}
return
}
// videoCard2msg 视频卡片转消息
func videoCard2msg(card Card) (msg []message.MessageSegment, err error) {
var mCard memberCard
func videoCard2msg(card bz.Card) (msg []message.MessageSegment, err error) {
var mCard bz.MemberCard
msg = make([]message.MessageSegment, 0, 16)
mCard, err = getMemberCard(card.Owner.Mid)
mCard, err = bz.GetMemberCard(card.Owner.Mid)
if err != nil {
return
}
msg = append(msg, message.Text("标题: ", card.Title, "\n"))
if card.Rights.IsCooperation == 1 {
for i := 0; i < len(card.Staff); i++ {
msg = append(msg, message.Text(card.Staff[i].Title, ": ", card.Staff[i].Name, " 粉丝: ", humanNum(card.Staff[i].Follower), "\n"))
msg = append(msg, message.Text(card.Staff[i].Title, ": ", card.Staff[i].Name, " 粉丝: ", bz.HumanNum(card.Staff[i].Follower), "\n"))
}
} else {
msg = append(msg, message.Text("UP主: ", card.Owner.Name, " 粉丝: ", humanNum(mCard.Fans), "\n"))
msg = append(msg, message.Text("UP主: ", card.Owner.Name, " 粉丝: ", bz.HumanNum(mCard.Fans), "\n"))
}
msg = append(msg, message.Text("播放: ", humanNum(card.Stat.View), " 弹幕: ", humanNum(card.Stat.Danmaku)))
msg = append(msg, message.Text("播放: ", bz.HumanNum(card.Stat.View), " 弹幕: ", bz.HumanNum(card.Stat.Danmaku)))
msg = append(msg, message.Image(card.Pic))
msg = append(msg, message.Text("\n点赞: ", humanNum(card.Stat.Like), " 投币: ", humanNum(card.Stat.Coin), "\n",
"收藏: ", humanNum(card.Stat.Favorite), " 分享: ", humanNum(card.Stat.Share), "\n",
vURL, card.BvID))
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))
return
}

View File

@@ -2,10 +2,12 @@ package bilibili
import (
"testing"
bz "github.com/FloatTech/AnimeAPI/bilibili"
)
func TestArticleInfo(t *testing.T) {
card, err := getArticleInfo("17279244")
card, err := bz.GetArticleInfo("17279244")
if err != nil {
t.Fatal(err)
}
@@ -43,7 +45,7 @@ func TestDynamicDetail(t *testing.T) {
}
func TestMemberCard(t *testing.T) {
card, err := getMemberCard(2)
card, err := bz.GetMemberCard(2)
if err != nil {
t.Fatal(err)
}
@@ -51,22 +53,22 @@ func TestMemberCard(t *testing.T) {
}
func TestVideoInfo(t *testing.T) {
card, err := getVideoInfo("10007")
card, err := bz.GetVideoInfo("10007")
if err != nil {
t.Fatal(err)
}
t.Log(videoCard2msg(card))
card, err = getVideoInfo("BV1xx411c7mD")
card, err = bz.GetVideoInfo("BV1xx411c7mD")
if err != nil {
t.Fatal(err)
}
t.Log(videoCard2msg(card))
card, err = getVideoInfo("bv1xx411c7mD")
card, err = bz.GetVideoInfo("bv1xx411c7mD")
if err != nil {
t.Fatal(err)
}
t.Log(videoCard2msg(card))
card, err = getVideoInfo("BV1mF411j7iU")
card, err = bz.GetVideoInfo("BV1mF411j7iU")
if err != nil {
t.Fatal(err)
}
@@ -74,7 +76,7 @@ func TestVideoInfo(t *testing.T) {
}
func TestLiveRoomInfo(t *testing.T) {
card, err := getLiveRoomInfo("83171")
card, err := bz.GetLiveRoomInfo("83171")
if err != nil {
t.Fatal(err)
}

View File

@@ -1,331 +0,0 @@
package bilibili
const (
// tURL bilibili动态前缀
tURL = "https://t.bilibili.com/"
// liveURL bilibili直播前缀
liveURL = "https://live.bilibili.com/"
// dynamicDetailURL 当前动态信息,一个card
dynamicDetailURL = "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail?dynamic_id=%v"
// memberCardURL 个人信息
memberCardURL = "https://account.bilibili.com/api/member/getCardByMid?mid=%v"
// articleInfoURL 查看专栏信息
articleInfoURL = "https://api.bilibili.com/x/article/viewinfo?id=%v"
// cvURL b站专栏前缀
cvURL = "https://www.bilibili.com/read/cv"
// liveRoomInfoURL 查看直播间信息
liveRoomInfoURL = "https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=%v"
// lURL b站直播间前缀
lURL = "https://live.bilibili.com/"
// videoInfoURL 查看视频信息
videoInfoURL = "https://api.bilibili.com/x/web-interface/view?aid=%v&bvid=%v"
// vURL 视频网址前缀
vURL = "https://www.bilibili.com/video/"
// searchUserURL 查找b站用户
searchUserURL = "http://api.bilibili.com/x/web-interface/search/type?search_type=bili_user&keyword=%v"
// vtbDetailURL 查找vtb信息
vtbDetailURL = "https://api.vtbs.moe/v1/detail/%v"
// medalwallURL 查找牌子
medalwallURL = "https://api.live.bilibili.com/xlive/web-ucenter/user/MedalWall?target_id=%v"
// spaceHistoryURL 历史动态信息,一共12个card
spaceHistoryURL = "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/space_history?host_uid=%v&offset_dynamic_id=%v&need_top=0"
// liveListURL 获得直播状态
liveListURL = "https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids"
// danmakuAPI 弹幕网获得用户弹幕api
danmakuAPI = "https://danmaku.suki.club/api/search/user/detail?uid=%v&pagenum=%v&pagesize=5"
// danmakuURL 弹幕网链接
danmakuURL = "https://danmaku.suki.club/user/%v"
)
// dynamicCard 总动态结构体,包括desc,card
type dynamicCard struct {
Desc Desc `json:"desc"`
Card string `json:"card"`
Extension struct {
VoteCfg struct {
VoteID int `json:"vote_id"`
Desc string `json:"desc"`
JoinNum int `json:"join_num"`
} `json:"vote_cfg"`
Vote string `json:"vote"`
} `json:"extension"`
}
// Card 卡片结构体
type Card struct {
Item struct {
Content string `json:"content"`
UploadTime int `json:"upload_time"`
Description string `json:"description"`
Pictures []struct {
ImgSrc string `json:"img_src"`
} `json:"pictures"`
Timestamp int `json:"timestamp"`
Cover struct {
Default string `json:"default"`
} `json:"cover"`
OrigType int `json:"orig_type"`
} `json:"item"`
AID interface{} `json:"aid"`
BvID interface{} `json:"bvid"`
Dynamic interface{} `json:"dynamic"`
Pic string `json:"pic"`
Title string `json:"title"`
ID int `json:"id"`
Summary string `json:"summary"`
ImageUrls []string `json:"image_urls"`
OriginImageUrls []string `json:"origin_image_urls"`
Sketch struct {
Title string `json:"title"`
DescText string `json:"desc_text"`
CoverURL string `json:"cover_url"`
TargetURL string `json:"target_url"`
} `json:"sketch"`
Stat struct {
Aid int `json:"aid"`
View int `json:"view"`
Danmaku int `json:"danmaku"`
Reply int `json:"reply"`
Favorite int `json:"favorite"`
Coin int `json:"coin"`
Share int `json:"share"`
Like int `json:"like"`
} `json:"stat"`
Stats struct {
Aid int `json:"aid"`
View int `json:"view"`
Danmaku int `json:"danmaku"`
Reply int `json:"reply"`
Favorite int `json:"favorite"`
Coin int `json:"coin"`
Share int `json:"share"`
Like int `json:"like"`
} `json:"stats"`
Owner struct {
Name string `json:"name"`
Pubdate int `json:"pubdate"`
Mid int `json:"mid"`
} `json:"owner"`
Cover string `json:"cover"`
ShortID interface{} `json:"short_id"`
LivePlayInfo struct {
ParentAreaName string `json:"parent_area_name"`
AreaName string `json:"area_name"`
Cover string `json:"cover"`
Link string `json:"link"`
Online int `json:"online"`
RoomID int `json:"room_id"`
LiveStatus int `json:"live_status"`
WatchedShow string `json:"watched_show"`
Title string `json:"title"`
} `json:"live_play_info"`
Intro string `json:"intro"`
Schema string `json:"schema"`
Author interface{} `json:"author"`
AuthorName string `json:"author_name"`
PlayCnt int `json:"play_cnt"`
ReplyCnt int `json:"reply_cnt"`
TypeInfo string `json:"type_info"`
User struct {
Name string `json:"name"`
Uname string `json:"uname"`
} `json:"user"`
Desc string `json:"desc"`
ShareSubtitle string `json:"share_subtitle"`
ShortLink string `json:"short_link"`
PublishTime int `json:"publish_time"`
BannerURL string `json:"banner_url"`
Ctime int `json:"ctime"`
Vest struct {
Content string `json:"content"`
} `json:"vest"`
Upper string `json:"upper"`
Origin string `json:"origin"`
Pubdate int `json:"pubdate"`
Rights struct {
IsCooperation int `json:"is_cooperation"`
} `json:"rights"`
Staff []struct {
Title string `json:"title"`
Name string `json:"name"`
Follower int `json:"follower"`
} `json:"staff"`
}
// Desc 描述结构体
type Desc struct {
Type int `json:"type"`
DynamicIDStr string `json:"dynamic_id_str"`
OrigType int `json:"orig_type"`
Timestamp int `json:"timestamp"`
Origin struct {
DynamicIDStr string `json:"dynamic_id_str"`
} `json:"origin"`
UserProfile struct {
Info struct {
Uname string `json:"uname"`
} `json:"info"`
} `json:"user_profile"`
}
// Vote 投票结构体
type Vote struct {
ChoiceCnt int `json:"choice_cnt"`
Desc string `json:"desc"`
Endtime int `json:"endtime"`
JoinNum int `json:"join_num"`
Options []struct {
Idx int `json:"idx"`
Desc string `json:"desc"`
ImgURL string `json:"img_url"`
} `json:"options"`
}
// memberCard 个人信息卡片
type memberCard struct {
Mid string `json:"mid"`
Name string `json:"name"`
Sex string `json:"sex"`
Face string `json:"face"`
Coins float64 `json:"coins"`
Regtime int64 `json:"regtime"`
Birthday string `json:"birthday"`
Sign string `json:"sign"`
Attentions []int64 `json:"attentions"`
Fans int `json:"fans"`
Friend int `json:"friend"`
Attention int `json:"attention"`
LevelInfo struct {
CurrentLevel int `json:"current_level"`
} `json:"level_info"`
}
// roomCard 直播间卡片
type roomCard struct {
RoomInfo struct {
RoomID int `json:"room_id"`
ShortID int `json:"short_id"`
Title string `json:"title"`
LiveStatus int `json:"live_status"`
AreaName string `json:"area_name"`
ParentAreaName string `json:"parent_area_name"`
Keyframe string `json:"keyframe"`
Online int `json:"online"`
} `json:"room_info"`
AnchorInfo struct {
BaseInfo struct {
Uname string `json:"uname"`
} `json:"base_info"`
} `json:"anchor_info"`
}
// searchData 查找b站用户总结构体
type searchData struct {
Data struct {
NumResults int `json:"numResults"`
Result []searchResult `json:"result"`
} `json:"data"`
}
// searchResult 查找b站用户结果
type searchResult struct {
Mid int64 `json:"mid"`
Uname string `json:"uname"`
Gender int64 `json:"gender"`
Usign string `json:"usign"`
Level int64 `json:"level"`
}
// medalData 牌子接口返回结构体
type medalData struct {
Code int `json:"code"`
Message string `json:"message"`
Data struct {
List []medal `json:"list"`
} `json:"data"`
}
// medalInfo b站牌子信息
type medalInfo struct {
Mid int64 `json:"target_id"`
MedalName string `json:"medal_name"`
Level int64 `json:"level"`
MedalColorStart int64 `json:"medal_color_start"`
MedalColorEnd int64 `json:"medal_color_end"`
MedalColorBorder int64 `json:"medal_color_border"`
}
type medal struct {
Uname string `json:"target_name"`
medalInfo `json:"medal_info"`
}
type medalSlice []medal
func (m medalSlice) Len() int {
return len(m)
}
func (m medalSlice) Swap(i, j int) {
m[i], m[j] = m[j], m[i]
}
func (m medalSlice) Less(i, j int) bool {
return m[i].Level > m[j].Level
}
// vtb信息
type vtbDetail struct {
Mid int `json:"mid"`
Uname string `json:"uname"`
Video int `json:"video"`
Roomid int `json:"roomid"`
Rise int `json:"rise"`
Follower int `json:"follower"`
GuardNum int `json:"guardNum"`
AreaRank int `json:"areaRank"`
}
// danmakusuki 弹幕网结构体
type danmakusuki struct {
Code int64 `json:"code"`
Message string `json:"message"`
Data struct {
Data []struct {
Channel struct {
Name string `json:"name"`
IsLiving bool `json:"isLiving"`
UID int64 `json:"uId"`
RoomID int64 `json:"roomId"`
FaceURL string `json:"faceUrl"`
LiveCount int64 `json:"liveCount"`
} `json:"channel"`
Live struct {
LiveID string `json:"liveId"`
Title string `json:"title"`
IsFinish bool `json:"isFinish"`
CoverURL string `json:"coverUrl"`
StartDate int64 `json:"startDate"`
StopDate int64 `json:"stopDate"`
DanmakusCount int64 `json:"danmakusCount"`
TotalIncome float64 `json:"totalIncome"`
WatchCount int64 `json:"watchCount"`
} `json:"live"`
Danmakus []struct {
Name string `json:"name"`
Type int64 `json:"type"`
UID int64 `json:"uId"`
SendDate int64 `json:"sendDate"`
Price float64 `json:"price"`
Message string `json:"message"`
} `json:"danmakus"`
} `json:"data"`
Total int64 `json:"total"`
PageNum int64 `json:"pageNum"`
PageSize int64 `json:"pageSize"`
HasMore bool `json:"hasMore"`
} `json:"data"`
}
// 配置结构体
type config struct {
BilibiliCookie string `json:"bilibili_cookie"`
}

View File

@@ -1,25 +0,0 @@
package bilibili
import (
"net/http"
"strconv"
)
// humanNum 格式化人数
func humanNum(res int) string {
if res/10000 != 0 {
return strconv.FormatFloat(float64(res)/10000, 'f', 2, 64) + "万"
}
return strconv.Itoa(res)
}
// getrealurl 获取跳转后的链接
func getrealurl(url string) (realurl string, err error) {
data, err := http.Head(url)
if err != nil {
return
}
_ = data.Body.Close()
realurl = data.Request.URL.String()
return
}

View File

@@ -3,6 +3,7 @@ package breakrepeat
import (
"math/rand"
"strconv"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
@@ -10,53 +11,39 @@ import (
zero "github.com/wdvxdr1123/ZeroBot"
)
const (
maxLimit = 3
)
const throttle = 3 // 不可超过 9
type result struct {
Limit int64
RawMsg string
}
var (
sm syncx.Map[int64, *result]
)
var sm syncx.Map[int64, string]
func init() {
engine := control.Register("breakrepeat", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "打断复读,打断3次以上复读\n",
Help: "打断复读\n- 打断" + strconv.Itoa(throttle) + "次以上复读\n",
})
engine.On(`message/group`, zero.OnlyGroup).SetBlock(false).
engine.On("message/group", zero.OnlyGroup, func(ctx *zero.Ctx) bool {
return !zero.HasPicture(ctx)
}).SetBlock(false).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
raw := ctx.Event.RawMessage
if r, ok := sm.Load(gid); !ok || r.RawMsg != raw {
sm.Store(gid, &result{
Limit: 0,
RawMsg: raw,
})
r, ok := sm.Load(gid)
if !ok || len(r) <= 3 || r[3:] != raw {
sm.Store(gid, "0: "+raw)
return
}
if r, ok := sm.Load(gid); ok {
sm.Store(gid, &result{
Limit: r.Limit + 1,
RawMsg: raw,
})
c := int(r[0] - '0')
if c < throttle {
sm.Store(gid, strconv.Itoa(c+1)+": "+raw)
return
}
if res, ok := sm.Load(gid); ok && res.Limit >= maxLimit {
r := []rune(res.RawMsg)
if len(r) > 2 {
rand.Shuffle(len(r), func(i, j int) {
r[i], r[j] = r[j], r[i]
})
ctx.Send(string(r))
}
sm.Store(gid, &result{
Limit: 0,
RawMsg: res.RawMsg,
sm.Delete(gid)
if len(r) > 5 {
ru := []rune(r[3:])
rand.Shuffle(len(ru), func(i, j int) {
ru[i], ru[j] = ru[j], ru[i]
})
r = string(ru)
}
ctx.Send(r)
})
}

View File

@@ -1,111 +0,0 @@
// Package charreverser 英文字符反转
package charreverser
import (
"regexp"
"strings"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const commandRegex = `[A-z]{1}([A-z]|\s)+[A-z]{1}` // 命令正则表达式
var (
charMap = map[rune]rune{
'a': 'ɐ',
'b': 'q',
'c': 'ɔ',
'd': 'p',
'e': 'ǝ',
'f': 'ɟ',
'g': 'ƃ',
'h': 'ɥ',
'i': 'ᴉ',
'j': 'ɾ',
'k': 'ʞ',
'l': 'l',
'm': 'ɯ',
'n': 'u',
'o': 'o',
'p': 'd',
'q': 'b',
'r': 'ɹ',
's': 's',
't': 'ʇ',
'u': 'n',
'v': 'ʌ',
'w': 'ʍ',
'x': 'x',
'y': 'ʎ',
'z': 'z',
'A': '∀',
'B': 'ᗺ',
'C': 'Ɔ',
'D': 'ᗡ',
'E': 'Ǝ',
'F': 'Ⅎ',
'G': '⅁',
'H': 'H',
'I': 'I',
'J': 'ſ',
'K': 'ʞ',
'L': '˥',
'M': 'W',
'N': 'N',
'O': 'O',
'P': 'Ԁ',
'Q': 'Ò',
'R': 'ᴚ',
'S': 'S',
'T': '⏊',
'U': '∩',
'V': 'Λ',
'W': 'M',
'X': 'X',
'Y': '⅄',
'Z': 'Z',
}
compiledRegex = regexp.MustCompile(commandRegex)
)
func init() {
// 初始化engine
engine := control.Register(
"charreverser",
&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "字符翻转\n -翻转 <英文字符串>",
},
)
// 处理字符翻转指令
engine.OnRegex(`翻转( )+[A-z]{1}([A-z]|\s)+[A-z]{1}`).SetBlock(true).Handle(
func(ctx *zero.Ctx) {
// 获取需要翻转的字符串
results := compiledRegex.FindAllString(ctx.MessageString(), -1)
str := results[0]
// 将字符顺序翻转
var tempBuilder strings.Builder
for i := len(str) - 1; i >= 0; i-- {
tempBuilder.WriteByte(str[i])
}
// 翻转字符字形
var reversedStrBuilder strings.Builder
for _, char := range tempBuilder.String() {
if char != ' ' {
reversedStrBuilder.WriteRune(charMap[char])
} else {
reversedStrBuilder.WriteRune(' ')
}
}
// 发送翻转后的字符串
ctx.SendChain(message.Text(reversedStrBuilder.String()))
},
)
}

32
plugin/chrev/init.go Normal file
View File

@@ -0,0 +1,32 @@
// Package chrev 英文字符反转
package chrev
import (
"strings"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() {
// 初始化engine
engine := control.Register("chrev", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "字符翻转\n- 翻转 I love you",
})
// 处理字符翻转指令
engine.OnRegex(`^翻转\s*([A-Za-z\s]*)$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 获取需要翻转的字符串
str := ctx.State["regex_matched"].([]string)[1]
// 将字符顺序翻转
tmp := strings.Builder{}
for i := len(str) - 1; i >= 0; i-- {
tmp.WriteRune(charMap[str[i]])
}
// 发送翻转后的字符串
ctx.SendChain(message.Text(tmp.String()))
})
}

59
plugin/chrev/map.go Normal file
View File

@@ -0,0 +1,59 @@
package chrev
var charMap [256]rune
func init() {
charMap[' '] = ' '
charMap['a'] = 'ɐ'
charMap['b'] = 'q'
charMap['c'] = 'ɔ'
charMap['d'] = 'p'
charMap['e'] = 'ǝ'
charMap['f'] = 'ɟ'
charMap['g'] = 'ƃ'
charMap['h'] = 'ɥ'
charMap['i'] = 'ᴉ'
charMap['j'] = 'ɾ'
charMap['k'] = 'ʞ'
charMap['l'] = 'l'
charMap['m'] = 'ɯ'
charMap['n'] = 'u'
charMap['o'] = 'o'
charMap['p'] = 'd'
charMap['q'] = 'b'
charMap['r'] = 'ɹ'
charMap['s'] = 's'
charMap['t'] = 'ʇ'
charMap['u'] = 'n'
charMap['v'] = 'ʌ'
charMap['w'] = 'ʍ'
charMap['x'] = 'x'
charMap['y'] = 'ʎ'
charMap['z'] = 'z'
charMap['A'] = '∀'
charMap['B'] = 'ᗺ'
charMap['C'] = 'Ɔ'
charMap['D'] = 'ᗡ'
charMap['E'] = 'Ǝ'
charMap['F'] = 'Ⅎ'
charMap['G'] = '⅁'
charMap['H'] = 'H'
charMap['I'] = 'I'
charMap['J'] = 'ſ'
charMap['K'] = 'ʞ'
charMap['L'] = '˥'
charMap['M'] = 'W'
charMap['N'] = 'N'
charMap['O'] = 'O'
charMap['P'] = 'Ԁ'
charMap['Q'] = 'Ò'
charMap['R'] = 'ᴚ'
charMap['S'] = 'S'
charMap['T'] = '⏊'
charMap['U'] = '∩'
charMap['V'] = 'Λ'
charMap['W'] = 'M'
charMap['X'] = 'X'
charMap['Y'] = '⅄'
charMap['Z'] = 'Z'
}

View File

@@ -26,7 +26,7 @@ func init() {
control.Register("coser", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "三次元小姐姐\n- coser",
}).ApplySingle(ctxext.DefaultSingle).OnFullMatch("coser", zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByGroup).
}).ApplySingle(ctxext.DefaultSingle).OnFullMatch("coser").SetBlock(true).Limit(ctxext.LimitByGroup).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女祈祷中......"))
data, err := web.RequestDataWith(web.NewDefaultClient(), coserURL, "GET", "", ua)
@@ -46,10 +46,7 @@ func init() {
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Image(value.String())))
return true
})
if id := ctx.SendGroupForwardMessage(
ctx.Event.GroupID,
m).Get("message_id").Int(); id == 0 {
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
})

View File

@@ -4,12 +4,13 @@ package deepdanbooru
import (
"crypto/md5"
"encoding/hex"
"strings"
"github.com/FloatTech/AnimeAPI/danbooru"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
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"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
@@ -30,7 +31,7 @@ func init() { // 插件主体
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女祈祷中..."))
for _, url := range ctx.State["image_url"].([]string) {
t, err := danbooru.TagURL("", url)
t, st, err := tagurl("", url)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -40,7 +41,11 @@ func init() { // 插件主体
if file.IsNotExist(f) {
_ = writer.SavePNG2Path(f, t)
}
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + f))
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image("file:///"+file.BOTPATH+"/"+f))}
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text("tags: ", strings.Join(st.tseq, ","))))
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
}
})
}

118
plugin/danbooru/tag.go Normal file
View File

@@ -0,0 +1,118 @@
package deepdanbooru
import (
"bytes"
"encoding/json"
"fmt"
"image"
"net/url"
"sort"
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
imgutils "github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/text" // jpg png gif
_ "golang.org/x/image/webp" // webp
)
const api = "https://nsfwtag.azurewebsites.net/api/tag?limit=0.5&url="
type sorttags struct {
tags map[string]float64
tseq []string
}
func newsorttags(tags map[string]float64) (s *sorttags) {
t := make([]string, 0, len(tags))
for k := range tags {
t = append(t, k)
}
return &sorttags{tags: tags, tseq: t}
}
func (s *sorttags) Len() int {
return len(s.tags)
}
func (s *sorttags) Less(i, j int) bool {
v1 := s.tseq[i]
v2 := s.tseq[j]
return s.tags[v1] >= s.tags[v2]
}
// Swap swaps the elements with indexes i and j.
func (s *sorttags) Swap(i, j int) {
s.tseq[j], s.tseq[i] = s.tseq[i], s.tseq[j]
}
func tagurl(name, u string) (im image.Image, st *sorttags, err error) {
ch := make(chan []byte, 1)
go func() {
var data []byte
data, err = web.GetData(u)
ch <- data
}()
data, err := web.GetData(api + url.QueryEscape(u))
if err != nil {
return
}
tags := make(map[string]float64)
err = json.Unmarshal(data, &tags)
if err != nil {
return
}
longestlen := 0
for k := range tags {
if len(k) > longestlen {
longestlen = len(k)
}
}
longestlen++
st = newsorttags(tags)
sort.Sort(st)
_, err = file.GetLazyData(text.BoldFontFile, true)
if err != nil {
return
}
_, err = file.GetLazyData(text.ConsolasFontFile, true)
if err != nil {
return
}
data = <-ch
if err != nil {
return
}
img, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return
}
img = imgutils.Limit(img, 1280, 720)
canvas := gg.NewContext(img.Bounds().Size().X, img.Bounds().Size().Y+int(float64(img.Bounds().Size().X)*0.2)+len(tags)*img.Bounds().Size().X/25)
canvas.SetRGB(1, 1, 1)
canvas.Clear()
canvas.DrawImage(img, 0, 0)
if err = canvas.LoadFontFace(text.BoldFontFile, float64(img.Bounds().Size().X)*0.1); err != nil {
return
}
canvas.SetRGB(0, 0, 0)
canvas.DrawString(name, float64(img.Bounds().Size().X)*0.02, float64(img.Bounds().Size().Y)+float64(img.Bounds().Size().X)*0.1)
i := float64(img.Bounds().Size().Y) + float64(img.Bounds().Size().X)*0.2
if err = canvas.LoadFontFace(text.ConsolasFontFile, float64(img.Bounds().Size().X)*0.04); err != nil {
return
}
rate := float64(img.Bounds().Size().X) * 0.04
for _, k := range st.tseq {
canvas.DrawString(fmt.Sprintf("* %-*s -%.3f-", longestlen, k, tags[k]), float64(img.Bounds().Size().X)*0.04, i)
i += rate
}
im = canvas.Image()
return
}

View File

@@ -35,8 +35,8 @@ type epidemic struct {
type area struct {
Name string `json:"name"`
Today struct {
Confirm int `json:"confirm"`
Wzzadd interface{} `json:"wzz_add"`
Confirm int `json:"confirm"`
Wzzadd any `json:"wzz_add"`
} `json:"today"`
Total struct {
NowConfirm int `json:"nowConfirm"`

View File

@@ -6,6 +6,7 @@ import (
"sync"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/zbputils/img"
"github.com/sirupsen/logrus"
)
@@ -18,10 +19,22 @@ type context struct {
func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
defer wg.Done()
target := datapath + `materials/` + name
var err error
if file.IsNotExist(target) {
err = file.DownloadTo(`https://gitcode.net/m0_60838134/imagematerials/-/raw/main/`+name, target, true)
data, err := web.RequestDataWith(web.NewTLS12Client(), `https://gitcode.net/m0_60838134/imagematerials/-/raw/main/`+name, "GET", "gitcode.net", web.RandUA())
if err != nil {
_ = os.Remove(target)
exit(err)
return
}
f, err := os.Create(target)
if err != nil {
exit(err)
return
}
_, err = f.Write(data)
_ = f.Close()
if err != nil {
_ = os.Remove(target)
exit(err)
return
}
@@ -35,8 +48,19 @@ func dlchan(name string, s *string, wg *sync.WaitGroup, exit func(error)) {
func dlblock(name string) (string, error) {
target := datapath + `materials/` + name
if file.IsNotExist(target) {
err := file.DownloadTo(`https://gitcode.net/m0_60838134/imagematerials/-/raw/main/`+name, target, true)
data, err := web.RequestDataWith(web.NewTLS12Client(), `https://gitcode.net/m0_60838134/imagematerials/-/raw/main/`+name, "GET", "gitcode.net", web.RandUA())
if err != nil {
_ = os.Remove(target)
return "", err
}
f, err := os.Create(target)
if err != nil {
return "", err
}
_, err = f.Write(data)
_ = f.Close()
if err != nil {
_ = os.Remove(target)
return "", err
}
logrus.Debugln("[gif] dl", name, "to", target, "succeeded")

File diff suppressed because it is too large Load Diff

View File

@@ -1,406 +1,43 @@
package guessmusic
type listRaw struct {
Name string `json:"name"`
ID int64 `json:"id"`
}
// config内容
type config struct {
MusicPath string `json:"musicPath"`
Local bool `json:"local"`
API bool `json:"api"`
Cookie string `json:"cookie"`
Playlist []listRaw `json:"playlist"`
MusicPath string `json:"musicPath"`
Local bool `json:"local"`
API bool `json:"api"`
Cookie string `json:"cookie"`
Playlist []listRaw `json:"playlist"`
Defaultlist []dlist `json:"defaultlist"`
}
type keyInfo struct {
Data struct {
Code int `json:"code"`
Unikey string `json:"unikey"`
} `json:"data"`
Code int `json:"code"`
}
type cookyInfo struct {
Code int `json:"code"`
Message string `json:"message"`
Cookie string `json:"cookie"`
}
type qrInfo struct {
Code int `json:"code"`
Data struct {
Qrurl string `json:"qrurl"`
Qrimg string `json:"qrimg"`
} `json:"data"`
}
type topList struct {
Code int `json:"code"`
RelatedVideos interface{} `json:"relatedVideos"`
Playlist struct {
ID int64 `json:"id"`
Name string `json:"name"`
CoverImgID int64 `json:"coverImgId"`
CoverImgURL string `json:"coverImgUrl"`
CoverImgIDStr string `json:"coverImgId_str"`
AdType int `json:"adType"`
UserID int `json:"userId"`
CreateTime int64 `json:"createTime"`
Status int `json:"status"`
OpRecommend bool `json:"opRecommend"`
HighQuality bool `json:"highQuality"`
NewImported bool `json:"newImported"`
UpdateTime int64 `json:"updateTime"`
TrackCount int `json:"trackCount"`
SpecialType int `json:"specialType"`
Privacy int `json:"privacy"`
TrackUpdateTime int64 `json:"trackUpdateTime"`
CommentThreadID string `json:"commentThreadId"`
PlayCount int `json:"playCount"`
TrackNumberUpdateTime int64 `json:"trackNumberUpdateTime"`
SubscribedCount int `json:"subscribedCount"`
CloudTrackCount int `json:"cloudTrackCount"`
Ordered bool `json:"ordered"`
Description string `json:"description"`
Tags []string `json:"tags"`
UpdateFrequency interface{} `json:"updateFrequency"`
BackgroundCoverID int `json:"backgroundCoverId"`
BackgroundCoverURL interface{} `json:"backgroundCoverUrl"`
TitleImage int `json:"titleImage"`
TitleImageURL interface{} `json:"titleImageUrl"`
EnglishTitle interface{} `json:"englishTitle"`
OfficialPlaylistType interface{} `json:"officialPlaylistType"`
Subscribers []struct {
DefaultAvatar bool `json:"defaultAvatar"`
Province int `json:"province"`
AuthStatus int `json:"authStatus"`
Followed bool `json:"followed"`
AvatarURL string `json:"avatarUrl"`
AccountStatus int `json:"accountStatus"`
Gender int `json:"gender"`
City int `json:"city"`
Birthday int `json:"birthday"`
UserID int `json:"userId"`
UserType int `json:"userType"`
Nickname string `json:"nickname"`
Signature string `json:"signature"`
Description string `json:"description"`
DetailDescription string `json:"detailDescription"`
AvatarImgID int64 `json:"avatarImgId"`
BackgroundImgID int64 `json:"backgroundImgId"`
BackgroundURL string `json:"backgroundUrl"`
Authority int `json:"authority"`
Mutual bool `json:"mutual"`
ExpertTags interface{} `json:"expertTags"`
Experts interface{} `json:"experts"`
DjStatus int `json:"djStatus"`
VipType int `json:"vipType"`
RemarkName interface{} `json:"remarkName"`
AuthenticationTypes int `json:"authenticationTypes"`
AvatarDetail interface{} `json:"avatarDetail"`
Anchor bool `json:"anchor"`
BackgroundImgIDStr string `json:"backgroundImgIdStr"`
AvatarImgIDStr string `json:"avatarImgIdStr"`
AvatarImgIDString string `json:"AvatarImgIDString"`
} `json:"subscribers"`
Subscribed interface{} `json:"subscribed"`
Creator struct {
DefaultAvatar bool `json:"defaultAvatar"`
Province int `json:"province"`
AuthStatus int `json:"authStatus"`
Followed bool `json:"followed"`
AvatarURL string `json:"avatarUrl"`
AccountStatus int `json:"accountStatus"`
Gender int `json:"gender"`
City int `json:"city"`
Birthday int `json:"birthday"`
UserID int `json:"userId"`
UserType int `json:"userType"`
Nickname string `json:"nickname"`
Signature string `json:"signature"`
Description string `json:"description"`
DetailDescription string `json:"detailDescription"`
AvatarImgID int64 `json:"avatarImgId"`
BackgroundImgID int64 `json:"backgroundImgId"`
BackgroundURL string `json:"backgroundUrl"`
Authority int `json:"authority"`
Mutual bool `json:"mutual"`
ExpertTags interface{} `json:"expertTags"`
Experts interface{} `json:"experts"`
DjStatus int `json:"djStatus"`
VipType int `json:"vipType"`
RemarkName interface{} `json:"remarkName"`
AuthenticationTypes int `json:"authenticationTypes"`
AvatarDetail struct {
UserType int `json:"userType"`
IdentityLevel int `json:"identityLevel"`
IdentityIconURL string `json:"identityIconUrl"`
} `json:"avatarDetail"`
Anchor bool `json:"anchor"`
BackgroundImgIDStr string `json:"backgroundImgIdStr"`
AvatarImgIDStr string `json:"avatarImgIdStr"`
AvatarImgIDString string `json:"AvatarImgIDString"`
} `json:"creator"`
Tracks []struct {
Name string `json:"name"`
ID int `json:"id"`
Pst int `json:"pst"`
T int `json:"t"`
Ar []struct {
ID int `json:"id"`
Name string `json:"name"`
Tns []interface{} `json:"tns"`
Alias []interface{} `json:"alias"`
} `json:"ar"`
Alia []string `json:"alia"`
Pop int `json:"pop"`
St int `json:"st"`
Rt string `json:"rt"`
Fee int `json:"fee"`
V int `json:"v"`
Crbt interface{} `json:"crbt"`
Cf string `json:"cf"`
Al struct {
ID int `json:"id"`
Name string `json:"name"`
PicURL string `json:"picUrl"`
Tns []interface{} `json:"tns"`
PicStr string `json:"pic_str"`
Pic int64 `json:"pic"`
} `json:"al"`
Dt int `json:"dt"`
H struct {
Br int `json:"br"`
Fid int `json:"fid"`
Size int `json:"size"`
Vd float64 `json:"vd"`
Sr int `json:"sr"`
} `json:"h"`
M struct {
Br int `json:"br"`
Fid int `json:"fid"`
Size int `json:"size"`
Vd float64 `json:"vd"`
Sr int `json:"sr"`
} `json:"m"`
L struct {
Br int `json:"br"`
Fid int `json:"fid"`
Size int `json:"size"`
Vd float64 `json:"vd"`
Sr int `json:"sr"`
} `json:"l"`
Sq interface{} `json:"sq"`
Hr interface{} `json:"hr"`
A interface{} `json:"a"`
Cd string `json:"cd"`
No int `json:"no"`
RtURL interface{} `json:"rtUrl"`
Ftype int `json:"ftype"`
RtUrls []interface{} `json:"rtUrls"`
DjID int `json:"djId"`
Copyright int `json:"copyright"`
SID int `json:"s_id"`
Mark int `json:"mark"`
OriginCoverType int `json:"originCoverType"`
OriginSongSimpleData interface{} `json:"originSongSimpleData"`
TagPicList interface{} `json:"tagPicList"`
ResourceState bool `json:"resourceState"`
Version int `json:"version"`
SongJumpInfo interface{} `json:"songJumpInfo"`
EntertainmentTags interface{} `json:"entertainmentTags"`
Single int `json:"single"`
NoCopyrightRcmd interface{} `json:"noCopyrightRcmd"`
Alg interface{} `json:"alg"`
Rtype int `json:"rtype"`
Rurl interface{} `json:"rurl"`
Mst int `json:"mst"`
Cp int `json:"cp"`
Mv int `json:"mv"`
PublishTime int64 `json:"publishTime"`
Tns []string `json:"tns,omitempty"`
} `json:"tracks"`
VideoIds interface{} `json:"videoIds"`
Videos interface{} `json:"videos"`
TrackIds []struct {
ID int `json:"id"`
V int `json:"v"`
T int `json:"t"`
At int64 `json:"at"`
Alg interface{} `json:"alg"`
UID int `json:"uid"`
RcmdReason string `json:"rcmdReason"`
Sc interface{} `json:"sc"`
Lr int `json:"lr,omitempty"`
} `json:"trackIds"`
ShareCount int `json:"shareCount"`
CommentCount int `json:"commentCount"`
RemixVideo interface{} `json:"remixVideo"`
SharedUsers interface{} `json:"sharedUsers"`
HistorySharedUsers interface{} `json:"historySharedUsers"`
GradeStatus string `json:"gradeStatus"`
Score interface{} `json:"score"`
AlgTags interface{} `json:"algTags"`
} `json:"playlist"`
Urls interface{} `json:"urls"`
Privileges []struct {
ID int `json:"id"`
Fee int `json:"fee"`
Payed int `json:"payed"`
RealPayed int `json:"realPayed"`
St int `json:"st"`
Pl int `json:"pl"`
Dl int `json:"dl"`
Sp int `json:"sp"`
Cp int `json:"cp"`
Subp int `json:"subp"`
Cs bool `json:"cs"`
Maxbr int `json:"maxbr"`
Fl int `json:"fl"`
Pc interface{} `json:"pc"`
Toast bool `json:"toast"`
Flag int `json:"flag"`
PaidBigBang bool `json:"paidBigBang"`
PreSell bool `json:"preSell"`
PlayMaxbr int `json:"playMaxbr"`
DownloadMaxbr int `json:"downloadMaxbr"`
MaxBrLevel string `json:"maxBrLevel"`
PlayMaxBrLevel string `json:"playMaxBrLevel"`
DownloadMaxBrLevel string `json:"downloadMaxBrLevel"`
PlLevel string `json:"plLevel"`
DlLevel string `json:"dlLevel"`
FlLevel string `json:"flLevel"`
Rscl int `json:"rscl"`
FreeTrialPrivilege struct {
ResConsumable bool `json:"resConsumable"`
UserConsumable bool `json:"userConsumable"`
ListenType interface{} `json:"listenType"`
} `json:"freeTrialPrivilege"`
ChargeInfoList []struct {
Rate int `json:"rate"`
ChargeURL interface{} `json:"chargeUrl"`
ChargeMessage interface{} `json:"chargeMessage"`
ChargeType int `json:"chargeType"`
} `json:"chargeInfoList"`
} `json:"privileges"`
SharedPrivilege interface{} `json:"sharedPrivilege"`
ResEntrance interface{} `json:"resEntrance"`
// 记录歌单绑定的网易云歌单ID
type listRaw struct {
Name string `json:"name"` // 歌单名称
ID int64 `json:"id"` // 歌单绑定的网易云ID
}
type topMusicInfo struct {
Songs []struct {
Name string `json:"name"`
ID int `json:"id"`
Pst int `json:"pst"`
T int `json:"t"`
Ar []struct {
ID int `json:"id"`
Name string `json:"name"`
Tns []interface{} `json:"tns"`
Alias []interface{} `json:"alias"`
} `json:"ar"`
Alia []string `json:"alia"`
Pop int `json:"pop"`
St int `json:"st"`
Rt string `json:"rt"`
Fee int `json:"fee"`
V int `json:"v"`
Crbt interface{} `json:"crbt"`
Cf string `json:"cf"`
Al struct {
ID int `json:"id"`
Name string `json:"name"`
PicURL string `json:"picUrl"`
Tns []interface{} `json:"tns"`
PicStr string `json:"pic_str"`
Pic int64 `json:"pic"`
} `json:"al"`
Dt int `json:"dt"`
H struct {
Br int `json:"br"`
Fid int `json:"fid"`
Size int `json:"size"`
Vd float32 `json:"vd"`
Sr int `json:"sr"`
} `json:"h"`
M struct {
Br int `json:"br"`
Fid int `json:"fid"`
Size int `json:"size"`
Vd float32 `json:"vd"`
Sr int `json:"sr"`
} `json:"m"`
L struct {
Br int `json:"br"`
Fid int `json:"fid"`
Size int `json:"size"`
Vd float32 `json:"vd"`
Sr int `json:"sr"`
} `json:"l"`
Sq interface{} `json:"sq"`
Hr interface{} `json:"hr"`
A interface{} `json:"a"`
Cd string `json:"cd"`
No int `json:"no"`
RtURL interface{} `json:"rtUrl"`
Ftype int `json:"ftype"`
RtUrls []interface{} `json:"rtUrls"`
DjID int `json:"djId"`
Copyright int `json:"copyright"`
SID int `json:"s_id"`
Mark int `json:"mark"`
OriginCoverType int `json:"originCoverType"`
OriginSongSimpleData interface{} `json:"originSongSimpleData"`
TagPicList interface{} `json:"tagPicList"`
ResourceState bool `json:"resourceState"`
Version int `json:"version"`
SongJumpInfo interface{} `json:"songJumpInfo"`
EntertainmentTags interface{} `json:"entertainmentTags"`
AwardTags interface{} `json:"awardTags"`
Single int `json:"single"`
NoCopyrightRcmd interface{} `json:"noCopyrightRcmd"`
Rtype int `json:"rtype"`
Rurl interface{} `json:"rurl"`
Mst int `json:"mst"`
Cp int `json:"cp"`
Mv int `json:"mv"`
PublishTime int64 `json:"publishTime"`
Tns []string `json:"tns,omitempty"`
} `json:"songs"`
Privileges []struct {
ID int `json:"id"`
Fee int `json:"fee"`
Payed int `json:"payed"`
St int `json:"st"`
Pl int `json:"pl"`
Dl int `json:"dl"`
Sp int `json:"sp"`
Cp int `json:"cp"`
Subp int `json:"subp"`
Cs bool `json:"cs"`
Maxbr int `json:"maxbr"`
Fl int `json:"fl"`
Toast bool `json:"toast"`
Flag int `json:"flag"`
PreSell bool `json:"preSell"`
PlayMaxbr int `json:"playMaxbr"`
DownloadMaxbr int `json:"downloadMaxbr"`
MaxBrLevel string `json:"maxBrLevel"`
PlayMaxBrLevel string `json:"playMaxBrLevel"`
DownloadMaxBrLevel string `json:"downloadMaxBrLevel"`
PlLevel string `json:"plLevel"`
DlLevel string `json:"dlLevel"`
FlLevel string `json:"flLevel"`
Rscl int `json:"rscl"`
FreeTrialPrivilege struct {
ResConsumable bool `json:"resConsumable"`
UserConsumable bool `json:"userConsumable"`
ListenType interface{} `json:"listenType"`
} `json:"freeTrialPrivilege"`
ChargeInfoList []struct {
Rate int `json:"rate"`
ChargeURL interface{} `json:"chargeUrl"`
ChargeMessage interface{} `json:"chargeMessage"`
ChargeType int `json:"chargeType"`
} `json:"chargeInfoList"`
} `json:"privileges"`
Code int `json:"code"`
// 记录群默认猜歌
type dlist struct {
GroupID int64 `json:"gid"` // 群号
Name string `json:"name"` // 歌单名称
}
// 本地歌单列表信息
type listinfo struct {
Name string `json:"name"` // 歌单名称
Number int // 歌曲数量
ID int64 // 歌单绑定的歌曲ID
}
// 独角兽API随机抽歌信息
type ovooaData struct {
Code int `json:"code"`
Text string `json:"text"`
Data struct {
Song string `json:"song"`
Singer string `json:"singer"`
Cover string `json:"cover"`
Music string `json:"Music"`
ID int `json:"id"`
} `json:"data"`
}

88
plugin/heisi/heisi.go Normal file
View File

@@ -0,0 +1,88 @@
// Package heisi 黑丝
package heisi
import (
"math/rand"
"strconv"
"unsafe"
fbctxext "github.com/FloatTech/floatbox/ctxext"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var (
heisiPic []item
baisiPic []item
jkPic []item
jurPic []item
zukPic []item
mcnPic []item
fileList = [...]string{"heisi.bin", "baisi.bin", "jk.bin", "jur.bin", "zuk.bin", "mcn.bin"}
)
func init() { // 插件主体
engine := control.Register("heisi", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "黑丝\n" +
"- 来点黑丝\n- 来点白丝\n- 来点jk\n- 来点巨乳\n- 来点足控\n- 来点网红",
PublicDataFolder: "Heisi",
})
engine.OnFullMatchGroup([]string{"来点黑丝", "来点白丝", "来点jk", "来点巨乳", "来点足控", "来点网红"}, zero.OnlyGroup, fbctxext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
for i, filePath := range fileList {
data, err := engine.GetLazyData(filePath, true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
if len(data)%10 != 0 {
ctx.SendChain(message.Text("ERROR: invalid data " + strconv.Itoa(i)))
return false
}
s := (*slice)(unsafe.Pointer(&data))
s.len /= 10
s.cap /= 10
switch i {
case 0:
heisiPic = *(*[]item)(unsafe.Pointer(s))
case 1:
baisiPic = *(*[]item)(unsafe.Pointer(s))
case 2:
jkPic = *(*[]item)(unsafe.Pointer(s))
case 3:
jurPic = *(*[]item)(unsafe.Pointer(s))
case 4:
zukPic = *(*[]item)(unsafe.Pointer(s))
case 5:
mcnPic = *(*[]item)(unsafe.Pointer(s))
}
}
return true
})).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
matched := ctx.State["matched"].(string)
var pic item
switch matched {
case "来点黑丝":
pic = heisiPic[rand.Intn(len(heisiPic))]
case "来点白丝":
pic = baisiPic[rand.Intn(len(baisiPic))]
case "来点jk":
pic = jkPic[rand.Intn(len(jkPic))]
case "来点巨乳":
pic = jurPic[rand.Intn(len(jurPic))]
case "来点足控":
pic = zukPic[rand.Intn(len(zukPic))]
case "来点网红":
pic = mcnPic[rand.Intn(len(mcnPic))]
}
m := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image(pic.String()))}
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
})
}

48
plugin/heisi/packer.go Normal file
View File

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

15
plugin/heisi/slice.go Normal file
View File

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

View File

@@ -4,6 +4,7 @@ package hyaku
import (
"encoding/csv"
"fmt"
"io"
"math/rand"
"os"
"reflect"
@@ -12,6 +13,7 @@ import (
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -60,17 +62,30 @@ func init() {
PrivateDataFolder: "hyaku",
})
csvfile := engine.DataFolder() + "hyaku.csv"
err := os.MkdirAll(engine.DataFolder()+"img", 0755)
if err != nil {
panic(err)
}
go func() {
var f *os.File
if file.IsNotExist(csvfile) {
err := file.DownloadTo(bed+"小倉百人一首.csv", csvfile, true)
data, err := web.RequestDataWith(web.NewTLS12Client(), bed+"小倉百人一首.csv", "GET", "gitcode.net", web.RandUA())
if err != nil {
_ = os.Remove(csvfile)
panic(err)
}
}
f, err := os.Open(csvfile)
if err != nil {
panic(err)
f, err = os.Create(csvfile)
if err != nil {
panic(err)
}
_, _ = f.Write(data)
_, _ = f.Seek(0, io.SeekStart)
} else {
var err error
f, err = os.Open(csvfile)
if err != nil {
panic(err)
}
}
records, err := csv.NewReader(f).ReadAll()
if err != nil {
@@ -98,10 +113,20 @@ func init() {
}()
engine.OnFullMatch("百人一首").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
i := rand.Intn(100)
img0, err := engine.GetCustomLazyData(bed, fmt.Sprintf("img/%03d.jpg", i+1))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
img1, err := engine.GetCustomLazyData(bed, fmt.Sprintf("img/%03d.png", i+1))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(
message.Image(fmt.Sprintf(bed+"img/%03d.jpg", i+1)),
message.ImageBytes(img0),
message.Text("\n", lines[i]),
message.Image(fmt.Sprintf(bed+"img/%03d.png", i+1)),
message.ImageBytes(img1),
)
})
engine.OnRegex(`^百人一首之\s?(\d+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
@@ -114,10 +139,20 @@ func init() {
ctx.SendChain(message.Text("ERROR: 超出范围"))
return
}
img0, err := engine.GetCustomLazyData(bed, fmt.Sprintf("img/%03d.jpg", i))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
img1, err := engine.GetCustomLazyData(bed, fmt.Sprintf("img/%03d.png", i))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(
message.Image(fmt.Sprintf(bed+"img/%03d.jpg", i)),
message.ImageBytes(img0),
message.Text("\n", lines[i-1]),
message.Image(fmt.Sprintf(bed+"img/%03d.png", i)),
message.ImageBytes(img1),
)
})
}

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

@@ -0,0 +1,122 @@
// Package jikipedia 小鸡词典
// 修改自https://github.com/TeamPGM/PagerMaid_Plugins_Pyro ,非常感谢!!
package jikipedia
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strings"
"github.com/FloatTech/floatbox/binary"
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 (
url = "https://api.jikipedia.com/go/search_entities"
)
type value struct {
Phrase string `json:"phrase"`
Page int `json:"page"`
Size int `json:"size"`
}
func init() {
// 初始化engine
engine := control.Register(
"jikipedia",
&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "小鸡词典\n -[查梗|小鸡词典][梗]",
},
)
engine.OnPrefixGroup([]string{"小鸡词典", "查梗"}).Limit(ctxext.LimitByGroup).SetBlock(true).Handle(
func(ctx *zero.Ctx) {
keyWord := strings.Trim(ctx.State["args"].(string), " ")
definition, err := parseKeyword(keyWord)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if definition.String() == "" {
ctx.SendChain(message.Text("好像什么都没查到,换个关键词试一试?"))
return
}
imgURL := definition.Get("images.0.scaled.path").String()
ctx.SendChain(message.Text("【标题】:", definition.Get("term.title"),
"\n【释义】:", definition.Get("plaintext"),
"\n【原文】:https://jikipedia.com/definition/", definition.Get("id")),
message.Image(imgURL))
},
)
}
func parseKeyword(keyWord string) (definition gjson.Result, err error) {
client := &http.Client{}
values := value{Phrase: keyWord, Page: 1, Size: 10}
jsonData, err := json.Marshal(values)
if err != nil {
return
}
var request *http.Request
request, err = http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return
}
request.Header = http.Header{
"Accept": {"application/json, text/plain, */*"},
"Accept-Encoding": {"gzip, deflate, br"},
"Accept-Language": {"zh-CN,zh-TW;q=0.9,zh;q=0.8"},
"Client": {"web"},
"Client-Version": {"2.7.2g"},
"Connection": {"keep-alive"},
"Host": {"api.jikipedia.com"},
"Origin": {"https://jikipedia.com"},
"Referer": {"https://jikipedia.com/"},
"Sec-Fetch-Dest": {"empty"},
"Sec-Fetch-Mode": {"cors"},
"Sec-Fetch-Site": {"same-site"},
"Token": {""},
"User-Agent": {"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Mobile Safari/537.36"},
"XID": {"uNo5bL1nyNCp/Gm7lJAHQ91220HLbMT8jqk9IJYhtHA4ofP+zgxwM6lSDIKiYoppP2k1IW/1Vxc2vOVGxOOVReebsLmWPHhTs7NCRygfDkE="},
"sec-ch-ua": {`" Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"`},
"sec-ch-ua-mobile": {"?1"},
"sec-ch-ua-platform": {`"Android"`},
}
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
var response *http.Response
response, err = client.Do(request)
if err != nil {
return
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
extraInfo := ""
if response.StatusCode == 423 {
extraInfo = "\n调用过多被网站暂时封禁请等待数个小时后使用该功能~"
}
s := fmt.Sprintf("status code: %d%s", response.StatusCode, extraInfo)
err = errors.New(s)
return
}
data, err := io.ReadAll(response.Body)
if err != nil {
return
}
gjson.Get(binary.BytesToString(data), "data").ForEach(func(key, value gjson.Result) bool {
definition = value.Get("definitions.0")
return definition.String() == ""
})
return
}

View File

@@ -0,0 +1,105 @@
// Package jptingroom 日语听力学习材料
package jptingroom
import (
"time"
"github.com/FloatTech/floatbox/binary"
fcext "github.com/FloatTech/floatbox/ctxext"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img/text"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
func init() { // 插件主体
engine := control.Register("jptingroom", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "日语听力学习材料\n" +
"- 随机日语听力\n" +
"- 随机日语歌曲\n" +
"- 日语听力 xxx\n" +
"- 日语歌曲 xxx\n",
PublicDataFolder: "Jptingroom",
})
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
db.DBPath = engine.DataFolder() + "item.db"
_, err := engine.GetLazyData("item.db", true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
err = db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
err = db.Create("item", &item{})
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
n, err := db.Count("item")
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return false
}
log.Infof("[jptingroom]读取%d条日语听力材料", n)
return true
})
// 开启
engine.OnFullMatchGroup([]string{"随机日语听力", "随机日语歌曲"}, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
matched := ctx.State["matched"].(string)
var t item
switch matched {
case "随机日语听力":
t = getRandomAudioByCategory("tingli")
case "随机日语歌曲":
t = getRandomAudioByCategory("gequ")
default:
}
if t.AudioURL == "" {
ctx.SendChain(message.Text("未能找到相关材料"))
return
}
ctx.SendChain(message.Record(t.AudioURL))
content := t.Title + "\n\n" + t.Content
data, err := text.RenderToBase64(content, text.FontFile, 400, 20)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
})
engine.OnRegex(`日语(听力|歌曲)\s?([一-龥A-Za-z0-9ぁ-んァ-ヶ]{1,50})$`, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
regexMatched := ctx.State["regex_matched"].([]string)
var t item
switch regexMatched[1] {
case "听力":
t = getRandomAudioByCategoryAndKeyword("tingli", regexMatched[2])
case "歌曲":
t = getRandomAudioByCategoryAndKeyword("gequ", regexMatched[2])
default:
}
if t.AudioURL == "" {
ctx.SendChain(message.Text("未能找到相关材料"))
return
}
content := t.Title + "\n\n" + t.Content
data, err := text.RenderToBase64(content, text.FontFile, 400, 20)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if id := ctx.SendChain(message.Image("base64://" + binary.BytesToString(data))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
})
}

View File

@@ -0,0 +1,30 @@
package jptingroom
import (
"time"
sql "github.com/FloatTech/sqlite"
)
type item struct {
ID int64 `db:"id"`
Title string `db:"title"`
PageURL string `db:"page_url"`
Category string `db:"category"`
Intro string `db:"intro"`
AudioURL string `db:"audio_url"`
Content string `db:"content"`
Datetime time.Time `db:"datetime"`
}
var db = &sql.Sqlite{}
func getRandomAudioByCategory(category string) (t item) {
_ = db.Find("item", &t, "where category = '"+category+"' ORDER BY RANDOM() limit 1")
return
}
func getRandomAudioByCategoryAndKeyword(category string, keyword string) (t item) {
_ = db.Find("item", &t, "where category = '"+category+"' and (title like '%"+keyword+"%' or content like '%"+keyword+"%') ORDER BY RANDOM() limit 1")
return
}

View File

@@ -3,6 +3,8 @@ package lolicon
import (
"encoding/base64"
"errors"
"net/url"
"strings"
"time"
@@ -16,7 +18,7 @@ import (
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img/pool"
imagepool "github.com/FloatTech/zbputils/img/pool"
)
const (
@@ -25,23 +27,35 @@ const (
)
var (
queue = make(chan string, capacity)
custapi = ""
queue = make(chan string, capacity)
customapi = ""
)
func init() {
en := control.Register("lolicon", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "lolicon\n" +
"- 来份萝莉\n" +
"- 随机图片\n" +
"- 随机图片 萝莉|少女\n" +
"- 设置随机图片地址[http...]",
}).ApplySingle(ctxext.DefaultSingle)
en.OnFullMatch("来份萝莉").Limit(ctxext.LimitByGroup).SetBlock(true).
en.OnPrefix("随机图片").Limit(ctxext.LimitByUser).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if imgtype := strings.TrimSpace(ctx.State["args"].(string)); imgtype != "" {
imageurl, err := getimgurl(api + "?tag=" + url.QueryEscape(imgtype))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if id := ctx.Send(message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image(imageurl))}).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
return
}
go func() {
for i := 0; i < math.Min(cap(queue)-len(queue), 2); i++ {
if custapi != "" {
data, err := web.GetData(custapi)
if customapi != "" {
data, err := web.GetData(customapi)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
continue
@@ -49,29 +63,22 @@ func init() {
queue <- "base64://" + base64.StdEncoding.EncodeToString(data)
continue
}
data, err := web.GetData(api)
imageurl, err := getimgurl(api)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
continue
}
json := gjson.ParseBytes(data)
if e := json.Get("error").Str; e != "" {
ctx.SendChain(message.Text("ERROR: ", e))
continue
}
url := json.Get("data.0.urls.original").Str
url = strings.ReplaceAll(url, "i.pixiv.cat", "i.pixiv.re")
name := url[strings.LastIndex(url, "/")+1 : len(url)-4]
m, err := pool.GetImage(name)
name := imageurl[strings.LastIndex(imageurl, "/")+1 : len(imageurl)-4]
m, err := imagepool.GetImage(name)
if err != nil {
m.SetFile(url)
_, err = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
m.SetFile(imageurl)
_, _ = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
process.SleepAbout1sTo2s()
}
if err == nil {
queue <- m.String()
} else {
queue <- url
queue <- imageurl
}
}
}()
@@ -79,12 +86,10 @@ func init() {
case <-time.After(time.Minute):
ctx.SendChain(message.Text("ERROR: 等待填充,请稍后再试......"))
case img := <-queue:
id := ctx.SendChain(message.Image(img))
if id.ID() == 0 {
if id := ctx.Send(message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image(img))}).ID(); id == 0 {
process.SleepAbout1sTo2s()
id = ctx.SendChain(message.Image(img).Add("cache", "0"))
if id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 图片发送失败,可能被风控了~"))
if id := ctx.Send(message.Message{ctxext.FakeSenderForwardNode(ctx, message.Image(img).Add("cache", "0"))}).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
}
}
}
@@ -92,10 +97,23 @@ func init() {
en.OnPrefix("设置随机图片地址", zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
u := strings.TrimSpace(ctx.State["args"].(string))
if !strings.HasPrefix(u, "http") {
ctx.SendChain(message.Text("ERROR: url非法!"))
return
}
custapi = u
ctx.SendChain(message.Text("成功设置随机图片地址为", u))
customapi = u
})
}
func getimgurl(url string) (string, error) {
data, err := web.GetData(url)
if err != nil {
return "", err
}
json := gjson.ParseBytes(data)
if e := json.Get("error").Str; e != "" {
return "", errors.New(e)
}
var imageurl string
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
}

View File

@@ -16,12 +16,13 @@ import (
const (
jpapi = "https://moegoe.azurewebsites.net/api/speak?text=%s&id=%d"
krapi = "https://moegoe.azurewebsites.net/api/speakkr?text=%s&id=%d"
cnapi = "http://233366.proxy.nscc-gz.cn:8888?speaker=%s&text=%s"
cnapi = "https://genshin.azurewebsites.net/api/speak?format=mp3&text=%s&id=%d"
)
var speakers = map[string]uint{
"宁宁": 0, "爱瑠": 1, "芳乃": 2, "茉子": 3, "丛雨": 4, "小春": 5, "七海": 6,
"Sua": 0, "Mimiru": 1, "Arin": 2, "Yeonhwa": 3, "Yuhwa": 4, "Seonbae": 5,
"派蒙": 0, "凯亚": 1, "安柏": 2, "丽莎": 3, "琴": 4, "香菱": 5, "枫原万叶": 6, "迪卢克": 7, "温迪": 8, "可莉": 9, "早柚": 10, "托马": 11, "芭芭拉": 12, "优菈": 13, "云堇": 14, "钟离": 15, "魈": 16, "凝光": 17, "雷电将军": 18, "北斗": 19, "甘雨": 20, "七七": 21, "刻晴": 22, "神里绫华": 23, "戴因斯雷布": 24, "雷泽": 25, "神里绫人": 26, "罗莎莉亚": 27, "阿贝多": 28, "八重神子": 29, "宵宫": 30, "荒泷一斗": 31, "九条裟罗": 32, "夜兰": 33, "珊瑚宫心海": 34, "五郎": 35, "散兵": 36, "女士": 37, "达达利亚": 38, "莫娜": 39, "班尼特": 40, "申鹤": 41, "行秋": 42, "烟绯": 43, "久岐忍": 44, "辛焱": 45, "砂糖": 46, "胡桃": 47, "重云": 48, "菲谢尔": 49, "诺艾尔": 50, "迪奥娜": 51, "鹿野院平藏": 52,
}
func init() {
@@ -46,8 +47,8 @@ func init() {
})
en.OnRegex("^让(派蒙|凯亚|安柏|丽莎|琴|香菱|枫原万叶|迪卢克|温迪|可莉|早柚|托马|芭芭拉|优菈|云堇|钟离|魈|凝光|雷电将军|北斗|甘雨|七七|刻晴|神里绫华|雷泽|神里绫人|罗莎莉亚|阿贝多|八重神子|宵宫|荒泷一斗|九条裟罗|夜兰|珊瑚宫心海|五郎|达达利亚|莫娜|班尼特|申鹤|行秋|烟绯|久岐忍|辛焱|砂糖|胡桃|重云|菲谢尔|诺艾尔|迪奥娜|鹿野院平藏)说([\\s\u4e00-\u9fa5\\pP]+)$").Limit(ctxext.LimitByGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
speaker := ctx.State["regex_matched"].([]string)[1]
text := ctx.State["regex_matched"].([]string)[2]
ctx.SendChain(message.Record(fmt.Sprintf(cnapi, url.QueryEscape(speaker), url.QueryEscape(text))))
id := speakers[ctx.State["regex_matched"].([]string)[1]]
ctx.SendChain(message.Record(fmt.Sprintf(cnapi, url.QueryEscape(text), id)))
})
}

View File

@@ -138,7 +138,7 @@ func kugou(keyword string) message.MessageSegment {
// cloud163 返回网易云音乐卡片
func cloud163(keyword string) (msg message.MessageSegment) {
requestURL := "https://music.cyrilstudio.top/search?keywords=" + url.QueryEscape(keyword)
requestURL := "http://music.163.com/api/search/get/web?type=1&limit=1&s=" + url.QueryEscape(keyword)
data, err := web.GetData(requestURL)
if err != nil {
msg = message.Text("ERROR: ", err)
@@ -150,14 +150,13 @@ func cloud163(keyword string) (msg message.MessageSegment) {
// qqmusic 返回QQ音乐卡片
func qqmusic(keyword string) (msg message.MessageSegment) {
requestURL := "https://c.y.qq.com/soso/fcgi-bin/client_search_cp?w=" + url.QueryEscape(keyword)
requestURL := "https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg?platform=yqq.json&key=" + url.QueryEscape(keyword)
data, err := web.RequestDataWith(web.NewDefaultClient(), requestURL, "GET", "", web.RandUA())
if err != nil {
msg = message.Text("ERROR: ", err)
return
}
info := gjson.ParseBytes(data[9 : len(data)-1]).Get("data.song.list.0")
msg = message.Music("qq", info.Get("songid").Int())
msg = message.Music("qq", gjson.ParseBytes(data).Get("data.song.itemlist.0.id").Int())
return
}

View File

@@ -32,7 +32,7 @@ func init() {
engine.OnPrefix("抽wife", zero.OnlyGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
grpf := strconv.FormatInt(ctx.Event.GroupID, 36)
wifes, err := os.ReadDir(base + "/" + grpf)
wifes, err := os.ReadDir(base + grpf)
if err != nil {
ctx.SendChain(message.Text("一个wife也没有哦~"))
return
@@ -42,7 +42,7 @@ func init() {
ctx.SendChain(message.Text("一个wife也没有哦~"))
case 1:
wn := wifes[0].Name()
ctx.SendChain(message.Text("大家的wife都是", wn, "\n"), message.Image(baseuri+"/"+grpf+"/"+wn), message.Text("\n哦~"))
ctx.SendChain(message.Text("大家的wife都是", wn, "\n"), message.Image(baseuri+grpf+"/"+wn), message.Text("\n哦~"))
default:
// 获取名字
name := ctx.NickName()
@@ -51,7 +51,7 @@ func init() {
r := rand.New(rand.NewSource(int64(binary.LittleEndian.Uint64(s[:]))))
n := r.Intn(len(wifes))
wn := wifes[n].Name()
ctx.SendChain(message.Text(name, "的wife是", wn, "\n"), message.Image(baseuri+"/"+grpf+"/"+wn), message.Text("\n哦~"))
ctx.SendChain(message.Text(name, "的wife是", wn, "\n"), message.Image(baseuri+grpf+"/"+wn), message.Text("\n哦~"))
}
})
// 上传一张图
@@ -69,7 +69,7 @@ func init() {
}
if name != "" {
url := ctx.State["image_url"].([]string)[0]
grpfolder := base + "/" + strconv.FormatInt(ctx.Event.GroupID, 36)
grpfolder := base + strconv.FormatInt(ctx.Event.GroupID, 36)
if file.IsNotExist(grpfolder) {
err := os.Mkdir(grpfolder, 0755)
if err != nil {
@@ -100,7 +100,7 @@ func init() {
}
}
if name != "" {
grpfolder := base + "/" + strconv.FormatInt(ctx.Event.GroupID, 36)
grpfolder := base + strconv.FormatInt(ctx.Event.GroupID, 36)
err := os.Remove(grpfolder + "/" + name)
if err == nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功!"))

View File

@@ -17,7 +17,7 @@ import (
"github.com/FloatTech/zbputils/img/text"
)
const bed = "https://gitcode.net/u011570312/senso-ji-omikuji/-/raw/main/%d_%d.jpg"
const bed = "https://gitcode.net/u011570312/senso-ji-omikuji/-/raw/main/"
func init() { // 插件主体
engine := control.Register("omikuji", &ctrl.Options[*zero.Ctx]{
@@ -30,10 +30,20 @@ func init() { // 插件主体
engine.OnFullMatchGroup([]string{"求签", "占卜"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
i := fcext.RandSenderPerDayN(ctx.Event.UserID, 100) + 1
img0, err := engine.GetCustomLazyData(bed, fmt.Sprintf("%d_%d.jpg", i, 0))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
img1, err := engine.GetCustomLazyData(bed, fmt.Sprintf("%d_%d.jpg", i, 1))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(
message.At(ctx.Event.UserID),
message.Image(fmt.Sprintf(bed, i, 0)),
message.Image(fmt.Sprintf(bed, i, 1)),
message.ImageBytes(img0),
message.ImageBytes(img1),
)
})
engine.OnFullMatch("解签", fcext.DoOnceOnSuccess(

View File

@@ -18,8 +18,6 @@ import (
"github.com/wdvxdr1123/ZeroBot/extension/single"
// 数据库
sql "github.com/FloatTech/sqlite"
// 定时器
"github.com/wdvxdr1123/ZeroBot/extension/rate"
// 画图
"github.com/Coloured-glaze/gg"
fcext "github.com/FloatTech/floatbox/ctxext"
@@ -29,12 +27,11 @@ import (
)
// nolint: asciicheck
//nolint: asciicheck
// nolint: asciicheck
var (
民政局 = &婚姻登记{
db: &sql.Sqlite{},
}
skillCD = rate.NewManager[string](time.Hour*12, 1)
sendtext = [...][]string{
{ // 表白成功
"是个勇敢的孩子(*/ω\*) 今天的运气都降临在你的身边~\n\n",
@@ -49,12 +46,12 @@ var (
"因为你的个人魅力~~今天他就是你的了w\n\n",
},
{ // 离婚失败
"打是情骂是爱,不打不亲不相爱。答应我不要分手。",
"打是情,骂是爱,不打不亲不相爱。答应我不要分手。",
"床头打架床尾和,夫妻没有隔夜仇。安啦安啦,不要闹变扭。",
},
{ // 离婚成功
"离婚成功力\n天涯何处无芳草何必单恋一枝花不如再摘一支bushi",
"离婚成功力\n话说你不考虑当个1",
"离婚成功力\n天涯何处无芳草何必单恋一枝花不如再摘一支bushi",
},
}
)
@@ -64,9 +61,14 @@ func init() {
DisableOnDefault: false,
PrivateDataFolder: "qqwife",
Help: "一群一天一夫一妻制群老婆\n每天凌晨刷新CP\n" +
"- 娶群友\n- 群老婆列表\n- 我群老婆\n" +
"--------------------------------\n以下技能每个CD12H不跨天刷新\n--------------------------------\n" +
"- (娶|嫁)@对方QQ\n- 当[对方Q号|@对方QQ]的小三\n- 闹离婚",
"- 娶群友\n- 群老婆列表\n- 允许/禁止自由恋爱\n- 允许/禁止牛头人\n- 设置CD为xx小时 →(默认12小时)\n- 重置花名册\n- 重置所有花名册(用于清除所有群数据及其设置)\n" +
"--------------------------------\n以下指令存在CD,不跨天刷新,前两个受指令开关\n--------------------------------\n" +
"- (娶|嫁)@对方QQ\n自由选择对象,自由恋爱(好感度越高成功率越高,保底30%概率)\n" +
"- 当[对方Q号|@对方QQ]的小三\n我和你才是真爱为了你我愿意付出一切(好感度越高成功率越高,保底10%概率)\n" +
"- 闹离婚\n你谁啊给我滚(好感度越高成功率越低)\n" +
"- 做媒 @攻方QQ @受方QQ\n身为管理群友的xing福是要搭把手的(攻受双方好感度越高成功率越高,保底30%概率)\n" +
"--------------------------------\n好感度规则\n--------------------------------\n" +
"娶群友指令好感度随机增加1~5。\nA牛B的C会导致C恨A好感度-5;\nB为了报复A好感度+5(什么柜子play)\nA为BC做媒,成功B、C对A好感度+1反之-1\n做媒成功BC好感度+1",
}).ApplySingle(single.New(
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
single.WithPostFn[int64](func(ctx *zero.Ctx) {
@@ -81,24 +83,76 @@ func init() {
民政局.db.DBPath = engine.DataFolder() + "结婚登记表.db"
err := 民政局.db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return false
}
return true
})
// 技能CD设置
engine.OnRegex(`^设置CD为(\d+)小时`, zero.OnlyGroup, zero.AdminPermission, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
cdTime, err := strconv.ParseFloat(ctx.State["regex_matched"].([]string)[1], 64)
if err != nil {
ctx.SendChain(message.Text("[qqwife]请设置纯数字\n", err))
return
}
gid := ctx.Event.GroupID
err = 民政局.setCDtime(gid, cdTime)
if err != nil {
ctx.SendChain(message.Text("[qqwife]设置CD时长失败\n", err))
return
}
ctx.SendChain(message.Text("设置成功"))
})
engine.OnRegex(`^(允许|禁止)(自由恋爱|牛头人)$`, zero.OnlyGroup, zero.AdminPermission, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
status := ctx.State["regex_matched"].([]string)[1]
mode := ctx.State["regex_matched"].([]string)[2]
gid := ctx.Event.GroupID
statusBool := 1
if status == "禁止" {
statusBool = 0
}
err := 民政局.修改模式(gid, mode, statusBool)
if err != nil {
ctx.SendChain(message.Text("[qqwife]群状态查询失败\n", err))
return
}
ctx.SendChain(message.Text("设置成功"))
})
// 好感度系统
engine.OnRegex(`^查好感度\s?\[CQ:at,qq=(\d+)\]`, zero.OnlyGroup, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
fiancee, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
if err != nil {
ctx.SendChain(message.Text("[qqwife]你对象好像不存在?\n", err))
return
}
uid := ctx.Event.UserID
favor, err := 民政局.getFavorability(uid, fiancee)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
return
}
// 输出结果
ctx.SendChain(
message.At(uid),
message.Text("\n当前你们好感度为", favor),
)
})
engine.OnFullMatch("娶群友", zero.OnlyGroup, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
_, err := 民政局.开门时间(gid)
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return
}
uid := ctx.Event.UserID
targetinfo, status, err := 民政局.查户口(gid, uid)
switch {
case status == "错":
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return
case (status == "攻" && targetinfo.Target == 0) ||
(status == "受" && targetinfo.User == 0): // 如果是单身贵族
@@ -107,7 +161,7 @@ func init() {
case status == "攻": // 娶过别人
ctx.SendChain(
message.At(uid),
message.Text("\n今天你已经娶过了,群老婆是"),
message.Text("\n今天你在", targetinfo.Updatetime, "娶了群友"),
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(targetinfo.Target, 10)+"&s=640").Add("cache", 0),
message.Text(
"\n",
@@ -119,12 +173,12 @@ func init() {
case status == "受": // 嫁给别人
ctx.SendChain(
message.At(uid),
message.Text("\n今天你被娶了,群老公是"),
message.Text("\n今天你在", targetinfo.Updatetime, "被群友"),
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(targetinfo.User, 10)+"&s=640").Add("cache", 0),
message.Text(
"\n",
"[", targetinfo.Username, "]",
"(", targetinfo.User, ")",
"(", targetinfo.User, ")娶了",
),
)
return
@@ -139,7 +193,11 @@ func init() {
qqgrouplist := make([]int64, 0, len(temp))
for k := 0; k < len(temp); k++ {
usr := temp[k].Get("user_id").Int()
_, status, _ := 民政局.查户口(gid, usr)
_, status, err := 民政局.查户口(gid, usr)
if status == "错" {
ctx.SendChain(message.Text("[qqwife]花名册数据读取有误,请重试\n", err))
return
}
if status != "单" {
continue
}
@@ -159,9 +217,13 @@ func init() {
// 去民政局办证
err = 民政局.登记(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return
}
favor, err := 民政局.setFavorability(uid, fiancee, 1+rand.Intn(5))
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
}
// 请大家吃席
ctx.SendChain(
message.At(uid),
@@ -170,23 +232,28 @@ func init() {
message.Text(
"\n",
"[", ctx.CardOrNickName(fiancee), "]",
"(", fiancee, ")哒",
"(", fiancee, ")哒\n当前你们好感度为", favor,
),
)
})
// 单身技能
engine.OnRegex(`^(娶|嫁)\[CQ:at,qq=(\d+)\]`, zero.OnlyGroup, getdb, checkdog).SetBlock(true).Limit(cdcheck, iscding).
engine.OnRegex(`^(娶|嫁)\[CQ:at,qq=(\d+)\]`, zero.OnlyGroup, getdb, checkdog).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
choice := ctx.State["regex_matched"].([]string)[1]
fiancee, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
uid := ctx.Event.UserID
gid := ctx.Event.GroupID
// 写入CD
err := 民政局.writeCDtime(gid, uid, 1)
if err != nil {
ctx.SendChain(message.At(uid), message.Text("[qqwife]你的技能CD记录失败\n", err))
}
if uid == fiancee { // 如果是自己
switch rand.Intn(3) {
case 1:
err := 民政局.登记(gid, uid, 0, "", "")
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return
}
ctx.SendChain(message.Text("今日获得成就:单身贵族"))
@@ -195,7 +262,15 @@ func init() {
}
return
}
if rand.Intn(2) == 0 { // 二分之一的概率表白成功
favor, err := 民政局.getFavorability(uid, fiancee)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
return
}
if favor < 30 {
favor = 30 // 保底30%概率
}
if rand.Intn(101) >= favor {
ctx.SendChain(message.Text(sendtext[1][rand.Intn(len(sendtext[1]))]))
return
}
@@ -205,14 +280,14 @@ func init() {
case "娶":
err := 民政局.登记(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
if err != nil {
ctx.SendChain(message.Text("结婚登记失败力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]结婚登记失败力\n", err))
return
}
choicetext = "\n今天你的群老婆是"
default:
err := 民政局.登记(gid, fiancee, uid, ctx.CardOrNickName(fiancee), ctx.CardOrNickName(uid))
if err != nil {
ctx.SendChain(message.Text("结婚登记失败力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]结婚登记失败力\n", err))
return
}
choicetext = "\n今天你的群老公是"
@@ -231,31 +306,45 @@ func init() {
)
})
// NTR技能
engine.OnRegex(`^当(\[CQ:at,qq=(\d+)\]\s?|(\d+))的小三`, zero.OnlyGroup, getdb, checkcp).SetBlock(true).Limit(cdcheck2, iscding).
engine.OnRegex(`^当(\[CQ:at,qq=(\d+)\]\s?|(\d+))的小三`, zero.OnlyGroup, getdb, checkcp).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
fid := ctx.State["regex_matched"].([]string)
fiancee, _ := strconv.ParseInt(fid[2]+fid[3], 10, 64)
uid := ctx.Event.UserID
// 写入CD
err := 民政局.writeCDtime(gid, uid, 2)
if err != nil {
ctx.SendChain(message.At(uid), message.Text("[qqwife]你的技能CD记录失败\n", err))
}
if fiancee == uid {
ctx.SendChain(message.Text("今日获得成就:自我攻略"))
return
}
if rand.Intn(10)/4 != 0 { // 十分之三的概率NTR成功
favor, err := 民政局.getFavorability(uid, fiancee)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
return
}
if favor < 30 {
favor = 30 // 保底10%概率
}
if rand.Intn(101) >= favor/3 {
ctx.SendChain(message.Text("失败了!可惜"))
return
}
gid := ctx.Event.GroupID
// 判断target是老公还是老婆
var choicetext string
userID := uid
targetID := fiancee
fianceeinfo, gender, err := 民政局.查户口(gid, fiancee)
userAID := uid //攻的
var userBID int64 //被牛的
userCID := fiancee //受的
fianceeinfo, gender, err := 民政局.查户口(gid, userCID)
switch gender {
case "单":
ctx.SendChain(message.Text("ta现在还是单身哦快向ta表白吧"))
return
case "错":
ctx.SendChain(message.Text("对象状态查询失败\n[error]", err))
ctx.SendChain(message.Text("[qqwife]对象状态查询失败\n", err))
return
case "攻":
err = 民政局.离婚休妻(gid, fianceeinfo.Target)
@@ -263,8 +352,9 @@ func init() {
ctx.SendChain(message.Text("ta不想和原来的对象分手...\n[error]", err))
return
}
userID = fiancee
targetID = uid
userAID = fiancee
userCID = uid
userBID = fianceeinfo.Target
choicetext = "老公"
case "受":
err = 民政局.离婚休夫(gid, fianceeinfo.User)
@@ -272,16 +362,25 @@ func init() {
ctx.SendChain(message.Text("ta不想和原来的对象分手...\n[error]", err))
return
}
userBID = fianceeinfo.User
choicetext = "老婆"
default:
ctx.SendChain(message.Text("数据库发生问题力"))
return
}
err = 民政局.登记(gid, userID, targetID, ctx.CardOrNickName(userID), ctx.CardOrNickName(targetID))
err = 民政局.登记(gid, userAID, userCID, ctx.CardOrNickName(userAID), ctx.CardOrNickName(userCID))
if err != nil {
ctx.SendChain(message.Text("复婚登记失败力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]复婚登记失败力\n", err))
return
}
favor, err = 民政局.setFavorability(userAID, userCID, -5)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
}
_, err = 民政局.setFavorability(userAID, userBID, 5)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
}
// 输出结果
ctx.SendChain(
message.Text(sendtext[2][rand.Intn(len(sendtext[2]))]),
@@ -291,16 +390,130 @@ func init() {
message.Text(
"\n",
"[", ctx.CardOrNickName(fiancee), "]",
"(", fiancee, ")哒",
"(", fiancee, ")哒\n当前你们好感度为", favor,
),
)
})
// 做媒技能
engine.OnRegex(`^做媒\s?\[CQ:at,qq=(\d+)\]\s?\[CQ:at,qq=(\d+)\]`, zero.OnlyGroup, zero.AdminPermission, getdb, checkCondition).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
gayOne, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
gayZero, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
// 写入CD
err := 民政局.writeCDtime(gid, uid, 3)
if err != nil {
ctx.SendChain(message.At(uid), message.Text("[qqwife]你的技能CD记录失败\n", err))
}
favor, err := 民政局.getFavorability(gayOne, gayZero)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
return
}
if favor < 30 {
favor = 30 // 保底30%概率
}
if rand.Intn(101) >= favor {
_, err = 民政局.setFavorability(uid, gayOne, -1)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
}
_, err = 民政局.setFavorability(uid, gayZero, -1)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
}
ctx.SendChain(message.Text(sendtext[1][rand.Intn(len(sendtext[1]))]))
return
}
// 去民政局登记
err = 民政局.登记(gid, gayOne, gayZero, ctx.CardOrNickName(gayOne), ctx.CardOrNickName(gayZero))
if err != nil {
ctx.SendChain(message.Text("[qqwife]结婚登记失败力\n", err))
return
}
_, err = 民政局.setFavorability(uid, gayOne, 1)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
}
_, err = 民政局.setFavorability(uid, gayZero, 1)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
}
_, err = 民政局.setFavorability(gayOne, gayZero, 1)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
}
// 请大家吃席
ctx.SendChain(
message.At(uid),
message.Text("恭喜你成功撮合了一对CP\n\n"),
message.At(gayOne),
message.Text("今天你的群老婆是"),
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(gayZero, 10)+"&s=640").Add("cache", 0),
message.Text(
"\n",
"[", ctx.CardOrNickName(gayZero), "]",
"(", gayZero, ")哒",
),
)
})
engine.OnFullMatchGroup([]string{"闹离婚", "办离婚"}, zero.OnlyGroup, getdb, checkdivorce).Limit(ctxext.LimitByUser).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
// 写入CD
err := 民政局.writeCDtime(gid, uid, 4)
if err != nil {
ctx.SendChain(message.At(uid), message.Text("[qqwife]你的技能CD记录失败\n", err))
}
info, uidstatus, err := 民政局.查户口(gid, uid)
mun := 2
var fiancee int64
switch uidstatus {
case "错":
ctx.SendChain(message.Text("[qqwife]用户状态查询失败\n", err))
return
case "攻":
mun = 1
fiancee = info.Target
case "受":
mun = 0
fiancee = info.User
}
favor, err := 民政局.getFavorability(uid, fiancee)
if err != nil {
ctx.SendChain(message.Text("[qqwife]好感度库发生问题力\n", err))
return
}
if favor < 20 {
favor = 10
}
if rand.Intn(101) > 100-favor {
ctx.SendChain(message.Text(sendtext[3][rand.Intn(len(sendtext[3]))]))
return
}
switch mun {
case 1:
err = 民政局.离婚休妻(gid, fiancee)
case 0:
err = 民政局.离婚休夫(gid, fiancee)
default:
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return
}
if err != nil {
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return
}
ctx.SendChain(message.Text(sendtext[4][mun]))
})
engine.OnFullMatch("群老婆列表", zero.OnlyGroup, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
ok, err := 民政局.开门时间(gid)
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return
}
if ok {
@@ -309,7 +522,7 @@ func init() {
}
list, number, err := 民政局.花名册(gid)
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return
}
if number <= 0 {
@@ -327,13 +540,13 @@ func init() {
/***********下载字体,可以注销掉***********/
_, err = file.GetLazyData(text.BoldFontFile, true)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
ctx.SendChain(message.Text("[qqwife]ERROR: ", err))
}
/***********设置字体颜色为黑色***********/
canvas.SetRGB(0, 0, 0)
/***********设置字体大小,并获取字体高度用来定位***********/
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize*2); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
ctx.SendChain(message.Text("[qqwife]ERROR: ", err))
return
}
sl, h := canvas.MeasureString("群老婆列表")
@@ -342,7 +555,7 @@ func init() {
canvas.DrawString("————————————————————", 0, 250-h)
/***********设置字体大小,并获取字体高度用来定位***********/
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
ctx.SendChain(message.Text("[qqwife]ERROR: ", err))
return
}
_, h = canvas.MeasureString("焯")
@@ -357,53 +570,6 @@ func init() {
ctx.SendChain(message.ImageBytes(data))
cl()
})
engine.OnFullMatchGroup([]string{"闹离婚", "办离婚"}, zero.OnlyGroup, getdb, func(ctx *zero.Ctx) bool {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
_, uidstatus, err := 民政局.查户口(gid, uid)
switch uidstatus {
case "错":
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
return false
case "单":
ctx.SendChain(message.Text("今天你还没结婚哦"))
return false
}
return true
}).SetBlock(true).Limit(cdcheck3, iscding2).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
info, uidstatus, err := 民政局.查户口(gid, uid)
mun := 2
switch uidstatus {
case "错":
ctx.SendChain(message.Text("用户状态查询失败\n[error]", err))
return
case "攻":
mun = 1
case "受":
mun = 0
}
if rand.Intn(10) != 1 { // 十分之一的概率成功
ctx.SendChain(message.Text(sendtext[3][rand.Intn(len(sendtext[3]))]))
return
}
switch mun {
case 1:
err = 民政局.离婚休妻(gid, info.Target)
case 0:
err = 民政局.离婚休妻(gid, info.Target)
default:
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
return
}
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
return
}
ctx.SendChain(message.Text(sendtext[4][mun]))
})
engine.OnRegex(`^重置(所有|本群|/d+)?花名册$`, zero.SuperUserPermission, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
cmd := "0"
@@ -427,54 +593,9 @@ func init() {
}
err := 民政局.清理花名册(cmd)
if err != nil {
ctx.SendChain(message.Text("数据库发生问题力\n[error]", err))
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return
}
ctx.SendChain(message.Text("重置成功"))
})
engine.OnFullMatch("我群老婆", zero.OnlyGroup, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
gid := ctx.Event.GroupID
ok, err := 民政局.开门时间(gid)
if err != nil {
ctx.SendChain(message.Text("群状态查询失败\n[error]", err))
return
}
if ok {
ctx.SendChain(message.Text("今天你还没结婚哦"))
return
}
uid := ctx.Event.UserID
info, uidstatus, err := 民政局.查户口(gid, uid)
switch uidstatus {
case "错":
ctx.SendChain(message.Text("用户状态查询失败\n[error]", err))
return
case "单":
ctx.SendChain(message.Text("今天你还没结婚哦"))
return
case "攻": // 娶过别人
ctx.SendChain(
message.At(uid),
message.Text("\n今天你的群老婆是"),
message.Text(
"\n",
"[", info.Targetname, "]",
"(", info.Target, ")哒",
),
)
return
case "受": // 嫁给别人
ctx.SendChain(
message.At(uid),
message.Text("\n今天你被娶了群老公是"),
message.Text(
"\n",
"[", info.Username, "]",
"(", info.User, ")哒",
),
)
return
}
})
}

View File

@@ -1,20 +1,20 @@
package qqwife
import (
"errors"
"strconv"
"sync"
"time"
sql "github.com/FloatTech/sqlite"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/extension/rate"
"github.com/wdvxdr1123/ZeroBot/message"
// 画图
"github.com/Coloured-glaze/gg"
)
//nolint: asciicheck
// nolint: asciicheck
// nolint: asciicheck
type 婚姻登记 struct {
db *sql.Sqlite
@@ -34,8 +34,24 @@ type userinfo struct {
// 民政局的当前时间
type updateinfo struct {
GID int64
Updatetime string // 登记时间
Updatetime string // 登记时间
CanMatch int // 订婚开关
CanNtr int // Ntr技能开关
CDtime float64 // CD时间
}
// 好感度系统
type favorability struct {
Userinfo string // 记录用户
Favor int // 好感度
}
// 技能CD记录表
type cdsheet struct {
Time int64 // 时间
GroupID int64 // 群号
UserID int64 // 用户
ModeID int64 // 技能类型
}
func (sql *婚姻登记) 开门时间(gid int64) (ok bool, err error) {
@@ -55,31 +71,103 @@ func (sql *婚姻登记) 开门时间(gid int64) (ok bool, err error) {
err = sql.db.Insert("updateinfo", &updateinfo{
GID: gid,
Updatetime: time.Now().Format("2006/01/02"),
CanMatch: 1,
CanNtr: 1,
CDtime: 12,
})
if err == nil {
ok = true
}
return
}
// 开门了就拿新的花名册
if time.Now().Format("2006/01/02") == dbinfo.Updatetime {
return
}
err = sql.db.Drop(gidstr)
// 开门了就拿新的花名册
err = sql.db.Drop("group" + gidstr)
if err != nil {
return
if err = sql.db.Create("group"+gidstr, &userinfo{}); err != nil {
return
}
}
updateinfo := updateinfo{
GID: gid,
Updatetime: time.Now().Format("2006/01/02"),
}
err = sql.db.Insert("updateinfo", &updateinfo)
dbinfo.Updatetime = time.Now().Format("2006/01/02")
err = sql.db.Insert("updateinfo", &dbinfo)
if err == nil {
ok = true
}
return
}
func (sql *婚姻登记) 营业模式(gid int64) (canMatch, canNtr int, err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
err = sql.db.Create("updateinfo", &updateinfo{})
if err != nil {
if err = sql.db.Drop("updateinfo"); err == nil {
err = sql.db.Create("updateinfo", &updateinfo{})
}
if err != nil {
return
}
}
gidstr := strconv.FormatInt(gid, 10)
dbinfo := updateinfo{}
err = sql.db.Find("updateinfo", &dbinfo, "where gid is "+gidstr)
if err != nil {
canMatch = 1
canNtr = 1
err = sql.db.Insert("updateinfo", &updateinfo{
GID: gid,
CanMatch: canMatch,
CanNtr: canNtr,
CDtime: 12,
})
return
}
canMatch = dbinfo.CanMatch
canNtr = dbinfo.CanNtr
return
}
func (sql *婚姻登记) 修改模式(gid int64, mode string, stauts int) (err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
err = sql.db.Create("updateinfo", &updateinfo{})
if err != nil {
if err = sql.db.Drop("updateinfo"); err == nil {
err = sql.db.Create("updateinfo", &updateinfo{})
}
if err != nil {
return
}
}
gidstr := strconv.FormatInt(gid, 10)
dbinfo := updateinfo{}
err = sql.db.Find("updateinfo", &dbinfo, "where gid is "+gidstr)
switch mode {
case "自由恋爱":
dbinfo.CanMatch = stauts
case "牛头人":
dbinfo.CanNtr = stauts
default:
return errors.New("错误:修改内容不匹配!")
}
if err != nil {
dbinfo.GID = gid
switch mode {
case "自由恋爱":
dbinfo.CanNtr = 1
case "牛头人":
dbinfo.CanMatch = 1
}
dbinfo.CDtime = 12
err = sql.db.Insert("updateinfo", &dbinfo)
return
}
err = sql.db.Insert("updateinfo", &dbinfo)
return
}
func (sql *婚姻登记) 清理花名册(gid string) error {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
@@ -88,19 +176,34 @@ func (sql *婚姻登记) 清理花名册(gid string) error {
return err
}
if gid != "0" {
grouplist = []string{gid}
grouplist = []string{"group" + gid}
}
for _, gid := range grouplist {
if gid == "favorability" {
continue
}
err = sql.db.Drop(gid)
if err != nil {
if err != nil || gid == "updateinfo" {
continue
}
gidint, _ := strconv.ParseInt(gid, 10, 64)
updateinfo := updateinfo{
upinfo := updateinfo{
GID: gidint,
Updatetime: time.Now().Format("2006/01/02"),
CanMatch: 1,
CanNtr: 1,
CDtime: 12,
}
err = sql.db.Insert("updateinfo", &updateinfo)
err = sql.db.Create("updateinfo", &updateinfo{})
if err != nil {
if err = sql.db.Drop("updateinfo"); err == nil {
err = sql.db.Create("updateinfo", &updateinfo{})
}
if err != nil {
return err
}
}
err = sql.db.Insert("updateinfo", &upinfo)
}
return err
}
@@ -108,7 +211,7 @@ func (sql *婚姻登记) 清理花名册(gid string) error {
func (sql *婚姻登记) 查户口(gid, uid int64) (info userinfo, status string, err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
gidstr := "group" + strconv.FormatInt(gid, 10)
uidstr := strconv.FormatInt(uid, 10)
status = "单"
err = sql.db.Create(gidstr, &userinfo{})
@@ -131,12 +234,12 @@ func (sql *婚姻登记) 查户口(gid, uid int64) (info userinfo, status string
func (sql *婚姻登记) 登记(gid, uid, target int64, username, targetname string) error {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
gidstr := "group" + strconv.FormatInt(gid, 10)
err := sql.db.Create(gidstr, &userinfo{})
if err != nil {
return err
}
updatetime := time.Now().Format("2006/01/02")
updatetime := time.Now().Format("15:04:05")
// 填写夫妻信息
uidinfo := userinfo{
User: uid,
@@ -153,7 +256,7 @@ func (sql *婚姻登记) 登记(gid, uid, target int64, username, targetname str
func (sql *婚姻登记) 离婚休妻(gid, wife int64) error {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
gidstr := "group" + strconv.FormatInt(gid, 10)
wifestr := strconv.FormatInt(wife, 10)
return sql.db.Del(gidstr, "where target = "+wifestr)
}
@@ -161,7 +264,7 @@ func (sql *婚姻登记) 离婚休妻(gid, wife int64) error {
func (sql *婚姻登记) 离婚休夫(gid, husband int64) error {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
gidstr := "group" + strconv.FormatInt(gid, 10)
husbandstr := strconv.FormatInt(husband, 10)
return sql.db.Del(gidstr, "where user = "+husbandstr)
}
@@ -169,7 +272,7 @@ func (sql *婚姻登记) 离婚休夫(gid, husband int64) error {
func (sql *婚姻登记) 花名册(gid int64) (list [][4]string, number int, err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
gidstr := strconv.FormatInt(gid, 10)
gidstr := "group" + strconv.FormatInt(gid, 10)
err = sql.db.Create(gidstr, &userinfo{})
if err != nil {
return
@@ -193,9 +296,7 @@ func (sql *婚姻登记) 花名册(gid int64) (list [][4]string, number int, err
list = append(list, dbinfo)
return nil
})
if len(list) == 0 {
number = 0
}
number = len(list)
return
}
@@ -219,28 +320,204 @@ func slicename(name string, canvas *gg.Context) (resultname string) {
return
}
// 以群号和昵称为限制
func cdcheck(ctx *zero.Ctx) *rate.Limiter {
limitID := strconv.FormatInt(ctx.Event.GroupID, 10) + strconv.FormatInt(ctx.Event.UserID, 10) + "1"
return skillCD.Load(limitID)
// 获取好感度
func (sql *婚姻登记) getFavorability(uid, target int64) (favor int, err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
err = sql.db.Create("favorability", &favorability{})
if err != nil {
return
}
info := favorability{}
uidstr := strconv.FormatInt(uid, 10)
targstr := strconv.FormatInt(target, 10)
err = sql.db.Find("favorability", &info, "where Userinfo glob '*"+uidstr+"+"+targstr+"*'")
if err != nil {
err = sql.db.Insert("favorability", &favorability{
Userinfo: uidstr + "+" + targstr + "+" + uidstr,
Favor: 0,
})
return
}
favor = info.Favor
return
}
func cdcheck2(ctx *zero.Ctx) *rate.Limiter {
limitID := strconv.FormatInt(ctx.Event.GroupID, 10) + strconv.FormatInt(ctx.Event.UserID, 10) + "2"
return skillCD.Load(limitID)
// 设置好感度 正增负减
func (sql *婚姻登记) setFavorability(uid, target int64, score int) (favor int, err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
err = sql.db.Create("favorability", &favorability{})
if err != nil {
return
}
info := favorability{}
uidstr := strconv.FormatInt(uid, 10)
targstr := strconv.FormatInt(target, 10)
err = sql.db.Find("favorability", &info, "where Userinfo glob '*"+uidstr+"+"+targstr+"*'")
if err != nil {
err = sql.db.Insert("favorability", &favorability{
Userinfo: uidstr + "+" + targstr + "+" + uidstr,
Favor: score,
})
return score, err
}
info.Favor += score
if info.Favor > 100 {
info.Favor = 100
} else if info.Favor < 0 {
info.Favor = 0
}
err = sql.db.Insert("favorability", &info)
return info.Favor, err
}
func cdcheck3(ctx *zero.Ctx) *rate.Limiter {
limitID := strconv.FormatInt(ctx.Event.GroupID, 10) + strconv.FormatInt(ctx.Event.UserID, 10) + "3"
return skillCD.Load(limitID)
// 获取技能时长
func (sql *婚姻登记) getCDtime(gid int64) (skillCD float64, err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
skillCD = 12
err = sql.db.Create("updateinfo", &updateinfo{})
if err != nil {
if err = sql.db.Drop("updateinfo"); err == nil {
err = sql.db.Create("updateinfo", &updateinfo{})
}
if err != nil {
return
}
}
gidstr := strconv.FormatInt(gid, 10)
dbinfo := updateinfo{}
err = sql.db.Find("updateinfo", &dbinfo, "where gid is "+gidstr)
if err != nil {
// 如果没有登记过就记录
err = sql.db.Insert("updateinfo", &updateinfo{
GID: gid,
CanMatch: 1,
CanNtr: 1,
CDtime: 12,
})
return
}
return dbinfo.CDtime, nil
}
func iscding(ctx *zero.Ctx) {
ctx.SendChain(message.Text("你的技能现在正在CD中"))
// 设置技能时长
func (sql *婚姻登记) setCDtime(gid int64, cdTime float64) (err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
err = sql.db.Create("updateinfo", &updateinfo{})
if err != nil {
if err = sql.db.Drop("updateinfo"); err == nil {
err = sql.db.Create("updateinfo", &updateinfo{})
}
if err != nil {
return
}
}
gidstr := strconv.FormatInt(gid, 10)
dbinfo := updateinfo{}
err = sql.db.Find("updateinfo", &dbinfo, "where gid is "+gidstr)
if err != nil {
// 如果没有登记过就记录
err = sql.db.Insert("updateinfo", &updateinfo{
GID: gid,
CanMatch: 1,
CanNtr: 1,
CDtime: cdTime,
})
return
}
dbinfo.CDtime = cdTime
err = sql.db.Insert("updateinfo", &dbinfo)
return
}
func iscding2(ctx *zero.Ctx) {
ctx.SendChain(message.Text("打灭,禁止离婚 (你的技能正在CD中)"))
// 记录CD
func (sql *婚姻登记) writeCDtime(gid, uid, mun int64) error {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
err := sql.db.Create("cdsheet", &cdsheet{})
if err != nil {
if err = sql.db.Drop("cdsheet"); err == nil {
err = sql.db.Create("cdsheet", &cdsheet{})
}
if err != nil {
return err
}
}
err = sql.db.Insert("cdsheet", &cdsheet{
Time: time.Now().Unix(),
GroupID: gid,
UserID: uid,
ModeID: mun,
})
return err
}
// 判断CD是否过时
func (sql *婚姻登记) compareCDtime(gid, uid, mun int64, cdtime float64) (ok bool, err error) {
sql.dbmu.Lock()
defer sql.dbmu.Unlock()
ok = false
err = sql.db.Create("cdsheet", &cdsheet{})
if err != nil {
if err = sql.db.Drop("cdsheet"); err == nil {
err = sql.db.Create("cdsheet", &cdsheet{})
}
if err != nil {
return
}
}
limitID := "where GroupID is " + strconv.FormatInt(gid, 10) +
" and UserID is " + strconv.FormatInt(uid, 10) +
" and ModeID is " + strconv.FormatInt(mun, 10)
exist := sql.db.CanFind("cdsheet", limitID)
if !exist {
return true, nil
}
cdinfo := cdsheet{}
err = sql.db.Find("cdsheet", &cdinfo, limitID)
if err != nil {
return
}
getTime := time.Unix(cdinfo.Time, 0)
if time.Since(getTime).Hours() > cdtime {
// 如果CD已过就删除
err = sql.db.Del("cdsheet", limitID)
return true, err
}
return
}
// 注入判断 是否为单身
func checkdog(ctx *zero.Ctx) bool {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
// 获取CD
cdTime, err := 民政局.getCDtime(gid)
if err != nil {
ctx.SendChain(message.Text("[qqwife]获取该群技能CD错误(将以CD12H计算)\n", err))
}
ok, err := 民政局.compareCDtime(gid, uid, 1, cdTime)
if err != nil {
ctx.SendChain(message.Text("[qqwife]查询用户CD状态失败,请重试\n", err))
return false
}
if !ok {
ctx.SendChain(message.Text("你的技能还在CD中..."))
return false
}
// 判断是否符合条件
stauts, _, err := 民政局.营业模式(gid)
if err != nil {
ctx.SendChain(message.Text("[qqwife]", err))
return false
}
if stauts == 0 {
ctx.SendChain(message.Text("你群包分配,别在娶妻上面下功夫,好好水群"))
return false
}
// 得先判断用户是否存在才行在,再重置
fiancee, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
if err != nil {
@@ -248,21 +525,19 @@ func checkdog(ctx *zero.Ctx) bool {
return false
}
// 判断是否需要重置
gid := ctx.Event.GroupID
ok, err := 民政局.开门时间(gid)
ok, err = 民政局.开门时间(gid)
if err != nil {
ctx.SendChain(message.Text("群状态查询失败\n[error]", err))
ctx.SendChain(message.Text("[qqwife]群状态查询失败\n", err))
return false
}
if ok {
return true // 重置后也全是单身
}
// 获取用户信息
uid := ctx.Event.UserID
uidtarget, uidstatus, err := 民政局.查户口(gid, uid)
switch {
case uidstatus == "错":
ctx.SendChain(message.Text("用户状态查询失败\n[error]", err))
ctx.SendChain(message.Text("[qqwife]用户状态查询失败\n", err))
return false
case uidstatus != "单" && (uidtarget.Target == 0 || uidtarget.User == 0): // 如果是单身贵族
ctx.SendChain(message.Text("今天的你是单身贵族噢"))
@@ -281,7 +556,7 @@ func checkdog(ctx *zero.Ctx) bool {
fianceeinfo, fianceestatus, err := 民政局.查户口(gid, fiancee)
switch {
case fianceestatus == "错":
ctx.SendChain(message.Text("对象状态查询失败\n[error]", err))
ctx.SendChain(message.Text("[qqwife]对象状态查询失败\n", err))
case fianceestatus == "单": // 如果为单身狗
return true
case fianceestatus != "单" && (fianceeinfo.Target == 0 || fianceeinfo.User == 0): // 如果是单身贵族
@@ -296,6 +571,32 @@ func checkdog(ctx *zero.Ctx) bool {
// 注入判断 是否满足小三要求
func checkcp(ctx *zero.Ctx) bool {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
// 获取CD
cdTime, err := 民政局.getCDtime(gid)
if err != nil {
ctx.SendChain(message.Text("[qqwife]获取该群技能CD错误(将以CD12H计算)\n", err))
}
ok, err := 民政局.compareCDtime(gid, uid, 2, cdTime)
if err != nil {
ctx.SendChain(message.Text("[qqwife]查询用户CD状态失败,请重试\n", err))
return false
}
if !ok {
ctx.SendChain(message.Text("你的技能还在CD中..."))
return false
}
// 判断是否符合条件
_, stauts, err := 民政局.营业模式(gid)
if err != nil {
ctx.SendChain(message.Text("[qqwife]", err))
return false
}
if stauts == 0 {
ctx.SendChain(message.Text("你群发布了牛头人禁止令,放弃吧"))
return false
}
// 得先判断用户是否存在才行在,再重置
fiancee, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
if err != nil {
@@ -303,21 +604,19 @@ func checkcp(ctx *zero.Ctx) bool {
return false
}
// 判断是否需要重置
gid := ctx.Event.GroupID
ok, err := 民政局.开门时间(gid)
ok, err = 民政局.开门时间(gid)
if err != nil {
ctx.SendChain(message.Text("群状态查询失败\n[error]", err))
ctx.SendChain(message.Text("[qqwife]群状态查询失败\n", err))
return false
}
if ok {
ctx.SendChain(message.Text("ta现在还是单身哦快向ta表白吧"))
return false // 重置后也全是单身
}
uid := ctx.Event.UserID
fianceeinfo, fianceestatus, err := 民政局.查户口(gid, fiancee)
switch {
case fianceestatus == "错":
ctx.SendChain(message.Text("对象状态查询失败\n[error]", err))
ctx.SendChain(message.Text("[qqwife]对象状态查询失败\n", err))
return false
case fianceestatus == "单": // 如果为单身狗
if fiancee == uid {
@@ -337,7 +636,7 @@ func checkcp(ctx *zero.Ctx) bool {
uidtarget, uidstatus, err := 民政局.查户口(gid, uid)
switch {
case uidstatus == "错":
ctx.SendChain(message.Text("用户状态查询失败\n[error]", err))
ctx.SendChain(message.Text("[qqwife]用户状态查询失败\n", err))
case uidstatus == "单": // 如果为单身狗
return true
case uidstatus != "单" && (uidtarget.Target == 0 || uidtarget.User == 0): // 如果是单身贵族
@@ -349,3 +648,111 @@ func checkcp(ctx *zero.Ctx) bool {
}
return false
}
// 注入判断 是否满足离婚要求
func checkdivorce(ctx *zero.Ctx) bool {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
// 获取CD
cdTime, err := 民政局.getCDtime(gid)
if err != nil {
ctx.SendChain(message.Text("[qqwife]获取该群技能CD错误(将以CD12H计算)\n", err))
}
ok, err := 民政局.compareCDtime(gid, uid, 4, cdTime)
if err != nil {
ctx.SendChain(message.Text("[qqwife]查询用户CD状态失败,请重试\n", err))
return false
}
if !ok {
ctx.SendChain(message.Text("你的技能还在CD中..."))
return false
}
// 判断是否符合条件
_, uidstatus, err := 民政局.查户口(gid, uid)
switch uidstatus {
case "错":
ctx.SendChain(message.Text("[qqwife]数据库发生问题力\n", err))
return false
case "单":
ctx.SendChain(message.Text("今天你还没结婚哦"))
return false
}
return true
}
// 注入判断 是否满足做媒要求
func checkCondition(ctx *zero.Ctx) bool {
gid := ctx.Event.GroupID
uid := ctx.Event.UserID
// 获取CD
cdTime, err := 民政局.getCDtime(gid)
if err != nil {
ctx.SendChain(message.Text("[qqwife]获取该群技能CD错误(将以CD12H计算)\n", err))
}
ok, err := 民政局.compareCDtime(gid, uid, 3, cdTime)
if err != nil {
ctx.SendChain(message.Text("[qqwife]查询用户CD状态失败,请重试\n", err))
return false
}
if !ok {
ctx.SendChain(message.Text("你的技能还在CD中..."))
return false
}
// 得先判断用户是否存在才行在,再重置
gayOne, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
if err != nil {
ctx.SendChain(message.Text("额,攻方好像不存在?"))
return false
}
gayZero, err := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
if err != nil {
ctx.SendChain(message.Text("额,受方好像不存在?"))
return false
}
if gayOne == uid || gayZero == uid {
ctx.SendChain(message.Text("禁止自己给自己做媒!"))
return false
}
if gayOne == gayZero {
ctx.SendChain(message.Text("你这个媒人XP很怪咧不能这样噢"))
return false
}
// 判断是否需要重置
ok, err = 民政局.开门时间(gid)
if err != nil {
ctx.SendChain(message.Text("[qqwife]群状态查询失败\n", err))
return false
}
if ok {
return true // 重置后也全是单身
}
fianceeinfo, fianceestatus, err := 民政局.查户口(gid, gayOne)
switch {
case fianceestatus == "错":
ctx.SendChain(message.Text("[qqwife]对象状态查询失败\n", err))
return false
case fianceestatus != "单" && (fianceeinfo.Target == 0 || fianceeinfo.User == 0): // 如果是单身贵族
ctx.SendChain(message.Text("今天的攻方是单身贵族噢"))
return false
case (fianceestatus == "攻" && fianceeinfo.Target == gayZero) ||
(fianceestatus == "受" && fianceeinfo.User == gayZero):
ctx.SendChain(message.Text("笨蛋ta们已经在一起了"))
return false
case fianceestatus != "单":
ctx.SendChain(message.Text("攻方不是单身,不允许给这种人做媒!"))
return false
}
// 获取用户信息
uidtarget, uidstatus, err := 民政局.查户口(gid, gayZero)
switch {
case uidstatus == "错":
ctx.SendChain(message.Text("[qqwife]用户状态查询失败\n", err))
case uidstatus == "单": // 如果为单身狗
return true
case uidstatus != "单" && (uidtarget.Target == 0 || uidtarget.User == 0): // 如果是单身贵族
ctx.SendChain(message.Text("今天的你是单身贵族噢"))
case uidstatus != "单":
ctx.SendChain(message.Text("受方不是单身,不允许给这种人做媒!"))
}
return false
}

View File

@@ -2,94 +2,17 @@
package runcode
import (
"errors"
"io"
"net/http"
"net/url"
"strings"
"time"
"github.com/FloatTech/AnimeAPI/runoob"
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"
"github.com/tidwall/gjson"
)
var (
templates = map[string]string{
"py2": "print 'Hello World!'",
"ruby": "puts \"Hello World!\";",
"rb": "puts \"Hello World!\";",
"php": "<?php\n\techo 'Hello World!';\n?>",
"javascript": "console.log(\"Hello World!\");",
"js": "console.log(\"Hello World!\");",
"node.js": "console.log(\"Hello World!\");",
"scala": "object Main {\n def main(args:Array[String])\n {\n println(\"Hello World!\")\n }\n\t\t\n}",
"go": "package main\n\nimport \"fmt\"\n\nfunc main() {\n fmt.Println(\"Hello, World!\")\n}",
"c": "#include <stdio.h>\n\nint main()\n{\n printf(\"Hello, World! \n\");\n return 0;\n}",
"c++": "#include <iostream>\nusing namespace std;\n\nint main()\n{\n cout << \"Hello World\";\n return 0;\n}",
"cpp": "#include <iostream>\nusing namespace std;\n\nint main()\n{\n cout << \"Hello World\";\n return 0;\n}",
"java": "public class HelloWorld {\n public static void main(String []args) {\n System.out.println(\"Hello World!\");\n }\n}",
"rust": "fn main() {\n println!(\"Hello World!\");\n}",
"rs": "fn main() {\n println!(\"Hello World!\");\n}",
"c#": "using System;\nnamespace HelloWorldApplication\n{\n class HelloWorld\n {\n static void Main(string[] args)\n {\n Console.WriteLine(\"Hello World!\");\n }\n }\n}",
"cs": "using System;\nnamespace HelloWorldApplication\n{\n class HelloWorld\n {\n static void Main(string[] args)\n {\n Console.WriteLine(\"Hello World!\");\n }\n }\n}",
"csharp": "using System;\nnamespace HelloWorldApplication\n{\n class HelloWorld\n {\n static void Main(string[] args)\n {\n Console.WriteLine(\"Hello World!\");\n }\n }\n}",
"shell": "echo 'Hello World!'",
"bash": "echo 'Hello World!'",
"erlang": "% escript will ignore the first line\n\nmain(_) ->\n io:format(\"Hello World!~n\").",
"perl": "print \"Hello, World!\n\";",
"python": "print(\"Hello, World!\")",
"py": "print(\"Hello, World!\")",
"swift": "var myString = \"Hello, World!\"\nprint(myString)",
"lua": "var myString = \"Hello, World!\"\nprint(myString)",
"pascal": "runcode Hello;\nbegin\n writeln ('Hello, world!')\nend.",
"kotlin": "fun main(args : Array<String>){\n println(\"Hello World!\")\n}",
"kt": "fun main(args : Array<String>){\n println(\"Hello World!\")\n}",
"r": "myString <- \"Hello, World!\"\nprint ( myString)",
"vb": "Module Module1\n\n Sub Main()\n Console.WriteLine(\"Hello World!\")\n End Sub\n\nEnd Module",
"typescript": "const hello : string = \"Hello World!\"\nconsole.log(hello)",
"ts": "const hello : string = \"Hello World!\"\nconsole.log(hello)",
}
table = map[string][2]string{
"py2": {"0", "py"},
"ruby": {"1", "rb"},
"rb": {"1", "rb"},
"php": {"3", "php"},
"javascript": {"4", "js"},
"js": {"4", "js"},
"node.js": {"4", "js"},
"scala": {"5", "scala"},
"go": {"6", "go"},
"c": {"7", "c"},
"c++": {"7", "cpp"},
"cpp": {"7", "cpp"},
"java": {"8", "java"},
"rust": {"9", "rs"},
"rs": {"9", "rs"},
"c#": {"10", "cs"},
"cs": {"10", "cs"},
"csharp": {"10", "cs"},
"shell": {"10", "sh"},
"bash": {"10", "sh"},
"erlang": {"12", "erl"},
"perl": {"14", "pl"},
"python": {"15", "py3"},
"py": {"15", "py3"},
"swift": {"16", "swift"},
"lua": {"17", "lua"},
"pascal": {"18", "pas"},
"kotlin": {"19", "kt"},
"kt": {"19", "kt"},
"r": {"80", "r"},
"vb": {"84", "vb"},
"typescript": {"1010", "ts"},
"ts": {"1010", "ts"},
}
)
var ro = runoob.NewRunOOB("b6365362a90ac2ac7098ba52c13e352b")
func init() {
control.Register("runcode", &ctrl.Options[*zero.Ctx]{
@@ -108,7 +31,7 @@ func init() {
israw := ctx.State["regex_matched"].([]string)[1] != ""
language := ctx.State["regex_matched"].([]string)[2]
language = strings.ToLower(language)
if runType, exist := table[language]; !exist {
if _, exist := runoob.LangTable[language]; !exist {
// 不支持语言
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
@@ -123,11 +46,11 @@ func init() {
message.Text("> ", ctx.Event.Sender.NickName, " ", language, "-template:\n"),
message.Text(
">runcode ", language, "\n",
templates[language],
runoob.Templates[language],
),
)
default:
if output, err := runCode(block, runType); err != nil {
if output, err := ro.Run(block, language, ""); err != nil {
// 运行失败
ctx.SendChain(
message.Text("> ", ctx.Event.Sender.NickName, "\n"),
@@ -135,6 +58,7 @@ func init() {
)
} else {
// 运行成功
output = cutTooLong(strings.Trim(output, "\n"))
if israw {
ctx.SendChain(message.Text(output))
} else {
@@ -149,59 +73,6 @@ func init() {
})
}
func runCode(code string, runType [2]string) (string, error) {
// 对菜鸟api发送数据并返回结果
api := "https://tool.runoob.com/compile2.php"
header := http.Header{
"Content-Type": []string{"application/x-www-form-urlencoded; charset=UTF-8"},
"Referer": []string{"https://c.runoob.com/"},
"User-Agent": []string{"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0"},
}
val := url.Values{
"code": []string{code},
"token": []string{"4381fe197827ec87cbac9552f14ec62a"},
"stdin": []string{""},
"language": []string{runType[0]},
"fileext": []string{runType[1]},
}
// 发送请求
client := &http.Client{
Timeout: 15 * time.Second,
}
request, _ := http.NewRequest("POST", api, strings.NewReader(val.Encode()))
request.Header = header
body, err := client.Do(request)
if err != nil {
return "", err
}
defer body.Body.Close()
if body.StatusCode != http.StatusOK {
return "", errors.New("code not 200")
}
res, err := io.ReadAll(body.Body)
if err != nil {
return "", err
}
// 结果处理
content := gjson.ParseBytes(res)
if e := content.Get("errors").Str; e != "\n\n" {
return "", errors.New(cutTooLong(clearNewLineSuffix(e)))
}
output := content.Get("output").Str
return cutTooLong(clearNewLineSuffix(output)), nil
}
// 清除末尾多余的换行符
func clearNewLineSuffix(text string) string {
for strings.HasSuffix(text, "\n") {
text = text[:len(text)-1]
}
return text
}
// 截断过长文本
func cutTooLong(text string) string {
temp := []rune(text)

View File

@@ -95,15 +95,8 @@ func init() { // 插件主体
"直链: ", "https://pixivel.moe/detail?id=", illust.Pid,
)
if imgs != nil {
if zero.OnlyGroup(ctx) {
ctx.SendGroupForwardMessage(ctx.Event.GroupID, message.Message{
ctxext.FakeSenderForwardNode(ctx, txt),
ctxext.FakeSenderForwardNode(ctx, imgs...),
})
} else {
// 发送搜索结果
ctx.Send(append(imgs, message.Text("\n"), txt))
}
ctx.Send(message.Message{ctxext.FakeSenderForwardNode(ctx, txt),
ctxext.FakeSenderForwardNode(ctx, imgs...)})
} else {
// 图片下载失败,仅发送文字结果
ctx.SendChain(txt)
@@ -113,7 +106,7 @@ func init() { // 插件主体
}
})
// 以图搜图
engine.OnKeywordGroup([]string{"以图搜图", "搜索图片", "以图识图"}, zero.OnlyGroup, zero.MustProvidePicture).SetBlock(true).
engine.OnKeywordGroup([]string{"以图搜图", "搜索图片", "以图识图"}, zero.MustProvidePicture).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 开始搜索图片
ctx.SendChain(message.Text("少女祈祷中..."))
@@ -154,14 +147,14 @@ func init() { // 插件主体
msg = append(msg, message.Image(pic))
}
msg = append(msg, message.Text("\n图源: ", result.Header.IndexName, binary.BytesToString(b)))
ctx.Send(msg)
ctx.Send(ctxext.FakeSenderForwardNode(ctx, msg...))
if s > 80.0 {
continue
}
}
}
} else {
ctx.SendChain(message.Text("请私聊发送 设置 saucenao api key [apikey] 以启用 saucenao 搜图, key 请前往 https://saucenao.com/user.php?page=search-api 获取"))
ctx.SendChain(message.Text("请私聊发送 设置 saucenao api key [apikey] 以启用 saucenao 搜图 (方括号不需要输入), key 请前往 https://saucenao.com/user.php?page=search-api 获取"))
}
// ascii2d 搜索
if result, err := ascii2d.Ascii2d(pic); err != nil {
@@ -182,10 +175,7 @@ func init() { // 插件主体
))),
)
}
if id := ctx.SendGroupForwardMessage(
ctx.Event.GroupID,
msg,
).Get("message_id").Int(); id == 0 {
if id := ctx.Send(msg).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
}

View File

@@ -83,7 +83,7 @@ func (sdb *scoredb) InsertOrUpdateScoreByUID(uid int64, score int) (err error) {
}
} else {
err = db.Model(&scoretable{}).Where("uid = ? ", uid).Update(
map[string]interface{}{
map[string]any{
"score": score,
}).Error
}
@@ -111,7 +111,7 @@ func (sdb *scoredb) InsertOrUpdateSignInCountByUID(uid int64, count int) (err er
}
} else {
err = db.Model(&signintable{}).Where("uid = ? ", uid).Update(
map[string]interface{}{
map[string]any{
"count": count,
}).Error
}

View File

@@ -10,15 +10,12 @@ import (
"github.com/Coloured-glaze/gg"
"github.com/golang/freetype"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
"github.com/wcharczuk/go-chart/v2"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -27,22 +24,22 @@ import (
)
const (
backgroundURL = "https://mirlkoi.ifast3.vipnps.vip/api.php?sort=pc&type=json"
referer = "https://iw233.cn/main.html"
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
backgroundURL = "https://img.moehu.org/pic.php?id=pc"
signinMax = 1
// SCOREMAX 分数上限定为120
SCOREMAX = 120
)
var levelArray = [...]int{0, 1, 2, 5, 10, 20, 35, 55, 75, 100, 120}
func init() {
engine := control.Register("score", &ctrl.Options[*zero.Ctx]{
var (
levelArray = [...]int{0, 1, 2, 5, 10, 20, 35, 55, 75, 100, 120}
engine = control.Register("score", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "签到得分\n- 签到\n- 获得签到背景[@xxx] | 获得签到背景\n- 查看分数排名",
PrivateDataFolder: "score",
})
)
func init() {
cachePath := engine.DataFolder() + "cache/"
go func() {
_ = os.RemoveAll(cachePath)
@@ -52,7 +49,7 @@ func init() {
}
sdb = initialize(engine.DataFolder() + "score.db")
}()
engine.OnFullMatch("签到", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).
engine.OnFullMatch("签到").Limit(ctxext.LimitByUser).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID
now := time.Now()
@@ -274,14 +271,5 @@ func initPic(picFile string) error {
if file.IsExist(picFile) {
return nil
}
data, err := web.RequestDataWith(web.NewDefaultClient(), backgroundURL, "GET", referer, ua)
if err != nil {
return err
}
picURL := gjson.Get(binary.BytesToString(data), "pic.0").Str
data, err = web.RequestDataWith(web.NewDefaultClient(), picURL, "GET", "", ua)
if err != nil {
return err
}
return os.WriteFile(picFile, data, 0644)
return file.DownloadTo(backgroundURL, picFile, true)
}

View File

@@ -94,7 +94,8 @@ func init() { // 插件主体
}
}
// 从缓冲池里抽一张
if id := ctx.SendChain(*pool.pop(imgtype)); id.ID() == 0 {
m := message.Message{ctxext.FakeSenderForwardNode(ctx, *pool.pop(imgtype))}
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
})

View File

@@ -77,7 +77,7 @@ func (sdb *sleepdb) sleep(gid, uid int64) (position int, awakeTime time.Duration
log.Debugln("sleeptime为", st)
awakeTime = now.Sub(st.SleepTime)
db.Model(&SleepManage{}).Where("group_id = ? and user_id = ?", gid, uid).Update(
map[string]interface{}{
map[string]any{
"sleep_time": now,
})
}
@@ -104,7 +104,7 @@ func (sdb *sleepdb) getUp(gid, uid int64) (position int, sleepTime time.Duration
log.Debugln("sleeptime为", st)
sleepTime = now.Sub(st.SleepTime)
db.Model(&SleepManage{}).Where("group_id = ? and user_id = ?", gid, uid).Update(
map[string]interface{}{
map[string]any{
"sleep_time": now,
})
}

View File

@@ -139,7 +139,7 @@ func init() {
}
return
}
msg := make([]message.MessageSegment, n)
msg := make(message.Message, n)
randomIntMap := make(map[int]int, 30)
for i := range msg {
j := rand.Intn(length)
@@ -156,13 +156,13 @@ func init() {
if p == 1 {
description = card.ReverseDescription
}
tarotMsg := []message.MessageSegment{
tarotMsg := message.Message{
message.Text(position[p], "的『", name, "』\n"),
message.Image(bed + reverse[p] + card.ImgURL),
message.Text("\n其释义为: ", description)}
msg[i] = ctxext.FakeSenderForwardNode(ctx, tarotMsg...)
}
ctx.SendGroupForwardMessage(ctx.Event.GroupID, msg)
ctx.Send(msg)
})
engine.OnRegex(`^解塔罗牌\s?(.*)`, getTarot).SetBlock(true).Limit(ctxext.LimitByGroup).Handle(func(ctx *zero.Ctx) {
@@ -213,7 +213,7 @@ func init() {
build.WriteString("---")
build.WriteString(match)
build.WriteString("\n")
msg := make([]message.MessageSegment, info.CardsNum+1)
msg := make(message.Message, info.CardsNum+1)
randomIntMap := make(map[int]int, 30)
for i := 0; i < info.CardsNum; i++ {
j := rand.Intn(length)
@@ -230,7 +230,7 @@ func init() {
if p == 1 {
description = card.ReverseDescription
}
tarotMsg := []message.MessageSegment{message.Image(bed + reverse[p] + card.ImgURL)}
tarotMsg := message.Message{message.Image(bed + reverse[p] + card.ImgURL)}
build.WriteString(info.Represent[0][i])
build.WriteString(":")
build.WriteString(position[p])
@@ -247,8 +247,8 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
msg[info.CardsNum] = ctxext.FakeSenderForwardNode(ctx, []message.MessageSegment{message.Image("base64://" + binary.BytesToString(formation))}...)
ctx.SendGroupForwardMessage(ctx.Event.GroupID, msg)
msg[info.CardsNum] = ctxext.FakeSenderForwardNode(ctx, message.Message{message.Image("base64://" + binary.BytesToString(formation))}...)
ctx.Send(msg)
} else {
ctx.SendChain(message.Text("没有找到", match, "噢~\n现有牌阵列表: \n", strings.Join(formationName, "\n")))
}

View File

@@ -223,7 +223,7 @@ func (vdb *VtbDB) GetVtbList() (uidList []string, err error) {
}
} else {
db.Model(&FirstCategory{}).Where("first_category_uid = ?", fc.FirstCategoryUID).Update(
map[string]interface{}{
map[string]any{
"first_category_index": i,
"first_category_name": item.Get("name").String(),
"first_category_description": item.Get("description").String(),
@@ -283,7 +283,7 @@ func (vdb *VtbDB) StoreVtb(uid string) (err error) {
}
} else {
db.Model(&SecondCategory{}).Where("first_category_uid = ? and second_category_index = ?", uid, secondIndex).Update(
map[string]interface{}{
map[string]any{
"second_category_name": secondItem.Get("categoryName").String(),
"second_category_author": secondItem.Get("author").String(),
"second_category_description": secondItem.Get("categoryDescription.zh-CN").String(),
@@ -313,7 +313,7 @@ func (vdb *VtbDB) StoreVtb(uid string) (err error) {
} else {
db.Model(&ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ? and third_category_index = ?",
uid, secondIndex, thirdIndex).Update(
map[string]interface{}{
map[string]any{
"third_category_name": thirdItem.Get("name").String(),
"third_category_description": thirdItem.Get("description.zh-CN").String(),
"third_category_path": thirdItem.Get("path").String(),

View File

@@ -0,0 +1,397 @@
// Package ernie AI画图
package ernie
import (
"errors"
"strconv"
"strings"
"sync"
"time"
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/process"
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"
// 数据库
sql "github.com/FloatTech/sqlite"
// 百度文心AI画图API
wenxin "github.com/FloatTech/AnimeAPI/wenxinAI/ernievilg"
)
const (
serviceName = "AIdraw"
serviceErr = "[" + serviceName + "]ERROR:\n"
)
type keydb struct {
db *sql.Sqlite
sync.RWMutex
}
// db内容
type apikey struct {
ID int64 // 群号
APIKey string // API Key
SecretKey string // Secret Key
Token string // AccessToken
Updatetime int64 // token的有效时间
MaxLimit int // 总使用次数
DayLimit int // 当天的使用次数
Lasttime string // 记录使用的时间,用于刷新使用次数
}
var (
groupinfo = &keydb{
db: &sql.Sqlite{},
}
limit = 50
dtype = [...]string{
"古风", "油画", "水彩画", "卡通画", "二次元", "浮世绘", "蒸汽波艺术", "low poly", "像素风格", "概念艺术", "未来主义", "赛博朋克", "写实风格", "洛丽塔风格", "巴洛克风格", "超现实主义",
}
)
func init() { // 插件主体
engine := control.Register(serviceName, &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "AI画图\n" +
"基于百度文心的免费AI画图插件,\n因为是免费的,图片质量你懂的。\n" +
"key申请链接https://wenxin.baidu.com/moduleApi/key\n" +
"注意每个apikey每日上限50次,总上限500次请求。次数超过了请自行更新apikey\n" +
"- 为[自己/本群/QQ号/群+群号]设置AI画图key [API Key] [Secret Key]\n" +
"例:\n[为10086设置AI画图key 123 456]\n[为群10010设置AI画图key 789 101]\n" +
"- [bot名称]画几张[图片描述]的[图片类型][图片尺寸]\n" +
"————————————————————\n" +
"图片描述指南:\n图片主体细节词(请用逗号连接)\n官方prompt指南:https://wenxin.baidu.com/wenxin/docs#Ol7ece95m\n" +
"————————————————————\n" +
"图片类型当前支持:" + strings.Join(dtype[:], "、") +
"\n————————————————————\n" +
"图片尺寸当前只支持:方图/长图/横图\n" +
"————————————————————\n" +
"指令示例:\n" +
"椛椛帮我画几张金凤凰背景绚烂高饱和古风仙境高清4K古风的油画方图",
PrivateDataFolder: "ernievilg",
}).ApplySingle(single.New(
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
single.WithPostFn[int64](func(ctx *zero.Ctx) {
ctx.Break()
ctx.Send(
message.ReplyWithMessage(ctx.Event.MessageID,
message.Text(zero.BotConfig.NickName[0], "正在给别人画图,请不要打扰哦"),
),
)
}),
))
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
groupinfo.db.DBPath = engine.DataFolder() + "keydb.db"
err := groupinfo.db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return false
}
return true
})
// 画图
engine.OnRegex(`画几张(.*[^的$])的(.*[^\s$])(方图|长图|横图)$`, zero.OnlyToMe, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
uid := -ctx.Event.UserID
gid := ctx.Event.GroupID
// 获取个人和群的key
userinfo, err1 := groupinfo.checkGroup(uid)
info, err2 := groupinfo.checkGroup(gid)
switch {
// 如果是个人请求且报错
case gid == 0 && err1 != nil:
ctx.SendChain(message.Text(serviceErr, err1))
return
// 如果群报错而个人没有,就切换成个人的
case err2 != nil && err1 == nil:
gid = uid
info = userinfo
// 如果都报错就以群为优先级
case err1 != nil && err2 != nil:
ctx.SendChain(message.Text(serviceErr, err2))
return
}
// 判断使用次数
check := false
switch {
// 群和个人都没有次数了
case info.DayLimit == 0 && userinfo.DayLimit == 0:
ctx.SendChain(message.Text("我已经画了", limit, "张了!我累了!不画不画,就不画!"))
return
// 个人还有次数的话
case info.DayLimit == 0 && userinfo.DayLimit != 0:
check = true
}
switch {
// 群和个人都没有总次数了
case info.MaxLimit == 0 && userinfo.MaxLimit == 0:
ctx.SendChain(message.Text("设置的key使用次数超过了限额请更换key。"))
return
// 个人还有总次数的话
case info.MaxLimit == 0 && userinfo.MaxLimit != 0:
check = true
}
if check { // 如果只有个人有次数就切换回个人key
gid = uid
info = userinfo
}
// 创建任务
keyword := ctx.State["regex_matched"].([]string)[1]
if len([]rune(keyword)) >= 64 { // 描述不能超过64个字
ctx.SendChain(message.Text("要求太多了啦!减少点!"))
return
}
picType := ctx.State["regex_matched"].([]string)[2]
chooseSize := ctx.State["regex_matched"].([]string)[3]
wtime := 3
picSize := "1024*1024"
switch chooseSize {
case "长图":
wtime = 5
picSize = "1024*1536"
case "横图":
wtime = 5
picSize = "1536*1024"
}
taskID, err := wenxin.BuildWork(info.Token, keyword, picType, picSize)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return
}
if taskID < 1 {
ctx.SendChain(message.Text("要求太复杂力!想不出来..."))
return
}
// 开始画图
ctx.SendChain(message.Text(zero.BotConfig.NickName[0], "知道了,我可能需要", time.Duration(wtime*10)*time.Second, "左右才能画好哦,请等待..."))
i := 0
for range time.NewTicker(10 * time.Second).C {
// 等待 wtime * 10秒
i++
if i <= wtime {
continue
}
/*
if i > 60{// 十分钟还不出图就放弃
ctx.SendChain(message.Text("呜呜呜,要求太复杂力!画不出来..."))
return
}
// 获取结果*/
picURL, status, err := wenxin.GetPic(info.Token, taskID)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return
}
if status == "0" {
msg := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text("我画好了!"))}
for _, imginfo := range picURL {
msg = append(msg,
ctxext.FakeSenderForwardNode(ctx,
message.Image(imginfo.Image)))
}
if id := ctx.Send(msg).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
break
}
}
err = groupinfo.update(gid)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
}
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("累死了,今天我最多只能画", info.DayLimit-1, "张图哦"))
})
engine.OnRegex(`^为(群)?(自己|本群|\d+)设置AI画图key\s(.*[^\s$])\s(.+)$`, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
mode := ctx.State["regex_matched"].([]string)[1]
user := ctx.State["regex_matched"].([]string)[2]
aKey := ctx.State["regex_matched"].([]string)[3]
sKey := ctx.State["regex_matched"].([]string)[4]
dbID := -ctx.Event.UserID // 默认给自己
switch {
case mode != "": // 指定群的话
gid, err := strconv.ParseInt(user, 10, 64)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return
}
dbID = gid
case user == "本群": // 用于本群
gid := ctx.Event.GroupID
if gid == 0 {
ctx.SendChain(message.Text(serviceErr, "请指定群聊,或者使用指令;\n为群xxx设置AI画图key xxx xxx"))
return
}
dbID = gid
case user != "自己": // 给别人开key
uid, err := strconv.ParseInt(user, 10, 64)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return
}
dbID = -uid
}
err := groupinfo.insert(dbID, aKey, sKey)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return
}
ctx.SendChain(message.Text("成功!"))
})
}
// 登记group的key
func (sql *keydb) insert(gid int64, akey, skey string) error {
sql.Lock()
defer sql.Unlock()
// 给db文件创建表格(没有才创建)表格名称groupinfo表格结构apikey
err := sql.db.Create("groupinfo", &apikey{})
if err != nil {
return err
}
// 获取group信息
groupinfo := apikey{} // 用于暂存数据
err = sql.db.Find("groupinfo", &groupinfo, "where ID is "+strconv.FormatInt(gid, 10))
if err != nil {
// 如果该group没有注册过
err = sql.db.Find("groupinfo", &groupinfo, "where APIKey is '"+akey+"' and SecretKey is '"+skey+"'")
if err == nil {
// 如果key存在过将当前的数据迁移过去
groupinfo.ID = gid
} else {
groupinfo = apikey{
ID: gid,
APIKey: akey,
SecretKey: skey,
MaxLimit: 500,
}
}
return sql.db.Insert("groupinfo", &groupinfo)
}
// 进行更新
groupinfo.APIKey = akey
groupinfo.SecretKey = skey
groupinfo.MaxLimit = 500
return sql.db.Insert("groupinfo", &groupinfo)
}
// 获取group信息
func (sql *keydb) checkGroup(gid int64) (groupinfo apikey, err error) {
sql.Lock()
defer sql.Unlock()
// 给db文件创建表格(没有才创建)表格名称groupinfo表格结构apikey
err = sql.db.Create("groupinfo", &apikey{})
if err != nil {
return
}
// 先判断该群是否已经设置过key了
if ok := sql.db.CanFind("groupinfo", "where ID is "+strconv.FormatInt(gid, 10)); !ok {
if gid > 0 {
err = errors.New("该群没有设置过apikey请前往https://wenxin.baidu.com/moduleApi/key获取key值后发送指令:\n为本群设置AI画图key [API Key] [Secret Key]")
} else {
err = errors.New("你没有设置过apikey请前往https://wenxin.baidu.com/moduleApi/key获取key值后发送指令:\n为自己设置AI画图key [API Key] [Secret Key]")
}
return
}
// 获取group信息
err = sql.db.Find("groupinfo", &groupinfo, "where ID is "+strconv.FormatInt(gid, 10))
if err != nil {
return
}
// 如果隔天使用刷新次数
if time.Now().Format("2006/01/02") != groupinfo.Lasttime {
groupinfo.DayLimit = limit
groupinfo.Lasttime = time.Now().Format("2006/01/02")
}
if err = sql.db.Insert("groupinfo", &groupinfo); err != nil {
return
}
// 如果token有效期过期
if time.Since(time.Unix(groupinfo.Updatetime, 0)).Hours() > 24 {
token, err1 := wenxin.GetToken(groupinfo.APIKey, groupinfo.SecretKey)
if err1 != nil {
err = err1
return
}
groupinfo.Token = token
groupinfo.Updatetime = time.Now().Unix()
err = sql.db.Insert("groupinfo", &groupinfo)
if err == nil {
// 更新相同key的他人次数
condition := "where not ID is " + strconv.FormatInt(gid, 10) +
" and APIKey = '" + groupinfo.APIKey +
"' and SecretKey = '" + groupinfo.SecretKey + "'"
otherinfo := apikey{}
var groups []int64 // 将相同的key的ID暂存
// 无视没有找到相同的key的err
_ = sql.db.FindFor("groupinfo", &otherinfo, condition, func() error {
groups = append(groups, otherinfo.ID)
return nil
})
if len(groups) != 0 { // 如果有相同的key就更新
for _, group := range groups {
err = sql.db.Find("groupinfo", &otherinfo, "where ID is "+strconv.FormatInt(group, 10))
if err == nil {
otherinfo.Token = groupinfo.Token
otherinfo.Updatetime = groupinfo.Updatetime
err = sql.db.Insert("groupinfo", &otherinfo)
}
}
}
}
}
return
}
// 记录次数(-1)
func (sql *keydb) update(gid int64) error {
sql.Lock()
defer sql.Unlock()
// 给db文件创建表格(没有才创建)表格名称groupinfo表格结构apikey
err := sql.db.Create("groupinfo", &apikey{})
if err != nil {
return err
}
groupinfo := apikey{} // 用于暂存数据
// 获取group信息
err = sql.db.Find("groupinfo", &groupinfo, "where ID is "+strconv.FormatInt(gid, 10))
if err != nil {
return err
}
groupinfo.MaxLimit--
groupinfo.DayLimit--
err = sql.db.Insert("groupinfo", &groupinfo)
if err != nil {
return err
}
// 更新相同key的他人次数
condition := "where not ID is " + strconv.FormatInt(gid, 10) +
" and APIKey = '" + groupinfo.APIKey +
"' and SecretKey = '" + groupinfo.SecretKey + "'"
otherinfo := apikey{}
var groups []int64 // 将相同的key的ID暂存
// 无视没有找到相同的key的err
_ = sql.db.FindFor("groupinfo", &otherinfo, condition, func() error {
groups = append(groups, otherinfo.ID)
return nil
})
if len(groups) != 0 { // 如果有相同的key就更新
for _, group := range groups {
err = sql.db.Find("groupinfo", &otherinfo, "where ID is "+strconv.FormatInt(group, 10))
if err == nil {
otherinfo.MaxLimit = groupinfo.MaxLimit
otherinfo.DayLimit = groupinfo.DayLimit
otherinfo.Lasttime = groupinfo.Lasttime
err = sql.db.Insert("groupinfo", &otherinfo)
}
}
}
return err
}

View File

@@ -69,7 +69,7 @@ func (gdb *ymgaldb) insertOrUpdateYmgalByID(id int64, title, pictureType, pictur
err = db.Model(&ymgal{}).Create(&y).Error // newUser not user
}
} else {
err = db.Model(&ymgal{}).Where("id = ? ", id).Update(map[string]interface{}{
err = db.Model(&ymgal{}).Where("id = ? ", id).Update(map[string]any{
"title": title,
"picture_type": pictureType,
"picture_description": pictureDescription,
@@ -108,7 +108,7 @@ func (gdb *ymgaldb) getYmgalByKey(pictureType, key string) (y ymgal) {
}
const (
webURL = "https://www.ymgal.com"
webURL = "https://www.ymgal.games"
cgType = "Gal CG"
emoticonType = "其他"
webPicURL = webURL + "/co/picset/"

View File

@@ -81,9 +81,7 @@ func sendYmgal(y ymgal, ctx *zero.Ctx) {
for _, v := range strings.Split(y.PictureList, ",") {
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Image(v)))
}
if id := ctx.SendGroupForwardMessage(
ctx.Event.GroupID,
m).Get("message_id").Int(); id == 0 {
if id := ctx.Send(m).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
}