From 0a7dab7a6598f75fce8ceef1cd43c1ca0650e071 Mon Sep 17 00:00:00 2001 From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com> Date: Fri, 24 Nov 2023 15:48:32 +0800 Subject: [PATCH 1/5] beta55 (#169) --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 1f82886a..7e63e777 100644 --- a/readme.md +++ b/readme.md @@ -84,7 +84,7 @@ gensokyo兼容 [OneBot-v11](https://github.com/botuniverse/onebot-11) ,并在 - [x] 支持array和信息段 - [x] 支持全域,频道,频道私聊,群,群私聊 - [x] 完善的重连,健壮的连接能力. -- [x] 持续更新 +- [x] 持续更新~ ### 实现 From 4a5b50f8a2f4a0e108098a018f28290819711c64 Mon Sep 17 00:00:00 2001 From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com> Date: Sat, 25 Nov 2023 08:46:34 +0800 Subject: [PATCH 2/5] Beta55 (#170) * beta55 * beta55 --- webui/api.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/webui/api.go b/webui/api.go index e657ef93..fcf621af 100644 --- a/webui/api.go +++ b/webui/api.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "path/filepath" + "runtime" "strconv" "strings" "time" @@ -88,7 +89,10 @@ func CombinedMiddleware(api openapi.OpenAPI, apiV2 openapi.OpenAPI) gin.HandlerF } //进程监控 if c.Param("filepath") == "/api/status" && c.Request.Method == http.MethodGet { - handleSysInfo(c) + // 检查操作系统是否不为Android + if runtime.GOOS != "android" { + handleSysInfo(c) + } return } //更新当前选中机器人的配置并重启应用(保持地址不变) From 2e6db5d26aecb2dd820962e42b55b1f00e490064 Mon Sep 17 00:00:00 2001 From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com> Date: Sun, 26 Nov 2023 22:29:52 +0800 Subject: [PATCH 3/5] Beta56 (#175) * beta55 * beta55 * add idmaps pro * add idmaps pr2o * add idmaps pr3o --- Processor/ProcessC2CMessage.go | 45 ++- Processor/ProcessChannelDirectMessage.go | 95 ++++-- Processor/ProcessGroupMessage.go | 43 ++- Processor/ProcessGuildATMessage.go | 43 ++- Processor/ProcessGuildNormalMessage.go | 45 ++- Processor/Processor.go | 238 ++++++++++--- config/config.go | 13 + echo/echo.go | 12 + handlers/message_parser.go | 10 +- handlers/send_group_msg.go | 61 +++- handlers/send_guild_channel_msg.go | 6 +- handlers/send_msg.go | 149 ++++----- handlers/send_private_msg.go | 178 +++++----- idmap/service.go | 405 +++++++++++++++++++++++ server/getIDHandler.go | 86 +++++ template/config_template.go | 1 + template/config_template.yml | 1 + 17 files changed, 1138 insertions(+), 293 deletions(-) diff --git a/Processor/ProcessC2CMessage.go b/Processor/ProcessC2CMessage.go index 18f7fe2d..5a50a9c6 100644 --- a/Processor/ProcessC2CMessage.go +++ b/Processor/ProcessC2CMessage.go @@ -34,11 +34,25 @@ func (p *Processors) ProcessC2CMessage(data *dto.WSC2CMessageData) error { //转换appidstring AppIDString := strconv.FormatUint(p.Settings.AppID, 10) echostr := AppIDString + "_" + strconv.FormatInt(s, 10) - - //将真实id转为int userid64 - userid64, err := idmap.StoreIDv2(data.Author.ID) - if err != nil { - log.Fatalf("Error storing ID: %v", err) + var userid64 int64 + var err error + if config.GetIdmapPro() { + //将真实id转为int userid64 + _, userid64, err = idmap.StoreIDv2Pro("group_private", data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + //当参数不全 + _, _ = idmap.StoreIDv2(data.Author.ID) + if !config.GetHashIDValue() { + mylog.Fatalf("避坑日志:你开启了高级id转换,请设置hash_id为true,并且删除idmaps并重启") + } + } else { + //将真实id转为int userid64 + userid64, err = idmap.StoreIDv2(data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } } //收到私聊信息调用的具体还原步骤 @@ -123,10 +137,22 @@ func (p *Processors) ProcessC2CMessage(data *dto.WSC2CMessageData) error { echostr := AppIDString + "_" + strconv.FormatInt(s, 10) //把userid作为群号 //映射str的userid到int - userid64, err := idmap.StoreIDv2(data.Author.ID) - if err != nil { - mylog.Printf("Error storing ID: %v", err) - return nil + var userid64 int64 + var err error + if config.GetIdmapPro() { + //将真实id转为int userid64 + _, userid64, err = idmap.StoreIDv2Pro("group_private", data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + //当参数不全,降级时 + _, _ = idmap.StoreIDv2(data.Author.ID) + } else { + //将真实id转为int userid64 + userid64, err = idmap.StoreIDv2(data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } } //映射str的messageID到int messageID64, err := idmap.StoreIDv2(data.ID) @@ -180,6 +206,7 @@ func (p *Processors) ProcessC2CMessage(data *dto.WSC2CMessageData) error { echo.AddMsgType(AppIDString, s, "group_private") //为不支持双向echo的ob服务端映射 echo.AddMsgID(AppIDString, userid64, data.ID) + //映射类型 echo.AddMsgType(AppIDString, userid64, "group_private") //懒message_id池 echo.AddLazyMessageId(strconv.FormatInt(userid64, 10), data.ID, time.Now()) diff --git a/Processor/ProcessChannelDirectMessage.go b/Processor/ProcessChannelDirectMessage.go index 024f36f7..7369c650 100644 --- a/Processor/ProcessChannelDirectMessage.go +++ b/Processor/ProcessChannelDirectMessage.go @@ -37,20 +37,43 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) AppIDString := strconv.FormatUint(p.Settings.AppID, 10) echostr := AppIDString + "_" + strconv.FormatInt(s, 10) - //将真实id转为int userid64 - userid64, err := idmap.StoreIDv2(data.Author.ID) - if err != nil { - log.Fatalf("Error storing ID: %v", err) + var userid64 int64 + var ChannelID64 int64 + var err error + if config.GetIdmapPro() { + //将真实id转为int userid64 + _, _, err = idmap.StoreIDv2Pro(data.ChannelID, data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + //将真实id转为int userid64 + userid64, err = idmap.StoreIDv2(data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + ChannelID64, err = idmap.StoreIDv2(data.ChannelID) + if err != nil { + mylog.Printf("Error storing ID: %v", err) + return nil + } + if !config.GetHashIDValue() { + mylog.Fatalf("避坑日志:你开启了高级id转换,请设置hash_id为true,并且删除idmaps并重启") + } + } else { + //将真实id转为int userid64 + userid64, err = idmap.StoreIDv2(data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + //将channelid写入数据库,可取出guild_id + ChannelID64, err = idmap.StoreIDv2(data.ChannelID) + if err != nil { + mylog.Printf("Error storing ID: %v", err) + return nil + } } - //将真实id写入数据库,可取出ChannelID idmap.WriteConfigv2(data.Author.ID, "channel_id", data.ChannelID) - //将channelid写入数据库,可取出guild_id - ChannelID64, err := idmap.StoreIDv2(data.ChannelID) - if err != nil { - mylog.Printf("Error storing ID: %v", err) - return nil - } //转成int再互转 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "guild_id", data.GuildID) //直接储存 适用于私信场景私聊 @@ -210,10 +233,40 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) } else { //将频道信息转化为群信息(特殊需求情况下) //将channelid写入bolt,可取出guild_id - ChannelID64, err := idmap.StoreIDv2(data.ChannelID) - if err != nil { - mylog.Printf("Error storing ID: %v", err) - return nil + var userid64 int64 + var ChannelID64 int64 + var err error + if config.GetIdmapPro() { + //将真实id转为int userid64 + _, _, err = idmap.StoreIDv2Pro(data.ChannelID, data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + //将真实id转为int userid64 + userid64, err = idmap.StoreIDv2(data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + ChannelID64, err = idmap.StoreIDv2(data.ChannelID) + if err != nil { + mylog.Printf("Error storing ID: %v", err) + return nil + } + if !config.GetHashIDValue() { + mylog.Fatalf("避坑日志:你开启了高级id转换,请设置hash_id为true,并且删除idmaps并重启") + } + } else { + //将真实id转为int userid64 + userid64, err = idmap.StoreIDv2(data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + //将真实channelid和虚拟做映射 + ChannelID64, err = idmap.StoreIDv2(data.ChannelID) + if err != nil { + mylog.Printf("Error storing ID: %v", err) + return nil + } } //转成int再互转 适用于群场景私聊 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "guild_id", data.GuildID) @@ -225,16 +278,13 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) mylog.Printf("信息被自定义黑白名单拦截") return nil } + //框架内指令 + p.HandleFrameworkCommand(messageText, data, "guild_private") //转换appid AppIDString := strconv.FormatUint(p.Settings.AppID, 10) //构造echo echostr := AppIDString + "_" + strconv.FormatInt(s, 10) - //映射str的userid到int - userid64, err := idmap.StoreIDv2(data.Author.ID) - if err != nil { - mylog.Printf("Error storing ID: %v", err) - return nil - } + //userid := int(userid64) //映射str的messageID到int messageID64, err := idmap.StoreIDv2(data.ID) @@ -294,6 +344,9 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) echo.AddMsgID(AppIDString, userid64, data.ID) //为频道私聊转群聊映射 echo.AddMsgID(AppIDString, ChannelID64, data.ID) + //将当前的userid和groupid和msgid进行一个更稳妥的映射 + echo.AddMsgIDv2(AppIDString, ChannelID64, userid64, data.ID) + //映射类型 echo.AddMsgType(AppIDString, userid64, "guild_private") //储存当前群或频道号的类型 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "type", "guild_private") diff --git a/Processor/ProcessGroupMessage.go b/Processor/ProcessGroupMessage.go index b3d8deaf..7c12a759 100644 --- a/Processor/ProcessGroupMessage.go +++ b/Processor/ProcessGroupMessage.go @@ -38,17 +38,34 @@ func (p *Processors) ProcessGroupMessage(data *dto.WSGroupATMessageData) error { // 构造echo echostr := AppIDString + "_" + strconv.FormatInt(s, 10) - - // 映射str的GroupID到int - GroupID64, err := idmap.StoreIDv2(data.GroupID) - if err != nil { - return fmt.Errorf("failed to convert ChannelID to int: %v", err) - } - // 映射str的userid到int - userid64, err := idmap.StoreIDv2(data.Author.ID) - if err != nil { - mylog.Printf("Error storing ID: %v", err) - return nil + var userid64 int64 + var GroupID64 int64 + var err error + if config.GetIdmapPro() { + //将真实id转为int userid64 + GroupID64, userid64, err = idmap.StoreIDv2Pro(data.GroupID, data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + //当参数不全 + _, _ = idmap.StoreIDv2(data.GroupID) + _, _ = idmap.StoreIDv2(data.Author.ID) + if !config.GetHashIDValue() { + mylog.Fatalf("避坑日志:你开启了高级id转换,请设置hash_id为true,并且删除idmaps并重启") + } + } else { + // 映射str的GroupID到int + GroupID64, err = idmap.StoreIDv2(data.GroupID) + if err != nil { + mylog.Errorf("failed to convert ChannelID to int: %v", err) + return nil + } + // 映射str的userid到int + userid64, err = idmap.StoreIDv2(data.Author.ID) + if err != nil { + mylog.Printf("Error storing ID: %v", err) + return nil + } } //映射str的messageID到int messageID64, err := idmap.StoreIDv2(data.ID) @@ -109,9 +126,11 @@ func (p *Processors) ProcessGroupMessage(data *dto.WSGroupATMessageData) error { echo.AddMsgType(AppIDString, s, "group") //为不支持双向echo的ob服务端映射 echo.AddMsgID(AppIDString, GroupID64, data.ID) - echo.AddMsgType(AppIDString, GroupID64, "group") + //将当前的userid和groupid和msgid进行一个更稳妥的映射 + echo.AddMsgIDv2(AppIDString, GroupID64, userid64, data.ID) //储存当前群或频道号的类型 idmap.WriteConfigv2(fmt.Sprint(GroupID64), "type", "group") + //映射类型 echo.AddMsgType(AppIDString, GroupID64, "group") //懒message_id池 echo.AddLazyMessageId(strconv.FormatInt(GroupID64, 10), data.ID, time.Now()) diff --git a/Processor/ProcessGuildATMessage.go b/Processor/ProcessGuildATMessage.go index f88af083..52436c09 100644 --- a/Processor/ProcessGuildATMessage.go +++ b/Processor/ProcessGuildATMessage.go @@ -114,11 +114,34 @@ func (p *Processors) ProcessGuildATMessage(data *dto.WSATMessageData) error { //将频道转化为一个群 //获取s s := client.GetGlobalS() - //将channelid写入ini,可取出guild_id - ChannelID64, err := idmap.StoreIDv2(data.ChannelID) - if err != nil { - mylog.Printf("Error storing ID: %v", err) - return nil + var userid64 int64 + var ChannelID64 int64 + var err error + if config.GetIdmapPro() { + //将真实id转为int userid64 + ChannelID64, userid64, err = idmap.StoreIDv2Pro(data.ChannelID, data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + //当参数不全时 + _, _ = idmap.StoreIDv2(data.ChannelID) + _, _ = idmap.StoreIDv2(data.Author.ID) + if !config.GetHashIDValue() { + mylog.Fatalf("避坑日志:你开启了高级id转换,请设置hash_id为true,并且删除idmaps并重启") + } + } else { + //将channelid写入ini,可取出guild_id + ChannelID64, err = idmap.StoreIDv2(data.ChannelID) + if err != nil { + mylog.Printf("Error storing ID: %v", err) + return nil + } + //映射str的userid到int + userid64, err = idmap.StoreIDv2(data.Author.ID) + if err != nil { + mylog.Printf("Error storing ID: %v", err) + return nil + } } //转成int再互转 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "guild_id", data.GuildID) @@ -134,13 +157,6 @@ func (p *Processors) ProcessGuildATMessage(data *dto.WSATMessageData) error { AppIDString := strconv.FormatUint(p.Settings.AppID, 10) //构造echo echostr := AppIDString + "_" + strconv.FormatInt(s, 10) - //映射str的userid到int - userid64, err := idmap.StoreIDv2(data.Author.ID) - if err != nil { - mylog.Printf("Error storing ID: %v", err) - return nil - } - //userid := int(userid64) //映射str的messageID到int messageID64, err := idmap.StoreIDv2(data.ID) if err != nil { @@ -197,7 +213,8 @@ func (p *Processors) ProcessGuildATMessage(data *dto.WSATMessageData) error { echo.AddMsgType(AppIDString, s, "guild") //为不支持双向echo的ob服务端映射 echo.AddMsgID(AppIDString, ChannelID64, data.ID) - echo.AddMsgType(AppIDString, ChannelID64, "guild") + //将当前的userid和groupid和msgid进行一个更稳妥的映射 + echo.AddMsgIDv2(AppIDString, ChannelID64, userid64, data.ID) //储存当前群或频道号的类型 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "type", "guild") echo.AddMsgType(AppIDString, ChannelID64, "guild") diff --git a/Processor/ProcessGuildNormalMessage.go b/Processor/ProcessGuildNormalMessage.go index f68786cf..9cb174e6 100644 --- a/Processor/ProcessGuildNormalMessage.go +++ b/Processor/ProcessGuildNormalMessage.go @@ -96,6 +96,7 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error { echo.AddMsgType(AppIDString, s, "guild") //为不支持双向echo的ob11服务端映射 echo.AddMsgID(AppIDString, userid64, data.ID) + //映射类型 echo.AddMsgType(AppIDString, userid64, "guild") //储存当前群或频道号的类型 idmap.WriteConfigv2(data.ChannelID, "type", "guild") @@ -116,12 +117,36 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error { //将频道转化为一个群 //获取s s := client.GetGlobalS() - //将channelid写入ini,可取出guild_id - ChannelID64, err := idmap.StoreIDv2(data.ChannelID) - if err != nil { - mylog.Printf("Error storing ID: %v", err) - return nil + var userid64 int64 + var ChannelID64 int64 + var err error + if config.GetIdmapPro() { + //将真实id转为int userid64 + ChannelID64, userid64, err = idmap.StoreIDv2Pro(data.ChannelID, data.Author.ID) + if err != nil { + mylog.Fatalf("Error storing ID: %v", err) + } + //当参数不全时 + _, _ = idmap.StoreIDv2(data.ChannelID) + _, _ = idmap.StoreIDv2(data.Author.ID) + if !config.GetHashIDValue() { + mylog.Fatalf("避坑日志:你开启了高级id转换,请设置hash_id为true,并且删除idmaps并重启") + } + } else { + //将channelid写入ini,可取出guild_id + ChannelID64, err = idmap.StoreIDv2(data.ChannelID) + if err != nil { + mylog.Printf("Error storing ID: %v", err) + return nil + } + //映射str的userid到int + userid64, err = idmap.StoreIDv2(data.Author.ID) + if err != nil { + mylog.Printf("Error storing ID: %v", err) + return nil + } } + //转成int再互转 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "guild_id", data.GuildID) //转换at @@ -136,13 +161,6 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error { AppIDString := strconv.FormatUint(p.Settings.AppID, 10) //构造echo echostr := AppIDString + "_" + strconv.FormatInt(s, 10) - //映射str的userid到int - userid64, err := idmap.StoreIDv2(data.Author.ID) - if err != nil { - mylog.Printf("Error storing ID: %v", err) - return nil - } - //userid := int(userid64) //映射str的messageID到int messageID64, err := idmap.StoreIDv2(data.ID) if err != nil { @@ -199,7 +217,8 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error { echo.AddMsgType(AppIDString, s, "guild") //为不支持双向echo的ob服务端映射 echo.AddMsgID(AppIDString, ChannelID64, data.ID) - echo.AddMsgType(AppIDString, ChannelID64, "guild") + //将当前的userid和groupid和msgid进行一个更稳妥的映射 + echo.AddMsgIDv2(AppIDString, ChannelID64, userid64, data.ID) //储存当前群或频道号的类型 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "type", "guild") echo.AddMsgType(AppIDString, ChannelID64, "guild") diff --git a/Processor/Processor.go b/Processor/Processor.go index 142d44d7..c00cb0dc 100644 --- a/Processor/Processor.go +++ b/Processor/Processor.go @@ -3,6 +3,8 @@ package Processor import ( "context" + "crypto/rand" + "encoding/hex" "encoding/json" "errors" "fmt" @@ -259,8 +261,8 @@ func (p *Processors) HandleFrameworkCommand(messageText string, data interface{} // 去除字符串前后的空格 cleanedMessage = strings.TrimSpace(cleanedMessage) var err error - var now, new string - var realid string + var now, new, newpro1, newpro2 string + var realid, realid2 string switch v := data.(type) { case *dto.WSGroupATMessageData: realid = v.Author.ID @@ -273,13 +275,39 @@ func (p *Processors) HandleFrameworkCommand(messageText string, data interface{} case *dto.WSC2CMessageData: realid = v.Author.ID } + + switch v := data.(type) { + case *dto.WSGroupATMessageData: + realid2 = v.GroupID + case *dto.WSATMessageData: + realid2 = v.ChannelID + case *dto.WSMessageData: + realid2 = v.ChannelID + case *dto.WSDirectMessageData: + realid2 = v.ChannelID + case *dto.WSC2CMessageData: + realid2 = "group_private" + } + // 获取MasterID数组 masterIDs := config.GetMasterID() // 根据realid获取new now, new, err = idmap.RetrieveVirtualValuev2(realid) + if config.GetIdmapPro() { + newpro1, newpro2, err = idmap.RetrieveVirtualValuev2Pro(realid2, realid) + } // 检查真实值或虚拟值是否在数组中 - realValueIncluded := contains(masterIDs, realid) - virtualValueIncluded := contains(masterIDs, new) + var realValueIncluded, virtualValueIncluded bool + + // 如果 masterIDs 数组为空,则这两个值恒为 true + if len(masterIDs) == 0 { + realValueIncluded = true + virtualValueIncluded = true + } else { + // 否则,检查真实值或虚拟值是否在数组中 + realValueIncluded = contains(masterIDs, realid) + virtualValueIncluded = contains(masterIDs, new) + } // me指令处理逻辑 if strings.HasPrefix(cleanedMessage, config.GetMePrefix()) { @@ -288,56 +316,190 @@ func (p *Processors) HandleFrameworkCommand(messageText string, data interface{} SendMessage(err.Error(), data, Type, p.Api, p.Apiv2) return err } - // 发送成功信息 - SendMessage("目前状态:\n当前真实值 "+now+"\n当前虚拟值 "+new+"\n"+config.GetBindPrefix()+" 当前虚拟值"+" 目标虚拟值", data, Type, p.Api, p.Apiv2) + if config.GetIdmapPro() { + // 构造清晰的对应关系信息 + userMapping := fmt.Sprintf("当前真实值(用户)/当前虚拟值(用户) = [%s/%s]", realid, newpro2) + groupMapping := fmt.Sprintf("当前真实值(群/频道)/当前虚拟值(群/频道) = [%s/%s]", realid2, newpro1) + + // 构造 bind 指令的使用说明 + bindInstruction := fmt.Sprintf("bind 指令: %s 当前虚拟值(用户) 目标虚拟值(用户) [当前虚拟值(群/频道) 目标虚拟值(群/频道)]", config.GetBindPrefix()) + + // 发送整合后的消息 + 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) + } return nil } - if realValueIncluded || virtualValueIncluded { - // bind指令处理逻辑 - if strings.HasPrefix(cleanedMessage, config.GetBindPrefix()) { - // 分割指令以获取参数 - parts := strings.Fields(cleanedMessage) - if len(parts) != 3 { - mylog.Printf("bind指令参数错误\n正确的格式" + config.GetBindPrefix() + " 当前虚拟值 新虚拟值") - return nil - } - - // 将字符串转换为 int64 - oldRowValue, err := strconv.ParseInt(parts[1], 10, 64) + if realValueIncluded || virtualValueIncluded || isValidTemporaryCommand(strings.Fields(cleanedMessage)[0]) { + // 执行 bind 操作 + if config.GetIdmapPro() { + err := performBindOperationV2(cleanedMessage, data, Type, p.Api, p.Apiv2, newpro1) if err != nil { - return err + mylog.Printf("bind遇到错误:%v", err) } - - newRowValue, err := strconv.ParseInt(parts[2], 10, 64) + } else { + err := performBindOperation(cleanedMessage, data, Type, p.Api, p.Apiv2) if err != nil { - return err + mylog.Printf("bind遇到错误:%v", err) } + } + return nil + } else { + if strings.HasPrefix(cleanedMessage, config.GetBindPrefix()) { + // 生成临时指令 + tempCmd := handleNoPermission() + mylog.Printf("您没有权限,使用临时指令:%s 忽略权限检查,或将masterid设置为空数组", tempCmd) + SendMessage("您没有权限,请配置config.yml或查看日志,使用临时指令", data, Type, p.Api, p.Apiv2) + } + return nil + } +} - // 调用 UpdateVirtualValue - err = idmap.UpdateVirtualValuev2(oldRowValue, newRowValue) - if err != nil { - SendMessage(err.Error(), data, Type, p.Api, p.Apiv2) - return err - } - now, new, err := idmap.RetrieveRealValuev2(newRowValue) - if err != nil { - SendMessage(err.Error(), data, Type, p.Api, p.Apiv2) - } else { - SendMessage("绑定成功,目前状态:\n当前真实值 "+now+"\n当前虚拟值 "+new, data, Type, p.Api, p.Apiv2) - } +// 生成由两个英文字母构成的唯一临时指令 +func generateTemporaryCommand() (string, error) { + bytes := make([]byte, 1) // 生成1字节的随机数,足以表示2个十六进制字符 + if _, err := rand.Read(bytes); err != nil { + return "", err // 处理随机数生成错误 + } + command := hex.EncodeToString(bytes)[:2] // 将1字节转换为2个十六进制字符 + return command, nil +} + +// 生成并添加一个新的临时指令 +func handleNoPermission() string { + idmap.MutexT.Lock() + defer idmap.MutexT.Unlock() + + cmd, _ := generateTemporaryCommand() + idmap.TemporaryCommands = append(idmap.TemporaryCommands, cmd) + return cmd +} + +// 检查指令是否是有效的临时指令 +func isValidTemporaryCommand(cmd string) bool { + idmap.MutexT.Lock() + defer idmap.MutexT.Unlock() + for i, tempCmd := range idmap.TemporaryCommands { + if tempCmd == cmd { + // 删除已验证的临时指令 + idmap.TemporaryCommands = append(idmap.TemporaryCommands[:i], idmap.TemporaryCommands[i+1:]...) + return true } + } + return false +} +// 执行 bind 操作的逻辑 +func performBindOperation(cleanedMessage string, data interface{}, Type string, p openapi.OpenAPI, p2 openapi.OpenAPI) error { + // 分割指令以获取参数 + parts := strings.Fields(cleanedMessage) + if len(parts) != 3 { + mylog.Printf("bind指令参数错误\n正确的格式" + config.GetBindPrefix() + " 当前虚拟值 新虚拟值") return nil + } + + // 将字符串转换为 int64 + oldRowValue, err := strconv.ParseInt(parts[1], 10, 64) + if err != nil { + return err + } + + newRowValue, err := strconv.ParseInt(parts[2], 10, 64) + if err != nil { + return err + } + + // 调用 UpdateVirtualValue + err = idmap.UpdateVirtualValuev2(oldRowValue, newRowValue) + if err != nil { + SendMessage(err.Error(), data, Type, p, p2) + return err + } + now, new, err := idmap.RetrieveRealValuev2(newRowValue) + if err != nil { + SendMessage(err.Error(), data, Type, p, p2) } else { - if strings.HasPrefix(cleanedMessage, config.GetBindPrefix()) { - mylog.Printf("您没有权限,请设置master_id,发送/me 获取虚拟值或真实值填入其中") - SendMessage("您没有权限,请设置master_id,发送/me 获取虚拟值或真实值填入其中", data, Type, p.Api, p.Apiv2) - } + SendMessage("绑定成功,目前状态:\n当前真实值 "+now+"\n当前虚拟值 "+new, data, Type, p, p2) + } + + return nil +} + +func performBindOperationV2(cleanedMessage string, data interface{}, Type string, p openapi.OpenAPI, p2 openapi.OpenAPI, GroupVir string) error { + // 分割指令以获取参数 + parts := strings.Fields(cleanedMessage) + + // 检查参数数量 + if len(parts) < 3 || len(parts) > 5 { + mylog.Printf("bind指令参数错误\n正确的格式: " + config.GetBindPrefix() + " 当前虚拟值(用户) 新虚拟值(用户) [当前虚拟值(群) 新虚拟值(群)]") return nil } + + // 当前虚拟值 用户 + oldVirtualValue1, err := strconv.ParseInt(parts[1], 10, 64) + if err != nil { + return err + } + //新的虚拟值 用户 + newVirtualValue1, err := strconv.ParseInt(parts[2], 10, 64) + if err != nil { + return err + } + + // 设置默认值 + var oldRowValue, newRowValue int64 + + // 如果提供了第3个和第4个参数,则解析它们 + if len(parts) > 3 { + oldRowValue, err = parseOrDefault(parts[3], GroupVir) + if err != nil { + return err + } + + newRowValue, err = parseOrDefault(parts[4], GroupVir) + if err != nil { + return err + } + } else { + // 如果没有提供这些参数,则直接使用 GroupVir + oldRowValue, err = strconv.ParseInt(GroupVir, 10, 64) + if err != nil { + return err + } + newRowValue = oldRowValue // 使用相同的值 + } + + // 调用 UpdateVirtualValue + err = idmap.UpdateVirtualValuev2Pro(oldRowValue, newRowValue, oldVirtualValue1, newVirtualValue1) + if err != nil { + SendMessage(err.Error(), data, Type, p, p2) + return err + } + + now, new, err := idmap.RetrieveRealValuesv2Pro(newRowValue, newVirtualValue1) + if err != nil { + SendMessage(err.Error(), data, Type, p, p2) + } else { + newVirtualValue1Str := strconv.FormatInt(newRowValue, 10) + newVirtualValue2Str := strconv.FormatInt(newVirtualValue1, 10) + SendMessage("绑定成功,目前状态:\n当前真实值(群)"+now+"\n当前真实值(用户)"+new+"\n当前虚拟值(群)"+newVirtualValue1Str+"当前虚拟值(用户)"+newVirtualValue2Str, data, Type, p, p2) + } + + return nil +} + +// parseOrDefault 将字符串转换为int64,如果无法转换或为0,则使用默认值 +func parseOrDefault(s string, defaultValue string) (int64, error) { + value, err := strconv.ParseInt(s, 10, 64) + if err == nil && value != 0 { + return value, nil + } + return strconv.ParseInt(defaultValue, 10, 64) } // contains 检查数组中是否包含指定的字符串 diff --git a/config/config.go b/config/config.go index e2f7e369..bdd3d731 100644 --- a/config/config.go +++ b/config/config.go @@ -82,6 +82,7 @@ type Settings struct { UrlPicTransfer bool `yaml:"url_pic_transfer"` LotusPassword string `yaml:"lotus_password"` WsServerPath string `yaml:"ws_server_path"` + IdmapPro bool `yaml:"idmap_pro"` } // LoadConfig 从文件中加载配置并初始化单例配置 @@ -976,3 +977,15 @@ func GetWsServerPath() string { } return instance.Settings.WsServerPath } + +// 获取GetIdmapPro的值 +func GetIdmapPro() bool { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to GetIdmapPro value.") + return false + } + return instance.Settings.IdmapPro +} diff --git a/echo/echo.go b/echo/echo.go index 5c936b32..0563f86c 100644 --- a/echo/echo.go +++ b/echo/echo.go @@ -60,6 +60,10 @@ func (e *EchoMapping) GenerateKey(appid string, s int64) string { return appid + "_" + strconv.FormatInt(s, 10) } +func (e *EchoMapping) GenerateKeyv2(appid string, groupid int64, userid int64) string { + return appid + "_" + strconv.FormatInt(groupid, 10) + "_" + strconv.FormatInt(userid, 10) +} + // 添加echo对应的类型 func AddMsgType(appid string, s int64, msgType string) { key := globalEchoMapping.GenerateKey(appid, s) @@ -76,6 +80,14 @@ func AddMsgID(appid string, s int64, msgID string) { globalEchoMapping.msgIDMapping[key] = msgID } +// 添加group和userid对应的messageid +func AddMsgIDv2(appid string, groupid int64, userid int64, msgID string) { + key := globalEchoMapping.GenerateKeyv2(appid, groupid, userid) + globalEchoMapping.mu.Lock() + defer globalEchoMapping.mu.Unlock() + globalEchoMapping.msgIDMapping[key] = msgID +} + // 根据给定的key获取消息类型 func GetMsgTypeByKey(key string) string { globalEchoMapping.mu.Lock() diff --git a/handlers/message_parser.go b/handlers/message_parser.go index 8637047a..69867181 100644 --- a/handlers/message_parser.go +++ b/handlers/message_parser.go @@ -315,11 +315,19 @@ func RevertTransformedText(data interface{}, msgtype string, api openapi.OpenAPI if config.GetWhitePrefixMode() { // 获取白名单数组 whitePrefixes := config.GetWhitePrefixs() + // 加锁以安全地读取 TemporaryCommands + idmap.MutexT.Lock() + temporaryCommands := make([]string, len(idmap.TemporaryCommands)) + copy(temporaryCommands, idmap.TemporaryCommands) + idmap.MutexT.Unlock() + + // 合并白名单和临时指令 + allPrefixes := append(whitePrefixes, temporaryCommands...) // 默认设置为不匹配 matched := false // 遍历白名单数组,检查是否有匹配项 - for _, prefix := range whitePrefixes { + for _, prefix := range allPrefixes { if strings.HasPrefix(messageText, prefix) { // 找到匹配项,保留 messageText 并跳出循环 matched = true diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index ec5c290a..8e345a04 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -33,7 +33,6 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap // 当 message.Echo 是字符串类型时执行此块 msgType = echo.GetMsgTypeByKey(echoStr) } - //如果获取不到 就用user_id获取信息类型 if msgType == "" { msgType = GetMessageTypeByUserid(config.GetAppIDStr(), message.Params.UserID) @@ -85,15 +84,43 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap mylog.Println("echo取群组发信息对应的message_id:", messageID) } } - //通过bolt数据库还原真实的GroupID - originalGroupID, err := idmap.RetrieveRowByIDv2(message.Params.GroupID.(string)) - if err != nil { - mylog.Printf("Error retrieving original GroupID: %v", err) - return + var originalGroupID string + // 检查UserID是否为nil + if message.Params.UserID != nil && config.GetIdmapPro() { + // 如果UserID不是nil且配置为使用Pro版本,则调用RetrieveRowByIDv2Pro + originalGroupID, _, err = idmap.RetrieveRowByIDv2Pro(message.Params.GroupID.(string), message.Params.UserID.(string)) + if err != nil { + mylog.Printf("Error1 retrieving original GroupID: %v", err) + } + mylog.Printf("测试,通过Proid获取的originalGroupID:%v", originalGroupID) + if originalGroupID == "" { + originalGroupID, err = idmap.RetrieveRowByIDv2(message.Params.GroupID.(string)) + if err != nil { + mylog.Printf("Error2 retrieving original GroupID: %v", err) + return + } + } + } else { + // 如果UserID是nil或配置不使用Pro版本,则调用RetrieveRowByIDv2 + originalGroupID, err = idmap.RetrieveRowByIDv2(message.Params.GroupID.(string)) + if err != nil { + mylog.Printf("Error retrieving original GroupID: %v", err) + return + } } message.Params.GroupID = originalGroupID mylog.Println("群组发信息messageText:", messageText) //mylog.Println("foundItems:", foundItems) + if messageID == "" { + // 检查 UserID 是否为 nil + if message.Params.UserID != nil { + messageID = GetMessageIDByUseridAndGroupid(config.GetAppIDStr(), message.Params.UserID, message.Params.GroupID) + mylog.Println("通过GetMessageIDByUseridAndGroupid函数获取的message_id:", message.Params.GroupID, messageID) + } else { + // 如果 UserID 是 nil,可以在这里处理,例如记录日志或采取其他措施 + mylog.Println("UserID 为 nil,跳过 GetMessageIDByUseridAndGroupid 调用") + } + } // 如果messageID为空,通过函数获取 if messageID == "" { messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), message.Params.GroupID) @@ -255,8 +282,14 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap case "guild": //用GroupID给ChannelID赋值,因为我们是把频道虚拟成了群 message.Params.ChannelID = message.Params.GroupID.(string) - // 使用RetrieveRowByIDv2还原真实的ChannelID - RChannelID, err := idmap.RetrieveRowByIDv2(message.Params.ChannelID) + var RChannelID string + if message.Params.UserID != nil && config.GetIdmapPro() { + RChannelID, _, err = idmap.RetrieveRowByIDv2Pro(message.Params.ChannelID, message.Params.UserID.(string)) + mylog.Printf("测试,通过Proid获取的RChannelID:%v", RChannelID) + } else { + // 使用RetrieveRowByIDv2还原真实的ChannelID + RChannelID, err = idmap.RetrieveRowByIDv2(message.Params.ChannelID) + } if err != nil { mylog.Printf("error retrieving real RChannelID: %v", err) } @@ -266,9 +299,17 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap handleSendGuildChannelMsg(client, api, apiv2, message) case "guild_private": //用group_id还原出channelid 这是虚拟成群的私聊信息 + var RChannelID string + var Vuserid string message.Params.ChannelID = message.Params.GroupID.(string) - // 使用RetrieveRowByIDv2还原真实的ChannelID - RChannelID, err := idmap.RetrieveRowByIDv2(message.Params.ChannelID) + Vuserid = message.Params.UserID.(string) + if Vuserid != "" && config.GetIdmapPro() { + RChannelID, _, err = idmap.RetrieveRowByIDv2Pro(message.Params.ChannelID, Vuserid) + mylog.Printf("测试,通过Proid获取的RChannelID:%v", RChannelID) + } else { + // 使用RetrieveRowByIDv2还原真实的ChannelID + RChannelID, err = idmap.RetrieveRowByIDv2(message.Params.ChannelID) + } if err != nil { mylog.Printf("error retrieving real ChannelID: %v", err) } diff --git a/handlers/send_guild_channel_msg.go b/handlers/send_guild_channel_msg.go index 69b98e03..05796268 100644 --- a/handlers/send_guild_channel_msg.go +++ b/handlers/send_guild_channel_msg.go @@ -51,7 +51,6 @@ func handleSendGuildChannelMsg(client callapi.Client, api openapi.OpenAPI, apiv2 messageText, foundItems := parseMessageContent(params) channelID := params.ChannelID - //mylog.Printf("发送文本信息失败: %v,%v", channelID, channelID) // 使用 echo 获取消息ID var messageID string if config.GetLazyMessageId() { @@ -65,7 +64,6 @@ func handleSendGuildChannelMsg(client callapi.Client, api openapi.OpenAPI, apiv2 mylog.Println("echo取频道发信息对应的message_id:", messageID) } } - // 如果messageID为空,通过函数获取 if messageID == "" { messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), channelID) mylog.Println("通过GetMessageIDByUseridOrGroupid函数获取的message_id:", messageID) @@ -129,8 +127,10 @@ func handleSendGuildChannelMsg(client callapi.Client, api openapi.OpenAPI, apiv2 params := message.Params channelID := params.ChannelID guildID := params.GuildID + var RChannelID string + var err error // 使用RetrieveRowByIDv2还原真实的ChannelID - RChannelID, err := idmap.RetrieveRowByIDv2(channelID) + RChannelID, err = idmap.RetrieveRowByIDv2(channelID) if err != nil { mylog.Printf("error retrieving real UserID: %v", err) } diff --git a/handlers/send_msg.go b/handlers/send_msg.go index 22e54c68..27406ee9 100644 --- a/handlers/send_msg.go +++ b/handlers/send_msg.go @@ -1,7 +1,6 @@ package handlers import ( - "context" "fmt" "strconv" "time" @@ -11,7 +10,6 @@ import ( "github.com/hoshinonyaruko/gensokyo/echo" "github.com/hoshinonyaruko/gensokyo/idmap" "github.com/hoshinonyaruko/gensokyo/mylog" - "github.com/tencent-connect/botgo/dto" "github.com/tencent-connect/botgo/openapi" ) @@ -26,7 +24,6 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope // 当 message.Echo 是字符串类型时执行此块 msgType = echo.GetMsgTypeByKey(echoStr) } - //如果获取不到 就用group_id获取信息类型 if msgType == "" { appID := config.GetAppIDStr() @@ -72,10 +69,19 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope case "guild": //用GroupID给ChannelID赋值,因为我们是把频道虚拟成了群 message.Params.ChannelID = message.Params.GroupID.(string) - // 使用RetrieveRowByIDv2还原真实的ChannelID - RChannelID, err := idmap.RetrieveRowByIDv2(message.Params.ChannelID) - if err != nil { - mylog.Printf("error retrieving real RChannelID: %v", err) + var RChannelID string + if config.GetIdmapPro() { + // 使用RetrieveRowByIDv2还原真实的ChannelID + RChannelID, _, err = idmap.RetrieveRowByIDv2Pro(message.Params.ChannelID, message.Params.UserID.(string)) + if err != nil { + mylog.Printf("error retrieving real RChannelID: %v", err) + } + } else { + // 使用RetrieveRowByIDv2还原真实的ChannelID + RChannelID, err = idmap.RetrieveRowByIDv2(message.Params.ChannelID) + if err != nil { + mylog.Printf("error retrieving real RChannelID: %v", err) + } } message.Params.ChannelID = RChannelID handleSendGuildChannelMsg(client, api, apiv2, message) @@ -87,86 +93,7 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope handleSendGuildChannelPrivateMsg(client, api, apiv2, message, nil, nil) case "group_private": //私聊信息 - //还原真实的userid - UserID, err := idmap.RetrieveRowByIDv2(message.Params.UserID.(string)) - if err != nil { - mylog.Printf("Error reading config: %v", err) - return - } - - // 解析消息内容 - messageText, foundItems := parseMessageContent(message.Params) - - // 使用 echo 获取消息ID - var messageID string - if config.GetLazyMessageId() { - //由于实现了Params的自定义unmarshell 所以可以类型安全的断言为string - messageID = echo.GetLazyMessagesId(UserID) - mylog.Printf("GetLazyMessagesId: %v", messageID) - } - if messageID == "" { - if echoStr, ok := message.Echo.(string); ok { - messageID = echo.GetMsgIDByKey(echoStr) - mylog.Println("echo取私聊发信息对应的message_id:", messageID) - } - } - // 如果messageID为空,通过函数获取 - if messageID == "" { - messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), UserID) - mylog.Println("通过GetMessageIDByUserid函数获取的message_id:", messageID) - } - //开发环境用 - if config.GetDevMsgID() { - messageID = "1000" - } - mylog.Println("私聊发信息messageText:", messageText) - //mylog.Println("foundItems:", foundItems) - - // 优先发送文本信息 - if messageText != "" { - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - groupReply := generateGroupMessage(messageID, nil, messageText, msgseq+1) - - // 进行类型断言 - groupMessage, ok := groupReply.(*dto.MessageToCreate) - if !ok { - mylog.Println("Error: Expected MessageToCreate type.") - return - } - - groupMessage.Timestamp = time.Now().Unix() // 设置时间戳 - _, err = apiv2.PostC2CMessage(context.TODO(), UserID, groupMessage) - if err != nil { - mylog.Printf("发送文本私聊信息失败: %v", err) - } - //发送成功回执 - SendResponse(client, err, &message) - } - - // 遍历foundItems并发送每种信息 - for key, urls := range foundItems { - for _, url := range urls { - var singleItem = make(map[string][]string) - singleItem[key] = []string{url} // 创建一个只包含一个 URL 的 singleItem - msgseq := echo.GetMappingSeq(messageID) - echo.AddMappingSeq(messageID, msgseq+1) - 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) - if err != nil { - mylog.Printf("发送 %s 私聊信息失败: %v", key, err) - } - //发送成功回执 - SendResponse(client, err, &message) - } - } + handleSendPrivateMsg(client, api, apiv2, message) default: mylog.Printf("1Unknown message type: %s", msgType) } @@ -212,3 +139,51 @@ func GetMessageIDByUseridOrGroupid(appID string, userID interface{}) string { key := appID + "_" + fmt.Sprint(userid64) return echo.GetMsgIDByKey(key) } + +// 通过user_id获取messageID +func GetMessageIDByUseridAndGroupid(appID string, userID interface{}, groupID interface{}) string { + // 从appID和userID生成key + var userIDStr string + switch u := userID.(type) { + case int: + userIDStr = strconv.Itoa(u) + case int64: + userIDStr = strconv.FormatInt(u, 10) + case float64: + userIDStr = strconv.FormatFloat(u, 'f', 0, 64) + case string: + userIDStr = u + default: + // 可能需要处理其他类型或报错 + return "" + } + // 从appID和userID生成key + var GroupIDStr string + switch u := groupID.(type) { + case int: + GroupIDStr = strconv.Itoa(u) + case int64: + GroupIDStr = strconv.FormatInt(u, 10) + case float64: + GroupIDStr = strconv.FormatFloat(u, 'f', 0, 64) + case string: + GroupIDStr = u + default: + // 可能需要处理其他类型或报错 + return "" + } + //将真实id转为int + userid64, err := idmap.StoreIDv2(userIDStr) + if err != nil { + mylog.Fatalf("Error storing ID 241: %v", err) + return "" + } + //将真实id转为int + groupid64, err := idmap.StoreIDv2(GroupIDStr) + if err != nil { + mylog.Fatalf("Error storing ID 256: %v", err) + return "" + } + key := appID + "_" + fmt.Sprint(userid64) + "_" + fmt.Sprint(groupid64) + return echo.GetMsgIDByKey(key) +} diff --git a/handlers/send_private_msg.go b/handlers/send_private_msg.go index cd74034a..64ba1c97 100644 --- a/handlers/send_private_msg.go +++ b/handlers/send_private_msg.go @@ -69,11 +69,22 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open switch msgType { case "group_private": //私聊信息 - //还原真实的userid - UserID, err := idmap.RetrieveRowByIDv2(message.Params.UserID.(string)) - if err != nil { - mylog.Printf("Error reading config: %v", err) - return + var UserID string + if config.GetIdmapPro() { + //还原真实的userid + _, UserID, err = idmap.RetrieveRowByIDv2Pro("group_private", message.Params.UserID.(string)) + if err != nil { + mylog.Printf("Error reading config: %v", err) + return + } + mylog.Printf("测试,通过Proid获取的UserID:%v", UserID) + } else { + //还原真实的userid + UserID, err = idmap.RetrieveRowByIDv2(message.Params.UserID.(string)) + if err != nil { + mylog.Printf("Error reading config: %v", err) + return + } } // 解析消息内容 @@ -131,51 +142,22 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open for key, urls := range foundItems { for _, url := range urls { var singleItem = make(map[string][]string) - singleItem[key] = []string{url} // 创建只包含一个 URL 的 singleItem - - // 生成消息 + singleItem[key] = []string{url} // 创建一个只包含一个 URL 的 singleItem msgseq := echo.GetMappingSeq(messageID) echo.AddMappingSeq(messageID, msgseq+1) - //时间限制 - lastSendTimestamp := echo.GetMappingFileTimeLimit(messageID) - if lastSendTimestamp == 0 { - lastSendTimestamp = echo.GetFileTimeLimit() - } - now := time.Now() - millis := now.UnixMilli() - diff := millis - lastSendTimestamp groupReply := generateGroupMessage(messageID, singleItem, "", msgseq+1) // 进行类型断言 richMediaMessage, ok := groupReply.(*dto.RichMediaMessage) if !ok { mylog.Printf("Error: Expected RichMediaMessage type for key %s.", key) - continue // 如果断言失败,跳过当前 url + continue // 跳过这个项,继续下一个 } - richMediaMessageCopy := *richMediaMessage // 创建 richMediaMessage 的副本 - mylog.Printf("上次发图(ms): %+v\n", diff) - if diff < 1000 { - waitDuration := time.Duration(1200-diff) * time.Millisecond - mylog.Printf("等待 %v...\n", waitDuration) - time.AfterFunc(waitDuration, func() { - mylog.Println("延迟完成") - _, err := apiv2.PostC2CMessage(context.TODO(), UserID, richMediaMessageCopy) - echo.AddMappingFileTimeLimit(messageID, millis) - echo.AddFileTimeLimit(millis) - if err != nil { - mylog.Printf("发送 %s 私聊信息失败: %v", key, err) - } - }) - } else { // 发送消息 - _, err := apiv2.PostC2CMessage(context.TODO(), UserID, richMediaMessage) - echo.AddMappingFileTimeLimit(messageID, millis) - echo.AddFileTimeLimit(millis) - if err != nil { - mylog.Printf("发送 %s 私聊信息失败: %v", key, err) - } + _, err = apiv2.PostC2CMessage(context.TODO(), UserID, richMediaMessage) + if err != nil { + mylog.Printf("发送 %s 私聊信息失败: %v", key, err) } - - // 发送成功回执 + //发送成功回执 SendResponse(client, err, &message) } } @@ -208,33 +190,15 @@ func handleSendGuildChannelPrivateMsg(client callapi.Client, api openapi.OpenAPI var guildID, channelID string var err error + var UserID string GroupID := message.Params.GroupID.(string) + RawUserID := message.Params.UserID.(string) if optionalGuildID != nil && optionalChannelID != nil { guildID = *optionalGuildID channelID = *optionalChannelID - } else { - //频道私信,虚拟成群 通过仅有的group来还原频道私信需要的guildid channelID - if GroupID != "" { - guildID, err = idmap.ReadConfigv2(GroupID, "guild_id") - if err != nil { - mylog.Printf("根据GroupID获取guild_id失败: %v", err) - return - } - channelID, err = idmap.RetrieveRowByIDv2(GroupID) - if err != nil { - mylog.Printf("根据GroupID获取channelID失败: %v", err) - return - } - } else { //默认私信场景 通过仅有的userid来还原频道私信需要的guildid channelID - guildID, channelID, err = getGuildIDFromMessage(message) - if err != nil { - mylog.Printf("获取 guild_id 和 channel_id 出错: %v", err) - return - } - } } - RawUserID := message.Params.UserID.(string) + // 使用 echo 获取消息ID var messageID string if config.GetLazyMessageId() { @@ -249,31 +213,72 @@ func handleSendGuildChannelPrivateMsg(client callapi.Client, api openapi.OpenAPI } } mylog.Println("私聊信息messageText:", messageText) - if RawUserID != "" { //还原真实的userid todo 太绕了 要精简下逻辑 - UserID, err := idmap.RetrieveRowByIDv2(RawUserID) - if err != nil { - mylog.Printf("Error reading config: %v", err) - return - } - // 如果messageID为空,通过函数获取 - if messageID == "" { - messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), UserID) - mylog.Println("通过GetMessageIDByUserid函数获取的message_id:", messageID) + //获取guild和channelid和message id流程(来个大佬简化下) + if RawUserID != "" { + if guildID == "" && channelID == "" { + //频道私信 转 私信 通过userid(author_id)来还原频道私信需要的guildid channelID + guildID, channelID, err = getGuildIDFromMessage(message) + if err != nil { + mylog.Printf("获取 guild_id 和 channel_id 出错: %v", err) + return + } + //频道私信 转 私信 + if GroupID != "" && config.GetIdmapPro() { + _, UserID, err = idmap.RetrieveRowByIDv2Pro(GroupID, RawUserID) + if err != nil { + mylog.Printf("Error reading config: %v", err) + return + } + mylog.Printf("测试,通过Proid获取的UserID:%v", UserID) + } else { + UserID, err = idmap.RetrieveRowByIDv2(RawUserID) + if err != nil { + mylog.Printf("Error reading config: %v", err) + return + } + } + // 如果messageID为空,通过函数获取 + if messageID == "" { + messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), UserID) + mylog.Println("通过GetMessageIDByUserid函数获取的message_id:", messageID) + } } } else { - //通过bolt数据库还原真实的GroupID - originalGroupID, err := idmap.RetrieveRowByIDv2(message.Params.GroupID.(string)) - if err != nil { - mylog.Printf("Error retrieving original GroupID: %v", err) - return - } - message.Params.GroupID = originalGroupID - mylog.Println("群组(私信虚拟成的)发信息messageText:", messageText) - //mylog.Println("foundItems:", foundItems) - // 如果messageID为空,通过函数获取 - if messageID == "" { - messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), message.Params.GroupID) - mylog.Println("通过GetMessageIDByUseridOrGroupid函数获取的message_id:", message.Params.GroupID, messageID) + if guildID == "" && channelID == "" { + //频道私信 转 群聊 通过groupid(author_id)来还原频道私信需要的guildid channelID + guildID, err = idmap.ReadConfigv2(GroupID, "guild_id") + if err != nil { + mylog.Printf("根据GroupID获取guild_id失败: %v", err) + return + } + channelID, err = idmap.RetrieveRowByIDv2(GroupID) + if err != nil { + mylog.Printf("根据GroupID获取channelID失败: %v", err) + return + } + //频道私信 转 群聊 获取id + var originalGroupID string + if config.GetIdmapPro() { + _, originalGroupID, err = idmap.RetrieveRowByIDv2Pro(channelID, GroupID) + if err != nil { + mylog.Printf("Error retrieving original GroupID: %v", err) + return + } + mylog.Printf("测试,通过Proid获取的originalGroupID:%v", originalGroupID) + } else { + originalGroupID, err = idmap.RetrieveRowByIDv2(message.Params.GroupID.(string)) + if err != nil { + mylog.Printf("Error retrieving original GroupID: %v", err) + return + } + } + mylog.Println("群组(私信虚拟成的)发信息messageText:", messageText) + //mylog.Println("foundItems:", foundItems) + // 如果messageID为空,通过函数获取 + if messageID == "" { + messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), originalGroupID) + mylog.Println("通过GetMessageIDByUseridOrGroupid函数获取的message_id:", originalGroupID, messageID) + } } } //开发环境用 @@ -352,9 +357,10 @@ func getGuildIDFromMessage(message callapi.ActionMessage) (string, string, error default: return "", "", fmt.Errorf("unexpected type for UserID: %T", v) // 使用%T来打印具体的类型 } - + var realUserID string + var err error // 使用RetrieveRowByIDv2还原真实的UserID - realUserID, err := idmap.RetrieveRowByIDv2(userID) + realUserID, err = idmap.RetrieveRowByIDv2(userID) if err != nil { return "", "", fmt.Errorf("error retrieving real UserID: %v", err) } diff --git a/idmap/service.go b/idmap/service.go index cb18cf96..fa3f4545 100644 --- a/idmap/service.go +++ b/idmap/service.go @@ -13,12 +13,20 @@ import ( "net/url" "strconv" "strings" + "sync" "github.com/boltdb/bolt" "github.com/hoshinonyaruko/gensokyo/config" "github.com/hoshinonyaruko/gensokyo/mylog" ) +var ( + // 用于存储临时指令的全局变量 + TemporaryCommands []string + // 用于保证线程安全的互斥锁 + MutexT sync.Mutex +) + const ( DBName = "idmap.db" BucketName = "ids" @@ -143,6 +151,52 @@ func StoreID(id string) (int64, error) { return newRow, err } +// 群号 然后 用户号 +func StoreIDPro(id string, subid string) (int64, int64, error) { + var newRowID, newSubRowID int64 + var err error + + err = db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(BucketName)) + + // 生成正向键 + forwardKey := fmt.Sprintf("%s:%s", id, subid) + + // 检查正向键是否已经存在 + existingForwardValue := b.Get([]byte(forwardKey)) + if existingForwardValue != nil { + // 解析已存在的值 + fmt.Sscanf(string(existingForwardValue), "%d:%d", &newRowID, &newSubRowID) + return nil + } + + // 生成新的ID和SubID + newRowID, err = generateRowID(id, 9) // 使用generateRowID来生成 + if err != nil { + return err + } + + newSubRowID, err = generateRowID(subid, 9) // 同样的方法生成SubID + if err != nil { + return err + } + //反向键 + reverseKey := fmt.Sprintf("%d:%d", newRowID, newSubRowID) + //正向值 + forwardValue := fmt.Sprintf("%d:%d", newRowID, newSubRowID) + //反向值 + reverseValue := fmt.Sprintf("%s:%s", id, subid) + + // 存储正向键和反向键 + b.Put([]byte(forwardKey), []byte(forwardValue)) + b.Put([]byte(reverseKey), []byte(reverseValue)) + + return nil + }) + + return newRowID, newSubRowID, err +} + // StoreIDv2 根据a储存b func StoreIDv2(id string) (int64, error) { if config.GetLotusValue() { @@ -185,6 +239,53 @@ func StoreIDv2(id string) (int64, error) { return StoreID(id) } +// 群号 然后 用户号 +func StoreIDv2Pro(id string, subid string) (int64, int64, error) { + if config.GetLotusValue() { + // 使用网络请求方式 + serverDir := config.GetServer_dir() + portValue := config.GetPortValue() + + // 根据portValue确定协议 + protocol := "http" + if portValue == "443" { + protocol = "https" + } + + // 构建请求URL + url := fmt.Sprintf("%s://%s:%s/getid?type=8&id=%s&subid=%s", protocol, serverDir, portValue, id, subid) + resp, err := http.Get(url) + if err != nil { + return 0, 0, fmt.Errorf("failed to send request: %v", err) + } + defer resp.Body.Close() + + // 解析响应 + var response map[string]interface{} + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + return 0, 0, fmt.Errorf("failed to decode response: %v", err) + } + if resp.StatusCode != http.StatusOK { + return 0, 0, fmt.Errorf("error response from server: %s", response["error"]) + } + + newRowValue, ok := response["row"].(float64) + if !ok { + return 0, 0, fmt.Errorf("invalid response format for row") + } + + newSubRowValue, ok := response["subRow"].(float64) + if !ok { + return 0, 0, fmt.Errorf("invalid response format for subRow") + } + + return int64(newRowValue), int64(newSubRowValue), nil + } + + // 如果lotus为假,调用本地StoreIDPro + return StoreIDPro(id, subid) +} + // 根据b得到a func RetrieveRowByID(rowid string) (string, error) { var id string @@ -204,6 +305,81 @@ func RetrieveRowByID(rowid string) (string, error) { return id, err } +// 群号 然后 用户号 +func RetrieveRowByIDv2Pro(newRowID string, newSubRowID string) (string, string, error) { + if config.GetLotusValue() { + // 使用网络请求方式 + serverDir := config.GetServer_dir() + portValue := config.GetPortValue() + + // 根据portValue确定协议 + protocol := "http" + if portValue == "443" { + protocol = "https" + } + + // 构建请求URL + url := fmt.Sprintf("%s://%s:%s/getid?type=9&id=%s&subid=%s", protocol, serverDir, portValue, newRowID, newSubRowID) + resp, err := http.Get(url) + if err != nil { + return "", "", fmt.Errorf("failed to send request: %v", err) + } + defer resp.Body.Close() + + // 解析响应 + var response map[string]interface{} + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + return "", "", fmt.Errorf("failed to decode response: %v", err) + } + if resp.StatusCode != http.StatusOK { + return "", "", fmt.Errorf("error response from server: %s", response["error"]) + } + + id, ok := response["id"].(string) + if !ok { + return "", "", fmt.Errorf("invalid response format for id") + } + + subid, ok := response["subid"].(string) + if !ok { + return "", "", fmt.Errorf("invalid response format for subid") + } + + return id, subid, nil + } + + // 如果lotus为假,调用本地数据库 + return RetrieveRowByIDPro(newRowID, newSubRowID) +} + +// 群号 还有用户号 +func RetrieveRowByIDPro(newRowID, newSubRowID string) (string, string, error) { + var id, subid string + + err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(BucketName)) + + // 根据新的行号和子行号检索ID和SubID + reverseKey := fmt.Sprintf("%s:%s", newRowID, newSubRowID) + reverseValueBytes := b.Get([]byte(reverseKey)) + if reverseValueBytes == nil { + return ErrKeyNotFound + } + + reverseValue := string(reverseValueBytes) + parts := strings.Split(reverseValue, ":") + if len(parts) != 2 { + return fmt.Errorf("invalid format for reverse key value") + } + + id, subid = parts[0], parts[1] + + return nil + }) + + return id, subid, err +} + // RetrieveRowByIDv2 根据b得到a func RetrieveRowByIDv2(rowid string) (string, error) { // 根据portValue确定协议 @@ -472,6 +648,7 @@ func RetrieveVirtualValue(realValue string) (string, string, error) { return realValue, fmt.Sprintf("%d", virtualValue), nil } +// 更新真实值对应的虚拟值 func UpdateVirtualValuev2(oldRowValue, newRowValue int64) error { if config.GetLotusValue() { // 构建请求URL @@ -498,6 +675,7 @@ func UpdateVirtualValuev2(oldRowValue, newRowValue int64) error { return UpdateVirtualValue(oldRowValue, newRowValue) } +// RetrieveRealValuev2 根据虚拟值获取真实值 func RetrieveRealValuev2(virtualValue int64) (string, string, error) { if config.GetLotusValue() { serverDir := config.GetServer_dir() @@ -573,3 +751,230 @@ func RetrieveVirtualValuev2(realValue string) (string, string, error) { // 如果lotus为假,就保持原来的RetrieveVirtualValue的方法 return RetrieveVirtualValue(realValue) } + +// 根据2个真实值 获取2个虚拟值 群号 然后 用户号 +func RetrieveVirtualValuev2Pro(realValue string, realValueSub string) (string, string, error) { + if config.GetLotusValue() { + // 使用网络请求方式 + serverDir := config.GetServer_dir() + portValue := config.GetPortValue() + + // 根据portValue确定协议 + protocol := "http" + if portValue == "443" { + protocol = "https" + } + + // 构建请求URL + url := fmt.Sprintf("%s://%s:%s/getid?type=9&id=%s&subid=%s", protocol, serverDir, portValue, realValue, realValueSub) + resp, err := http.Get(url) + if err != nil { + return "", "", fmt.Errorf("failed to send request: %v", err) + } + defer resp.Body.Close() + + // 解析响应 + var response map[string]interface{} + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + return "", "", fmt.Errorf("failed to decode response: %v", err) + } + if resp.StatusCode != http.StatusOK { + return "", "", fmt.Errorf("error response from server: %s", response["error"]) + } + + firstValue, ok := response["firstValue"].(string) + if !ok { + return "", "", fmt.Errorf("invalid response format for first value") + } + + secondValue, ok := response["secondValue"].(string) + if !ok { + return "", "", fmt.Errorf("invalid response format for second value") + } + + return firstValue, secondValue, nil + } + + // 如果lotus为假,调用本地RetrieveVirtualValuePro + return RetrieveVirtualValuePro(realValue, realValueSub) +} + +// 根据2个真实值 获取2个虚拟值 群号 然后 用户号 +func RetrieveVirtualValuePro(realValue string, realValueSub string) (string, string, error) { + var newRowID, newSubRowID string + + err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(BucketName)) + + // 构建正向键 + forwardKey := fmt.Sprintf("%s:%s", realValue, realValueSub) + + // 从数据库检索正向键对应的值 + forwardValueBytes := b.Get([]byte(forwardKey)) + if forwardValueBytes == nil { + return ErrKeyNotFound + } + + forwardValue := string(forwardValueBytes) + parts := strings.Split(forwardValue, ":") + if len(parts) != 2 { + return fmt.Errorf("invalid format for forward key value") + } + + newRowID, newSubRowID = parts[0], parts[1] + + return nil + }) + + if err != nil { + return "", "", err + } + + return newRowID, newSubRowID, nil +} + +// RetrieveRealValuePro 根据两个虚拟值获取相应的两个真实值 群号 然后 用户号 +func RetrieveRealValuePro(virtualValue1, virtualValue2 int64) (string, string, error) { + var realValue1, realValue2 string + + err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(BucketName)) + + // 根据两个虚拟值构造键 + compositeKey := fmt.Sprintf("%d:%d", virtualValue1, virtualValue2) + compositeValueBytes := b.Get([]byte(compositeKey)) + if compositeValueBytes == nil { + return fmt.Errorf("no real values found for virtual values: %d, %d", virtualValue1, virtualValue2) + } + + // 解析获取到的真实值 + compositeValue := string(compositeValueBytes) + parts := strings.Split(compositeValue, ":") + if len(parts) != 2 { + return fmt.Errorf("invalid format for composite key value: %s", compositeValue) + } + + realValue1, realValue2 = parts[0], parts[1] + + return nil + }) + + if err != nil { + return "", "", err + } + + return realValue1, realValue2, nil +} + +// RetrieveRealValuesv2Pro 根据两个虚拟值获取两个真实值 群号 然后 用户号 +func RetrieveRealValuesv2Pro(virtualValue int64, virtualValueSub int64) (string, string, error) { + if config.GetLotusValue() { + // 使用网络请求方式 + serverDir := config.GetServer_dir() + portValue := config.GetPortValue() + + // 根据portValue确定协议 + protocol := "http" + if portValue == "443" { + protocol = "https" + } + + // 构建请求URL + url := fmt.Sprintf("%s://%s:%s/getrealvalues?type=11&id=%d&subid=%d", protocol, serverDir, portValue, virtualValue, virtualValueSub) + resp, err := http.Get(url) + if err != nil { + return "", "", fmt.Errorf("failed to send request: %v", err) + } + defer resp.Body.Close() + + // 解析响应 + var response map[string]interface{} + if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { + return "", "", fmt.Errorf("failed to decode response: %v", err) + } + if resp.StatusCode != http.StatusOK { + return "", "", fmt.Errorf("error response from server: %s", response["error"]) + } + + firstRealValue, ok := response["firstRealValue"].(string) + if !ok { + return "", "", fmt.Errorf("invalid response format for first real value") + } + + secondRealValue, ok := response["secondRealValue"].(string) + if !ok { + return "", "", fmt.Errorf("invalid response format for second real value") + } + + return firstRealValue, secondRealValue, nil + } + + // 如果lotus为假,调用本地函数 + return RetrieveRealValuePro(virtualValue, virtualValueSub) +} + +// UpdateVirtualValuePro 更新一对旧虚拟值到新虚拟值的映射 旧群号 新群号 旧用户 新用户 +func UpdateVirtualValuePro(oldVirtualValue1, newVirtualValue1, oldVirtualValue2, newVirtualValue2 int64) error { + return db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(BucketName)) + // 构造旧和新的复合键 + oldCompositeKey := fmt.Sprintf("%d:%d", oldVirtualValue1, oldVirtualValue2) + newCompositeKey := fmt.Sprintf("%d:%d", newVirtualValue1, newVirtualValue2) + // 检查旧复合键是否存在 + compositeValueBytes := b.Get([]byte(oldCompositeKey)) + if compositeValueBytes == nil { + return fmt.Errorf("不存在的复合虚拟值:%d-%d", oldVirtualValue1, oldVirtualValue2) + } + // 检查新复合键是否已经存在 + if b.Get([]byte(newCompositeKey)) != nil { + return fmt.Errorf("该复合虚拟值已存在:%d-%d", newVirtualValue1, newVirtualValue2) + } + // 删除旧的复合键和正向键 + if err := b.Delete([]byte(oldCompositeKey)); err != nil { + return err + } + if err := b.Delete(compositeValueBytes); err != nil { + return err + } + // 反向键 + if err := b.Put([]byte(newCompositeKey), []byte(compositeValueBytes)); err != nil { + return err + } + // 正向键 + if err := b.Put(compositeValueBytes, []byte(newCompositeKey)); err != nil { + return err + } + + return nil + }) +} + +// UpdateVirtualValuev2Pro 根据配置更新两对虚拟值 旧群 新群 旧用户 新用户 +func UpdateVirtualValuev2Pro(oldVirtualValue1, newVirtualValue1, oldVirtualValue2, newVirtualValue2 int64) error { + if config.GetLotusValue() { + // 构建请求URL + serverDir := config.GetServer_dir() + portValue := config.GetPortValue() + protocol := "http" + if portValue == "443" { + protocol = "https" + } + + url := fmt.Sprintf("%s://%s:%s/updatevalues?type=12&oldVirtualValue1=%d&newVirtualValue1=%d&oldVirtualValue2=%d&newVirtualValue2=%d", + protocol, serverDir, portValue, oldVirtualValue1, newVirtualValue1, oldVirtualValue2, newVirtualValue2) + + resp, err := http.Get(url) + if err != nil { + return fmt.Errorf("failed to send request: %v", err) + } + defer resp.Body.Close() + + // 检查响应状态 + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("error response from server") + } + return nil + } + + return UpdateVirtualValuePro(oldVirtualValue1, newVirtualValue1, oldVirtualValue2, newVirtualValue2) +} diff --git a/server/getIDHandler.go b/server/getIDHandler.go index 58c9db79..63f674c3 100644 --- a/server/getIDHandler.go +++ b/server/getIDHandler.go @@ -102,6 +102,92 @@ func GetIDHandler(c *gin.Context) { return } + _, virtualValue, err := idmap.RetrieveVirtualValuev2(realValue) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, gin.H{"virtual": virtualValue}) + case 8: + // 调用新的 StoreIDv2Pro + subid := c.Query("subid") + if subid == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "subid parameter is required for type 8"}) + return + } + newRow, newSubRow, err := idmap.StoreIDv2Pro(idOrRow, subid) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, gin.H{"row": newRow, "subRow": newSubRow}) + + case 9: + // 调用新的 RetrieveRowByIDv2Pro + subid := c.Query("subid") + if subid == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "subid parameter is required for type 9"}) + return + } + id, subid, err := idmap.RetrieveRowByIDv2Pro(idOrRow, subid) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, gin.H{"id": id, "subid": subid}) + case 10: + subid := c.Query("subid") + if idOrRow == "" || subid == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "id and subid parameters are required for type 10"}) + return + } + + firstValue, secondValue, err := idmap.RetrieveVirtualValuev2Pro(idOrRow, subid) // 确保函数名称正确 + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"firstValue": firstValue, "secondValue": secondValue}) + case 11: + subid := c.Query("subid") + if idOrRow == "" || subid == "" { + c.JSON(http.StatusBadRequest, gin.H{"error": "id and subid parameters are required for type 11"}) + return + } + virtualValue, err := strconv.ParseInt(idOrRow, 10, 64) + virtualValueSub, err := strconv.ParseInt(subid, 10, 64) + firstRealValue, secondRealValue, err := idmap.RetrieveRealValuesv2Pro(virtualValue, virtualValueSub) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"firstRealValue": firstRealValue, "secondRealValue": secondRealValue}) + case 12: + oldVirtualValue1Str := c.Query("oldVirtualValue1") + newVirtualValue1Str := c.Query("newVirtualValue1") + oldVirtualValue2Str := c.Query("oldVirtualValue2") + newVirtualValue2Str := c.Query("newVirtualValue2") + + // 将字符串转换为int64 + oldVirtualValue1, err := strconv.ParseInt(oldVirtualValue1Str, 10, 64) + newVirtualValue1, err := strconv.ParseInt(newVirtualValue1Str, 10, 64) + oldVirtualValue2, err := strconv.ParseInt(oldVirtualValue2Str, 10, 64) + newVirtualValue2, err := strconv.ParseInt(newVirtualValue2Str, 10, 64) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input values"}) + return + } + + err = idmap.UpdateVirtualValuev2Pro(oldVirtualValue1, newVirtualValue1, oldVirtualValue2, newVirtualValue2) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "Virtual values updated successfully"}) + } } diff --git a/template/config_template.go b/template/config_template.go index 18ced242..79ce91fd 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -93,6 +93,7 @@ settings: dev_message_id : false #在沙盒和测试环境使用无限制msg_id 仅沙盒有效,正式环境请关闭,内测结束后,tx侧未来会移除 send_error : true #将报错用文本发出,避免机器人被审核报无响应 url_pic_transfer : false #把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(暂时不需要) + idmap_pro : false #需开启hash_id配合,高级id转换增强,可以多个真实值bind到同一个虚拟值,对于每个用户,每个群\私聊\判断私聊\频道,都会产生新的虚拟值,但可以多次bind,bind到同一个数字.数据库负担会变大. title : "Gensokyo © 2023 - Hoshinonyaruko" #程序的标题 如果多个机器人 可根据标题区分 diff --git a/template/config_template.yml b/template/config_template.yml index d4791339..d01a93ed 100644 --- a/template/config_template.yml +++ b/template/config_template.yml @@ -73,3 +73,4 @@ settings: url_pic_transfer : false #把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(暂时不需要) lotus_password : "" # lotus鉴权 设置后,从gsk需要保持相同密码来访问主gsk ws_server_path : "ws" #默认监听0.0.0.0:port/ws_server_path 若有安全需求,可不放通port到公网,或设置ws_server_token 若想监听/ 可改为"" + idmap_pro : false #需开启hash_id配合,高级id转换增强,可以多个真实值bind到同一个虚拟值,对于每个用户,每个群\私聊\判断私聊\频道,都会产生新的虚拟值,但可以多次bind,bind到同一个数字.数据库负担会变大. From f635b92656d597b1001f0eceea617092304c233c Mon Sep 17 00:00:00 2001 From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com> Date: Sun, 26 Nov 2023 22:37:23 +0800 Subject: [PATCH 4/5] Beta56 (#176) * beta55 * beta55 * add idmaps pro * add idmaps pr2o * add idmaps pr3o * add idmaps pr4o --- Processor/Processor.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Processor/Processor.go b/Processor/Processor.go index c00cb0dc..fa80e455 100644 --- a/Processor/Processor.go +++ b/Processor/Processor.go @@ -656,6 +656,8 @@ func (p *Processors) Autobind(data interface{}) error { if err := updateMappings(userid64, vuinValue, GroupID64, idValue); err != nil { return err } + // idmaps pro也更新 + idmap.UpdateVirtualValuev2Pro(GroupID64, idValue, userid64, vuinValue) } else if !vuinBound { // 只有vuin未绑定,更新vuin映射 if err := idmap.UpdateVirtualValuev2(userid64, vuinValue); err != nil { From 62f91d3c58a0c8c1ec82956fbd926574e417a439 Mon Sep 17 00:00:00 2001 From: SanaeFox <36219542+Hoshinonyaruko@users.noreply.github.com> Date: Mon, 27 Nov 2023 09:58:48 +0800 Subject: [PATCH 5/5] Beta56 (#178) * beta55 * beta55 * add idmaps pro * add idmaps pr2o * add idmaps pr3o * add idmaps pr4o * add idmaps pr5o --- main.go | 9 +++++++-- template/config_template.go | 2 +- template/config_template.yml | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index c3586724..21227054 100644 --- a/main.go +++ b/main.go @@ -308,8 +308,13 @@ func main() { if conf.Settings.AppID != 12345 { if conf.Settings.EnableWsServer { wspath := config.GetWsServerPath() - r.GET("/"+wspath, server.WsHandlerWithDependencies(api, apiV2, p)) - log.Println("正向ws启动成功,监听0.0.0.0:" + serverPort + "/" + wspath + "请注意设置ws_server_token,并对外放通端口...") + if wspath != "nil" { + r.GET("", server.WsHandlerWithDependencies(api, apiV2, p)) + log.Println("正向ws启动成功,监听0.0.0.0:" + serverPort + "请注意设置ws_server_token(可空),并对外放通端口...") + } else { + r.GET("/"+wspath, server.WsHandlerWithDependencies(api, apiV2, p)) + log.Println("正向ws启动成功,监听0.0.0.0:" + serverPort + "/" + wspath + "请注意设置ws_server_token(可空),并对外放通端口...") + } } } r.POST("/url", url.CreateShortURLHandler) diff --git a/template/config_template.go b/template/config_template.go index 79ce91fd..1deabf9c 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -48,7 +48,7 @@ settings: record_bitRate : 24000 #语音文件的比特率 默认25000 代表 25 kbps 最高无限 请根据带宽 您发送的实际码率调整 #正向ws设置 - ws_server_path : "ws" #默认监听0.0.0.0:port/ws_server_path 若有安全需求,可不放通port到公网,或设置ws_server_token 若想监听/ 可改为"" + ws_server_path : "ws" #默认监听0.0.0.0:port/ws_server_path 若有安全需求,可不放通port到公网,或设置ws_server_token 若想监听/ 可改为"",若想监听到不带/地址请写nil enable_ws_server: true #是否启用正向ws服务器 监听server_dir:port/ws_server_path ws_server_token : "12345" #正向ws的token 不启动正向ws可忽略 可为空 diff --git a/template/config_template.yml b/template/config_template.yml index d01a93ed..ec562650 100644 --- a/template/config_template.yml +++ b/template/config_template.yml @@ -72,5 +72,5 @@ settings: add_at_group : false #自动在群聊指令前加上at,某些机器人写法特别,必须有at才反应时,请打开,默认请关闭(如果需要at,不需要at指令混杂,请优化代码适配群场景,群场景目前没有at概念 url_pic_transfer : false #把图片url(任意来源图链)变成你备案的白名单url 需要较高上下行+ssl+自备案域名+设置白名单域名(暂时不需要) lotus_password : "" # lotus鉴权 设置后,从gsk需要保持相同密码来访问主gsk - ws_server_path : "ws" #默认监听0.0.0.0:port/ws_server_path 若有安全需求,可不放通port到公网,或设置ws_server_token 若想监听/ 可改为"" + ws_server_path : "ws" #默认监听0.0.0.0:port/ws_server_path 若有安全需求,可不放通port到公网,或设置ws_server_token 若想监听/ 可改为"" 若想监听不带/地址请写nil idmap_pro : false #需开启hash_id配合,高级id转换增强,可以多个真实值bind到同一个虚拟值,对于每个用户,每个群\私聊\判断私聊\频道,都会产生新的虚拟值,但可以多次bind,bind到同一个数字.数据库负担会变大.