From a7588ab89b5a6c24c115eae7fa6745e706c858c5 Mon Sep 17 00:00:00 2001 From: cosmo Date: Tue, 21 Nov 2023 10:00:23 +0800 Subject: [PATCH 1/8] bugfix --- echo/echo.go | 36 ++++++++++++++++++++++++++++++++++++ handlers/send_group_msg.go | 22 ++++++++++++++++++++++ handlers/send_msg.go | 23 +++++++++++++++++++++++ handlers/send_private_msg.go | 5 +++++ 4 files changed, 86 insertions(+) diff --git a/echo/echo.go b/echo/echo.go index e0711514..5c936b32 100644 --- a/echo/echo.go +++ b/echo/echo.go @@ -29,6 +29,17 @@ type StringToInt64MappingSeq struct { mapping map[string]int64 } +// Int64Stack 用于存储 int64 的栈 +type Int64Stack struct { + mu sync.Mutex + stack []int64 +} + +// 定义一个全局的 Int64Stack 实例 +var globalInt64Stack = &Int64Stack{ + stack: make([]int64, 0), +} + var globalEchoMapping = &EchoMapping{ msgTypeMapping: make(map[string]string), msgIDMapping: make(map[string]string), @@ -120,3 +131,28 @@ func GetMappingFileTimeLimit(key string) int64 { defer globalStringToInt64MappingSeq.mu.Unlock() return globalStringToInt64MappingSeq.mapping[key] } + +// Add 添加一个新的 int64 到全局栈中 +func AddFileTimeLimit(value int64) { + globalInt64Stack.mu.Lock() + defer globalInt64Stack.mu.Unlock() + + // 添加新元素到栈顶 + globalInt64Stack.stack = append(globalInt64Stack.stack, value) + + // 如果栈的大小超过 10,移除最早添加的元素 + if len(globalInt64Stack.stack) > 10 { + globalInt64Stack.stack = globalInt64Stack.stack[1:] + } +} + +// Get 获取全局栈顶的元素 +func GetFileTimeLimit() int64 { + globalInt64Stack.mu.Lock() + defer globalInt64Stack.mu.Unlock() + + if len(globalInt64Stack.stack) == 0 { + return 0 // 当栈为空时返回 0 + } + return globalInt64Stack.stack[len(globalInt64Stack.stack)-1] +} diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index d0e6250c..69704f0e 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -133,6 +133,9 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap echo.AddMappingSeq(messageID, msgseq+1) //时间限制 lastSendTimestamp := echo.GetMappingFileTimeLimit(messageID) + if lastSendTimestamp == 0 { + lastSendTimestamp = echo.GetFileTimeLimit() + } now := time.Now() millis := now.UnixMilli() diff := millis - lastSendTimestamp @@ -153,6 +156,7 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap mylog.Println("延迟完成") _, err := apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), richMediaMessageCopy) echo.AddMappingFileTimeLimit(messageID, millis) + echo.AddFileTimeLimit(millis) if err != nil { mylog.Printf("发送 %s 信息失败_send_group_msg: %v", key, err) if config.GetSendError() { //把报错当作文本发出去 @@ -177,8 +181,26 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap } else { _, err := apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), richMediaMessage) echo.AddMappingFileTimeLimit(messageID, millis) + echo.AddFileTimeLimit(millis) if err != nil { mylog.Printf("发送 %s 信息失败_send_group_msg: %v", key, err) + if config.GetSendError() { //把报错当作文本发出去 + msgseq := echo.GetMappingSeq(messageID) + echo.AddMappingSeq(messageID, msgseq+1) + groupReply := generateGroupMessage(messageID, nil, err.Error(), msgseq+1) + // 进行类型断言 + groupMessage, ok := groupReply.(*dto.MessageToCreate) + if !ok { + mylog.Println("Error: Expected MessageToCreate type.") + return // 或其他错误处理 + } + groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 + //重新为err赋值 + _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) + if err != nil { + mylog.Printf("发送文本报错信息失败: %v", err) + } + } } } //发送成功回执 diff --git a/handlers/send_msg.go b/handlers/send_msg.go index 0736b553..5f4187e1 100644 --- a/handlers/send_msg.go +++ b/handlers/send_msg.go @@ -131,6 +131,9 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope echo.AddMappingSeq(messageID, msgseq+1) //时间限制 lastSendTimestamp := echo.GetMappingFileTimeLimit(messageID) + if lastSendTimestamp == 0 { + lastSendTimestamp = echo.GetFileTimeLimit() + } now := time.Now() millis := now.UnixMilli() diff := millis - lastSendTimestamp @@ -153,6 +156,7 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope mylog.Println("延迟完成") _, err := apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), richMediaMessageCopy) echo.AddMappingFileTimeLimit(messageID, millis) + echo.AddFileTimeLimit(millis) if err != nil { mylog.Printf("发送 %s 信息失败_send_msg: %v", key, err) if config.GetSendError() { //把报错当作文本发出去 @@ -177,9 +181,28 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope } else { _, err := apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), richMediaMessage) echo.AddMappingFileTimeLimit(messageID, millis) + echo.AddFileTimeLimit(millis) if err != nil { mylog.Printf("发送 %s 信息失败_send_group_msg: %v", key, err) + if config.GetSendError() { //把报错当作文本发出去 + msgseq := echo.GetMappingSeq(messageID) + echo.AddMappingSeq(messageID, msgseq+1) + groupReply := generateGroupMessage(messageID, nil, err.Error(), msgseq+1) + // 进行类型断言 + groupMessage, ok := groupReply.(*dto.MessageToCreate) + if !ok { + mylog.Println("Error: Expected MessageToCreate type.") + return // 或其他错误处理 + } + groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 + //重新为err赋值 + _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) + if err != nil { + mylog.Printf("发送文本报错信息失败: %v", err) + } + } } + } //发送成功回执 SendResponse(client, err, &message) diff --git a/handlers/send_private_msg.go b/handlers/send_private_msg.go index 5ffecac4..cd74034a 100644 --- a/handlers/send_private_msg.go +++ b/handlers/send_private_msg.go @@ -138,6 +138,9 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open echo.AddMappingSeq(messageID, msgseq+1) //时间限制 lastSendTimestamp := echo.GetMappingFileTimeLimit(messageID) + if lastSendTimestamp == 0 { + lastSendTimestamp = echo.GetFileTimeLimit() + } now := time.Now() millis := now.UnixMilli() diff := millis - lastSendTimestamp @@ -158,6 +161,7 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open mylog.Println("延迟完成") _, err := apiv2.PostC2CMessage(context.TODO(), UserID, richMediaMessageCopy) echo.AddMappingFileTimeLimit(messageID, millis) + echo.AddFileTimeLimit(millis) if err != nil { mylog.Printf("发送 %s 私聊信息失败: %v", key, err) } @@ -165,6 +169,7 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open } else { // 发送消息 _, err := apiv2.PostC2CMessage(context.TODO(), UserID, richMediaMessage) echo.AddMappingFileTimeLimit(messageID, millis) + echo.AddFileTimeLimit(millis) if err != nil { mylog.Printf("发送 %s 私聊信息失败: %v", key, err) } From 9a32e08355aa9fdcf3d0affbda14bdb4e40f0a47 Mon Sep 17 00:00:00 2001 From: cosmo Date: Tue, 21 Nov 2023 22:09:40 +0800 Subject: [PATCH 2/8] add a lot --- Processor/ProcessGroupMessage.go | 4 ++ config/config.go | 38 ++++++++++++ handlers/send_group_msg.go | 99 +++++++++++++++++++++++++++++++- handlers/send_msg.go | 36 +++++++++++- template/config_template.go | 3 + template/config_template.yml | 5 +- 6 files changed, 180 insertions(+), 5 deletions(-) diff --git a/Processor/ProcessGroupMessage.go b/Processor/ProcessGroupMessage.go index 6e4ffc81..b3d8deaf 100644 --- a/Processor/ProcessGroupMessage.go +++ b/Processor/ProcessGroupMessage.go @@ -27,6 +27,10 @@ func (p *Processors) ProcessGroupMessage(data *dto.WSGroupATMessageData) error { mylog.Printf("信息被自定义黑白名单拦截") return nil } + //群没有at,但用户可以选择加一个 + if config.GetAddAtGroup() { + messageText = "[CQ:at,qq=" + config.GetAppIDStr() + "] " + messageText + } //框架内指令 p.HandleFrameworkCommand(messageText, data, "group") // 转换appid diff --git a/config/config.go b/config/config.go index 840064ee..d655c568 100644 --- a/config/config.go +++ b/config/config.go @@ -78,6 +78,9 @@ type Settings struct { RecordBitRate int `yaml:"record_bitRate"` NoWhiteResponse string `yaml:"No_White_Response"` SendError bool `yaml:"send_error"` + AddAtGroup bool `yaml:"add_at_group"` + SendErrorPicAsUrl bool `yaml:"send_error_pic_as_url"` + UrlPicTransfer bool `yaml:"url_pic_transfer"` } // LoadConfig 从文件中加载配置并初始化单例配置 @@ -925,3 +928,38 @@ func GetSendError() bool { return instance.Settings.SendError } +// 获取GetAddAtGroup的值 +func GetAddAtGroup() bool { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to GetAddGroupAt value.") + return true + } + return instance.Settings.AddAtGroup +} + +// 获取GetSendErrorPicAsUrl的值 +func GetSendErrorPicAsUrl() bool { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to GetErrorPicAsUrl value.") + return true + } + return instance.Settings.SendErrorPicAsUrl +} + +// 获取GetUrlPicTransfer的值 +func GetUrlPicTransfer() bool { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to GetUrlPicTransfer value.") + return true + } + return instance.Settings.UrlPicTransfer +} diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index 69704f0e..d367110f 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -4,6 +4,8 @@ import ( "bytes" "context" "encoding/base64" + "io" + "net/http" "os" "strconv" "time" @@ -15,6 +17,7 @@ import ( "github.com/hoshinonyaruko/gensokyo/images" "github.com/hoshinonyaruko/gensokyo/mylog" "github.com/hoshinonyaruko/gensokyo/silk" + "github.com/hoshinonyaruko/gensokyo/url" "github.com/tencent-connect/botgo/dto" "github.com/tencent-connect/botgo/openapi" ) @@ -176,6 +179,23 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap mylog.Printf("发送文本报错信息失败: %v", err) } } + if config.GetSendErrorPicAsUrl() { + msgseq := echo.GetMappingSeq(messageID) + echo.AddMappingSeq(messageID, msgseq+1) + groupReply := generateGroupMessage(messageID, nil, richMediaMessageCopy.URL, msgseq+1) + // 进行类型断言 + groupMessage, ok := groupReply.(*dto.MessageToCreate) + if !ok { + mylog.Println("Error: Expected MessageToCreate type.") + return // 或其他错误处理 + } + groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 + //重新为err赋值 + _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) + if err != nil { + mylog.Printf("发送图片报错后转url发送失败: %v", err) + } + } } }) } else { @@ -201,6 +221,23 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap mylog.Printf("发送文本报错信息失败: %v", err) } } + if config.GetSendErrorPicAsUrl() { + msgseq := echo.GetMappingSeq(messageID) + echo.AddMappingSeq(messageID, msgseq+1) + groupReply := generateGroupMessage(messageID, nil, richMediaMessageCopy.URL, msgseq+1) + // 进行类型断言 + groupMessage, ok := groupReply.(*dto.MessageToCreate) + if !ok { + mylog.Println("Error: Expected MessageToCreate type.") + return // 或其他错误处理 + } + groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 + //重新为err赋值 + _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) + if err != nil { + mylog.Printf("发送图片报错后转url发送失败: %v", err) + } + } } } //发送成功回执 @@ -351,12 +388,68 @@ func generateGroupMessage(id string, foundItems map[string][]string, messageText SrvSendMsg: true, } } else if imageURLs, ok := foundItems["url_image"]; ok && len(imageURLs) > 0 { + var newpiclink string + if config.GetUrlPicTransfer() { + // 从URL下载图片 + resp, err := http.Get("http://" + imageURLs[0]) + if err != nil { + mylog.Printf("Error downloading the image: %v", err) + return &dto.MessageToCreate{ + Content: "错误: 下载图片失败", + MsgID: id, + MsgSeq: msgseq, + MsgType: 0, // 默认文本类型 + } + } + defer resp.Body.Close() + + // 读取图片数据 + imageData, err := io.ReadAll(resp.Body) + if err != nil { + mylog.Printf("Error reading the image data: %v", err) + return &dto.MessageToCreate{ + Content: "错误: 读取图片数据失败", + MsgID: id, + MsgSeq: msgseq, + MsgType: 0, + } + } + + // 转换为base64 + base64Encoded := base64.StdEncoding.EncodeToString(imageData) + + // 上传图片并获取新的URL + newURL, err := images.UploadBase64ImageToServer(base64Encoded) + if err != nil { + mylog.Printf("Error uploading base64 encoded image: %v", err) + return &dto.MessageToCreate{ + Content: "错误: 上传图片失败", + MsgID: id, + MsgSeq: msgseq, + MsgType: 0, + } + } + // 将图片链接缩短 避免 url not allow + if config.GetLotusValue() { + // 连接到另一个gensokyo + newURL = url.GenerateShortURL(newURL) + } else { + // 自己是主节点 + newURL = url.GenerateShortURL(newURL) + // 使用getBaseURL函数来获取baseUrl并与newURL组合 + newURL = url.GetBaseURL() + "/url/" + newURL + } + newpiclink = newURL + } else { + newpiclink = "http://" + imageURLs[0] + } + // 发链接图片 return &dto.RichMediaMessage{ EventID: id, - FileType: 1, // 1代表图片 - URL: "http://" + imageURLs[0], //url在base64时候被截断了,在这里补全 - Content: "", // 这个字段文档没有了 + FileType: 1, // 1代表图片 + URL: newpiclink, // 新图片链接 + Content: "", // 这个字段文档没有了 SrvSendMsg: true, } } else if voiceURLs, ok := foundItems["base64_record"]; ok && len(voiceURLs) > 0 { diff --git a/handlers/send_msg.go b/handlers/send_msg.go index 5f4187e1..78931368 100644 --- a/handlers/send_msg.go +++ b/handlers/send_msg.go @@ -176,6 +176,23 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope mylog.Printf("发送文本报错信息失败: %v", err) } } + if config.GetSendErrorPicAsUrl() { + msgseq := echo.GetMappingSeq(messageID) + echo.AddMappingSeq(messageID, msgseq+1) + groupReply := generateGroupMessage(messageID, nil, richMediaMessageCopy.URL, msgseq+1) + // 进行类型断言 + groupMessage, ok := groupReply.(*dto.MessageToCreate) + if !ok { + mylog.Println("Error: Expected MessageToCreate type.") + return // 或其他错误处理 + } + groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 + //重新为err赋值 + _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) + if err != nil { + mylog.Printf("发送图片报错后转url发送失败: %v", err) + } + } } }) } else { @@ -183,7 +200,7 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope echo.AddMappingFileTimeLimit(messageID, millis) echo.AddFileTimeLimit(millis) if err != nil { - mylog.Printf("发送 %s 信息失败_send_group_msg: %v", key, err) + mylog.Printf("发送 %s 信息失败_send_msg: %v", key, err) if config.GetSendError() { //把报错当作文本发出去 msgseq := echo.GetMappingSeq(messageID) echo.AddMappingSeq(messageID, msgseq+1) @@ -201,6 +218,23 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope mylog.Printf("发送文本报错信息失败: %v", err) } } + if config.GetSendErrorPicAsUrl() { + msgseq := echo.GetMappingSeq(messageID) + echo.AddMappingSeq(messageID, msgseq+1) + groupReply := generateGroupMessage(messageID, nil, richMediaMessageCopy.URL, msgseq+1) + // 进行类型断言 + groupMessage, ok := groupReply.(*dto.MessageToCreate) + if !ok { + mylog.Println("Error: Expected MessageToCreate type.") + return // 或其他错误处理 + } + groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 + //重新为err赋值 + _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) + if err != nil { + mylog.Printf("发送图片报错后转url发送失败: %v", err) + } + } } } diff --git a/template/config_template.go b/template/config_template.go index a9ebfe6b..1f518785 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -73,6 +73,7 @@ settings: remove_prefix : false #是否忽略公域机器人指令前第一个/ remove_at : false #是否忽略公域机器人指令前第一个[CQ:aq,qq=机器人] 场景(公域机器人,但插件未适配at开头) remove_bot_at_group : true #因为群聊机器人不支持发at,开启本开关会自动隐藏群机器人发出的at(不影响频道场景) + add_at_group : false #自动在群聊指令前加上at,某些机器人写法特别,必须有at才反应时,请打开,默认请关闭(如果需要at,不需要at指令混杂,请优化代码适配群场景,群场景目前没有at概念) white_prefix_mode : false #公域 过审用 指令白名单模式开关 如果审核严格 请开启并设置白名单指令 以白名单开头的指令会被通过,反之被拦截 white_prefixs : [""] #可设置多个 比如设置 机器人 测试 则只有信息以机器人 测试开头会相应 remove_prefix remove_at 需为true时生效 @@ -90,6 +91,8 @@ settings: sandbox_mode : false #默认false 如果你只希望沙箱频道使用,请改为true dev_message_id : false #在沙盒和测试环境使用无限制msg_id 仅沙盒有效,正式环境请关闭,内测结束后,tx侧未来会移除 send_error : true #将报错用文本发出,避免机器人被审核报无响应 + send_error_pic_as_url : false #临时解决22009报错 + url_pic_transfer : false #可与url_pic_transfer配合使用 也可单独使用 把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(是目前gsk门槛最高的配置) title : "Gensokyo © 2023 - Hoshinonyaruko" #程序的标题 如果多个机器人 可根据标题区分 diff --git a/template/config_template.yml b/template/config_template.yml index 9018489f..0c9e0b96 100644 --- a/template/config_template.yml +++ b/template/config_template.yml @@ -69,4 +69,7 @@ settings: record_sampleRate : 24000 #语音文件的采样率 最高48000 默认24000 单位Khz record_bitRate : 24000 #语音文件的比特率 默认24000 代表 24 kbps 最高无限 请根据带宽 您发送的实际码率调整 No_White_Response : "" #默认不兜底,强烈建议设置一个友善的兜底回复,告知审核机器人已无隐藏指令,如:你输入的指令不对哦,@机器人来获取可用指令 - send_error : true #将报错用文本发出,避免机器人被审核报无响应 \ No newline at end of file + send_error : true #将报错用文本发出,避免机器人被审核报无响应 + add_at_group : false #自动在群聊指令前加上at,某些机器人写法特别,必须有at才反应时,请打开,默认请关闭(如果需要at,不需要at指令混杂,请优化代码适配群场景,群场景目前没有at概念 + send_error_pic_as_url : false #临时解决22009报错 + url_pic_transfer : false #可与url_pic_transfer配合使用 也可单独使用 把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(是目前gsk门槛最高的配置) \ No newline at end of file From 97e1ecb787458d851c02761acaefc6734160352a Mon Sep 17 00:00:00 2001 From: cosmo Date: Wed, 22 Nov 2023 00:45:25 +0800 Subject: [PATCH 3/8] add a lot --- sys/restart_unix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/restart_unix.go b/sys/restart_unix.go index b198f48e..00ebf1aa 100644 --- a/sys/restart_unix.go +++ b/sys/restart_unix.go @@ -21,7 +21,7 @@ func NewRestarter() *UnixRestarter { func (r *UnixRestarter) Restart(executableName string) error { scriptContent := "#!/bin/sh\n" + "sleep 1\n" + // Sleep for a bit to allow the main application to exit - "exec " + executableName + "\n" + "." + executableName + "\n" scriptName := "restart.sh" if err := os.WriteFile(scriptName, []byte(scriptContent), 0755); err != nil { From c80929fdea4fb18ac74a5220586a096564175396 Mon Sep 17 00:00:00 2001 From: cosmo Date: Wed, 22 Nov 2023 01:22:43 +0800 Subject: [PATCH 4/8] add webui sysinfo --- go.mod | 19 ++++++++-------- go.sum | 29 +++++++++++-------------- webui/api.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 209b573b..228c9d2f 100644 --- a/go.mod +++ b/go.mod @@ -6,23 +6,24 @@ require ( github.com/boltdb/bolt v1.3.1 github.com/fatih/color v1.15.0 github.com/gin-gonic/gin v1.9.1 + github.com/google/uuid v1.4.0 github.com/gorilla/websocket v1.4.2 + github.com/shirou/gopsutil v3.21.11+incompatible github.com/tencent-connect/botgo v0.1.6 gopkg.in/yaml.v3 v3.0.1 ) require ( - github.com/google/uuid v1.4.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mvdan/xurls v1.1.0 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect - github.com/wdvxdr1123/go-silk v0.0.0-20220304095002-f67345df09ea // indirect - modernc.org/libc v1.8.1 // indirect - modernc.org/mathutil v1.2.2 // indirect - modernc.org/memory v1.0.4 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect ) replace github.com/tencent-connect/botgo => ./botgo + replace github.com/wdvxdr1123/go-silk => ./go-silk require ( @@ -44,15 +45,15 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect - github.com/tidwall/gjson v1.9.3 // indirect + github.com/tidwall/gjson v1.9.3 github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect golang.org/x/arch v0.3.0 // indirect golang.org/x/crypto v0.9.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/net v0.10.0 + golang.org/x/sys v0.13.0 golang.org/x/text v0.9.0 // indirect google.golang.org/protobuf v1.30.0 // indirect mvdan.cc/xurls v1.1.0 diff --git a/go.sum b/go.sum index b485bef4..52ae7f96 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -74,7 +76,6 @@ github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -85,8 +86,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mvdan/xurls v1.1.0 h1:OpuDelGQ1R1ueQ6sSryzi6P+1RtBpfQHM8fJwlE45ww= github.com/mvdan/xurls v1.1.0/go.mod h1:tQlNn3BED8bE/15hnSL2HLkDeLWpNPAwtw7wkEq44oU= -github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= -github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -102,8 +101,8 @@ github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZ github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -122,13 +121,17 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/wdvxdr1123/go-silk v0.0.0-20220304095002-f67345df09ea h1:sl1pYm1kHtIndckTY8YDt+QFt77vI0JnKHP0U8rZtKc= -github.com/wdvxdr1123/go-silk v0.0.0-20220304095002-f67345df09ea/go.mod h1:ecFKZPX81BaB70I6ruUgEwYcDOtuNgJGnjdK+MIl5ko= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -154,14 +157,13 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -169,6 +171,8 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -206,13 +210,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -modernc.org/libc v1.8.1 h1:y9oPIhwcaFXxX7kMp6Qb2ZLKzr0mDkikWN3CV5GS63o= -modernc.org/libc v1.8.1/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= -modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM= -modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= mvdan.cc/xurls v1.1.0 h1:kj0j2lonKseISJCiq1Tfk+iTv65dDGCl0rTbanXJGGc= mvdan.cc/xurls v1.1.0/go.mod h1:TNWuhvo+IqbUCmtUIb/3LJSQdrzel8loVpgFm0HikbI= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/webui/api.go b/webui/api.go index 7cdca9c0..70ddb8ca 100644 --- a/webui/api.go +++ b/webui/api.go @@ -14,6 +14,11 @@ import ( "github.com/gin-gonic/gin" "github.com/hoshinonyaruko/gensokyo/config" "github.com/hoshinonyaruko/gensokyo/mylog" + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/disk" + "github.com/shirou/gopsutil/host" + "github.com/shirou/gopsutil/mem" + "github.com/shirou/gopsutil/process" "github.com/tencent-connect/botgo/dto" "github.com/tencent-connect/botgo/openapi" ) @@ -65,6 +70,17 @@ func CombinedMiddleware(api openapi.OpenAPI, apiV2 openapi.OpenAPI) gin.HandlerF handleDeleteConfig(c) return } + //结束当前实例的进程 + if c.Param("filepath") == "/api/"+appIDStr+"/process" && c.Request.Method == http.MethodDelete { + // 正常退出 + os.Exit(0) + return + } + //进程监控 + if c.Param("filepath") == "/api/status" && c.Request.Method == http.MethodGet { + handleSysInfo(c) + return + } //更新当前选中机器人的配置并重启应用(保持地址不变) if c.Param("filepath") == "/api/"+appIDStr+"/config" && c.Request.Method == http.MethodPatch { handlePatchConfig(c) @@ -480,3 +496,48 @@ func HandleCheckLoginStatusRequest(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"isLoggedIn": false, "error": "Invalid cookie"}) } } + +func handleSysInfo(c *gin.Context) { + // 获取CPU使用率 + cpuPercent, _ := cpu.Percent(time.Second, false) + + // 获取内存信息 + vmStat, _ := mem.VirtualMemory() + + // 获取磁盘使用情况 + diskStat, _ := disk.Usage("/") + + // 获取系统启动时间 + bootTime, _ := host.BootTime() + + // 获取当前进程信息 + proc, _ := process.NewProcess(int32(os.Getpid())) + procPercent, _ := proc.CPUPercent() + memInfo, _ := proc.MemoryInfo() + procStartTime, _ := proc.CreateTime() + + // 构造返回的JSON数据 + sysInfo := gin.H{ + "cpu_percent": cpuPercent[0], // CPU使用率 + "memory": gin.H{ + "total": vmStat.Total, // 总内存 + "available": vmStat.Available, // 可用内存 + "percent": vmStat.UsedPercent, // 内存使用率 + }, + "disk": gin.H{ + "total": diskStat.Total, // 磁盘总容量 + "free": diskStat.Free, // 磁盘剩余空间 + "percent": diskStat.UsedPercent, // 磁盘使用率 + }, + "boot_time": bootTime, // 系统启动时间 + "process": gin.H{ + "pid": proc.Pid, // 当前进程ID + "status": "running", // 进程状态,这里假设为运行中 + "memory_used": memInfo.RSS, // 进程使用的内存 + "cpu_percent": procPercent, // 进程CPU使用率 + "start_time": procStartTime, // 进程启动时间 + }, + } + // 返回JSON数据 + c.JSON(http.StatusOK, sysInfo) +} From 15c20ce8fd991041dc88b48231ada1788a474a72 Mon Sep 17 00:00:00 2001 From: cosmo Date: Wed, 22 Nov 2023 01:35:07 +0800 Subject: [PATCH 5/8] add webui sysinfo --- webui/api.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/webui/api.go b/webui/api.go index 70ddb8ca..e657ef93 100644 --- a/webui/api.go +++ b/webui/api.go @@ -36,6 +36,7 @@ func CombinedMiddleware(api openapi.OpenAPI, apiV2 openapi.OpenAPI) gin.HandlerF if strings.HasPrefix(c.Request.URL.Path, "/webui/api") { // 处理API请求 appIDStr := config.GetAppIDStr() + //todo 完善logs的 get方法 来获取历史日志 // 检查路径是否匹配 `/api/{uin}/process/logs` if strings.HasPrefix(c.Param("filepath"), "/api/") && strings.HasSuffix(c.Param("filepath"), "/process/logs") { if c.GetHeader("Upgrade") == "websocket" { @@ -45,6 +46,15 @@ func CombinedMiddleware(api openapi.OpenAPI, apiV2 openapi.OpenAPI) gin.HandlerF } return } + //主页日志 + if c.Param("filepath") == "/api/logs" { + if c.GetHeader("Upgrade") == "websocket" { + mylog.WsHandlerWithDependencies(c) + } else { + getProcessLogs(c) + } + return + } // 如果请求路径与appIDStr匹配,并且请求方法为PUT if c.Param("filepath") == appIDStr && c.Request.Method == http.MethodPut { HandleAppIDRequest(c) @@ -342,6 +352,7 @@ func HandleProcessStatusRequest(c *gin.Context) { c.JSON(http.StatusOK, responseData) } +// 待完善 从mylog通道取出日志信息,然后一股脑返回 func getProcessLogs(c *gin.Context) { c.JSON(200, []interface{}{}) } From 7706072037997e48e2c19c6a88b22b912aa1a4f5 Mon Sep 17 00:00:00 2001 From: cosmo Date: Wed, 22 Nov 2023 19:41:57 +0800 Subject: [PATCH 6/8] beta51 --- botgo/dto/message.go | 14 +++ botgo/dto/message_create.go | 6 + botgo/openapi/iface.go | 2 +- botgo/openapi/v1/message.go | 12 +- botgo/openapi/v2/message.go | 38 ++++-- config/config.go | 13 --- handlers/send_group_msg.go | 217 +++++++++++++++++++---------------- handlers/send_msg.go | 177 +--------------------------- template/config_template.go | 3 +- template/config_template.yml | 3 +- 10 files changed, 183 insertions(+), 302 deletions(-) diff --git a/botgo/dto/message.go b/botgo/dto/message.go index 23744523..14318ec3 100644 --- a/botgo/dto/message.go +++ b/botgo/dto/message.go @@ -41,6 +41,20 @@ type Message struct { SrcGuildID string `json:"src_guild_id"` } +type MediaResponse struct { + //UUID + FileUUID string `json:"file_uuid"` + //file_info + FileInfo string `json:"file_info"` + TTL int `json:"ttl"` +} + +//新增 +type GroupMessageResponse struct { + MediaResponse *MediaResponse + Message *Message +} + // Embed 结构 type Embed struct { Title string `json:"title,omitempty"` diff --git a/botgo/dto/message_create.go b/botgo/dto/message_create.go index b473d2f2..d0b96623 100644 --- a/botgo/dto/message_create.go +++ b/botgo/dto/message_create.go @@ -25,6 +25,11 @@ type RichMediaMessage struct { Content string `json:"content,omitempty"` } +// Meida message内的富媒体消息 +type Media struct { + FileInfo string `json:"file_info"` +} + // GetEventID 事件ID func (msg RichMediaMessage) GetEventID() string { return msg.EventID @@ -42,6 +47,7 @@ type MessageToCreate struct { Embed *Embed `json:"embed,omitempty"` Ark *Ark `json:"ark,omitempty"` Image string `json:"image,omitempty"` + Media Media `json:"media,omitempty"` // 要回复的消息id,为空是主动消息,公域机器人会异步审核,不为空是被动消息,公域机器人会校验语料 MsgID string `json:"msg_id,omitempty"` MessageReference *MessageReference `json:"message_reference,omitempty"` diff --git a/botgo/openapi/iface.go b/botgo/openapi/iface.go index 34dca682..f2ae3207 100644 --- a/botgo/openapi/iface.go +++ b/botgo/openapi/iface.go @@ -76,7 +76,7 @@ type MessageAPI interface { PostSettingGuide(ctx context.Context, channelID string, atUserIDs []string) (*dto.Message, error) // PostGroupMessage 发送群消息 - PostGroupMessage(ctx context.Context, groupID string, msg dto.APIMessage) (*dto.Message, error) + PostGroupMessage(ctx context.Context, groupID string, msg dto.APIMessage) (*dto.GroupMessageResponse, error) // PostC2CMessage 发送C2C消息 PostC2CMessage(ctx context.Context, userID string, msg dto.APIMessage) (*dto.Message, error) } diff --git a/botgo/openapi/v1/message.go b/botgo/openapi/v1/message.go index 716bc62e..436e939a 100644 --- a/botgo/openapi/v1/message.go +++ b/botgo/openapi/v1/message.go @@ -191,7 +191,7 @@ func getGroupURLBySendType(msgType dto.SendType) uri { } // PostGroupMessage 回复群消息 -func (o *openAPI) PostGroupMessage(ctx context.Context, groupID string, msg dto.APIMessage) (*dto.Message, error) { +func (o *openAPI) PostGroupMessage(ctx context.Context, groupID string, msg dto.APIMessage) (*dto.GroupMessageResponse, error) { resp, err := o.request(ctx). SetResult(dto.Message{}). SetPathParam("group_id", groupID). @@ -200,7 +200,15 @@ func (o *openAPI) PostGroupMessage(ctx context.Context, groupID string, msg dto. if err != nil { return nil, err } - return resp.Result().(*dto.Message), nil + msgType := msg.GetSendType() + result := &dto.GroupMessageResponse{} + switch msgType { + case dto.RichMedia: + result.MediaResponse = resp.Result().(*dto.MediaResponse) + default: + result.Message = resp.Result().(*dto.Message) + } + return result, nil } func getC2CURLBySendType(msgType dto.SendType) uri { diff --git a/botgo/openapi/v2/message.go b/botgo/openapi/v2/message.go index ed6a1af9..10f9bf2e 100644 --- a/botgo/openapi/v2/message.go +++ b/botgo/openapi/v2/message.go @@ -7,6 +7,7 @@ import ( "fmt" "strconv" + "github.com/go-resty/resty/v2" "github.com/tidwall/gjson" "github.com/tencent-connect/botgo/dto" @@ -191,16 +192,39 @@ func getGroupURLBySendType(msgType dto.SendType) uri { } // PostGroupMessage 回复群消息 -func (o *openAPIv2) PostGroupMessage(ctx context.Context, groupID string, msg dto.APIMessage) (*dto.Message, error) { - resp, err := o.request(ctx). - SetResult(dto.Message{}). - SetPathParam("group_id", groupID). - SetBody(msg). - Post(o.getURL(getGroupURLBySendType(msg.GetSendType()))) +func (o *openAPIv2) PostGroupMessage(ctx context.Context, groupID string, msg dto.APIMessage) (*dto.GroupMessageResponse, error) { + var resp *resty.Response + var err error + + msgType := msg.GetSendType() + switch msgType { + case dto.RichMedia: + resp, err = o.request(ctx). + SetResult(dto.MediaResponse{}). // 设置为媒体响应类型 + SetPathParam("group_id", groupID). + SetBody(msg). + Post(o.getURL(getGroupURLBySendType(msgType))) + default: + resp, err = o.request(ctx). + SetResult(dto.Message{}). // 设置为消息类型 + SetPathParam("group_id", groupID). + SetBody(msg). + Post(o.getURL(getGroupURLBySendType(msgType))) + } + if err != nil { return nil, err } - return resp.Result().(*dto.Message), nil + + result := &dto.GroupMessageResponse{} + switch msgType { + case dto.RichMedia: + result.MediaResponse = resp.Result().(*dto.MediaResponse) + default: + result.Message = resp.Result().(*dto.Message) + } + + return result, nil } func getC2CURLBySendType(msgType dto.SendType) uri { diff --git a/config/config.go b/config/config.go index d655c568..3d230dd4 100644 --- a/config/config.go +++ b/config/config.go @@ -79,7 +79,6 @@ type Settings struct { NoWhiteResponse string `yaml:"No_White_Response"` SendError bool `yaml:"send_error"` AddAtGroup bool `yaml:"add_at_group"` - SendErrorPicAsUrl bool `yaml:"send_error_pic_as_url"` UrlPicTransfer bool `yaml:"url_pic_transfer"` } @@ -940,18 +939,6 @@ func GetAddAtGroup() bool { return instance.Settings.AddAtGroup } -// 获取GetSendErrorPicAsUrl的值 -func GetSendErrorPicAsUrl() bool { - mu.Lock() - defer mu.Unlock() - - if instance == nil { - mylog.Println("Warning: instance is nil when trying to GetErrorPicAsUrl value.") - return true - } - return instance.Settings.SendErrorPicAsUrl -} - // 获取GetUrlPicTransfer的值 func GetUrlPicTransfer() bool { mu.Lock() diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index d367110f..5e30df0e 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -103,6 +103,70 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap if config.GetDevMsgID() { messageID = "1000" } + var singleItem = make(map[string][]string) + var imageType, imageUrl string + imageCount := 0 + + // 检查不同类型的图片并计算数量 + if imageURLs, ok := foundItems["local_image"]; ok && len(imageURLs) == 1 { + imageType = "local_image" + imageUrl = imageURLs[0] + imageCount++ + } else if imageURLs, ok := foundItems["url_image"]; ok && len(imageURLs) == 1 { + imageType = "url_image" + imageUrl = imageURLs[0] + imageCount++ + } else if base64Images, ok := foundItems["base64_image"]; ok && len(base64Images) == 1 { + imageType = "base64_image" + imageUrl = base64Images[0] + imageCount++ + } + + if imageCount == 1 && messageText != "" { + mylog.Printf("发图文混合信息") + // 创建包含单个图片的 singleItem + singleItem[imageType] = []string{imageUrl} + msgseq := echo.GetMappingSeq(messageID) + echo.AddMappingSeq(messageID, msgseq+1) + groupReply := generateGroupMessage(messageID, singleItem, "", msgseq+1) + // 进行类型断言 + richMediaMessage, ok := groupReply.(*dto.RichMediaMessage) + if !ok { + mylog.Printf("Error: Expected RichMediaMessage type for key ") + } + // 上传图片并获取FileInfo + fileInfo, err := uploadMedia(context.TODO(), message.Params.GroupID.(string), richMediaMessage, apiv2) + if err != nil { + mylog.Printf("上传图片失败: %v", err) + return // 或其他错误处理 + } + // 创建包含文本和图像信息的消息 + msgseq = echo.GetMappingSeq(messageID) + echo.AddMappingSeq(messageID, msgseq+1) + groupMessage := &dto.MessageToCreate{ + Content: messageText, // 添加文本内容 + Media: dto.Media{ + FileInfo: fileInfo, // 添加图像信息 + }, + MsgID: messageID, + MsgSeq: msgseq, + MsgType: 7, // 假设7是组合消息类型 + } + groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 + + // 发送组合消息 + _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) + if err != nil { + mylog.Printf("发送组合消息失败: %v", err) + return // 或其他错误处理 + } + + // 发送成功回执 + SendResponse(client, err, &message) + + delete(foundItems, imageType) // 从foundItems中删除已处理的图片项 + } + // 优先发送文本信息 if messageText != "" { msgseq := echo.GetMappingSeq(messageID) @@ -134,14 +198,6 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap //mylog.Println("singleItem:", singleItem) msgseq := echo.GetMappingSeq(messageID) echo.AddMappingSeq(messageID, msgseq+1) - //时间限制 - lastSendTimestamp := echo.GetMappingFileTimeLimit(messageID) - if lastSendTimestamp == 0 { - lastSendTimestamp = echo.GetFileTimeLimit() - } - now := time.Now() - millis := now.UnixMilli() - diff := millis - lastSendTimestamp groupReply := generateGroupMessage(messageID, singleItem, "", msgseq+1) // 进行类型断言 richMediaMessage, ok := groupReply.(*dto.RichMediaMessage) @@ -149,95 +205,45 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap mylog.Printf("Error: Expected RichMediaMessage type for key %s.", key) continue // 跳过这个项,继续下一个 } - mylog.Printf("richMediaMessage: %+v\n", richMediaMessage) - richMediaMessageCopy := *richMediaMessage // 创建 richMediaMessage 的副本 - mylog.Printf("上次发图(ms): %+v\n", diff) - if diff < 1000 { - waitDuration := time.Duration(1200-diff) * time.Millisecond - mylog.Printf("等待 %v...\n", waitDuration) - time.AfterFunc(waitDuration, func() { - mylog.Println("延迟完成") - _, err := apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), richMediaMessageCopy) - echo.AddMappingFileTimeLimit(messageID, millis) - echo.AddFileTimeLimit(millis) + message_return, err := apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), richMediaMessage) + if err != nil { + mylog.Printf("发送 %s 信息失败_send_group_msg: %v", key, err) + if config.GetSendError() { //把报错当作文本发出去 + msgseq := echo.GetMappingSeq(messageID) + echo.AddMappingSeq(messageID, msgseq+1) + groupReply := generateGroupMessage(messageID, nil, err.Error(), msgseq+1) + // 进行类型断言 + groupMessage, ok := groupReply.(*dto.MessageToCreate) + if !ok { + mylog.Println("Error: Expected MessageToCreate type.") + return // 或其他错误处理 + } + groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 + //重新为err赋值 + _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) if err != nil { - mylog.Printf("发送 %s 信息失败_send_group_msg: %v", key, err) - if config.GetSendError() { //把报错当作文本发出去 - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - groupReply := generateGroupMessage(messageID, nil, err.Error(), msgseq+1) - // 进行类型断言 - groupMessage, ok := groupReply.(*dto.MessageToCreate) - if !ok { - mylog.Println("Error: Expected MessageToCreate type.") - return // 或其他错误处理 - } - groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 - //重新为err赋值 - _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) - if err != nil { - mylog.Printf("发送文本报错信息失败: %v", err) - } - } - if config.GetSendErrorPicAsUrl() { - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - groupReply := generateGroupMessage(messageID, nil, richMediaMessageCopy.URL, msgseq+1) - // 进行类型断言 - groupMessage, ok := groupReply.(*dto.MessageToCreate) - if !ok { - mylog.Println("Error: Expected MessageToCreate type.") - return // 或其他错误处理 - } - groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 - //重新为err赋值 - _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) - if err != nil { - mylog.Printf("发送图片报错后转url发送失败: %v", err) - } - } + mylog.Printf("发送文本报错信息失败: %v", err) } - }) - } else { - _, err := apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), richMediaMessage) - echo.AddMappingFileTimeLimit(messageID, millis) - echo.AddFileTimeLimit(millis) + } + } + if message_return.MediaResponse.FileInfo != "" { + msgseq := echo.GetMappingSeq(messageID) + echo.AddMappingSeq(messageID, msgseq+1) + media := dto.Media{ + FileInfo: message_return.MediaResponse.FileInfo, + } + groupMessage := &dto.MessageToCreate{ + Content: " ", + MsgID: messageID, + MsgSeq: msgseq, + MsgType: 7, // 默认文本类型 + Media: media, + } + groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 + //重新为err赋值 + _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) if err != nil { - mylog.Printf("发送 %s 信息失败_send_group_msg: %v", key, err) - if config.GetSendError() { //把报错当作文本发出去 - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - groupReply := generateGroupMessage(messageID, nil, err.Error(), msgseq+1) - // 进行类型断言 - groupMessage, ok := groupReply.(*dto.MessageToCreate) - if !ok { - mylog.Println("Error: Expected MessageToCreate type.") - return // 或其他错误处理 - } - groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 - //重新为err赋值 - _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) - if err != nil { - mylog.Printf("发送文本报错信息失败: %v", err) - } - } - if config.GetSendErrorPicAsUrl() { - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - groupReply := generateGroupMessage(messageID, nil, richMediaMessageCopy.URL, msgseq+1) - // 进行类型断言 - groupMessage, ok := groupReply.(*dto.MessageToCreate) - if !ok { - mylog.Println("Error: Expected MessageToCreate type.") - return // 或其他错误处理 - } - groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 - //重新为err赋值 - _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) - if err != nil { - mylog.Printf("发送图片报错后转url发送失败: %v", err) - } - } + mylog.Printf("发送图片失败: %v", err) } } //发送成功回执 @@ -294,7 +300,7 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap } } -// 整理和组合富媒体信息 +// 上传富媒体信息 func generateGroupMessage(id string, foundItems map[string][]string, messageText string, msgseq int) interface{} { if imageURLs, ok := foundItems["local_image"]; ok && len(imageURLs) > 0 { // 从本地路径读取图片 @@ -344,7 +350,7 @@ func generateGroupMessage(id string, foundItems map[string][]string, messageText FileType: 1, // 1代表图片 URL: imageURL, Content: "", // 这个字段文档没有了 - SrvSendMsg: true, + SrvSendMsg: false, } } else if RecordURLs, ok := foundItems["local_record"]; ok && len(RecordURLs) > 0 { // 从本地路径读取语音 @@ -385,7 +391,7 @@ func generateGroupMessage(id string, foundItems map[string][]string, messageText FileType: 3, // 3代表语音 URL: imageURL, Content: "", // 这个字段文档没有了 - SrvSendMsg: true, + SrvSendMsg: false, } } else if imageURLs, ok := foundItems["url_image"]; ok && len(imageURLs) > 0 { var newpiclink string @@ -450,7 +456,7 @@ func generateGroupMessage(id string, foundItems map[string][]string, messageText FileType: 1, // 1代表图片 URL: newpiclink, // 新图片链接 Content: "", // 这个字段文档没有了 - SrvSendMsg: true, + SrvSendMsg: false, } } else if voiceURLs, ok := foundItems["base64_record"]; ok && len(voiceURLs) > 0 { // 适配base64 slik @@ -486,7 +492,7 @@ func generateGroupMessage(id string, foundItems map[string][]string, messageText FileType: 3, // 3代表语音 URL: imageURL, Content: "", // 这个字段文档没有了 - SrvSendMsg: true, + SrvSendMsg: false, } } } else if base64_image, ok := foundItems["base64_image"]; ok && len(base64_image) > 0 { @@ -523,7 +529,7 @@ func generateGroupMessage(id string, foundItems map[string][]string, messageText FileType: 1, // 1代表图片 URL: imageURL, Content: "", // 这个字段文档没有了 - SrvSendMsg: true, + SrvSendMsg: false, } } } else { @@ -579,3 +585,14 @@ func GetMessageTypeByGroupid(appID string, GroupID interface{}) string { key := appID + "_" + GroupIDStr return echo.GetMsgTypeByKey(key) } + +// uploadMedia 上传媒体并返回FileInfo +func uploadMedia(ctx context.Context, groupID string, richMediaMessage *dto.RichMediaMessage, apiv2 openapi.OpenAPI) (string, error) { + // 调用API来上传媒体 + messageReturn, err := apiv2.PostGroupMessage(ctx, groupID, richMediaMessage) + if err != nil { + return "", err + } + // 返回上传后的FileInfo + return messageReturn.MediaResponse.FileInfo, nil +} diff --git a/handlers/send_msg.go b/handlers/send_msg.go index 78931368..22e54c68 100644 --- a/handlers/send_msg.go +++ b/handlers/send_msg.go @@ -67,181 +67,8 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope switch msgType { case "group": - // 解析消息内容 - messageText, foundItems := parseMessageContent(message.Params) - // 使用 echo 获取消息ID - var messageID string - if config.GetLazyMessageId() { - //由于实现了Params的自定义unmarshell 所以可以类型安全的断言为string - messageID = echo.GetLazyMessagesId(message.Params.GroupID.(string)) - mylog.Printf("GetLazyMessagesId: %v", messageID) - } - //判断是否使用了懒messageid,如果没有,优先从echo获取messageid - if messageID == "" { - if echoStr, ok := message.Echo.(string); ok { - messageID = echo.GetMsgIDByKey(echoStr) - mylog.Println("echo取群组发信息对应的message_id:", messageID) - } - } - mylog.Println("群组发信息messageText:", messageText) - //通过bolt数据库还原真实的GroupID - originalGroupID, err := idmap.RetrieveRowByIDv2(message.Params.GroupID.(string)) - if err != nil { - mylog.Printf("Error retrieving original GroupID: %v", err) - return - } - message.Params.GroupID = originalGroupID - // 如果messageID为空,通过函数获取 - if messageID == "" { - messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), message.Params.GroupID) - mylog.Println("通过GetMessageIDByUserid函数获取的message_id:", messageID) - } - //开发环境用 - if config.GetDevMsgID() { - messageID = "1000" - } - // 优先发送文本信息 - if messageText != "" { - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - groupReply := generateGroupMessage(messageID, nil, messageText, msgseq+1) - - // 进行类型断言 - groupMessage, ok := groupReply.(*dto.MessageToCreate) - if !ok { - mylog.Println("Error: Expected MessageToCreate type.") - return // 或其他错误处理 - } - - groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 - _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) - if err != nil { - mylog.Printf("发送文本群组信息失败: %v", err) - } - //发送成功回执 - SendResponse(client, err, &message) - } - - // 遍历foundItems并发送每种信息 - for key, urls := range foundItems { - for _, url := range urls { - var singleItem = make(map[string][]string) - singleItem[key] = []string{url} // 创建一个只包含一个 URL 的 singleItem - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - //时间限制 - lastSendTimestamp := echo.GetMappingFileTimeLimit(messageID) - if lastSendTimestamp == 0 { - lastSendTimestamp = echo.GetFileTimeLimit() - } - now := time.Now() - millis := now.UnixMilli() - diff := millis - lastSendTimestamp - groupReply := generateGroupMessage(messageID, singleItem, "", msgseq+1) - - // 进行类型断言 - richMediaMessage, ok := groupReply.(*dto.RichMediaMessage) - if !ok { - mylog.Printf("Error: Expected RichMediaMessage type for key %s.", key) - continue // 跳过这个项,继续下一个 - } - - mylog.Printf("richMediaMessage: %+v\n", richMediaMessage) - richMediaMessageCopy := *richMediaMessage // 创建 richMediaMessage 的副本 - mylog.Printf("上次发图(ms): %+v\n", diff) - if diff < 1000 { - waitDuration := time.Duration(1200-diff) * time.Millisecond - mylog.Printf("等待 %v...\n", waitDuration) - time.AfterFunc(waitDuration, func() { - mylog.Println("延迟完成") - _, err := apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), richMediaMessageCopy) - echo.AddMappingFileTimeLimit(messageID, millis) - echo.AddFileTimeLimit(millis) - if err != nil { - mylog.Printf("发送 %s 信息失败_send_msg: %v", key, err) - if config.GetSendError() { //把报错当作文本发出去 - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - groupReply := generateGroupMessage(messageID, nil, err.Error(), msgseq+1) - // 进行类型断言 - groupMessage, ok := groupReply.(*dto.MessageToCreate) - if !ok { - mylog.Println("Error: Expected MessageToCreate type.") - return // 或其他错误处理 - } - groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 - //重新为err赋值 - _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) - if err != nil { - mylog.Printf("发送文本报错信息失败: %v", err) - } - } - if config.GetSendErrorPicAsUrl() { - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - groupReply := generateGroupMessage(messageID, nil, richMediaMessageCopy.URL, msgseq+1) - // 进行类型断言 - groupMessage, ok := groupReply.(*dto.MessageToCreate) - if !ok { - mylog.Println("Error: Expected MessageToCreate type.") - return // 或其他错误处理 - } - groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 - //重新为err赋值 - _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) - if err != nil { - mylog.Printf("发送图片报错后转url发送失败: %v", err) - } - } - } - }) - } else { - _, err := apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), richMediaMessage) - echo.AddMappingFileTimeLimit(messageID, millis) - echo.AddFileTimeLimit(millis) - if err != nil { - mylog.Printf("发送 %s 信息失败_send_msg: %v", key, err) - if config.GetSendError() { //把报错当作文本发出去 - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - groupReply := generateGroupMessage(messageID, nil, err.Error(), msgseq+1) - // 进行类型断言 - groupMessage, ok := groupReply.(*dto.MessageToCreate) - if !ok { - mylog.Println("Error: Expected MessageToCreate type.") - return // 或其他错误处理 - } - groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 - //重新为err赋值 - _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) - if err != nil { - mylog.Printf("发送文本报错信息失败: %v", err) - } - } - if config.GetSendErrorPicAsUrl() { - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - groupReply := generateGroupMessage(messageID, nil, richMediaMessageCopy.URL, msgseq+1) - // 进行类型断言 - groupMessage, ok := groupReply.(*dto.MessageToCreate) - if !ok { - mylog.Println("Error: Expected MessageToCreate type.") - return // 或其他错误处理 - } - groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 - //重新为err赋值 - _, err = apiv2.PostGroupMessage(context.TODO(), message.Params.GroupID.(string), groupMessage) - if err != nil { - mylog.Printf("发送图片报错后转url发送失败: %v", err) - } - } - } - - } - //发送成功回执 - SendResponse(client, err, &message) - } - } + //复用处理逻辑 + handleSendGroupMsg(client, api, apiv2, message) case "guild": //用GroupID给ChannelID赋值,因为我们是把频道虚拟成了群 message.Params.ChannelID = message.Params.GroupID.(string) diff --git a/template/config_template.go b/template/config_template.go index 1f518785..0994ebd8 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -91,8 +91,7 @@ settings: sandbox_mode : false #默认false 如果你只希望沙箱频道使用,请改为true dev_message_id : false #在沙盒和测试环境使用无限制msg_id 仅沙盒有效,正式环境请关闭,内测结束后,tx侧未来会移除 send_error : true #将报错用文本发出,避免机器人被审核报无响应 - send_error_pic_as_url : false #临时解决22009报错 - url_pic_transfer : false #可与url_pic_transfer配合使用 也可单独使用 把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(是目前gsk门槛最高的配置) + url_pic_transfer : false #把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(暂时不需要) title : "Gensokyo © 2023 - Hoshinonyaruko" #程序的标题 如果多个机器人 可根据标题区分 diff --git a/template/config_template.yml b/template/config_template.yml index 0c9e0b96..221ebb51 100644 --- a/template/config_template.yml +++ b/template/config_template.yml @@ -71,5 +71,4 @@ settings: No_White_Response : "" #默认不兜底,强烈建议设置一个友善的兜底回复,告知审核机器人已无隐藏指令,如:你输入的指令不对哦,@机器人来获取可用指令 send_error : true #将报错用文本发出,避免机器人被审核报无响应 add_at_group : false #自动在群聊指令前加上at,某些机器人写法特别,必须有at才反应时,请打开,默认请关闭(如果需要at,不需要at指令混杂,请优化代码适配群场景,群场景目前没有at概念 - send_error_pic_as_url : false #临时解决22009报错 - url_pic_transfer : false #可与url_pic_transfer配合使用 也可单独使用 把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(是目前gsk门槛最高的配置) \ No newline at end of file + url_pic_transfer : false #把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(暂时不需要) \ No newline at end of file From 0be0f78639ef1708ece3e61649e1f7369fd17b80 Mon Sep 17 00:00:00 2001 From: cosmo Date: Wed, 22 Nov 2023 19:47:55 +0800 Subject: [PATCH 7/8] beta51 --- handlers/send_group_msg.go | 1 + 1 file changed, 1 insertion(+) diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index 5e30df0e..b807317c 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -165,6 +165,7 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap SendResponse(client, err, &message) delete(foundItems, imageType) // 从foundItems中删除已处理的图片项 + messageText = "" } // 优先发送文本信息 From 7fffb931cfeb992ed92cfe917918f6eca9454744 Mon Sep 17 00:00:00 2001 From: cosmo Date: Wed, 22 Nov 2023 20:11:03 +0800 Subject: [PATCH 8/8] test --- handlers/send_group_msg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index b807317c..d8e066d7 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -227,7 +227,7 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap } } } - if message_return.MediaResponse.FileInfo != "" { + if message_return != nil && message_return.MediaResponse != nil && message_return.MediaResponse.FileInfo != "" { msgseq := echo.GetMappingSeq(messageID) echo.AddMappingSeq(messageID, msgseq+1) media := dto.Media{