mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-11 09:40:25 +00:00
Compare commits
23 Commits
v1.7.0-bet
...
v1.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68386910c4 | ||
|
|
1734f1f7d4 | ||
|
|
86b87c2b4e | ||
|
|
e9eb4c5602 | ||
|
|
6474b36ccd | ||
|
|
107149892c | ||
|
|
f1dba97922 | ||
|
|
bc3c4303be | ||
|
|
f7a61ed0ee | ||
|
|
107b38e2f5 | ||
|
|
0d85fa04e1 | ||
|
|
1d8f5a7869 | ||
|
|
5e93368e57 | ||
|
|
56e931665e | ||
|
|
e5b2b369e3 | ||
|
|
58cf08fc39 | ||
|
|
c18f9b8b72 | ||
|
|
0df465e1c6 | ||
|
|
8b010321d5 | ||
|
|
e1591c44b6 | ||
|
|
cc26eb1332 | ||
|
|
366c7acb90 | ||
|
|
d8cb5206e8 |
38
README.md
38
README.md
@@ -9,7 +9,7 @@
|
||||
ZeroBot-Plugin 是 ZeroBot 的 实用插件合集<br><br>
|
||||
|
||||
|
||||
<img src="http://cmoe.azurewebsites.net/cmoe?name=ZeroBot-Plugin&theme=r34" /><br>
|
||||
<img src="https://counter.seku.su/cmoe?name=ZeroBot-Plugin&theme=r34" /><br>
|
||||
|
||||
[](https://github.com/Mrs4s/MiraiGo)
|
||||
[](https://github.com/takayama-lily/oicq)
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
[](https://goreportcard.com/badge/github.com/FloatTech/ZeroBot-Plugin)
|
||||
[](https://t.me/zerobotplugin)
|
||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||
[](https://github.com/wdvxdr1123/ZeroBot)
|
||||
[](https://raw.githubusercontent.com/FloatTech/ZeroBot-Plugin/master/LICENSE)
|
||||
[](https://jq.qq.com/?_wv=1027&k=QMb7x1mM)
|
||||
[](https://t.me/zerobotplugin)
|
||||
@@ -93,7 +93,7 @@ zerobot [-h] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w] [-c|s
|
||||
|
||||
> 插件的优先级为`import`的先后顺序。
|
||||
|
||||
> `webui`默认禁用不编译,打开后会增加程序体积并使控制台日志格式紊乱。
|
||||
> `webui`默认禁用不编译,打开后会增加程序体积。
|
||||
|
||||
<details>
|
||||
<summary>插件控制</summary>
|
||||
@@ -436,11 +436,11 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>百度一下</summary>
|
||||
<summary>百度百科</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/baidu"`
|
||||
|
||||
- [x] 百度下[xxx]
|
||||
- [x] 百度/百科[xxx]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -559,7 +559,7 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] b站推送列表
|
||||
|
||||
- [x] 拉取b站推送 (使用job执行定时任务------记录在"@every 10s"触发的指令)
|
||||
- [x] 拉取b站推送 (使用job执行定时任务------记录在"@every 5m"触发的指令)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
@@ -821,6 +821,16 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 来点黑丝/白丝/jk/巨乳/足控/网红
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>一言</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/hitokoto"`
|
||||
|
||||
- [x] 一言[xxx]
|
||||
|
||||
- [x] 系列一言
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>炉石</summary>
|
||||
@@ -1273,6 +1283,22 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 黄油角色[@xxx]
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>steam</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/steam"`
|
||||
|
||||
- [x] steam[添加|删除]订阅xxxxx
|
||||
|
||||
- [x] steam查看订阅
|
||||
|
||||
- [x] steam绑定 api key xxxxxxx
|
||||
|
||||
- [x] 查看apikey
|
||||
|
||||
- [x] 拉取steam订阅 (使用job执行定时任务------记录在"@every 1m"触发的指令)
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>抽塔罗牌</summary>
|
||||
|
||||
13
go.mod
13
go.mod
@@ -4,15 +4,15 @@ go 1.20
|
||||
|
||||
require (
|
||||
github.com/Baidu-AIP/golang-sdk v1.1.1
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230301080805-a8aa0e4cee1f
|
||||
github.com/FloatTech/floatbox v0.0.0-20230301074105-03017a267762
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230316111643-46d40c9d80e3
|
||||
github.com/FloatTech/floatbox v0.0.0-20230316111222-7ffde57284cc
|
||||
github.com/FloatTech/gg v1.1.2
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230215052637-9f7b05520ca9
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230315152233-49741fc994f9
|
||||
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9
|
||||
github.com/FloatTech/sqlite v1.5.7
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230301071613-f2c5c97cec88
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230309054847-f60ce7c0aa73
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230316111343-dd078fa43fe3
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230316111555-2d1ec958de04
|
||||
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
|
||||
@@ -37,7 +37,7 @@ require (
|
||||
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.10
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.11
|
||||
gitlab.com/gomidi/midi/v2 v2.0.25
|
||||
golang.org/x/image v0.3.0
|
||||
golang.org/x/sys v0.4.0
|
||||
@@ -68,6 +68,7 @@ require (
|
||||
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/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||
github.com/pkumza/numcn v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
|
||||
26
go.sum
26
go.sum
@@ -2,24 +2,24 @@ github.com/Baidu-AIP/golang-sdk v1.1.1 h1:RQsAmgDSAkiq22I6n7XJ2t3afgzFeqjY46FGhv
|
||||
github.com/Baidu-AIP/golang-sdk v1.1.1/go.mod h1:bXnGw7xPeKt8aF7UCELKrV6UZ/46spItONK1RQBQj1Y=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230301080805-a8aa0e4cee1f h1:X1qnXmZgogBgTdhpXz3Gl31nHdh5X6EP1F7iKH7JRHg=
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230301080805-a8aa0e4cee1f/go.mod h1:4oFxa7b00MOHULzGm0GN97u/VqCq0J0NvLCF7Puymbs=
|
||||
github.com/FloatTech/floatbox v0.0.0-20230301074105-03017a267762 h1:UU9kPDPm9vRA2/qRTK33fa07AEnE6skjdyyvImAlel0=
|
||||
github.com/FloatTech/floatbox v0.0.0-20230301074105-03017a267762/go.mod h1:J0zCOJayFOyswwCNlqBQGu2q7OPjiu78kjr0oVF+MrM=
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230316111643-46d40c9d80e3 h1:SyXS1YXrRuzO3YVCZB/5gSX7vaFbSMwzN+RXLNNKq5M=
|
||||
github.com/FloatTech/AnimeAPI v1.6.1-0.20230316111643-46d40c9d80e3/go.mod h1:h+22XrJTgcn0m4aM3o1pYo5G0+Mv4v7wW5xvZQ4LabY=
|
||||
github.com/FloatTech/floatbox v0.0.0-20230316111222-7ffde57284cc h1:1yentlIEJImE0rla5xE7o73ZW37eS/byFhPEwx9WYEs=
|
||||
github.com/FloatTech/floatbox v0.0.0-20230316111222-7ffde57284cc/go.mod h1:FwQm6wk+b4wuW54KCKn3zccMX47Q5apnHD/Yakzv0fI=
|
||||
github.com/FloatTech/gg v1.1.2 h1:YolgOYg3uDHc1+g0bLtt6QuRA/pvLn+b9IBCIhOOX88=
|
||||
github.com/FloatTech/gg v1.1.2/go.mod h1:uzPzAeT35egARdRuu+1oyjU3CmTwCceoq3Vvje7LpcI=
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230215052637-9f7b05520ca9 h1:Havq0z/N79KeD50L7ms+Hv8F4Sw98Dt8lXM8jECp04o=
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230215052637-9f7b05520ca9/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs=
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230315152233-49741fc994f9 h1:IzZLuM/fgKclyMaU/Qb1qlLdGrs2FTietkqOWhh07Gw=
|
||||
github.com/FloatTech/imgfactory v0.2.2-0.20230315152233-49741fc994f9/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs=
|
||||
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9 h1:hffajvmQFfP68U6wUwHemPuuwCUoss+SEFfoLYwbGwE=
|
||||
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9/go.mod h1:NBFPhWae4hqVMeG8ELBBnUQkKce3nDjkljVn6PdiUNs=
|
||||
github.com/FloatTech/sqlite v1.5.7 h1:Bvo4LSojcZ6dVtbHrkqvt6z4v8e+sj0G5PSUIvdawsk=
|
||||
github.com/FloatTech/sqlite v1.5.7/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY=
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw=
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230301071613-f2c5c97cec88 h1:jdTWiYXGtYZhxIn9oGYkObNVa8GtJvki+ihsoMlLJPs=
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230301071613-f2c5c97cec88/go.mod h1:8IRMtcWhK4S8QdpStJqXQZtIBgAqUH72Imq3BQ45TWg=
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230309054847-f60ce7c0aa73 h1:dYRnXrzZYh19IabKc419B51yrHut75Fu5R0W79kAHzI=
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230309054847-f60ce7c0aa73/go.mod h1:QwQvA0E+SRcW2kjXt07etth+uunhnCC0fYGhTbl1pgk=
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230316111343-dd078fa43fe3 h1:mCVrTvS2LMNaI2bNA1Gu/B4F5MnfGaTaJClgR6+rhdA=
|
||||
github.com/FloatTech/zbpctrl v1.5.3-0.20230316111343-dd078fa43fe3/go.mod h1:IagyEhY38VcbbQgVRzAM9f9mhaUn90rM5BTPfudtl1g=
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230316111555-2d1ec958de04 h1:ovL+7SAPTBCXy6XNRSdJhNvHtbueWCwEb/jtztmizAc=
|
||||
github.com/FloatTech/zbputils v1.6.2-0.20230316111555-2d1ec958de04/go.mod h1:jUmX4WBgGRcfjGeIobmVao10AHmXtL3gT00qLbx3/yo=
|
||||
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=
|
||||
@@ -154,6 +154,8 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -201,8 +203,8 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm
|
||||
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.10 h1:exmPWNjWtOMLgLQW/svQDybExRJAfDkjpE3S2U6fBOY=
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.10/go.mod h1:y29UIOy0RD3P+0meDNIWRhcJF3jtWPN9xP9hgt/AJAU=
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.11 h1:44Wr6CsCtWlFensK5IhuVCWkosdRw0rA8SygVD8DgoI=
|
||||
github.com/wdvxdr1123/ZeroBot v1.6.11/go.mod h1:y29UIOy0RD3P+0meDNIWRhcJF3jtWPN9xP9hgt/AJAU=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
package banner
|
||||
|
||||
// Version ...
|
||||
var Version = "v1.7.0-beta3"
|
||||
var Version = "v1.7.0"
|
||||
|
||||
// Copyright ...
|
||||
var Copyright = "© 2020 - 2023 FloatTech"
|
||||
|
||||
// Banner ...
|
||||
var Banner = "* OneBot + ZeroBot + Golang\n" +
|
||||
"* Version " + Version + " - 2023-03-09 13:57:06 +0800 CST\n" +
|
||||
"* Version " + Version + " - 2023-03-20 12:27:42 +0800 CST\n" +
|
||||
"* Copyright " + Copyright + ". All Rights Reserved.\n" +
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin"
|
||||
|
||||
15
main.go
15
main.go
@@ -95,6 +95,7 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/github" // 搜索GitHub仓库
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/guessmusic" // 猜歌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/heisi" // 黑丝
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hitokoto" // 一言
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs" // 炉石
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/hyaku" // 百人一首
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/image_finder" // 关键字搜图
|
||||
@@ -130,6 +131,7 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/setutime" // 来份涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shadiao" // 沙雕app
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/shindan" // 测定
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/steam" // steam相关
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tarot" // 抽塔罗牌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou" // 舔狗日记
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tracemoe" // 搜番
|
||||
@@ -232,13 +234,12 @@ func init() {
|
||||
fmt.Println("Usage:")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(0)
|
||||
} else {
|
||||
if *d && !*w {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if *w {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
}
|
||||
}
|
||||
if *d && !*w {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if *w {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
}
|
||||
|
||||
for _, s := range flag.Args() {
|
||||
|
||||
@@ -187,7 +187,13 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
back = imgfactory.Size(back, int(bw*cw/bw), int(bh*cw/bw)).Image()
|
||||
canvas.DrawImage(back, 0, 0)
|
||||
}
|
||||
|
||||
var blurback image.Image
|
||||
bwg := &sync.WaitGroup{}
|
||||
bwg.Add(1)
|
||||
go func() {
|
||||
defer bwg.Done()
|
||||
blurback = imaging.Blur(canvas.Image(), 8)
|
||||
}()
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(5)
|
||||
|
||||
@@ -200,8 +206,8 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
titlecard := gg.NewContext(cardw, titlecardh)
|
||||
|
||||
titlecard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70)
|
||||
bwg.Wait()
|
||||
titlecard.DrawImage(blurback, -70, -70)
|
||||
|
||||
titlecard.DrawRoundedRectangle(1, 1, float64(titlecard.W()-1*2), float64(titlecardh-1*2), 16)
|
||||
titlecard.SetLineWidth(3)
|
||||
@@ -253,8 +259,8 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
basiccard := gg.NewContext(cardw, basiccardh)
|
||||
|
||||
basiccard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70-titlecardh-40)
|
||||
bwg.Wait()
|
||||
basiccard.DrawImage(blurback, -70, -70-titlecardh-40)
|
||||
|
||||
basiccard.DrawRoundedRectangle(1, 1, float64(basiccard.W()-1*2), float64(basiccardh-1*2), 16)
|
||||
basiccard.SetLineWidth(3)
|
||||
@@ -317,7 +323,8 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
diskcard := gg.NewContext(cardw, diskcardh)
|
||||
diskcard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70-titlecardh-40-basiccardh-40)
|
||||
bwg.Wait()
|
||||
diskcard.DrawImage(blurback, -70, -70-titlecardh-40-basiccardh-40)
|
||||
|
||||
diskcard.DrawRoundedRectangle(1, 1, float64(diskcard.W()-1*2), float64(diskcardh-1*2), 16)
|
||||
diskcard.SetLineWidth(3)
|
||||
@@ -335,6 +342,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
if dslen == 1 {
|
||||
diskcard.SetRGBA255(192, 192, 192, 255)
|
||||
diskcard.DrawRoundedRectangle(40, 40, float64(diskcard.W())-40-100, 50, 12)
|
||||
diskcard.ClipPreserve()
|
||||
diskcard.Fill()
|
||||
|
||||
switch {
|
||||
@@ -348,7 +356,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
|
||||
diskcard.DrawRoundedRectangle(40, 40, (float64(diskcard.W())-40-100)*diskstate[0].precent*0.01, 50, 12)
|
||||
diskcard.Fill()
|
||||
|
||||
diskcard.ResetClip()
|
||||
diskcard.SetRGBA255(30, 30, 30, 255)
|
||||
|
||||
fw, _ := diskcard.MeasureString(diskstate[0].name)
|
||||
@@ -392,8 +400,8 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
moreinfocard := gg.NewContext(cardw, moreinfocardh)
|
||||
|
||||
moreinfocard.DrawImage(imaging.Blur(canvas.Image(), 8), -70, -70-titlecardh-40-basiccardh-40-diskcardh-40)
|
||||
bwg.Wait()
|
||||
moreinfocard.DrawImage(blurback, -70, -70-titlecardh-40-basiccardh-40-diskcardh-40)
|
||||
|
||||
moreinfocard.DrawRoundedRectangle(1, 1, float64(moreinfocard.W()-1*2), float64(moreinfocard.H()-1*2), 16)
|
||||
moreinfocard.SetLineWidth(3)
|
||||
@@ -430,7 +438,7 @@ func drawstatus(m *ctrl.Control[*zero.Ctx], uid int64, botname string) (sendimg
|
||||
shadow.Stroke()
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40), float64(cardw), float64(basiccardh), 16)
|
||||
shadow.Stroke()
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40), float64(cardw), float64(basiccardh), 16)
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40), float64(cardw), float64(diskcardh), 16)
|
||||
shadow.Stroke()
|
||||
shadow.DrawRoundedRectangle(70, float64(70+titlecardh+40+basiccardh+40+diskcardh+40), float64(cardw), float64(moreinfocardh), 16)
|
||||
shadow.Stroke()
|
||||
@@ -567,23 +575,21 @@ func diskstate() (stateinfo []*status, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
stateinfo = make([]*status, len(parts))
|
||||
for i, v := range parts {
|
||||
stateinfo = make([]*status, 0, len(parts))
|
||||
for _, v := range parts {
|
||||
mp := v.Mountpoint
|
||||
if strings.HasPrefix(mp, "/snap/") || strings.HasPrefix(mp, "/apex/") {
|
||||
continue
|
||||
}
|
||||
diskusage, err := disk.Usage(mp)
|
||||
usage := ""
|
||||
precent := 0.0
|
||||
if err != nil {
|
||||
usage = err.Error()
|
||||
} else {
|
||||
usage = storagefmt(float64(diskusage.Used)) + " / " + storagefmt(float64(diskusage.Total))
|
||||
precent = math.Round(diskusage.UsedPercent)
|
||||
continue
|
||||
}
|
||||
stateinfo[i] = &status{
|
||||
precent: precent,
|
||||
stateinfo = append(stateinfo, &status{
|
||||
precent: math.Round(diskusage.UsedPercent),
|
||||
name: mp,
|
||||
text: []string{usage},
|
||||
}
|
||||
text: []string{storagefmt(float64(diskusage.Used)) + " / " + storagefmt(float64(diskusage.Total))},
|
||||
})
|
||||
}
|
||||
return stateinfo, nil
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func randText(text ...string) message.MessageSegment {
|
||||
}
|
||||
|
||||
// isAtriSleeping 凌晨0点到6点,ATRI 在睡觉,不回应任何请求
|
||||
func isAtriSleeping(ctx *zero.Ctx) bool {
|
||||
func isAtriSleeping(*zero.Ctx) bool {
|
||||
if now := time.Now().Hour(); now >= 1 && now < 6 {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,27 +1,51 @@
|
||||
// Package baidu 百度一下
|
||||
// Package baidu 百度百科
|
||||
package baidu
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() {
|
||||
control.Register("baidu", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "不会百度吗",
|
||||
Help: "- 百度下[xxx]",
|
||||
}).OnPrefix("百度下").SetBlock(true).Limit(ctxext.LimitByGroup).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
txt := ctx.State["args"].(string)
|
||||
if txt != "" {
|
||||
ctx.SendChain(message.Text("https://buhuibaidu.me/?s=" + url.QueryEscape(txt)))
|
||||
}
|
||||
})
|
||||
const (
|
||||
api = "https://api.a20safe.com/api.php?api=21&key=7d06a110e9e20a684e02934549db1d3d&text=%s" // api地址
|
||||
)
|
||||
|
||||
type result struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data []struct {
|
||||
Content string `json:"content"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func init() { // 主函数
|
||||
en := control.Register("baidu", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Help: "百度百科\n" +
|
||||
"- 百度/百科[关键字]",
|
||||
})
|
||||
en.OnRegex(`^[百度|百科]\s*(.+)$`).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
es, err := web.GetData(fmt.Sprintf(api, ctx.State["regex_matched"].([]string)[1])) // 将网站返回结果赋值
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("出现错误捏:", err))
|
||||
return
|
||||
}
|
||||
var r result // r数组
|
||||
err = json.Unmarshal(es, &r) // 填api返回结果,struct地址
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("出现错误捏:", err))
|
||||
return
|
||||
}
|
||||
if r.Code == 0 && len(r.Data) > 0 {
|
||||
ctx.SendChain(message.Text(r.Data[0].Content)) // 输出提取后的结果
|
||||
} else {
|
||||
ctx.SendChain(message.Text("API访问错误"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func init() {
|
||||
"- 查成分 [xxx]\n" +
|
||||
"- 查弹幕 [xxx]\n" +
|
||||
"- 设置b站cookie b_ut=7;buvid3=0;i-wanna-go-back=-1;innersign=0;\n" +
|
||||
"- 更新vup" +
|
||||
"- 更新vup\n" +
|
||||
"Tips: (412就是拦截的意思,建议私聊把cookie设全)\n",
|
||||
PublicDataFolder: "Bilibili",
|
||||
})
|
||||
|
||||
@@ -44,6 +44,9 @@ func init() {
|
||||
return "", err
|
||||
}
|
||||
arr := gjson.Get(helper.BytesToString(data), "data.data").Array()
|
||||
if len(arr) == 0 {
|
||||
return "", errors.New("data is empty")
|
||||
}
|
||||
pic := arr[rand.Intn(len(arr))]
|
||||
return pic.String(), nil
|
||||
}, web.GetData, time.Minute)
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
package drawlots
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/gif"
|
||||
"math/rand"
|
||||
"os"
|
||||
@@ -11,6 +13,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/FloatTech/imgfactory"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
control "github.com/FloatTech/zbputils/control"
|
||||
@@ -38,9 +41,11 @@ var (
|
||||
return lotsList
|
||||
}()
|
||||
en = control.Register("drawlots", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "多功能抽签",
|
||||
Help: "支持图包文件夹和gif抽签\n-------------\n- (刷新)抽签列表\n- 抽[签名]签\n- 看签[gif签名]\n- 加签[签名][gif图片]\n- 删签[gif签名]",
|
||||
DisableOnDefault: false,
|
||||
Brief: "多功能抽签",
|
||||
Help: "支持图包文件夹和gif抽签\n" +
|
||||
"-------------\n" +
|
||||
"- (刷新)抽签列表\n- 抽[签名]签\n- 看[gif签名]签\n- 加[签名]签[gif图片]\n- 删[gif签名]签",
|
||||
PrivateDataFolder: "drawlots",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
datapath = file.BOTPATH + "/" + en.DataFolder()
|
||||
@@ -71,7 +76,7 @@ func init() {
|
||||
lotsType := ctx.State["regex_matched"].([]string)[1]
|
||||
fileInfo, ok := lotsList[lotsType]
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("签名[", lotsType, "]不存在"))
|
||||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("才...才没有", lotsType, "签这种东西啦")))
|
||||
return
|
||||
}
|
||||
if fileInfo.lotsType == "folder" {
|
||||
@@ -96,40 +101,39 @@ func init() {
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.ImageBytes(data))
|
||||
})
|
||||
en.OnPrefix("看签", zero.UserOrGrpAdmin).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^看(.+)签$`, zero.UserOrGrpAdmin).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.Event.MessageID
|
||||
lotsName := strings.TrimSpace(ctx.State["args"].(string))
|
||||
lotsName := ctx.State["regex_matched"].([]string)[1]
|
||||
fileInfo, ok := lotsList[lotsName]
|
||||
if !ok {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("签名[", lotsName, "]不存在")))
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("才...才没有", lotsName, "签这种东西啦")))
|
||||
return
|
||||
}
|
||||
if fileInfo.lotsType == "folder" {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("仅支持查看gif抽签")))
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("只能查看gif签哦~")))
|
||||
return
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Image("file:///"+datapath+lotsName+"."+fileInfo.lotsType)))
|
||||
})
|
||||
en.OnPrefix("加签", zero.SuperUserPermission, zero.MustProvidePicture).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^加(.+)签.*`, zero.SuperUserPermission, zero.MustProvidePicture).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.Event.MessageID
|
||||
lotsName := strings.TrimSpace(ctx.State["args"].(string))
|
||||
lotsName := ctx.State["regex_matched"].([]string)[1]
|
||||
if lotsName == "" {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("请使用正确的指令形式")))
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("请使用正确的指令形式哦~")))
|
||||
return
|
||||
}
|
||||
picURL := ctx.State["image_url"].([]string)[0]
|
||||
err := file.DownloadTo(picURL, datapath+"/"+lotsName+".gif")
|
||||
gifdata, err := web.GetData(picURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
im, err := gif.DecodeAll(bytes.NewReader(gifdata))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
file, err := os.Open(datapath + "/" + lotsName + ".gif")
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
}
|
||||
im, err := gif.DecodeAll(file)
|
||||
_ = file.Close()
|
||||
fileName := datapath + "/" + lotsName + ".gif"
|
||||
err = file.DownloadTo(picURL, fileName)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR:", err))
|
||||
return
|
||||
@@ -138,18 +142,18 @@ func init() {
|
||||
lotsType: "gif",
|
||||
quantity: len(im.Image),
|
||||
}
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("成功")))
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("成功!")))
|
||||
})
|
||||
en.OnPrefix("删签", zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
en.OnRegex(`^删(.+)签$`, zero.SuperUserPermission).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) {
|
||||
id := ctx.Event.MessageID
|
||||
lotsName := strings.TrimSpace(ctx.State["args"].(string))
|
||||
lotsName := ctx.State["regex_matched"].([]string)[1]
|
||||
fileInfo, ok := lotsList[lotsName]
|
||||
if !ok {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("签名[", lotsName, "]不存在")))
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("才...才没有", lotsName, "签这种东西啦")))
|
||||
return
|
||||
}
|
||||
if fileInfo.lotsType == "folder" {
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("图包请手动移除(保护图源误删),谢谢")))
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("为了防止误删图源,图包请手动移除哦~")))
|
||||
return
|
||||
}
|
||||
err := os.Remove(datapath + lotsName + "." + fileInfo.lotsType)
|
||||
@@ -158,7 +162,7 @@ func init() {
|
||||
return
|
||||
}
|
||||
delete(lotsList, lotsName)
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("成功")))
|
||||
ctx.Send(message.ReplyWithMessage(id, message.Text("成功!")))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -169,7 +173,7 @@ func getList() (list map[string]info, err error) {
|
||||
return
|
||||
}
|
||||
if len(files) == 0 {
|
||||
err = errors.New("不存在任何抽签")
|
||||
err = errors.New("什么签也没有哦~")
|
||||
return
|
||||
}
|
||||
for _, lots := range files {
|
||||
@@ -214,13 +218,13 @@ func randFile(path string, indexMax int) (string, error) {
|
||||
if drawFile.IsDir() {
|
||||
indexMax--
|
||||
if indexMax <= 0 {
|
||||
return "", errors.New("图包[" + path + "]存在太多非图片文件,请清理")
|
||||
return "", errors.New("图包[" + path + "]存在太多非图片文件,请清理~")
|
||||
}
|
||||
return randFile(path, indexMax)
|
||||
}
|
||||
return picPath + "/" + drawFile.Name(), err
|
||||
}
|
||||
return "", errors.New("图包[" + path + "]不存在签内容")
|
||||
return "", errors.New("图包[" + path + "]不存在签内容!")
|
||||
}
|
||||
|
||||
func randGif(gifName string) (image.Image, error) {
|
||||
@@ -240,10 +244,10 @@ func randGif(gifName string) (image.Image, error) {
|
||||
return nil, err
|
||||
}
|
||||
v := im.Image[rand.Intn(len(im.Image))]
|
||||
return imgfactory.Size(firstImg, firstImg.Bounds().Max.X, firstImg.Bounds().Max.Y).InsertUpC(v, 0, 0, firstImg.Bounds().Max.X/2, firstImg.Bounds().Max.Y/2).Clone().Image(),err
|
||||
return imgfactory.Size(firstImg, firstImg.Bounds().Dx(), firstImg.Bounds().Dy()).InsertUpC(v, 0, 0, firstImg.Bounds().Dx()/2, firstImg.Bounds().Dy()/2).Clone().Image(),err
|
||||
/*/
|
||||
// 如果gif图片出现信息缺失请使用上面注释掉的代码,把下面注释了(上面代码部分图存在bug)
|
||||
v := im.Image[rand.Intn(len(im.Image))]
|
||||
return imgfactory.Size(v, v.Bounds().Max.X, v.Bounds().Max.Y).Image(), err
|
||||
return imgfactory.NewFactoryBG(v.Rect.Dx(), v.Rect.Dy(), color.NRGBA{0, 0, 0, 255}).InsertUp(v, 0, 0, 0, 0).Clone().Image(), err
|
||||
// */
|
||||
}
|
||||
|
||||
174
plugin/hitokoto/hitokoto.go
Normal file
174
plugin/hitokoto/hitokoto.go
Normal file
@@ -0,0 +1,174 @@
|
||||
// Package hitokoto 一言
|
||||
package hitokoto
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.Register("hitokoto", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "一言",
|
||||
Help: "- 一言[xxx]\n" +
|
||||
"- 系列一言",
|
||||
PublicDataFolder: "Hitokoto",
|
||||
})
|
||||
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
dbfile := engine.DataFolder() + "hitokoto.db"
|
||||
_, err := engine.GetLazyData("hitokoto.db", false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
hdb, err = initialize(dbfile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
engine.OnPrefix(`一言`, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
args := ctx.State["args"].(string)
|
||||
blist, err := hdb.getByKey(strings.TrimSpace(args))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if len(blist) == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: hitokoto empty"))
|
||||
return
|
||||
}
|
||||
m := make(message.Message, 0, 10)
|
||||
text := strings.Builder{}
|
||||
if len(blist) <= 10 {
|
||||
for _, b := range blist {
|
||||
text.WriteString(b.Hitokoto)
|
||||
text.WriteString("\n——")
|
||||
text.WriteString(b.From)
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
|
||||
text.Reset()
|
||||
}
|
||||
} else {
|
||||
indexes := map[int]struct{}{}
|
||||
for i := 0; i < 10; i++ {
|
||||
ind := rand.Intn(len(blist))
|
||||
if _, ok := indexes[ind]; ok {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
indexes[ind] = struct{}{}
|
||||
}
|
||||
for k := range indexes {
|
||||
b := blist[k]
|
||||
text.WriteString(b.Hitokoto)
|
||||
text.WriteString("\n——")
|
||||
text.WriteString(b.From)
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
|
||||
text.Reset()
|
||||
}
|
||||
}
|
||||
if id := ctx.Send(m).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch(`系列一言`, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
results, err := hdb.getAllCategory()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
tex := strings.Builder{}
|
||||
tex.WriteString("请输入系列一言序号\n")
|
||||
for i, v := range results {
|
||||
tex.WriteString(strconv.Itoa(i))
|
||||
tex.WriteString(". ")
|
||||
tex.WriteString(v.Category)
|
||||
tex.WriteString("\n")
|
||||
}
|
||||
base64Str, err := text.RenderToBase64(tex.String(), text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(base64Str)))
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.SendChain(message.Text("系列一言指令过期"))
|
||||
return
|
||||
case c := <-recv:
|
||||
msg := c.Event.Message.ExtractPlainText()
|
||||
num, err := strconv.Atoi(msg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("请输入数字!"))
|
||||
continue
|
||||
}
|
||||
if num < 0 || num >= len(results) {
|
||||
ctx.SendChain(message.Text("序号非法!"))
|
||||
continue
|
||||
}
|
||||
ctx.SendChain(message.Text("请欣赏系列一言: ", results[num].Category))
|
||||
hlist, err := hdb.getByCategory(results[num].Category)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if len(hlist) == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: hitokoto empty"))
|
||||
return
|
||||
}
|
||||
m := make(message.Message, 0, 10)
|
||||
text := strings.Builder{}
|
||||
if len(hlist) <= 10 {
|
||||
for _, b := range hlist {
|
||||
text.WriteString(b.Hitokoto)
|
||||
text.WriteString("\n——")
|
||||
text.WriteString(b.From)
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
|
||||
text.Reset()
|
||||
}
|
||||
} else {
|
||||
indexes := map[int]struct{}{}
|
||||
for i := 0; i < 10; i++ {
|
||||
ind := rand.Intn(len(hlist))
|
||||
if _, ok := indexes[ind]; ok {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
indexes[ind] = struct{}{}
|
||||
}
|
||||
for k := range indexes {
|
||||
b := hlist[k]
|
||||
text.WriteString(b.Hitokoto)
|
||||
text.WriteString("\n——")
|
||||
text.WriteString(b.From)
|
||||
m = append(m, ctxext.FakeSenderForwardNode(ctx, message.Text(text.String())))
|
||||
text.Reset()
|
||||
}
|
||||
}
|
||||
if id := ctx.Send(m).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控或下载图片用时过长,请耐心等待"))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
73
plugin/hitokoto/model.go
Normal file
73
plugin/hitokoto/model.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package hitokoto
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
// hdb 表情包数据库全局变量
|
||||
var hdb *hitokotodb
|
||||
|
||||
// hitokotodb 表情包数据库
|
||||
type hitokotodb gorm.DB
|
||||
|
||||
// initialize 初始化
|
||||
func initialize(dbpath string) (db *hitokotodb, err error) {
|
||||
if _, err = os.Stat(dbpath); err != nil || os.IsNotExist(err) {
|
||||
// 生成文件
|
||||
f, err := os.Create(dbpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = f.Close()
|
||||
}
|
||||
gdb, err := gorm.Open("sqlite3", dbpath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
gdb.AutoMigrate(&hitokoto{})
|
||||
return (*hitokotodb)(gdb), nil
|
||||
}
|
||||
|
||||
type hitokoto struct {
|
||||
ID int `json:"id" gorm:"column:id;primary_key"`
|
||||
Hitokoto string `json:"hitokoto" gorm:"column:hitokoto"`
|
||||
Type string `json:"type" gorm:"column:type"`
|
||||
From string `json:"from" gorm:"column:from"`
|
||||
FromWho string `json:"from_who" gorm:"column:from_who"`
|
||||
Creator string `json:"creator" gorm:"column:creator"`
|
||||
CreatorUID int `json:"creator_uid" gorm:"column:creator_uid"`
|
||||
Reviewer int `json:"reviewer" gorm:"column:reviewer"`
|
||||
UUID string `json:"uuid" gorm:"column:uuid"`
|
||||
CreatedAt string `json:"created_at" gorm:"column:created_at"`
|
||||
Category string `json:"catogory" gorm:"column:category"`
|
||||
}
|
||||
|
||||
// TableName 表名
|
||||
func (hitokoto) TableName() string {
|
||||
return "hitokoto"
|
||||
}
|
||||
|
||||
func (hdb *hitokotodb) getByKey(key string) (b []hitokoto, err error) {
|
||||
db := (*gorm.DB)(hdb)
|
||||
err = db.Where("hitokoto like ?", "%"+key+"%").Find(&b).Error
|
||||
return
|
||||
}
|
||||
|
||||
type result struct {
|
||||
Category string
|
||||
Count int
|
||||
}
|
||||
|
||||
func (hdb *hitokotodb) getAllCategory() (results []result, err error) {
|
||||
db := (*gorm.DB)(hdb)
|
||||
err = db.Table("hitokoto").Select("category, count(1) as count").Group("category").Scan(&results).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (hdb *hitokotodb) getByCategory(category string) (h []hitokoto, err error) {
|
||||
db := (*gorm.DB)(hdb)
|
||||
err = db.Where("category = ?", category).Find(&h).Error
|
||||
return
|
||||
}
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
jiami1 = "http://ovooa.com/API/sho_u/?msg=%v" // 加密api地址
|
||||
jiami2 = "http://ovooa.com/API/sho_u/?format=1&msg=%v" // 解密api地址
|
||||
jiami1 = "http://ovooa.caonm.net/API/sho_u/?msg=%v" // 加密api地址
|
||||
jiami2 = "http://ovooa.caonm.net/API/sho_u/?format=1&msg=%v" // 解密api地址
|
||||
|
||||
)
|
||||
|
||||
|
||||
@@ -302,7 +302,7 @@ func init() {
|
||||
func (sql *婚姻登记) 查看设置(gid int64) (dbinfo updateinfo, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
// 创建群表哥
|
||||
// 创建群表格
|
||||
err = sql.db.Create("updateinfo", &updateinfo{})
|
||||
if err != nil {
|
||||
return
|
||||
@@ -350,7 +350,7 @@ func (sql *婚姻登记) 查户口(gid, uid int64) (info userinfo, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
gidstr := "group" + strconv.FormatInt(gid, 10)
|
||||
// 创建群表哥
|
||||
// 创建群表格
|
||||
err = sql.db.Create(gidstr, &userinfo{})
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
@@ -74,15 +74,15 @@ func init() { // 插件主体
|
||||
imgs = append(imgs, message.Image(m.String()))
|
||||
continue
|
||||
}
|
||||
logrus.Debugln("[sausenao]开始下载", n)
|
||||
logrus.Debugln("[sausenao]urls:", illust.ImageUrls)
|
||||
logrus.Debugln("[saucenao]开始下载", n)
|
||||
logrus.Debugln("[saucenao]urls:", illust.ImageUrls)
|
||||
err1 := illust.DownloadToCache(i)
|
||||
if err1 == nil {
|
||||
m.SetFile(f)
|
||||
_, _ = m.Push(ctxext.SendToSelf(ctx), ctxext.GetMessage(ctx))
|
||||
}
|
||||
if err1 != nil {
|
||||
logrus.Debugln("[sausenao]下载err:", err1)
|
||||
logrus.Debugln("[saucenao]下载err:", err1)
|
||||
}
|
||||
}
|
||||
imgs = append(imgs, message.Image("file:///"+f))
|
||||
@@ -109,8 +109,13 @@ func init() { // 插件主体
|
||||
engine.OnKeywordGroup([]string{"以图搜图", "搜索图片", "以图识图"}, zero.MustProvidePicture).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
// 开始搜索图片
|
||||
pics, ok := ctx.State["image_url"].([]string)
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("ERROR: 未获取到图片链接"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("少女祈祷中..."))
|
||||
for _, pic := range ctx.State["image_url"].([]string) {
|
||||
for _, pic := range pics {
|
||||
if saucenaocli != nil {
|
||||
resp, err := saucenaocli.FromURL(pic)
|
||||
if err == nil && resp.Count() > 0 {
|
||||
@@ -157,27 +162,27 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("请私聊发送 设置 saucenao api key [apikey] 以启用 saucenao 搜图 (方括号不需要输入), key 请前往 https://saucenao.com/user.php?page=search-api 获取"))
|
||||
}
|
||||
// ascii2d 搜索
|
||||
if result, err := ascii2d.ASCII2d(pic); err != nil {
|
||||
result, err := ascii2d.ASCII2d(pic)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
continue
|
||||
} else {
|
||||
msg := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text("ascii2d搜图结果"))}
|
||||
for i := 0; i < len(result) && i < 5; i++ {
|
||||
msg = append(msg, ctxext.FakeSenderForwardNode(ctx,
|
||||
message.Image(result[i].Thumb),
|
||||
message.Text(fmt.Sprintf(
|
||||
"标题: %s\n图源: %s\n画师: %s\n画师链接: %s\n图片链接: %s",
|
||||
result[i].Name,
|
||||
result[i].Type,
|
||||
result[i].AuthNm,
|
||||
result[i].Author,
|
||||
result[i].Link,
|
||||
))),
|
||||
)
|
||||
}
|
||||
if id := ctx.Send(msg).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
}
|
||||
msg := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text("ascii2d搜图结果"))}
|
||||
for i := 0; i < len(result) && i < 5; i++ {
|
||||
msg = append(msg, ctxext.FakeSenderForwardNode(ctx,
|
||||
message.Image(result[i].Thumb),
|
||||
message.Text(fmt.Sprintf(
|
||||
"标题: %s\n图源: %s\n画师: %s\n画师链接: %s\n图片链接: %s",
|
||||
result[i].Name,
|
||||
result[i].Type,
|
||||
result[i].AuthNm,
|
||||
result[i].Author,
|
||||
result[i].Link,
|
||||
))),
|
||||
)
|
||||
}
|
||||
if id := ctx.Send(msg).ID(); id == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -167,7 +167,7 @@ func init() {
|
||||
}
|
||||
// draw head
|
||||
nickName := ctx.CardOrNickName(uid)
|
||||
canvas.DrawStringWrapped(nickName, 350, 180, 0.5, 0.5, 0.5, 0.5, gg.AlignLeft)
|
||||
canvas.DrawString(nickName, 350, 180)
|
||||
canvas.Fill()
|
||||
// main draw
|
||||
data, err = file.GetLazyData(text.FontFile, control.Md5File, true)
|
||||
|
||||
@@ -236,10 +236,7 @@ func (p *imgpool) add(ctx *zero.Ctx, imgtype string, id int64) error {
|
||||
return err
|
||||
}
|
||||
// 添加插画到对应的数据库table
|
||||
if err := p.db.Insert(imgtype, illust); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return p.db.Insert(imgtype, illust)
|
||||
}
|
||||
|
||||
func (p *imgpool) remove(imgtype string, id int64) error {
|
||||
|
||||
@@ -55,13 +55,13 @@ func timeDuration(time time.Duration) (hour, minute, second int64) {
|
||||
}
|
||||
|
||||
// 只统计6点到12点的早安
|
||||
func isMorning(ctx *zero.Ctx) bool {
|
||||
func isMorning(*zero.Ctx) bool {
|
||||
now := time.Now().Hour()
|
||||
return now >= 6 && now <= 12
|
||||
}
|
||||
|
||||
// 只统计21点到凌晨3点的晚安
|
||||
func isEvening(ctx *zero.Ctx) bool {
|
||||
func isEvening(*zero.Ctx) bool {
|
||||
now := time.Now().Hour()
|
||||
return now >= 21 || now <= 3
|
||||
}
|
||||
|
||||
134
plugin/steam/listenter.go
Normal file
134
plugin/steam/listenter.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package steam
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/tidwall/gjson"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
// ----------------------- 远程调用 ----------------------
|
||||
const (
|
||||
URL = "https://api.steampowered.com/" // steam API 调用地址
|
||||
StatusURL = "ISteamUser/GetPlayerSummaries/v2/?key=%+v&steamids=%+v" // 根据用户steamID获取用户状态
|
||||
steamapikeygid = 3
|
||||
)
|
||||
|
||||
var apiKey string
|
||||
|
||||
func init() {
|
||||
engine.OnRegex(`^steam绑定\s*api\s*key\s*(.*)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
apiKey = ctx.State["regex_matched"].([]string)[1]
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
_ = m.Manager.Response(steamapikeygid)
|
||||
err := m.Manager.SetExtra(steamapikeygid, apiKey)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: 保存apikey失败!"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("保存apikey成功!"))
|
||||
})
|
||||
engine.OnFullMatch("查看apikey", zero.OnlyPrivate, zero.SuperUserPermission, getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
ctx.SendChain(message.Text("apikey为: ", apiKey))
|
||||
})
|
||||
engine.OnFullMatch("拉取steam订阅", getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
su := zero.BotConfig.SuperUsers[0]
|
||||
// 获取所有处于监听状态的用户信息
|
||||
infos, err := database.findAll()
|
||||
if err != nil {
|
||||
// 挂了就给管理员发消息
|
||||
ctx.SendPrivateMessage(su, message.Text("[steam] ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if len(infos) == 0 {
|
||||
return
|
||||
}
|
||||
// 收集这波用户的streamId,然后查当前的状态,并建立信息映射表
|
||||
streamIds := make([]string, len(infos))
|
||||
localPlayerMap := make(map[int64]*player)
|
||||
for i := 0; i < len(infos); i++ {
|
||||
streamIds[i] = strconv.FormatInt(infos[i].SteamID, 10)
|
||||
localPlayerMap[infos[i].SteamID] = &infos[i]
|
||||
}
|
||||
// 将所有用户状态查一遍
|
||||
playerStatus, err := getPlayerStatus(streamIds...)
|
||||
if err != nil {
|
||||
// 出错就发消息
|
||||
ctx.SendPrivateMessage(su, message.Text("[steam] ERROR: ", err))
|
||||
return
|
||||
}
|
||||
// 遍历返回的信息做对比,假如信息有变化则发消息
|
||||
now := time.Now()
|
||||
msg := make(message.Message, 0, len(playerStatus))
|
||||
for _, playerInfo := range playerStatus {
|
||||
msg = msg[:0]
|
||||
localInfo := localPlayerMap[playerInfo.SteamID]
|
||||
// 排除不需要处理的情况
|
||||
if localInfo.GameID == 0 && playerInfo.GameID == 0 {
|
||||
continue
|
||||
}
|
||||
// 打开游戏
|
||||
if localInfo.GameID == 0 && playerInfo.GameID != 0 {
|
||||
msg = append(msg, message.Text(playerInfo.PersonaName, "正在玩", playerInfo.GameExtraInfo))
|
||||
localInfo.LastUpdate = now.Unix()
|
||||
}
|
||||
// 更换游戏
|
||||
if localInfo.GameID != 0 && playerInfo.GameID != localInfo.GameID && playerInfo.GameID != 0 {
|
||||
msg = append(msg, message.Text(playerInfo.PersonaName, "玩了", (now.Unix()-localInfo.LastUpdate)/60, "分钟后, 丢下了", localInfo.GameExtraInfo, ", 转头去玩", playerInfo.GameExtraInfo))
|
||||
localInfo.LastUpdate = now.Unix()
|
||||
}
|
||||
// 关闭游戏
|
||||
if playerInfo.GameID != localInfo.GameID && playerInfo.GameID == 0 {
|
||||
msg = append(msg, message.Text(playerInfo.PersonaName, "玩了", (now.Unix()-localInfo.LastUpdate)/60, "分钟后, 关掉了", localInfo.GameExtraInfo))
|
||||
localInfo.LastUpdate = 0
|
||||
}
|
||||
if len(msg) != 0 {
|
||||
groups := strings.Split(localInfo.Target, ",")
|
||||
for _, groupString := range groups {
|
||||
group, err := strconv.ParseInt(groupString, 10, 64)
|
||||
if err != nil {
|
||||
ctx.SendPrivateMessage(su, message.Text("[steam] ERROR: ", err, "\nOTHER: SteamID ", localInfo.SteamID))
|
||||
continue
|
||||
}
|
||||
ctx.SendGroupMessage(group, msg)
|
||||
}
|
||||
}
|
||||
// 更新数据
|
||||
localInfo.GameID = playerInfo.GameID
|
||||
localInfo.GameExtraInfo = playerInfo.GameExtraInfo
|
||||
if err = database.update(localInfo); err != nil {
|
||||
ctx.SendPrivateMessage(su, message.Text("[steam] ERROR: ", err, "\nEXP: 更新数据失败\nOTHER: SteamID ", localInfo.SteamID))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// getPlayerStatus 获取用户状态
|
||||
func getPlayerStatus(streamIds ...string) ([]*player, error) {
|
||||
players := make([]*player, 0)
|
||||
// 拼接请求地址
|
||||
url := fmt.Sprintf(URL+StatusURL, apiKey, strings.Join(streamIds, ","))
|
||||
// 拉取并解析数据
|
||||
data, err := web.GetData(url)
|
||||
if err != nil {
|
||||
return players, err
|
||||
}
|
||||
dataStr := binary.BytesToString(data)
|
||||
index := gjson.Get(dataStr, "response.players.#").Uint()
|
||||
for i := uint64(0); i < index; i++ {
|
||||
players = append(players, &player{
|
||||
SteamID: gjson.Get(dataStr, fmt.Sprintf("response.players.%d.steamid", i)).Int(),
|
||||
PersonaName: gjson.Get(dataStr, fmt.Sprintf("response.players.%d.personaname", i)).String(),
|
||||
GameID: gjson.Get(dataStr, fmt.Sprintf("response.players.%d.gameid", i)).Int(),
|
||||
GameExtraInfo: gjson.Get(dataStr, fmt.Sprintf("response.players.%d.gameextrainfo", i)).String(),
|
||||
})
|
||||
}
|
||||
return players, nil
|
||||
}
|
||||
158
plugin/steam/steam.go
Normal file
158
plugin/steam/steam.go
Normal file
@@ -0,0 +1,158 @@
|
||||
// Package steam 获取steam用户状态
|
||||
package steam
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/math"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/ctxext"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
engine = control.Register("steam", &ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "steam相关插件",
|
||||
Help: "- steam添加订阅 xxxxxxx (可输入需要绑定的 steamid)\n" +
|
||||
"- steam删除订阅 xxxxxxx (删除你创建的对于 steamid 的绑定)\n" +
|
||||
"- steam查询订阅 (查询本群内所有的绑定对象)\n" +
|
||||
"-----------------------\n" +
|
||||
"- steam绑定 api key xxxxxxx (密钥在steam网站申请, 申请地址: https://steamcommunity.com/dev/registerkey)\n" +
|
||||
"- 查看apikey (查询已经绑定的密钥)\n" +
|
||||
"- 拉取steam订阅 (使用插件定时任务开始)\n" +
|
||||
"-----------------------\n" +
|
||||
"Tips: steamID在用户资料页的链接上面, 形如7656119820673xxxx\n" +
|
||||
"需要先私聊绑定apikey, 订阅用户之后使用job插件设置定时, 例: \n" +
|
||||
"记录在\"@every 1m\"触发的指令\n" +
|
||||
"拉取steam订阅",
|
||||
PrivateDataFolder: "steam",
|
||||
}).ApplySingle(ctxext.DefaultSingle)
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 创建绑定流程
|
||||
engine.OnRegex(`^steam添加订阅\s*(\d+)$`, zero.OnlyGroup, getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
steamidstr := ctx.State["regex_matched"].([]string)[1]
|
||||
steamID := math.Str2Int64(steamidstr)
|
||||
// 获取用户状态
|
||||
playerStatus, err := getPlayerStatus(steamidstr)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 添加失败, 获取用户信息错误"))
|
||||
return
|
||||
}
|
||||
if len(playerStatus) == 0 {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: 需要添加的用户不存在, 请检查id或url"))
|
||||
return
|
||||
}
|
||||
playerData := playerStatus[0]
|
||||
// 判断用户是否已经初始化:若未初始化,通过用户的steamID获取当前状态并初始化;若已经初始化则更新用户信息
|
||||
info, err := database.find(steamID)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 添加失败,数据库错误"))
|
||||
return
|
||||
}
|
||||
// 处理数据
|
||||
groupID := strconv.FormatInt(ctx.Event.GroupID, 10)
|
||||
if info.Target == "" {
|
||||
info = player{
|
||||
SteamID: steamID,
|
||||
PersonaName: playerData.PersonaName,
|
||||
Target: groupID,
|
||||
GameID: playerData.GameID,
|
||||
GameExtraInfo: playerData.GameExtraInfo,
|
||||
LastUpdate: time.Now().Unix(),
|
||||
}
|
||||
} else if !strings.Contains(info.Target, groupID) {
|
||||
info.Target = strings.Join([]string{info.Target, groupID}, ",")
|
||||
}
|
||||
// 更新数据库
|
||||
if err = database.update(&info); err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 更新数据库失败"))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("添加成功"))
|
||||
})
|
||||
// 删除绑定流程
|
||||
engine.OnRegex(`^steam删除订阅\s*(\d+)$`, zero.OnlyGroup, getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
steamID := math.Str2Int64(ctx.State["regex_matched"].([]string)[1])
|
||||
groupID := strconv.FormatInt(ctx.Event.GroupID, 10)
|
||||
// 判断是否已经绑定该steamID,若已绑定就将群列表从推送群列表钟去除
|
||||
info, err := database.findWithGroupID(steamID, groupID)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 删除失败,数据库错误"))
|
||||
return
|
||||
}
|
||||
if info.SteamID == 0 {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: 所需要删除的用户不存在。"))
|
||||
return
|
||||
}
|
||||
// 从绑定列表中剔除需要删除的对象
|
||||
targets := strings.Split(info.Target, ",")
|
||||
newTargets := make([]string, 0)
|
||||
for _, target := range targets {
|
||||
if target == groupID {
|
||||
continue
|
||||
}
|
||||
newTargets = append(newTargets, target)
|
||||
}
|
||||
if len(newTargets) == 0 {
|
||||
if err = database.del(steamID); err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 删除失败,数据库错误"))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
info.Target = strings.Join(newTargets, ",")
|
||||
if err = database.update(&info); err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 删除失败,数据库错误"))
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.SendChain(message.Text("删除成功"))
|
||||
})
|
||||
// 查询当前群绑定信息
|
||||
engine.OnFullMatch("steam查询订阅", zero.OnlyGroup, getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||||
// 获取群信息
|
||||
groupID := strconv.FormatInt(ctx.Event.GroupID, 10)
|
||||
// 获取所有绑定信息
|
||||
infos, err := database.findAll()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: ", err, "\nEXP: 查询订阅失败, 数据库错误"))
|
||||
return
|
||||
}
|
||||
if len(infos) == 0 {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: 还未订阅过用户关系!"))
|
||||
return
|
||||
}
|
||||
// 遍历所有信息,如果包含该群就收集对应的steamID
|
||||
var sb strings.Builder
|
||||
head := " 查询steam订阅成功, 该群订阅的用户有: \n"
|
||||
sb.WriteString(head)
|
||||
for _, info := range infos {
|
||||
if strings.Contains(info.Target, groupID) {
|
||||
sb.WriteString(" ")
|
||||
sb.WriteString(info.PersonaName)
|
||||
sb.WriteString(":")
|
||||
sb.WriteString(strconv.FormatInt(info.SteamID, 10))
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
}
|
||||
if sb.String() == head {
|
||||
ctx.SendChain(message.Text("查询成功,该群暂时还没有被绑定的用户!"))
|
||||
return
|
||||
}
|
||||
// 组装并返回结果
|
||||
data, err := text.RenderToBase64(sb.String(), text.FontFile, 400, 18)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Image("base64://" + binary.BytesToString(data)))
|
||||
})
|
||||
}
|
||||
117
plugin/steam/store.go
Normal file
117
plugin/steam/store.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package steam
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||
sql "github.com/FloatTech/sqlite"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var (
|
||||
database streamDB
|
||||
// 开启并检查数据库链接
|
||||
getDB = fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
database.db.DBPath = engine.DataFolder() + "steam.db"
|
||||
err := database.db.Open(time.Hour * 24)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
if err = database.db.Create(TableListenPlayer, &player{}); err != nil {
|
||||
ctx.SendChain(message.Text("[steam] ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
// 校验密钥是否初始化
|
||||
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
|
||||
_ = m.Manager.Response(steamapikeygid)
|
||||
_ = m.Manager.GetExtra(steamapikeygid, &apiKey)
|
||||
if apiKey == "" {
|
||||
ctx.SendChain(message.Text("ERROR: 未设置steam apikey"))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
)
|
||||
|
||||
// streamDB 继承方法的存储结构
|
||||
type streamDB struct {
|
||||
sync.RWMutex
|
||||
db sql.Sqlite
|
||||
}
|
||||
|
||||
const (
|
||||
// TableListenPlayer 存储查询用户信息
|
||||
TableListenPlayer = "listen_player"
|
||||
)
|
||||
|
||||
// player 用户状态存储结构体
|
||||
type player struct {
|
||||
SteamID int64 `json:"steam_id"` // 绑定用户标识ID
|
||||
PersonaName string `json:"persona_name"` // 用户昵称
|
||||
Target string `json:"target"` // 信息推送群组
|
||||
GameID int64 `json:"game_id"` // 游戏ID
|
||||
GameExtraInfo string `json:"game_extra_info"` // 游戏信息
|
||||
LastUpdate int64 `json:"last_update"` // 更新时间
|
||||
}
|
||||
|
||||
// update 如果主键不存在则插入一条新的数据,如果主键存在直接复写
|
||||
func (sql *streamDB) update(dbInfo *player) error {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
return sql.db.Insert(TableListenPlayer, dbInfo)
|
||||
}
|
||||
|
||||
// find 根据主键查信息
|
||||
func (sql *streamDB) find(steamID int64) (dbInfo player, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
condition := "where steam_id = " + strconv.FormatInt(steamID, 10)
|
||||
if !sql.db.CanFind(TableListenPlayer, condition) {
|
||||
return player{}, nil // 规避没有该用户数据的报错
|
||||
}
|
||||
err = sql.db.Find(TableListenPlayer, &dbInfo, condition)
|
||||
return
|
||||
}
|
||||
|
||||
// findWithGroupID 根据用户steamID和groupID查询信息
|
||||
func (sql *streamDB) findWithGroupID(steamID int64, groupID string) (dbInfo player, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
condition := "where steam_id = " + strconv.FormatInt(steamID, 10) + " AND target LIKE '%" + groupID + "%'"
|
||||
if !sql.db.CanFind(TableListenPlayer, condition) {
|
||||
return player{}, nil // 规避没有该用户数据的报错
|
||||
}
|
||||
err = sql.db.Find(TableListenPlayer, &dbInfo, condition)
|
||||
return
|
||||
}
|
||||
|
||||
// findAll 查询所有库信息
|
||||
func (sql *streamDB) findAll() (dbInfos []player, err error) {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
var info player
|
||||
num, err := sql.db.Count(TableListenPlayer)
|
||||
if err != nil || num == 0 {
|
||||
return
|
||||
}
|
||||
dbInfos = make([]player, 0, num)
|
||||
err = sql.db.FindFor(TableListenPlayer, &info, "", func() error {
|
||||
if info.SteamID != 0 {
|
||||
dbInfos = append(dbInfos, info)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// del 删除指定数据
|
||||
func (sql *streamDB) del(steamID int64) error {
|
||||
sql.Lock()
|
||||
defer sql.Unlock()
|
||||
return sql.db.Del(TableListenPlayer, "where steam_id = "+strconv.FormatInt(steamID, 10))
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
"0409": {
|
||||
"identity": {
|
||||
"name": "ZeroBot-Plugin",
|
||||
"version": "1.7.0.1737"
|
||||
"version": "1.7.0.1760"
|
||||
},
|
||||
"description": "",
|
||||
"minimum-os": "vista",
|
||||
@@ -36,23 +36,23 @@
|
||||
"#1": {
|
||||
"0000": {
|
||||
"fixed": {
|
||||
"file_version": "1.7.0.1737",
|
||||
"product_version": "v1.7.0-beta3",
|
||||
"timestamp": "2023-03-09T13:57:18+08:00"
|
||||
"file_version": "1.7.0.1760",
|
||||
"product_version": "v1.7.0",
|
||||
"timestamp": "2023-03-20T12:28:01+08:00"
|
||||
},
|
||||
"info": {
|
||||
"0409": {
|
||||
"Comments": "OneBot plugins based on ZeroBot",
|
||||
"CompanyName": "FloatTech",
|
||||
"FileDescription": "https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
"FileVersion": "1.7.0.1737",
|
||||
"FileVersion": "1.7.0.1760",
|
||||
"InternalName": "",
|
||||
"LegalCopyright": "© 2020 - 2023 FloatTech. All Rights Reserved.",
|
||||
"LegalTrademarks": "",
|
||||
"OriginalFilename": "ZBP.EXE",
|
||||
"PrivateBuild": "",
|
||||
"ProductName": "ZeroBot-Plugin",
|
||||
"ProductVersion": "v1.7.0-beta3",
|
||||
"ProductVersion": "v1.7.0",
|
||||
"SpecialBuild": ""
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user