From 063bbca1f66a93d83e6fb1efd85600504f7170ed Mon Sep 17 00:00:00 2001 From: cosmo Date: Mon, 11 Dec 2023 21:18:47 +0800 Subject: [PATCH 1/5] beta88 --- handlers/send_group_msg.go | 2 +- readme.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index aa94449c..3f05e047 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -352,7 +352,7 @@ func HandleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap Vuserid, ok := message.Params.UserID.(string) if !ok { mylog.Printf("Error illegal UserID") - return + return "", nil } if Vuserid != "" && config.GetIdmapPro() { RChannelID, _, err = idmap.RetrieveRowByIDv2Pro(message.Params.ChannelID, Vuserid) diff --git a/readme.md b/readme.md index d9a388fe..4b78c21a 100644 --- a/readme.md +++ b/readme.md @@ -68,8 +68,8 @@ gensokyo兼容 [OneBot-v11](https://github.com/botuniverse/onebot-11) ,并在 ### 接口 -- [ ] HTTP API 实现中 -- [ ] 反向 HTTP POST 实现中 +- [x] HTTP API +- [x] 反向 HTTP POST - [x] 正向 WebSocket - [x] 反向 WebSocket From 09d44793c2919c2cd3e2386e2b9b18bc3730e8b9 Mon Sep 17 00:00:00 2001 From: cosmo Date: Wed, 13 Dec 2023 16:45:23 +0800 Subject: [PATCH 2/5] beta89 --- Processor/ProcessC2CMessage.go | 21 +++++++--- Processor/ProcessChannelDirectMessage.go | 41 ++++++++++++++------ Processor/ProcessGroupMessage.go | 27 +++++++++---- Processor/ProcessGuildATMessage.go | 17 +++++++- Processor/ProcessGuildNormalMessage.go | 26 ++++++++----- Processor/Processor.go | 49 ++++++++++++++++++------ config/config.go | 13 +++++++ idmap/service.go | 10 +++++ template/config_template.go | 1 + template/config_template.yml | 1 + 10 files changed, 158 insertions(+), 48 deletions(-) diff --git a/Processor/ProcessC2CMessage.go b/Processor/ProcessC2CMessage.go index 0fe18fdb..55265014 100644 --- a/Processor/ProcessC2CMessage.go +++ b/Processor/ProcessC2CMessage.go @@ -85,7 +85,12 @@ func (p *Processors) ProcessC2CMessage(data *dto.WSC2CMessageData) error { if config.GetArrayValue() { segmentedMessages = handlers.ConvertToSegmentedMessage(data) } - IsBindedUserId := idmap.CheckValue(data.Author.ID, userid64) + var IsBindedUserId bool + if config.GetHashIDValue() { + IsBindedUserId = idmap.CheckValue(data.Author.ID, userid64) + } else { + IsBindedUserId = idmap.CheckValuev2(userid64) + } privateMsg := OnebotPrivateMessage{ RawMessage: messageText, Message: segmentedMessages, @@ -98,11 +103,15 @@ func (p *Processors) ProcessC2CMessage(data *dto.WSC2CMessageData) error { Nickname: "", //这个不支持,但加机器人好友,会收到一个事件,可以对应储存获取,用idmaps可以做到. UserID: userid64, }, - SubType: "friend", - Time: time.Now().Unix(), - Avatar: "", //todo 同上 - RealMessageType: "group_private", - IsBindedUserId: IsBindedUserId, + SubType: "friend", + Time: time.Now().Unix(), + } + if !config.GetNativeOb11() { + privateMsg.RealMessageType = "group_private" + privateMsg.IsBindedUserId = IsBindedUserId + if IsBindedUserId { + privateMsg.Avatar, _ = GenerateAvatarURL(userid64) + } } // 根据条件判断是否添加Echo字段 if config.GetTwoWayEcho() { diff --git a/Processor/ProcessChannelDirectMessage.go b/Processor/ProcessChannelDirectMessage.go index 10dbeb6a..5f2a6b4d 100644 --- a/Processor/ProcessChannelDirectMessage.go +++ b/Processor/ProcessChannelDirectMessage.go @@ -106,7 +106,13 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) if config.GetArrayValue() { segmentedMessages = handlers.ConvertToSegmentedMessage(data) } - IsBindedUserId := idmap.CheckValue(data.Author.ID, userid64) + var IsBindedUserId bool + if config.GetHashIDValue() { + IsBindedUserId = idmap.CheckValue(data.Author.ID, userid64) + } else { + IsBindedUserId = idmap.CheckValuev2(userid64) + } + privateMsg := OnebotPrivateMessage{ RawMessage: messageText, Message: segmentedMessages, @@ -119,11 +125,14 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) Nickname: data.Member.Nick, UserID: userid64, }, - SubType: "friend", - Time: time.Now().Unix(), - Avatar: data.Author.Avatar, - RealMessageType: "guild_private", - IsBindedUserId: IsBindedUserId, + SubType: "friend", + Time: time.Now().Unix(), + } + //增强字段 + if !config.GetNativeOb11() { + privateMsg.RealMessageType = "guild_private" + privateMsg.IsBindedUserId = IsBindedUserId + privateMsg.Avatar = data.Author.Avatar } // 根据条件判断是否添加Echo字段 if config.GetTwoWayEcho() { @@ -318,7 +327,12 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) if config.GetArrayValue() { segmentedMessages = handlers.ConvertToSegmentedMessage(data) } - IsBindedUserId := idmap.CheckValue(data.Author.ID, userid64) + var IsBindedUserId bool + if config.GetHashIDValue() { + IsBindedUserId = idmap.CheckValue(data.Author.ID, userid64) + } else { + IsBindedUserId = idmap.CheckValuev2(userid64) + } groupMsg := OnebotGroupMessage{ RawMessage: messageText, Message: segmentedMessages, @@ -338,11 +352,14 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) Area: "", Level: "0", }, - SubType: "normal", - Time: time.Now().Unix(), - Avatar: data.Author.Avatar, - RealMessageType: "guild_private", - IsBindedUserId: IsBindedUserId, + SubType: "normal", + Time: time.Now().Unix(), + } + //增强字段 + if !config.GetNativeOb11() { + groupMsg.RealMessageType = "guild_private" + groupMsg.IsBindedUserId = IsBindedUserId + groupMsg.Avatar = data.Author.Avatar } // 根据条件判断是否添加Echo字段 if config.GetTwoWayEcho() { diff --git a/Processor/ProcessGroupMessage.go b/Processor/ProcessGroupMessage.go index fa60e013..163d5b13 100644 --- a/Processor/ProcessGroupMessage.go +++ b/Processor/ProcessGroupMessage.go @@ -88,8 +88,14 @@ func (p *Processors) ProcessGroupMessage(data *dto.WSGroupATMessageData) error { if config.GetArrayValue() { segmentedMessages = handlers.ConvertToSegmentedMessage(data) } - IsBindedUserId := idmap.CheckValue(data.Author.ID, userid64) - IsBindedGroupId := idmap.CheckValue(data.GroupID, GroupID64) + var IsBindedUserId, IsBindedGroupId bool + if config.GetHashIDValue() { + IsBindedUserId = idmap.CheckValue(data.Author.ID, userid64) + IsBindedGroupId = idmap.CheckValue(data.GroupID, GroupID64) + } else { + IsBindedUserId = idmap.CheckValuev2(userid64) + IsBindedGroupId = idmap.CheckValuev2(GroupID64) + } groupMsg := OnebotGroupMessage{ RawMessage: messageText, Message: segmentedMessages, @@ -106,12 +112,17 @@ func (p *Processors) ProcessGroupMessage(data *dto.WSGroupATMessageData) error { Area: "0", Level: "0", }, - SubType: "normal", - Time: time.Now().Unix(), - Avatar: "", - RealMessageType: "group", - IsBindedUserId: IsBindedUserId, - IsBindedGroupId: IsBindedGroupId, + SubType: "normal", + Time: time.Now().Unix(), + } + //增强配置 + if !config.GetNativeOb11() { + groupMsg.RealMessageType = "group" + groupMsg.IsBindedUserId = IsBindedUserId + groupMsg.IsBindedGroupId = IsBindedGroupId + if IsBindedUserId { + groupMsg.Avatar, _ = GenerateAvatarURL(userid64) + } } //根据条件判断是否增加nick和card var CaN = config.GetCardAndNick() diff --git a/Processor/ProcessGuildATMessage.go b/Processor/ProcessGuildATMessage.go index b87ff1dc..0f3ba9cb 100644 --- a/Processor/ProcessGuildATMessage.go +++ b/Processor/ProcessGuildATMessage.go @@ -178,8 +178,14 @@ func (p *Processors) ProcessGuildATMessage(data *dto.WSATMessageData) error { if config.GetArrayValue() { segmentedMessages = handlers.ConvertToSegmentedMessage(data) } - IsBindedUserId := idmap.CheckValue(data.Author.ID, userid64) - IsBindedGroupId := idmap.CheckValue(data.GroupID, ChannelID64) + var IsBindedUserId, IsBindedGroupId bool + if config.GetHashIDValue() { + IsBindedUserId = idmap.CheckValue(data.Author.ID, userid64) + IsBindedGroupId = idmap.CheckValue(data.ChannelID, ChannelID64) + } else { + IsBindedUserId = idmap.CheckValuev2(userid64) + IsBindedGroupId = idmap.CheckValuev2(ChannelID64) + } groupMsg := OnebotGroupMessage{ RawMessage: messageText, Message: segmentedMessages, @@ -205,6 +211,13 @@ func (p *Processors) ProcessGuildATMessage(data *dto.WSATMessageData) error { IsBindedUserId: IsBindedUserId, IsBindedGroupId: IsBindedGroupId, } + //增强配置 + if !config.GetNativeOb11() { + groupMsg.RealMessageType = "guild" + groupMsg.IsBindedUserId = IsBindedUserId + groupMsg.IsBindedGroupId = IsBindedGroupId + groupMsg.Avatar = data.Author.Avatar + } // 根据条件判断是否添加Echo字段 if config.GetTwoWayEcho() { groupMsg.Echo = echostr diff --git a/Processor/ProcessGuildNormalMessage.go b/Processor/ProcessGuildNormalMessage.go index ff305e59..c32dff6c 100644 --- a/Processor/ProcessGuildNormalMessage.go +++ b/Processor/ProcessGuildNormalMessage.go @@ -155,7 +155,6 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error { return nil } } - //转成int再互转 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "guild_id", data.GuildID) //转换at @@ -182,8 +181,14 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error { if config.GetArrayValue() { segmentedMessages = handlers.ConvertToSegmentedMessage(data) } - IsBindedUserId := idmap.CheckValue(data.Author.ID, userid64) - IsBindedGroupId := idmap.CheckValue(data.GroupID, ChannelID64) + var IsBindedUserId, IsBindedGroupId bool + if config.GetHashIDValue() { + IsBindedUserId = idmap.CheckValue(data.Author.ID, userid64) + IsBindedGroupId = idmap.CheckValue(data.ChannelID, ChannelID64) + } else { + IsBindedUserId = idmap.CheckValuev2(userid64) + IsBindedGroupId = idmap.CheckValuev2(ChannelID64) + } groupMsg := OnebotGroupMessage{ RawMessage: messageText, Message: segmentedMessages, @@ -202,12 +207,15 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error { Area: "", Level: "0", }, - SubType: "normal", - Time: time.Now().Unix(), - Avatar: data.Author.Avatar, - RealMessageType: "guild", - IsBindedUserId: IsBindedUserId, - IsBindedGroupId: IsBindedGroupId, + SubType: "normal", + Time: time.Now().Unix(), + } + //增强配置 + if !config.GetNativeOb11() { + groupMsg.RealMessageType = "guild" + groupMsg.IsBindedUserId = IsBindedUserId + groupMsg.IsBindedGroupId = IsBindedGroupId + groupMsg.Avatar = data.Author.Avatar } // 根据条件判断是否添加Echo字段 if config.GetTwoWayEcho() { diff --git a/Processor/Processor.go b/Processor/Processor.go index 573278b9..46e6a122 100644 --- a/Processor/Processor.go +++ b/Processor/Processor.go @@ -9,6 +9,7 @@ import ( "encoding/json" "errors" "fmt" + "math/big" "net/http" "reflect" "regexp" @@ -86,9 +87,9 @@ type OnebotGroupMessage struct { MessageSeq int `json:"message_seq"` Font int `json:"font"` UserID int64 `json:"user_id"` - RealMessageType string `json:"real_message_type"` //当前信息的真实类型 group group_private guild guild_private - IsBindedGroupId bool `json:"is_binded_group_id"` //当前群号是否是binded后的 - IsBindedUserId bool `json:"is_binded_user_id"` //当前用户号号是否是binded后的 + RealMessageType string `json:"real_message_type,omitempty"` //当前信息的真实类型 group group_private guild guild_private + IsBindedGroupId bool `json:"is_binded_group_id,omitempty"` //当前群号是否是binded后的 + IsBindedUserId bool `json:"is_binded_user_id,omitempty"` //当前用户号号是否是binded后的 } // 私聊信息事件 @@ -103,12 +104,12 @@ type OnebotPrivateMessage struct { Time int64 `json:"time"` Avatar string `json:"avatar,omitempty"` Echo string `json:"echo,omitempty"` - Message interface{} `json:"message"` // For array format - MessageSeq int `json:"message_seq"` // Optional field - Font int `json:"font"` // Optional field - UserID int64 `json:"user_id"` // Can be either string or int depending on logic - RealMessageType string `json:"real_message_type"` //当前信息的真实类型 group group_private guild guild_private - IsBindedUserId bool `json:"is_binded_user_id"` //当前用户号号是否是binded后的 + Message interface{} `json:"message"` // For array format + MessageSeq int `json:"message_seq"` // Optional field + Font int `json:"font"` // Optional field + UserID int64 `json:"user_id"` // Can be either string or int depending on logic + RealMessageType string `json:"real_message_type,omitempty"` //当前信息的真实类型 group group_private guild guild_private + IsBindedUserId bool `json:"is_binded_user_id,omitempty"` //当前用户号号是否是binded后的 } type PrivateSender struct { @@ -261,10 +262,23 @@ func (p *Processors) BroadcastMessageToAll(message map[string]interface{}) error return fmt.Errorf(strings.Join(errors, "; ")) } - PostMessageToUrls(message) + //判断是否填写了反向post地址 + if !allEmpty(config.GetPostUrl()) { + PostMessageToUrls(message) + } return nil } +// allEmpty checks if all the strings in the slice are empty. +func allEmpty(addresses []string) bool { + for _, addr := range addresses { + if addr != "" { + return false + } + } + return true +} + // 上报信息给反向Http func PostMessageToUrls(message map[string]interface{}) { // 获取上报 URL 列表 @@ -536,7 +550,7 @@ func performBindOperation(cleanedMessage string, data interface{}, Type string, if err != nil { SendMessage(err.Error(), data, Type, p, p2) } else { - SendMessage("绑定成功,目前状态:\n当前真实值 "+now+"\n当前虚拟值 "+new, data, Type, p, p2) + SendMessage("绑定成功,目前状态:\n当前真实值 "+new+"\n当前虚拟值 "+now, data, Type, p, p2) } return nil @@ -825,3 +839,16 @@ func updateMappings(userid64, vuinValue, GroupID64, idValue int64) error { } return nil } + +// GenerateAvatarURL 生成根据给定 userID 和随机 q 值组合的 QQ 头像 URL +func GenerateAvatarURL(userID int64) (string, error) { + // 使用 crypto/rand 生成更安全的随机数 + n, err := rand.Int(rand.Reader, big.NewInt(5)) + if err != nil { + return "", err + } + qNumber := n.Int64() + 1 // 产生 1 到 5 的随机数 + + // 构建并返回 URL + return fmt.Sprintf("http://q%d.qlogo.cn/g?b=qq&nk=%d&s=640", qNumber, userID), nil +} diff --git a/config/config.go b/config/config.go index f1fbd2f4..21269394 100644 --- a/config/config.go +++ b/config/config.go @@ -101,6 +101,7 @@ type Settings struct { PostSecret []string `yaml:"post_secret"` PostMaxRetries []int `yaml:"post_max_retries"` PostRetriesInterval []int `yaml:"post_retries_interval"` + NativeOb11 bool `yaml:"native_ob11"` } // LoadConfig 从文件中加载配置并初始化单例配置 @@ -1221,3 +1222,15 @@ func GetPostRetriesInterval() []int { } return instance.Settings.PostRetriesInterval } + +// 获取GetTransferUrl的值 +func GetNativeOb11() bool { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to NativeOb11 value.") + return false + } + return instance.Settings.NativeOb11 +} diff --git a/idmap/service.go b/idmap/service.go index 6a5c2194..b2c77de6 100644 --- a/idmap/service.go +++ b/idmap/service.go @@ -104,6 +104,16 @@ func CheckValue(id string, value int64) bool { return generatedValue != value } +func CheckValuev2(value int64) bool { + var isbinded bool + if value < 100000 { + isbinded = false + } else { + isbinded = true + } + return isbinded +} + // 根据a储存b func StoreID(id string) (int64, error) { var newRow int64 diff --git a/template/config_template.go b/template/config_template.go index be42d80e..0b95b310 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -52,6 +52,7 @@ settings: reconnect_times : 100 #反向ws连接失败后的重试次数,希望一直重试,可设置9999 heart_beat_interval : 10 #反向ws心跳间隔 单位秒 推荐5-10 launch_reconnect_times : 1 #启动时尝试反向ws连接次数,建议先打开应用端再开启gensokyo,因为启动时连接会阻塞webui启动,默认只连接一次,可自行增大 + native_ob11 : false #如果你的机器人收到事件报错,请开启此选项增加兼容性 #正向ws设置 ws_server_path : "ws" #默认监听0.0.0.0:port/ws_server_path 若有安全需求,可不放通port到公网,或设置ws_server_token 若想监听/ 可改为"",若想监听到不带/地址请写nil diff --git a/template/config_template.yml b/template/config_template.yml index 5fae8c06..cce6756c 100644 --- a/template/config_template.yml +++ b/template/config_template.yml @@ -84,3 +84,4 @@ settings: launch_reconnect_times : 1 #启动时尝试反向ws连接次数,建议先打开应用端再开启gensokyo,因为启动时连接会阻塞webui启动,默认只连接一次,可自行增大 white_bypass : [] #格式[1,2,3],白名单不生效的群,用于设置自己的灰度沙箱,避免测试时候反复开关白名单的不便. transfer_url : true #默认开启,关闭后自理url发送,配置server_dir为你的域名,配置crt和key后,将域名/url和/image在q.qq.com后台通过校验,自动使用302跳转处理机器人发出的所有域名. + native_ob11 : false #如果你的机器人收到事件报错,请开启此选项增加兼容性 \ No newline at end of file From 65c31245996ab85ef3dcddbc4d6cb71586a68dd0 Mon Sep 17 00:00:00 2001 From: cosmo Date: Thu, 14 Dec 2023 00:06:42 +0800 Subject: [PATCH 3/5] bugfix --- handlers/send_private_msg.go | 2 +- idmap/service.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/handlers/send_private_msg.go b/handlers/send_private_msg.go index 56cf1ec2..895e3fad 100644 --- a/handlers/send_private_msg.go +++ b/handlers/send_private_msg.go @@ -285,7 +285,7 @@ func HandleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open echo.AddMsgType(config.GetAppIDStr(), idInt64, tryMessageTypes[echo.GetMapping(idInt64)-1]) delay := config.GetSendDelay() time.Sleep(time.Duration(delay) * time.Millisecond) - HandleSendGroupMsg(client, api, apiv2, messageCopy) + HandleSendPrivateMsg(client, api, apiv2, messageCopy) } return retmsg, nil } diff --git a/idmap/service.go b/idmap/service.go index b2c77de6..9110ae28 100644 --- a/idmap/service.go +++ b/idmap/service.go @@ -806,7 +806,7 @@ func RetrieveRealValuev2(virtualValue int64) (string, string, error) { return "", "", fmt.Errorf("error response from server") } - realValue, ok := response["realValue"].(string) + realValue, ok := response["real"].(string) if !ok { return "", "", fmt.Errorf("invalid response format") } From 295f7c6ba88da5de7039efd00ca049f800f685be Mon Sep 17 00:00:00 2001 From: cosmo Date: Thu, 14 Dec 2023 15:19:15 +0800 Subject: [PATCH 4/5] beta90 --- Processor/ProcessGuildATMessage.go | 2 ++ Processor/ProcessGuildNormalMessage.go | 2 ++ handlers/send_private_msg.go | 35 ++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Processor/ProcessGuildATMessage.go b/Processor/ProcessGuildATMessage.go index 0f3ba9cb..8cbcb2af 100644 --- a/Processor/ProcessGuildATMessage.go +++ b/Processor/ProcessGuildATMessage.go @@ -154,6 +154,8 @@ func (p *Processors) ProcessGuildATMessage(data *dto.WSATMessageData) error { } //转成int再互转 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "guild_id", data.GuildID) + //储存原来的(获取群列表需要) + idmap.WriteConfigv2(data.ChannelID, "guild_id", data.GuildID) //转换at和图片 messageText := handlers.RevertTransformedText(data, "guild", p.Api, p.Apiv2, ChannelID64) if messageText == "" { diff --git a/Processor/ProcessGuildNormalMessage.go b/Processor/ProcessGuildNormalMessage.go index c32dff6c..f5c4f3a4 100644 --- a/Processor/ProcessGuildNormalMessage.go +++ b/Processor/ProcessGuildNormalMessage.go @@ -157,6 +157,8 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error { } //转成int再互转 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "guild_id", data.GuildID) + //储存原来的(获取群列表需要) + idmap.WriteConfigv2(data.ChannelID, "guild_id", data.GuildID) //转换at messageText := handlers.RevertTransformedText(data, "guild", p.Api, p.Apiv2, ChannelID64) if messageText == "" { diff --git a/handlers/send_private_msg.go b/handlers/send_private_msg.go index 895e3fad..094c9770 100644 --- a/handlers/send_private_msg.go +++ b/handlers/send_private_msg.go @@ -336,8 +336,12 @@ func HandleSendGuildChannelPrivateMsg(client callapi.Client, api openapi.OpenAPI //频道私信 转 私信 通过userid(author_id)来还原频道私信需要的guildid channelID guildID, channelID, err = getGuildIDFromMessage(message) if err != nil { - mylog.Printf("获取 guild_id 和 channel_id 出错: %v", err) - return "", nil + mylog.Printf("获取 guild_id 和 channel_id 出错,进行重试: %v", err) + guildID, channelID, err = getGuildIDFromMessagev2(message) + if err != nil { + mylog.Printf("获取 guild_id 和 channel_id 出错,重试失败: %v", err) + return "", nil + } } //频道私信 转 私信 if GroupID != "" && config.GetIdmapPro() { @@ -538,6 +542,33 @@ func getGuildIDFromMessage(message callapi.ActionMessage) (string, string, error return guildID, channelID, nil } +// 这个函数可以通过int类型的虚拟groupid反推真实的guild_id和channel_id +func getGuildIDFromMessagev2(message callapi.ActionMessage) (string, string, error) { + var GroupID string + //groupID此时是转换后的channelid + + // 判断UserID的类型,并将其转换为string + switch v := message.Params.GroupID.(type) { + case int: + GroupID = strconv.Itoa(v) + case float64: + GroupID = strconv.FormatInt(int64(v), 10) // 将float64先转为int64,然后再转为string + case string: + GroupID = v + default: + return "", "", fmt.Errorf("unexpected type for UserID: %T", v) // 使用%T来打印具体的类型 + } + + var err error + //使用channelID作为sectionName从数据库中获取guild_id + guildID, err := idmap.ReadConfigv2(GroupID, "guild_id") + if err != nil { + return "", "", fmt.Errorf("error reading guild_id: %v", err) + } + + return guildID, GroupID, nil +} + // uploadMedia 上传媒体并返回FileInfo func uploadMediaPrivate(ctx context.Context, UserID string, richMediaMessage *dto.RichMediaMessage, apiv2 openapi.OpenAPI) (string, error) { // 调用API来上传媒体 From 5a1c537f56398a351ad07e8fba92323022cec76b Mon Sep 17 00:00:00 2001 From: cosmo Date: Sat, 16 Dec 2023 15:02:17 +0800 Subject: [PATCH 5/5] beta91 --- Processor/Processor.go | 17 +++++++++++-- config/config.go | 26 ++++++++++++++++++++ echo/echo.go | 16 +++++++++---- go.mod | 1 + go.sum | 2 ++ handlers/message_parser.go | 38 ++++++++++++++++++++++++++---- handlers/send_group_forward_msg.go | 2 +- handlers/send_group_msg.go | 2 +- handlers/send_guild_channel_msg.go | 2 +- handlers/send_private_msg.go | 4 ++-- template/config_template.go | 2 ++ template/config_template.yml | 4 +++- 12 files changed, 100 insertions(+), 16 deletions(-) diff --git a/Processor/Processor.go b/Processor/Processor.go index 46e6a122..b0e34154 100644 --- a/Processor/Processor.go +++ b/Processor/Processor.go @@ -344,6 +344,7 @@ func (p *Processors) HandleFrameworkCommand(messageText string, data interface{} } var err error var now, new, newpro1, newpro2 string + var nowgroup, newgroup string var realid, realid2 string var guildid, guilduserid string switch v := data.(type) { @@ -378,10 +379,22 @@ func (p *Processors) HandleFrameworkCommand(messageText string, data interface{} // 获取MasterID数组 masterIDs := config.GetMasterID() - // 根据realid获取new + // 根据realid获取new(用户id) now, new, err = idmap.RetrieveVirtualValuev2(realid) + if err != nil { + mylog.Printf("根据realid获取new(用户id) 错误:%v", err) + } + // 根据realid获取new(群id) + nowgroup, newgroup, err = idmap.RetrieveVirtualValuev2(realid2) + if err != nil { + mylog.Printf("根据realid获取new(群id)错误:%v", err) + } + // idmaps-pro获取群和用户id if config.GetIdmapPro() { newpro1, newpro2, err = idmap.RetrieveVirtualValuev2Pro(realid2, realid) + if err != nil { + mylog.Printf("idmaps-pro获取群和用户id 错误:%v", err) + } } // 检查真实值或虚拟值是否在数组中 var realValueIncluded, virtualValueIncluded bool @@ -437,7 +450,7 @@ func (p *Processors) HandleFrameworkCommand(messageText string, data interface{} message := fmt.Sprintf("idmaps-pro状态:\n%s\n%s\n%s", userMapping, groupMapping, bindInstruction) SendMessage(message, data, Type, p.Api, p.Apiv2) } else { - SendMessage("目前状态:\n当前真实值 "+now+"\n当前虚拟值 "+new+"\nbind指令:"+config.GetBindPrefix()+" 当前虚拟值"+" 目标虚拟值", data, Type, p.Api, p.Apiv2) + SendMessage("目前状态:\n当前真实值(用户) "+now+"\n当前虚拟值(用户) "+new+"\n当前真实值(群/频道) "+nowgroup+"\n当前虚拟值(群/频道) "+newgroup+"\nbind指令:"+config.GetBindPrefix()+" 当前虚拟值"+" 目标虚拟值", data, Type, p.Api, p.Apiv2) } return nil } diff --git a/config/config.go b/config/config.go index 21269394..b465c779 100644 --- a/config/config.go +++ b/config/config.go @@ -102,6 +102,8 @@ type Settings struct { PostMaxRetries []int `yaml:"post_max_retries"` PostRetriesInterval []int `yaml:"post_retries_interval"` NativeOb11 bool `yaml:"native_ob11"` + RamDomSeq bool `yaml:"ramdom_seq"` + UrlToQrimage bool `yaml:"url_to_qrimage"` } // LoadConfig 从文件中加载配置并初始化单例配置 @@ -1234,3 +1236,27 @@ func GetNativeOb11() bool { } return instance.Settings.NativeOb11 } + +// 获取GetRamDomSeq的值 +func GetRamDomSeq() bool { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to GetRamDomSeq value.") + return false + } + return instance.Settings.RamDomSeq +} + +// 获取GetUrlToQrimage的值 +func GetUrlToQrimage() bool { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to GetUrlToQrimage value.") + return false + } + return instance.Settings.UrlToQrimage +} diff --git a/echo/echo.go b/echo/echo.go index 91f22e9a..3c099d35 100644 --- a/echo/echo.go +++ b/echo/echo.go @@ -1,9 +1,12 @@ package echo import ( + "math/rand" "strconv" "sync" + "time" + "github.com/hoshinonyaruko/gensokyo/config" "github.com/tencent-connect/botgo/dto" ) @@ -142,11 +145,16 @@ func AddMappingSeq(key string, value int) { globalStringToIntMappingSeq.mapping[key] = value } -// GetMapping 根据给定的 string 键获取映射值 +// GetMappingSeq 根据给定的 string 键获取映射值 func GetMappingSeq(key string) int { - globalStringToIntMappingSeq.mu.Lock() - defer globalStringToIntMappingSeq.mu.Unlock() - return globalStringToIntMappingSeq.mapping[key] + if config.GetRamDomSeq() { + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + return rng.Intn(10000) + 1 // 生成 1 到 10000 的随机数 + } else { + globalStringToIntMappingSeq.mu.Lock() + defer globalStringToIntMappingSeq.mu.Unlock() + return globalStringToIntMappingSeq.mapping[key] + } } // AddMapping 添加一个新的映射 diff --git a/go.mod b/go.mod index 228c9d2f..0ca57807 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( 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/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // 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 diff --git a/go.sum b/go.sum index 52ae7f96..9d54ec2d 100644 --- a/go.sum +++ b/go.sum @@ -103,6 +103,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= 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= diff --git a/handlers/message_parser.go b/handlers/message_parser.go index 8b0e03d4..e9bf2871 100644 --- a/handlers/message_parser.go +++ b/handlers/message_parser.go @@ -2,6 +2,7 @@ package handlers import ( "context" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -20,6 +21,7 @@ import ( "github.com/hoshinonyaruko/gensokyo/idmap" "github.com/hoshinonyaruko/gensokyo/mylog" "github.com/hoshinonyaruko/gensokyo/url" + "github.com/skip2/go-qrcode" "github.com/tencent-connect/botgo/dto" "github.com/tencent-connect/botgo/openapi" "mvdan.cc/xurls" //xurls是一个从文本提取url的库 适用于多种场景 @@ -77,7 +79,7 @@ func SendResponse(client callapi.Client, err error, message *callapi.ActionMessa } // 信息处理函数 -func parseMessageContent(paramsMessage callapi.ParamsContent) (string, map[string][]string) { +func parseMessageContent(paramsMessage callapi.ParamsContent, message callapi.ActionMessage, client callapi.Client, api openapi.OpenAPI, apiv2 openapi.OpenAPI) (string, map[string][]string) { messageText := "" switch message := paramsMessage.Message.(type) { @@ -192,7 +194,7 @@ func parseMessageContent(paramsMessage callapi.ParamsContent) (string, map[strin messageText = pattern.pattern.ReplaceAllString(messageText, "") } //最后再处理Url - messageText = transformMessageTextUrl(messageText) + messageText = transformMessageTextUrl(messageText, message, client, api, apiv2) // for key, items := range foundItems { // fmt.Printf("Key: %s, Items: %v\n", key, items) @@ -238,13 +240,14 @@ func transformMessageTextAt(messageText string) string { } // 链接处理 -func transformMessageTextUrl(messageText string) string { - //是否处理url +func transformMessageTextUrl(messageText string, message callapi.ActionMessage, client callapi.Client, api openapi.OpenAPI, apiv2 openapi.OpenAPI) string { + // 是否处理url if config.GetTransferUrl() { // 判断服务器地址是否是IP地址 serverAddress := config.GetServer_dir() isIP := isIPAddress(serverAddress) VisualIP := config.GetVisibleIP() + // 使用xurls来查找和替换所有的URL messageText = xurls.Relaxed.ReplaceAllStringFunc(messageText, func(originalURL string) string { // 当服务器地址是IP地址且GetVisibleIP为false时,替换URL为空 @@ -252,6 +255,21 @@ func transformMessageTextUrl(messageText string) string { return "" } + // 如果启用了URL到QR码的转换 + if config.GetUrlToQrimage() { + // 将URL转换为QR码的字节形式 + qrCodeGenerator, _ := qrcode.New(originalURL, qrcode.High) + qrCodeGenerator.DisableBorder = true + pngBytes, _ := qrCodeGenerator.PNG(37) + //pngBytes 二维码图片的字节数据 + base64Image := base64.StdEncoding.EncodeToString(pngBytes) + picmsg := processActionMessageWithBase64PicReplace(base64Image, message) + ret := callapi.CallAPIFromDict(client, api, apiv2, picmsg) + mylog.Printf("发送url转图片结果:%v", ret) + // 从文本中去除原始URL + return "" // 返回空字符串以去除URL + } + // 根据配置处理URL if config.GetLotusValue() { // 连接到另一个gensokyo @@ -268,6 +286,18 @@ func transformMessageTextUrl(messageText string) string { return messageText } +// processActionMessageWithBase64PicReplace 将原有的callapi.ActionMessage内容替换为一个base64图片 +func processActionMessageWithBase64PicReplace(base64Image string, message callapi.ActionMessage) callapi.ActionMessage { + newMessage := createCQImageMessage(base64Image) + message.Params.Message = newMessage + return message +} + +// createCQImageMessage 从 base64 编码的图片创建 CQ 码格式的消息 +func createCQImageMessage(base64Image string) string { + return "[CQ:image,file=" + base64Image + "]" +} + // 处理at和其他定形文到onebotv11格式(cq码) func RevertTransformedText(data interface{}, msgtype string, api openapi.OpenAPI, apiv2 openapi.OpenAPI, vgid int64) string { var msg *dto.Message diff --git a/handlers/send_group_forward_msg.go b/handlers/send_group_forward_msg.go index 3a9960dd..aa475b8b 100644 --- a/handlers/send_group_forward_msg.go +++ b/handlers/send_group_forward_msg.go @@ -44,7 +44,7 @@ func HandleSendGroupForwardMsg(client callapi.Client, api openapi.OpenAPI, apiv2 content, ok := nodeData["content"].([]interface{}) if ok { // 处理 segment 类型的 content - messageText, _ = parseMessageContent(callapi.ParamsContent{Message: content}) + messageText, _ = parseMessageContent(callapi.ParamsContent{Message: content}, message, client, api, apiv2) } else { // 处理直接包含的文本内容 contentString, ok := nodeData["content"].(string) diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index 3f05e047..31203be2 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -77,7 +77,7 @@ func HandleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap switch msgType { case "group": // 解析消息内容 - messageText, foundItems := parseMessageContent(message.Params) + messageText, foundItems := parseMessageContent(message.Params, message, client, api, apiv2) var SSM bool // 使用 echo 获取消息ID var messageID string diff --git a/handlers/send_guild_channel_msg.go b/handlers/send_guild_channel_msg.go index 7b06c5ce..73364679 100644 --- a/handlers/send_guild_channel_msg.go +++ b/handlers/send_guild_channel_msg.go @@ -52,7 +52,7 @@ func HandleSendGuildChannelMsg(client callapi.Client, api openapi.OpenAPI, apiv2 //原生guild信息 case "guild": params := message.Params - messageText, foundItems := parseMessageContent(params) + messageText, foundItems := parseMessageContent(params, message, client, api, apiv2) channelID := params.ChannelID // 使用 echo 获取消息ID diff --git a/handlers/send_private_msg.go b/handlers/send_private_msg.go index 094c9770..7a8a709b 100644 --- a/handlers/send_private_msg.go +++ b/handlers/send_private_msg.go @@ -90,7 +90,7 @@ func HandleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open } // 解析消息内容 - messageText, foundItems := parseMessageContent(message.Params) + messageText, foundItems := parseMessageContent(message.Params, message, client, api, apiv2) // 使用 echo 获取消息ID var messageID string @@ -293,7 +293,7 @@ func HandleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open // 处理频道私信 最后2个指针参数可空 代表使用userid倒推 func HandleSendGuildChannelPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.OpenAPI, message callapi.ActionMessage, optionalGuildID *string, optionalChannelID *string) (string, error) { params := message.Params - messageText, foundItems := parseMessageContent(params) + messageText, foundItems := parseMessageContent(params, message, client, api, apiv2) var guildID, channelID string var err error diff --git a/template/config_template.go b/template/config_template.go index 0b95b310..46c61b55 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -53,6 +53,8 @@ settings: heart_beat_interval : 10 #反向ws心跳间隔 单位秒 推荐5-10 launch_reconnect_times : 1 #启动时尝试反向ws连接次数,建议先打开应用端再开启gensokyo,因为启动时连接会阻塞webui启动,默认只连接一次,可自行增大 native_ob11 : false #如果你的机器人收到事件报错,请开启此选项增加兼容性 + ramdom_seq : false #当多开gensokyo时,如果遇到群信息只能发出一条,请开启每个gsk的此项.(建议使用一个gsk连接多个应用) + url_to_qrimage : false #将信息中的url转换为二维码单独作为图片发出,需要同时设置 #SSL配置类 机器人发送URL设置 的 transfer_url 为 true #正向ws设置 ws_server_path : "ws" #默认监听0.0.0.0:port/ws_server_path 若有安全需求,可不放通port到公网,或设置ws_server_token 若想监听/ 可改为"",若想监听到不带/地址请写nil diff --git a/template/config_template.yml b/template/config_template.yml index cce6756c..dba1a601 100644 --- a/template/config_template.yml +++ b/template/config_template.yml @@ -84,4 +84,6 @@ settings: launch_reconnect_times : 1 #启动时尝试反向ws连接次数,建议先打开应用端再开启gensokyo,因为启动时连接会阻塞webui启动,默认只连接一次,可自行增大 white_bypass : [] #格式[1,2,3],白名单不生效的群,用于设置自己的灰度沙箱,避免测试时候反复开关白名单的不便. transfer_url : true #默认开启,关闭后自理url发送,配置server_dir为你的域名,配置crt和key后,将域名/url和/image在q.qq.com后台通过校验,自动使用302跳转处理机器人发出的所有域名. - native_ob11 : false #如果你的机器人收到事件报错,请开启此选项增加兼容性 \ No newline at end of file + native_ob11 : false #如果你的机器人收到事件报错,请开启此选项增加兼容性 + ramdom_seq : false #当多开gensokyo时,如果遇到群信息只能发出一条,请开启每个gsk的此项.(建议使用一个gsk连接多个应用) + url_to_qrimage : false #将信息中的url转换为二维码单独作为图片发出,需要同时设置 #SSL配置类 机器人发送URL设置 的 transfer_url 为 true \ No newline at end of file