fix:修复报错
This commit is contained in:
parent
09d98fb8eb
commit
e6c142f3a1
|
|
@ -88,7 +88,7 @@ permissionConfig:
|
||||||
permission_url: "http://api.test.user.1688sup.cn:8001/v1/menu/myCodes?systemId="
|
permission_url: "http://api.test.user.1688sup.cn:8001/v1/menu/myCodes?systemId="
|
||||||
|
|
||||||
|
|
||||||
ding_talk_bots:
|
#ding_talk_bots:
|
||||||
public:
|
# public:
|
||||||
client_id: "dingchg59zwwvmuuvldx",
|
# client_id: "dingchg59zwwvmuuvldx",
|
||||||
client_secret: "ZwetAnRiTQobNFVlNrshRagSMAJIFpBAepWkWI7on7Tt_o617KHtTjBLp8fQfplz",
|
# client_secret: "ZwetAnRiTQobNFVlNrshRagSMAJIFpBAepWkWI7on7Tt_o617KHtTjBLp8fQfplz",
|
||||||
|
|
@ -2,29 +2,61 @@ package biz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ai_scheduler/internal/biz/do"
|
"ai_scheduler/internal/biz/do"
|
||||||
|
"ai_scheduler/internal/data/constants"
|
||||||
|
"ai_scheduler/internal/data/impl"
|
||||||
|
"ai_scheduler/internal/data/model"
|
||||||
"ai_scheduler/internal/entitys"
|
"ai_scheduler/internal/entitys"
|
||||||
|
"ai_scheduler/internal/pkg/mapstructure"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2/log"
|
||||||
"github.com/open-dingtalk/dingtalk-stream-sdk-go/chatbot"
|
"github.com/open-dingtalk/dingtalk-stream-sdk-go/chatbot"
|
||||||
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AiRouterBiz 智能路由服务
|
// AiRouterBiz 智能路由服务
|
||||||
type DingTalkBotBiz struct {
|
type DingTalkBotBiz struct {
|
||||||
do *do.Do
|
do *do.Do
|
||||||
handle *do.Handle
|
handle *do.Handle
|
||||||
|
botConfigImpl *impl.BotConfigImpl
|
||||||
|
replier *chatbot.ChatbotReplier
|
||||||
|
log log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDingTalkBotBiz
|
// NewDingTalkBotBiz
|
||||||
func NewDingTalkBotBiz(
|
func NewDingTalkBotBiz(
|
||||||
do *do.Do,
|
do *do.Do,
|
||||||
handle *do.Handle,
|
handle *do.Handle,
|
||||||
|
botConfigImpl *impl.BotConfigImpl,
|
||||||
) *DingTalkBotBiz {
|
) *DingTalkBotBiz {
|
||||||
return &DingTalkBotBiz{
|
return &DingTalkBotBiz{
|
||||||
do: do,
|
do: do,
|
||||||
handle: handle,
|
handle: handle,
|
||||||
|
botConfigImpl: botConfigImpl,
|
||||||
|
replier: chatbot.NewChatbotReplier(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DingTalkBotBiz) GetDingTalkBotCfgList() (dingBotList []entitys.DingTalkBot, err error) {
|
||||||
|
botConfig := make([]model.AiBotConfig, 0)
|
||||||
|
|
||||||
|
cond := builder.NewCond()
|
||||||
|
cond = cond.And(builder.Eq{"status": constants.Enable})
|
||||||
|
cond = cond.And(builder.Eq{"bot_type": constants.BotTypeDingTalk})
|
||||||
|
err = d.botConfigImpl.GetRangeToMapStruct(&cond, &botConfig)
|
||||||
|
for _, v := range botConfig {
|
||||||
|
var config entitys.DingTalkBot
|
||||||
|
err = mapstructure.Decode(v, &config)
|
||||||
|
if err != nil {
|
||||||
|
d.log.Info("初始化“%s”失败:%s", v.BotName, err.Error())
|
||||||
|
}
|
||||||
|
dingBotList = append(dingBotList, config)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (d *DingTalkBotBiz) InitRequire(ctx context.Context, data *chatbot.BotCallbackDataModel) (requireData *entitys.RequireDataDingTalkBot, err error) {
|
func (d *DingTalkBotBiz) InitRequire(ctx context.Context, data *chatbot.BotCallbackDataModel) (requireData *entitys.RequireDataDingTalkBot, err error) {
|
||||||
requireData = &entitys.RequireDataDingTalkBot{
|
requireData = &entitys.RequireDataDingTalkBot{
|
||||||
Req: data,
|
Req: data,
|
||||||
|
|
@ -37,6 +69,74 @@ func (d *DingTalkBotBiz) InitRequire(ctx context.Context, data *chatbot.BotCallb
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DingTalkBotBiz) Recognize(ctx context.Context, rec *entitys.Recognize, ch chan entitys.Response) (match *entitys.Match, err error) {
|
func (d *DingTalkBotBiz) Recognize(ctx context.Context, bot *chatbot.BotCallbackDataModel) (match entitys.Match, err error) {
|
||||||
return d.handle.RecognizeBot(ctx, rec, ch)
|
|
||||||
|
return d.handle.Recognize(ctx, nil, &do.WithDingTalkBot{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DingTalkBotBiz) HandleRes(ctx context.Context, data *chatbot.BotCallbackDataModel, resp entitys.Response) error {
|
||||||
|
switch resp.Type {
|
||||||
|
case entitys.ResponseText:
|
||||||
|
return d.replyText(ctx, data.SessionWebhook, resp.Content)
|
||||||
|
case entitys.ResponseStream:
|
||||||
|
return d.replySteam(ctx, data.SessionWebhook, resp.Content)
|
||||||
|
case entitys.ResponseImg:
|
||||||
|
return d.replyImg(ctx, data.SessionWebhook, resp.Content)
|
||||||
|
case entitys.ResponseFile:
|
||||||
|
return d.replyFile(ctx, data.SessionWebhook, resp.Content)
|
||||||
|
case entitys.ResponseMarkdown:
|
||||||
|
return d.replyMarkdown(ctx, data.SessionWebhook, resp.Content)
|
||||||
|
case entitys.ResponseActionCard:
|
||||||
|
return d.replyActionCard(ctx, data.SessionWebhook, resp.Content)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DingTalkBotBiz) replySteam(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
||||||
|
msg := content
|
||||||
|
if len(arg) > 0 {
|
||||||
|
msg = fmt.Sprintf(content, arg)
|
||||||
|
}
|
||||||
|
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DingTalkBotBiz) replyText(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
||||||
|
msg := content
|
||||||
|
if len(arg) > 0 {
|
||||||
|
msg = fmt.Sprintf(content, arg)
|
||||||
|
}
|
||||||
|
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DingTalkBotBiz) replyImg(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
||||||
|
msg := content
|
||||||
|
if len(arg) > 0 {
|
||||||
|
msg = fmt.Sprintf(content, arg)
|
||||||
|
}
|
||||||
|
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DingTalkBotBiz) replyFile(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
||||||
|
msg := content
|
||||||
|
if len(arg) > 0 {
|
||||||
|
msg = fmt.Sprintf(content, arg)
|
||||||
|
}
|
||||||
|
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DingTalkBotBiz) replyMarkdown(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
||||||
|
msg := content
|
||||||
|
if len(arg) > 0 {
|
||||||
|
msg = fmt.Sprintf(content, arg)
|
||||||
|
}
|
||||||
|
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DingTalkBotBiz) replyActionCard(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
||||||
|
msg := content
|
||||||
|
if len(arg) > 0 {
|
||||||
|
msg = fmt.Sprintf(content, arg)
|
||||||
|
}
|
||||||
|
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package do
|
package do
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"ai_scheduler/internal/biz/handle"
|
||||||
"ai_scheduler/internal/entitys"
|
"ai_scheduler/internal/entitys"
|
||||||
"ai_scheduler/internal/pkg"
|
"ai_scheduler/internal/pkg"
|
||||||
"context"
|
"context"
|
||||||
|
|
@ -42,7 +43,7 @@ func (f *WithSys) CreatePrompt(ctx context.Context, rec *entitys.Recognize) (mes
|
||||||
|
|
||||||
func (f *WithSys) getUserContent(ctx context.Context, rec *entitys.Recognize) (content strings.Builder, err error) {
|
func (f *WithSys) getUserContent(ctx context.Context, rec *entitys.Recognize) (content strings.Builder, err error) {
|
||||||
var hasFile bool
|
var hasFile bool
|
||||||
if len(rec.UserContent.FileUrl) > 0 || rec.UserContent.File != nil {
|
if rec.UserContent.File != nil && (len(rec.UserContent.File.FileUrl) > 0 || rec.UserContent.File.File != nil) {
|
||||||
hasFile = true
|
hasFile = true
|
||||||
}
|
}
|
||||||
content.WriteString(rec.UserContent.Text)
|
content.WriteString(rec.UserContent.Text)
|
||||||
|
|
@ -64,7 +65,65 @@ func (f *WithSys) getUserContent(ctx context.Context, rec *entitys.Recognize) (c
|
||||||
if hasFile {
|
if hasFile {
|
||||||
content.WriteString("\n")
|
content.WriteString("\n")
|
||||||
content.WriteString("### 文件内容:\n")
|
content.WriteString("### 文件内容:\n")
|
||||||
hand.WriteString(rec.UserContent.FileUrl, rec.UserContent.FileUrl)
|
handle.HandleRecognizeFile(rec.UserContent.File)
|
||||||
|
//...do something with file
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type WithDingTalkBot struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *WithDingTalkBot) CreatePrompt(ctx context.Context, rec *entitys.Recognize) (mes []api.Message, err error) {
|
||||||
|
var (
|
||||||
|
prompt = make([]api.Message, 0) // 初始化一个空的api.Message切片
|
||||||
|
)
|
||||||
|
// 获取用户内容,如果出错则直接返回错误
|
||||||
|
content, err := f.getUserContent(ctx, rec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 构建提示消息列表,包含系统提示、助手回复和用户内容
|
||||||
|
mes = append(prompt, api.Message{
|
||||||
|
Role: "system", // 系统角色
|
||||||
|
Content: rec.SystemPrompt, // 系统提示内容
|
||||||
|
}, api.Message{
|
||||||
|
Role: "assistant", // 助手角色
|
||||||
|
Content: "### 聊天记录:" + pkg.JsonStringIgonErr(rec.ChatHis), // 助手回复内容
|
||||||
|
}, api.Message{
|
||||||
|
Role: "user", // 用户角色
|
||||||
|
Content: content.String(), // 用户输入内容
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *WithDingTalkBot) getUserContent(ctx context.Context, rec *entitys.Recognize) (content strings.Builder, err error) {
|
||||||
|
var hasFile bool
|
||||||
|
if rec.UserContent.File != nil && (len(rec.UserContent.File.FileUrl) > 0 || rec.UserContent.File.File != nil) {
|
||||||
|
hasFile = true
|
||||||
|
}
|
||||||
|
content.WriteString(rec.UserContent.Text)
|
||||||
|
if hasFile {
|
||||||
|
content.WriteString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rec.UserContent.Tag) > 0 {
|
||||||
|
content.WriteString("\n")
|
||||||
|
content.WriteString("### 工具必须使用:")
|
||||||
|
content.WriteString(rec.UserContent.Tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rec.ChatHis.Messages) > 0 {
|
||||||
|
content.WriteString("### 引用历史聊天记录:\n")
|
||||||
|
content.WriteString(pkg.JsonStringIgonErr(rec.ChatHis))
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasFile {
|
||||||
|
content.WriteString("\n")
|
||||||
|
content.WriteString("### 文件内容:\n")
|
||||||
|
handle.HandleRecognizeFile(rec.UserContent.File)
|
||||||
|
//...do something with file
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,7 @@ type Config struct {
|
||||||
DB DB `mapstructure:"db"`
|
DB DB `mapstructure:"db"`
|
||||||
DefaultPrompt SysPrompt `mapstructure:"default_prompt"`
|
DefaultPrompt SysPrompt `mapstructure:"default_prompt"`
|
||||||
PermissionConfig PermissionConfig `mapstructure:"permissionConfig"`
|
PermissionConfig PermissionConfig `mapstructure:"permissionConfig"`
|
||||||
DingTalkBots map[string]*DingTalkBot `mapstructure:"ding_talk_bots"`
|
// DingTalkBots map[string]*DingTalkBot `mapstructure:"ding_talk_bots"`
|
||||||
}
|
|
||||||
|
|
||||||
type DingTalkBot struct {
|
|
||||||
ClientId string `mapstructure:"client_id"`
|
|
||||||
ClientSecret string `mapstructure:"client_secret"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SysPrompt struct {
|
type SysPrompt struct {
|
||||||
|
|
|
||||||
|
|
@ -25,3 +25,9 @@ var ChatStyleMap = map[ChatStyle]string{
|
||||||
ChatStyleCute: "可爱",
|
ChatStyleCute: "可爱",
|
||||||
ChatStyleAngry: "愤怒",
|
ChatStyleAngry: "愤怒",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BotType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
BotTypeDingTalk BotType = 1 // 系统的bug/优化建议
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ BaseModel 是一个泛型结构体,用于封装GORM数据库通用操作。
|
||||||
// 定义受支持的PO类型集合(可根据需要扩展), 只有包含表结构才能使用BaseModel,避免使用出现问题
|
// 定义受支持的PO类型集合(可根据需要扩展), 只有包含表结构才能使用BaseModel,避免使用出现问题
|
||||||
type PO interface {
|
type PO interface {
|
||||||
model.AiChatHi |
|
model.AiChatHi |
|
||||||
model.AiSy | model.AiSession | model.AiTask | model.AiBot
|
model.AiSy | model.AiSession | model.AiTask | model.AiBotConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type BaseModel[P PO] struct {
|
type BaseModel[P PO] struct {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,6 @@ type BotChatHisImpl struct {
|
||||||
dataTemp.DataTemp
|
dataTemp.DataTemp
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBotChatHisImpl(db *utils.Db) *TaskImpl {
|
func NewBotChatHisImpl(db *utils.Db) *BotChatHisImpl {
|
||||||
return &TaskImpl{*dataTemp.NewDataTemp(db, new(model.AiBotChatHi))}
|
return &BotChatHisImpl{*dataTemp.NewDataTemp(db, new(model.AiBotChatHi))}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package impl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ai_scheduler/internal/data/model"
|
||||||
|
"ai_scheduler/tmpl/dataTemp"
|
||||||
|
"ai_scheduler/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BotConfigImpl struct {
|
||||||
|
dataTemp.DataTemp
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBotConfigImpl(db *utils.Db) *BotConfigImpl {
|
||||||
|
return &BotConfigImpl{
|
||||||
|
DataTemp: *dataTemp.NewDataTemp(db, new(model.AiBotConfig)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
package impl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"ai_scheduler/internal/data/model"
|
|
||||||
"ai_scheduler/tmpl/dataTemp"
|
|
||||||
"ai_scheduler/utils"
|
|
||||||
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type BotImpl struct {
|
|
||||||
dataTemp.DataTemp
|
|
||||||
BaseRepository[model.AiBot]
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewBotImpl(db *utils.Db) *BotImpl {
|
|
||||||
return &BotImpl{
|
|
||||||
DataTemp: *dataTemp.NewDataTemp(db, new(model.AiBot)),
|
|
||||||
BaseRepository: NewBaseModel[model.AiBot](db.Client),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithSysId 系统id
|
|
||||||
func (s *BotImpl) WithSysId(sysId interface{}) CondFunc {
|
|
||||||
return func(db *gorm.DB) *gorm.DB {
|
|
||||||
return db.Where("sys_id = ?", sysId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,4 +4,10 @@ import (
|
||||||
"github.com/google/wire"
|
"github.com/google/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ProviderImpl = wire.NewSet(NewSessionImpl, NewSysImpl, NewTaskImpl, NewChatHisImpl)
|
var ProviderImpl = wire.NewSet(
|
||||||
|
NewSessionImpl,
|
||||||
|
NewSysImpl,
|
||||||
|
NewTaskImpl,
|
||||||
|
NewChatHisImpl,
|
||||||
|
NewBotConfigImpl,
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const TableNameAiBot = "ai_bot"
|
const TableNameAiBotConfig = "ai_bot_config"
|
||||||
|
|
||||||
// AiBot mapped from table <ai_bot>
|
// AiBotConfig mapped from table <ai_bot_config>
|
||||||
type AiBot struct {
|
type AiBotConfig struct {
|
||||||
BotID int32 `gorm:"column:bot_id;primaryKey;autoIncrement:true" json:"bot_id"`
|
BotID int32 `gorm:"column:bot_id;primaryKey;autoIncrement:true" json:"bot_id"`
|
||||||
SysID int32 `gorm:"column:sys_id;not null" json:"sys_id"`
|
SysID int32 `gorm:"column:sys_id;not null" json:"sys_id"`
|
||||||
BotType int32 `gorm:"column:bot_type" json:"bot_type"`
|
BotType int32 `gorm:"column:bot_type;not null;default:1" json:"bot_type"`
|
||||||
BotName string `gorm:"column:bot_name;not null" json:"bot_name"`
|
BotName string `gorm:"column:bot_name;not null" json:"bot_name"`
|
||||||
BotConfig string `gorm:"column:bot_config;not null" json:"bot_config"`
|
BotConfig string `gorm:"column:bot_config;not null" json:"bot_config"`
|
||||||
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
|
CreateAt time.Time `gorm:"column:create_at;default:CURRENT_TIMESTAMP" json:"create_at"`
|
||||||
|
|
@ -23,7 +23,7 @@ type AiBot struct {
|
||||||
DeleteAt time.Time `gorm:"column:delete_at" json:"delete_at"`
|
DeleteAt time.Time `gorm:"column:delete_at" json:"delete_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName AiBot's table name
|
// TableName AiBotConfig's table name
|
||||||
func (*AiBot) TableName() string {
|
func (*AiBotConfig) TableName() string {
|
||||||
return TableNameAiBot
|
return TableNameAiBotConfig
|
||||||
}
|
}
|
||||||
|
|
@ -22,3 +22,8 @@ type RequireDataDingTalkBot struct {
|
||||||
ImgByte []api.ImageData
|
ImgByte []api.ImageData
|
||||||
ImgUrls []string
|
ImgUrls []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DingTalkBot struct {
|
||||||
|
ClientId string `mapstructure:"client_id"`
|
||||||
|
ClientSecret string `mapstructure:"client_secret"`
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ai_scheduler/internal/config"
|
"ai_scheduler/internal/entitys"
|
||||||
"ai_scheduler/internal/services"
|
"ai_scheduler/internal/services"
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type DingBotServiceInterface interface {
|
type DingBotServiceInterface interface {
|
||||||
GetServiceCfg(cfg map[string]*config.DingTalkBot) (*config.DingTalkBot, string)
|
GetServiceCfg() ([]entitys.DingTalkBot, error)
|
||||||
OnChatBotMessageReceived(ctx context.Context, data *chatbot.BotCallbackDataModel) (content []byte, err error)
|
OnChatBotMessageReceived(ctx context.Context, data *chatbot.BotCallbackDataModel) (content []byte, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -19,15 +19,19 @@ type DingTalkBotServer struct {
|
||||||
Clients []*client.StreamClient
|
Clients []*client.StreamClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDingTalkBotServer 批量注册钉钉客户端cli
|
||||||
|
// 这里支持两种方式,一种是完全独立service,一种是直接用现成的service
|
||||||
|
// 独立的service,在本页的ProvideAllDingBotServices方法进行注册
|
||||||
|
// 现成的service参考services->dtalk_bot.go
|
||||||
|
// 具体使用请根据实际业务需求
|
||||||
func NewDingTalkBotServer(
|
func NewDingTalkBotServer(
|
||||||
cfg *config.Config,
|
|
||||||
services []DingBotServiceInterface,
|
services []DingBotServiceInterface,
|
||||||
) *DingTalkBotServer {
|
) *DingTalkBotServer {
|
||||||
clients := make([]*client.StreamClient, 0)
|
clients := make([]*client.StreamClient, 0)
|
||||||
for _, service := range services {
|
for _, service := range services {
|
||||||
serviceConf, index := service.GetServiceCfg(cfg.DingTalkBots)
|
serviceConfigs, index := service.GetServiceCfg()
|
||||||
if serviceConf == nil {
|
for _, serviceConf := range serviceConfigs {
|
||||||
log.Info("未找到%s配置", index)
|
if serviceConf.ClientId == "" || serviceConf.ClientSecret == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cli := DingBotServerInit(serviceConf.ClientId, serviceConf.ClientSecret, service)
|
cli := DingBotServerInit(serviceConf.ClientId, serviceConf.ClientSecret, service)
|
||||||
|
|
@ -37,6 +41,7 @@ func NewDingTalkBotServer(
|
||||||
}
|
}
|
||||||
clients = append(clients, cli)
|
clients = append(clients, cli)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return &DingTalkBotServer{
|
return &DingTalkBotServer{
|
||||||
Clients: clients,
|
Clients: clients,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package services
|
||||||
import (
|
import (
|
||||||
"ai_scheduler/internal/biz"
|
"ai_scheduler/internal/biz"
|
||||||
"ai_scheduler/internal/config"
|
"ai_scheduler/internal/config"
|
||||||
|
|
||||||
"ai_scheduler/internal/entitys"
|
"ai_scheduler/internal/entitys"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -12,40 +13,38 @@ import (
|
||||||
|
|
||||||
type DingBotService struct {
|
type DingBotService struct {
|
||||||
config *config.Config
|
config *config.Config
|
||||||
replier *chatbot.ChatbotReplier
|
|
||||||
env string
|
dingTalkBotBiz *biz.DingTalkBotBiz
|
||||||
DingTalkBotBiz *biz.DingTalkBotBiz
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDingBotService(config *config.Config, DingTalkBotBiz *biz.DingTalkBotBiz) *DingBotService {
|
func NewDingBotService(config *config.Config, DingTalkBotBiz *biz.DingTalkBotBiz) *DingBotService {
|
||||||
return &DingBotService{config: config, replier: chatbot.NewChatbotReplier(), env: "public", DingTalkBotBiz: DingTalkBotBiz}
|
return &DingBotService{config: config, dingTalkBotBiz: DingTalkBotBiz}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DingBotService) GetServiceCfg(cfg map[string]*config.DingTalkBot) (*config.DingTalkBot, string) {
|
func (d *DingBotService) GetServiceCfg() ([]entitys.DingTalkBot, error) {
|
||||||
return cfg[d.env], d.env
|
return d.dingTalkBotBiz.GetDingTalkBotCfgList()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DingBotService) OnChatBotMessageReceived(ctx context.Context, data *chatbot.BotCallbackDataModel) (content []byte, err error) {
|
func (d *DingBotService) OnChatBotMessageReceived(ctx context.Context, data *chatbot.BotCallbackDataModel) (content []byte, err error) {
|
||||||
requireData, err := d.DingTalkBotBiz.InitRequire(ctx, data)
|
requireData, err := d.dingTalkBotBiz.InitRequire(ctx, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer close(requireData.Ch)
|
defer close(requireData.Ch)
|
||||||
|
//if match, _err := d.dingTalkBotBiz.Recognize(ctx, data); _err != nil {
|
||||||
if recognizeErr := d.DingTalkBotBiz.Recognize(ctx, requireData); recognizeErr != nil {
|
// requireData.Ch <- entitys.Response{
|
||||||
requireData.Ch <- entitys.Response{
|
// Type: entitys.ResponseEnd,
|
||||||
Type: entitys.ResponseEnd,
|
// Content: fmt.Sprintf("处理消息时出错: %s", _err.Error()),
|
||||||
Content: fmt.Sprintf("处理消息时出错: %v", recognizeErr),
|
// }
|
||||||
}
|
//}
|
||||||
}
|
////向下传递
|
||||||
//向下传递
|
//if err = d.dingTalkBotBiz.HandleMatch(ctx, nil, requireData); err != nil {
|
||||||
if err = d.handle.HandleMatch(ctx, nil, requireData); err != nil {
|
// requireData.Ch <- entitys.Response{
|
||||||
requireData.Ch <- entitys.Response{
|
// Type: entitys.ResponseEnd,
|
||||||
Type: entitys.ResponseEnd,
|
// Content: fmt.Sprintf("匹配失败: %v", err),
|
||||||
Content: fmt.Sprintf("匹配失败: %v", err),
|
// }
|
||||||
}
|
//}
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
|
@ -59,77 +58,10 @@ func (d *DingBotService) OnChatBotMessageReceived(ctx context.Context, data *cha
|
||||||
if resp.Type == entitys.ResponseLog {
|
if resp.Type == entitys.ResponseLog {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := d.handleRes(ctx, data, resp); err != nil {
|
if err := d.dingTalkBotBiz.HandleRes(ctx, data, resp); err != nil {
|
||||||
return nil, fmt.Errorf("回复失败: %w", err)
|
return nil, fmt.Errorf("回复失败: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DingBotService) handleRes(ctx context.Context, data *chatbot.BotCallbackDataModel, resp entitys.Response) error {
|
|
||||||
switch resp.Type {
|
|
||||||
case entitys.ResponseText:
|
|
||||||
return d.replyText(ctx, data.SessionWebhook, resp.Content)
|
|
||||||
case entitys.ResponseStream:
|
|
||||||
return d.replySteam(ctx, data.SessionWebhook, resp.Content)
|
|
||||||
case entitys.ResponseImg:
|
|
||||||
return d.replyImg(ctx, data.SessionWebhook, resp.Content)
|
|
||||||
case entitys.ResponseFile:
|
|
||||||
return d.replyFile(ctx, data.SessionWebhook, resp.Content)
|
|
||||||
case entitys.ResponseMarkdown:
|
|
||||||
return d.replyMarkdown(ctx, data.SessionWebhook, resp.Content)
|
|
||||||
case entitys.ResponseActionCard:
|
|
||||||
return d.replyActionCard(ctx, data.SessionWebhook, resp.Content)
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DingBotService) replyText(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
|
||||||
msg := content
|
|
||||||
if len(arg) > 0 {
|
|
||||||
msg = fmt.Sprintf(content, arg)
|
|
||||||
}
|
|
||||||
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DingBotService) replySteam(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
|
||||||
msg := content
|
|
||||||
if len(arg) > 0 {
|
|
||||||
msg = fmt.Sprintf(content, arg)
|
|
||||||
}
|
|
||||||
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DingBotService) replyImg(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
|
||||||
msg := content
|
|
||||||
if len(arg) > 0 {
|
|
||||||
msg = fmt.Sprintf(content, arg)
|
|
||||||
}
|
|
||||||
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DingBotService) replyFile(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
|
||||||
msg := content
|
|
||||||
if len(arg) > 0 {
|
|
||||||
msg = fmt.Sprintf(content, arg)
|
|
||||||
}
|
|
||||||
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DingBotService) replyMarkdown(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
|
||||||
msg := content
|
|
||||||
if len(arg) > 0 {
|
|
||||||
msg = fmt.Sprintf(content, arg)
|
|
||||||
}
|
|
||||||
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DingBotService) replyActionCard(ctx context.Context, SessionWebhook string, content string, arg ...string) error {
|
|
||||||
msg := content
|
|
||||||
if len(arg) > 0 {
|
|
||||||
msg = fmt.Sprintf(content, arg)
|
|
||||||
}
|
|
||||||
return d.replier.SimpleReplyText(ctx, SessionWebhook, []byte(msg))
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,10 @@ import (
|
||||||
"github.com/google/wire"
|
"github.com/google/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ProviderSetServices = wire.NewSet(NewChatService, NewSessionService, gateway.NewGateway, NewTaskService, NewCallbackService, NewHistoryService)
|
var ProviderSetServices = wire.NewSet(
|
||||||
|
NewChatService,
|
||||||
|
NewSessionService, gateway.NewGateway,
|
||||||
|
NewTaskService,
|
||||||
|
NewCallbackService,
|
||||||
|
NewDingBotService,
|
||||||
|
NewHistoryService)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue