Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beta70 #202

Merged
merged 6 commits into from
Dec 2, 2023
Merged
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
8 changes: 7 additions & 1 deletion botgo/dto/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,18 @@ type MediaResponse struct {
TTL int `json:"ttl"`
}

//新增
//群信息结构
type GroupMessageResponse struct {
MediaResponse *MediaResponse
Message *Message
}

// C2CMessageResponse 用于包装 C2C 消息的响应
type C2CMessageResponse struct {
Message *Message `json:"message,omitempty"`
MediaResponse *MediaResponse `json:"media_response,omitempty"`
}

// Embed 结构
type Embed struct {
Title string `json:"title,omitempty"`
Expand Down
2 changes: 1 addition & 1 deletion botgo/openapi/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ type MessageAPI interface {
// PostGroupMessage 发送群消息
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)
PostC2CMessage(ctx context.Context, userID string, msg dto.APIMessage) (*dto.C2CMessageResponse, error)
}

// GuildAPI guild 相关接口
Expand Down
38 changes: 31 additions & 7 deletions botgo/openapi/v1/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"strconv"

"github.com/go-resty/resty/v2"
"github.com/tidwall/gjson"

"github.com/tencent-connect/botgo/dto"
Expand Down Expand Up @@ -221,14 +222,37 @@ func getC2CURLBySendType(msgType dto.SendType) uri {
}

// PostC2CMessage 回复C2C消息
func (o *openAPI) PostC2CMessage(ctx context.Context, userID string, msg dto.APIMessage) (*dto.Message, error) {
resp, err := o.request(ctx).
SetResult(dto.Message{}).
SetPathParam("user_id", userID).
SetBody(msg).
Post(o.getURL(getC2CURLBySendType(msg.GetSendType())))
func (o *openAPI) PostC2CMessage(ctx context.Context, userID string, msg dto.APIMessage) (*dto.C2CMessageResponse, 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("user_id", userID).
SetBody(msg).
Post(o.getURL(getC2CURLBySendType(msgType)))
default:
resp, err = o.request(ctx).
SetResult(dto.Message{}). // 设置为消息类型
SetPathParam("user_id", userID).
SetBody(msg).
Post(o.getURL(getC2CURLBySendType(msgType)))
}

if err != nil {
return nil, err
}
return resp.Result().(*dto.Message), nil

result := &dto.C2CMessageResponse{}
switch msgType {
case dto.RichMedia:
result.MediaResponse = resp.Result().(*dto.MediaResponse)
default:
result.Message = resp.Result().(*dto.Message)
}

return result, nil
}
37 changes: 30 additions & 7 deletions botgo/openapi/v2/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,14 +237,37 @@ func getC2CURLBySendType(msgType dto.SendType) uri {
}

// PostC2CMessage 回复C2C消息
func (o *openAPIv2) PostC2CMessage(ctx context.Context, userID string, msg dto.APIMessage) (*dto.Message, error) {
resp, err := o.request(ctx).
SetResult(dto.Message{}).
SetPathParam("user_id", userID).
SetBody(msg).
Post(o.getURL(getC2CURLBySendType(msg.GetSendType())))
func (o *openAPIv2) PostC2CMessage(ctx context.Context, userID string, msg dto.APIMessage) (*dto.C2CMessageResponse, 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("user_id", userID).
SetBody(msg).
Post(o.getURL(getC2CURLBySendType(msgType)))
default:
resp, err = o.request(ctx).
SetResult(dto.Message{}). // 设置为消息类型
SetPathParam("user_id", userID).
SetBody(msg).
Post(o.getURL(getC2CURLBySendType(msgType)))
}

if err != nil {
return nil, err
}
return resp.Result().(*dto.Message), nil

result := &dto.C2CMessageResponse{}
switch msgType {
case dto.RichMedia:
result.MediaResponse = resp.Result().(*dto.MediaResponse)
default:
result.Message = resp.Result().(*dto.Message)
}

return result, nil
}
13 changes: 13 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ type Settings struct {
CardAndNick string `yaml:"card_nick"`
AutoBind bool `yaml:"auto_bind"`
CustomBotName string `yaml:"custom_bot_name"`
SendDelay int `yaml:"send_delay"`
}

// LoadConfig 从文件中加载配置并初始化单例配置
Expand Down Expand Up @@ -1028,3 +1029,15 @@ func GetCustomBotName() string {
}
return instance.Settings.CustomBotName
}

// 获取send_delay的值
func GetSendDelay() int {
mu.Lock()
defer mu.Unlock()

if instance == nil {
mylog.Println("Warning: instance is nil when trying to GetSendDelay value.")
return 300
}
return instance.Settings.SendDelay
}
3 changes: 2 additions & 1 deletion handlers/send_group_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,8 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap
tryMessageTypes := []string{"group", "guild", "guild_private"}
messageCopy := message // 创建message的副本
echo.AddMsgType(config.GetAppIDStr(), idInt64, tryMessageTypes[echo.GetMapping(idInt64)-1])
time.Sleep(300 * time.Millisecond)
delay := config.GetSendDelay()
time.Sleep(time.Duration(delay) * time.Millisecond)
handleSendGroupMsg(client, api, apiv2, messageCopy)
}
}
Expand Down
3 changes: 2 additions & 1 deletion handlers/send_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope
tryMessageTypes := []string{"group", "guild", "guild_private"}
messageCopy := message // 创建message的副本
echo.AddMsgType(config.GetAppIDStr(), idInt64, tryMessageTypes[echo.GetMapping(idInt64)-1])
time.Sleep(300 * time.Millisecond)
delay := config.GetSendDelay()
time.Sleep(time.Duration(delay) * time.Millisecond)
handleSendMsg(client, api, apiv2, messageCopy)
}
}
Expand Down
123 changes: 119 additions & 4 deletions handlers/send_private_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,72 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open
mylog.Println("私聊发信息messageText:", messageText)
//mylog.Println("foundItems:", foundItems)

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 ")
return
}
// 上传图片并获取FileInfo
fileInfo, err := uploadMediaPrivate(context.TODO(), UserID, 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.PostC2CMessage(context.TODO(), UserID, groupMessage)
if err != nil {
mylog.Printf("发送组合消息失败: %v", err)
return // 或其他错误处理
}

// 发送成功回执
SendResponse(client, err, &message)

delete(foundItems, imageType) // 从foundItems中删除已处理的图片项
messageText = ""
}

// 优先发送文本信息
if messageText != "" {
msgseq := echo.GetMappingSeq(messageID)
Expand Down Expand Up @@ -144,19 +210,56 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open
for _, url := range urls {
var singleItem = make(map[string][]string)
singleItem[key] = []string{url} // 创建一个只包含一个 URL 的 singleItem
//mylog.Println("singleItem:", singleItem)
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 %s.", key)
continue // 跳过这个项,继续下一个
}
_, err = apiv2.PostC2CMessage(context.TODO(), UserID, richMediaMessage)
message_return, err := apiv2.PostC2CMessage(context.TODO(), UserID, richMediaMessage)
if err != nil {
mylog.Printf("发送 %s 私聊信息失败: %v", key, err)
mylog.Printf("发送 %s 信息失败_send_private_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.PostC2CMessage(context.TODO(), UserID, groupMessage)
if err != nil {
mylog.Printf("发送 %s 私聊信息失败: %v", key, err)
}
}
}
if message_return != nil && message_return.MediaResponse != nil && 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.PostC2CMessage(context.TODO(), UserID, groupMessage)
if err != nil {
mylog.Printf("发送 %s 私聊信息失败: %v", key, err)
}
}
//发送成功回执
SendResponse(client, err, &message)
Expand All @@ -179,7 +282,8 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open
tryMessageTypes := []string{"group", "guild", "guild_private"}
messageCopy := message // 创建message的副本
echo.AddMsgType(config.GetAppIDStr(), idInt64, tryMessageTypes[echo.GetMapping(idInt64)-1])
time.Sleep(300 * time.Millisecond)
delay := config.GetSendDelay()
time.Sleep(time.Duration(delay) * time.Millisecond)
handleSendGroupMsg(client, api, apiv2, messageCopy)
}
}
Expand Down Expand Up @@ -420,3 +524,14 @@ func getGuildIDFromMessage(message callapi.ActionMessage) (string, string, error

return guildID, channelID, nil
}

// uploadMedia 上传媒体并返回FileInfo
func uploadMediaPrivate(ctx context.Context, UserID string, richMediaMessage *dto.RichMediaMessage, apiv2 openapi.OpenAPI) (string, error) {
// 调用API来上传媒体
messageReturn, err := apiv2.PostC2CMessage(ctx, UserID, richMediaMessage)
if err != nil {
return "", err
}
// 返回上传后的FileInfo
return messageReturn.MediaResponse.FileInfo, nil
}
1 change: 1 addition & 0 deletions template/config_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ settings:
send_error : true #将报错用文本发出,避免机器人被审核报无响应
url_pic_transfer : false #把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(暂时不需要)
idmap_pro : false #需开启hash_id配合,高级id转换增强,可以多个真实值bind到同一个虚拟值,对于每个用户,每个群\私聊\判断私聊\频道,都会产生新的虚拟值,但可以多次bind,bind到同一个数字.数据库负担会变大.
send_delay : 300 #单位 毫秒 默认300ms 可以视情况减少到100或者50

title : "Gensokyo © 2023 - Hoshinonyaruko" #程序的标题 如果多个机器人 可根据标题区分
custom_bot_name : "Gensokyo全域机器人" #自定义机器人名字,会在api调用中返回,默认Gensokyo全域机器人
Expand Down
1 change: 1 addition & 0 deletions template/config_template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,4 @@ settings:
card_nick : "" #默认为空,连接mirai-overflow时,请设置为非空,这里是机器人对用户称谓,为空为插件获取,mirai不支持
auto_bind : true #测试功能,后期会移除
custom_bot_name : "Gensokyo全域机器人" #自定义机器人名字,会在api调用中返回,默认Gensokyo全域机器人
send_delay : 300 #单位 毫秒 默认300ms 可以视情况减少到100或者50
Loading