mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 05:30:07 +08:00
优化代码结构 & fix job regex
This commit is contained in:
parent
340db0c644
commit
6acd930455
4
go.mod
4
go.mod
@ -7,8 +7,9 @@ require (
|
||||
github.com/FloatTech/AnimeAPI v1.5.1-0.20220901132657-2585bbc03bf6
|
||||
github.com/FloatTech/floatbox v0.0.0-20220822040527-f059031fec44
|
||||
github.com/FloatTech/sqlite v0.3.3
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
|
||||
github.com/FloatTech/zbpctrl v1.4.1-0.20220715042842-93f081cb0133
|
||||
github.com/FloatTech/zbputils v1.5.1-0.20220826103123-0c73a585e38f
|
||||
github.com/FloatTech/zbputils v1.5.1-0.20220906100116-30c0892066d6
|
||||
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c
|
||||
github.com/antchfx/htmlquery v1.2.5
|
||||
github.com/corona10/goimagehash v1.0.3
|
||||
@ -36,7 +37,6 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b // indirect
|
||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc // indirect
|
||||
github.com/antchfx/xpath v1.2.1 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@ -21,8 +21,8 @@ github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJG
|
||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
||||
github.com/FloatTech/zbpctrl v1.4.1-0.20220715042842-93f081cb0133 h1:nP9NI4I+vtwAbiU7wCJwjuzCzMZ/yJYg8h3667HGnv0=
|
||||
github.com/FloatTech/zbpctrl v1.4.1-0.20220715042842-93f081cb0133/go.mod h1:72BnjyBwQWUC8mqM9dPk5ZrjxXCilQCVp+jfgHATNdw=
|
||||
github.com/FloatTech/zbputils v1.5.1-0.20220826103123-0c73a585e38f h1:R13GKhRZfB42nsCEqek/ZlGbKBopQOZFYwBU9qSCfhg=
|
||||
github.com/FloatTech/zbputils v1.5.1-0.20220826103123-0c73a585e38f/go.mod h1:ZT91eCYR6y1HbLRTO5EB7o8K7qEPbCsX7vjhYIuMijc=
|
||||
github.com/FloatTech/zbputils v1.5.1-0.20220906100116-30c0892066d6 h1:9+PCM0UzbtrpYSzkvy+AeVy6bpprmVd6BUs17Njao04=
|
||||
github.com/FloatTech/zbputils v1.5.1-0.20220906100116-30c0892066d6/go.mod h1:ZT91eCYR6y1HbLRTO5EB7o8K7qEPbCsX7vjhYIuMijc=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c h1:cNPOdTNiVwxLpROLjXCgbIPvdkE+BwvxDvgmdYmWx6Q=
|
||||
github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c/go.mod h1:KqZzu7slNKROh3TSYEH/IUMG6f4M+1qubZ5e52QypsE=
|
||||
|
||||
@ -2,13 +2,15 @@
|
||||
package antiabuse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"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/img/text"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
@ -19,6 +21,7 @@ func init() {
|
||||
Help: "违禁词检测",
|
||||
PrivateDataFolder: "anti_abuse",
|
||||
})
|
||||
|
||||
onceRule := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
managers = ctx.State["managers"].(*ctrl.Control[*zero.Ctx]).Manager
|
||||
db.DBPath = engine.DataFolder() + "anti_abuse.db"
|
||||
@ -32,39 +35,62 @@ func init() {
|
||||
ctx.SendChain(message.Text("create table error: ", err))
|
||||
return false
|
||||
}
|
||||
err = recoverWord()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("recover data error: ", err))
|
||||
return true
|
||||
})
|
||||
|
||||
engine.OnMessage(onceRule, zero.OnlyGroup, func(ctx *zero.Ctx) bool {
|
||||
if !ctx.Event.IsToMe {
|
||||
return true
|
||||
}
|
||||
uid := ctx.Event.UserID
|
||||
gid := ctx.Event.GroupID
|
||||
grp := strconv.FormatInt(gid, 36)
|
||||
msg := strings.ReplaceAll(ctx.MessageString(), "\n", "")
|
||||
msg = strings.ReplaceAll(msg, "\r", "")
|
||||
msg = strings.ReplaceAll(msg, "\t", "")
|
||||
msg = strings.ReplaceAll(msg, ";", "")
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
if db.CanFind(grp, "WHERE instr('"+msg+"', word)>=0") {
|
||||
if err := managers.DoBlock(uid); err == nil {
|
||||
cache.Set(uid, struct{}{})
|
||||
ctx.SetGroupBan(gid, uid, 4*3600)
|
||||
ctx.SendChain(message.Text("检测到违禁词,已封禁/屏蔽4小时"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("block user error:", err))
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
engine.OnMessage(onceRule, zero.OnlyGroup, banRule)
|
||||
|
||||
engine.OnCommand("添加违禁词", zero.OnlyGroup, zero.AdminPermission, onceRule).Handle(
|
||||
func(ctx *zero.Ctx) {
|
||||
args := ctx.State["args"].(string)
|
||||
if err := insertWord(ctx.Event.GroupID, args); err != nil {
|
||||
ctx.SendChain(message.Text("error:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(fmt.Sprintf("添加违禁词 %s 成功", args)))
|
||||
ctx.SendChain(message.Text("添加违禁词 ", args, " 成功"))
|
||||
}
|
||||
})
|
||||
|
||||
engine.OnCommand("删除违禁词", zero.OnlyGroup, zero.AdminPermission, onceRule).Handle(
|
||||
func(ctx *zero.Ctx) {
|
||||
args := ctx.State["args"].(string)
|
||||
if err := deleteWord(ctx.Event.GroupID, args); err != nil {
|
||||
ctx.SendChain(message.Text("error:", err))
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
} else {
|
||||
ctx.SendChain(message.Text(fmt.Sprintf("删除违禁词 %s 成功", args)))
|
||||
}
|
||||
})
|
||||
engine.OnCommand("查看违禁词", zero.OnlyGroup, onceRule).Handle(
|
||||
func(ctx *zero.Ctx) {
|
||||
if set, ok := wordMap[ctx.Event.GroupID]; !ok {
|
||||
ctx.SendChain(message.Text("本群无违禁词"))
|
||||
} else {
|
||||
ctx.SendChain(message.Text("本群违禁词有:", strings.Join(set.ToSlice(), " |")))
|
||||
ctx.SendChain(message.Text("删除违禁词 ", args, " 成功"))
|
||||
}
|
||||
})
|
||||
|
||||
engine.OnCommand("查看违禁词", zero.OnlyGroup, onceRule).Handle(
|
||||
func(ctx *zero.Ctx) {
|
||||
b, err := text.RenderToBase64(listWords(ctx.Event.GroupID), text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Text("本群违禁词有:\n"), message.Image("base64://"+binary.BytesToString(b)))
|
||||
})
|
||||
}
|
||||
|
||||
76
plugin/antiabuse/db.go
Normal file
76
plugin/antiabuse/db.go
Normal file
@ -0,0 +1,76 @@
|
||||
package antiabuse
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
sqlite "github.com/FloatTech/sqlite"
|
||||
"github.com/FloatTech/ttl"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
)
|
||||
|
||||
var managers *ctrl.Manager[*zero.Ctx] // managers lazy load
|
||||
var db = &sqlite.Sqlite{}
|
||||
var mu sync.RWMutex
|
||||
|
||||
func onDel(uid int64, _ struct{}) {
|
||||
if managers == nil {
|
||||
return
|
||||
}
|
||||
if err := managers.DoUnblock(uid); err != nil {
|
||||
logrus.Error("do unblock error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
var cache = ttl.NewCacheOn(4*time.Hour, [4]func(int64, struct{}){nil, nil, onDel, nil})
|
||||
|
||||
type banWord struct {
|
||||
Word string `db:"word"`
|
||||
}
|
||||
|
||||
var nilban = &banWord{}
|
||||
|
||||
func insertWord(gid int64, word string) error {
|
||||
grp := strconv.FormatInt(gid, 36)
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
err := db.Create(grp, nilban)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return db.Insert(grp, (*banWord)(unsafe.Pointer(&word)))
|
||||
}
|
||||
|
||||
func deleteWord(gid int64, word string) error {
|
||||
grp := strconv.FormatInt(gid, 36)
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if n, _ := db.Count(grp); n == 0 {
|
||||
return errors.New("本群还没有违禁词~")
|
||||
}
|
||||
return db.Del(grp, "WHRER word='"+word+"'")
|
||||
}
|
||||
|
||||
func listWords(gid int64) string {
|
||||
grp := strconv.FormatInt(gid, 36)
|
||||
word := ""
|
||||
ptr := (*banWord)(unsafe.Pointer(&word))
|
||||
sb := strings.Builder{}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
_ = db.FindFor(grp, ptr, "", func() error {
|
||||
sb.WriteString(word)
|
||||
sb.WriteString(" |")
|
||||
return nil
|
||||
})
|
||||
if sb.Len() <= 2 {
|
||||
return ""
|
||||
}
|
||||
return sb.String()[:sb.Len()-2]
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
package antiabuse
|
||||
|
||||
import "sync"
|
||||
|
||||
//Set defines HashSet structure
|
||||
type Set[T comparable] struct {
|
||||
sync.RWMutex
|
||||
m map[T]struct{}
|
||||
}
|
||||
|
||||
// NewSet creates Set with optional key(s)
|
||||
func NewSet[T comparable]() *Set[T] {
|
||||
return &Set[T]{m: make(map[T]struct{})}
|
||||
}
|
||||
|
||||
// Add adds key(s) to Set
|
||||
func (s *Set[T]) Add(key ...T) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
for _, k := range key {
|
||||
s.m[k] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// Include asserts key in Set
|
||||
func (s *Set[T]) Include(key T) bool {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
_, ok := s.m[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Iter calls f when traversing Set
|
||||
func (s *Set[T]) Iter(f func(T) error) error {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
var err error
|
||||
for key := range s.m {
|
||||
err = f(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove removes key from Set
|
||||
func (s *Set[T]) Remove(key T) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
delete(s.m, key)
|
||||
}
|
||||
|
||||
// ToSlice convert Set to slice
|
||||
func (s *Set[T]) ToSlice() (res []T) {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
for key := range s.m {
|
||||
res = append(res, key)
|
||||
}
|
||||
return res
|
||||
}
|
||||
@ -1,110 +0,0 @@
|
||||
package antiabuse
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
sqlite "github.com/FloatTech/sqlite"
|
||||
"github.com/FloatTech/ttl"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/sirupsen/logrus"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
var managers *ctrl.Manager[*zero.Ctx] //managers lazy load
|
||||
var errBreak = errors.New("break")
|
||||
var db = &sqlite.Sqlite{}
|
||||
var crc32Table = crc32.MakeTable(crc32.IEEE)
|
||||
var wordMap = make(map[int64]*Set[string])
|
||||
|
||||
func onDel(uid int64, _ struct{}) {
|
||||
if managers == nil {
|
||||
return
|
||||
}
|
||||
if err := managers.DoUnblock(uid); err != nil {
|
||||
logrus.Error("do unblock error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
var cache = ttl.NewCacheOn[int64, struct{}](4*time.Hour, [4]func(int64, struct{}){
|
||||
nil, nil, onDel, nil})
|
||||
|
||||
type banWord struct {
|
||||
Crc32ID uint32 `db:"crc32_id"`
|
||||
GroupID int64 `db:"group_id"`
|
||||
Word string `db:"word"`
|
||||
}
|
||||
|
||||
func banRule(ctx *zero.Ctx) bool {
|
||||
if !ctx.Event.IsToMe {
|
||||
return true
|
||||
}
|
||||
uid := ctx.Event.UserID
|
||||
gid := ctx.Event.GroupID
|
||||
wordSet := wordMap[gid]
|
||||
if wordSet == nil {
|
||||
return true
|
||||
}
|
||||
err := wordSet.Iter(func(word string) error {
|
||||
if strings.Contains(ctx.MessageString(), word) {
|
||||
if err := managers.DoBlock(uid); err != nil {
|
||||
return err
|
||||
}
|
||||
cache.Set(uid, struct{}{})
|
||||
return errBreak
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil && err != errBreak {
|
||||
ctx.SendChain(message.Text("block user error:", err))
|
||||
return true
|
||||
}
|
||||
ctx.SetGroupBan(gid, uid, 4*3600)
|
||||
ctx.SendChain(message.Text("检测到违禁词,已封禁/屏蔽4小时"))
|
||||
return false
|
||||
}
|
||||
|
||||
func insertWord(gid int64, word string) error {
|
||||
str := fmt.Sprintf("%d-%s", gid, word)
|
||||
checksum := crc32.Checksum([]byte(str), crc32Table)
|
||||
obj := &banWord{checksum, gid, word}
|
||||
if _, ok := wordMap[gid]; !ok {
|
||||
wordMap[gid] = NewSet[string]()
|
||||
}
|
||||
wordMap[gid].Add(word)
|
||||
return db.Insert("banWord", obj)
|
||||
}
|
||||
|
||||
func deleteWord(gid int64, word string) error {
|
||||
if _, ok := wordMap[gid]; !ok {
|
||||
return errors.New("本群还没有违禁词~")
|
||||
}
|
||||
if !wordMap[gid].Include(word) {
|
||||
return errors.New(word + " 不在本群违禁词集合中")
|
||||
}
|
||||
wordMap[gid].Remove(word)
|
||||
str := fmt.Sprintf("%d-%s", gid, word)
|
||||
checksum := crc32.Checksum([]byte(str), crc32Table)
|
||||
sql := fmt.Sprintf("WHERE crc32_id = %d", checksum)
|
||||
return db.Del("banWord", sql)
|
||||
}
|
||||
|
||||
func recoverWord() error {
|
||||
if !db.CanFind("banWord", "") {
|
||||
return nil
|
||||
}
|
||||
obj := &banWord{}
|
||||
err := db.FindFor("banWord", obj, "", func() error {
|
||||
if _, ok := wordMap[obj.GroupID]; !ok {
|
||||
wordMap[obj.GroupID] = NewSet[string]()
|
||||
}
|
||||
wordMap[obj.GroupID].Add(obj.Word)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
@ -1,202 +0,0 @@
|
||||
package antiabuse
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestInsertWord(t *testing.T) {
|
||||
wordMap = make(map[int64]*Set[string])
|
||||
defer func() {
|
||||
wordMap = make(map[int64]*Set[string])
|
||||
}()
|
||||
path := "test.db"
|
||||
defer func() {
|
||||
err := os.Remove("test.db")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
db.DBPath = path
|
||||
err := db.Open(0)
|
||||
defer func() {
|
||||
err := db.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
err = db.Create("banWord", &banWord{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
err := db.Drop("banWord")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
err = insertWord(123, "one")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if ok := wordMap[123].Include("one"); !ok {
|
||||
t.Fatal(`wordMap[123] should found "one" but not`)
|
||||
}
|
||||
if !db.CanFind("banWord", "WHERE group_id=123 AND word= 'one' ") {
|
||||
t.Fatal(`db should found 123-one but not`)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteWord(t *testing.T) {
|
||||
wordMap = make(map[int64]*Set[string])
|
||||
defer func() {
|
||||
wordMap = make(map[int64]*Set[string])
|
||||
}()
|
||||
path := "test.db"
|
||||
defer func() {
|
||||
err := os.Remove("test.db")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
db.DBPath = path
|
||||
err := db.Open(0)
|
||||
defer func() {
|
||||
err := db.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
err = db.Create("banWord", &banWord{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
err := db.Drop("banWord")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
err = insertWord(123, "one")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = deleteWord(123, "one")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShowWord(t *testing.T) {
|
||||
wordMap = make(map[int64]*Set[string])
|
||||
defer func() {
|
||||
wordMap = make(map[int64]*Set[string])
|
||||
}()
|
||||
path := "test.db"
|
||||
defer func() {
|
||||
err := os.Remove("test.db")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
db.DBPath = path
|
||||
err := db.Open(0)
|
||||
defer func() {
|
||||
err := db.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
err = db.Create("banWord", &banWord{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
err := db.Drop("banWord")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
err = insertWord(123, "one")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = insertWord(123, "one")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = insertWord(123, "two")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var db123 []string
|
||||
var map123 []string
|
||||
obj := &banWord{}
|
||||
err = db.FindFor("banWord", obj, "WHERE group_id=123", func() error {
|
||||
db123 = append(db123, obj.Word)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sort.Strings(db123)
|
||||
if len(db123) != 2 || db123[0] != "one" || db123[1] != "two" {
|
||||
t.Fatal("db should found 123-one and 123-two but not")
|
||||
}
|
||||
map123 = wordMap[123].ToSlice()
|
||||
sort.Strings(map123)
|
||||
if len(map123) != 2 || map123[0] != "one" || map123[1] != "two" {
|
||||
t.Fatal("wordMap[123] should found 123-one and 123-two but not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecoverWord(t *testing.T) {
|
||||
wordMap = make(map[int64]*Set[string])
|
||||
defer func() {
|
||||
wordMap = make(map[int64]*Set[string])
|
||||
}()
|
||||
path := "test.db"
|
||||
defer func() {
|
||||
err := os.Remove("test.db")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
db.DBPath = path
|
||||
err := db.Open(0)
|
||||
defer func() {
|
||||
err := db.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
err = db.Create("banWord", &banWord{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
err := db.Drop("banWord")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
err = insertWord(123, "one")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = insertWord(123, "two")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wordMap = make(map[int64]*Set[string])
|
||||
err = recoverWord()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
map123 := wordMap[123].ToSlice()
|
||||
sort.Strings(map123)
|
||||
if len(map123) != 2 || map123[0] != "one" || map123[1] != "two" {
|
||||
t.Fatal("wordMap[123] should found 123-one and 123-two but not")
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user