Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions airecord/record.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Package airecord 群应用:AI声聊
package airecord

import (
"strconv"
"strings"
"time"

"github.com/sirupsen/logrus"
"github.com/tidwall/gjson"

zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"

ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
)

func init() {
if err := loadConfig(); err != nil {
logrus.Warnln("WARN: 加载配置文件失败,使用默认配置:", err)
} else {
logrus.Infoln("成功从文件加载语音记录配置")
}
en := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Extra: control.ExtraFromString("airecord"),
Brief: "群应用:AI声聊",
Help: "- 设置AI语音群号1048452984(tips:机器人任意所在群聊即可)\n" +
"- 设置AI语音模型\n" +
"- 查看AI语音配置\n" +
"- 发送AI语音xxx",
PrivateDataFolder: "airecord",
})

en.OnPrefix("设置AI语音群号", zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
u := strings.TrimSpace(ctx.State["args"].(string))
num, err := strconv.ParseInt(u, 10, 64)
if err != nil {
ctx.SendChain(message.Text("ERROR: parse gid err: ", err))
return
}
setCustomGID(num)
ctx.SendChain(message.Text("设置AI语音群号为", num))
})
en.OnFullMatch("设置AI语音模型", zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession())
recv, cancel := next.Repeat()
defer cancel()
jsonData := ctx.GetAICharacters(0, 1)

Check failure on line 52 in airecord/record.go

View workflow job for this annotation

GitHub Actions / lint

ctx.GetAICharacters undefined (type *zero.Ctx has no field or method GetAICharacters)

// 转换为字符串数组
var names []string
// 初始化两个映射表
nameToID := make(map[string]string)
nameToURL := make(map[string]string)
characters := jsonData.Get("#.characters")

// 遍历每个角色对象
characters.ForEach(func(_, group gjson.Result) bool {
group.ForEach(func(_, character gjson.Result) bool {
// 提取当前角色的三个字段
name := character.Get("character_name").String()
names = append(names, name)
// 存入映射表(重复名称会覆盖,保留最后出现的条目)
nameToID[name] = character.Get("character_id").String()
nameToURL[name] = character.Get("preview_url").String()
return true // 继续遍历
})
return true // 继续遍历
})
var builder strings.Builder
// 写入开头文本
builder.WriteString("请选择语音模型序号:\n")

// 遍历names数组,拼接序号和名称
for i, v := range names {
// 将数字转换为字符串(不依赖fmt)
numStr := strconv.Itoa(i)
// 拼接格式:"序号. 名称\n"
builder.WriteString(numStr)
builder.WriteString(". ")
builder.WriteString(v)
builder.WriteString("\n")
}
// 获取最终字符串
ctx.SendChain(message.Text(builder.String()))
for {
select {
case <-time.After(time.Second * 120):
ctx.SendChain(message.Text("设置AI语音模型指令过期"))
return
case ct := <-recv:
msg := ct.Event.Message.ExtractPlainText()
num, err := strconv.Atoi(msg)
if err != nil {
ctx.SendChain(message.Text("请输入数字!"))
continue
}
if num < 0 || num >= len(names) {
ctx.SendChain(message.Text("序号非法!"))
continue
}
setRecordModel(names[num], nameToID[names[num]])
ctx.SendChain(message.Text("已选择语音模型: ", names[num]))
ctx.SendChain(message.Record(nameToURL[names[num]]))
return
}
}
})
en.OnFullMatch("查看AI语音配置").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text(printRecordConfig(recordcfg)))
})
en.OnPrefix("发送AI语音").SetBlock(true).
Handle(func(ctx *zero.Ctx) {
u := strings.TrimSpace(ctx.State["args"].(string))
record := ctx.GetAIRecord(recordcfg.ModelID, recordcfg.Customgid, u).String()

Check failure on line 120 in airecord/record.go

View workflow job for this annotation

GitHub Actions / lint

ctx.GetAIRecord undefined (type *zero.Ctx has no field or method GetAIRecord) (typecheck)
if record == "" {
ctx.SendChain(message.Text("ERROR: get record err: empty record"))
return
}
ctx.SendChain(message.Record(record))
})
}
79 changes: 79 additions & 0 deletions airecord/recordcfg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package airecord

import (
"encoding/json"
"fmt"
"os"
"strings"

"github.com/sirupsen/logrus"
)

var (
recordcfg recordconfig
configPath = "data/airecord/recordconfig.json" // 配置文件路径
)

// recordconfig 存储语音记录相关配置
type recordconfig struct {
ModelName string `json:"modelName"` // 语音模型名称
ModelID string `json:"modelID"` // 语音模型ID
Customgid int64 `json:"customgid"` // 自定义群ID
}

// GetRecordConfig 返回当前语音记录配置信息
func GetRecordConfig() recordconfig {
return recordcfg
}

// setRecordModel 设置语音记录模型
func setRecordModel(modelName, modelID string) {
recordcfg.ModelName = modelName
recordcfg.ModelID = modelID
saveConfig() // 保存配置
}

// setCustomGID 设置自定义群ID
func setCustomGID(gid int64) {
recordcfg.Customgid = gid
saveConfig() // 保存配置
}

// printRecordConfig 生成格式化的语音记录配置信息字符串
func printRecordConfig(recCfg recordconfig) string {
var builder strings.Builder
builder.WriteString("当前语音记录配置:\n")
builder.WriteString(fmt.Sprintf("• 语音模型名称:%s\n", recCfg.ModelName))
builder.WriteString(fmt.Sprintf("• 语音模型ID:%s\n", recCfg.ModelID))
builder.WriteString(fmt.Sprintf("• 自定义群ID:%d\n", recCfg.Customgid))
return builder.String()
}

// saveConfig 将配置保存到JSON文件
func saveConfig() error {
data, err := json.MarshalIndent(recordcfg, "", " ")
if err != nil {
logrus.Warnln("ERROR: 序列化配置失败:", err)
return err
}
err = os.WriteFile(configPath, data, 0644)
if err != nil {
logrus.Warnln("ERROR: 写入配置文件失败:", err)
return err
}
return nil
}

// loadConfig 从JSON文件加载配置
func loadConfig() error {
data, err := os.ReadFile(configPath)
if err != nil {
return err
}
err = json.Unmarshal(data, &recordcfg)
if err != nil {
logrus.Warnln("ERROR: 解析配置文件失败:", err)
return err
}
return nil
}
2 changes: 1 addition & 1 deletion driver/funcall.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
r = &zero.APIResponse{ // 发送api调用响应
Status: s,
Data: data.Get("data"),
Msg: m,
Message: m,

Check failure on line 165 in driver/funcall.go

View workflow job for this annotation

GitHub Actions / lint

unknown field Message in struct literal of type zero.APIResponse (typecheck)
Wording: w,
RetCode: c,
Echo: req.Echo,
Expand Down
Loading