mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-11 09:40:25 +00:00
Compare commits
13 Commits
v1.2.0-bet
...
v1.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb63b98f39 | ||
|
|
f3f7e2d3c1 | ||
|
|
89121cfc57 | ||
|
|
d8a41a5ee1 | ||
|
|
f8ca9355d2 | ||
|
|
d4bceb1922 | ||
|
|
876d85ac4e | ||
|
|
ab34930beb | ||
|
|
35f7450ab2 | ||
|
|
2917ff6701 | ||
|
|
d1656b25c9 | ||
|
|
e6a20866b6 | ||
|
|
9de065d31a |
@@ -122,6 +122,12 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
|
||||
- [x] 添加[涩图/二次元/风景/车万][P站图片ID]
|
||||
- [x] 删除[涩图/二次元/风景/车万][P站图片ID]
|
||||
- [x] > setu status
|
||||
- **本地涩图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_nativesetu"`
|
||||
- [x] 本地[xxx]
|
||||
- [x] 刷新本地[xxx]
|
||||
- [x] 设置本地setu绝对路径[xxx]
|
||||
- [x] 刷新所有本地setu
|
||||
- [x] 所有本地setu分类
|
||||
- **lolicon** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_lolicon"`
|
||||
- [x] 来份萝莉
|
||||
- **搜图** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_saucenao"`
|
||||
@@ -152,6 +158,7 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
|
||||
- **鬼东西** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_wtf"`
|
||||
- [x] 鬼东西列表
|
||||
- [x] 查询鬼东西[序号][@xxx]
|
||||
- 注:由于需要科学,默认注释。
|
||||
- **AIfalse** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false"`
|
||||
- [x] 查询计算机当前活跃度 [身体检查]
|
||||
- [x] 清理缓存
|
||||
|
||||
@@ -94,7 +94,6 @@ func (m *Control) IsEnabledIn(gid int64) bool {
|
||||
m.RLock()
|
||||
err = db.Find(m.service, &c, "WHERE gid = "+strconv.FormatInt(gid, 10))
|
||||
m.RUnlock()
|
||||
logrus.Debugln("[control] db find gid =", c.GroupID)
|
||||
if err == nil && gid == c.GroupID {
|
||||
logrus.Debugf("[control] plugin %s of grp %d : %d", m.service, c.GroupID, c.Disable)
|
||||
return c.Disable == 0
|
||||
@@ -103,7 +102,7 @@ func (m *Control) IsEnabledIn(gid int64) bool {
|
||||
m.RLock()
|
||||
err = db.Find(m.service, &c, "WHERE gid = 0")
|
||||
m.RUnlock()
|
||||
if err == nil {
|
||||
if err == nil && c.GroupID == 0 {
|
||||
logrus.Debugf("[control] plugin %s of all : %d", m.service, c.Disable)
|
||||
return c.Disable == 0
|
||||
}
|
||||
@@ -178,6 +177,7 @@ func init() {
|
||||
service, ok := Lookup(model.Args)
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("没有找到指定服务!"))
|
||||
return
|
||||
}
|
||||
grp := ctx.Event.GroupID
|
||||
if grp == 0 {
|
||||
@@ -202,6 +202,7 @@ func init() {
|
||||
service, ok := Lookup(model.Args)
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("没有找到指定服务!"))
|
||||
return
|
||||
}
|
||||
grp := ctx.Event.GroupID
|
||||
if grp == 0 {
|
||||
@@ -219,6 +220,7 @@ func init() {
|
||||
service, ok := Lookup(model.Args)
|
||||
if !ok {
|
||||
ctx.SendChain(message.Text("没有找到指定服务!"))
|
||||
return
|
||||
}
|
||||
if service.options.Help != "" {
|
||||
ctx.SendChain(message.Text(service.options.Help))
|
||||
|
||||
2
go.mod
2
go.mod
@@ -6,6 +6,7 @@ require (
|
||||
github.com/FloatTech/AnimeAPI v1.1.10
|
||||
github.com/FloatTech/ZeroBot-Plugin-Gif v0.2.4
|
||||
github.com/FloatTech/bot-manager v1.0.1-0.20211112011524-85b9895271ed
|
||||
github.com/corona10/goimagehash v1.0.3
|
||||
github.com/fogleman/gg v1.3.0
|
||||
github.com/fumiama/cron v1.3.0
|
||||
github.com/fumiama/go-base16384 v1.2.1
|
||||
@@ -22,4 +23,5 @@ require (
|
||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
|
||||
github.com/tidwall/gjson v1.11.0
|
||||
github.com/wdvxdr1123/ZeroBot v1.4.1
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
|
||||
)
|
||||
|
||||
8
go.sum
8
go.sum
@@ -19,6 +19,8 @@ github.com/antchfx/htmlquery v1.2.3 h1:sP3NFDneHx2stfNXCKbhHFo8XgNjCACnU/4AO5gWz
|
||||
github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
|
||||
github.com/antchfx/xpath v1.1.6 h1:6sVh6hB5T6phw1pFpHRQ+C4bd8sNI+O58flqtg7h0R0=
|
||||
github.com/antchfx/xpath v1.1.6/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
|
||||
github.com/corona10/goimagehash v1.0.3 h1:NZM518aKLmoNluluhfHGxT3LGOnrojrxhGn63DR/CZA=
|
||||
github.com/corona10/goimagehash v1.0.3/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
|
||||
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=
|
||||
@@ -39,10 +41,6 @@ github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
|
||||
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
|
||||
github.com/fumiama/go-base16384 v1.2.1 h1:6OGprW8g/95m2ocmryHi8mipZ7bx9StFMZDKEqLvMiA=
|
||||
github.com/fumiama/go-base16384 v1.2.1/go.mod h1:1HTC0QFL7BjS0DuO5Qm+fBYKQkHqmAapLbRpCxrhPXQ=
|
||||
github.com/fumiama/gofastTEA v0.0.3 h1:JKcNktWArLkJe88Y+zGmsQGhqlh8IzYqUnWy2ipylh0=
|
||||
github.com/fumiama/gofastTEA v0.0.3/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
|
||||
github.com/fumiama/gofastTEA v0.0.4 h1:SOWEIXBkFekhaxZoLEFk/L3rOh2X1G5PeM2TLAZycaQ=
|
||||
github.com/fumiama/gofastTEA v0.0.4/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
|
||||
github.com/fumiama/gofastTEA v0.0.5 h1:Pd/2eSfLl2V0CqZL8pnu1CIU8Fy4HYpLutpliXU70Ds=
|
||||
github.com/fumiama/gofastTEA v0.0.5/go.mod h1:+sBZ05nCA2skZkursHNvyr8kULlEetrYTM2y5kA4rQc=
|
||||
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
|
||||
@@ -114,6 +112,8 @@ github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b h1:6Xjqolv/0D
|
||||
github.com/modern-go/reflect2 v1.0.2-0.20210109003243-333559e1834b/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mroth/weightedrand v0.4.1 h1:rHcbUBopmi/3x4nnrvwGJBhX9d0vk+KgoLUZeDP6YyI=
|
||||
github.com/mroth/weightedrand v0.4.1/go.mod h1:3p2SIcC8al1YMzGhAIoXD+r9olo/g/cdJgAD905gyNE=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
|
||||
5
main.go
5
main.go
@@ -26,6 +26,7 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_translation" // 翻译
|
||||
|
||||
// 娱乐类
|
||||
// _ "github.com/FloatTech/ZeroBot-Plugin/plugin_wtf" // 鬼东西
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin-Gif" // 制图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_false" // 服务器监控
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_choose" // 选择困难症帮手
|
||||
@@ -37,7 +38,6 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji" // 浅草寺求签
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn" // 投胎
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shindan" // 测定
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_wtf" // 鬼东西
|
||||
|
||||
// b站相关
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_bilibili" // 查询b站用户信息
|
||||
@@ -48,6 +48,7 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_aiwife" // 随机老婆
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_image_finder" // 关键字搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_lolicon" // lolicon 随机图片
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_nativesetu" // 本地涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_saucenao" // 以图搜图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_setutime" // 来份涩图
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_tracemoe" // 搜番
|
||||
@@ -63,7 +64,7 @@ import (
|
||||
var (
|
||||
contents = []string{
|
||||
"* OneBot + ZeroBot + Golang",
|
||||
"* Version 1.2.0 - 2021-10-29 13:08:45 +0800 CST",
|
||||
"* Version 1.2.1 - 2021-11-29 20:27:37 +0800 CST",
|
||||
"* Copyright © 2020 - 2021 FloatTech. All Rights Reserved.",
|
||||
"* Project: https://github.com/FloatTech/ZeroBot-Plugin",
|
||||
}
|
||||
|
||||
@@ -62,18 +62,6 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// Slice is the runtime representation of a slice.
|
||||
// It cannot be used safely or portably and its representation may
|
||||
// change in a later release.
|
||||
//
|
||||
// Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the
|
||||
// data it references will not be garbage collected.
|
||||
type slice struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
Cap int
|
||||
}
|
||||
|
||||
func getea(key string) tea.TEA {
|
||||
kr := []rune(key)
|
||||
if len(kr) > 4 {
|
||||
@@ -83,8 +71,5 @@ func getea(key string) tea.TEA {
|
||||
kr = append(kr, rune(4-len(kr)))
|
||||
}
|
||||
}
|
||||
skr := *(*slice)(unsafe.Pointer(&kr))
|
||||
skr.Len *= 4
|
||||
skr.Cap *= 4
|
||||
return tea.NewTeaCipher(*(*[]byte)(unsafe.Pointer(&skr)))
|
||||
return *(*tea.TEA)(*(*unsafe.Pointer)(unsafe.Pointer(&kr)))
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/fumiama/cron"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
@@ -23,88 +24,128 @@ type follower struct {
|
||||
|
||||
// 开启日报推送
|
||||
func init() {
|
||||
engine.OnFullMatch("/开启粉丝日报", zero.AdminPermission).SetBlock(true).
|
||||
fansDaily()
|
||||
en := control.Register("fansdaily", &control.Options{
|
||||
DisableOnDefault: true,
|
||||
Help: "fansdaily\n- /开启粉丝日报\n- /关闭粉丝日报",
|
||||
})
|
||||
zero.OnCommand("开启粉丝日报", zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
fansDaily(ctx.Event.GroupID) // 群号传进去给下面发信息的函数
|
||||
m, ok := control.Lookup("fansdaily")
|
||||
if ok {
|
||||
if m.IsEnabledIn(ctx.Event.GroupID) {
|
||||
ctx.Send(message.Text("已启用!"))
|
||||
} else {
|
||||
m.Enable(ctx.Event.GroupID)
|
||||
ctx.Send(message.Text("添加成功!"))
|
||||
}
|
||||
} else {
|
||||
ctx.Send(message.Text("找不到该服务!"))
|
||||
}
|
||||
})
|
||||
en.OnCommand("关闭粉丝日报", zero.AdminPermission).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
m, ok := control.Lookup("fansdaily")
|
||||
if ok {
|
||||
if m.IsEnabledIn(ctx.Event.GroupID) {
|
||||
m.Disable(ctx.Event.GroupID)
|
||||
ctx.Send(message.Text("关闭成功!"))
|
||||
} else {
|
||||
ctx.Send(message.Text("未启用!"))
|
||||
}
|
||||
} else {
|
||||
ctx.Send(message.Text("找不到该服务!"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 定时任务每天晚上最后2分钟执行一次
|
||||
func fansDaily(groupID int64) {
|
||||
func fansDaily() {
|
||||
c := cron.New()
|
||||
_, err := c.AddFunc("58 23 * * *", func() { fansData(groupID) })
|
||||
_, err := c.AddFunc("58 23 * * *", func() { sendNotice() })
|
||||
if err == nil {
|
||||
c.Start()
|
||||
}
|
||||
}
|
||||
|
||||
// 获取数据拼接消息链并发送
|
||||
func fansData(groupID int64) {
|
||||
// TODO: 更改为 GetBot
|
||||
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
|
||||
var (
|
||||
diana = fansapi("672328094")
|
||||
ava = fansapi("672346917")
|
||||
eileen = fansapi("672342685")
|
||||
bella = fansapi("672353429")
|
||||
carol = fansapi("351609538")
|
||||
)
|
||||
ctx.SendGroupMessage(
|
||||
groupID,
|
||||
message.Text(
|
||||
time.Now().Format("2006-01-02"), " Asoul全团粉丝日报如下", "\n\n",
|
||||
"uid: ", diana.Mid, "\n",
|
||||
"名字: ", diana.Uname, "\n",
|
||||
"当前粉丝数: ", diana.Follower, "\n",
|
||||
"今日涨粉数: ", diana.Rise, "\n",
|
||||
"视频投稿数: ", diana.Video, "\n",
|
||||
"直播间id: ", diana.Roomid, "\n",
|
||||
"舰队: ", diana.GuardNum, "\n",
|
||||
"直播总排名: ", diana.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672328094", "\n\n",
|
||||
func getMsg() message.MessageSegment {
|
||||
var (
|
||||
diana = fansapi("672328094")
|
||||
ava = fansapi("672346917")
|
||||
eileen = fansapi("672342685")
|
||||
bella = fansapi("672353429")
|
||||
carol = fansapi("351609538")
|
||||
)
|
||||
return message.Text(
|
||||
time.Now().Format("2006-01-02"), " Asoul全团粉丝日报如下", "\n\n",
|
||||
"uid: ", diana.Mid, "\n",
|
||||
"名字: ", diana.Uname, "\n",
|
||||
"当前粉丝数: ", diana.Follower, "\n",
|
||||
"今日涨粉数: ", diana.Rise, "\n",
|
||||
"视频投稿数: ", diana.Video, "\n",
|
||||
"直播间id: ", diana.Roomid, "\n",
|
||||
"舰队: ", diana.GuardNum, "\n",
|
||||
"直播总排名: ", diana.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672328094", "\n\n",
|
||||
|
||||
"uid: ", ava.Mid, "\n",
|
||||
"名字: ", ava.Uname, "\n",
|
||||
"当前粉丝数: ", ava.Follower, "\n",
|
||||
"今日涨粉数: ", ava.Rise, "\n",
|
||||
"视频投稿数: ", ava.Video, "\n",
|
||||
"直播间id: ", ava.Roomid, "\n",
|
||||
"舰队: ", ava.GuardNum, "\n",
|
||||
"直播总排名: ", ava.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672346917", "\n\n",
|
||||
"uid: ", ava.Mid, "\n",
|
||||
"名字: ", ava.Uname, "\n",
|
||||
"当前粉丝数: ", ava.Follower, "\n",
|
||||
"今日涨粉数: ", ava.Rise, "\n",
|
||||
"视频投稿数: ", ava.Video, "\n",
|
||||
"直播间id: ", ava.Roomid, "\n",
|
||||
"舰队: ", ava.GuardNum, "\n",
|
||||
"直播总排名: ", ava.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672346917", "\n\n",
|
||||
|
||||
"uid: ", eileen.Mid, "\n",
|
||||
"名字: ", eileen.Uname, "\n",
|
||||
"当前粉丝数: ", eileen.Follower, "\n",
|
||||
"今日涨粉数: ", eileen.Rise, "\n",
|
||||
"视频投稿数: ", eileen.Video, "\n",
|
||||
"直播间id: ", eileen.Roomid, "\n",
|
||||
"舰队: ", eileen.GuardNum, "\n",
|
||||
"直播总排名: ", eileen.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672342685", "\n\n",
|
||||
"uid: ", eileen.Mid, "\n",
|
||||
"名字: ", eileen.Uname, "\n",
|
||||
"当前粉丝数: ", eileen.Follower, "\n",
|
||||
"今日涨粉数: ", eileen.Rise, "\n",
|
||||
"视频投稿数: ", eileen.Video, "\n",
|
||||
"直播间id: ", eileen.Roomid, "\n",
|
||||
"舰队: ", eileen.GuardNum, "\n",
|
||||
"直播总排名: ", eileen.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672342685", "\n\n",
|
||||
|
||||
"uid: ", bella.Mid, "\n",
|
||||
"名字: ", bella.Uname, "\n",
|
||||
"当前粉丝数: ", bella.Follower, "\n",
|
||||
"今日涨粉数: ", bella.Rise, "\n",
|
||||
"视频投稿数: ", bella.Video, "\n",
|
||||
"直播间id: ", bella.Roomid, "\n",
|
||||
"舰队: ", bella.GuardNum, "\n",
|
||||
"直播总排名: ", bella.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672353429", "\n\n",
|
||||
"uid: ", bella.Mid, "\n",
|
||||
"名字: ", bella.Uname, "\n",
|
||||
"当前粉丝数: ", bella.Follower, "\n",
|
||||
"今日涨粉数: ", bella.Rise, "\n",
|
||||
"视频投稿数: ", bella.Video, "\n",
|
||||
"直播间id: ", bella.Roomid, "\n",
|
||||
"舰队: ", bella.GuardNum, "\n",
|
||||
"直播总排名: ", bella.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "672353429", "\n\n",
|
||||
|
||||
"uid: ", carol.Mid, "\n",
|
||||
"名字: ", carol.Uname, "\n",
|
||||
"当前粉丝数: ", carol.Follower, "\n",
|
||||
"今日涨粉数: ", carol.Rise, "\n",
|
||||
"视频投稿数: ", carol.Video, "\n",
|
||||
"直播间id: ", carol.Roomid, "\n",
|
||||
"舰队: ", carol.GuardNum, "\n",
|
||||
"直播总排名: ", carol.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "351609538",
|
||||
))
|
||||
return true
|
||||
})
|
||||
"uid: ", carol.Mid, "\n",
|
||||
"名字: ", carol.Uname, "\n",
|
||||
"当前粉丝数: ", carol.Follower, "\n",
|
||||
"今日涨粉数: ", carol.Rise, "\n",
|
||||
"视频投稿数: ", carol.Video, "\n",
|
||||
"直播间id: ", carol.Roomid, "\n",
|
||||
"舰队: ", carol.GuardNum, "\n",
|
||||
"直播总排名: ", carol.AreaRank, "\n",
|
||||
"数据来源: ", "https://vtbs.moe/detail/", "351609538",
|
||||
)
|
||||
}
|
||||
|
||||
// 获取数据拼接消息链并发送
|
||||
func sendNotice() {
|
||||
m, ok := control.Lookup("fansdaily")
|
||||
if ok {
|
||||
msg := getMsg()
|
||||
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
|
||||
for _, g := range ctx.GetGroupList().Array() {
|
||||
grp := g.Get("group_id").Int()
|
||||
if m.IsEnabledIn(grp) {
|
||||
ctx.SendGroupMessage(grp, msg)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 请求api
|
||||
|
||||
@@ -16,8 +16,7 @@ var engine = control.Register("bilibili", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "bilibili\n" +
|
||||
"- >vup info [名字|uid]\n" +
|
||||
"- >user info [名字|uid]\n" +
|
||||
"- /开启粉丝日报",
|
||||
"- >user info [名字|uid]",
|
||||
})
|
||||
|
||||
// 查成分的
|
||||
|
||||
131
plugin_nativesetu/data.go
Normal file
131
plugin_nativesetu/data.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package nativesetu
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/corona10/goimagehash"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
"golang.org/x/image/webp"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
|
||||
)
|
||||
|
||||
// setuclass holds setus in a folder, which is the class name.
|
||||
type setuclass struct {
|
||||
ImgID int64 `db:"imgid"` // ImgID 图片唯一 id (dhash)
|
||||
Name string `db:"name"` // Name 图片名
|
||||
Path string `db:"path"` // Path 图片路径
|
||||
}
|
||||
|
||||
var (
|
||||
setuclasses []string
|
||||
db = &sql.Sqlite{DBPath: dbfile}
|
||||
mu sync.RWMutex
|
||||
)
|
||||
|
||||
func init() {
|
||||
go func() {
|
||||
process.SleepAbout1sTo2s()
|
||||
err := os.MkdirAll(datapath, 0755)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if file.IsExist(cfgfile) {
|
||||
b, err := os.ReadFile(cfgfile)
|
||||
if err == nil {
|
||||
setupath = helper.BytesToString(b)
|
||||
logrus.Println("[nsetu] set setu dir to", setupath)
|
||||
}
|
||||
}
|
||||
if file.IsExist(dbfile) {
|
||||
err := db.Open()
|
||||
if err == nil {
|
||||
setuclasses, err = db.ListTables()
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Errorln("[nsetu]", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func scanall(path string) error {
|
||||
setuclasses = nil
|
||||
model := &setuclass{}
|
||||
root := os.DirFS(path)
|
||||
_ = db.Close()
|
||||
_ = os.Remove(dbfile)
|
||||
return fs.WalkDir(root, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() {
|
||||
clsn := d.Name()
|
||||
if clsn != "." {
|
||||
mu.Lock()
|
||||
err = db.Create(clsn, model)
|
||||
setuclasses = append(setuclasses, clsn)
|
||||
mu.Unlock()
|
||||
if err == nil {
|
||||
err = scanclass(root, path, clsn)
|
||||
if err != nil {
|
||||
logrus.Errorln("[nsetu]", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func scanclass(root fs.FS, path, clsn string) error {
|
||||
ds, err := fs.ReadDir(root, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mu.Lock()
|
||||
_ = db.Truncate(clsn)
|
||||
mu.Unlock()
|
||||
for _, d := range ds {
|
||||
if !d.IsDir() {
|
||||
relpath := path + "/" + d.Name()
|
||||
fullpath := setupath + "/" + relpath
|
||||
logrus.Debugln("[nsetu] read", fullpath)
|
||||
f, e := os.ReadFile(fullpath)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
b := bytes.NewReader(f)
|
||||
img, _, e := image.Decode(b)
|
||||
if e != nil {
|
||||
b.Seek(0, io.SeekStart)
|
||||
img, e = webp.Decode(b)
|
||||
}
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
dh, e := goimagehash.DifferenceHash(img)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
dhi := int64(dh.GetHash())
|
||||
logrus.Debugln("[nsetu] insert", d.Name(), "with id", dhi, "into", clsn)
|
||||
mu.Lock()
|
||||
err = db.Insert(clsn, &setuclass{ImgID: dhi, Name: d.Name(), Path: relpath})
|
||||
mu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
94
plugin_nativesetu/main.go
Normal file
94
plugin_nativesetu/main.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package nativesetu
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/rule"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
)
|
||||
|
||||
const (
|
||||
datapath = "data/nsetu"
|
||||
dbfile = datapath + "/data.db"
|
||||
cfgfile = datapath + "/setupath.txt"
|
||||
)
|
||||
|
||||
var (
|
||||
setupath = "/tmp" // 绝对路径,图片根目录
|
||||
)
|
||||
|
||||
func init() {
|
||||
engine := control.Register("nativesetu", &control.Options{
|
||||
DisableOnDefault: false,
|
||||
Help: "本地涩图\n" +
|
||||
"- 本地[xxx]\n" +
|
||||
"- 刷新本地[xxx]\n" +
|
||||
"- 设置本地setu绝对路径[xxx]\n" +
|
||||
"- 刷新所有本地setu\n" +
|
||||
"- 所有本地setu分类",
|
||||
})
|
||||
engine.OnRegex(`^本地(.*)$`, func(ctx *zero.Ctx) bool { return rule.FirstValueInList(setuclasses)(ctx) }).SetBlock(true).SetPriority(36).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
imgtype := ctx.State["regex_matched"].([]string)[1]
|
||||
sc := new(setuclass)
|
||||
mu.RLock()
|
||||
err := db.Pick(imgtype, sc)
|
||||
mu.RUnlock()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
} else {
|
||||
p := "file:///" + setupath + "/" + sc.Path
|
||||
ctx.SendChain(message.Text(imgtype, ": ", sc.Name, "\n"), message.Image(p))
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^刷新本地(.*)$`, func(ctx *zero.Ctx) bool { return rule.FirstValueInList(setuclasses)(ctx) }, zero.SuperUserPermission).SetBlock(true).SetPriority(36).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
imgtype := ctx.State["regex_matched"].([]string)[1]
|
||||
err := scanclass(os.DirFS(setupath), imgtype, imgtype)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
})
|
||||
engine.OnRegex(`^设置本地setu绝对路径(.*)$`, zero.SuperUserPermission).SetBlock(true).SetPriority(36).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
setupath = ctx.State["regex_matched"].([]string)[1]
|
||||
err := os.WriteFile(cfgfile, helper.StringToBytes(setupath), 0644)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("刷新所有本地setu", zero.SuperUserPermission).SetBlock(true).SetPriority(36).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
err := scanall(setupath)
|
||||
if err == nil {
|
||||
ctx.SendChain(message.Text("成功!"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("所有本地setu分类").SetBlock(true).SetPriority(36).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
msg := "所有本地setu分类"
|
||||
mu.RLock()
|
||||
for i, c := range setuclasses {
|
||||
n, err := db.Count(c)
|
||||
if err == nil {
|
||||
msg += fmt.Sprintf("\n%02d. %s(%d)", i, c, n)
|
||||
} else {
|
||||
msg += fmt.Sprintf("\n%02d. %s(error)", i, c)
|
||||
logrus.Errorln("[nsetu]", err)
|
||||
}
|
||||
}
|
||||
mu.RUnlock()
|
||||
ctx.SendChain(message.Text(msg))
|
||||
})
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
prio = 100
|
||||
prio = 256
|
||||
bucket = rate.NewManager(time.Minute, 20) // 青云客接口回复
|
||||
engine *zero.Engine
|
||||
)
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/FloatTech/ZeroBot-Plugin/control"
|
||||
fileutil "github.com/FloatTech/ZeroBot-Plugin/utils/file"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/math"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/rule"
|
||||
"github.com/FloatTech/ZeroBot-Plugin/utils/sql"
|
||||
)
|
||||
|
||||
@@ -112,7 +113,7 @@ func init() { // 插件主体
|
||||
"- 删除[涩图/二次元/风景/车万][P站图片ID]\n" +
|
||||
"- >setu status",
|
||||
})
|
||||
engine.OnRegex(`^来份(.*)$`, firstValueInList(pool.List)).SetBlock(true).SetPriority(20).
|
||||
engine.OnRegex(`^来份(.*)$`, rule.FirstValueInList(pool.List)).SetBlock(true).SetPriority(20).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
if !limit.Load(ctx.Event.UserID).Acquire() {
|
||||
ctx.SendChain(message.Text("请稍后重试0x0..."))
|
||||
@@ -125,7 +126,7 @@ func init() { // 插件主体
|
||||
for i := 0; i < times; i++ {
|
||||
illust := &pixiv.Illust{}
|
||||
// 查询出一张图片
|
||||
if err := pool.DB.Find(imgtype, illust, "ORDER BY RANDOM() limit 1"); err != nil {
|
||||
if err := pool.DB.Pick(imgtype, illust); err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
continue
|
||||
}
|
||||
@@ -155,7 +156,7 @@ func init() { // 插件主体
|
||||
}
|
||||
})
|
||||
|
||||
engine.OnRegex(`^添加(.*?)(\d+)$`, firstValueInList(pool.List), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
|
||||
engine.OnRegex(`^添加(.*?)(\d+)$`, rule.FirstValueInList(pool.List), zero.SuperUserPermission).SetBlock(true).SetPriority(21).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var (
|
||||
imgtype = ctx.State["regex_matched"].([]string)[1]
|
||||
@@ -186,7 +187,7 @@ func init() { // 插件主体
|
||||
ctx.SendChain(message.Text("添加成功"))
|
||||
})
|
||||
|
||||
engine.OnRegex(`^删除(.*?)(\d+)$`, firstValueInList(pool.List), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
|
||||
engine.OnRegex(`^删除(.*?)(\d+)$`, rule.FirstValueInList(pool.List), zero.SuperUserPermission).SetBlock(true).SetPriority(22).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var (
|
||||
imgtype = ctx.State["regex_matched"].([]string)[1]
|
||||
@@ -218,19 +219,6 @@ func init() { // 插件主体
|
||||
})
|
||||
}
|
||||
|
||||
// firstValueInList 判断正则匹配的第一个参数是否在列表中
|
||||
func firstValueInList(list []string) zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
first := ctx.State["regex_matched"].([]string)[1]
|
||||
for i := range list {
|
||||
if first == list[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// size 返回缓冲池指定类型的现有大小
|
||||
func (p *imgpool) size(imgtype string) int {
|
||||
return len(p.Pool[imgtype])
|
||||
|
||||
16
utils/rule/extension.go
Normal file
16
utils/rule/extension.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package rule
|
||||
|
||||
import zero "github.com/wdvxdr1123/ZeroBot"
|
||||
|
||||
// FirstValueInList 判断正则匹配的第一个参数是否在列表中
|
||||
func FirstValueInList(list []string) zero.Rule {
|
||||
return func(ctx *zero.Ctx) bool {
|
||||
first := ctx.State["regex_matched"].([]string)[1]
|
||||
for _, v := range list {
|
||||
if first == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package sql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
@@ -15,6 +16,27 @@ type Sqlite struct {
|
||||
DBPath string
|
||||
}
|
||||
|
||||
// Open 打开数据库
|
||||
func (db *Sqlite) Open() (err error) {
|
||||
if db.DB == nil {
|
||||
database, err := sql.Open("sqlite3", db.DBPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
db.DB = database
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Close 关闭数据库
|
||||
func (db *Sqlite) Close() (err error) {
|
||||
if db.DB != nil {
|
||||
err = db.DB.Close()
|
||||
db.DB = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Create 生成数据库
|
||||
// 默认结构体的第一个元素为主键
|
||||
// 返回错误
|
||||
@@ -56,7 +78,7 @@ func (db *Sqlite) Create(table string, objptr interface{}) (err error) {
|
||||
// 默认结构体的第一个元素为主键
|
||||
// 返回错误
|
||||
func (db *Sqlite) Insert(table string, objptr interface{}) error {
|
||||
rows, err := db.DB.Query("SELECT * FROM " + table + ";")
|
||||
rows, err := db.DB.Query("SELECT * FROM " + table + " limit 1;")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -66,9 +88,9 @@ func (db *Sqlite) Insert(table string, objptr interface{}) error {
|
||||
tags, _ := rows.Columns()
|
||||
rows.Close()
|
||||
var (
|
||||
values = values(objptr)
|
||||
top = len(tags) - 1
|
||||
cmd = []string{}
|
||||
vals = values(objptr)
|
||||
top = len(tags) - 1
|
||||
cmd = []string{}
|
||||
)
|
||||
cmd = append(cmd, "REPLACE INTO")
|
||||
cmd = append(cmd, table)
|
||||
@@ -104,7 +126,7 @@ func (db *Sqlite) Insert(table string, objptr interface{}) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = stmt.Exec(values...)
|
||||
_, err = stmt.Exec(vals...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -129,16 +151,22 @@ func (db *Sqlite) Find(table string, objptr interface{}, condition string) error
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if !rows.Next() {
|
||||
return errors.New("sql.Find: null result")
|
||||
}
|
||||
err = rows.Scan(addrs(objptr)...)
|
||||
for rows.Next() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = rows.Scan(addrs(objptr)...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// Pick 从 table 随机一行
|
||||
func (db *Sqlite) Pick(table string, objptr interface{}) error {
|
||||
return db.Find(table, objptr, "ORDER BY RANDOM() limit 1")
|
||||
}
|
||||
|
||||
// ListTables 列出所有表名
|
||||
@@ -166,7 +194,7 @@ func (db *Sqlite) ListTables() (s []string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Del 删除数据库
|
||||
// Del 删除数据库表项
|
||||
// condition 可为"WHERE id = 0"
|
||||
// 返回错误
|
||||
func (db *Sqlite) Del(table string, condition string) error {
|
||||
@@ -185,11 +213,27 @@ func (db *Sqlite) Del(table string, condition string) error {
|
||||
return stmt.Close()
|
||||
}
|
||||
|
||||
// Truncate 清空数据库表
|
||||
func (db *Sqlite) Truncate(table string) error {
|
||||
var cmd = []string{}
|
||||
cmd = append(cmd, "TRUNCATE TABLE")
|
||||
cmd = append(cmd, table)
|
||||
stmt, err := db.DB.Prepare(strings.Join(cmd, " ") + ";")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = stmt.Exec()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return stmt.Close()
|
||||
}
|
||||
|
||||
// Count 查询数据库行数
|
||||
// 返回行数以及错误
|
||||
func (db *Sqlite) Count(table string) (num int, err error) {
|
||||
var cmd = []string{}
|
||||
cmd = append(cmd, "SELECT * FROM")
|
||||
cmd = append(cmd, "SELECT COUNT(1) FROM")
|
||||
cmd = append(cmd, table)
|
||||
rows, err := db.DB.Query(strings.Join(cmd, " ") + ";")
|
||||
if err != nil {
|
||||
@@ -198,8 +242,8 @@ func (db *Sqlite) Count(table string) (num int, err error) {
|
||||
if rows.Err() != nil {
|
||||
return num, rows.Err()
|
||||
}
|
||||
for rows.Next() {
|
||||
num++
|
||||
if rows.Next() {
|
||||
rows.Scan(&num)
|
||||
}
|
||||
rows.Close()
|
||||
return num, nil
|
||||
@@ -229,8 +273,22 @@ func kinds(objptr interface{}) []string {
|
||||
}
|
||||
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
|
||||
switch elem.Field(i).Type().String() {
|
||||
case "int64":
|
||||
case "int8":
|
||||
kinds = append(kinds, "TINYINT")
|
||||
case "uint8", "byte":
|
||||
kinds = append(kinds, "UNSIGNED TINYINT")
|
||||
case "int16":
|
||||
kinds = append(kinds, "SMALLINT")
|
||||
case "uint16":
|
||||
kinds = append(kinds, "UNSIGNED SMALLINT")
|
||||
case "int32":
|
||||
kinds = append(kinds, "INT")
|
||||
case "uint32":
|
||||
kinds = append(kinds, "UNSIGNED INT")
|
||||
case "int64":
|
||||
kinds = append(kinds, "BIGINT")
|
||||
case "uint64":
|
||||
kinds = append(kinds, "UNSIGNED BIGINT")
|
||||
case "string":
|
||||
kinds = append(kinds, "TEXT")
|
||||
default:
|
||||
@@ -249,14 +307,7 @@ func values(objptr interface{}) []interface{} {
|
||||
elem = elem.Field(0)
|
||||
}
|
||||
for i, flen := 0, elem.Type().NumField(); i < flen; i++ {
|
||||
switch elem.Field(i).Type().String() {
|
||||
case "int64":
|
||||
values = append(values, elem.Field(i).Int())
|
||||
case "string":
|
||||
values = append(values, elem.Field(i).String())
|
||||
default:
|
||||
values = append(values, elem.Field(i).String())
|
||||
}
|
||||
values = append(values, elem.Field(i).Interface())
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user