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
+}