diff --git a/Processor/ProcessC2CMessage.go b/Processor/ProcessC2CMessage.go index 10f83f66..fd0617d3 100644 --- a/Processor/ProcessC2CMessage.go +++ b/Processor/ProcessC2CMessage.go @@ -82,6 +82,9 @@ func (p *Processors) ProcessC2CMessage(data *dto.WSC2CMessageData) error { //其实不需要用AppIDString,因为gensokyo是单机器人框架 //可以试着开发一个,会很棒的 echo.AddMsgID(AppIDString, userid64, data.ID) + //懒message_id池 + echo.AddLazyMessageId(strconv.FormatInt(userid64, 10), data.ID, time.Now()) + //储存类型 echo.AddMsgType(AppIDString, userid64, "group_private") //储存当前群或频道号的类型 私信不需要 //idmap.WriteConfigv2(data.ChannelID, "type", "group_private") @@ -162,6 +165,8 @@ func (p *Processors) ProcessC2CMessage(data *dto.WSC2CMessageData) error { //为不支持双向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()) //调试 PrintStructWithFieldNames(groupMsg) diff --git a/Processor/ProcessChannelDirectMessage.go b/Processor/ProcessChannelDirectMessage.go index 56dbb1e3..5f0d5e61 100644 --- a/Processor/ProcessChannelDirectMessage.go +++ b/Processor/ProcessChannelDirectMessage.go @@ -98,6 +98,8 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) //其实不需要用AppIDString,因为gensokyo是单机器人框架 echo.AddMsgID(AppIDString, userid64, data.ID) echo.AddMsgType(AppIDString, userid64, "guild_private") + //懒message_id池 + echo.AddLazyMessageId(strconv.FormatInt(userid64, 10), data.ID, time.Now()) // 调试 PrintStructWithFieldNames(privateMsg) @@ -182,6 +184,8 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) //储存当前群或频道号的类型 idmap.WriteConfigv2(data.ChannelID, "type", "guild_private") //todo 完善频道类型信息转换 + //懒message_id池 + echo.AddLazyMessageId(strconv.FormatInt(userid64, 10), data.ID, time.Now()) //调试 PrintStructWithFieldNames(onebotMsg) @@ -273,6 +277,8 @@ func (p *Processors) ProcessChannelDirectMessage(data *dto.WSDirectMessageData) //储存当前群或频道号的类型 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "type", "guild_private") echo.AddMsgType(AppIDString, ChannelID64, "guild_private") + //懒message_id池 + echo.AddLazyMessageId(strconv.FormatInt(userid64, 10), data.ID, time.Now()) //调试 PrintStructWithFieldNames(groupMsg) diff --git a/Processor/ProcessGroupMessage.go b/Processor/ProcessGroupMessage.go index 0de1b65a..45998b18 100644 --- a/Processor/ProcessGroupMessage.go +++ b/Processor/ProcessGroupMessage.go @@ -102,6 +102,8 @@ func (p *Processors) ProcessGroupMessage(data *dto.WSGroupATMessageData) error { //储存当前群或频道号的类型 idmap.WriteConfigv2(fmt.Sprint(GroupID64), "type", "group") echo.AddMsgType(AppIDString, GroupID64, "group") + //懒message_id池 + echo.AddLazyMessageId(strconv.FormatInt(GroupID64, 10), data.ID, time.Now()) // 调试 PrintStructWithFieldNames(groupMsg) diff --git a/Processor/ProcessGuildATMessage.go b/Processor/ProcessGuildATMessage.go index 222fc0ac..c9260516 100644 --- a/Processor/ProcessGuildATMessage.go +++ b/Processor/ProcessGuildATMessage.go @@ -92,6 +92,8 @@ func (p *Processors) ProcessGuildATMessage(data *dto.WSATMessageData) error { //储存当前群或频道号的类型 idmap.WriteConfigv2(data.ChannelID, "type", "guild") //todo 完善频道转换 + //懒message_id池 + echo.AddLazyMessageId(data.ChannelID, data.ID, time.Now()) //调试 PrintStructWithFieldNames(onebotMsg) @@ -187,6 +189,8 @@ func (p *Processors) ProcessGuildATMessage(data *dto.WSATMessageData) error { //储存当前群或频道号的类型 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "type", "guild") echo.AddMsgType(AppIDString, ChannelID64, "guild") + //懒message_id池 + echo.AddLazyMessageId(strconv.FormatInt(ChannelID64, 10), data.ID, time.Now()) //调试 PrintStructWithFieldNames(groupMsg) diff --git a/Processor/ProcessGuildNormalMessage.go b/Processor/ProcessGuildNormalMessage.go index 11e01514..4b80efe0 100644 --- a/Processor/ProcessGuildNormalMessage.go +++ b/Processor/ProcessGuildNormalMessage.go @@ -94,6 +94,8 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error { //储存当前群或频道号的类型 idmap.WriteConfigv2(data.ChannelID, "type", "guild") //todo 完善频道ob信息 + //懒message_id池 + echo.AddLazyMessageId(data.ChannelID, data.ID, time.Now()) //调试 PrintStructWithFieldNames(onebotMsg) @@ -189,6 +191,8 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error { //储存当前群或频道号的类型 idmap.WriteConfigv2(fmt.Sprint(ChannelID64), "type", "guild") echo.AddMsgType(AppIDString, ChannelID64, "guild") + //懒message_id池 + echo.AddLazyMessageId(strconv.FormatInt(ChannelID64, 10), data.ID, time.Now()) //调试 PrintStructWithFieldNames(groupMsg) diff --git a/Processor/Processor.go b/Processor/Processor.go index f85a0c0a..1e4212cd 100644 --- a/Processor/Processor.go +++ b/Processor/Processor.go @@ -49,7 +49,7 @@ type OnebotChannelMessage struct { Avatar string `json:"avatar"` UserID int64 `json:"user_id"` RawMessage string `json:"raw_message"` - Echo string `json:"echo"` + Echo string `json:"echo,omitempty"` } // 群信息事件 @@ -64,7 +64,7 @@ type OnebotGroupMessage struct { SubType string `json:"sub_type"` Time int64 `json:"time"` Avatar string `json:"avatar"` - Echo string `json:"echo"` + Echo string `json:"echo,omitempty"` Message interface{} `json:"message"` // For array format MessageSeq int `json:"message_seq"` Font int `json:"font"` @@ -82,7 +82,7 @@ type OnebotPrivateMessage struct { SubType string `json:"sub_type"` Time int64 `json:"time"` Avatar string `json:"avatar"` - Echo string `json:"echo"` + Echo string `json:"echo,omitempty"` Message interface{} `json:"message"` // For array format MessageSeq int `json:"message_seq"` // Optional field Font int `json:"font"` // Optional field diff --git a/config/config.go b/config/config.go index df7fea6f..9eac71ca 100644 --- a/config/config.go +++ b/config/config.go @@ -58,6 +58,7 @@ type Settings struct { Title string `yaml:"title"` HashID bool `yaml:"hash_id"` TwoWayEcho bool `yaml:"twoway_echo"` + LazyMessageId bool `yaml:"lazy_message_id"` } // LoadConfig 从文件中加载配置并初始化单例配置 @@ -403,6 +404,18 @@ func GetTwoWayEcho() bool { return instance.Settings.TwoWayEcho } +// 获取LazyMessageId状态 +func GetLazyMessageId() bool { + mu.Lock() + defer mu.Unlock() + + if instance == nil { + mylog.Println("Warning: instance is nil when trying to get LazyMessageId value.") + return false + } + return instance.Settings.LazyMessageId +} + // 获取HashID func GetHashIDValue() bool { mu.Lock() diff --git a/echo/messageidmap.go b/echo/messageidmap.go new file mode 100644 index 00000000..f970f778 --- /dev/null +++ b/echo/messageidmap.go @@ -0,0 +1,61 @@ +package echo + +import ( + "math/rand" + "sync" + "time" +) + +type messageRecord struct { + messageID string + timestamp time.Time +} + +type messageStore struct { + mu sync.RWMutex + records map[string][]messageRecord +} + +var instance *messageStore +var once sync.Once + +// 惰性初始化 +func initInstance() *messageStore { + once.Do(func() { + instance = &messageStore{ + records: make(map[string][]messageRecord), + } + }) + return instance +} + +// AddLazyMessageId 添加 message_id 和它的时间戳到指定群号 +func AddLazyMessageId(groupID, messageID string, timestamp time.Time) { + store := initInstance() + store.mu.Lock() + defer store.mu.Unlock() + store.records[groupID] = append(store.records[groupID], messageRecord{messageID: messageID, timestamp: timestamp}) +} + +// GetRecentMessages 获取指定群号中最近5分钟内的 message_id +func GetLazyMessagesId(groupID string) string { + store := initInstance() + store.mu.RLock() + defer store.mu.RUnlock() + + fiveMinutesAgo := time.Now().Add(-5 * time.Minute) + var recentMessages []string + for _, record := range store.records[groupID] { + if record.timestamp.After(fiveMinutesAgo) { + recentMessages = append(recentMessages, record.messageID) + } + } + var randomMessageID string + if len(recentMessages) > 0 { + randomIndex := rand.Intn(len(recentMessages)) + randomMessageID = recentMessages[randomIndex] + } else { + randomMessageID = "" + } + return randomMessageID +} diff --git a/handlers/get_login_info.go b/handlers/get_login_info.go index 58070b14..fee772b5 100644 --- a/handlers/get_login_info.go +++ b/handlers/get_login_info.go @@ -54,6 +54,4 @@ func getLoginInfo(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Open } else { mylog.Printf("响应get_login_info: %+v", outputMap) } - - return } diff --git a/handlers/mark_msg_as_read.go b/handlers/mark_msg_as_read.go new file mode 100644 index 00000000..69b90aae --- /dev/null +++ b/handlers/mark_msg_as_read.go @@ -0,0 +1,45 @@ +package handlers + +import ( + "github.com/hoshinonyaruko/gensokyo/callapi" + "github.com/hoshinonyaruko/gensokyo/mylog" + "github.com/tencent-connect/botgo/openapi" + "github.com/tidwall/gjson" +) + +type MarkThisMessageAsReadAPIResponse struct { + Status string `json:"status"` + Data gjson.Result `json:"data"` + Msg string `json:"msg"` + Wording string `json:"wording"` + RetCode int64 `json:"retcode"` + Echo interface{} `json:"echo"` +} + +func init() { + callapi.RegisterHandler("mark_msg_as_read", MarkThisMessageAsRead) +} + +func MarkThisMessageAsRead(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.OpenAPI, message callapi.ActionMessage) { + + var response MarkThisMessageAsReadAPIResponse + + response.Data.Str = "123" + response.Msg = "123" + response.RetCode = 0 + response.Status = "ok" + response.Echo = message.Echo + + // Convert the members slice to a map + outputMap := structToMap(response) + + mylog.Printf("mark_msg_as_read: %+v\n", outputMap) + + err := client.SendMessage(outputMap) + if err != nil { + mylog.Printf("Error sending message via client: %v", err) + } else { + mylog.Printf("响应mark_msg_as_read: %+v", outputMap) + } + +} diff --git a/handlers/send_group_msg.go b/handlers/send_group_msg.go index b59cc2bb..3160096b 100644 --- a/handlers/send_group_msg.go +++ b/handlers/send_group_msg.go @@ -46,9 +46,16 @@ func handleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap // 使用 echo 获取消息ID var messageID string - if echoStr, ok := message.Echo.(string); ok { - messageID = echo.GetMsgIDByKey(echoStr) - mylog.Println("echo取群组发信息对应的message_id:", messageID) + if config.GetLazyMessageId() { + //由于实现了Params的自定义unmarshell 所以可以类型安全的断言为string + messageID = echo.GetLazyMessagesId(message.Params.GroupID.(string)) + mylog.Printf("GetLazyMessagesId: %v", messageID) + } + if messageID == "" { + if echoStr, ok := message.Echo.(string); ok { + messageID = echo.GetMsgIDByKey(echoStr) + mylog.Println("echo取群组发信息对应的message_id:", messageID) + } } //通过bolt数据库还原真实的GroupID originalGroupID, err := idmap.RetrieveRowByIDv2(message.Params.GroupID.(string)) diff --git a/handlers/send_guild_channel_msg.go b/handlers/send_guild_channel_msg.go index 28c3cc4b..6e2484d8 100644 --- a/handlers/send_guild_channel_msg.go +++ b/handlers/send_guild_channel_msg.go @@ -54,9 +54,16 @@ func handleSendGuildChannelMsg(client callapi.Client, api openapi.OpenAPI, apiv2 //mylog.Printf("发送文本信息失败: %v,%v", channelID, channelID) // 使用 echo 获取消息ID var messageID string - if echoStr, ok := message.Echo.(string); ok { - messageID = echo.GetMsgIDByKey(echoStr) - mylog.Println("echo取频道发信息对应的message_id:", messageID) + if config.GetLazyMessageId() { + //由于实现了Params的自定义unmarshell 所以可以类型安全的断言为string + messageID = echo.GetLazyMessagesId(channelID) + 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 == "" { diff --git a/handlers/send_msg.go b/handlers/send_msg.go index 659625b3..fa43c488 100644 --- a/handlers/send_msg.go +++ b/handlers/send_msg.go @@ -47,12 +47,19 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope case "group": // 解析消息内容 messageText, foundItems := parseMessageContent(message.Params) - // 使用 echo 获取消息ID var messageID string - if echoStr, ok := message.Echo.(string); ok { - messageID = echo.GetMsgIDByKey(echoStr) - mylog.Println("echo取群组发信息对应的message_id:", messageID) + if config.GetLazyMessageId() { + //由于实现了Params的自定义unmarshell 所以可以类型安全的断言为string + messageID = echo.GetLazyMessagesId(message.Params.GroupID.(string)) + mylog.Printf("GetLazyMessagesId: %v", messageID) + } + //判断是否使用了懒messageid,如果没有,优先从echo获取messageid + if messageID == "" { + if echoStr, ok := message.Echo.(string); ok { + messageID = echo.GetMsgIDByKey(echoStr) + mylog.Println("echo取群组发信息对应的message_id:", messageID) + } } mylog.Println("群组发信息messageText:", messageText) //通过bolt数据库还原真实的GroupID @@ -124,27 +131,7 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope //根据userid绑定得到的具体真实事件类型,这里也有多种可能性 //1,私聊(但虚拟成了群),这里用群号取得需要的id //2,频道私聊(但虚拟成了私聊)这里传递2个nil,用user_id去推测channel_id和guild_id - - var channelIDPtr *string - var GuildidPtr *string - - // 先尝试将GroupID断言为字符串 - if channelID, ok := message.Params.GroupID.(string); ok && channelID != "" { - channelIDPtr = &channelID - // 读取bolt数据库 通过ChannelID取回之前储存的guild_id - if value, err := idmap.ReadConfigv2(*channelIDPtr, "guild_id"); err == nil && value != "" { - GuildidPtr = &value - } else { - mylog.Printf("Error reading config: %v", err) - } - } - - if channelIDPtr == nil || GuildidPtr == nil { - mylog.Printf("Value or ChannelID is empty or in error. Value: %v, ChannelID: %v", GuildidPtr, channelIDPtr) - } - - handleSendGuildChannelPrivateMsg(client, api, apiv2, message, GuildidPtr, channelIDPtr) - + handleSendGuildChannelPrivateMsg(client, api, apiv2, message, nil, nil) case "group_private": //私聊信息 //还原真实的userid @@ -159,9 +146,16 @@ func handleSendMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.Ope // 使用 echo 获取消息ID var messageID string - if echoStr, ok := message.Echo.(string); ok { - messageID = echo.GetMsgIDByKey(echoStr) - mylog.Println("echo取私聊发信息对应的message_id:", messageID) + 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 == "" { diff --git a/handlers/send_private_msg.go b/handlers/send_private_msg.go index 2e67f50b..9cff8454 100644 --- a/handlers/send_private_msg.go +++ b/handlers/send_private_msg.go @@ -58,9 +58,16 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open // 使用 echo 获取消息ID var messageID string - if echoStr, ok := message.Echo.(string); ok { - messageID = echo.GetMsgIDByKey(echoStr) - mylog.Println("echo取私聊发信息对应的message_id:", messageID) + 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仍然为空,尝试使用config.GetAppID和UserID的组合来获取messageID // 如果messageID为空,通过函数获取 @@ -121,37 +128,37 @@ func handleSendPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 open } // 这里是只有群私聊会用到 -func generatePrivateMessage(id string, foundItems map[string][]string, messageText string) interface{} { - if imageURLs, ok := foundItems["local_image"]; ok && len(imageURLs) > 0 { - // 本地发图逻辑 todo 适配base64图片 - return &dto.RichMediaMessage{ - EventID: id, - FileType: 1, // 1代表图片 - URL: imageURLs[0], - Content: "", // 这个字段文档没有了 - SrvSendMsg: true, - } - } else if imageURLs, ok := foundItems["url_image"]; ok && len(imageURLs) > 0 { - // 发链接图片 - return &dto.RichMediaMessage{ - EventID: id, - FileType: 1, // 1代表图片 - URL: "http://" + imageURLs[0], - Content: "", // 这个字段文档没有了 - SrvSendMsg: true, - } - } else if voiceURLs, ok := foundItems["base64_record"]; ok && len(voiceURLs) > 0 { - // 目前不支持发语音 todo 适配base64 slik - } else { - // 返回文本信息 - return &dto.MessageToCreate{ - Content: messageText, - MsgID: id, - MsgType: 0, // 默认文本类型 - } - } - return nil -} +// func generatePrivateMessage(id string, foundItems map[string][]string, messageText string) interface{} { +// if imageURLs, ok := foundItems["local_image"]; ok && len(imageURLs) > 0 { +// // 本地发图逻辑 todo 适配base64图片 +// return &dto.RichMediaMessage{ +// EventID: id, +// FileType: 1, // 1代表图片 +// URL: imageURLs[0], +// Content: "", // 这个字段文档没有了 +// SrvSendMsg: true, +// } +// } else if imageURLs, ok := foundItems["url_image"]; ok && len(imageURLs) > 0 { +// // 发链接图片 +// return &dto.RichMediaMessage{ +// EventID: id, +// FileType: 1, // 1代表图片 +// URL: "http://" + imageURLs[0], +// Content: "", // 这个字段文档没有了 +// SrvSendMsg: true, +// } +// } else if voiceURLs, ok := foundItems["base64_record"]; ok && len(voiceURLs) > 0 { +// // 目前不支持发语音 todo 适配base64 slik +// } else { +// // 返回文本信息 +// return &dto.MessageToCreate{ +// Content: messageText, +// MsgID: id, +// MsgType: 0, // 默认文本类型 +// } +// } +// return nil +// } // 处理频道私信 最后2个指针参数可空 代表使用userid倒推 func handleSendGuildChannelPrivateMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.OpenAPI, message callapi.ActionMessage, optionalGuildID *string, optionalChannelID *string) { @@ -175,15 +182,27 @@ func handleSendGuildChannelPrivateMsg(client callapi.Client, api openapi.OpenAPI // 使用 echo 获取消息ID var messageID string - if echoStr, ok := message.Echo.(string); ok { - messageID = echo.GetMsgIDByKey(echoStr) - mylog.Println("echo取私聊发信息对应的message_id:", messageID) + if config.GetLazyMessageId() { + //由于实现了Params的自定义unmarshell 所以可以类型安全的断言为string + messageID = echo.GetLazyMessagesId(message.Params.UserID.(string)) + mylog.Printf("GetLazyMessagesId: %v", messageID) + } + if messageID == "" { + if echoStr, ok := message.Echo.(string); ok { + messageID = echo.GetMsgIDByKey(echoStr) + mylog.Println("echo取私聊发信息对应的message_id:", messageID) + } } mylog.Println("私聊信息messageText:", messageText) - //mylog.Println("foundItems:", foundItems) + //还原真实的userid todo 太绕了 要精简下逻辑 + UserID, err := idmap.RetrieveRowByIDv2(message.Params.UserID.(string)) + if err != nil { + mylog.Printf("Error reading config: %v", err) + return + } // 如果messageID为空,通过函数获取 if messageID == "" { - messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), message.Params.UserID) + messageID = GetMessageIDByUseridOrGroupid(config.GetAppIDStr(), UserID) mylog.Println("通过GetMessageIDByUserid函数获取的message_id:", messageID) } diff --git a/handlers/set_group_whole_ban.go b/handlers/set_group_whole_ban.go index 4252bbb4..c8555898 100644 --- a/handlers/set_group_whole_ban.go +++ b/handlers/set_group_whole_ban.go @@ -11,7 +11,7 @@ import ( ) func init() { - callapi.RegisterHandler("get_group_whole_ban", setGroupBan) + callapi.RegisterHandler("get_group_whole_ban", setGroupWholeBan) } func setGroupWholeBan(client callapi.Client, api openapi.OpenAPI, apiv2 openapi.OpenAPI, message callapi.ActionMessage) { diff --git a/template/config_template.go b/template/config_template.go index 7856fb45..9612bfc9 100644 --- a/template/config_template.go +++ b/template/config_template.go @@ -57,6 +57,7 @@ settings: title : "Gensokyo © 2023 - Hoshinonyaruko" #程序的标题 如果多个机器人 可根据标题区分 hash_id : false #使用hash来进行idmaps转换,可以让user_id不是123开始的递增值 twoway_echo : false #是否采用双向echo,根据机器人选择,獭獭\早苗 true 红色问答\椛椛 或者其他 请使用 false + lazy_message_id : false #false=message_id 条条准确对应 true=message_id 按时间范围随机对应(适合主动推送bot)前提,有足够多的活跃信息刷新id池 ` const Logo = ` ' diff --git a/template/config_template.yml b/template/config_template.yml index c29c14dc..5d860851 100644 --- a/template/config_template.yml +++ b/template/config_template.yml @@ -48,4 +48,5 @@ settings: sandbox_mode : false #默认false 如果你只希望沙箱频道使用,请改为true title : "Gensokyo © 2023 - Hoshinonyaruko" #程序的标题 如果多个机器人 可根据标题区分 hash_id : false #使用hash来进行idmaps转换,可以让user_id不是123开始的递增值 - twoway_echo : false #是否采用双向echo,根据机器人选择,獭獭\早苗 true 红色问答\椛椛 或者其他 请使用 false \ No newline at end of file + twoway_echo : false #是否采用双向echo,根据机器人选择,獭獭\早苗 true 红色问答\椛椛 或者其他 请使用 false + lazy_message_id : false #false=message_id 条条准确对应 true=message_id 按时间范围随机对应(适合主动推送bot)前提,有足够多的活跃信息刷新id池 \ No newline at end of file