From a6ebe5722bc90f7c34a253fc479415a91bda3bf2 Mon Sep 17 00:00:00 2001 From: cosmo Date: Sat, 29 Jun 2024 22:15:21 +0800 Subject: [PATCH 1/7] beta447 --- 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 1d63faee49470d5c3e46efa92d5361ec9280fc28 Mon Sep 17 00:00:00 2001 From: cosmo Date: Mon, 1 Jul 2024 22:02:27 +0800 Subject: [PATCH 2/7] 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 cd346278749fc6759658b94337e4510816055a57 Mon Sep 17 00:00:00 2001 From: cosmo Date: Thu, 4 Jul 2024 14:47:07 +0800 Subject: [PATCH 3/7] 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 b790b29ec0acb0f1af93ce9f2272356912ee97c7 Mon Sep 17 00:00:00 2001 From: cosmo Date: Thu, 4 Jul 2024 16:51:02 +0800 Subject: [PATCH 4/7] 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 7a9b56a5bab382951fef7c823e68b77e64d40cbe Mon Sep 17 00:00:00 2001 From: cosmo Date: Thu, 4 Jul 2024 16:57:20 +0800 Subject: [PATCH 5/7] 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互联类 From e17d0d4ce838fc8a779309fa01e364618d87f680 Mon Sep 17 00:00:00 2001 From: cosmo Date: Thu, 4 Jul 2024 18:40:56 +0800 Subject: [PATCH 6/7] beta452 --- ...7\260&\345\220\257\345\212\250gensokyo.md" | 0 handlers/message_parser.go | 52 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 "docs/\350\265\267\346\255\245-\346\263\250\345\206\214QQ\345\274\200\346\224\276\345\271\263\345\217\260&\345\220\257\345\212\250gensokyo.md" diff --git "a/docs/\350\265\267\346\255\245-\346\263\250\345\206\214QQ\345\274\200\346\224\276\345\271\263\345\217\260&\345\220\257\345\212\250gensokyo.md" "b/docs/\350\265\267\346\255\245-\346\263\250\345\206\214QQ\345\274\200\346\224\276\345\271\263\345\217\260&\345\220\257\345\212\250gensokyo.md" new file mode 100644 index 00000000..e69de29b diff --git a/handlers/message_parser.go b/handlers/message_parser.go index 1254dc8c..0416a76c 100644 --- a/handlers/message_parser.go +++ b/handlers/message_parser.go @@ -585,8 +585,13 @@ func parseMessageContent(paramsMessage callapi.ParamsContent, message callapi.Ac mylog.Println("Unsupported message format: params.message field is not a string, map or slice") } - //处理at - messageText = transformMessageTextAt(messageText, paramsMessage.GroupID.(string)) + if paramsMessage.GroupID == nil { + //处理at + messageText = transformMessageTextAtNoGroupID(messageText) + } else { + //处理at + messageText = transformMessageTextAt(messageText, paramsMessage.GroupID.(string)) + } //mylog.Printf(messageText) @@ -698,6 +703,49 @@ func transformMessageTextAt(messageText string, groupid string) string { return messageText } +// at处理 +func transformMessageTextAtNoGroupID(messageText 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+\]`) + messageText = replyRE.ReplaceAllString(messageText, "") + + // 使用正则表达式来查找所有[CQ:at,qq=数字]的模式 + re := regexp.MustCompile(`\[CQ:at,qq=(\d+)\]`) + messageText = re.ReplaceAllStringFunc(messageText, func(m string) string { + submatches := re.FindStringSubmatch(m) + if len(submatches) > 1 { + var realUserID string + var err error + if config.GetIdmapPro() { + // 这是个魔法数 代表私聊 + _, realUserID, err = idmap.RetrieveRowByIDv2Pro("690426430", submatches[1]) + } else { + realUserID, err = idmap.RetrieveRowByIDv2(submatches[1]) + } + if err != nil { + // 如果出错,也替换成相应的格式,但使用原始QQ号 + mylog.Printf("Error retrieving user ID: %v", err) + return "<@!" + submatches[1] + ">" + } + + // 在这里检查 GetRemoveBotAtGroup 和 realUserID 的长度 + if config.GetRemoveBotAtGroup() && len(realUserID) == 32 { + return "" + } + + return "<@!" + realUserID + ">" + } + return m + }) + return messageText +} + // 链接处理 func transformMessageTextUrl(messageText string, message callapi.ActionMessage, client callapi.Client, api openapi.OpenAPI, apiv2 openapi.OpenAPI) string { // 是否处理url From 13181759dbe85cad3f5a6acde0b2698d323aab55 Mon Sep 17 00:00:00 2001 From: cosmo Date: Thu, 4 Jul 2024 19:31:22 +0800 Subject: [PATCH 7/7] beta453 --- "docs/api\344\273\213\347\273\215.md" | 40 +++++ ...api\345\267\256\345\274\202-delete_msg.md" | 17 ++ ...7\346\241\243-markdown message segment.md" | 54 ++++++ ...1\243-markdown\345\256\232\344\271\211.md" | 167 ++++++++++++++++++ ...64\345\244\232\346\226\207\346\241\243.md" | 2 + ...7\260&\345\220\257\345\212\250gensokyo.md" | 56 ++++++ ...\351\242\235\345\244\226api-get_avatar.md" | 27 +++ readme.md | 2 + 8 files changed, 365 insertions(+) create mode 100644 "docs/api\344\273\213\347\273\215.md" create mode 100644 "docs/api\345\267\256\345\274\202-delete_msg.md" create mode 100644 "docs/\346\226\207\346\241\243-markdown message segment.md" create mode 100644 "docs/\346\226\207\346\241\243-markdown\345\256\232\344\271\211.md" create mode 100644 "docs/\346\233\264\345\244\232\346\226\207\346\241\243.md" create mode 100644 "docs/\351\242\235\345\244\226api-get_avatar.md" diff --git "a/docs/api\344\273\213\347\273\215.md" "b/docs/api\344\273\213\347\273\215.md" new file mode 100644 index 00000000..5f278dca --- /dev/null +++ "b/docs/api\344\273\213\347\273\215.md" @@ -0,0 +1,40 @@ +目前支持的API列表 + +具体api的定义请参考[onebot-11](https://github.com/botuniverse/onebot-11) + +### 支持的API列表 + +1. `/avatar` - avatar.go +2. `/delete_msg` - delete_msg.go +3. `/get_avatar` - get_avatar.go +4. `/get_friend_list` - get_friend_list.go +5. `/get_group_info` - get_group_info.go +6. `/get_group_list` - get_group_list.go +7. `/get_group_member_info` - get_group_member_info.go +8. `/get_group_member_list` - get_group_member_list.go +9. `/get_guild_channel_list` - get_guild_channel_list.go +10. `/get_guild_list` - get_guild_list.go +11. `/get_guild_service_profile` - get_guild_service_profile.go +12. `/get_login_info` - get_login_info.go +13. `/get_online_clients` - get_online_clients.go +14. `/get_status` - get_status.go +15. `/get_version_info` - get_version_info.go +16. `/handle_quick_operation` - handle_quick_operation.go +17. `/handle_quick_operation_async` - handle_quick_operation_async.go +18. `/mark_msg_as_read` - mark_msg_as_read.go +19. `/message_parser` - message_parser.go +20. `/put_interaction` - put_interaction.go +21. `/send_group_forward_msg` - send_group_forward_msg.go +22. `/send_group_msg` - send_group_msg.go +23. `/send_group_msg_async` - send_group_msg_async.go +24. `/send_group_msg_raw` - send_group_msg_raw.go +25. `/send_guild_channel_forum` - send_guild_channel_forum.go +26. `/send_guild_channel_msg` - send_guild_channel_msg.go +27. `/send_guild_private_msg` - send_guild_private_msg.go +28. `/send_msg` - send_msg.go +29. `/send_msg_async` - send_msg_async.go +30. `/send_private_msg` - send_private_msg.go +31. `/send_private_msg_async` - send_private_msg_async.go +32. `/send_private_msg_sse` - send_private_msg_sse.go +33. `/set_group_ban` - set_group_ban.go +34. `/set_group_whole_ban` - set_group_whole_ban.go \ No newline at end of file diff --git "a/docs/api\345\267\256\345\274\202-delete_msg.md" "b/docs/api\345\267\256\345\274\202-delete_msg.md" new file mode 100644 index 00000000..2bd6cd81 --- /dev/null +++ "b/docs/api\345\267\256\345\274\202-delete_msg.md" @@ -0,0 +1,17 @@ +# API: delete_msg + +撤回消息。 + +## 参数 + +| 字段名 | 数据类型 | 默认值 | 说明 | +|-------------|----------------|--------|-----------------------------------| +| message_id | number (int32) | - | 消息 ID | +| user_id | number | - | 对方 QQ 号(消息类型为 private 时需要) | +| group_id | number | - | 群号(消息类型为 group 时需要) | +| channel_id | number | - | 频道号(消息类型是 guild 时需要) | +| guild_id | number | - | 子频道号(消息类型是 guild_Private 时需要) | + +## 响应数据 + +无 \ No newline at end of file diff --git "a/docs/\346\226\207\346\241\243-markdown message segment.md" "b/docs/\346\226\207\346\241\243-markdown message segment.md" new file mode 100644 index 00000000..d03a2495 --- /dev/null +++ "b/docs/\346\226\207\346\241\243-markdown message segment.md" @@ -0,0 +1,54 @@ +```markdown +# Gensokyo Markdown Segment + +Gensokyo的Markdown Segment是对现有OneBot v11的扩展。 + +## Markdown卡片(文本形式) + +```json +{ + "type": "markdown", + "data": { + "data": "文本内容" + } +} +``` + +| 参数名 | 收 | 发 | 可能的值 | 说明 | +|----------|----|----|----------|-------------| +| data | ✓ | ✓ | - | md文本 | + +**文本内容为**: +- [链接](https://www.yuque.com/km57bt/hlhnxg/ddkv4a2lgcswitei) 中markdown的json字符串的base64(以base64://开头,文字处理为/u形式的unicode)或按以下规则处理后的,json实体化文本。 + +**转义**: +CQ 码由字符 [ 起始, 以 ] 结束, 并且以 , 分割各个参数。如果你的 CQ 码中, 参数值包括了这些字符, 那么它们应该被使用 HTML 特殊字符的编码方式进行转义。 + +字符 | 对应实体转义序列 +-----|------------------ +& | & +[ | [ +] | ] +, | , + +## Markdown卡片(object形式) + +```json +{ + "type": "markdown", + "data": { + "data": md object + } +} +``` + +| 参数名 | 收 | 发 | 可能的值 | 说明 | +|----------|----|----|----------|-------------| +| data | ✓ | ✓ | - | md object | + +**结构请参考**: +支持MessageSegment [链接](https://www.yuque.com/km57bt/hlhnxg/ddkv4a2lgcswitei) 与文本形式实际包含内容相同,但传参类型不同,不是string,而是你所组合的md卡片object(map)。 + +data下层应包含data(2层data),data.markdown,data.keyboard。 +同时与type同级的data字段是OneBot v11标准固定的,所以json结构会呈现data.data.markdown,data.data.keyboard双层结构。 +``` \ No newline at end of file diff --git "a/docs/\346\226\207\346\241\243-markdown\345\256\232\344\271\211.md" "b/docs/\346\226\207\346\241\243-markdown\345\256\232\344\271\211.md" new file mode 100644 index 00000000..c5eb6909 --- /dev/null +++ "b/docs/\346\226\207\346\241\243-markdown\345\256\232\344\271\211.md" @@ -0,0 +1,167 @@ +```markdown +## md cq码/segment格式 + +### CQ码格式 + +```markdown +[CQ:markdown,data=xxx] +``` + +推荐使用模板:[链接到模板](https://github.com/hoshinonyaruko/gensokyo-qqmd) + +- `data,xxx` 是经过base64编码的JSON数据,支持与其他CQ码拼接,可以组合成message segment形式。 + +官方文档:[开发者文档](https://bot.q.qq.com/wiki/develop) + +新文档:[API v2文档](https://bot.q.qq.com/wiki/develop/api-v2/) + +### 自定义md格式 + +```json +{ + "markdown": { + "content": "你好" + }, + "keyboard": { + "content": { + "rows": [ + { + "buttons": [ + { + "render_data": { + "label": "再来一张", + "visited_label": "正在绘图", + "style": 1 + }, + "action": { + "type": 2, + "permission": { + "type": 2, + "specify_role_ids": [ + "1", + "2", + "3" + ] + }, + "click_limit": 10, + "unsupport_tips": "编辑-兼容文本", + "data": "你好", + "at_bot_show_channel_list": false + } + } + ] + } + ] + } + }, + "msg_id": "123", + "timestamp": "123", + "msg_type": 2 +} +``` + +### 模板md格式 + +```json +{ + "markdown": { + "custom_template_id": "101993071_1658748972", + "params": [ + { + "key": "text", + "values": ["标题"] + }, + { + "key": "image", + "values": [ + "https://resource5-1255303497.cos.ap-guangzhou.myqcloud.com/abcmouse_word_watch/other/mkd_img.png" + ] + } + ] + }, + "keyboard": { + "content": { + "rows": [ + { + "buttons": [ + { + "render_data": { + "label": "再来一次", + "visited_label": "再来一次" + }, + "action": { + "type": 1, + "permission": { + "type": 1, + "specify_role_ids": [ + "1", + "2", + "3" + ] + }, + "click_limit": 10, + "unsupport_tips": "兼容文本", + "data": "data", + "at_bot_show_channel_list": true + } + } + ] + } + ] + } + } +} +``` + +### 按钮格式 + +```json +{ + "keyboard": { + "id": 1, + "rows": [ + { + "buttons": [ + { + "render_data": { + "label": "再来一次", + "visited_label": "再来一次" + }, + "action": { + "type": 1, + "permission": { + "type": 1, + "specify_role_ids": [ + "1", + "2", + "3" + ] + }, + "click_limit": 10, + "unsupport_tips": "兼容文本", + "data": "data", + "at_bot_show_channel_list": true + } + } + ] + } + ] + } +} +``` + +### 图文混排格式 + +```markdown +{{.text}}![{{.image_info}}]({{.image_url}}) +``` + +![{{.image_info}}]({{.image_url}}){{.text}} + +注意:在`{{}}`中不可以使用`![]()`这种Markdown格式的关键字。 + +![text #208px #320px](https://xxxxx.png) +``` + +详细文档请参考:[发消息含有消息按钮组件的消息](https://bot.q.qq.com/wiki/develop/api/openapi/message/post_keyboard_messages.html#%E5%8F%91%E9%80%81%E5%90%AB%E6%9C%89%E6%B6%88%E6%81%AF%E6%8C%89%E9%92%AE%E7%BB%84%E4%BB%B6%E7%9A%84%E6%B6%88%E6%81%AF) +``` \ No newline at end of file diff --git "a/docs/\346\233\264\345\244\232\346\226\207\346\241\243.md" "b/docs/\346\233\264\345\244\232\346\226\207\346\241\243.md" new file mode 100644 index 00000000..e149a183 --- /dev/null +++ "b/docs/\346\233\264\345\244\232\346\226\207\346\241\243.md" @@ -0,0 +1,2 @@ +文档陆续迁移中,更多文档可查看 +[yuque](https://www.yuque.com/km57bt/hlhnxg/mw7gm8dlpccd324e) \ No newline at end of file diff --git "a/docs/\350\265\267\346\255\245-\346\263\250\345\206\214QQ\345\274\200\346\224\276\345\271\263\345\217\260&\345\220\257\345\212\250gensokyo.md" "b/docs/\350\265\267\346\255\245-\346\263\250\345\206\214QQ\345\274\200\346\224\276\345\271\263\345\217\260&\345\220\257\345\212\250gensokyo.md" index e69de29b..edb128de 100644 --- "a/docs/\350\265\267\346\255\245-\346\263\250\345\206\214QQ\345\274\200\346\224\276\345\271\263\345\217\260&\345\220\257\345\212\250gensokyo.md" +++ "b/docs/\350\265\267\346\255\245-\346\263\250\345\206\214QQ\345\274\200\346\224\276\345\271\263\345\217\260&\345\220\257\345\212\250gensokyo.md" @@ -0,0 +1,56 @@ +```markdown +# 创建QQ机器人并配置 + +首先,您需要在 [QQ开放平台](https://q.qq.com/qqbot/) 注册一个开发者账号,确保使用您的大号QQ进行注册,而非小号。 + +## 注册步骤 + +1. 登录 QQ 开放平台,使用大号QQ注册账号。 +2. 注册完成后,进入开发者控制台。 + +## 创建机器人 + +根据 [图文版教程](https://www.yuque.com/km57bt/hlhnxg/hoxlh53gg11h7r3l) 中的指导操作,创建您的机器人,并进行必要的配置。 + +## 设置Intent + +根据您的频道类型选择合适的Intent设置: + +### 私域频道 + +```yaml +text_intent: + - DirectMessageHandler + - CreateMessageHandler + - InteractionHandler + - GroupATMessageEventHandler + - C2CMessageEventHandler + - GroupMsgRejectHandler + - GroupMsgReceiveHandler + - GroupAddRobotEventHandler + - GroupDelRobotEventHandler +``` + +### 公域频道 + +```yaml +text_intent: + - DirectMessageHandler + - ATMessageEventHandler + - InteractionHandler + - GroupATMessageEventHandler + - C2CMessageEventHandler + - GroupMsgRejectHandler + - GroupMsgReceiveHandler + - GroupAddRobotEventHandler + - GroupDelRobotEventHandler +``` + +确保按照上述格式将Intent配置正确,这将确保机器人能够正确地处理消息和事件。 + +## 连接nb2和koishi + +完成上述基础配置后,您可以继续学习如何使用nb2和koishi等应用程序来开发您的自定义插件。 + +现在,您已经完成了基础配置和必要的设置,可以开始进行进一步的开发和集成了。 +``` \ No newline at end of file diff --git "a/docs/\351\242\235\345\244\226api-get_avatar.md" "b/docs/\351\242\235\345\244\226api-get_avatar.md" new file mode 100644 index 00000000..768ee75e --- /dev/null +++ "b/docs/\351\242\235\345\244\226api-get_avatar.md" @@ -0,0 +1,27 @@ +```markdown +# API: get_avatar + +获取用户头像。 + +## 返回值 + +```go +type GetAvatarResponse struct { + Message string `json:"message"` + RetCode int `json:"retcode"` + Echo interface{} `json:"echo"` + UserID int64 `json:"user_id"` +} +``` + +## 所需字段 + +- **group_id**: 群号(当获取群成员头像时需要) +- **user_id**: 用户 QQ 号(当获取私信头像时需要) + +## CQcode + +CQ头像码格式.支持message segment式传参,将at segment类比修改为avatar即可. +[CQ:avatar,qq=123456] + +``` \ No newline at end of file diff --git a/readme.md b/readme.md index b77013a7..b525998d 100644 --- a/readme.md +++ b/readme.md @@ -50,6 +50,8 @@ _✨ 基于 [OneBot](https://github.com/howmanybots/onebot/blob/master/README.md ## 介绍 gensokyo兼容 [OneBot-v11](https://github.com/botuniverse/onebot-11) ,并在其基础上做了一些扩展,详情请看 OneBot 的文档。 +Gensokyo文档(施工中):[起步](/docs/起步-注册QQ开放平台&启动gensokyo.md) + 可将官方的websocket和api转换至onebotv11标准, 支持连接koishi,nonebot2,trss,zerobot,MiraiCQ,hoshino..