From 8b010321d52cec9c6b8a1499e62b42f82417d2bd Mon Sep 17 00:00:00 2001 From: himawari <54976075+guohuiyuan@users.noreply.github.com> Date: Sun, 12 Mar 2023 11:09:07 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E6=B7=BB=E5=8A=A0=E4=B8=80?= =?UTF-8?q?=E8=A8=80=20(#616)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ 添加一言 * 🎨 优化随机数 * 🎨 更新包 * 🎨 优化随机结构 * 🎨 修改随机算法 --------- Co-authored-by: 源文雨 <41315874+fumiama@users.noreply.github.com> --- README.md | 12 ++- go.mod | 2 +- go.sum | 4 +- main.go | 1 + plugin/hitokoto/hitokoto.go | 174 ++++++++++++++++++++++++++++++++++++ plugin/hitokoto/model.go | 73 +++++++++++++++ 6 files changed, 262 insertions(+), 4 deletions(-) create mode 100644 plugin/hitokoto/hitokoto.go create mode 100644 plugin/hitokoto/model.go diff --git a/README.md b/README.md index 067082c57e..69ccfc136b 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ zerobot [-h] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w] [-c|s > 插件的优先级为`import`的先后顺序。 -> `webui`默认禁用不编译,打开后会增加程序体积并使控制台日志格式紊乱。 +> `webui`默认禁用不编译,打开后会增加程序体积。
插件控制 @@ -821,6 +821,16 @@ print("run[CQ:image,file="+j["img"]+"]") - [x] 来点黑丝/白丝/jk/巨乳/足控/网红 +
+
+ 一言 + + `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/hitokoto"` + + - [x] 一言[xxx] + + - [x] 系列一言 +
炉石 diff --git a/go.mod b/go.mod index 9f2716069a..f10494ccbe 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( 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/zbputils v1.6.2-0.20230310162032-fe2036d0667a 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 diff --git a/go.sum b/go.sum index 3efeead51b..77c1a41a44 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,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.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/zbputils v1.6.2-0.20230310162032-fe2036d0667a h1:As8TrKJhLtPSvu/qWAav1StdHWUn7ReDcrfTJlJga1s= +github.com/FloatTech/zbputils v1.6.2-0.20230310162032-fe2036d0667a/go.mod h1:QwQvA0E+SRcW2kjXt07etth+uunhnCC0fYGhTbl1pgk= 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= diff --git a/main.go b/main.go index 2fdcc2bcff..58308ab389 100644 --- a/main.go +++ b/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" // 关键字搜图 diff --git a/plugin/hitokoto/hitokoto.go b/plugin/hitokoto/hitokoto.go new file mode 100644 index 0000000000..c08c2f5f31 --- /dev/null +++ b/plugin/hitokoto/hitokoto.go @@ -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 + } + } + }) +} diff --git a/plugin/hitokoto/model.go b/plugin/hitokoto/model.go new file mode 100644 index 0000000000..63e182a5ca --- /dev/null +++ b/plugin/hitokoto/model.go @@ -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 +}