From ef9f764fa07661b366cfdd26a3e0045266d3aaa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Tue, 6 Sep 2022 21:20:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0ban=E4=BA=BA=E8=AE=B0?= =?UTF-8?q?=E5=BF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugin/antiabuse/anti.go | 33 +++++++++++++++++++++------ plugin/antiabuse/db.go | 48 ++++++++++++++++++++++++++++++++++------ 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/plugin/antiabuse/anti.go b/plugin/antiabuse/anti.go index 034a0f0c..218c8484 100644 --- a/plugin/antiabuse/anti.go +++ b/plugin/antiabuse/anti.go @@ -2,6 +2,7 @@ package antiabuse import ( + "strconv" "strings" "time" @@ -16,10 +17,12 @@ import ( "github.com/wdvxdr1123/ZeroBot/message" ) +const banhour = 4 + var ( managers *ctrl.Manager[*zero.Ctx] // managers lazy load - cache = ttl.NewCacheOn(4*time.Hour, [4]func(int64, struct{}){nil, nil, onDel, nil}) - db = &antidb{} + cache = ttl.NewCacheOn(banhour*time.Hour, [4]func(int64, struct{}){nil, nil, onDel, nil}) + db *antidb ) func onDel(uid int64, _ struct{}) { @@ -27,7 +30,10 @@ func onDel(uid int64, _ struct{}) { return } if err := managers.DoUnblock(uid); err != nil { - logrus.Errorln("[antiabuse] do unblock:", err) + logrus.Errorln("[antiabuse.onDel] unblock:", err) + } + if err := db.Del("__bantime__", "WHERE id="+strconv.FormatInt(uid, 10)); err != nil { + logrus.Errorln("[antiabuse.onDel] db:", err) } } @@ -40,8 +46,8 @@ func init() { onceRule := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool { managers = ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).Manager - db.DBPath = engine.DataFolder() + "anti_abuse.db" - err := db.Open(time.Hour * 4) + var err error + db, err = newantidb(engine.DataFolder() + "anti_abuse.db") if err != nil { ctx.SendChain(message.Text("ERROR: ", err)) return false @@ -61,9 +67,22 @@ func init() { msg = strings.ReplaceAll(msg, ";", "") if db.isInAntiList(uid, gid, msg) { if err := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).Manager.DoBlock(uid); err == nil { + t := time.Now().Unix() cache.Set(uid, struct{}{}) - ctx.SetGroupBan(gid, uid, 4*3600) - ctx.SendChain(message.Text("检测到违禁词, 已封禁/屏蔽4小时")) + ctx.SetGroupBan(gid, uid, banhour*3600) + ctx.SendChain(message.Text("检测到违禁词, 已封禁/屏蔽", banhour, "小时")) + db.Lock() + defer db.Unlock() + err := db.Create("__bantime__", nilbt) + if err != nil { + ctx.SendChain(message.Text("ERROR: ", err)) + return false + } + err = db.Insert("__bantime__", &banTime{ID: uid, Time: t}) + if err != nil { + ctx.SendChain(message.Text("ERROR: ", err)) + return false + } } else { ctx.SendChain(message.Text("ERROR: block user: ", err)) } diff --git a/plugin/antiabuse/db.go b/plugin/antiabuse/db.go index 91c15b82..6e25afe4 100644 --- a/plugin/antiabuse/db.go +++ b/plugin/antiabuse/db.go @@ -5,6 +5,7 @@ import ( "strconv" "strings" "sync" + "time" sqlite "github.com/FloatTech/sqlite" ) @@ -18,7 +19,34 @@ type banWord struct { Word string `db:"word"` } -var nilban = &banWord{} +type banTime struct { + ID int64 `db:"id"` + Time int64 `db:"time"` +} + +var ( + nilban = &banWord{} + nilbt = &banTime{} +) + +func newantidb(path string) (*antidb, error) { + db := &antidb{Sqlite: sqlite.Sqlite{DBPath: path}} + err := db.Open(time.Hour * banhour) + if err != nil { + return nil, err + } + _ = db.Del("__bantime__", "WHERE time<="+strconv.FormatInt(time.Now().Add(-time.Hour*banhour).Unix(), 10)) + return db, db.FindFor("__bantime__", nilbt, "", func() error { + t := time.Unix(nilbt.Time, 0) + ttl := time.Until(t.Add(time.Hour * banhour)) // second + if ttl < time.Minute { + return nil + } + cache.Set(nilbt.ID, struct{}{}) + cache.Touch(nilbt.ID, -time.Since(t)) + return nil + }) +} func (db *antidb) isInAntiList(uid, gid int64, msg string) bool { grp := strconv.FormatInt(gid, 36) @@ -52,15 +80,21 @@ func (db *antidb) listWords(gid int64) string { grp := strconv.FormatInt(gid, 36) word := &banWord{} sb := strings.Builder{} - db.Lock() - defer db.Unlock() + sb.WriteByte('[') + i := 0 + db.RLock() + defer db.RUnlock() _ = db.FindFor(grp, word, "", func() error { + if i > 0 { + sb.WriteString(" | ") + } sb.WriteString(word.Word) - sb.WriteString(" | ") + i++ return nil }) - if sb.Len() <= 3 { - return "" + if sb.Len() <= 4 { + return "[]" } - return sb.String()[:sb.Len()-3] + sb.WriteByte(']') + return sb.String() }