Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beta129 #302

Merged
merged 9 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Processor/ProcessGroupMessage.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ func (p *Processors) ProcessGroupMessage(data *dto.WSGroupATMessageData) error {
echo.AddMsgType(AppIDString, GroupID64, "group")
//懒message_id池
echo.AddLazyMessageId(strconv.FormatInt(GroupID64, 10), data.ID, time.Now())
//懒message_id池
echo.AddLazyMessageId(strconv.FormatInt(userid64, 10), data.ID, time.Now())
// 调试
PrintStructWithFieldNames(groupMsg)

Expand Down
4 changes: 4 additions & 0 deletions Processor/ProcessGuildATMessage.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ func (p *Processors) ProcessGuildATMessage(data *dto.WSATMessageData) error {
//todo 完善频道转换
//懒message_id池
echo.AddLazyMessageId(data.ChannelID, data.ID, time.Now())
//懒message_id池
echo.AddLazyMessageId(strconv.FormatInt(userid64, 10), data.ID, time.Now())

//调试
PrintStructWithFieldNames(onebotMsg)
Expand Down Expand Up @@ -264,6 +266,8 @@ func (p *Processors) ProcessGuildATMessage(data *dto.WSATMessageData) error {
echo.AddMsgType(AppIDString, ChannelID64, "guild")
//懒message_id池
echo.AddLazyMessageId(strconv.FormatInt(ChannelID64, 10), data.ID, time.Now())
//懒message_id池
echo.AddLazyMessageId(strconv.FormatInt(userid64, 10), data.ID, time.Now())

//调试
PrintStructWithFieldNames(groupMsg)
Expand Down
4 changes: 4 additions & 0 deletions Processor/ProcessGuildNormalMessage.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error {
//todo 完善频道ob信息
//懒message_id池
echo.AddLazyMessageId(data.ChannelID, data.ID, time.Now())
//懒message_id池
echo.AddLazyMessageId(strconv.FormatInt(userid64, 10), data.ID, time.Now())

//调试
PrintStructWithFieldNames(onebotMsg)
Expand Down Expand Up @@ -272,6 +274,8 @@ func (p *Processors) ProcessGuildNormalMessage(data *dto.WSMessageData) error {
echo.AddMsgType(AppIDString, ChannelID64, "guild")
//懒message_id池
echo.AddLazyMessageId(strconv.FormatInt(ChannelID64, 10), data.ID, time.Now())
//懒message_id池
echo.AddLazyMessageId(strconv.FormatInt(userid64, 10), data.ID, time.Now())

//调试
PrintStructWithFieldNames(groupMsg)
Expand Down
76 changes: 66 additions & 10 deletions Processor/Processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ type OnebotPrivateMessage struct {
IsBindedUserId bool `json:"is_binded_user_id,omitempty"` //当前用户号号是否是binded后的
}

// onebotv11标准扩展
type OnebotInteractionNotice struct {
GroupID int64 `json:"group_id,omitempty"`
NoticeType string `json:"notice_type,omitempty"`
PostType string `json:"post_type,omitempty"`
SelfID int64 `json:"self_id,omitempty"`
SubType string `json:"sub_type,omitempty"`
Time int64 `json:"time,omitempty"`
UserID int64 `json:"user_id,omitempty"`
Data *dto.WSInteractionData `json:"data,omitempty"`
}

type PrivateSender struct {
Nickname string `json:"nickname"`
UserID int64 `json:"user_id"` // Can be either string or int depending on logic
Expand All @@ -123,19 +135,63 @@ func FoxTimestamp() int64 {

// ProcessInlineSearch 处理内联查询
func (p *Processors) ProcessInlineSearch(data *dto.WSInteractionData) error {
//ctx := context.Background() // 或从更高级别传递一个上下文
// 转换appid
var userid64 int64
var GroupID64 int64
var err error
var fromgid, fromuid string
if data.GroupOpenID != "" {
fromgid = data.GroupOpenID
fromuid = data.GroupMemberOpenID
} else {
fromgid = data.ChannelID
fromuid = "0"
}
if config.GetIdmapPro() {
//将真实id转为int userid64
GroupID64, userid64, err = idmap.StoreIDv2Pro(fromgid, fromuid)
if err != nil {
mylog.Fatalf("Error storing ID: %v", err)
}
//当参数不全
_, _ = idmap.StoreIDv2(fromgid)
_, _ = idmap.StoreIDv2(fromuid)
if !config.GetHashIDValue() {
mylog.Fatalf("避坑日志:你开启了高级id转换,请设置hash_id为true,并且删除idmaps并重启")
}
} else {
// 映射str的GroupID到int
GroupID64, err = idmap.StoreIDv2(fromgid)
if err != nil {
mylog.Errorf("failed to convert ChannelID to int: %v", err)
return nil
}
// 映射str的userid到int
userid64, err = idmap.StoreIDv2(fromuid)
if err != nil {
mylog.Printf("Error storing ID: %v", err)
return nil
}
}
notice := &OnebotInteractionNotice{
GroupID: GroupID64,
NoticeType: "interaction",
PostType: "notice",
SelfID: int64(p.Settings.AppID),
SubType: "create",
Time: time.Now().Unix(),
UserID: userid64,
Data: data,
}

// 在这里处理内联查询
// 这可能涉及解析查询、调用某些API、获取结果并格式化为响应
// ...
//调试
PrintStructWithFieldNames(notice)

// 示例:发送响应
// response := "Received your interaction!" // 创建响应消息
// err := p.api.PostInteractionResponse(ctx, response) // 替换为您的OpenAPI方法
// if err != nil {
// return err
// }
// Convert OnebotGroupMessage to map and send
noticeMap := structToMap(notice)

//上报信息到onebotv11应用端(正反ws)
p.BroadcastMessageToAll(noticeMap)
return nil
}

Expand Down
34 changes: 22 additions & 12 deletions botgo/dto/interaction.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package dto

import "encoding/json"

// Interaction 互动行为对象
type Interaction struct {
ID string `json:"id,omitempty"` // 互动行为唯一标识
ApplicationID string `json:"application_id,omitempty"` // 应用ID
Type InteractionType `json:"type,omitempty"` // 互动类型
Data *InteractionData `json:"data,omitempty"` // 互动数据
GuildID string `json:"guild_id,omitempty"` // 频道 ID
ChannelID string `json:"channel_id,omitempty"` // 子频道 ID
Version uint32 `json:"version,omitempty"` // 版本,默认为 1
ID string `json:"id,omitempty"` // 平台方事件 ID
Type InteractionType `json:"type,omitempty"` // 消息按钮: 11, 单聊快捷菜单: 12
Scene string `json:"scene,omitempty"` // 事件发生的场景
ChatType int `json:"chat_type,omitempty"` // 频道场景: 0, 群聊场景: 1, 单聊场景: 2
Timestamp string `json:"timestamp,omitempty"` // 触发时间 RFC 3339 格式
GuildID string `json:"guild_id,omitempty"` // 频道的 openid
ChannelID string `json:"channel_id,omitempty"` // 文字子频道的 openid
UserOpenID string `json:"user_openid,omitempty"` // 单聊按钮触发的用户 openid
GroupOpenID string `json:"group_openid,omitempty"` // 群的 openid
GroupMemberOpenID string `json:"group_member_openid,omitempty"` // 群成员 openid
Data *InteractionData `json:"data,omitempty"` // 互动数据
Version uint32 `json:"version,omitempty"` // 版本,默认为 1
ApplicationID string `json:"application_id,omitempty"` // 机器人的 appid
}

// InteractionType 互动类型
Expand All @@ -25,9 +29,15 @@ const (

// InteractionData 互动数据
type InteractionData struct {
Name string `json:"name,omitempty"` // 标题
Type InteractionDataType `json:"type,omitempty"` // 数据类型,不同数据类型对应不同的 resolved 数据
Resolved json.RawMessage `json:"resolved,omitempty"` // 跟不同的互动类型和数据类型有关系的数据
Name string `json:"name,omitempty"` // 标题
Type InteractionDataType `json:"type,omitempty"` // 数据类型
Resolved struct {
ButtonData string `json:"button_data,omitempty"` // 操作按钮的 data 字段值
ButtonID string `json:"button_id,omitempty"` // 操作按钮的 id 字段值
UserID string `json:"user_id,omitempty"` // 操作的用户 userid
FeatureID string `json:"feature_id,omitempty"` // 操作按钮的 feature id
MessageID string `json:"message_id,omitempty"` // 操作的消息 id
} `json:"resolved,omitempty"`
}

// InteractionDataType 互动数据类型
Expand Down
8 changes: 4 additions & 4 deletions botgo/dto/keyboard/keyboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type RenderData struct {

// Action 按纽点击操作
type Action struct {
Type ActionType `json:"type,omitempty"` // 操作类型
Type ActionType `json:"type,omitempty"` // 操作类型 设置 0 跳转按钮:http 或 小程序 客户端识别 scheme,设置 1 回调按钮:回调后台接口, data 传给后台,设置 2 指令按钮:自动在输入框插入 @bot data
Permission *Permission `json:"permission,omitempty"` // 可操作
ClickLimit uint32 `json:"click_limit,omitempty"` // 可点击的次数, 默认不限
Data string `json:"data,omitempty"` // 操作相关数据
Expand All @@ -68,10 +68,10 @@ type Action struct {

// Permission 按纽操作权限
type Permission struct {
// Type 操作权限类型
// Type 操作权限类型 0 指定用户可操作,1 仅管理者可操作,2 所有人可操作,3 指定身份组可操作(仅频道可用)
Type PermissionType `json:"type,omitempty"`
// SpecifyRoleIDs 身份组
// SpecifyRoleIDs 身份组(仅频道可用)
SpecifyRoleIDs []string `json:"specify_role_ids,omitempty"`
// SpecifyUserIDs 指定 UserID
// SpecifyUserIDs 指定 UserID 有权限的用户 id 的列表
SpecifyUserIDs []string `json:"specify_user_ids,omitempty"`
}
35 changes: 35 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ type Settings struct {
TransFormApiIds bool `yaml:"transform_api_ids"`
CustomTemplateID string `yaml:"custom_template_id"`
KeyBoardID string `yaml:"keyboard_id"`
Uin int64 `yaml:"uin"`
VwhitePrefixMode bool `yaml:"v_white_prefix_mode"`
Enters []string `yaml:"enters"`
}

// LoadConfig 从文件中加载配置并初始化单例配置
Expand Down Expand Up @@ -1676,3 +1679,35 @@ func GetKeyBoardID() string {
}
return instance.Settings.KeyBoardID
}

// 获取Uin String
func GetUinStr() string {
mu.Lock()
defer mu.Unlock()
if instance != nil {
return fmt.Sprintf("%d", instance.Settings.Uin)
}
return "0"
}

// 获取 VV GetVwhitePrefixMode 的值
func GetVwhitePrefixMode() bool {
mu.Lock()
defer mu.Unlock()

if instance == nil {
mylog.Println("Warning: instance is nil when trying to VwhitePrefixMode value.")
return false
}
return instance.Settings.VwhitePrefixMode
}

// 获取Enters的值
func GetEnters() []string {
mu.Lock()
defer mu.Unlock()
if instance != nil {
return instance.Settings.Enters
}
return nil // 返回nil,如果instance为nil
}
4 changes: 2 additions & 2 deletions handlers/message_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -503,8 +503,8 @@ func RevertTransformedText(data interface{}, msgtype string, api openapi.OpenAPI
aliases := config.GetAlias()
messageText = processMessageText(messageText, aliases)
//mylog.Printf("4[%v]", messageText)
// 检查是否启用白名单模式
if config.GetWhitePrefixMode() && matchedPrefix != nil {
// 检查是否启用二级白名单模式
if config.GetVwhitePrefixMode() && matchedPrefix != nil {
// 获取白名单反转标志
whiteBypassRevers := config.GetWhiteBypassRevers()

Expand Down
83 changes: 73 additions & 10 deletions handlers/send_group_msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ func HandleSendGroupMsg(client callapi.Client, api openapi.OpenAPI, apiv2 openap
//由于实现了Params的自定义unmarshell 所以可以类型安全的断言为string
messageID = echo.GetLazyMessagesId(message.Params.GroupID.(string))
mylog.Printf("GetLazyMessagesId: %v", messageID)
//如果应用端传递了user_id 就让at不要顺序乱套
if message.Params.UserID != nil {
messageID = echo.GetLazyMessagesId(message.Params.UserID.(string))
mylog.Printf("GetLazyMessagesIdv2: %v", messageID)
}
if messageID != "" {
//尝试发送栈内信息
SSM = true
Expand Down Expand Up @@ -1082,6 +1087,10 @@ func auto_md(message callapi.ActionMessage, messageText string, richMediaMessage
mylog.Printf("获取图片宽高出错")
}
imgDesc := fmt.Sprintf("图片 #%dpx #%dpx", width, height)
// 将所有的\r\n替换为\r
messageText = strings.ReplaceAll(messageText, "\r\n", "\r")
// 将所有的\n替换为\r
messageText = strings.ReplaceAll(messageText, "\n", "\r")
// 检查messageText是否以\r开头
if !strings.HasPrefix(messageText, "\r") {
messageText = "\r" + messageText
Expand All @@ -1108,26 +1117,64 @@ func auto_md(message callapi.ActionMessage, messageText string, richMediaMessage
buttonCount := 0 // 当前行的按钮计数

for _, whiteLabel := range whiteList {
// 使用 strconv.Atoi 检查 whiteLabel 是否为纯数字
if _, err := strconv.Atoi(whiteLabel); err == nil {
// 如果没有错误,表示 whiteLabel 是一个数字,因此忽略这个元素并继续下一个迭代
continue
// 如果whiteList的成员数大于或等于15,才检查whiteLabel是否为纯数字
if len(whiteList) >= 15 {
if _, err := strconv.Atoi(whiteLabel); err == nil {
// 如果没有错误,表示 whiteLabel 是一个数字,因此忽略这个元素并继续下一个迭代
// 避免 因为纯数字按钮太多导致混乱,但是少量的纯数字按钮可以允许
continue
}
}
// 检查msg_on_touch是否已经以whiteLabel结尾
//场景 按钮递归时 比如 随机meme 再来一次,同时随机meme是*类型一级指令
var dataLabel string
if !strings.HasSuffix(msg_on_touch, whiteLabel) {
dataLabel = msg_on_touch + whiteLabel
} else {
dataLabel = msg_on_touch
}

var actiontype keyboard.ActionType
var permission *keyboard.Permission
var actiondata string
//检查是否设置了enter数组
enter := checkDataLabelPrefix(dataLabel)
switch whiteLabel {
case "邀请机器人":
botuin := config.GetUinStr()
botappid := config.GetAppIDStr()
boturl := BuildQQBotShareLink(botuin, botappid)
actiontype = 0
actiondata = boturl
permission = &keyboard.Permission{
Type: 2, // 所有人可操作
}
case "测试按钮回调":
actiontype = 1
actiondata = "收到就代表是管理员哦"
permission = &keyboard.Permission{
Type: 1, // 仅管理可操作
}
default:
actiontype = 2 //帮用户输入指令
actiondata = dataLabel //从虚拟前缀的二级指令组合md按钮
permission = &keyboard.Permission{
Type: 2, // 所有人可操作
}
}
// 创建按钮
button := &keyboard.Button{
RenderData: &keyboard.RenderData{
Label: whiteLabel,
VisitedLabel: whiteLabel,
Style: 1,
Style: 1, //蓝色边缘
},
Action: &keyboard.Action{
Type: 2, // 帮用户输入二级指令
Permission: &keyboard.Permission{
Type: 2, //所有人可操作
},
Data: msg_on_touch + " " + whiteLabel,
Type: actiontype,
Permission: permission,
Data: actiondata,
UnsupportTips: "请升级新版手机QQ",
Enter: enter,
},
}

Expand All @@ -1153,3 +1200,19 @@ func auto_md(message callapi.ActionMessage, messageText string, richMediaMessage
}
return md, kb, transmd
}

// 构建QQ群机器人分享链接的函数
func BuildQQBotShareLink(uin string, appid string) string {
return fmt.Sprintf("https://qun.qq.com/qunpro/robot/qunshare?robot_uin=%s&robot_appid=%s", uin, appid)
}

// 检查dataLabel是否以config中getenters返回的任一字符串开头
func checkDataLabelPrefix(dataLabel string) bool {
enters := config.GetEnters()
for _, enter := range enters {
if enter != "" && strings.HasPrefix(dataLabel, enter) {
return true
}
}
return false
}
Loading
Loading