From 8d2dffba3a874faf7a61d79b1342ca5e2f107d80 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Wed, 30 Jul 2025 20:52:19 +0800
Subject: [PATCH 01/14] =?UTF-8?q?=E2=9C=A8=20=E6=B7=BB=E5=8A=A0=E9=87=8D?=
=?UTF-8?q?=E7=BD=AE=E8=81=8A=E5=A4=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
plugin/aichat/main.go | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/plugin/aichat/main.go b/plugin/aichat/main.go
index c8ac1df646..5331cad234 100644
--- a/plugin/aichat/main.go
+++ b/plugin/aichat/main.go
@@ -41,7 +41,8 @@ var (
"- 设置AI聊天最大长度4096\n" +
"- 设置AI聊天TopP 0.9\n" +
"- 设置AI聊天(不)以AI语音输出\n" +
- "- 查看AI聊天配置\n",
+ "- 查看AI聊天配置\n" +
+ "- 重置AI聊天\n",
PrivateDataFolder: "aichat",
})
)
@@ -305,4 +306,8 @@ func init() {
}
ctx.SendChain(message.Text(printConfig(rate, temp, cfg)))
})
+ en.OnFullMatch("重置AI聊天", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
+ chat.Reset()
+ ctx.SendChain(message.Text("成功"))
+ })
}
From 8feca47d46976c810a2525450bf7f87f3ff4ca70 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Wed, 30 Jul 2025 21:01:07 +0800
Subject: [PATCH 02/14] =?UTF-8?q?=F0=9F=8E=A8=20=E4=BC=98=E5=8C=96?=
=?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=8F=90=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 5 +++--
plugin/aichat/main.go | 4 ++--
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 1442aad6ff..3e46929e5e 100644
--- a/README.md
+++ b/README.md
@@ -1612,9 +1612,9 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 设置AI聊天温度80
- [x] 设置AI聊天接口类型[OpenAI|OLLaMA|GenAI]
- [x] 设置AI聊天(不)支持系统提示词
- - [x] 设置AI聊天接口地址https://api.deepseek.com/chat/completions
+ - [x] 设置AI聊天接口地址https://api.siliconflow.cn/v1/chat/completions
- [x] 设置AI聊天密钥xxx
- - [x] 设置AI聊天模型名xxx
+ - [x] 设置AI聊天模型名Qwen/Qwen3-8B
- [x] 查看AI聊天系统提示词
- [x] 重置AI聊天系统提示词
- [x] 设置AI聊天系统提示词xxx
@@ -1624,6 +1624,7 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 设置AI聊天TopP 0.9
- [x] 设置AI聊天(不)以AI语音输出
- [x] 查看AI聊天配置
+ - [x] 重置AI聊天
diff --git a/plugin/aichat/main.go b/plugin/aichat/main.go
index 5331cad234..bc851ac919 100644
--- a/plugin/aichat/main.go
+++ b/plugin/aichat/main.go
@@ -30,9 +30,9 @@ var (
"- 设置AI聊天温度80\n" +
"- 设置AI聊天接口类型[OpenAI|OLLaMA|GenAI]\n" +
"- 设置AI聊天(不)支持系统提示词\n" +
- "- 设置AI聊天接口地址https://api.deepseek.com/chat/completions\n" +
+ "- 设置AI聊天接口地址https://api.siliconflow.cn/v1/chat/completions\n" +
"- 设置AI聊天密钥xxx\n" +
- "- 设置AI聊天模型名xxx\n" +
+ "- 设置AI聊天模型名Qwen/Qwen3-8B\n" +
"- 查看AI聊天系统提示词\n" +
"- 重置AI聊天系统提示词\n" +
"- 设置AI聊天系统提示词xxx\n" +
From e5a7c30f494337717fd795889da0860e120ecef8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Thu, 31 Jul 2025 00:33:56 +0800
Subject: [PATCH 03/14] =?UTF-8?q?=E2=9C=A8=20=E6=B7=BB=E5=8A=A0=E7=BE=A4?=
=?UTF-8?q?=E8=81=8A=E6=91=98=E8=A6=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
plugin/aichat/main.go | 89 +++++++++++++++++++++++++++++++++++++++-
plugin/wordcount/main.go | 2 +-
2 files changed, 88 insertions(+), 3 deletions(-)
diff --git a/plugin/aichat/main.go b/plugin/aichat/main.go
index bc851ac919..c00419ead5 100644
--- a/plugin/aichat/main.go
+++ b/plugin/aichat/main.go
@@ -1,14 +1,17 @@
-// Package aichat OpenAI聊天
+// Package aichat OpenAI聊天和群聊摘要
package aichat
import (
+ "fmt"
"math/rand"
"strconv"
"strings"
+ "unicode"
"github.com/fumiama/deepinfra"
"github.com/fumiama/deepinfra/model"
"github.com/sirupsen/logrus"
+ "github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -42,7 +45,8 @@ var (
"- 设置AI聊天TopP 0.9\n" +
"- 设置AI聊天(不)以AI语音输出\n" +
"- 查看AI聊天配置\n" +
- "- 重置AI聊天\n",
+ "- 重置AI聊天\n" +
+ "- 群聊摘要 [群号] [消息数目]|群聊摘要 123456 1000\n",
PrivateDataFolder: "aichat",
})
)
@@ -310,4 +314,85 @@ func init() {
chat.Reset()
ctx.SendChain(message.Text("成功"))
})
+
+ // 添加群聊摘要功能
+ en.OnRegex(`^群聊摘要\s?(\d*)\s?(\d*)$`, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
+ ctx.SendChain(message.Text("少女思考中..."))
+ gid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
+ p, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
+ if p > 1000 {
+ p = 1000
+ }
+ if p == 0 {
+ p = 200
+ }
+ if gid == 0 {
+ gid = ctx.Event.GroupID
+ }
+ group := ctx.GetGroupInfo(gid, false)
+ if group.MemberCount == 0 {
+ ctx.SendChain(message.Text(zero.BotConfig.NickName[0], "未加入", group.Name, "(", gid, "),无法获取摘要"))
+ return
+ }
+
+ var messages []string
+
+ h := ctx.GetGroupMessageHistory(gid, 0, p, false)
+ h.Get("messages").ForEach(func(_, msgObj gjson.Result) bool {
+ nickname := removeControlChars(msgObj.Get("sender.nickname").Str)
+ text := strings.TrimSpace(message.ParseMessageFromString(msgObj.Get("raw_message").Str).ExtractPlainText())
+ if text != "" {
+ messages = append(messages, nickname+": "+text)
+ }
+ return true
+ })
+
+ if len(messages) == 0 {
+ ctx.SendChain(message.Text("ERROR: 历史消息为空或者无法获得历史消息"))
+ return
+ }
+
+ // 调用大模型API进行摘要
+ summary, err := summarizeMessages(messages)
+ if err != nil {
+ ctx.SendChain(message.Text("ERROR: ", err))
+ return
+ }
+
+ ctx.SendChain(message.Text(
+ fmt.Sprintf("群 %s(%d) 的 %d 条消息摘要:\n\n", group.Name, gid, p),
+ summary,
+ ))
+ })
+}
+
+// summarizeMessages 调用大模型API进行消息摘要
+func summarizeMessages(messages []string) (string, error) {
+ // 使用现有的AI配置进行摘要
+ x := deepinfra.NewAPI(cfg.API, cfg.Key)
+ mod := model.NewOpenAI(
+ cfg.ModelName, cfg.Separator,
+ float32(70)/100, 0.9, 4096,
+ )
+
+ // 构造摘要请求提示
+ summaryPrompt := "请将以下群聊消息总结成一段简洁的摘要,保留每个用户主要话题和关键信息:\n\n" +
+ strings.Join(messages, "\n") + "\n\n群聊摘要:"
+
+ data, err := x.Request(mod.User(summaryPrompt))
+ if err != nil {
+ return "", err
+ }
+
+ return strings.TrimSpace(data), nil
+}
+
+func removeControlChars(s string) string {
+ var builder strings.Builder
+ for _, r := range s {
+ if !unicode.IsControl(r) { // 保留非控制字符
+ builder.WriteRune(r)
+ }
+ }
+ return builder.String()
}
diff --git a/plugin/wordcount/main.go b/plugin/wordcount/main.go
index 5e58069fa3..2ffbf78d57 100644
--- a/plugin/wordcount/main.go
+++ b/plugin/wordcount/main.go
@@ -114,7 +114,7 @@ func init() {
messageSeq := h.Get("messages.0.message_seq").Int()
msghists <- &h
for i := 1; i < int(p/20) && messageSeq != 0; i++ {
- h := ctx.GetGroupMessageHistory(gid, messageSeq)
+ h := ctx.GetGroupMessageHistory(gid, messageSeq, 20, false)
msghists <- &h
messageSeq = h.Get("messages.0.message_seq").Int()
}
From eae8383b130e7339470f5f58f23ae584ba346a8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Thu, 31 Jul 2025 11:21:26 +0800
Subject: [PATCH 04/14] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8D?=
=?UTF-8?q?=E8=AF=BB=E9=85=8D=E7=BD=AEbug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
plugin/aichat/main.go | 37 +++++++++++++------------------------
1 file changed, 13 insertions(+), 24 deletions(-)
diff --git a/plugin/aichat/main.go b/plugin/aichat/main.go
index c00419ead5..7474263045 100644
--- a/plugin/aichat/main.go
+++ b/plugin/aichat/main.go
@@ -1,4 +1,4 @@
-// Package aichat OpenAI聊天和群聊摘要
+// Package aichat OpenAI聊天和群聊总结
package aichat
import (
@@ -6,7 +6,7 @@ import (
"math/rand"
"strconv"
"strings"
- "unicode"
+ "time"
"github.com/fumiama/deepinfra"
"github.com/fumiama/deepinfra/model"
@@ -21,6 +21,7 @@ import (
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/chat"
"github.com/FloatTech/zbputils/control"
+ "github.com/FloatTech/zbputils/ctxext"
)
var (
@@ -46,7 +47,7 @@ var (
"- 设置AI聊天(不)以AI语音输出\n" +
"- 查看AI聊天配置\n" +
"- 重置AI聊天\n" +
- "- 群聊摘要 [群号] [消息数目]|群聊摘要 123456 1000\n",
+ "- 群聊总结 [消息数目]|群聊总结 1000\n",
PrivateDataFolder: "aichat",
})
)
@@ -58,6 +59,7 @@ var (
"GenAI": 2,
}
apilist = [3]string{"OpenAI", "OLLaMA", "GenAI"}
+ limit = ctxext.NewLimiterManager(time.Second*60, 1)
)
func init() {
@@ -315,20 +317,17 @@ func init() {
ctx.SendChain(message.Text("成功"))
})
- // 添加群聊摘要功能
- en.OnRegex(`^群聊摘要\s?(\d*)\s?(\d*)$`, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
+ // 添加群聊总结功能
+ en.OnRegex(`^群聊总结\s?(\d*)$`, ensureconfig, zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女思考中..."))
- gid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
- p, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
+ p, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
if p > 1000 {
p = 1000
}
if p == 0 {
p = 200
}
- if gid == 0 {
- gid = ctx.Event.GroupID
- }
+ gid := ctx.Event.GroupID
group := ctx.GetGroupInfo(gid, false)
if group.MemberCount == 0 {
ctx.SendChain(message.Text(zero.BotConfig.NickName[0], "未加入", group.Name, "(", gid, "),无法获取摘要"))
@@ -339,7 +338,7 @@ func init() {
h := ctx.GetGroupMessageHistory(gid, 0, p, false)
h.Get("messages").ForEach(func(_, msgObj gjson.Result) bool {
- nickname := removeControlChars(msgObj.Get("sender.nickname").Str)
+ nickname := msgObj.Get("sender.nickname").Str
text := strings.TrimSpace(message.ParseMessageFromString(msgObj.Get("raw_message").Str).ExtractPlainText())
if text != "" {
messages = append(messages, nickname+": "+text)
@@ -360,7 +359,7 @@ func init() {
}
ctx.SendChain(message.Text(
- fmt.Sprintf("群 %s(%d) 的 %d 条消息摘要:\n\n", group.Name, gid, p),
+ fmt.Sprintf("群 %s(%d) 的 %d 条消息总结:\n\n", group.Name, gid, p),
summary,
))
})
@@ -376,8 +375,8 @@ func summarizeMessages(messages []string) (string, error) {
)
// 构造摘要请求提示
- summaryPrompt := "请将以下群聊消息总结成一段简洁的摘要,保留每个用户主要话题和关键信息:\n\n" +
- strings.Join(messages, "\n") + "\n\n群聊摘要:"
+ summaryPrompt := "请总结这个群聊内容,要求按发言顺序梳理,明确标注每个发言者的昵称,并完整呈现其核心观点、提出的问题、发表的看法或做出的回应,确保不遗漏关键信息,且能体现成员间的对话逻辑和互动关系:\n\n" +
+ strings.Join(messages, "\n---\n")
data, err := x.Request(mod.User(summaryPrompt))
if err != nil {
@@ -386,13 +385,3 @@ func summarizeMessages(messages []string) (string, error) {
return strings.TrimSpace(data), nil
}
-
-func removeControlChars(s string) string {
- var builder strings.Builder
- for _, r := range s {
- if !unicode.IsControl(r) { // 保留非控制字符
- builder.WriteRune(r)
- }
- }
- return builder.String()
-}
From 3eadcc3a49e91076bd00af86a0b5f6c25ca08c5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Thu, 31 Jul 2025 11:40:05 +0800
Subject: [PATCH 05/14] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E6=94=B9wordcoun?=
=?UTF-8?q?t=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 1 +
plugin/aichat/main.go | 17 +++++++++-----
plugin/wordcount/main.go | 51 +++++++++++-----------------------------
3 files changed, 26 insertions(+), 43 deletions(-)
diff --git a/README.md b/README.md
index 3e46929e5e..d8dc09a404 100644
--- a/README.md
+++ b/README.md
@@ -1625,6 +1625,7 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 设置AI聊天(不)以AI语音输出
- [x] 查看AI聊天配置
- [x] 重置AI聊天
+ - [x] 群聊总结 [消息数目]|群聊总结 1000
diff --git a/plugin/aichat/main.go b/plugin/aichat/main.go
index 7474263045..7f6bda37c6 100644
--- a/plugin/aichat/main.go
+++ b/plugin/aichat/main.go
@@ -2,7 +2,6 @@
package aichat
import (
- "fmt"
"math/rand"
"strconv"
"strings"
@@ -59,7 +58,7 @@ var (
"GenAI": 2,
}
apilist = [3]string{"OpenAI", "OLLaMA", "GenAI"}
- limit = ctxext.NewLimiterManager(time.Second*60, 1)
+ limit = ctxext.NewLimiterManager(time.Second*30, 1)
)
func init() {
@@ -358,10 +357,16 @@ func init() {
return
}
- ctx.SendChain(message.Text(
- fmt.Sprintf("群 %s(%d) 的 %d 条消息总结:\n\n", group.Name, gid, p),
- summary,
- ))
+ var b strings.Builder
+ b.WriteString("群 ")
+ b.WriteString(group.Name)
+ b.WriteByte('(')
+ b.WriteString(strconv.FormatInt(gid, 10))
+ b.WriteString(") 的 ")
+ b.WriteString(strconv.FormatInt(p, 10))
+ b.WriteString(" 条消息总结:\n\n")
+ b.WriteString(summary)
+ ctx.SendChain(message.Text(b.String()))
})
}
diff --git a/plugin/wordcount/main.go b/plugin/wordcount/main.go
index 2ffbf78d57..2b713263d2 100644
--- a/plugin/wordcount/main.go
+++ b/plugin/wordcount/main.go
@@ -8,7 +8,6 @@ import (
"sort"
"strconv"
"strings"
- "sync"
"time"
"github.com/go-ego/gse"
@@ -108,44 +107,22 @@ func init() {
return
}
messageMap := make(map[string]int, 256)
- msghists := make(chan *gjson.Result, 256)
- go func() {
- h := ctx.GetLatestGroupMessageHistory(gid)
- messageSeq := h.Get("messages.0.message_seq").Int()
- msghists <- &h
- for i := 1; i < int(p/20) && messageSeq != 0; i++ {
- h := ctx.GetGroupMessageHistory(gid, messageSeq, 20, false)
- msghists <- &h
- messageSeq = h.Get("messages.0.message_seq").Int()
- }
- close(msghists)
- }()
- var wg sync.WaitGroup
- var mapmu sync.Mutex
- for h := range msghists {
- wg.Add(1)
- go func(h *gjson.Result) {
- for _, v := range h.Get("messages.#.message").Array() {
- tex := strings.TrimSpace(message.ParseMessageFromString(v.Str).ExtractPlainText())
- if tex == "" {
- continue
- }
- segments := seg.Segment(helper.StringToBytes(tex))
- words := gse.ToSlice(segments, true)
- for _, word := range words {
- word = strings.TrimSpace(word)
- i := sort.SearchStrings(stopwords, word)
- if re.MatchString(word) && (i >= len(stopwords) || stopwords[i] != word) {
- mapmu.Lock()
- messageMap[word]++
- mapmu.Unlock()
- }
+ h := ctx.GetGroupMessageHistory(gid, 0, p, false)
+ h.Get("messages").ForEach(func(_, msgObj gjson.Result) bool {
+ tex := strings.TrimSpace(message.ParseMessageFromString(msgObj.Get("raw_message").Str).ExtractPlainText())
+ if tex != "" {
+ segments := seg.Segment(helper.StringToBytes(tex))
+ words := gse.ToSlice(segments, true)
+ for _, word := range words {
+ word = strings.TrimSpace(word)
+ i := sort.SearchStrings(stopwords, word)
+ if re.MatchString(word) && (i >= len(stopwords) || stopwords[i] != word) {
+ messageMap[word]++
}
}
- wg.Done()
- }(h)
- }
- wg.Wait()
+ }
+ return true
+ })
wc := rankByWordCount(messageMap)
if len(wc) > 20 {
From 9e98b8fe3017ecb1c006b4da0ae83ca846db8906 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Thu, 31 Jul 2025 15:04:14 +0800
Subject: [PATCH 06/14] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8D?=
=?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=B0=B4=E7=BE=A4bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
plugin/chatcount/chatcount.go | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/plugin/chatcount/chatcount.go b/plugin/chatcount/chatcount.go
index a4e1bb41a8..caf88ebeed 100644
--- a/plugin/chatcount/chatcount.go
+++ b/plugin/chatcount/chatcount.go
@@ -43,8 +43,15 @@ func init() {
})
engine.OnPrefix(`查询水群`, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
+ param := ctx.State["args"].(string)
+ var uid int64
+ if len(ctx.Event.Message) > 1 && ctx.Event.Message[1].Type == "at" {
+ uid, _ = strconv.ParseInt(ctx.Event.Message[1].Data["qq"], 10, 64)
+ } else if param == "" {
+ uid = ctx.Event.UserID
+ }
name := ctx.NickName()
- todayTime, todayMessage, totalTime, totalMessage := ctdb.getChatTime(ctx.Event.GroupID, ctx.Event.UserID)
+ todayTime, todayMessage, totalTime, totalMessage := ctdb.getChatTime(ctx.Event.GroupID, uid)
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(fmt.Sprintf("%s今天水了%d分%d秒,发了%d条消息;总计水了%d分%d秒,发了%d条消息。", name, todayTime/60, todayTime%60, todayMessage, totalTime/60, totalTime%60, totalMessage)))
})
engine.OnFullMatch("查看水群排名", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).
From c72a5d2e8783e2191295e605359368c4a5aafd71 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Thu, 31 Jul 2025 15:09:05 +0800
Subject: [PATCH 07/14] =?UTF-8?q?=F0=9F=8E=A8=20=E7=83=AD=E8=AF=8D?=
=?UTF-8?q?=E9=99=90=E5=88=B6=E5=BD=93=E5=89=8D=E7=BE=A4=E8=81=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 2 +-
plugin/wordcount/main.go | 11 ++++-------
2 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index d8dc09a404..69e1b47378 100644
--- a/README.md
+++ b/README.md
@@ -1496,7 +1496,7 @@ print("run[CQ:image,file="+j["img"]+"]")
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/word_count"`
- - [x] 热词 [群号] [消息数目]|热词 123456 1000
+ - [x] 热词 [消息数目]|热词 1000
diff --git a/plugin/wordcount/main.go b/plugin/wordcount/main.go
index 2b713263d2..127c7da8db 100644
--- a/plugin/wordcount/main.go
+++ b/plugin/wordcount/main.go
@@ -39,7 +39,7 @@ func init() {
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "聊天热词",
- Help: "- 热词 [群号] [消息数目]|热词 123456 1000",
+ Help: "- 热词 [消息数目]|热词 1000",
PublicDataFolder: "WordCount",
})
cachePath := engine.DataFolder() + "cache/"
@@ -50,7 +50,7 @@ func init() {
}
_ = os.RemoveAll(cachePath)
_ = os.MkdirAll(cachePath, 0755)
- engine.OnRegex(`^热词\s?(\d*)\s?(\d*)$`, zero.OnlyGroup, fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
+ engine.OnRegex(`^热词\s?(\d*)$`, zero.OnlyGroup, fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
_, err := engine.GetLazyData("stopwords.txt", false)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
@@ -84,17 +84,14 @@ func init() {
}
ctx.SendChain(message.Text("少女祈祷中..."))
- gid, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
- p, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[2], 10, 64)
+ p, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
if p > 10000 {
p = 10000
}
if p == 0 {
p = 1000
}
- if gid == 0 {
- gid = ctx.Event.GroupID
- }
+ gid := ctx.Event.GroupID
group := ctx.GetGroupInfo(gid, false)
if group.MemberCount == 0 {
ctx.SendChain(message.Text(zero.BotConfig.NickName[0], "未加入", group.Name, "(", gid, "),无法获得热词呢"))
From 0ec648093b541c25e93a5e2211a4d4e3b0b126f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Thu, 31 Jul 2025 15:18:35 +0800
Subject: [PATCH 08/14] =?UTF-8?q?=F0=9F=8E=A8=20token=E6=B6=88=E8=80=97?=
=?UTF-8?q?=E5=A4=A7=EF=BC=8C=E6=B7=BB=E5=8A=A0admin=E6=9D=83=E9=99=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
plugin/aichat/main.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugin/aichat/main.go b/plugin/aichat/main.go
index 7f6bda37c6..412b4cda97 100644
--- a/plugin/aichat/main.go
+++ b/plugin/aichat/main.go
@@ -317,7 +317,7 @@ func init() {
})
// 添加群聊总结功能
- en.OnRegex(`^群聊总结\s?(\d*)$`, ensureconfig, zero.OnlyGroup).SetBlock(true).Limit(limit.LimitByGroup).Handle(func(ctx *zero.Ctx) {
+ en.OnRegex(`^群聊总结\s?(\d*)$`, ensureconfig, zero.OnlyGroup, zero.AdminPermission).SetBlock(true).Limit(limit.LimitByGroup).Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女思考中..."))
p, _ := strconv.ParseInt(ctx.State["regex_matched"].([]string)[1], 10, 64)
if p > 1000 {
From c690405d65caa8c7bec3fa35421a292e7308f581 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Thu, 31 Jul 2025 15:28:28 +0800
Subject: [PATCH 09/14] =?UTF-8?q?=F0=9F=8E=A8=20=E8=BD=AC=E5=8F=91?=
=?UTF-8?q?=E5=88=86=E6=AE=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
plugin/aichat/main.go | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/plugin/aichat/main.go b/plugin/aichat/main.go
index 412b4cda97..dbb9e9aa80 100644
--- a/plugin/aichat/main.go
+++ b/plugin/aichat/main.go
@@ -366,7 +366,18 @@ func init() {
b.WriteString(strconv.FormatInt(p, 10))
b.WriteString(" 条消息总结:\n\n")
b.WriteString(summary)
- ctx.SendChain(message.Text(b.String()))
+
+ // 分割总结内容为多段
+ parts := strings.Split(b.String(), "\n\n")
+ msg := make(message.Message, 0, len(parts))
+ for _, part := range parts {
+ if part != "" {
+ msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Text(part)))
+ }
+ }
+ if len(msg) > 0 {
+ ctx.Send(msg)
+ }
})
}
From 307f66ffe39ec805b3d8f02233507cb56b1c28c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Thu, 31 Jul 2025 17:32:40 +0800
Subject: [PATCH 10/14] =?UTF-8?q?=E2=9C=A8=20=E6=B7=BB=E5=8A=A0ai=E7=94=BB?=
=?UTF-8?q?=E5=9B=BE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
main.go | 1 +
plugin/aiimage/config.go | 76 ++++++++++++++++++++
plugin/aiimage/main.go | 150 +++++++++++++++++++++++++++++++++++++++
3 files changed, 227 insertions(+)
create mode 100644 plugin/aiimage/config.go
create mode 100644 plugin/aiimage/main.go
diff --git a/main.go b/main.go
index 5e9b13e577..117b111aa1 100644
--- a/main.go
+++ b/main.go
@@ -67,6 +67,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/custom" // 自定义插件合集
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/ahsai" // ahsai tts
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aifalse" // 服务器监控
+ _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiimage" // AI画图
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiwife" // 随机老婆
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/alipayvoice" // 支付宝到账语音
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/animetrace" // AnimeTrace 动画/Galgame识别
diff --git a/plugin/aiimage/config.go b/plugin/aiimage/config.go
new file mode 100644
index 0000000000..d1111f9eaa
--- /dev/null
+++ b/plugin/aiimage/config.go
@@ -0,0 +1,76 @@
+// Package aiimage 提供AI画图功能配置
+package aiimage
+
+import (
+ "fmt"
+ "os"
+ "strings"
+ "sync"
+ "time"
+
+ sql "github.com/FloatTech/sqlite"
+)
+
+// Storage 管理画图配置存储
+type Storage struct {
+ sync.RWMutex
+ db sql.Sqlite
+}
+
+var (
+ sdb = &Storage{
+ db: sql.New("data/aiimage/config.db"),
+ }
+)
+
+func init() {
+ if err := os.MkdirAll("data/aiimage", 0755); err != nil {
+ panic(err)
+ }
+ if err := sdb.db.Open(time.Hour * 24); err != nil {
+ panic(err)
+ }
+ if err := sdb.db.Create("config", &ImageConfig{}); err != nil {
+ panic(err)
+ }
+}
+
+// ImageConfig 存储AI画图配置信息
+type ImageConfig struct {
+ ID int64 `db:"id"` // 主键ID
+ APIKey string `db:"apiKey"` // API密钥
+ APIURL string `db:"apiUrl"` // API地址
+ ModelName string `db:"modelName"` // 画图模型名称
+}
+
+// GetConfig 获取当前配置
+func GetConfig() ImageConfig {
+ sdb.RLock()
+ defer sdb.RUnlock()
+ cfg := ImageConfig{}
+ _ = sdb.db.Find("config", &cfg, "WHERE id = 1")
+ return cfg
+}
+
+// SetConfig 设置AI画图配置
+func SetConfig(apiKey, apiURL, modelName string) error {
+ sdb.Lock()
+ defer sdb.Unlock()
+ return sdb.db.Insert("config", &ImageConfig{
+ ID: 1,
+ APIKey: apiKey,
+ APIURL: apiURL,
+ ModelName: modelName,
+ })
+}
+
+// PrintConfig 返回格式化后的配置信息
+func PrintConfig() string {
+ cfg := GetConfig()
+ var builder strings.Builder
+ builder.WriteString("当前AI画图配置:\n")
+ builder.WriteString(fmt.Sprintf("• 密钥: %s\n", cfg.APIKey))
+ builder.WriteString(fmt.Sprintf("• 接口地址: %s\n", cfg.APIURL))
+ builder.WriteString(fmt.Sprintf("• 模型名: %s\n", cfg.ModelName))
+ return builder.String()
+}
diff --git a/plugin/aiimage/main.go b/plugin/aiimage/main.go
new file mode 100644
index 0000000000..e9461c48a7
--- /dev/null
+++ b/plugin/aiimage/main.go
@@ -0,0 +1,150 @@
+// Package aiimage AI画图
+package aiimage
+
+import (
+ "bytes"
+ "encoding/json"
+ "net/http"
+ "strings"
+
+ "github.com/FloatTech/floatbox/web"
+ "github.com/tidwall/gjson"
+ zero "github.com/wdvxdr1123/ZeroBot"
+ "github.com/wdvxdr1123/ZeroBot/message"
+
+ ctrl "github.com/FloatTech/zbpctrl"
+ "github.com/FloatTech/zbputils/control"
+ "github.com/FloatTech/zbputils/ctxext"
+)
+
+func init() {
+ en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
+ DisableOnDefault: false,
+ Extra: control.ExtraFromString("aiimage"),
+ Brief: "AI画图",
+ Help: "- 设置AI画图密钥\n" +
+ "- 设置AI画图接口地址https://api.siliconflow.cn/v1/images/generations\n" +
+ "- 设置AI画图模型名Kwai-Kolors/Kolors\n" +
+ "- 查看AI画图配置\n" +
+ "- AI画图 [描述]",
+ PrivateDataFolder: "aiimage",
+ })
+
+ en.OnPrefix("设置AI画图密钥", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
+ Handle(func(ctx *zero.Ctx) {
+ apiKey := strings.TrimSpace(ctx.State["args"].(string))
+ cfg := GetConfig()
+ err := SetConfig(apiKey, cfg.APIURL, cfg.ModelName)
+ if err != nil {
+ ctx.SendChain(message.Text("ERROR: 设置API密钥失败: ", err))
+ return
+ }
+ ctx.SendChain(message.Text("成功设置API密钥"))
+ })
+
+ en.OnPrefix("设置AI画图接口地址", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
+ Handle(func(ctx *zero.Ctx) {
+ apiURL := strings.TrimSpace(ctx.State["args"].(string))
+ cfg := GetConfig()
+ err := SetConfig(cfg.APIKey, apiURL, cfg.ModelName)
+ if err != nil {
+ ctx.SendChain(message.Text("ERROR: 设置API地址失败: ", err))
+ return
+ }
+ ctx.SendChain(message.Text("成功设置API地址"))
+ })
+
+ en.OnPrefix("设置AI画图模型名", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
+ Handle(func(ctx *zero.Ctx) {
+ modelName := strings.TrimSpace(ctx.State["args"].(string))
+ cfg := GetConfig()
+ err := SetConfig(cfg.APIKey, cfg.APIURL, modelName)
+ if err != nil {
+ ctx.SendChain(message.Text("ERROR: 设置模型失败: ", err))
+ return
+ }
+ ctx.SendChain(message.Text("成功设置模型: ", modelName))
+ })
+
+ en.OnFullMatch("查看AI画图配置", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
+ Handle(func(ctx *zero.Ctx) {
+ ctx.SendChain(message.Text(PrintConfig()))
+ })
+
+ en.OnPrefix("AI画图").SetBlock(true).
+ Handle(func(ctx *zero.Ctx) {
+ prompt := strings.TrimSpace(ctx.State["args"].(string))
+ if prompt == "" {
+ ctx.SendChain(message.Text("请输入图片描述"))
+ return
+ }
+
+ cfg := GetConfig()
+ if cfg.APIKey == "" || cfg.APIURL == "" {
+ ctx.SendChain(message.Text("请先配置API密钥和地址"))
+ return
+ }
+
+ // 准备请求数据
+ reqData := map[string]interface{}{
+ "model": cfg.ModelName,
+ "prompt": prompt,
+ "image_size": "1024x1024",
+ "batch_size": 4,
+ "num_inference_steps": 20,
+ "guidance_scale": 7.5,
+ }
+ reqBytes, _ := json.Marshal(reqData)
+
+ // 发送API请求
+ data, err := web.RequestDataWithHeaders(
+ web.NewDefaultClient(),
+ cfg.APIURL,
+ "POST",
+ func(req *http.Request) error {
+ req.Header.Set("Authorization", "Bearer "+cfg.APIKey)
+ req.Header.Set("Content-Type", "application/json")
+ return nil
+ },
+ bytes.NewReader(reqBytes),
+ )
+ if err != nil {
+ ctx.SendChain(message.Text("API请求失败: ", err))
+ return
+ }
+
+ // 解析API响应
+ jsonData := gjson.ParseBytes(data)
+ images := jsonData.Get("images")
+ if !images.Exists() {
+ images = jsonData.Get("data")
+ if !images.Exists() {
+ ctx.SendChain(message.Text("未获取到图片URL"))
+ return
+ }
+ }
+
+ // 发送生成的图片和相关信息
+ inferenceTime := jsonData.Get("timings.inference").Float()
+ seed := jsonData.Get("seed").Int()
+ msg := make(message.Message, 0, 1)
+ msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Text("图片生成成功!\n",
+ "提示词: ", prompt, "\n",
+ "模型: ", cfg.ModelName, "\n",
+ "推理时间: ", inferenceTime, "秒\n",
+ "种子: ", seed)))
+
+ // 添加所有图片
+ images.ForEach(func(_, value gjson.Result) bool {
+ url := value.Get("url").String()
+ if url != "" {
+ msg = append(msg, ctxext.FakeSenderForwardNode(ctx, message.Image(url)))
+ }
+ return true
+ })
+
+ if len(msg) > 0 {
+ ctx.Send(msg)
+ }
+ })
+}
From 334363c2dc50078edd331cdb3f666f1602838303 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Thu, 31 Jul 2025 18:37:25 +0800
Subject: [PATCH 11/14] =?UTF-8?q?=F0=9F=8E=A8=20readme=E6=B7=BB=E5=8A=A0ai?=
=?UTF-8?q?=E7=94=BB=E5=9B=BE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 12 ++++++++++++
plugin/aiimage/main.go | 1 +
2 files changed, 13 insertions(+)
diff --git a/README.md b/README.md
index 69e1b47378..7126c5cf65 100644
--- a/README.md
+++ b/README.md
@@ -412,6 +412,18 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 设置默认限速为每 m [分钟 | 秒] n 次触发
+
+
+ aiimage
+
+ `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiimage"`
+
+ - [x] 设置AI画图密钥
+ - [x] 设置AI画图接口地址https://api.siliconflow.cn/v1/images/generations
+ - [x] 设置AI画图模型名Kwai-Kolors/Kolors
+ - [x] 查看AI画图配置
+ - [x] AI画图 [描述]
+
AIWife
diff --git a/plugin/aiimage/main.go b/plugin/aiimage/main.go
index e9461c48a7..0c4fa7c81f 100644
--- a/plugin/aiimage/main.go
+++ b/plugin/aiimage/main.go
@@ -73,6 +73,7 @@ func init() {
en.OnPrefix("AI画图").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
+ ctx.SendChain(message.Text("少女思考中..."))
prompt := strings.TrimSpace(ctx.State["args"].(string))
if prompt == "" {
ctx.SendChain(message.Text("请输入图片描述"))
From 958be34780758dc633bcf200c71fbecf7fea9af5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Thu, 31 Jul 2025 18:51:04 +0800
Subject: [PATCH 12/14] =?UTF-8?q?=E2=9C=A8=20=E6=B7=BB=E5=8A=A0=E6=A0=A1?=
=?UTF-8?q?=E9=AA=8C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
plugin/aiimage/main.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/plugin/aiimage/main.go b/plugin/aiimage/main.go
index 0c4fa7c81f..bb52ad86ef 100644
--- a/plugin/aiimage/main.go
+++ b/plugin/aiimage/main.go
@@ -81,8 +81,8 @@ func init() {
}
cfg := GetConfig()
- if cfg.APIKey == "" || cfg.APIURL == "" {
- ctx.SendChain(message.Text("请先配置API密钥和地址"))
+ if cfg.APIKey == "" || cfg.APIURL == "" || cfg.ModelName == "" {
+ ctx.SendChain(message.Text("请先配置API密钥、地址和模型"))
return
}
From bd53c190b4cea95c83c3944bb4c5b63a50cf4118 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Tue, 12 Aug 2025 17:01:43 +0800
Subject: [PATCH 13/14] =?UTF-8?q?=F0=9F=8E=A8=20=E6=9B=B4=E6=96=B0zbputils?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
go.mod | 6 +++---
go.sum | 12 ++++++------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/go.mod b/go.mod
index c319db1c9e..3e7cd6dc5d 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
github.com/FloatTech/sqlite v1.7.1
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562
github.com/FloatTech/zbpctrl v1.7.0
- github.com/FloatTech/zbputils v1.7.2-0.20250614165821-95cf57cf2434
+ github.com/FloatTech/zbputils v1.7.2-0.20250812085410-2741050f465f
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5
github.com/Tnze/go-mc v1.20.2
@@ -22,7 +22,7 @@ require (
github.com/disintegration/imaging v1.6.2
github.com/fumiama/ahsai v0.1.0
github.com/fumiama/cron v1.3.0
- github.com/fumiama/deepinfra v0.0.0-20250601112706-0175c95164c1
+ github.com/fumiama/deepinfra v0.0.0-20250812083039-f1b27f21d8c9
github.com/fumiama/go-base16384 v1.7.0
github.com/fumiama/go-registry v0.2.7
github.com/fumiama/gotracemoe v0.0.3
@@ -45,7 +45,7 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/tidwall/gjson v1.18.0
github.com/wcharczuk/go-chart/v2 v2.1.2
- github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250707133321-6197b8ee5df7
+ github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250804063440-ccc03e33ac20
gitlab.com/gomidi/midi/v2 v2.1.7
golang.org/x/image v0.24.0
golang.org/x/sys v0.30.0
diff --git a/go.sum b/go.sum
index d4b9a61146..31ada71b36 100644
--- a/go.sum
+++ b/go.sum
@@ -17,8 +17,8 @@ github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562 h1:snfw7FNFym1eNnLrQ
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
github.com/FloatTech/zbpctrl v1.7.0 h1:Hxo6EIhJo+pHjcQP9QgIJgluaT1pHH99zkk3njqTNMo=
github.com/FloatTech/zbpctrl v1.7.0/go.mod h1:xmM4dSwHA02Gei3ogCRiG+RTrw/7Z69PfrN5NYf8BPE=
-github.com/FloatTech/zbputils v1.7.2-0.20250614165821-95cf57cf2434 h1:oEYQFQ2/qx10FtZKCNbW3Ohj/Iw71aM4RWpIu+LMmf8=
-github.com/FloatTech/zbputils v1.7.2-0.20250614165821-95cf57cf2434/go.mod h1:ArZ0fMAcmPEIXOqDmfzbSx+oYH8sssApQnbCu694iS8=
+github.com/FloatTech/zbputils v1.7.2-0.20250812085410-2741050f465f h1:5jnrFe9FTydb/pcUhxkWHuQVCwmYIZmneOkvmgHOwGI=
+github.com/FloatTech/zbputils v1.7.2-0.20250812085410-2741050f465f/go.mod h1:HG/yZwExV3b1Vqu4chbqwhfX4hx7gDS07QO436JkwIg=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 h1:S/ferNiehVjNaBMNNBxUjLtVmP/YWD6Yh79RfPv4ehU=
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
@@ -59,8 +59,8 @@ github.com/fumiama/ahsai v0.1.0 h1:LXD61Kaj6kJHa3AEGsLIfKNzcgaVxg7JB72OR4yNNZ4=
github.com/fumiama/ahsai v0.1.0/go.mod h1:fFeNnqgo44i8FIaguK659aQryuZeFy+4klYLQu/rfdk=
github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
-github.com/fumiama/deepinfra v0.0.0-20250601112706-0175c95164c1 h1:qE3l/y4Y1gMD2NokQ5Nw4NIUjL8ZwYLPIHOExQNu4hM=
-github.com/fumiama/deepinfra v0.0.0-20250601112706-0175c95164c1/go.mod h1:wW05PQSn8mo1mZIoa6LBUE+3xIBjkoONvnfPTV5ZOhY=
+github.com/fumiama/deepinfra v0.0.0-20250812083039-f1b27f21d8c9 h1:X2h8RnCgC04LmwBoizYbFawXh/h6CouXmhYtaVuUn7k=
+github.com/fumiama/deepinfra v0.0.0-20250812083039-f1b27f21d8c9/go.mod h1:wW05PQSn8mo1mZIoa6LBUE+3xIBjkoONvnfPTV5ZOhY=
github.com/fumiama/go-base16384 v1.7.0 h1:6fep7XPQWxRlh4Hu+KsdH+6+YdUp+w6CwRXtMWSsXCA=
github.com/fumiama/go-base16384 v1.7.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
github.com/fumiama/go-registry v0.2.7 h1:tLEqgEpsiybQMqBv0dLHm5leia/z1DhajMupwnOHeNs=
@@ -199,8 +199,8 @@ github.com/vcaesar/cedar v0.20.2/go.mod h1:lyuGvALuZZDPNXwpzv/9LyxW+8Y6faN7zauFe
github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4=
github.com/wcharczuk/go-chart/v2 v2.1.2 h1:Y17/oYNuXwZg6TFag06qe8sBajwwsuvPiJJXcUcLL6E=
github.com/wcharczuk/go-chart/v2 v2.1.2/go.mod h1:Zi4hbaqlWpYajnXB2K22IUYVXRXaLfSGNNR7P4ukyyQ=
-github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250707133321-6197b8ee5df7 h1:ya+lVbCC/EN5JumpQDDlVCSrWzLwHl4CHzlTANKDvrU=
-github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250707133321-6197b8ee5df7/go.mod h1:C86nQ0gIdAri4K2vg8IIQIslt08zzrKMcqYt8zhkx1M=
+github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250804063440-ccc03e33ac20 h1:Yzd+cbiJQYtf6cZDP5ZB/LqjNWiV752+5P6Eua+wnic=
+github.com/wdvxdr1123/ZeroBot v1.8.2-0.20250804063440-ccc03e33ac20/go.mod h1:C86nQ0gIdAri4K2vg8IIQIslt08zzrKMcqYt8zhkx1M=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
From 2b6a08cfb92013e8562b1c162e1c850ae533b965 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E9=94=85=E9=A5=AD?= <1156544355@qq.com>
Date: Fri, 15 Aug 2025 23:10:02 +0800
Subject: [PATCH 14/14] =?UTF-8?q?=F0=9F=8E=A8=20=E4=BC=98=E5=8C=96ai?=
=?UTF-8?q?=E7=94=BB=E5=9B=BE=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 2 +-
plugin/aiimage/config.go | 44 +++++++++-----------------------
plugin/aiimage/main.go | 54 +++++++++++++++++++++++++++-------------
3 files changed, 50 insertions(+), 50 deletions(-)
diff --git a/README.md b/README.md
index 7126c5cf65..f7535e4ae7 100644
--- a/README.md
+++ b/README.md
@@ -418,7 +418,7 @@ print("run[CQ:image,file="+j["img"]+"]")
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/aiimage"`
- - [x] 设置AI画图密钥
+ - [x] 设置AI画图密钥xxx
- [x] 设置AI画图接口地址https://api.siliconflow.cn/v1/images/generations
- [x] 设置AI画图模型名Kwai-Kolors/Kolors
- [x] 查看AI画图配置
diff --git a/plugin/aiimage/config.go b/plugin/aiimage/config.go
index d1111f9eaa..e48ec5c926 100644
--- a/plugin/aiimage/config.go
+++ b/plugin/aiimage/config.go
@@ -3,60 +3,40 @@ package aiimage
import (
"fmt"
- "os"
"strings"
"sync"
- "time"
sql "github.com/FloatTech/sqlite"
)
-// Storage 管理画图配置存储
-type Storage struct {
+// storage 管理画图配置存储
+type storage struct {
sync.RWMutex
db sql.Sqlite
}
-var (
- sdb = &Storage{
- db: sql.New("data/aiimage/config.db"),
- }
-)
-
-func init() {
- if err := os.MkdirAll("data/aiimage", 0755); err != nil {
- panic(err)
- }
- if err := sdb.db.Open(time.Hour * 24); err != nil {
- panic(err)
- }
- if err := sdb.db.Create("config", &ImageConfig{}); err != nil {
- panic(err)
- }
-}
-
-// ImageConfig 存储AI画图配置信息
-type ImageConfig struct {
+// imageConfig 存储AI画图配置信息
+type imageConfig struct {
ID int64 `db:"id"` // 主键ID
APIKey string `db:"apiKey"` // API密钥
APIURL string `db:"apiUrl"` // API地址
ModelName string `db:"modelName"` // 画图模型名称
}
-// GetConfig 获取当前配置
-func GetConfig() ImageConfig {
+// getConfig 获取当前配置
+func (sdb *storage) getConfig() imageConfig {
sdb.RLock()
defer sdb.RUnlock()
- cfg := ImageConfig{}
+ cfg := imageConfig{}
_ = sdb.db.Find("config", &cfg, "WHERE id = 1")
return cfg
}
-// SetConfig 设置AI画图配置
-func SetConfig(apiKey, apiURL, modelName string) error {
+// setConfig 设置AI画图配置
+func (sdb *storage) setConfig(apiKey, apiURL, modelName string) error {
sdb.Lock()
defer sdb.Unlock()
- return sdb.db.Insert("config", &ImageConfig{
+ return sdb.db.Insert("config", &imageConfig{
ID: 1,
APIKey: apiKey,
APIURL: apiURL,
@@ -65,8 +45,8 @@ func SetConfig(apiKey, apiURL, modelName string) error {
}
// PrintConfig 返回格式化后的配置信息
-func PrintConfig() string {
- cfg := GetConfig()
+func (sdb *storage) PrintConfig() string {
+ cfg := sdb.getConfig()
var builder strings.Builder
builder.WriteString("当前AI画图配置:\n")
builder.WriteString(fmt.Sprintf("• 密钥: %s\n", cfg.APIKey))
diff --git a/plugin/aiimage/main.go b/plugin/aiimage/main.go
index bb52ad86ef..519065e92a 100644
--- a/plugin/aiimage/main.go
+++ b/plugin/aiimage/main.go
@@ -6,8 +6,11 @@ import (
"encoding/json"
"net/http"
"strings"
+ "time"
+ fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/web"
+ sql "github.com/FloatTech/sqlite"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
@@ -18,11 +21,13 @@ import (
)
func init() {
+ var sdb = &storage{}
+
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Extra: control.ExtraFromString("aiimage"),
Brief: "AI画图",
- Help: "- 设置AI画图密钥\n" +
+ Help: "- 设置AI画图密钥xxx\n" +
"- 设置AI画图接口地址https://api.siliconflow.cn/v1/images/generations\n" +
"- 设置AI画图模型名Kwai-Kolors/Kolors\n" +
"- 查看AI画图配置\n" +
@@ -30,11 +35,27 @@ func init() {
PrivateDataFolder: "aiimage",
})
- en.OnPrefix("设置AI画图密钥", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
+ getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
+ sdb.db = sql.New(en.DataFolder() + "aiimage.db")
+ err := sdb.db.Open(time.Hour)
+ if err == nil {
+ // 创建配置表
+ err = sdb.db.Create("config", &imageConfig{})
+ if err != nil {
+ ctx.SendChain(message.Text("[ERROR]:", err))
+ return false
+ }
+ return true
+ }
+ ctx.SendChain(message.Text("[ERROR]:", err))
+ return false
+ })
+
+ en.OnPrefix("设置AI画图密钥", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
apiKey := strings.TrimSpace(ctx.State["args"].(string))
- cfg := GetConfig()
- err := SetConfig(apiKey, cfg.APIURL, cfg.ModelName)
+ cfg := sdb.getConfig()
+ err := sdb.setConfig(apiKey, cfg.APIURL, cfg.ModelName)
if err != nil {
ctx.SendChain(message.Text("ERROR: 设置API密钥失败: ", err))
return
@@ -42,11 +63,11 @@ func init() {
ctx.SendChain(message.Text("成功设置API密钥"))
})
- en.OnPrefix("设置AI画图接口地址", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
+ en.OnPrefix("设置AI画图接口地址", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
apiURL := strings.TrimSpace(ctx.State["args"].(string))
- cfg := GetConfig()
- err := SetConfig(cfg.APIKey, apiURL, cfg.ModelName)
+ cfg := sdb.getConfig()
+ err := sdb.setConfig(cfg.APIKey, apiURL, cfg.ModelName)
if err != nil {
ctx.SendChain(message.Text("ERROR: 设置API地址失败: ", err))
return
@@ -54,11 +75,11 @@ func init() {
ctx.SendChain(message.Text("成功设置API地址"))
})
- en.OnPrefix("设置AI画图模型名", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
+ en.OnPrefix("设置AI画图模型名", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
modelName := strings.TrimSpace(ctx.State["args"].(string))
- cfg := GetConfig()
- err := SetConfig(cfg.APIKey, cfg.APIURL, modelName)
+ cfg := sdb.getConfig()
+ err := sdb.setConfig(cfg.APIKey, cfg.APIURL, modelName)
if err != nil {
ctx.SendChain(message.Text("ERROR: 设置模型失败: ", err))
return
@@ -66,12 +87,12 @@ func init() {
ctx.SendChain(message.Text("成功设置模型: ", modelName))
})
- en.OnFullMatch("查看AI画图配置", zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
+ en.OnFullMatch("查看AI画图配置", getdb, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
- ctx.SendChain(message.Text(PrintConfig()))
+ ctx.SendChain(message.Text(sdb.PrintConfig()))
})
- en.OnPrefix("AI画图").SetBlock(true).
+ en.OnPrefix("AI画图", getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女思考中..."))
prompt := strings.TrimSpace(ctx.State["args"].(string))
@@ -80,22 +101,21 @@ func init() {
return
}
- cfg := GetConfig()
+ cfg := sdb.getConfig()
if cfg.APIKey == "" || cfg.APIURL == "" || cfg.ModelName == "" {
ctx.SendChain(message.Text("请先配置API密钥、地址和模型"))
return
}
// 准备请求数据
- reqData := map[string]interface{}{
+ reqBytes, _ := json.Marshal(map[string]interface{}{
"model": cfg.ModelName,
"prompt": prompt,
"image_size": "1024x1024",
"batch_size": 4,
"num_inference_steps": 20,
"guidance_scale": 7.5,
- }
- reqBytes, _ := json.Marshal(reqData)
+ })
// 发送API请求
data, err := web.RequestDataWithHeaders(