From 24485e617131219449a94c34ff5ac1c2b6fcf3e0 Mon Sep 17 00:00:00 2001 From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com> Date: Sat, 29 Jun 2024 22:16:49 +0800 Subject: [PATCH 1/5] beta447 (#447) --- idmap/service.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/idmap/service.go b/idmap/service.go index 090b9382..53167f7d 100644 --- a/idmap/service.go +++ b/idmap/service.go @@ -113,7 +113,7 @@ func CleanBucket(bucketName string) { return fmt.Errorf("bucket %s not found", bucketName) } - // 使用游标遍历bucket + // 使用游标遍历bucket 正向键 k:v 32位openid:大宽int64 64位msgid:大宽int6 c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { // 检查键或值是否包含冒号 @@ -121,7 +121,7 @@ func CleanBucket(bucketName string) { continue // 忽略包含冒号的键值对 } - // 检查值id的长度 + // 检查值id的长度 这里是正向键 id := string(k) if len(id) != 32 { if err := c.Delete(); err != nil { @@ -131,14 +131,14 @@ func CleanBucket(bucketName string) { } } - // 再次遍历处理reverseKey的情况 + // 再次遍历处理reverseKey的情况 反向键 row-整数:string 32位openid/64位msgid for k, v := c.First(); k != nil; k, v = c.Next() { if strings.HasPrefix(string(k), "row-") { if bytes.Contains(k, []byte(":")) || bytes.Contains(v, []byte(":")) { continue // 忽略包含冒号的键值对 } - - id := string(b.Get(k)) + // 这里检查反向键是否是32位 + id := string(v) if len(id) != 32 { if err := b.Delete(k); err != nil { return err From d855fd89208189de1de7887aeb5486c8ecdcf856 Mon Sep 17 00:00:00 2001 From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:04:16 +0800 Subject: [PATCH 2/5] Beta448 (#448) * beta447 * beta448 --- idmap/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idmap/service.go b/idmap/service.go index 53167f7d..31c1fb48 100644 --- a/idmap/service.go +++ b/idmap/service.go @@ -117,7 +117,7 @@ func CleanBucket(bucketName string) { c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { // 检查键或值是否包含冒号 - if bytes.Contains(k, []byte(":")) || bytes.Contains(v, []byte(":")) { + if bytes.Contains(k, []byte(":")) || bytes.Contains(v, []byte(":")) || bytes.Contains(k, []byte("row-")) { continue // 忽略包含冒号的键值对 } From 1e9eb2cca106f7d397e2c7fc9bf6477cf9093f23 Mon Sep 17 00:00:00 2001 From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com> Date: Thu, 4 Jul 2024 14:52:27 +0800 Subject: [PATCH 3/5] Beta449 (#449) * beta447 * beta448 * beta449 --- config/config.go | 12 ++++++ handlers/avatar.go | 79 +++++++++++++++++++++++++++++++++++++ handlers/get_avatar.go | 5 +++ handlers/message_parser.go | 32 ++++++++++++--- structs/structs.go | 5 ++- template/config_template.go | 1 + 6 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 handlers/avatar.go diff --git a/config/config.go b/config/config.go index 887598e8..d6739645 100644 --- a/config/config.go +++ b/config/config.go @@ -2340,3 +2340,15 @@ func GetLinkNum() int { return instance.Settings.LinkNum } + +// 获取GetDoNotReplaceAppid的值 +func GetDoNotReplaceAppid() bool { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to DoNotReplaceAppid value.") + return false + } + return instance.Settings.DoNotReplaceAppid +} diff --git a/handlers/avatar.go b/handlers/avatar.go new file mode 100644 index 00000000..508a402d --- /dev/null +++ b/handlers/avatar.go @@ -0,0 +1,79 @@ +package handlers + +import ( + "fmt" + "regexp" + + "github.com/hoshinonyaruko/gensokyo/config" + "github.com/hoshinonyaruko/gensokyo/idmap" + "github.com/hoshinonyaruko/gensokyo/mylog" +) + +func ProcessCQAvatar(groupID string, text string) string { + // 断言并获取 groupID 和 qq 号 + qqRegex := regexp.MustCompile(`\[CQ:avatar,qq=(\d+)\]`) + qqMatches := qqRegex.FindAllStringSubmatch(text, -1) + + for _, match := range qqMatches { + qqStr := match[1] // 提取 qq 号 + + var originalUserID string + var err error + if config.GetIdmapPro() { + // 如果UserID不是nil且配置为使用Pro版本,则调用RetrieveRowByIDv2Pro + _, originalUserID, err = idmap.RetrieveRowByIDv2Pro(groupID, qqStr) + if err != nil { + mylog.Printf("Error1 retrieving original GroupID: %v", err) + _, originalUserID, err = idmap.RetrieveRowByIDv2Pro("690426430", qqStr) + if err != nil { + mylog.Printf("Error reading private originalUserID: %v", err) + } + } + } else { + originalUserID, err = idmap.RetrieveRowByIDv2(qqStr) + if err != nil { + mylog.Printf("Error retrieving original UserID: %v", err) + } + } + + // 生成头像URL + avatarURL, _ := GenerateAvatarURLV2(originalUserID) + + // 替换文本中的 [CQ:avatar,qq=12345678] 为 [CQ:image,file=avatarurl] + replacement := fmt.Sprintf("[CQ:image,file=%s]", avatarURL) + text = qqRegex.ReplaceAllString(text, replacement) + } + + return text +} + +func GetAvatarCQCode(groupID, qqNumber string) (string, error) { + var originalUserID string + var err error + + if config.GetIdmapPro() { + // 如果配置为使用Pro版本,则调用RetrieveRowByIDv2Pro + _, originalUserID, err = idmap.RetrieveRowByIDv2Pro(groupID, qqNumber) + if err != nil { + mylog.Printf("Error retrieving original GroupID: %v", err) + return "", err + } + } else { + // 否则调用RetrieveRowByIDv2 + originalUserID, err = idmap.RetrieveRowByIDv2(qqNumber) + if err != nil { + mylog.Printf("Error retrieving original UserID: %v", err) + return "", err + } + } + + // 生成头像URL + avatarURL, err := GenerateAvatarURLV2(originalUserID) + if err != nil { + mylog.Printf("Error generating avatar URL: %v", err) + return "", err + } + + // 返回格式化后的字符串 + return fmt.Sprintf("[CQ:image,file=%s]", avatarURL), nil +} diff --git a/handlers/get_avatar.go b/handlers/get_avatar.go index edfabfaf..95360515 100644 --- a/handlers/get_avatar.go +++ b/handlers/get_avatar.go @@ -3,6 +3,7 @@ package handlers import ( "encoding/json" "fmt" + "strconv" "github.com/hoshinonyaruko/gensokyo/callapi" "github.com/hoshinonyaruko/gensokyo/config" @@ -15,6 +16,7 @@ type GetAvatarResponse struct { Message string `json:"message"` RetCode int `json:"retcode"` Echo interface{} `json:"echo"` + UserID int64 `json:"user_id"` } func init() { @@ -46,9 +48,12 @@ func GetAvatar(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.OpenAPI avatarurl, _ := GenerateAvatarURLV2(originalUserID) + useridstr := message.Params.UserID.(string) + response.Message = avatarurl response.RetCode = 0 response.Echo = message.Echo + response.UserID, _ = strconv.ParseInt(useridstr, 10, 64) outputMap := structToMap(response) diff --git a/handlers/message_parser.go b/handlers/message_parser.go index 9948a873..3c621dc2 100644 --- a/handlers/message_parser.go +++ b/handlers/message_parser.go @@ -416,6 +416,8 @@ func parseMessageContent(paramsMessage callapi.ParamsContent, message callapi.Ac if config.GetEnableChangeWord() { messageText = acnode.CheckWordOUT(messageText) } + // 解析[CQ:avatar,qq=123456] + messageText = ProcessCQAvatar(paramsMessage.GroupID.(string), messageText) case []interface{}: //多个映射组成的切片 mylog.Printf("params.message is a slice (segment_type_koishi)\n") @@ -450,6 +452,9 @@ func parseMessageContent(paramsMessage callapi.ParamsContent, message callapi.Ac case "at": qqNumber, _ := segmentMap["data"].(map[string]interface{})["qq"].(string) segmentContent = "[CQ:at,qq=" + qqNumber + "]" + case "avatar": + qqNumber, _ := segmentMap["data"].(map[string]interface{})["qq"].(string) + segmentContent, _ = GetAvatarCQCode(paramsMessage.GroupID.(string), qqNumber) case "markdown": mdContent, ok := segmentMap["data"].(map[string]interface{})["data"] if ok { @@ -518,6 +523,9 @@ func parseMessageContent(paramsMessage callapi.ParamsContent, message callapi.Ac case "at": qqNumber, _ := message["data"].(map[string]interface{})["qq"].(string) messageText = "[CQ:at,qq=" + qqNumber + "]" + case "avatar": + qqNumber, _ := message["data"].(map[string]interface{})["qq"].(string) + messageText, _ = GetAvatarCQCode(paramsMessage.GroupID.(string), qqNumber) case "markdown": mdContent, ok := message["data"].(map[string]interface{})["data"] if ok { @@ -563,8 +571,9 @@ func parseMessageContent(paramsMessage callapi.ParamsContent, message callapi.Ac default: mylog.Println("Unsupported message format: params.message field is not a string, map or slice") } + //处理at - messageText = transformMessageTextAt(messageText) + messageText = transformMessageTextAt(messageText, paramsMessage.GroupID.(string)) //mylog.Printf(messageText) @@ -635,9 +644,12 @@ func isIPAddress(address string) bool { } // at处理 -func transformMessageTextAt(messageText string) string { - // 首先,将AppID替换为BotID - messageText = strings.ReplaceAll(messageText, AppID, BotID) +func transformMessageTextAt(messageText string, groupid string) string { + // DoNotReplaceAppid=false(默认频道bot,需要自己at自己时,否则改成true) + if !config.GetDoNotReplaceAppid() { + // 首先,将AppID替换为BotID + messageText = strings.ReplaceAll(messageText, AppID, BotID) + } // 去除所有[CQ:reply,id=数字] todo 更好的处理办法 replyRE := regexp.MustCompile(`\[CQ:reply,id=\d+\]`) @@ -648,7 +660,13 @@ func transformMessageTextAt(messageText string) string { messageText = re.ReplaceAllStringFunc(messageText, func(m string) string { submatches := re.FindStringSubmatch(m) if len(submatches) > 1 { - realUserID, err := idmap.RetrieveRowByIDv2(submatches[1]) + var realUserID string + var err error + if config.GetIdmapPro() { + _, realUserID, err = idmap.RetrieveRowByIDv2Pro(groupid, submatches[1]) + } else { + realUserID, err = idmap.RetrieveRowByIDv2(submatches[1]) + } if err != nil { // 如果出错,也替换成相应的格式,但使用原始QQ号 mylog.Printf("Error retrieving user ID: %v", err) @@ -758,7 +776,7 @@ func RevertTransformedText(data interface{}, msgtype string, api openapi.OpenAPI //处理前 先去前后空 messageText = strings.TrimSpace(msg.Content) } - var originmessageText = messageText + //mylog.Printf("1[%v]", messageText) // 将messageText里的BotID替换成AppID @@ -802,6 +820,8 @@ func RevertTransformedText(data interface{}, msgtype string, api openapi.OpenAPI messageText = strings.TrimSpace(messageText) } } + + var originmessageText = messageText //mylog.Printf("2[%v]", messageText) // 检查是否需要移除前缀 diff --git a/structs/structs.go b/structs/structs.go index c524b209..624961c5 100644 --- a/structs/structs.go +++ b/structs/structs.go @@ -141,8 +141,9 @@ type Settings struct { EnableChangeWord bool `yaml:"enableChangeWord"` DefaultChangeWord string `yaml:"defaultChangeWord"` //错误临时修复类 - Fix11300 bool `yaml:"fix_11300"` - HttpOnlyBot bool `yaml:"http_only_bot"` + Fix11300 bool `yaml:"fix_11300"` + HttpOnlyBot bool `yaml:"http_only_bot"` + DoNotReplaceAppid bool `yaml:"do_not_replace_appid"` //内置指令 BindPrefix string `yaml:"bind_prefix"` MePrefix string `yaml:"me_prefix"` diff --git a/template/config_template.go b/template/config_template.go index a377af81..e1fdd9d0 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -184,6 +184,7 @@ settings: #错误临时修复类 fix_11300: false #修复11300报错,需要在develop_bot_id填入自己机器人的appid. 11300原因暂时未知,临时修复方案. http_only_bot : false #这个配置项会自动配置,请不要修改,保持false. + do_not_replace_appid : false #在频道内机器人尝试at自己回at不到,保持false.群内机器人有发送用户头像url的需求时,true(因为用户头像url包含了appid,如果false就会出错.) #内置指令类 bind_prefix : "/bind" #需设置 #增强配置项 master_id 可触发 From d8cab9c892a3438dfca96afe8f2496e35f3ca3e1 Mon Sep 17 00:00:00 2001 From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:55:02 +0800 Subject: [PATCH 4/5] Beta450 (#450) * beta447 * beta448 * beta449 * beta450 --- handlers/avatar.go | 71 +++++++++++++++++++++++++++++++++++++- handlers/message_parser.go | 21 ++++++++--- 2 files changed, 87 insertions(+), 5 deletions(-) diff --git a/handlers/avatar.go b/handlers/avatar.go index 508a402d..dff391ad 100644 --- a/handlers/avatar.go +++ b/handlers/avatar.go @@ -27,6 +27,7 @@ func ProcessCQAvatar(groupID string, text string) string { _, originalUserID, err = idmap.RetrieveRowByIDv2Pro("690426430", qqStr) if err != nil { mylog.Printf("Error reading private originalUserID: %v", err) + return "" } } } else { @@ -47,6 +48,70 @@ func ProcessCQAvatar(groupID string, text string) string { return text } +func ProcessCQAvatarNoGroupID(text string) string { + // 断言并获取 groupID 和 qq 号 + qqRegex := regexp.MustCompile(`\[CQ:avatar,qq=(\d+)\]`) + qqMatches := qqRegex.FindAllStringSubmatch(text, -1) + + for _, match := range qqMatches { + qqStr := match[1] // 提取 qq 号 + + var originalUserID string + var err error + if config.GetIdmapPro() { + _, originalUserID, err = idmap.RetrieveRowByIDv2Pro("690426430", qqStr) + if err != nil { + mylog.Printf("Error reading private originalUserID: %v", err) + } + } else { + originalUserID, err = idmap.RetrieveRowByIDv2(qqStr) + if err != nil { + mylog.Printf("Error retrieving original UserID: %v", err) + } + } + + // 生成头像URL + avatarURL, _ := GenerateAvatarURLV2(originalUserID) + + // 替换文本中的 [CQ:avatar,qq=12345678] 为 [CQ:image,file=avatarurl] + replacement := fmt.Sprintf("[CQ:image,file=%s]", avatarURL) + text = qqRegex.ReplaceAllString(text, replacement) + } + + return text +} + +func GetAvatarCQCodeNoGroupID(qqNumber string) (string, error) { + var originalUserID string + var err error + + if config.GetIdmapPro() { + // 如果配置为使用Pro版本,则调用RetrieveRowByIDv2Pro + _, originalUserID, err = idmap.RetrieveRowByIDv2Pro("690426430", qqNumber) + if err != nil { + mylog.Printf("Error reading private originalUserID: %v", err) + return "", err + } + } else { + // 否则调用RetrieveRowByIDv2 + originalUserID, err = idmap.RetrieveRowByIDv2(qqNumber) + if err != nil { + mylog.Printf("Error retrieving original UserID: %v", err) + return "", err + } + } + + // 生成头像URL + avatarURL, err := GenerateAvatarURLV2(originalUserID) + if err != nil { + mylog.Printf("Error generating avatar URL: %v", err) + return "", err + } + + // 返回格式化后的字符串 + return fmt.Sprintf("[CQ:image,file=%s]", avatarURL), nil +} + func GetAvatarCQCode(groupID, qqNumber string) (string, error) { var originalUserID string var err error @@ -56,7 +121,11 @@ func GetAvatarCQCode(groupID, qqNumber string) (string, error) { _, originalUserID, err = idmap.RetrieveRowByIDv2Pro(groupID, qqNumber) if err != nil { mylog.Printf("Error retrieving original GroupID: %v", err) - return "", err + _, originalUserID, err = idmap.RetrieveRowByIDv2Pro("690426430", qqNumber) + if err != nil { + mylog.Printf("Error reading private originalUserID: %v", err) + return "", err + } } } else { // 否则调用RetrieveRowByIDv2 diff --git a/handlers/message_parser.go b/handlers/message_parser.go index 3c621dc2..1254dc8c 100644 --- a/handlers/message_parser.go +++ b/handlers/message_parser.go @@ -416,8 +416,13 @@ func parseMessageContent(paramsMessage callapi.ParamsContent, message callapi.Ac if config.GetEnableChangeWord() { messageText = acnode.CheckWordOUT(messageText) } - // 解析[CQ:avatar,qq=123456] - messageText = ProcessCQAvatar(paramsMessage.GroupID.(string), messageText) + if paramsMessage.GroupID == nil { + // 解析[CQ:avatar,qq=123456] + messageText = ProcessCQAvatarNoGroupID(messageText) + } else { + // 解析[CQ:avatar,qq=123456] + messageText = ProcessCQAvatar(paramsMessage.GroupID.(string), messageText) + } case []interface{}: //多个映射组成的切片 mylog.Printf("params.message is a slice (segment_type_koishi)\n") @@ -454,7 +459,11 @@ func parseMessageContent(paramsMessage callapi.ParamsContent, message callapi.Ac segmentContent = "[CQ:at,qq=" + qqNumber + "]" case "avatar": qqNumber, _ := segmentMap["data"].(map[string]interface{})["qq"].(string) - segmentContent, _ = GetAvatarCQCode(paramsMessage.GroupID.(string), qqNumber) + if paramsMessage.GroupID == nil { + segmentContent, _ = GetAvatarCQCodeNoGroupID(qqNumber) + } else { + segmentContent, _ = GetAvatarCQCode(paramsMessage.GroupID.(string), qqNumber) + } case "markdown": mdContent, ok := segmentMap["data"].(map[string]interface{})["data"] if ok { @@ -525,7 +534,11 @@ func parseMessageContent(paramsMessage callapi.ParamsContent, message callapi.Ac messageText = "[CQ:at,qq=" + qqNumber + "]" case "avatar": qqNumber, _ := message["data"].(map[string]interface{})["qq"].(string) - messageText, _ = GetAvatarCQCode(paramsMessage.GroupID.(string), qqNumber) + if paramsMessage.GroupID == nil { + messageText, _ = GetAvatarCQCodeNoGroupID(qqNumber) + } else { + messageText, _ = GetAvatarCQCode(paramsMessage.GroupID.(string), qqNumber) + } case "markdown": mdContent, ok := message["data"].(map[string]interface{})["data"] if ok { From 40576e759d92734bdd31b0db2c6372b7f22c308d Mon Sep 17 00:00:00 2001 From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:59:10 +0800 Subject: [PATCH 5/5] Beta451 (#451) * beta447 * beta448 * beta449 * beta450 * beta451 --- template/config_template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/config_template.go b/template/config_template.go index e1fdd9d0..4827a82d 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -42,7 +42,7 @@ settings: global_group_msg_rre_to_message : false # 是否将用户开关机器人资料页的机器人推送开关 产生的事件转换为文本信息并发送给应用端.false将使用onebotv11的notice类型上报. global_group_msg_reject_message : "机器人主动消息被关闭" # 当开启 global_group_msg_rre_to_message 时,机器人主动信息被关闭将上报的信息. 自行添加intent - GroupMsgRejectHandler global_group_msg_receive_message : "机器人主动消息被开启" # 建议设置为无规则复杂随机内容,避免用户指令内容碰撞. 自行添加 intent - GroupMsgReceiveHandler - hash_id : false # 使用hash来进行idmaps转换,可以让user_id不是123开始的递增值 + hash_id : true # 使用hash来进行idmaps转换,可以让user_id不是123开始的递增值 idmap_pro : false # 需开启hash_id配合,高级id转换增强,可以多个真实值bind到同一个虚拟值,对于每个用户,每个群\私聊\判断私聊\频道,都会产生新的虚拟值,但可以多次bind,bind到同一个数字.数据库负担会变大. #Gensokyo互联类