️ 优化 rule.FirstValueInList

This commit is contained in:
fumiama 2022-01-30 20:05:39 +08:00
parent ded20441fa
commit ec5798f264
5 changed files with 88 additions and 76 deletions

4
go.mod
View File

@ -3,8 +3,8 @@ module github.com/FloatTech/ZeroBot-Plugin
go 1.17 go 1.17
require ( require (
github.com/FloatTech/AnimeAPI v1.2.4-fix13 github.com/FloatTech/AnimeAPI v1.2.5-beta1
github.com/FloatTech/zbputils v1.2.4-fix7 github.com/FloatTech/zbputils v1.2.5-beta1
github.com/antchfx/htmlquery v1.2.4 github.com/antchfx/htmlquery v1.2.4
github.com/corona10/goimagehash v1.0.3 github.com/corona10/goimagehash v1.0.3
github.com/fogleman/gg v1.3.0 github.com/fogleman/gg v1.3.0

8
go.sum
View File

@ -1,8 +1,8 @@
github.com/FloatTech/AnimeAPI v1.2.4-fix13 h1:sAaVw946DMId2absfBQTlbcBWwZ02CRgpitTs/vm3r4= github.com/FloatTech/AnimeAPI v1.2.5-beta1 h1:Iv/Uy7ODu06Rd0n9CzUsivfHfI/Nmg4cHHdMU5j6FX4=
github.com/FloatTech/AnimeAPI v1.2.4-fix13/go.mod h1:ttVc5AiHkQOGOjKgrAS0yZFRefGwlMsBCxFwEPXznYs= github.com/FloatTech/AnimeAPI v1.2.5-beta1/go.mod h1:tWU3xDvkSqnFD8SCTS5oko1UhkVlrNLK6PmN0ea6n6Q=
github.com/FloatTech/bot-manager v1.0.0/go.mod h1:8YYRJ16oroGHQGD2En0oVnmcKJkxR9O/jd5BPSfWfOQ= github.com/FloatTech/bot-manager v1.0.0/go.mod h1:8YYRJ16oroGHQGD2En0oVnmcKJkxR9O/jd5BPSfWfOQ=
github.com/FloatTech/zbputils v1.2.4-fix7 h1:rgjiy9b/vkqUDmRjrjzGlSjKCNPMY+0dybuhar2CfF4= github.com/FloatTech/zbputils v1.2.5-beta1 h1:wptmjPpsaoK77igPKFmdUB86AWPyNyuEtT7LNYt2t4U=
github.com/FloatTech/zbputils v1.2.4-fix7/go.mod h1:1VE4gxnrr+uRz/TDPgx3GT8GmVayoF5e0wolBQU3t+k= github.com/FloatTech/zbputils v1.2.5-beta1/go.mod h1:1VE4gxnrr+uRz/TDPgx3GT8GmVayoF5e0wolBQU3t+k=
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb h1:Rkj28fqIwGx/EgBzRYtpmJRfH6wqVn7cNdc7aJ0QE4M= github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb h1:Rkj28fqIwGx/EgBzRYtpmJRfH6wqVn7cNdc7aJ0QE4M=
github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb/go.mod h1:imVKbfKqqeit+C/eaWGb4MKQ3z3gN6pRpBU5RMtp5so= github.com/Mrs4s/MiraiGo v0.0.0-20211120033824-43b23f4e6fcb/go.mod h1:imVKbfKqqeit+C/eaWGb4MKQ3z3gN6pRpBU5RMtp5so=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=

View File

@ -5,6 +5,7 @@ import (
"image" "image"
"io/fs" "io/fs"
"os" "os"
"strings"
"sync" "sync"
"github.com/corona10/goimagehash" "github.com/corona10/goimagehash"
@ -24,11 +25,7 @@ type setuclass struct {
Path string `db:"path"` // Path 图片路径 Path string `db:"path"` // Path 图片路径
} }
var ( var ns *nsetu
setuclasses []string
db = &sql.Sqlite{DBPath: dbfile}
mu sync.RWMutex
)
func init() { func init() {
go func() { go func() {
@ -44,24 +41,33 @@ func init() {
logrus.Println("[nsetu] set setu dir to", setupath) logrus.Println("[nsetu] set setu dir to", setupath)
} }
} }
if file.IsExist(dbfile) { ns = &nsetu{db: &sql.Sqlite{DBPath: dbfile}}
err := db.Open()
if err == nil {
setuclasses, err = db.ListTables()
}
if err != nil {
logrus.Errorln("[nsetu]", err)
}
}
}() }()
} }
func scanall(path string) error { type nsetu struct {
setuclasses = nil db *sql.Sqlite
mu sync.RWMutex
}
func (n *nsetu) List() (l []string) {
if file.IsExist(n.db.DBPath) {
err := n.db.Open()
if err == nil {
l, err = n.db.ListTables()
}
if err != nil {
logrus.Errorln("[nsetu]", err)
}
}
return
}
func (n *nsetu) scanall(path string) error {
model := &setuclass{} model := &setuclass{}
root := os.DirFS(path) root := os.DirFS(path)
_ = db.Close() _ = n.db.Close()
_ = os.Remove(dbfile) _ = os.Remove(n.db.DBPath)
return fs.WalkDir(root, ".", func(path string, d fs.DirEntry, err error) error { return fs.WalkDir(root, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil { if err != nil {
return err return err
@ -69,12 +75,11 @@ func scanall(path string) error {
if d.IsDir() { if d.IsDir() {
clsn := d.Name() clsn := d.Name()
if clsn != "." { if clsn != "." {
mu.Lock() n.mu.Lock()
err = db.Create(clsn, model) err = n.db.Create(clsn, model)
setuclasses = append(setuclasses, clsn) n.mu.Unlock()
mu.Unlock()
if err == nil { if err == nil {
err = scanclass(root, path, clsn) err = n.scanclass(root, path, clsn)
if err != nil { if err != nil {
logrus.Errorln("[nsetu]", err) logrus.Errorln("[nsetu]", err)
return err return err
@ -86,17 +91,21 @@ func scanall(path string) error {
}) })
} }
func scanclass(root fs.FS, path, clsn string) error { func (n *nsetu) scanclass(root fs.FS, path, clsn string) error {
ds, err := fs.ReadDir(root, path) ds, err := fs.ReadDir(root, path)
if err != nil { if err != nil {
return err return err
} }
mu.Lock() n.mu.Lock()
_ = db.Truncate(clsn) _ = n.db.Truncate(clsn)
mu.Unlock() n.mu.Unlock()
for _, d := range ds { for _, d := range ds {
if !d.IsDir() { nm := d.Name()
relpath := path + "/" + d.Name() ln := strings.ToLower(nm)
if !d.IsDir() &&
(strings.HasSuffix(ln, ".jpg") || strings.HasSuffix(ln, ".jpeg") ||
strings.HasSuffix(ln, ".png") || strings.HasSuffix(ln, ".gif") || strings.HasSuffix(ln, ".webp")) {
relpath := path + "/" + nm
logrus.Debugln("[nsetu] read", relpath) logrus.Debugln("[nsetu] read", relpath)
f, e := fs.ReadFile(root, relpath) f, e := fs.ReadFile(root, relpath)
if e != nil { if e != nil {
@ -112,10 +121,10 @@ func scanclass(root fs.FS, path, clsn string) error {
return e return e
} }
dhi := int64(dh.GetHash()) dhi := int64(dh.GetHash())
logrus.Debugln("[nsetu] insert", d.Name(), "with id", dhi, "into", clsn) logrus.Debugln("[nsetu] insert", nm, "with id", dhi, "into", clsn)
mu.Lock() n.mu.Lock()
err = db.Insert(clsn, &setuclass{ImgID: dhi, Name: d.Name(), Path: relpath}) err = n.db.Insert(clsn, &setuclass{ImgID: dhi, Name: nm, Path: relpath})
mu.Unlock() n.mu.Unlock()
if err != nil { if err != nil {
return err return err
} }

View File

@ -36,13 +36,13 @@ func init() {
"- 刷新所有本地setu\n" + "- 刷新所有本地setu\n" +
"- 所有本地setu分类", "- 所有本地setu分类",
}) })
engine.OnRegex(`^本地(.*)$`, func(ctx *zero.Ctx) bool { return rule.FirstValueInList(setuclasses)(ctx) }).SetBlock(true). engine.OnRegex(`^本地(.*)$`, rule.FirstValueInList(ns)).SetBlock(true).
Handle(func(ctx *zero.Ctx) { Handle(func(ctx *zero.Ctx) {
imgtype := ctx.State["regex_matched"].([]string)[1] imgtype := ctx.State["regex_matched"].([]string)[1]
sc := new(setuclass) sc := new(setuclass)
mu.RLock() ns.mu.RLock()
err := db.Pick(imgtype, sc) err := ns.db.Pick(imgtype, sc)
mu.RUnlock() ns.mu.RUnlock()
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
} else { } else {
@ -50,10 +50,10 @@ func init() {
ctx.SendChain(message.Text(imgtype, ": ", sc.Name, "\n"), message.Image(p)) 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). engine.OnRegex(`^刷新本地(.*)$`, rule.FirstValueInList(ns), zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) { Handle(func(ctx *zero.Ctx) {
imgtype := ctx.State["regex_matched"].([]string)[1] imgtype := ctx.State["regex_matched"].([]string)[1]
err := scanclass(os.DirFS(setupath), imgtype, imgtype) err := ns.scanclass(os.DirFS(setupath), imgtype, imgtype)
if err == nil { if err == nil {
ctx.SendChain(message.Text("成功!")) ctx.SendChain(message.Text("成功!"))
} else { } else {
@ -72,7 +72,7 @@ func init() {
}) })
engine.OnFullMatch("刷新所有本地setu", zero.SuperUserPermission).SetBlock(true). engine.OnFullMatch("刷新所有本地setu", zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) { Handle(func(ctx *zero.Ctx) {
err := scanall(setupath) err := ns.scanall(setupath)
if err == nil { if err == nil {
ctx.SendChain(message.Text("成功!")) ctx.SendChain(message.Text("成功!"))
} else { } else {
@ -82,9 +82,9 @@ func init() {
engine.OnFullMatch("所有本地setu分类").SetBlock(true). engine.OnFullMatch("所有本地setu分类").SetBlock(true).
Handle(func(ctx *zero.Ctx) { Handle(func(ctx *zero.Ctx) {
msg := "所有本地setu分类" msg := "所有本地setu分类"
mu.RLock() ns.mu.RLock()
for i, c := range setuclasses { for i, c := range ns.List() {
n, err := db.Count(c) n, err := ns.db.Count(c)
if err == nil { if err == nil {
msg += fmt.Sprintf("\n%02d. %s(%d)", i, c, n) msg += fmt.Sprintf("\n%02d. %s(%d)", i, c, n)
} else { } else {
@ -92,7 +92,7 @@ func init() {
logrus.Errorln("[nsetu]", err) logrus.Errorln("[nsetu]", err)
} }
} }
mu.RUnlock() ns.mu.RUnlock()
ctx.SendChain(message.Text(msg)) ctx.SendChain(message.Text(msg))
}) })
} }

View File

@ -35,7 +35,7 @@ type imgpool struct {
pool map[string][]*pixiv.Illust pool map[string][]*pixiv.Illust
} }
func (p *imgpool) list() (l []string) { func (p *imgpool) List() (l []string) {
var err error var err error
l, err = p.db.ListTables() l, err = p.db.ListTables()
if err != nil { if err != nil {
@ -44,7 +44,32 @@ func (p *imgpool) list() (l []string) {
return l return l
} }
var pool *imgpool
func init() { // 插件主体 func init() { // 插件主体
_ = os.MkdirAll("data/SetuTime", 0755)
go func() {
process.SleepAbout1sTo2s()
pool = &imgpool{
db: &sql.Sqlite{DBPath: "data/SetuTime/SetuTime.db"},
path: pixiv.CacheDir,
max: 10,
pool: map[string][]*pixiv.Illust{},
}
// 如果数据库不存在则下载
_, _ = fileutil.GetLazyData(pool.db.DBPath, false, false)
err := pool.db.Open()
if err != nil {
panic(err)
}
for _, imgtype := range pool.List() {
if err := pool.db.Create(imgtype, &pixiv.Illust{}); err != nil {
panic(err)
}
}
}()
limit := rate.NewManager(time.Minute*1, 5) limit := rate.NewManager(time.Minute*1, 5)
engine := control.Register("setutime", order.PrioSetuTime, &control.Options{ engine := control.Register("setutime", order.PrioSetuTime, &control.Options{
DisableOnDefault: false, DisableOnDefault: false,
@ -54,29 +79,7 @@ func init() { // 插件主体
"- 删除[涩图/二次元/风景/车万][P站图片ID]\n" + "- 删除[涩图/二次元/风景/车万][P站图片ID]\n" +
"- >setu status", "- >setu status",
}) })
process.SleepAbout1sTo2s() engine.OnRegex(`^来份(.*)$`, rule.FirstValueInList(pool)).SetBlock(true).
pool := func() *imgpool {
cache := &imgpool{
db: &sql.Sqlite{DBPath: "data/SetuTime/SetuTime.db"},
path: pixiv.CacheDir,
max: 10,
pool: map[string][]*pixiv.Illust{},
}
_ = os.MkdirAll("data/SetuTime", 0755)
// 如果数据库不存在则下载
_, _ = fileutil.GetLazyData(cache.db.DBPath, false, false)
err := cache.db.Open()
if err != nil {
panic(err)
}
for _, imgtype := range cache.list() {
if err := cache.db.Create(imgtype, &pixiv.Illust{}); err != nil {
panic(err)
}
}
return cache
}()
engine.OnRegex(`^来份(.*)$`, rule.FirstValueInList(pool.list())).SetBlock(true).
Handle(func(ctx *zero.Ctx) { Handle(func(ctx *zero.Ctx) {
if !limit.Load(ctx.Event.UserID).Acquire() { if !limit.Load(ctx.Event.UserID).Acquire() {
ctx.SendChain(message.Text("请稍后重试0x0...")) ctx.SendChain(message.Text("请稍后重试0x0..."))
@ -114,7 +117,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text("成功向分类", imgtype, "添加图片", id)) ctx.SendChain(message.Text("成功向分类", imgtype, "添加图片", id))
}) })
engine.OnRegex(`^删除(.*?)(\d+)$`, rule.FirstValueInList(pool.list()), zero.SuperUserPermission).SetBlock(true). engine.OnRegex(`^删除(.*?)(\d+)$`, rule.FirstValueInList(pool), zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) { Handle(func(ctx *zero.Ctx) {
var ( var (
imgtype = ctx.State["regex_matched"].([]string)[1] imgtype = ctx.State["regex_matched"].([]string)[1]
@ -132,7 +135,7 @@ func init() { // 插件主体
engine.OnFullMatchGroup([]string{">setu status"}).SetBlock(true). engine.OnFullMatchGroup([]string{">setu status"}).SetBlock(true).
Handle(func(ctx *zero.Ctx) { Handle(func(ctx *zero.Ctx) {
state := []string{"[SetuTime]"} state := []string{"[SetuTime]"}
for _, imgtype := range pool.list() { for _, imgtype := range pool.List() {
num, err := pool.db.Count(imgtype) num, err := pool.db.Count(imgtype)
if err != nil { if err != nil {
num = 0 num = 0