Compare commits

..

27 Commits

Author SHA1 Message Date
源文雨
20821827b3 🔖 v1.6.2-beta2 2023-02-06 21:47:25 +08:00
源文雨
3dd10169e3 update deps 2023-02-06 21:40:41 +08:00
DreamZero
8cd60a84d5 复制黏贴被发现了( (#578) 2023-02-06 16:49:55 +08:00
DreamZero
03a2f4c331 给aifalse加一点细节 (#575) 2023-02-05 12:59:50 +08:00
icarus-ai
cfc9b55fce 更新quic-go版本,以支持使用Go 1.20编译 (#577)
* 支持 Go 1.20

* fix workflows (≖_≖ )

* 回滚 workflows

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

* 修正错别字

* 增加整理提示语

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

* 🎨 修改readme

* 🎨 修lint

* 🎨 修改包

* 🎨 使用新版http封装

* 🎨 new line
2023-01-30 17:40:57 +08:00
源文雨
f1a33a1845 🔖 v1.6.1-fix1 2023-01-16 11:36:31 +08:00
源文雨
0a72566378 fix #561: render text black & shindan 2023-01-16 11:35:11 +08:00
lianhong2758
a029add486 权重查询美化 (#560) 2023-01-16 11:25:39 +08:00
源文雨
778b8749ea 🐛 修复pixiv无法获取original url 2023-01-13 16:28:17 +08:00
31 changed files with 2192 additions and 192 deletions

View File

@@ -52,7 +52,7 @@ zerobot [-h] [-n nickname] [-t token] [-u url] [-p prefix] [-d|w] [-c|s config.j
- **-c config.json**: 从`config.json`加载`bot`配置
- **-s config.json**: 保存现在`bot`配置到`config.json`
- **-l latency**: 全局处理延时 (ms)
- **-r ringlen**: 接收消息环缓冲区大小
- **-r ringlen**: 接收消息环缓冲区大小`0`为不设缓冲,并发处理
- **-x max process time**: 最大处理时间 (min)
- **qqs**: superusers 的 qq 号
- **&**: 驻留在后台,必须放在最后,仅`Linux`下有效
@@ -104,6 +104,10 @@ zerobot [-h] [-n nickname] [-t token] [-u url] [-p prefix] [-d|w] [-c|s config.j
- [x] /禁用 xxx (在发送的群/用户禁用xxx)
- [x] /此处启用所有插件
- [x] /此处禁用所有插件
- [x] /全局启用 xxx
- [x] /全局禁用 xxx
@@ -1032,6 +1036,12 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 小说[xxx]
- 设置小说配置 zerobot 123456
- 下载小说30298
- 注: 建议去https://www.23qb.com/ 注册一个账号, 小说下载有积分限制
</details>
<details>
<summary>nsfw图片识别</summary>
@@ -1261,6 +1271,16 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 更新vtb
</details>
<details>
<summary>钱包</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wallet"`
- [x] 查看我的钱包
- [x] 查看钱包排名
</details>
<details>
<summary>网易云音乐热评</summary>
@@ -1269,6 +1289,23 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 来份网易云热评
</details>
<details>
<summary>星际战甲</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/warframeapi"`
- [x] wf时间同步
- [x] [金星|地球|火卫二]平原状态
- [x] .wm [物品名称]
- [x] 仲裁
- [x] 警报
- [x] 每日特惠
</details>
<details>
<summary>天气/拼音查询-名言</summary>

44
go.mod
View File

@@ -4,17 +4,20 @@ go 1.19
require (
github.com/Baidu-AIP/golang-sdk v1.1.1
github.com/Coloured-glaze/gg v1.3.4
github.com/FloatTech/AnimeAPI v1.6.1-0.20230111055153-4d8aebd3eab9
github.com/FloatTech/floatbox v0.0.0-20230111053652-a03d6334fadf
github.com/FloatTech/AnimeAPI v1.6.1-0.20230130095520-be357484e5a7
github.com/FloatTech/floatbox v0.0.0-20230205065512-4039f6dd0a68
github.com/FloatTech/gg v1.1.0
github.com/FloatTech/rendercard v0.0.9-0.20230206125820-929cee91387c
github.com/FloatTech/sqlite v1.5.7
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
github.com/FloatTech/zbpctrl v1.5.3-0.20230109124217-41203036b80a
github.com/FloatTech/zbputils v1.6.2-0.20230112162135-c326104c37e6
github.com/FloatTech/zbpctrl v1.5.3-0.20230130095145-714ad318cd52
github.com/FloatTech/zbputils v1.6.2-0.20230206130001-6b404926bf66
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5
github.com/antchfx/htmlquery v1.2.5
github.com/corona10/goimagehash v1.1.0
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3
github.com/disintegration/imaging v1.6.2
github.com/fumiama/ahsai v0.1.0
github.com/fumiama/cron v1.3.0
github.com/fumiama/go-base16384 v1.6.4
@@ -25,27 +28,28 @@ require (
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/jinzhu/gorm v1.9.16
github.com/jozsefsallai/gophersauce v1.0.1
github.com/lucas-clemente/quic-go v0.31.1
github.com/lithammer/fuzzysearch v1.1.5
github.com/mroth/weightedrand v1.0.0
github.com/pkg/errors v0.9.1
github.com/shirou/gopsutil/v3 v3.22.11
github.com/quic-go/quic-go v0.32.0
github.com/shirou/gopsutil/v3 v3.23.1
github.com/sirupsen/logrus v1.9.0
github.com/tidwall/gjson v1.14.4
github.com/wcharczuk/go-chart/v2 v2.1.0
github.com/wdvxdr1123/ZeroBot v1.6.7
github.com/wdvxdr1123/ZeroBot v1.6.8
gitlab.com/gomidi/midi/v2 v2.0.25
golang.org/x/image v0.3.0
golang.org/x/text v0.6.0
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/FloatTech/rendercard v0.0.8 // indirect
github.com/antchfx/xpath v1.2.1 // indirect
github.com/disintegration/imaging v1.6.2 // indirect
github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect
github.com/faiface/beep v1.1.0 // indirect
github.com/fumiama/go-simple-protobuf v0.1.0 // indirect
github.com/fumiama/gofastTEA v0.0.10 // indirect
github.com/fumiama/imgsz v0.0.2 // indirect
github.com/gabriel-vasile/mimetype v1.0.4 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
@@ -59,29 +63,29 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/marten-seemann/qpack v0.3.0 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
github.com/pkumza/numcn v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/crypto v0.4.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9 // indirect
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/text v0.6.0 // indirect
golang.org/x/tools v0.1.12 // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.4.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/tools v0.2.0 // indirect
modernc.org/libc v1.21.5 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.4.0 // indirect

76
go.sum
View File

@@ -1,23 +1,23 @@
github.com/Baidu-AIP/golang-sdk v1.1.1 h1:RQsAmgDSAkiq22I6n7XJ2t3afgzFeqjY46FGhvrx4cw=
github.com/Baidu-AIP/golang-sdk v1.1.1/go.mod h1:bXnGw7xPeKt8aF7UCELKrV6UZ/46spItONK1RQBQj1Y=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Coloured-glaze/gg v1.3.4 h1:l31zIF/HaVwkzjrj+A56RGQoSKyKuR1IWtIrqXGFStI=
github.com/Coloured-glaze/gg v1.3.4/go.mod h1:Ih5NLNNDHOy3RJbB0EPqGTreIzq/H02TGThIagh8HJg=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/FloatTech/AnimeAPI v1.6.1-0.20230111055153-4d8aebd3eab9 h1:TOd10BBqoHPwbOmULK4a6imdaljkOxKIZFyFKbQqTEA=
github.com/FloatTech/AnimeAPI v1.6.1-0.20230111055153-4d8aebd3eab9/go.mod h1:aOU5EVMvflX5Btv0jGLgB6gcSYeR/FNiR2cJG07vd4U=
github.com/FloatTech/floatbox v0.0.0-20230111053652-a03d6334fadf h1:aVmgzw9hJA39/2iR800qq1dU682LpW9/czIkoshDzKw=
github.com/FloatTech/floatbox v0.0.0-20230111053652-a03d6334fadf/go.mod h1:0+3iDgifrdiEoEsmYe+yiAlUQcmnudhTiiBdSkam2XY=
github.com/FloatTech/rendercard v0.0.8 h1:IOZ757RKJGj4EAQj7XoW8iSNl6yVS98z0DK9LDup+Yo=
github.com/FloatTech/rendercard v0.0.8/go.mod h1:hDqmlGgXBPI3QAvkE2kKjdPFAIB5cFQ55QnmXapAr3I=
github.com/FloatTech/AnimeAPI v1.6.1-0.20230130095520-be357484e5a7 h1:4FCjcjcsjUSJzmuUi8u570SUnmYasZ98ugSRg2SIl18=
github.com/FloatTech/AnimeAPI v1.6.1-0.20230130095520-be357484e5a7/go.mod h1:LmHu358Oovtxhc/7xz+IfffUAMCX2bijpEvWatacEYQ=
github.com/FloatTech/floatbox v0.0.0-20230205065512-4039f6dd0a68 h1:K03MRdjGBtoZ7QOnyeKf8dmxsRoNF7dN0udNrR5t138=
github.com/FloatTech/floatbox v0.0.0-20230205065512-4039f6dd0a68/go.mod h1:OoZE4Ra7olpFaJSrlD6mcyT4chPLg9QBRE1pzTC8R84=
github.com/FloatTech/gg v1.1.0 h1:4qmsleYqRZ/gv48izGgkyJgvP1RmybA5xJJnzkhK/OU=
github.com/FloatTech/gg v1.1.0/go.mod h1:uzPzAeT35egARdRuu+1oyjU3CmTwCceoq3Vvje7LpcI=
github.com/FloatTech/rendercard v0.0.9-0.20230206125820-929cee91387c h1:nE1X4Z3BAyYydlo0QKVU/nUtEyF5ek/cN6S5sZsyio4=
github.com/FloatTech/rendercard v0.0.9-0.20230206125820-929cee91387c/go.mod h1:0LVxMhsw6LayHM78pJ58/TCkx0/CIVuYc19fCHpM/5g=
github.com/FloatTech/sqlite v1.5.7 h1:Bvo4LSojcZ6dVtbHrkqvt6z4v8e+sj0G5PSUIvdawsk=
github.com/FloatTech/sqlite v1.5.7/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY=
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw=
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
github.com/FloatTech/zbpctrl v1.5.3-0.20230109124217-41203036b80a h1:O+GS8J1pEM4E8q05EcopHBK6kfIr0BJJ/cHuPa8yWLM=
github.com/FloatTech/zbpctrl v1.5.3-0.20230109124217-41203036b80a/go.mod h1:UT3bZNKMF/+r2XzSvIVXWudnTgmWsQrRPOJ3bmBfjFI=
github.com/FloatTech/zbputils v1.6.2-0.20230112162135-c326104c37e6 h1:ZVpK24lgc6O2K2JBWk+NwOnMHzfotz7+EPkjHr6flrE=
github.com/FloatTech/zbputils v1.6.2-0.20230112162135-c326104c37e6/go.mod h1:A43VDRGxLk0nV8jv0ONMErudXRn58W/JQTg7S9RpbfU=
github.com/FloatTech/zbpctrl v1.5.3-0.20230130095145-714ad318cd52 h1:BrStRXeosWh8L0iA/EjPd8w6xNexDkqki39ITZko/9Q=
github.com/FloatTech/zbpctrl v1.5.3-0.20230130095145-714ad318cd52/go.mod h1:qqMLUwR7tKpqnAqsgI7aZbn0hbs2FEVF4ylMXqIpBdY=
github.com/FloatTech/zbputils v1.6.2-0.20230206130001-6b404926bf66 h1:Flhj6lBRDQQnAkRML2pIJEwqSu1NjfS2Tzh0HncaC2Q=
github.com/FloatTech/zbputils v1.6.2-0.20230206130001-6b404926bf66/go.mod h1:cJiEzrjnkGlnw1oyL4wXmF64njoDN/jNV1Qm+Hu3B2o=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA=
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
@@ -38,6 +38,8 @@ github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozb
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3 h1:qshMBFxVjYjzI+kwvWvgoByF3uMCvnJiaK8KslWAbr8=
github.com/davidscholberg/go-durationfmt v0.0.0-20170122144659-64843a2083d3/go.mod h1:M9fx6rAdHSYLKxXPgUXGgblb586CA7ceNrpu4DEc2No=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
@@ -64,6 +66,8 @@ github.com/fumiama/gofastTEA v0.0.10 h1:JJJ+brWD4kie+mmK2TkspDXKzqq0IjXm89aGYfoG
github.com/fumiama/gofastTEA v0.0.10/go.mod h1:RIdbYZyB4MbH6ZBlPymRaXn3cD6SedlCu5W/HHfMPBk=
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565 h1:sQuR2+N5HurnvsZhiKdEg+Ig354TaqgCQRxd/0KgIOQ=
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565/go.mod h1:UUEvyLTJ7yoOA/viKG4wEis4ERydM7+Ny6gZUWgkS80=
github.com/fumiama/sqlite3 v1.20.0-with-win386 h1:ZR1AXGBEtkfq9GAXehOVcwn+aaCG8itrkgEsz4ggx5k=
@@ -126,17 +130,11 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lucas-clemente/quic-go v0.31.1 h1:O8Od7hfioqq0PMYHDyBkxU2aA7iZ2W9pjbrWuja2YR4=
github.com/lucas-clemente/quic-go v0.31.1/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q=
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6ki6hE=
github.com/marten-seemann/qpack v0.3.0/go.mod h1:cGfKPBiP4a9EQdxCwEwI/GEeWAsjSekBvx/X8mh58+g=
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
@@ -161,10 +159,20 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
github.com/quic-go/quic-go v0.32.0 h1:lY02md31s1JgPiiyfqJijpu/UX/Iun304FI3yUqX7tA=
github.com/quic-go/quic-go v0.32.0/go.mod h1:/fCsKANhQIeD5l76c2JFU+07gVE3KaA0FP+0zMWwfwo=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/shirou/gopsutil/v3 v3.22.11 h1:kxsPKS+Eeo+VnEQ2XCaGJepeP6KY53QoRTETx3+1ndM=
github.com/shirou/gopsutil/v3 v3.22.11/go.mod h1:xl0EeL4vXJ+hQMAGN8B9VFpxukEMA0XdevQOe5MZ1oY=
github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4=
github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -188,8 +196,8 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
github.com/wdvxdr1123/ZeroBot v1.6.7 h1:JK29W0j9k82X4FdGcbgqP5IFikUYMaUysUOIALGfQrw=
github.com/wdvxdr1123/ZeroBot v1.6.7/go.mod h1:T5kD5vLi/YxL/fyDOCOaawi96LRBdJjcXh2CIjDyFfg=
github.com/wdvxdr1123/ZeroBot v1.6.8 h1:jdFhd6Bk0JBIKPpKhHnkACtjnIf4co6Hdw3U16e4Gi0=
github.com/wdvxdr1123/ZeroBot v1.6.8/go.mod h1:T5kD5vLi/YxL/fyDOCOaawi96LRBdJjcXh2CIjDyFfg=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
@@ -201,12 +209,13 @@ golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9 h1:tLxpBz7qD8qFkRDC159unetNbxKp4zeqsqw2rLwvdxc=
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8=
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
@@ -224,8 +233,9 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -237,8 +247,8 @@ golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -259,8 +269,9 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -273,8 +284,9 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
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=

View File

@@ -1,10 +1,10 @@
package kanban
// Version ...
var Version = "v1.6.1"
var Version = "v1.6.2-beta2"
// Banner ...
var Banner = "* OneBot + ZeroBot + Golang\n" +
"* Version " + Version + " - 2023-01-13 00:49:39 +0800 CST\n" +
"* Version " + Version + " - 2023-02-06 21:46:22 +0800 CST\n" +
"* Copyright © 2020 - 2023 FloatTech. All Rights Reserved.\n" +
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"

View File

@@ -132,6 +132,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtb_quotation" // vtb语录
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wallet" // 钱包
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wangyiyun" // 网易云音乐热评
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/warframeapi" // warframeAPI插件
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenben" // 文本指令大全
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinAI" // 百度文心AI画图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count" // 聊天热词
@@ -261,7 +262,6 @@ func init() {
logrus.Infoln("[main] 从", *runcfg, "读取配置文件")
return
}
config.W = []*driver.WSClient{driver.NewWebSocketClient(*url, *token)}
config.Z = zero.Config{
NickName: append([]string{*adana}, "ATRI", "atri", "亚托莉", "アトリ"),

View File

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

View File

@@ -2,23 +2,49 @@
package aifalse
import (
"fmt"
"bytes"
"errors"
"image"
"math"
"runtime"
"strconv"
"strings"
"sync"
"time"
"github.com/FloatTech/AnimeAPI/bilibili"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/gg"
"github.com/FloatTech/rendercard"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/text"
"github.com/disintegration/imaging"
"github.com/shirou/gopsutil/v3/cpu"
"github.com/shirou/gopsutil/v3/disk"
"github.com/shirou/gopsutil/v3/host"
"github.com/shirou/gopsutil/v3/mem"
"github.com/sirupsen/logrus"
"golang.org/x/text/cases"
"golang.org/x/text/language"
"github.com/FloatTech/ZeroBot-Plugin/kanban"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
const (
backgroundURL = "https://iw233.cn/api.php?sort=mp"
referer = "https://weibo.com/"
)
var boottime = time.Now()
func init() { // 插件主体
engine := control.Register("aifalse", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
@@ -39,12 +65,16 @@ func init() { // 插件主体
}
engine.OnFullMatchGroup([]string{"检查身体", "自检", "启动自检", "系统状态"}, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(
"* CPU占用: ", cpuPercent(), "%\n",
"* RAM占用: ", memPercent(), "%\n",
"* 硬盘使用: ", diskPercent(),
),
)
img, err := drawstatus(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), ctx.Event.SelfID, zero.BotConfig.NickName[0])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
sendimg, cl := writer.ToBytes(img)
if id := ctx.SendChain(message.ImageBytes(sendimg)); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
cl()
})
engine.OnRegex(`^设置默认限速为每\s*(\d+)\s*(分钟|秒)\s*(\d+)\s*次触发$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
@@ -84,38 +114,479 @@ func init() { // 插件主体
})
}
func cpuPercent() float64 {
func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg image.Image, err error) {
diskstate, err := diskstate()
if err != nil {
return
}
diskcardh := 40 + (20+50)*len(diskstate) + 40 - 20
moreinfo, err := moreinfo(m)
if err != nil {
return
}
moreinfocardh := 30 + (20+32*72/96)*len(moreinfo) + 30 - 20
basicstate, err := basicstate()
if err != nil {
return
}
url, err := bilibili.GetRealURL(backgroundURL)
if err != nil {
return
}
data, err := web.RequestDataWith(web.NewDefaultClient(), url, "", referer, "", nil)
if err != nil {
return
}
back, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return
}
data, err = web.GetData("http://q4.qlogo.cn/g?b=qq&nk=" + strconv.FormatInt(uid, 10) + "&s=640")
if err != nil {
return
}
avatar, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
return
}
avatarf := img.Size(avatar, 200, 200)
fontbyte, err := file.GetLazyData(text.GlowSansFontFile, control.Md5File, true)
if err != nil {
return
}
canvas := gg.NewContext(1280, 70+250+40+380+diskcardh+40+moreinfocardh+40+70)
bh, bw, ch, cw := float64(back.Bounds().Dy()), float64(back.Bounds().Dx()), float64(canvas.H()), float64(canvas.W())
if bh/bw < ch/cw {
back = img.Size(back, int(bw*ch/bh), int(bh*ch/bh)).Im
canvas.DrawImageAnchored(back, canvas.W()/2, canvas.H()/2, 0.5, 0.5)
} else {
back = img.Size(back, int(bw*cw/bw), int(bh*cw/bw)).Im
canvas.DrawImage(back, 0, 0)
}
wg := &sync.WaitGroup{}
wg.Add(5)
cardw := canvas.W() - 70 - 70
titlecardh := 250
basiccardh := 380
var titleimg, basicimg, diskimg, moreinfoimg, shadowimg image.Image
go func() {
defer wg.Done()
titlecard := gg.NewContext(cardw, titlecardh)
titlecard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70)
titlecard.DrawRoundedRectangle(1, 1, float64(titlecard.W()-1*2), float64(titlecardh-1*2), 16)
titlecard.SetLineWidth(3)
titlecard.SetRGBA255(255, 255, 255, 100)
titlecard.StrokePreserve()
titlecard.SetRGBA255(255, 255, 255, 140)
titlecard.Fill()
titlecard.DrawImage(avatarf.Circle(0).Im, (titlecardh-avatarf.H)/2, (titlecardh-avatarf.H)/2)
err = titlecard.ParseFontFace(fontbyte, 72)
if err != nil {
return
}
fw, _ := titlecard.MeasureString(botname)
titlecard.SetRGBA255(30, 30, 30, 255)
titlecard.DrawStringAnchored(botname, float64(titlecardh)+fw/2, float64(titlecardh)*0.5/2, 0.5, 0.5)
err = titlecard.ParseFontFace(fontbyte, 24)
if err != nil {
return
}
titlecard.SetRGBA255(30, 30, 30, 180)
titlecard.NewSubPath()
titlecard.MoveTo(float64(titlecardh), float64(titlecardh)/2)
titlecard.LineTo(float64(titlecard.W()-titlecardh), float64(titlecardh)/2)
titlecard.Stroke()
brt, err := botruntime()
if err != nil {
return
}
fw, _ = titlecard.MeasureString(brt)
titlecard.DrawStringAnchored(brt, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.25/2), 0.5, 0.5)
bs, err := botstatus()
if err != nil {
return
}
fw, _ = titlecard.MeasureString(bs)
titlecard.DrawStringAnchored(bs, float64(titlecardh)+fw/2, float64(titlecardh)*(0.5+0.5/2), 0.5, 0.5)
titleimg = rendercard.Fillet(titlecard.Image(), 16)
}()
go func() {
defer wg.Done()
basiccard := gg.NewContext(cardw, basiccardh)
basiccard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70-titlecardh-40)
basiccard.DrawRoundedRectangle(1, 1, float64(basiccard.W()-1*2), float64(basiccardh-1*2), 16)
basiccard.SetLineWidth(3)
basiccard.SetRGBA255(255, 255, 255, 100)
basiccard.StrokePreserve()
basiccard.SetRGBA255(255, 255, 255, 140)
basiccard.Fill()
bslen := len(basicstate)
for i, v := range basicstate {
offset := float64(i) * ((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1) + 200)
basiccard.SetRGBA255(235, 235, 235, 255)
basiccard.DrawCircle((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 100)
basiccard.Fill()
switch {
case v.precent > 90:
basiccard.SetRGBA255(255, 70, 0, 255)
case v.precent > 70:
basiccard.SetRGBA255(255, 165, 0, 255)
default:
basiccard.SetRGBA255(145, 240, 145, 255)
}
basiccard.NewSubPath()
basiccard.MoveTo((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2)
basiccard.DrawEllipticalArc((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 100, 100, -0.5*math.Pi, -0.5*math.Pi+2*v.precent*0.01*math.Pi)
basiccard.Fill()
basiccard.SetRGBA255(255, 255, 255, 255)
basiccard.DrawCircle((float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 80)
basiccard.Fill()
err = basiccard.ParseFontFace(fontbyte, 42)
if err != nil {
return
}
basiccard.SetRGBA255(213, 213, 213, 255)
basiccard.DrawStringAnchored(strconv.FormatFloat(v.precent, 'f', 0, 64)+"%", (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200/2, 0.5, 0.5)
basiccard.SetRGBA255(30, 30, 30, 255)
_, fw := basiccard.MeasureString(v.name)
basiccard.DrawStringAnchored(v.name, (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200+15+basiccard.FontHeight()/2, 0.5, 0.5)
err = basiccard.ParseFontFace(fontbyte, 20)
if err != nil {
return
}
basiccard.SetRGBA255(30, 30, 30, 180)
textoffsety := basiccard.FontHeight() + 10
for k, s := range v.text {
basiccard.DrawStringAnchored(s, (float64(basiccard.W())-200*float64(bslen))/float64(bslen+1)+200/2+offset, 20+200+15+fw+15+basiccard.FontHeight()/2+float64(k)*textoffsety, 0.5, 0.5)
}
}
basicimg = rendercard.Fillet(basiccard.Image(), 16)
}()
go func() {
defer wg.Done()
diskcard := gg.NewContext(cardw, diskcardh)
diskcard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70-titlecardh-40-basiccardh-40)
diskcard.DrawRoundedRectangle(1, 1, float64(diskcard.W()-1*2), float64(diskcardh-1*2), 16)
diskcard.SetLineWidth(3)
diskcard.SetRGBA255(255, 255, 255, 100)
diskcard.StrokePreserve()
diskcard.SetRGBA255(255, 255, 255, 140)
diskcard.Fill()
err = diskcard.ParseFontFace(fontbyte, 32)
if err != nil {
return
}
dslen := len(diskstate)
if dslen == 1 {
diskcard.SetRGBA255(192, 192, 192, 255)
diskcard.DrawRoundedRectangle(40, 40, float64(diskcard.W())-40-100, 50, 12)
diskcard.Fill()
switch {
case diskstate[0].precent > 90:
diskcard.SetRGBA255(255, 70, 0, 255)
case diskstate[0].precent > 70:
diskcard.SetRGBA255(255, 165, 0, 255)
default:
diskcard.SetRGBA255(145, 240, 145, 255)
}
diskcard.DrawRoundedRectangle(40, 40, (float64(diskcard.W())-40-100)*diskstate[0].precent*0.01, 50, 12)
diskcard.Fill()
diskcard.SetRGBA255(30, 30, 30, 255)
fw, _ := diskcard.MeasureString(diskstate[0].name)
fw1, _ := diskcard.MeasureString(diskstate[0].text[0])
diskcard.DrawStringAnchored(diskstate[0].name, 40+10+fw/2, 40+50/2, 0.5, 0.5)
diskcard.DrawStringAnchored(diskstate[0].text[0], (float64(diskcard.W())-100-10)-fw1/2, 40+50/2, 0.5, 0.5)
diskcard.DrawStringAnchored(strconv.FormatFloat(diskstate[0].precent, 'f', 0, 64)+"%", float64(diskcard.W())-100/2, 40+50/2, 0.5, 0.5)
} else {
for i, v := range diskstate {
offset := float64(i)*(50+20) - 20
diskcard.SetRGBA255(192, 192, 192, 255)
diskcard.DrawRoundedRectangle(40, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+offset, float64(diskcard.W())-40-100, 50, 12)
diskcard.Fill()
switch {
case v.precent > 90:
diskcard.SetRGBA255(255, 70, 0, 255)
case v.precent > 70:
diskcard.SetRGBA255(255, 165, 0, 255)
default:
diskcard.SetRGBA255(145, 240, 145, 255)
}
diskcard.DrawRoundedRectangle(40, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+offset, (float64(diskcard.W())-40-100)*v.precent*0.01, 50, 12)
diskcard.Fill()
diskcard.SetRGBA255(30, 30, 30, 255)
fw, _ := diskcard.MeasureString(v.name)
fw1, _ := diskcard.MeasureString(v.text[0])
diskcard.DrawStringAnchored(v.name, 40+10+fw/2, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+50/2+offset, 0.5, 0.5)
diskcard.DrawStringAnchored(v.text[0], (float64(diskcard.W())-100-10)-fw1/2, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+50/2+offset, 0.5, 0.5)
diskcard.DrawStringAnchored(strconv.FormatFloat(v.precent, 'f', 0, 64)+"%", float64(diskcard.W())-100/2, 40+(float64(diskcardh-40*2)-50*float64(dslen))/float64(dslen-1)+50/2+offset, 0.5, 0.5)
}
}
diskimg = rendercard.Fillet(diskcard.Image(), 16)
}()
go func() {
defer wg.Done()
moreinfocard := gg.NewContext(cardw, moreinfocardh)
moreinfocard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70-titlecardh-40-basiccardh-40-diskcardh-40)
moreinfocard.DrawRoundedRectangle(1, 1, float64(moreinfocard.W()-1*2), float64(moreinfocard.H()-1*2), 16)
moreinfocard.SetLineWidth(3)
moreinfocard.SetRGBA255(255, 255, 255, 100)
moreinfocard.StrokePreserve()
moreinfocard.SetRGBA255(255, 255, 255, 140)
moreinfocard.Fill()
err = moreinfocard.ParseFontFace(fontbyte, 32)
if err != nil {
return
}
milen := len(moreinfo)
for i, v := range moreinfo {
offset := float64(i)*(20+moreinfocard.FontHeight()) - 20
moreinfocard.SetRGBA255(30, 30, 30, 255)
fw, _ := moreinfocard.MeasureString(v.name)
fw1, _ := moreinfocard.MeasureString(v.text[0])
moreinfocard.DrawStringAnchored(v.name, 20+fw/2, 30+(float64(moreinfocardh-30*2)-moreinfocard.FontHeight()*float64(milen))/float64(milen-1)+moreinfocard.FontHeight()/2+offset, 0.5, 0.5)
moreinfocard.DrawStringAnchored(v.text[0], float64(moreinfocard.W())-20-fw1/2, 30+(float64(moreinfocardh-30*2)-moreinfocard.FontHeight()*float64(milen))/float64(milen-1)+moreinfocard.FontHeight()/2+offset, 0.5, 0.5)
}
moreinfoimg = rendercard.Fillet(moreinfocard.Image(), 16)
}()
go func() {
defer wg.Done()
shadow := gg.NewContext(canvas.W(), canvas.H())
shadow.SetRGBA255(0, 0, 0, 100)
shadow.SetLineWidth(12)
shadow.DrawRoundedRectangle(70, 70, float64(cardw), float64(titlecardh), 16)
shadow.Stroke()
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40), float64(cardw), float64(basiccardh), 16)
shadow.Stroke()
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40), float64(cardw), float64(basiccardh), 16)
shadow.Stroke()
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40+diskcardh+40), float64(cardw), float64(moreinfocardh), 16)
shadow.Stroke()
shadowimg = imaging.Blur(shadow.Image(), 24)
}()
wg.Wait()
if shadowimg == nil || titleimg == nil || basicimg == nil || diskimg == nil || moreinfoimg == nil {
err = errors.New("图片渲染失败")
return
}
canvas.DrawImage(shadowimg, 0, 0)
canvas.DrawImage(titleimg, 70, 70)
canvas.DrawImage(basicimg, 70, 70+titlecardh+40)
canvas.DrawImage(diskimg, 70, 70+titlecardh+40+basiccardh+40)
canvas.DrawImage(moreinfoimg, 70, 70+titlecardh+40+basiccardh+40+diskcardh+40)
err = canvas.ParseFontFace(fontbyte, 28)
if err != nil {
return
}
canvas.SetRGBA255(0, 0, 0, 255)
canvas.DrawStringAnchored("Created By ZeroBot-Plugin "+kanban.Version, float64(canvas.W())/2+3, float64(canvas.H())-70/2+3, 0.5, 0.5)
canvas.SetRGBA255(255, 255, 255, 255)
canvas.DrawStringAnchored("Created By ZeroBot-Plugin "+kanban.Version, float64(canvas.W())/2, float64(canvas.H())-70/2, 0.5, 0.5)
sendimg = canvas.Image()
return
}
func botruntime() (string, error) {
hostinfo, err := host.Info()
if err != nil {
return "", err
}
t := &strings.Builder{}
t.WriteString("ZeroBot-Plugin 已运行 ")
t.WriteString(strconv.FormatInt((time.Now().Unix()-boottime.Unix())/86400, 10))
t.WriteString(" 天 ")
t.WriteString(time.Unix(time.Now().Unix()-boottime.Unix(), 0).UTC().Format("15:04:05"))
t.WriteString(" | 系统运行 ")
t.WriteString(strconv.FormatInt(int64(hostinfo.Uptime)/86400, 10))
t.WriteString(" 天 ")
t.WriteString(time.Unix(int64(hostinfo.Uptime), 0).UTC().Format("15:04:05"))
return t.String(), nil
}
func botstatus() (string, error) {
hostinfo, err := host.Info()
if err != nil {
return "", err
}
t := &strings.Builder{}
t.WriteString(time.Now().Format("2006-01-02 15:04:05"))
t.WriteString(" | Compiled by ")
t.WriteString(runtime.Version())
t.WriteString(" | ")
t.WriteString(cases.Title(language.English).String(hostinfo.OS))
return t.String(), nil
}
type status struct {
precent float64
name string
text []string
}
func basicstate() (stateinfo [3]*status, err error) {
percent, err := cpu.Percent(time.Second, false)
if err != nil {
return -1
return
}
return math.Round(percent[0])
cpuinfo, err := cpu.Info()
if err != nil {
return
}
cores := strconv.Itoa(int(cpuinfo[0].Cores)) + " Core"
times := "最大 " + strconv.FormatFloat(cpuinfo[0].Mhz/1000, 'f', 1, 64) + "Ghz"
stateinfo[0] = &status{
precent: math.Round(percent[0]),
name: "CPU",
text: []string{cores, times},
}
raminfo, err := mem.VirtualMemory()
if err != nil {
return
}
total := "总共 " + storagefmt(float64(raminfo.Total))
used := "已用 " + storagefmt(float64(raminfo.Used))
free := "剩余 " + storagefmt(float64(raminfo.Free))
stateinfo[1] = &status{
precent: math.Round(raminfo.UsedPercent),
name: "RAM",
text: []string{total, used, free},
}
swapinfo, err := mem.SwapMemory()
if err != nil {
return
}
total = "总共 " + storagefmt(float64(swapinfo.Total))
used = "已用 " + storagefmt(float64(swapinfo.Used))
free = "剩余 " + storagefmt(float64(swapinfo.Free))
stateinfo[2] = &status{
precent: math.Round(swapinfo.UsedPercent),
name: "SWAP",
text: []string{total, used, free},
}
return
}
func memPercent() float64 {
memInfo, err := mem.VirtualMemory()
if err != nil {
return -1
func storagefmt(num float64) string {
if num /= 1024; num < 1 {
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "B"
}
return math.Round(memInfo.UsedPercent)
if num /= 1024; num < 1 {
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "KB"
}
if num /= 1024; num < 1 {
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "MB"
}
if num /= 1024; num < 1 {
return strconv.FormatFloat(num*1024, 'f', 2, 64) + "GB"
}
return strconv.FormatFloat(num, 'f', 2, 64) + "TB"
}
func diskPercent() string {
parts, err := disk.Partitions(true)
func diskstate() (stateinfo []*status, err error) {
parts, err := disk.Partitions(false)
if err != nil {
return err.Error()
return
}
msg := ""
for _, p := range parts {
diskInfo, err := disk.Usage(p.Mountpoint)
stateinfo = make([]*status, len(parts))
for i, v := range parts {
mp := v.Mountpoint
diskusage, err := disk.Usage(mp)
usage := ""
precent := 0.0
if err != nil {
msg += "\n - " + err.Error()
continue
usage = err.Error()
} else {
usage = storagefmt(float64(diskusage.Used)) + " / " + storagefmt(float64(diskusage.Total))
precent = math.Round(diskusage.UsedPercent)
}
pc := uint(math.Round(diskInfo.UsedPercent))
if pc > 0 {
msg += fmt.Sprintf("\n - %s(%dM) %d%%", p.Mountpoint, diskInfo.Total/1024/1024, pc)
stateinfo[i] = &status{
precent: precent,
name: mp,
text: []string{usage},
}
}
return msg
return stateinfo, nil
}
func moreinfo(m *ctrl.Control[*zero.Ctx]) (stateinfo []*status, err error) {
hostinfo, err := host.Info()
if err != nil {
return
}
cpuinfo, err := cpu.Info()
if err != nil {
return
}
count := len(m.Manager.M)
stateinfo = []*status{
{name: "OS", text: []string{hostinfo.Platform}},
{name: "CPU", text: []string{cpuinfo[0].ModelName}},
{name: "Version", text: []string{hostinfo.PlatformVersion}},
{name: "Plugin", text: []string{"共 " + strconv.Itoa(count) + " 个"}},
}
return
}

View File

@@ -2,6 +2,7 @@
package aireply
import (
"regexp"
"strconv"
"time"
@@ -59,6 +60,7 @@ func init() { // 插件主体
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("成功"))
})
endpre := regexp.MustCompile(`\pP$`)
ent.OnMessage(zero.OnlyToMe).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
msg := ctx.ExtractPlainText()
@@ -72,7 +74,12 @@ func init() { // 插件主体
ctx.SendChain(message.Text("ERROR: ", err))
return
}
rec, err := speaker.Speak(ctx.Event.UserID, func() string { return reply })
rec, err := speaker.Speak(ctx.Event.UserID, func() string {
if !endpre.MatchString(reply) {
return reply + "。"
}
return reply
})
if err != nil {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(reply))
return

View File

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

View File

@@ -16,12 +16,12 @@ import (
"strconv"
"time"
"github.com/Coloured-glaze/gg"
bz "github.com/FloatTech/AnimeAPI/bilibili"
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/gg"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img"

View File

@@ -53,7 +53,7 @@ func init() {
text := strings.ReplaceAll(cs.Story, "<攻>", gong)
text = strings.ReplaceAll(text, "<受>", shou)
text = strings.ReplaceAll(text, cs.Gong, gong)
text = strings.ReplaceAll(text, cs.Shou, gong)
text = strings.ReplaceAll(text, cs.Shou, shou)
ctx.SendChain(message.Text(text))
})
engine.OnPrefix("磕cp", getdb).SetBlock(true).Handle(func(ctx *zero.Ctx) {

View File

@@ -8,9 +8,9 @@ import (
"net/url"
"sort"
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/gg"
"github.com/FloatTech/zbputils/control"
imgutils "github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/text" // jpg png gif

View File

@@ -11,7 +11,7 @@ import (
"os"
"strconv"
"github.com/Coloured-glaze/gg" // 注册了 jpg png gif
"github.com/FloatTech/gg" // 注册了 jpg png gif
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"

View File

@@ -6,9 +6,9 @@ import (
"image/color"
"sync"
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/gg"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/text"

View File

@@ -8,9 +8,9 @@ import (
"strconv"
"sync"
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/gg"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/text"

View File

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

View File

@@ -18,10 +18,10 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
// 图片输出
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/process"
"github.com/FloatTech/gg"
"github.com/FloatTech/zbputils/img/text"
)

View File

@@ -11,7 +11,7 @@ import (
"regexp"
"strings"
"github.com/lucas-clemente/quic-go/http3"
"github.com/quic-go/quic-go/http3"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"

View File

@@ -222,7 +222,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("那我就不手下留情了~"))
})
// 修改名片
engine.OnRegex(`^修改名片.*(\d+).*\s+(.*)`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
engine.OnRegex(`^修改名片.*?(\d+).+?\s*(.*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if len(ctx.State["regex_matched"].([]string)[2]) > 60 {
ctx.SendChain(message.Text("名字太长啦!"))
@@ -236,30 +236,38 @@ func init() { // 插件主体
ctx.SendChain(message.Text("嗯!已经修改了"))
})
// 修改头衔
engine.OnRegex(`^修改头衔.*(\d+).*\s+(.*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
engine.OnRegex(`^修改头衔.*?(\d+).+?\s*(.*)$`, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if len(ctx.State["regex_matched"].([]string)[1]) > 18 {
sptitle := ctx.State["regex_matched"].([]string)[2]
if sptitle == "" {
ctx.SendChain(message.Text("头衔不能为空!"))
return
} else if len(sptitle) > 18 {
ctx.SendChain(message.Text("头衔太长啦!"))
return
}
ctx.SetGroupSpecialTitle(
ctx.Event.GroupID,
math.Str2Int64(ctx.State["regex_matched"].([]string)[1]), // 被修改群头衔的人
ctx.State["regex_matched"].([]string)[2], // 修改成的群头衔
sptitle, // 修改成的群头衔
)
ctx.SendChain(message.Text("嗯!已经修改了"))
})
// 申请头衔
engine.OnRegex(`^申请头衔\s+(.*)$`, zero.OnlyGroup).SetBlock(true).
engine.OnRegex(`^申请头衔\s*(.*)$`, zero.OnlyGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if len(ctx.State["regex_matched"].([]string)[1]) > 18 {
sptitle := ctx.State["regex_matched"].([]string)[1]
if sptitle == "" {
ctx.SendChain(message.Text("头衔不能为空!"))
return
} else if len(sptitle) > 18 {
ctx.SendChain(message.Text("头衔太长啦!"))
return
}
ctx.SetGroupSpecialTitle(
ctx.Event.GroupID,
ctx.Event.UserID, // 被修改群头衔的人
ctx.State["regex_matched"].([]string)[1], // 修改成的群头衔
ctx.Event.UserID, // 被修改群头衔的人
sptitle, // 修改成的群头衔
)
ctx.SendChain(message.Text("嗯!不错的头衔呢~"))
})

View File

@@ -3,19 +3,21 @@ package novel
import (
"fmt"
"io"
"net/http"
"net/http/cookiejar"
"net/url"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/antchfx/htmlquery"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
ub "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"
@@ -32,26 +34,47 @@ const (
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
loginURL = websiteURL + "/login.php?do=submit&jumpurl=https%3A%2F%2Fwww.23qb.com%2F"
searchURL = websiteURL + "/saerch.php"
downloadURL = websiteURL + "/modules/article/txtarticle.php?id=%v"
detailURL = websiteURL + "/book/%v/"
idReg = `/(\d+)/`
)
var gCurCookieJar *cookiejar.Jar
var (
cachePath string
// apikey 由账号和密码拼接而成, 例: zerobot,123456
apikey string
)
func init() {
control.Register("novel", &ctrl.Options[*zero.Ctx]{
engine := control.Register("novel", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "铅笔小说网搜索",
Help: "- 小说[xxx]",
}).OnRegex("^小说([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).Limit(ctxext.LimitByUser).
Help: "- 小说[xxx]\n" +
"- 设置小说配置 zerobot 123456\n" +
"- 下载小说30298\n" +
"建议去https://www.23qb.com/ 注册一个账号, 小说下载有积分限制",
PrivateDataFolder: "novel",
})
cachePath = engine.DataFolder() + "cache/"
_ = os.MkdirAll(cachePath, 0755)
engine.OnRegex("^小说([\u4E00-\u9FA5A-Za-z0-9]{1,25})$").SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女祈祷中......"))
err := login(username, password)
key := getAPIKey(ctx)
u, p, _ := strings.Cut(key, ",")
if u == "" {
u = username
}
if p == "" {
p = password
}
cookie, err := login(u, p)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
searchKey := ctx.State["regex_matched"].([]string)[1]
searchHTML, err := search(searchKey)
searchHTML, err := search(searchKey, cookie)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
@@ -93,7 +116,7 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if id := ctx.SendChain(message.Image("base64://" + helper.BytesToString(data))); id.ID() == 0 {
if id := ctx.SendChain(message.Image("base64://" + ub.BytesToString(data))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
}
} else {
@@ -124,23 +147,76 @@ func init() {
ctx.SendChain(message.Text(text))
}
})
engine.OnRegex(`^设置小说配置\s(.*[^\s$])\s(.+)$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
regexMatched := ctx.State["regex_matched"].([]string)
err := setAPIKey(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), regexMatched[1]+","+regexMatched[2])
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("成功设置小说配置\nusername: ", regexMatched[1], "\npassword: ", regexMatched[2]))
})
engine.OnRegex("^下载小说([0-9]{1,25})$").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
regexMatched := ctx.State["regex_matched"].([]string)
id := regexMatched[1]
ctx.SendChain(message.Text("少女祈祷中......"))
key := getAPIKey(ctx)
u, p, _ := strings.Cut(key, ",")
if u == "" {
u = username
}
if p == "" {
p = password
}
cookie, err := login(u, p)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
detailHTML, err := detail(id, cookie)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
doc, err := htmlquery.Parse(strings.NewReader(detailHTML))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
title := htmlquery.InnerText(htmlquery.FindOne(doc, "//*[@id='bookinfo']/div[@class='bookright']/div[@class='d_title']/h1"))
fileName := filepath.Join(cachePath, title+".txt")
if file.IsExist(fileName) {
ctx.UploadThisGroupFile(filepath.Join(file.BOTPATH, fileName), filepath.Base(fileName), "")
return
}
data, err := download(id, cookie)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
err = os.WriteFile(fileName, ub.StringToBytes(data), 0666)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.UploadThisGroupFile(filepath.Join(file.BOTPATH, fileName), filepath.Base(fileName), "")
})
}
func login(username, password string) (err error) {
gCurCookieJar, _ = cookiejar.New(nil)
client := &http.Client{
Jar: gCurCookieJar,
}
usernameData, err := ub.UTF82GBK(helper.StringToBytes(username))
func login(username, password string) (cookie string, err error) {
client := &http.Client{}
usernameData, err := ub.UTF82GBK(ub.StringToBytes(username))
if err != nil {
return
}
usernameGbk := helper.BytesToString(usernameData)
passwordData, err := ub.UTF82GBK(helper.StringToBytes(password))
usernameGbk := ub.BytesToString(usernameData)
passwordData, err := ub.UTF82GBK(ub.StringToBytes(password))
if err != nil {
return
}
passwordGbk := helper.BytesToString(passwordData)
passwordGbk := ub.BytesToString(passwordData)
loginReq, err := http.NewRequest("POST", loginURL, strings.NewReader(fmt.Sprintf("username=%s&password=%s&usecookie=315360000&action=login&submit=%s", url.QueryEscape(usernameGbk), url.QueryEscape(passwordGbk), submit)))
if err != nil {
return
@@ -151,38 +227,79 @@ func login(username, password string) (err error) {
if err != nil {
return
}
_ = loginResp.Body.Close()
defer loginResp.Body.Close()
for _, v := range loginResp.Cookies() {
cookie += v.Name + "=" + v.Value + ";"
}
return
}
func search(searchKey string) (searchHTML string, err error) {
searchKeyData, err := ub.UTF82GBK(helper.StringToBytes(searchKey))
func search(searchKey string, cookie string) (searchHTML string, err error) {
searchKeyData, err := ub.UTF82GBK(ub.StringToBytes(searchKey))
if err != nil {
return
}
searchKeyGbk := helper.BytesToString(searchKeyData)
client := &http.Client{
Jar: gCurCookieJar,
}
searchReq, err := http.NewRequest("POST", searchURL, strings.NewReader(fmt.Sprintf("searchkey=%s&searchtype=all", url.QueryEscape(searchKeyGbk))))
searchKeyGbk := ub.BytesToString(searchKeyData)
data, err := web.RequestDataWithHeaders(web.NewDefaultClient(), searchURL, "POST", func(r *http.Request) error {
r.Header.Set("Cookie", cookie)
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
r.Header.Set("User-Agent", ua)
return nil
}, strings.NewReader(fmt.Sprintf("searchkey=%s&searchtype=all", url.QueryEscape(searchKeyGbk))))
if err != nil {
return
}
searchReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
searchReq.Header.Set("User-Agent", ua)
searchResp, err := client.Do(searchReq)
searchData, err := ub.GBK2UTF8(data)
if err != nil {
return
}
searchData, err := io.ReadAll(searchResp.Body)
_ = searchResp.Body.Close()
if err != nil {
return
}
searchData, err = ub.GBK2UTF8(searchData)
if err != nil {
return
}
searchHTML = helper.BytesToString(searchData)
return searchHTML, nil
searchHTML = ub.BytesToString(searchData)
return
}
func detail(id string, cookie string) (detailHTML string, err error) {
data, err := web.RequestDataWithHeaders(web.NewDefaultClient(), fmt.Sprintf(detailURL, id), "GET", func(r *http.Request) error {
r.Header.Set("Cookie", cookie)
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
r.Header.Set("User-Agent", ua)
return nil
}, nil)
if err != nil {
return
}
detailData, err := ub.GBK2UTF8(data)
if err != nil {
return
}
detailHTML = ub.BytesToString(detailData)
return
}
func download(id string, cookie string) (downloadHTML string, err error) {
data, err := web.RequestDataWithHeaders(web.NewDefaultClient(), fmt.Sprintf(downloadURL, id), "GET", func(r *http.Request) error {
r.Header.Set("Cookie", cookie)
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
r.Header.Set("User-Agent", ua)
return nil
}, nil)
if err != nil {
return
}
downloadHTML = ub.BytesToString(data)
return
}
func getAPIKey(ctx *zero.Ctx) string {
if apikey == "" {
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
_ = m.Manager.GetExtra(-1, &apikey)
logrus.Debugln("[novel] get api key:", apikey)
}
return apikey
}
func setAPIKey(m *ctrl.Control[*zero.Ctx], key string) error {
apikey = key
_ = m.Manager.Response(-1)
return m.Manager.SetExtra(-1, apikey)
}

View File

@@ -21,12 +21,11 @@ import (
// 数据库
sql "github.com/FloatTech/sqlite"
// 画图
"github.com/Coloured-glaze/gg"
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/gg"
"github.com/FloatTech/zbputils/img/text"
// 货币系统
)
type 婚姻登记 struct {
@@ -60,7 +59,7 @@ var (
engine = control.Register("qqwife", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "一群一天一夫一妻制群老婆",
Help: "- 娶群友\n- 群老婆列表\n- [允许|禁止]自由恋爱\n- [允许|禁止]牛头人\n- 设置CD为xx小时 →(默认12小时)\n- 重置花名册\n- 重置所有花名册(用于清除所有群数据及其设置)\n- 查好感度[对方Q号|@对方QQ]\n- 好感度列表\n" +
Help: "- 娶群友\n- 群老婆列表\n- [允许|禁止]自由恋爱\n- [允许|禁止]牛头人\n- 设置CD为xx小时 →(默认12小时)\n- 重置花名册\n- 重置所有花名册(用于清除所有群数据及其设置)\n- 查好感度[对方Q号|@对方QQ]\n- 好感度列表\n- 好感度数据整理 (当好感度列表出现重复名字时使用)\n" +
"--------------------------------\n以下指令存在CD,不跨天刷新,前两个受指令开关\n--------------------------------\n" +
"- (娶|嫁)@对方QQ\n自由选择对象, 自由恋爱(好感度越高成功率越高,保底30%概率)\n" +
"- 当[对方Q号|@对方QQ]的小三\n我和你才是真爱, 为了你我愿意付出一切(好感度越高成功率越高,保底10%概率)\n" +
@@ -69,7 +68,7 @@ var (
"- 做媒 @攻方QQ @受方QQ\n身为管理, 群友的xing福是要搭把手的(攻受双方好感度越高成功率越高,保底30%概率)\n" +
"--------------------------------\n好感度规则\n--------------------------------\n" +
"\"娶群友\"指令好感度随机增加1~5。\n\"A牛B的C\"会导致C恨A, 好感度-5;\nB为了报复A, 好感度+5(什么柜子play)\nA为BC做媒,成功B、C对A好感度+1反之-1\n做媒成功BC好感度+1" +
"Tips: 群老婆列表过0点刷新",
"\nTips: 群老婆列表过0点刷新",
PrivateDataFolder: "qqwife",
}).ApplySingle(single.New(
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),

View File

@@ -14,9 +14,9 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
// 画图
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/gg"
"github.com/FloatTech/zbputils/img/text"
// 货币系统
@@ -84,16 +84,18 @@ func init() {
ctx.SendChain(message.Text("你钱包没钱啦!"))
return
}
moneyToFavor := rand.Intn(math.Min(walletinfo, 100))
moneyToFavor := rand.Intn(math.Min(walletinfo, 100)) + 1
// 计算钱对应的好感值
newFavor := 1
moodMax := 2
if favor > 50 {
newFavor = moneyToFavor % 10 // 礼物厌倦
} else {
moodMax = 5
newFavor += rand.Intn(moneyToFavor)
}
// 随机对方心情
mood := rand.Intn(2)
mood := rand.Intn(moodMax)
if mood == 0 {
newFavor = -newFavor
}
@@ -191,6 +193,71 @@ func init() {
ctx.SendChain(message.ImageBytes(data))
cl()
})
engine.OnFullMatch("好感度数据整理", zero.SuperUserPermission, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("开始整理力,请稍等"))
民政局.Lock()
defer 民政局.Unlock()
count, err := 民政局.db.Count("favorability")
if err != nil {
ctx.SendChain(message.Text("[ERROR]: ", err))
return
}
if count == 0 {
ctx.SendChain(message.Text("[ERROR]: 不存在好感度数据."))
return
}
favor := favorability{}
delInfo := make([]string, 0, count*2)
favorInfo := make(map[string]int, count*2)
_ = 民政局.db.FindFor("favorability", &favor, "group by Userinfo", func() error {
delInfo = append(delInfo, favor.Userinfo)
// 解析旧数据
userList := strings.Split(favor.Userinfo, "+")
maxQQ, _ := strconv.ParseInt(userList[0], 10, 64)
minQQ, _ := strconv.ParseInt(userList[1], 10, 64)
if maxQQ > minQQ {
favor.Userinfo = userList[0] + "+" + userList[1]
} else {
favor.Userinfo = userList[1] + "+" + userList[0]
}
// 判断是否是重复的
score, ok := favorInfo[favor.Userinfo]
if ok {
if score < favor.Favor {
favorInfo[favor.Userinfo] = favor.Favor
}
} else {
favorInfo[favor.Userinfo] = favor.Favor
}
return nil
})
for _, updateinfo := range delInfo {
// 删除旧数据
err = 民政局.db.Del("favorability", "where Userinfo = '"+updateinfo+"'")
if err != nil {
userList := strings.Split(favor.Userinfo, "+")
uid1, _ := strconv.ParseInt(userList[0], 10, 64)
uid2, _ := strconv.ParseInt(userList[1], 10, 64)
ctx.SendChain(message.Text("[ERROR]: 删除", ctx.CardOrNickName(uid1), "和", ctx.CardOrNickName(uid2), "的好感度时发生了错误。\n错误信息:", err))
}
}
for userInfo, favor := range favorInfo {
favorInfo := favorability{
Userinfo: userInfo,
Favor: favor,
}
err = 民政局.db.Insert("favorability", &favorInfo)
if err != nil {
userList := strings.Split(userInfo, "+")
uid1, _ := strconv.ParseInt(userList[0], 10, 64)
uid2, _ := strconv.ParseInt(userList[1], 10, 64)
ctx.SendChain(message.Text("[ERROR]: 更新", ctx.CardOrNickName(uid1), "和", ctx.CardOrNickName(uid2), "的好感度时发生了错误。\n错误信息:", err))
}
}
ctx.SendChain(message.Text("清理好了哦"))
})
}
func (sql *婚姻登记) 查好感度(uid, target int64) (int, error) {
@@ -201,9 +268,19 @@ func (sql *婚姻登记) 查好感度(uid, target int64) (int, error) {
return 0, err
}
info := favorability{}
uidstr := strconv.FormatInt(uid, 10)
targstr := strconv.FormatInt(target, 10)
_ = sql.db.Find("favorability", &info, "where Userinfo glob '*"+uidstr+"+"+targstr+"*'")
if uid > target {
userinfo := strconv.FormatInt(uid, 10) + "+" + strconv.FormatInt(target, 10)
err = sql.db.Find("favorability", &info, "where Userinfo is '"+userinfo+"'")
if err != nil {
_ = sql.db.Find("favorability", &info, "where Userinfo glob '*"+userinfo+"*'")
}
} else {
userinfo := strconv.FormatInt(target, 10) + "+" + strconv.FormatInt(uid, 10)
err = sql.db.Find("favorability", &info, "where Userinfo is '"+userinfo+"'")
if err != nil {
_ = sql.db.Find("favorability", &info, "where Userinfo glob '*"+userinfo+"*'")
}
}
return info.Favor, nil
}
@@ -256,8 +333,19 @@ func (sql *婚姻登记) 更新好感度(uid, target int64, score int) (favor in
info := favorability{}
uidstr := strconv.FormatInt(uid, 10)
targstr := strconv.FormatInt(target, 10)
_ = sql.db.Find("favorability", &info, "where Userinfo glob '*"+uidstr+"+"+targstr+"*'")
info.Userinfo = uidstr + "+" + targstr + "+" + uidstr
if uid > target {
info.Userinfo = uidstr + "+" + targstr
err = sql.db.Find("favorability", &info, "where Userinfo is '"+info.Userinfo+"'")
} else {
info.Userinfo = targstr + "+" + uidstr
err = sql.db.Find("favorability", &info, "where Userinfo is '"+info.Userinfo+"'")
}
if err != nil {
err = sql.db.Find("favorability", &info, "where Userinfo glob '*"+targstr+"+"+uidstr+"*'")
if err == nil { // 如果旧数据存在就删除旧数据
err = 民政局.db.Del("favorability", "where Userinfo = '"+info.Userinfo+"'")
}
}
info.Favor += score
if info.Favor > 100 {
info.Favor = 100

View File

@@ -4,6 +4,7 @@ package quan
import (
"fmt"
"strconv"
"strings"
"github.com/FloatTech/floatbox/web"
ctrl "github.com/FloatTech/zbpctrl"
@@ -35,6 +36,23 @@ func init() { // 主函数
ctx.SendChain(message.Text("出现错误捏:", err))
return
}
ctx.SendChain(message.Text(str, helper.BytesToString(es))) // 输出结果
if len(helper.BytesToString(es)) <= 24 {
ctx.SendChain(message.Text("网站维护中")) // 输出结果
return
}
f := helper.BytesToString(es)[24:]
_, err = strconv.Atoi(f)
if err != nil {
ctx.SendChain(message.Text("网站维护中")) // 输出结果
return
}
var msg strings.Builder
msg.WriteString("查询账号:")
msg.WriteString(str)
msg.WriteString("\n")
msg.WriteString("查询状态:成功\n")
msg.WriteString("您的权重为:")
msg.WriteString(f)
ctx.SendChain(message.Text(msg.String())) // 输出结果
})
}

View File

@@ -12,11 +12,11 @@ import (
"strings"
"time"
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/AnimeAPI/qzone"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/gg"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"

View File

@@ -9,10 +9,13 @@ import (
"strconv"
"time"
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/AnimeAPI/bilibili"
"github.com/FloatTech/AnimeAPI/wallet"
"github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/floatbox/process"
"github.com/FloatTech/floatbox/web"
"github.com/FloatTech/gg"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
@@ -23,13 +26,11 @@ import (
"github.com/wcharczuk/go-chart/v2"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
// 货币系统
"github.com/FloatTech/AnimeAPI/wallet"
)
const (
backgroundURL = "https://img.moehu.org/pic.php?id=pc"
backgroundURL = "https://iw233.cn/api.php?sort=pc"
referer = "https://weibo.com/"
signinMax = 1
// SCOREMAX 分数上限定为1200
SCOREMAX = 1200
@@ -307,5 +308,13 @@ func initPic(picFile string) error {
return nil
}
defer process.SleepAbout1sTo2s()
return file.DownloadTo(backgroundURL, picFile)
url, err := bilibili.GetRealURL(backgroundURL)
if err != nil {
return err
}
data, err := web.RequestDataWith(web.NewDefaultClient(), url, "", referer, "", nil)
if err != nil {
return err
}
return os.WriteFile(picFile, data, 0644)
}

View File

@@ -122,10 +122,6 @@ func init() {
ctx.SendChain(message.Text("ERROR: 张数必须为正"))
return
}
if n > 1 && !zero.OnlyGroup(ctx) {
ctx.SendChain(message.Text("ERROR: 抽取多张仅支持群聊"))
return
}
if n > 20 {
ctx.SendChain(message.Text("ERROR: 抽取张数过多"))
return

94
plugin/warframeapi/api.go Normal file
View File

@@ -0,0 +1,94 @@
package warframeapi
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"sort"
"github.com/FloatTech/floatbox/web"
)
const wfapiurl = "https://api.warframestat.us/pc" // 星际战甲API
const wfitemurl = "https://api.warframe.market/v1/items" // 星际战甲游戏品信息列表URL
// 从WFapi获取数据
func newwfapi() (w wfapi, err error) {
var data []byte
data, err = web.GetData(wfapiurl)
if err != nil {
return
}
err = json.Unmarshal(data, &w)
return
}
// 获取Warframe市场的售价表并进行排序,cn_name为物品中文名称onlyMaxRank表示只取最高等级的物品返回物品售价表物品信息物品英文
func getitemsorder(cnName string, onlyMaxRank bool) (od orders, it *itemsInSet, n string, err error) {
var wfapiio wfAPIItemsOrders
data, err := web.RequestDataWithHeaders(&http.Client{}, fmt.Sprintf("https://api.warframe.market/v1/items/%s/orders?include=item", cnName), "GET", func(request *http.Request) error {
request.Header.Add("Accept", "application/json")
request.Header.Add("Platform", "pc")
return nil
}, nil)
if err != nil {
return
}
err = json.Unmarshal(data, &wfapiio)
if len(wfapiio.Payload.Orders) == 0 {
err = errors.New("no such name")
}
od = make(orders, 0, len(wfapiio.Payload.Orders))
// 遍历市场物品列表
for _, v := range wfapiio.Payload.Orders {
// 取其中类型为售卖,且去掉不在线的玩家
if v.OrderType == "sell" && v.User.Status != "offline" {
if !onlyMaxRank {
od = append(od, v)
continue
}
if v.ModRank == wfapiio.Include.Item.ItemsInSet[0].ModMaxRank {
od = append(od, v)
}
}
}
// 对报价表进行排序,由低到高
sort.Sort(od)
// 获取物品信息
for i, v := range wfapiio.Include.Item.ItemsInSet {
if v.URLName == cnName {
it = &wfapiio.Include.Item.ItemsInSet[i]
n = v.En.ItemName
return
}
}
it = &wfapiio.Include.Item.ItemsInSet[0]
n = wfapiio.Include.Item.ItemsInSet[0].En.ItemName
return
}
func newwm() (wmitems map[string]items, itemNames []string) {
var itemapi wfAPIItem // WarFrame市场的数据实例
data, err := web.RequestDataWithHeaders(&http.Client{}, wfitemurl, "GET", func(request *http.Request) error {
request.Header.Add("Accept", "application/json")
request.Header.Add("Language", "zh-hans")
return nil
}, nil)
if err != nil {
panic(err)
}
err = json.Unmarshal(data, &itemapi)
if err != nil {
panic(err)
}
wmitems = make(map[string]items, len(itemapi.Payload.Items)*4)
itemNames = make([]string, len(itemapi.Payload.Items))
for i, v := range itemapi.Payload.Items {
wmitems[v.ItemName] = v
itemNames[i] = v.ItemName
}
return
}

404
plugin/warframeapi/main.go Normal file
View File

@@ -0,0 +1,404 @@
// Package warframeapi 星际战甲
package warframeapi
import (
"fmt"
"strconv"
"strings"
"time"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/lithammer/fuzzysearch/fuzzy"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var wmitems, itemNames = newwm()
func init() {
eng := control.Register("warframeapi", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "星际战甲",
Help: "- wf时间同步\n" +
"- [金星|地球|火卫二]平原时间\n" +
"- .wm [物品名称]\n" +
"- wf仲裁\n" +
"- wf警报\n" +
"- wf每日特惠",
PrivateDataFolder: "warframeapi",
})
// 获取具体的平原时间, 在触发后, 会启动持续时间按5分钟的时间更新模拟, 以此处理短时间内请求时, 时间不会变化的问题
eng.OnSuffix("平原时间").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
if !gameWorld.hasSync() { // 没有进行同步,就拉取一次服务器状态
wfapi, err := newwfapi()
if err != nil {
ctx.SendChain(message.Text("ERROR: 获取服务器时间失败"))
}
gameWorld.refresh(&wfapi)
}
var msg any
switch ctx.State["args"].(string) {
case "地球", "夜灵":
msg = gameWorld.w[0]
case "金星", "奥布山谷":
msg = gameWorld.w[1]
case "魔胎之境", "火卫二", "火卫":
msg = gameWorld.w[2]
default:
msg = "ERROR: 平原不存在"
}
ctx.SendChain(message.Text(msg))
// 是否正在进行同步,没有就开启同步,有就不开启
if !gameWorld.hasSync() {
if gameWorld.setsync() {
go func() {
// 30*10=300=5分钟
for i := 0; i < 30; i++ {
time.Sleep(10 * time.Second)
gameWorld.update() // 5分钟内每隔10秒更新一下时间
}
// 5分钟时间同步结束
_ = gameWorld.resetsync()
}()
}
}
})
eng.OnFullMatch("wf警报").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
wfapi, err := newwfapi()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
// 如果返回的wfapi中, 警报数量>0
if len(wfapi.Alerts) > 0 {
msgs := make(message.Message, len(wfapi.Alerts))
// 遍历警报数据, 打印警报信息
for i, v := range wfapi.Alerts {
msgs[i] = ctxext.FakeSenderForwardNode(ctx, message.Text(
"激活: ", v.Active,
"\n节点: ", v.Mission.Node,
"\n类型: ", v.Mission.Type,
"\n敌人等级: ", v.Mission.MinEnemyLevel, "~", v.Mission.MaxEnemyLevel,
"\n奖励: ", v.Mission.Reward.AsString,
"\n剩余时间:", v.Eta))
}
ctx.SendChain(msgs...)
}
})
//TODO:订阅功能-等待重做
// eng.OnRegex(`^(订阅|取消订阅)(.*)平原(.*)$`).SetBlock(true).
// Handle(func(ctx *zero.Ctx) {
// args := ctx.State["regex_matched"].([]string)
// var isEnable bool
// if args[1] == "订阅" {
// isEnable = true
// }
// updateWFAPI()
// status := false
// switch args[3] {
// case "fass", "白天", "温暖":
// status = true
// }
// switch args[2] {
// case "金星", "奥布山谷":
// //sublist = append(sublist, subList{ctx.Event.GroupID, ctx.Event.UserID, 1, status, false})
// if isEnable {
// addUseSub(ctx.Event.UserID, ctx.Event.GroupID, 1, status)
// } else {
// removeUseSub(ctx.Event.UserID, ctx.Event.GroupID, 1)
// }
// ctx.SendChain(
// message.At(ctx.Event.UserID),
// message.Text("已成功", args[1]),
// message.Text(gameTimes[1].Name),
// message.Text(status),
// )
// case "地球", "夜灵":
// if isEnable {
// addUseSub(ctx.Event.UserID, ctx.Event.GroupID, 0, status)
// } else {
// removeUseSub(ctx.Event.UserID, ctx.Event.GroupID, 0)
// }
// ctx.SendChain(
// message.At(ctx.Event.UserID),
// message.Text("已成功", args[1]),
// message.Text(gameTimes[0].Name),
// message.Text(status),
// )
// case "魔胎之境", "火卫", "火卫二":
// if isEnable {
// addUseSub(ctx.Event.UserID, ctx.Event.GroupID, 2, status)
// } else {
// removeUseSub(ctx.Event.UserID, ctx.Event.GroupID, 2)
// }
// ctx.SendChain(
// message.At(ctx.Event.UserID),
// message.Text("已成功", args[1]),
// message.Text(gameTimes[2].Name),
// message.Text(status),
// )
// default:
// ctx.SendChain(message.Text("ERROR: 平原不存在"))
// return
// }
// })
// eng.OnFullMatch(`wf订阅检测`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
// rwm.Lock()
// var msg []message.MessageSegment
// for i, v := range gameTimes {
// nt := time.Until(v.NextTime).Seconds()
// switch {
// case nt < 0:
// if v.Status {
// v.NextTime = v.NextTime.Add(time.Duration(v.NightTime) * time.Second)
// } else {
// v.NextTime = v.NextTime.Add(time.Duration(v.DayTime) * time.Second)
// }
// v.Status = !v.Status
//
// msg = callUser(i, v.Status, 0)
// case nt < float64(5)*60:
// msg = callUser(i, !v.Status, 5)
// case nt < float64(15)*60:
// if i == 2 && !v.Status {
// return
// }
// msg = callUser(i, !v.Status, 15)
// }
// }
// rwm.Unlock()
// if msg != nil && len(msg) > 0 {
// ctx.SendChain(msg...)
// }
// })
eng.OnFullMatch("wf仲裁").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 通过wfapi获取仲裁信息
wfapi, err := newwfapi()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text(
"节点: ", wfapi.Arbitration.Node,
"\n类型: ", wfapi.Arbitration.Type,
"\n阵营: ", wfapi.Arbitration.Enemy,
"\n剩余时间: ", int(wfapi.Arbitration.Expiry.Sub(time.Now().UTC()).Minutes()), "m",
))
})
eng.OnFullMatch("wf每日特惠").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
wfapi, err := newwfapi()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
if len(wfapi.DailyDeals) > 0 {
msgs := make(message.Message, len(wfapi.DailyDeals))
for i, dd := range wfapi.DailyDeals {
msgs[i] = ctxext.FakeSenderForwardNode(ctx, message.Text(
"物品: ", dd.Item,
"\n价格: ", dd.OriginalPrice, "→", dd.SalePrice,
"\n数量: (", dd.Total, "/", dd.Sold, ")",
"\n时间: ", dd.Eta,
))
}
ctx.SendChain(msgs...)
}
})
// eng.OnRegex(`^入侵$`).SetBlock(true).
// Handle(func(ctx *zero.Ctx) {
// updateWFAPI(ctx)
// for _, dd := range wfapi.dailyDeals {
// imagebuild.DrawTextSend([]string{
// "节点:" + wfapi.arbitration.Node,
// "类型:" + wfapi.arbitration.Type,
// "阵营:" + wfapi.arbitration.Enemy,
// "剩余时间:" + fmt.Sprint(int(wfapi.arbitration.Expiry.Sub(time.Now().UTC()).Minutes())) + "m",
// }, ctx)
// }
// })
eng.OnFullMatch("wf时间同步").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
wfapi, err := newwfapi()
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
gameWorld.refresh(&wfapi)
ctx.SendChain(message.Text("已拉取服务器时间并同步到本地模拟"))
})
// 根据名称从Warframe市场查询物品售价
eng.OnPrefix(".wm ").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
// 根据输入的名称, 从游戏物品名称列表中进行模糊搜索
sol := fuzzy.FindNormalizedFold(ctx.State["args"].(string), itemNames)
// 物品名称
var name string
// 根据搜搜结果, 打印找到的物品
switch len(sol) {
case 0: // 没有搜索到任何东西
ctx.SendChain(message.Text("无法查询到该物品"))
return
case 1: // 如果只搜索到了一个
name = sol[0]
default: // 如果搜搜到了多个
sb := strings.Builder{}
if len(sol) > 25 {
sb.WriteString("数量过多, 只显示前25\n")
sol = sol[:25]
}
sb.WriteString("[0] ")
sb.WriteString(sol[0])
for i, v := range sol[1:] {
sb.WriteString("\n[")
sb.WriteString(strconv.Itoa(i + 1))
sb.WriteString("] ")
sb.WriteString(v)
}
ctx.SendChain(
ctxext.FakeSenderForwardNode(ctx, message.Text("包含多个结果, 请输入编号查看(30s内),输入c直接结束会话")),
ctxext.FakeSenderForwardNode(ctx, message.Text(&sb)),
)
itemIndex := getitemnameindex(ctx)
if itemIndex < 0 {
return
}
if itemIndex >= len(sol) || itemIndex < 0 {
ctx.SendChain(message.Text("ERROR: 编号超出范围"))
return
}
name = sol[itemIndex]
}
onlymaxrank := false
msgs := message.Message{}
GETWM:
if onlymaxrank {
msgs = msgs[:0]
}
sells, iteminfo, txt, err := getitemsorder(wmitems[name].URLName, onlymaxrank)
if !onlymaxrank {
if iteminfo.ZhHans.WikiLink == "" {
msgs = append(msgs, ctxext.FakeSenderForwardNode(ctx,
message.Image("https://warframe.market/static/assets/"+wmitems[name].Thumb),
message.Text("\n", wmitems[name].ItemName)))
} else {
msgs = append(msgs, ctxext.FakeSenderForwardNode(ctx,
message.Image("https://warframe.market/static/assets/"+wmitems[name].Thumb),
message.Text("\n", wmitems[name].ItemName, "\nwiki: ", iteminfo.ZhHans.WikiLink)))
}
}
if err != nil {
msgs = append(msgs, ctxext.FakeSenderForwardNode(ctx, message.Text("ERROR: ", err)))
ctx.SendChain(msgs...)
return
}
if sells == nil {
msgs = append(msgs, ctxext.FakeSenderForwardNode(ctx, message.Text("无可购买对象")))
ctx.SendChain(msgs...)
return
}
ismod := iteminfo.ModMaxRank != 0
max := 5
if len(sells) < max {
max = len(sells)
}
sb := strings.Builder{}
if ismod {
if !onlymaxrank {
msgs = append(msgs, ctxext.FakeSenderForwardNode(ctx, message.Text("请输入编号选择, 或输入r获取满级报价(30s内)\n输入c直接结束会话")))
} else {
msgs = append(msgs, ctxext.FakeSenderForwardNode(ctx, message.Text("请输入编号选择(30s内)\n输入c直接结束会话")))
}
for i := 0; i < max; i++ {
// msgs = append(msgs, ctxext.FakeSenderForwardNode(ctx,
// message.Text(fmt.Sprintf("[%d] (Rank:%d/%d) %dP - %s\n", i, sells[i].ModRank, iteminfo.ModMaxRank, sells[i].Platinum, sells[i].User.IngameName))))
sb.WriteString(fmt.Sprintf("[%d] (Rank:%d/%d) %dP - %s\n", i, sells[i].ModRank, iteminfo.ModMaxRank, sells[i].Platinum, sells[i].User.IngameName))
}
} else {
for i := 0; i < max; i++ {
// msgs = append(msgs, ctxext.FakeSenderForwardNode(ctx,
// message.Text(fmt.Sprintf("[%d] %dP -%s\n", i, sells[i].Platinum, sells[i].User.IngameName))))
sb.WriteString(fmt.Sprintf("[%d] %dP -%s\n", i, sells[i].Platinum, sells[i].User.IngameName))
}
}
msgs = append(msgs, ctxext.FakeSenderForwardNode(ctx, message.Text(&sb)))
ctx.SendChain(msgs...)
for i := 0; i < 3; i++ {
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession()).Next()
select {
case <-time.After(time.Second * 30):
ctx.SendChain(message.Text("会话已结束!"))
return
case e := <-next:
msg := e.Event.Message.ExtractPlainText()
// 重新获取报价
if msg == "r" {
onlymaxrank = true
goto GETWM
}
// 主动结束会话
if msg == "c" {
ctx.SendChain(message.Text("会话已结束!"))
return
}
i, err := strconv.Atoi(msg)
if err != nil {
ctx.SendChain(message.Text("请输入数字! (输入c结束会话)"))
continue
}
if ismod {
ctx.SendChain(message.Text("/w ", sells[i].User.IngameName, " Hi! I want to buy: ", txt, "(Rank:", sells[i].ModRank, ") for ", sells[i].Platinum, " platinum. (warframe.market)"))
} else {
ctx.SendChain(message.Text("/w ", sells[i].User.IngameName, " Hi! I want to buy: ", txt, " for ", sells[i].Platinum, " platinum. (warframe.market)"))
}
return
}
}
})
}
// 获取搜索结果中的物品具体名称index的FutureEvent
//
// 传入ctx和一个递归次数上限,返回一个int
// 如果为返回内容为负, 说明
// -1 会话超时
// -2 主动结束
// -3 连续3次错误
func getitemnameindex(ctx *zero.Ctx) int {
recv, cancel := zero.NewFutureEvent("message", 999, false, ctx.CheckSession()).Repeat()
defer cancel()
for i := 0; i < 3; i++ {
select {
case <-time.After(time.Second * 30):
// 超时15秒处理
ctx.SendChain(message.Text("会话已超时!"))
return -1
case e := <-recv:
msg := e.Event.Message.ExtractPlainText()
// 输入c主动结束的处理
if msg == "c" {
ctx.SendChain(message.Text("会话已结束!"))
return -2
}
// 尝试对输入进行数字转换
num, err := strconv.Atoi(msg)
if err != nil {
ctx.SendChain(message.Text("请输入数字! (输入c结束会话)"))
continue
}
return num
}
}
ctx.SendChain(message.Text("连续输入错误, 会话已结束!"))
return -3
}

630
plugin/warframeapi/types.go Normal file
View File

@@ -0,0 +1,630 @@
package warframeapi
import "time"
type wfapi struct {
Timestamp time.Time `json:"timestamp"`
News []news `json:"news"`
Events []events `json:"events"`
Alerts []alerts `json:"alerts"`
Sortie sortie `json:"sortie"`
SyndicateMissions []syndicateMissions `json:"syndicateMissions"`
Fissures []fissures `json:"fissures"`
GlobalUpgrades []interface{} `json:"globalUpgrades"`
FlashSales []flashSales `json:"flashSales"`
Invasions []invasions `json:"invasions"`
DarkSectors []interface{} `json:"darkSectors"`
VoidTrader voidTrader `json:"voidTrader"`
DailyDeals []dailyDeals `json:"dailyDeals"`
Simaris simaris `json:"simaris"`
ConclaveChallenges []conclaveChallenges `json:"conclaveChallenges"`
PersistentEnemies []interface{} `json:"persistentEnemies"`
EarthCycle earthCycle `json:"earthCycle"`
CetusCycle cetusCycle `json:"cetusCycle"`
CambionCycle cambionCycle `json:"cambionCycle"`
ZarimanCycle zarimanCycle `json:"zarimanCycle"`
WeeklyChallenges []interface{} `json:"weeklyChallenges"`
ConstructionProgress constructionProgress `json:"constructionProgress"`
VallisCycle vallisCycle `json:"vallisCycle"`
Nightwave nightwave `json:"nightwave"`
Kuva []interface{} `json:"kuva"`
Arbitration arbitration `json:"arbitration"`
SentientOutposts sentientOutposts `json:"sentientOutposts"`
SteelPath steelPath `json:"steelPath"`
VaultTrader vaultTrader `json:"vaultTrader"`
}
type translations struct {
En string `json:"en"`
Fr string `json:"fr"`
It string `json:"it"`
De string `json:"de"`
Es string `json:"es"`
Pt string `json:"pt"`
Ru string `json:"ru"`
Pl string `json:"pl"`
Uk string `json:"uk"`
Tr string `json:"tr"`
Ja string `json:"ja"`
Zh string `json:"zh"`
Ko string `json:"ko"`
Tc string `json:"tc"`
}
type news struct {
ID string `json:"id"`
Message string `json:"message"`
Link string `json:"link"`
ImageLink string `json:"imageLink"`
Priority bool `json:"priority"`
Date time.Time `json:"date"`
Eta string `json:"eta"`
Update bool `json:"update"`
PrimeAccess bool `json:"primeAccess"`
Stream bool `json:"stream"`
Translations translations `json:"translations"`
AsString string `json:"asString"`
}
type metadata struct {
}
type nextAlt struct {
Expiry time.Time `json:"expiry"`
Activation time.Time `json:"activation"`
}
type events struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
StartString string `json:"startString"`
Expiry time.Time `json:"expiry"`
Active bool `json:"active"`
MaximumScore int `json:"maximumScore"`
CurrentScore int `json:"currentScore"`
SmallInterval interface{} `json:"smallInterval"`
LargeInterval interface{} `json:"largeInterval"`
Faction string `json:"faction"`
Description string `json:"description"`
Tooltip string `json:"tooltip"`
Node string `json:"node"`
ConcurrentNodes []interface{} `json:"concurrentNodes"`
Rewards []interface{} `json:"rewards"`
Expired bool `json:"expired"`
InterimSteps []interface{} `json:"interimSteps"`
ProgressSteps []interface{} `json:"progressSteps"`
IsPersonal bool `json:"isPersonal"`
RegionDrops []interface{} `json:"regionDrops"`
ArchwingDrops []interface{} `json:"archwingDrops"`
AsString string `json:"asString"`
Metadata metadata `json:"metadata"`
CompletionBonuses []interface{} `json:"completionBonuses"`
AltExpiry time.Time `json:"altExpiry"`
AltActivation time.Time `json:"altActivation"`
NextAlt nextAlt `json:"nextAlt"`
}
type variants struct {
MissionType string `json:"missionType"`
Modifier string `json:"modifier"`
ModifierDescription string `json:"modifierDescription"`
Node string `json:"node"`
}
type sortie struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
StartString string `json:"startString"`
Expiry time.Time `json:"expiry"`
Active bool `json:"active"`
RewardPool string `json:"rewardPool"`
Variants []variants `json:"variants"`
Boss string `json:"boss"`
Faction string `json:"faction"`
Expired bool `json:"expired"`
Eta string `json:"eta"`
}
type jobs struct {
ID string `json:"id"`
RewardPool []string `json:"rewardPool"`
Type string `json:"type"`
EnemyLevels []int `json:"enemyLevels"`
StandingStages []int `json:"standingStages"`
MinMR int `json:"minMR"`
Expiry time.Time `json:"expiry"`
TimeBound string `json:"timeBound,omitempty"`
}
type syndicateMissions struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
StartString string `json:"startString"`
Expiry time.Time `json:"expiry"`
Active bool `json:"active"`
Syndicate string `json:"syndicate"`
SyndicateKey string `json:"syndicateKey"`
Nodes []interface{} `json:"nodes"`
Jobs []jobs `json:"jobs"`
Eta string `json:"eta"`
}
type fissures struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
StartString string `json:"startString"`
Expiry time.Time `json:"expiry"`
Active bool `json:"active"`
Node string `json:"node"`
MissionType string `json:"missionType"`
MissionKey string `json:"missionKey"`
Enemy string `json:"enemy"`
EnemyKey string `json:"enemyKey"`
NodeKey string `json:"nodeKey"`
Tier string `json:"tier"`
TierNum int `json:"tierNum"`
Expired bool `json:"expired"`
Eta string `json:"eta"`
IsStorm bool `json:"isStorm"`
}
type flashSales struct {
Item string `json:"item"`
Expiry time.Time `json:"expiry"`
Activation time.Time `json:"activation"`
Discount int `json:"discount"`
RegularOverride int `json:"regularOverride"`
PremiumOverride int `json:"premiumOverride"`
IsShownInMarket bool `json:"isShownInMarket"`
IsFeatured bool `json:"isFeatured"`
IsPopular bool `json:"isPopular"`
ID string `json:"id"`
Expired bool `json:"expired"`
Eta string `json:"eta"`
}
type countedItems struct {
Count int `json:"count"`
Type string `json:"type"`
Key string `json:"key"`
}
type attackerReward struct {
Items []interface{} `json:"items"`
CountedItems []countedItems `json:"countedItems"`
Credits int `json:"credits"`
AsString string `json:"asString"`
ItemString string `json:"itemString"`
Thumbnail string `json:"thumbnail"`
Color int `json:"color"`
}
type reward struct {
Items []interface{} `json:"items"`
CountedItems []countedItems `json:"countedItems"`
Credits int `json:"credits"`
AsString string `json:"asString"`
ItemString string `json:"itemString"`
Thumbnail string `json:"thumbnail"`
Color int `json:"color"`
}
type attacker struct {
Reward reward `json:"reward"`
Faction string `json:"faction"`
FactionKey string `json:"factionKey"`
}
type defenderReward struct {
Items []interface{} `json:"items"`
CountedItems []countedItems `json:"countedItems"`
Credits int `json:"credits"`
AsString string `json:"asString"`
ItemString string `json:"itemString"`
Thumbnail string `json:"thumbnail"`
Color int `json:"color"`
}
type defender struct {
Reward reward `json:"reward"`
Faction string `json:"faction"`
FactionKey string `json:"factionKey"`
}
type invasions struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
StartString string `json:"startString"`
Node string `json:"node"`
NodeKey string `json:"nodeKey"`
Desc string `json:"desc"`
AttackerReward attackerReward `json:"attackerReward"`
AttackingFaction string `json:"attackingFaction"`
Attacker attacker `json:"attacker"`
DefenderReward defenderReward `json:"defenderReward"`
DefendingFaction string `json:"defendingFaction"`
Defender defender `json:"defender"`
VsInfestation bool `json:"vsInfestation"`
Count int `json:"count"`
RequiredRuns int `json:"requiredRuns"`
Completion float64 `json:"completion"`
Completed bool `json:"completed"`
Eta string `json:"eta"`
RewardTypes []string `json:"rewardTypes"`
}
type voidTrader struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
StartString string `json:"startString"`
Expiry time.Time `json:"expiry"`
Active bool `json:"active"`
Character string `json:"character"`
Location string `json:"location"`
Inventory []interface{} `json:"inventory"`
PsID string `json:"psId"`
EndString string `json:"endString"`
InitialStart time.Time `json:"initialStart"`
Schedule []interface{} `json:"schedule"`
}
type dailyDeals struct {
Item string `json:"item"`
Expiry time.Time `json:"expiry"`
Activation time.Time `json:"activation"`
OriginalPrice int `json:"originalPrice"`
SalePrice int `json:"salePrice"`
Total int `json:"total"`
Sold int `json:"sold"`
ID string `json:"id"`
Eta string `json:"eta"`
Discount int `json:"discount"`
}
type simaris struct {
Target string `json:"target"`
IsTargetActive bool `json:"isTargetActive"`
AsString string `json:"asString"`
}
type conclaveChallenges struct {
ID string `json:"id"`
Expiry time.Time `json:"expiry"`
Activation time.Time `json:"activation"`
Amount int `json:"amount"`
Mode string `json:"mode"`
Category string `json:"category"`
Eta string `json:"eta"`
Expired bool `json:"expired"`
Daily bool `json:"daily"`
RootChallenge bool `json:"rootChallenge"`
EndString string `json:"endString"`
Description string `json:"description"`
Title string `json:"title"`
Standing int `json:"standing"`
AsString string `json:"asString"`
}
type earthCycle struct {
ID string `json:"id"`
Expiry time.Time `json:"expiry"`
Activation time.Time `json:"activation"`
IsDay bool `json:"isDay"`
State string `json:"state"`
TimeLeft string `json:"timeLeft"`
}
type cetusCycle struct {
ID string `json:"id"`
Expiry time.Time `json:"expiry"`
Activation time.Time `json:"activation"`
IsDay bool `json:"isDay"`
State string `json:"state"`
TimeLeft string `json:"timeLeft"`
IsCetus bool `json:"isCetus"`
ShortString string `json:"shortString"`
}
type cambionCycle struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
Expiry time.Time `json:"expiry"`
TimeLeft string `json:"timeLeft"`
Active string `json:"active"`
}
type zarimanCycle struct {
ID string `json:"id"`
BountiesEndDate time.Time `json:"bountiesEndDate"`
Expiry time.Time `json:"expiry"`
Activation time.Time `json:"activation"`
IsCorpus bool `json:"isCorpus"`
State string `json:"state"`
TimeLeft string `json:"timeLeft"`
ShortString string `json:"shortString"`
}
type constructionProgress struct {
ID string `json:"id"`
FomorianProgress string `json:"fomorianProgress"`
RazorbackProgress string `json:"razorbackProgress"`
UnknownProgress string `json:"unknownProgress"`
}
type vallisCycle struct {
ID string `json:"id"`
Expiry time.Time `json:"expiry"`
IsWarm bool `json:"isWarm"`
State string `json:"state"`
Activation time.Time `json:"activation"`
TimeLeft string `json:"timeLeft"`
ShortString string `json:"shortString"`
}
type params struct {
}
type activeChallenges struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
StartString string `json:"startString"`
Expiry time.Time `json:"expiry"`
Active bool `json:"active"`
IsDaily bool `json:"isDaily,omitempty"`
IsElite bool `json:"isElite"`
Desc string `json:"desc"`
Title string `json:"title"`
Reputation int `json:"reputation"`
}
type nightwave struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
StartString string `json:"startString"`
Expiry time.Time `json:"expiry"`
Active bool `json:"active"`
Season int `json:"season"`
Tag string `json:"tag"`
Phase int `json:"phase"`
Params params `json:"params"`
PossibleChallenges []interface{} `json:"possibleChallenges"`
ActiveChallenges []activeChallenges `json:"activeChallenges"`
RewardTypes []string `json:"rewardTypes"`
}
type arbitration struct {
Activation time.Time `json:"activation"`
Expiry time.Time `json:"expiry"`
Enemy string `json:"enemy"`
Type string `json:"type"`
Archwing bool `json:"archwing"`
Sharkwing bool `json:"sharkwing"`
Node string `json:"node"`
NodeKey string `json:"nodeKey"`
TypeKey string `json:"typeKey"`
ID string `json:"id"`
Expired bool `json:"expired"`
}
type mission struct {
Node string `json:"node"`
Faction string `json:"faction"`
Type string `json:"type"`
}
type sentientOutposts struct {
Mission mission `json:"mission"`
Activation time.Time `json:"activation"`
Expiry time.Time `json:"expiry"`
Active bool `json:"active"`
ID string `json:"id"`
}
type currentReward struct {
Name string `json:"name"`
Cost int `json:"cost"`
}
type rotation struct {
Name string `json:"name"`
Cost int `json:"cost"`
}
type evergreens struct {
Name string `json:"name"`
Cost int `json:"cost"`
}
type incursions struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
Expiry time.Time `json:"expiry"`
}
type steelPath struct {
CurrentReward currentReward `json:"currentReward"`
Activation time.Time `json:"activation"`
Expiry time.Time `json:"expiry"`
Remaining string `json:"remaining"`
Rotation []rotation `json:"rotation"`
Evergreens []evergreens `json:"evergreens"`
Incursions incursions `json:"incursions"`
}
type inventory struct {
Item string `json:"item"`
Ducats int `json:"ducats"`
Credits interface{} `json:"credits"`
}
type schedule struct {
Expiry time.Time `json:"expiry"`
Item string `json:"item"`
}
type vaultTrader struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
StartString string `json:"startString"`
Expiry time.Time `json:"expiry"`
Active bool `json:"active"`
Character string `json:"character"`
Location string `json:"location"`
Inventory []inventory `json:"inventory"`
PsID string `json:"psId"`
EndString string `json:"endString"`
InitialStart time.Time `json:"initialStart"`
Completed bool `json:"completed"`
Schedule []schedule `json:"schedule"`
}
type alerts struct {
ID string `json:"id"`
Activation time.Time `json:"activation"`
StartString string `json:"startString"`
Expiry time.Time `json:"expiry"`
Active bool `json:"active"`
Mission struct {
Description string `json:"description"`
Node string `json:"node"`
NodeKey string `json:"nodeKey"`
Type string `json:"type"`
TypeKey string `json:"typeKey"`
Faction string `json:"faction"`
Reward struct {
Items []interface{} `json:"items"`
CountedItems []struct {
Count int `json:"count"`
Type string `json:"type"`
Key string `json:"key"`
} `json:"countedItems"`
Credits int `json:"credits"`
AsString string `json:"asString"`
ItemString string `json:"itemString"`
Thumbnail string `json:"thumbnail"`
Color int `json:"color"`
} `json:"reward"`
MinEnemyLevel int `json:"minEnemyLevel"`
MaxEnemyLevel int `json:"maxEnemyLevel"`
MaxWaveNum int `json:"maxWaveNum"`
Nightmare bool `json:"nightmare"`
ArchwingRequired bool `json:"archwingRequired"`
IsSharkwing bool `json:"isSharkwing"`
LevelOverride string `json:"levelOverride"`
EnemySpec string `json:"enemySpec"`
AdvancedSpawners []interface{} `json:"advancedSpawners"`
RequiredItems []interface{} `json:"requiredItems"`
LevelAuras []interface{} `json:"levelAuras"`
} `json:"mission"`
Eta string `json:"eta"`
RewardTypes []string `json:"rewardTypes"`
Tag string `json:"tag"`
}
type wfAPIItem struct {
Payload payload `json:"payload"`
}
type items struct {
URLName string `json:"url_name"`
Thumb string `json:"thumb"`
ItemName string `json:"item_name"`
ID string `json:"id"`
Vaulted bool `json:"vaulted,omitempty"`
}
type payload struct {
Items []items `json:"items"`
Orders orders `json:"orders"`
}
type wfAPIItemsOrders struct {
Payload payload `json:"payload"`
Include include `json:"include"`
}
type user struct {
IngameName string `json:"ingame_name"`
LastSeen time.Time `json:"last_seen"`
Reputation int `json:"reputation"`
Region string `json:"region"`
ID string `json:"id"`
Avatar interface{} `json:"avatar"`
Status string `json:"status"`
}
type orders []struct {
OrderType string `json:"order_type"`
LastUpdate time.Time `json:"last_update"`
Region string `json:"region"`
Quantity int `json:"quantity"`
Visible bool `json:"visible"`
CreationDate time.Time `json:"creation_date"`
Platinum int `json:"platinum"`
Platform string `json:"platform"`
User user `json:"user"`
ID string `json:"id"`
ModRank int `json:"mod_rank"`
}
func (a orders) Len() int { // 重写 Len() 方法
return len(a)
}
func (a orders) Swap(i, j int) { // 重写 Swap() 方法
a[i], a[j] = a[j], a[i]
}
func (a orders) Less(i, j int) bool { // 重写 Less() 方法, 从大到小排序
return a[i].Platinum < a[j].Platinum
}
type en struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type ru struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type ko struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type fr struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type sv struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type de struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type zhHant struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type zhHans struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type pt struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type es struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type pl struct {
ItemName string `json:"item_name"`
Description string `json:"description"`
WikiLink string `json:"wiki_link"`
Drop []interface{} `json:"drop"`
}
type itemsInSet struct {
Icon string `json:"icon"`
URLName string `json:"url_name"`
SubIcon string `json:"sub_icon"`
ModMaxRank int `json:"mod_max_rank"`
Thumb string `json:"thumb"`
SetRoot bool `json:"set_root"`
QuantityForSet int `json:"quantity_for_set,omitempty"`
ID string `json:"id"`
TradingTax int `json:"trading_tax"`
Tags []string `json:"tags"`
MasteryLevel int `json:"mastery_level"`
Ducats int `json:"ducats"`
IconFormat string `json:"icon_format"`
En en `json:"en"`
Ru ru `json:"ru"`
Ko ko `json:"ko"`
Fr fr `json:"fr"`
Sv sv `json:"sv"`
De de `json:"de"`
ZhHant zhHant `json:"zh-hant"`
ZhHans zhHans `json:"zh-hans"`
Pt pt `json:"pt"`
Es es `json:"es"`
Pl pl `json:"pl"`
}
type item struct {
ID string `json:"id"`
ItemsInSet []itemsInSet `json:"items_in_set"`
}
type include struct {
Item item `json:"item"`
}

108
plugin/warframeapi/world.go Normal file
View File

@@ -0,0 +1,108 @@
package warframeapi
import (
"strings"
"sync"
"sync/atomic"
"time"
"github.com/davidscholberg/go-durationfmt"
)
// 游戏时间模拟
type timezone struct {
sync.RWMutex `json:"-"`
Name string `json:"name"` // 时间名称
NextTime time.Time `json:"time"` // 下次更新时间
IsDay bool `json:"status"` // 状态
DayDesc string `json:"true_des"` // 状态说明
NightDesc string `json:"false_des"` // 状态说明
DayLen int `json:"day"` // 白天时长
NightLen int `json:"night"` // 夜间时长
}
type world struct {
w [3]*timezone
hassync uintptr
}
var gameWorld = newworld()
// String 根据传入的世界编号,获取对应的游戏时间文本
func (t *timezone) String() string {
t.RLock()
defer t.RUnlock()
sb := strings.Builder{}
sb.WriteString("平原时间: ")
if t.IsDay {
sb.WriteString(t.DayDesc)
} else {
sb.WriteString(t.NightDesc)
}
sb.WriteString(", ")
sb.WriteString("下次更新: ")
d := time.Until(t.NextTime)
durStr, _ := durationfmt.Format(d, "%m分%s秒后")
sb.WriteString(durStr)
return sb.String()
}
func newworld() (w world) {
w.w = [3]*timezone{
{Name: "地球平原", DayDesc: "白天", NightDesc: "夜晚", DayLen: 100 * 60, NightLen: 50 * 60},
{Name: "金星平原", DayDesc: "温暖", NightDesc: "寒冷", DayLen: 400, NightLen: 20 * 60},
{Name: "火卫二平原", DayDesc: "fass", NightDesc: "vome", DayLen: 100 * 60, NightLen: 50 * 60},
}
return
}
func (w *world) hasSync() bool {
return atomic.LoadUintptr(&w.hassync) != 0
}
func (w *world) setsync() bool {
return atomic.CompareAndSwapUintptr(&w.hassync, 0, 1)
}
func (w *world) resetsync() bool {
return atomic.CompareAndSwapUintptr(&w.hassync, 1, 0)
}
// 根据API返回内容修正游戏时间
func (w *world) refresh(api *wfapi) {
for _, t := range w.w {
t.Lock()
}
w.w[0].NextTime = api.CetusCycle.Expiry.Local()
w.w[0].IsDay = api.CetusCycle.IsDay
w.w[1].NextTime = api.VallisCycle.Expiry.Local()
w.w[1].IsDay = api.VallisCycle.IsWarm
w.w[2].NextTime = api.CambionCycle.Expiry.Local()
w.w[2].IsDay = api.CambionCycle.Active == "fass"
}
// 游戏时间更新
func (w *world) update() {
if !w.hasSync() {
return
}
for _, t := range w.w {
t.Lock()
// 当前时间对比下一次游戏状态更新时间,看看还剩多少秒
nt := time.Until(t.NextTime).Seconds()
// 已经过了游戏时间状态更新时间
if nt < 0 {
// 更新游戏状态,如果是白天就切换到晚上,反之亦然
if t.IsDay {
// 计算下次的晚上更新时间
t.NextTime = t.NextTime.Add(time.Duration(t.NightLen) * time.Second)
} else {
// 计算下次的白天更新时间
t.NextTime = t.NextTime.Add(time.Duration(t.DayLen) * time.Second)
}
}
t.Unlock()
}
}

View File

@@ -14,10 +14,10 @@ import (
"github.com/FloatTech/AnimeAPI/tl"
"github.com/Coloured-glaze/gg"
"github.com/FloatTech/floatbox/binary"
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/img/writer"
"github.com/FloatTech/gg"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"