1
0
mirror of https://github.com/fumiama/NanoBot.git synced 2026-06-12 14:10:47 +08:00

统一Message结构体

This commit is contained in:
源文雨
2023-11-16 22:57:47 +09:00
parent d2f8a94e75
commit 947bcc5121
12 changed files with 88 additions and 225 deletions

View File

@@ -485,14 +485,14 @@ func (ctx *Ctx) GetMyGuilds(before, after string, limit int) (guilds []Guild, er
// PostFileToQQUser 发送文件到 QQ 用户的 openid // PostFileToQQUser 发送文件到 QQ 用户的 openid
// //
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html#%E5%8F%91%E9%80%81%E5%88%B0%E5%8D%95%E8%81%8A // https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html#%E5%8F%91%E9%80%81%E5%88%B0%E5%8D%95%E8%81%8A
func (ctx *Ctx) PostFileToQQUser(id string, content *FilePost) (*IDTimestampMessageResult, error) { func (ctx *Ctx) PostFileToQQUser(id string, content *FilePost) (*Message, error) {
return ctx.caller.PostFileToQQUser(id, content) return ctx.caller.PostFileToQQUser(id, content)
} }
// PostFileToQQGroup 发送文件到 QQ 群的 openid // PostFileToQQGroup 发送文件到 QQ 群的 openid
// //
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html#%E5%8F%91%E9%80%81%E5%88%B0%E7%BE%A4%E8%81%8A // https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html#%E5%8F%91%E9%80%81%E5%88%B0%E7%BE%A4%E8%81%8A
func (ctx *Ctx) PostFileToQQGroup(id string, content *FilePost) (*IDTimestampMessageResult, error) { func (ctx *Ctx) PostFileToQQGroup(id string, content *FilePost) (*Message, error) {
return ctx.caller.PostFileToQQGroup(id, content) return ctx.caller.PostFileToQQGroup(id, content)
} }
@@ -503,14 +503,14 @@ func (ctx *Ctx) PostFileToQQGroup(id string, content *FilePost) (*IDTimestampMes
// PostMessageToQQUser 向 openid 指定的用户发送消息 // PostMessageToQQUser 向 openid 指定的用户发送消息
// //
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/send.html#%E5%8D%95%E8%81%8A // https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/send.html#%E5%8D%95%E8%81%8A
func (ctx *Ctx) PostMessageToQQUser(id string, content *MessagePostV2) (*IDTimestampMessageResult, error) { func (ctx *Ctx) PostMessageToQQUser(id string, content *MessagePost) (*Message, error) {
return ctx.caller.PostMessageToQQUser(id, content) return ctx.caller.PostMessageToQQUser(id, content)
} }
// PostMessageToQQGroup 向 openid 指定的群发送消息 // PostMessageToQQGroup 向 openid 指定的群发送消息
// //
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/send.html#%E7%BE%A4%E8%81%8A // https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/send.html#%E7%BE%A4%E8%81%8A
func (ctx *Ctx) PostMessageToQQGroup(id string, content *MessagePostV2) (*IDTimestampMessageResult, error) { func (ctx *Ctx) PostMessageToQQGroup(id string, content *MessagePost) (*Message, error) {
return ctx.caller.PostMessageToQQGroup(id, content) return ctx.caller.PostMessageToQQGroup(id, content)
} }

View File

@@ -6,7 +6,6 @@ import (
"reflect" "reflect"
"strings" "strings"
"sync" "sync"
"time"
) )
//go:generate go run codegen/context/main.go //go:generate go run codegen/context/main.go
@@ -86,9 +85,9 @@ func (ctx *Ctx) Send(messages Messages) (m []*Message, err error) {
var reply *Message var reply *Message
for _, msg := range messages { for _, msg := range messages {
switch msg.Type { switch msg.Type {
case MessageTypeText: case MessageSegmentTypeText:
textlist = append(textlist, msg.Data) textlist = append(textlist, msg.Data)
case MessageTypeImage: case MessageSegmentTypeImage:
reply, err = ctx.SendImage(msg.Data, isnextreply, textlist...) reply, err = ctx.SendImage(msg.Data, isnextreply, textlist...)
if isnextreply { if isnextreply {
isnextreply = false isnextreply = false
@@ -98,7 +97,7 @@ func (ctx *Ctx) Send(messages Messages) (m []*Message, err error) {
if err != nil { if err != nil {
return return
} }
case MessageTypeImageBytes: case MessageSegmentTypeImageBytes:
if ctx.IsQQ { if ctx.IsQQ {
continue continue
} }
@@ -111,30 +110,29 @@ func (ctx *Ctx) Send(messages Messages) (m []*Message, err error) {
if err != nil { if err != nil {
return return
} }
case MessageTypeReply: case MessageSegmentTypeReply:
isnextreply = true isnextreply = true
case MessageTypeAudio, MessageTypeVideo: case MessageSegmentTypeAudio, MessageSegmentTypeVideo:
if !ctx.IsQQ { if !ctx.IsQQ {
continue continue
} }
fp := &FilePost{ fp := &FilePost{
URL: msg.Data, URL: msg.Data,
} }
if msg.Type == MessageTypeAudio { if msg.Type == MessageSegmentTypeAudio {
fp.Type = FileTypeAudio fp.Type = FileTypeAudio
} else if msg.Type == MessageTypeVideo { } else if msg.Type == MessageSegmentTypeVideo {
fp.Type = FileTypeVideo fp.Type = FileTypeVideo
} }
var idts *IDTimestampMessageResult
if OnlyQQGroup(ctx) { if OnlyQQGroup(ctx) {
idts, err = ctx.PostFileToQQGroup(ctx.Message.ChannelID, fp) reply, err = ctx.PostFileToQQGroup(ctx.Message.ChannelID, fp)
} else if OnlyQQPrivate(ctx) { } else if OnlyQQPrivate(ctx) {
idts, err = ctx.PostFileToQQUser(ctx.Message.Author.ID, fp) reply, err = ctx.PostFileToQQUser(ctx.Message.Author.ID, fp)
} }
m = append(m, reply)
if err != nil { if err != nil {
return return
} }
reply = &Message{ID: idts.ID, Timestamp: time.Unix(int64(idts.Timestamp), 0)}
} }
} }
if len(textlist) > 0 { if len(textlist) > 0 {
@@ -168,35 +166,21 @@ func (ctx *Ctx) Post(replytosender bool, post *MessagePost) (reply *Message, err
} else if OnlyChannel(ctx) { } else if OnlyChannel(ctx) {
reply, err = ctx.PostMessageToChannel(msg.ChannelID, post) reply, err = ctx.PostMessageToChannel(msg.ChannelID, post)
} else { // v2 } else { // v2
var idts *IDTimestampMessageResult
typ := MessageTypeV2Text
switch { switch {
case post.Markdown != nil: case post.Markdown != nil:
typ = MessageTypeV2Markdown post.Type = MessageTypeMarkdown
case post.Ark != nil: case post.Ark != nil:
typ = MessageTypeV2Ark post.Type = MessageTypeArk
case post.Embed != nil: case post.Embed != nil:
typ = MessageTypeV2Embed post.Type = MessageTypeEmbed
} default:
v2post := &MessagePostV2{ post.Type = MessageTypeText
Type: typ,
Seq: len(GetTriggeredMessages(msg.ID)) + 1,
Content: post.Content,
ReplyMessageID: post.ReplyMessageID,
MessageReference: post.MessageReference,
Markdown: post.Markdown,
KeyBoard: post.KeyBoard,
Ark: post.Ark,
Embed: post.Embed,
} }
post.Seq = len(GetTriggeredMessages(msg.ID)) + 1
if OnlyQQGroup(ctx) { if OnlyQQGroup(ctx) {
idts, err = ctx.PostMessageToQQGroup(msg.ChannelID, v2post) reply, err = ctx.PostMessageToQQGroup(msg.ChannelID, post)
} else if OnlyQQPrivate(ctx) { } else if OnlyQQPrivate(ctx) {
idts, err = ctx.PostMessageToQQUser(msg.ChannelID, v2post) reply, err = ctx.PostMessageToQQUser(msg.ChannelID, post)
}
reply = &Message{
ID: idts.ID,
Timestamp: time.Unix(int64(idts.Timestamp), 0),
} }
} }
if err != nil && msg != nil && reply != nil && reply.ID != "" { if err != nil && msg != nil && reply != nil && reply.ID != "" {
@@ -213,24 +197,19 @@ func (ctx *Ctx) SendPlainMessage(replytosender bool, printable ...any) (*Message
} }
// SendImage 发送带图片消息到对方 // SendImage 发送带图片消息到对方
func (ctx *Ctx) SendImage(file string, replytosender bool, caption ...any) (*Message, error) { func (ctx *Ctx) SendImage(file string, replytosender bool, caption ...any) (reply *Message, err error) {
if OnlyQQ(ctx) { if OnlyQQ(ctx) {
var idts *IDTimestampMessageResult
var err error
fp := &FilePost{ fp := &FilePost{
Type: FileTypeImage, Type: FileTypeImage,
URL: file, URL: file,
} }
_, _ = ctx.SendPlainMessage(replytosender, caption...) _, _ = ctx.SendPlainMessage(replytosender, caption...)
if OnlyQQGroup(ctx) { if OnlyQQGroup(ctx) {
idts, err = ctx.PostFileToQQGroup(ctx.Message.ChannelID, fp) reply, err = ctx.PostFileToQQGroup(ctx.Message.ChannelID, fp)
} else if OnlyQQPrivate(ctx) { } else if OnlyQQPrivate(ctx) {
idts, err = ctx.PostFileToQQUser(ctx.Message.Author.ID, fp) reply, err = ctx.PostFileToQQUser(ctx.Message.Author.ID, fp)
} }
if err != nil { return
return nil, err
}
return &Message{ID: idts.ID, Timestamp: time.Unix(int64(idts.Timestamp), 0)}, nil
} }
post := &MessagePost{ post := &MessagePost{

View File

@@ -82,27 +82,15 @@ func (bot *Bot) processEvent(payload *WebsocketPayload) {
ctx.value = x ctx.value = x
switch tp { switch tp {
case "Message": case "Message":
ctx.Message = (*Message)(x.UnsafePointer())
if ctx.Message.MentionEveryone {
ctx.IsToMe = true
}
if ctx.IsQQ { if ctx.IsQQ {
msgv2 := (*MessageV2)(x.UnsafePointer()) if ctx.Message.Author.UserOpenID != "" {
ctx.Message = &Message{ ctx.Message.Author.ID = ctx.Message.Author.UserOpenID
ID: msgv2.ID, } else if ctx.Message.Author.MemberOpenID != "" {
Content: msgv2.Content, ctx.Message.Author.ID = ctx.Message.Author.MemberOpenID
ChannelID: msgv2.GroupOpenID,
GuildID: payload.T,
Timestamp: msgv2.Timestamp,
Attachments: msgv2.Attachments,
Author: &User{},
}
if msgv2.Author.UserOpenID != "" {
ctx.Message.Author.ID = msgv2.Author.UserOpenID
} else if msgv2.Author.MemberOpenID != "" {
ctx.Message.Author.ID = msgv2.Author.MemberOpenID
}
ctx.Value = ctx.Message
} else {
ctx.Message = (*Message)(x.UnsafePointer())
if ctx.Message.MentionEveryone {
ctx.IsToMe = true
} }
} }
log.Infoln(getLogHeader(), "=>", ctx.Message) log.Infoln(getLogHeader(), "=>", ctx.Message)

View File

@@ -70,8 +70,8 @@ type Handler struct {
OnAudioOrLiveChannelMemberExit func(s uint32, bot *Bot, d *AudioLiveChannelUsersChange) OnAudioOrLiveChannelMemberExit func(s uint32, bot *Bot, d *AudioLiveChannelUsersChange)
// QQ (1<<25) QQ 的一堆事件 // QQ (1<<25) QQ 的一堆事件
OnC2cMessageCreate func(s uint32, bot *Bot, d *MessageV2) OnC2cMessageCreate func(s uint32, bot *Bot, d *Message)
OnGroupAtMessageCreate func(s uint32, bot *Bot, d *MessageV2) OnGroupAtMessageCreate func(s uint32, bot *Bot, d *Message)
OnGroupAddRobot func(s uint32, bot *Bot, d *QQRobotStatus) OnGroupAddRobot func(s uint32, bot *Bot, d *QQRobotStatus)
OnGroupDelRobot func(s uint32, bot *Bot, d *QQRobotStatus) OnGroupDelRobot func(s uint32, bot *Bot, d *QQRobotStatus)
OnGroupMsgReject func(s uint32, bot *Bot, d *QQRobotStatus) OnGroupMsgReject func(s uint32, bot *Bot, d *QQRobotStatus)

View File

@@ -27,15 +27,15 @@ func GetTriggeredMessages(id string) []string {
return triggeredMessages.Get(id) return triggeredMessages.Get(id)
} }
type MessageType int type MessageSegmentType int
const ( const (
MessageTypeText MessageType = iota MessageSegmentTypeText MessageSegmentType = iota
MessageTypeImage MessageSegmentTypeImage
MessageTypeImageBytes MessageSegmentTypeImageBytes
MessageTypeReply MessageSegmentTypeReply
MessageTypeAudio MessageSegmentTypeAudio
MessageTypeVideo MessageSegmentTypeVideo
) )
// Message impl the array form of message // Message impl the array form of message
@@ -44,7 +44,7 @@ type Messages []MessageSegment
// MessageSegment impl the single message // MessageSegment impl the single message
// MessageSegment 消息数组 // MessageSegment 消息数组
type MessageSegment struct { type MessageSegment struct {
Type MessageType Type MessageSegmentType
Data string Data string
} }
@@ -56,7 +56,7 @@ func (m MessageSegment) String() string {
// Text 纯文本 // Text 纯文本
func Text(text ...interface{}) MessageSegment { func Text(text ...interface{}) MessageSegment {
return MessageSegment{ return MessageSegment{
Type: MessageTypeText, Type: MessageSegmentTypeText,
Data: HideURL(MessageEscape(fmt.Sprint(text...))), Data: HideURL(MessageEscape(fmt.Sprint(text...))),
} }
} }
@@ -65,7 +65,7 @@ func Text(text ...interface{}) MessageSegment {
// https://bot.q.qq.com/wiki/develop/api/openapi/message/message_format.html#%E6%94%AF%E6%8C%81%E7%9A%84%E6%A0%BC%E5%BC%8F // https://bot.q.qq.com/wiki/develop/api/openapi/message/message_format.html#%E6%94%AF%E6%8C%81%E7%9A%84%E6%A0%BC%E5%BC%8F
func Face(id int) MessageSegment { func Face(id int) MessageSegment {
return MessageSegment{ return MessageSegment{
Type: MessageTypeText, Type: MessageSegmentTypeText,
Data: "<emoji:" + strconv.Itoa(id) + ">", Data: "<emoji:" + strconv.Itoa(id) + ">",
} }
} }
@@ -73,7 +73,7 @@ func Face(id int) MessageSegment {
// Image 普通图片 // Image 普通图片
func Image(file string) MessageSegment { func Image(file string) MessageSegment {
return MessageSegment{ return MessageSegment{
Type: MessageTypeImage, Type: MessageSegmentTypeImage,
Data: file, Data: file,
} }
} }
@@ -81,7 +81,7 @@ func Image(file string) MessageSegment {
// ImageBytes 普通图片 // ImageBytes 普通图片
func ImageBytes(data []byte) MessageSegment { func ImageBytes(data []byte) MessageSegment {
return MessageSegment{ return MessageSegment{
Type: MessageTypeImageBytes, Type: MessageSegmentTypeImageBytes,
Data: BytesToString(data), Data: BytesToString(data),
} }
} }
@@ -93,7 +93,7 @@ func At(id string) MessageSegment {
return AtAll() return AtAll()
} }
return MessageSegment{ return MessageSegment{
Type: MessageTypeText, Type: MessageSegmentTypeText,
Data: "<@!" + id + ">", Data: "<@!" + id + ">",
} }
} }
@@ -102,7 +102,7 @@ func At(id string) MessageSegment {
// https://bot.q.qq.com/wiki/develop/api/openapi/message/message_format.html#%E6%94%AF%E6%8C%81%E7%9A%84%E6%A0%BC%E5%BC%8F // https://bot.q.qq.com/wiki/develop/api/openapi/message/message_format.html#%E6%94%AF%E6%8C%81%E7%9A%84%E6%A0%BC%E5%BC%8F
func AtAll() MessageSegment { func AtAll() MessageSegment {
return MessageSegment{ return MessageSegment{
Type: MessageTypeText, Type: MessageSegmentTypeText,
Data: "@everyone", Data: "@everyone",
} }
} }
@@ -111,7 +111,7 @@ func AtAll() MessageSegment {
// https://bot.q.qq.com/wiki/develop/api/openapi/message/message_format.html#%E6%94%AF%E6%8C%81%E7%9A%84%E6%A0%BC%E5%BC%8F // https://bot.q.qq.com/wiki/develop/api/openapi/message/message_format.html#%E6%94%AF%E6%8C%81%E7%9A%84%E6%A0%BC%E5%BC%8F
func AtChannel(id string) MessageSegment { func AtChannel(id string) MessageSegment {
return MessageSegment{ return MessageSegment{
Type: MessageTypeText, Type: MessageSegmentTypeText,
Data: "<#channel_id>", Data: "<#channel_id>",
} }
} }
@@ -120,7 +120,7 @@ func AtChannel(id string) MessageSegment {
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html // https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html
func Record(url string) MessageSegment { func Record(url string) MessageSegment {
return MessageSegment{ return MessageSegment{
Type: MessageTypeAudio, Type: MessageSegmentTypeAudio,
Data: url, Data: url,
} }
} }
@@ -129,7 +129,7 @@ func Record(url string) MessageSegment {
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html // https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html
func Video(url string) MessageSegment { func Video(url string) MessageSegment {
return MessageSegment{ return MessageSegment{
Type: MessageTypeVideo, Type: MessageSegmentTypeVideo,
Data: url, Data: url,
} }
} }
@@ -138,7 +138,7 @@ func Video(url string) MessageSegment {
// https://github.com/botuniverse/onebot-11/tree/master/message/segment.md#%E5%9B%9E%E5%A4%8D // https://github.com/botuniverse/onebot-11/tree/master/message/segment.md#%E5%9B%9E%E5%A4%8D
func ReplyTo(id string) MessageSegment { func ReplyTo(id string) MessageSegment {
return MessageSegment{ return MessageSegment{
Type: MessageTypeReply, Type: MessageSegmentTypeReply,
Data: id, Data: id,
} }
} }

View File

@@ -120,7 +120,7 @@ func (bot *Bot) DeleteOpenAPIWithPtr(ep, contenttype string, ptr any, body io.Re
return bot.dohttprequest(NewHTTPEndpointDeleteRequestWithAuth, ep, contenttype, ptr, body) return bot.dohttprequest(NewHTTPEndpointDeleteRequestWithAuth, ep, contenttype, ptr, body)
} }
//go:generate go run codegen/postopenapiof/main.go Channel GuildRoleCreate Message DMS IDTimestampMessageResult //go:generate go run codegen/postopenapiof/main.go Channel GuildRoleCreate Message DMS
// PostOpenAPI 从 ep 得到 json 结构化数据返回值写到 ptr, ptr 除 Slice 外必须在开头继承 CodeMessageBase // PostOpenAPI 从 ep 得到 json 结构化数据返回值写到 ptr, ptr 除 Slice 外必须在开头继承 CodeMessageBase
func (bot *Bot) PostOpenAPI(ep, contenttype string, ptr any, body io.Reader) error { func (bot *Bot) PostOpenAPI(ep, contenttype string, ptr any, body io.Reader) error {

View File

@@ -55,15 +55,3 @@ func (bot *Bot) postOpenAPIofDMS(ep, contenttype string, body io.Reader) (*DMS,
} }
return &resp.DMS, err return &resp.DMS, err
} }
func (bot *Bot) postOpenAPIofIDTimestampMessageResult(ep, contenttype string, body io.Reader) (*IDTimestampMessageResult, error) {
resp := &struct {
CodeMessageBase
IDTimestampMessageResult
}{}
err := bot.PostOpenAPI(ep, contenttype, resp, body)
if err != nil {
err = errors.Wrap(err, getCallerFuncName())
}
return &resp.IDTimestampMessageResult, err
}

View File

@@ -22,6 +22,7 @@ type Message struct {
ID string `json:"id"` ID string `json:"id"`
ChannelID string `json:"channel_id"` ChannelID string `json:"channel_id"`
GuildID string `json:"guild_id"` GuildID string `json:"guild_id"`
GroupOpenID string `json:"group_openid"`
Content string `json:"content"` Content string `json:"content"`
Timestamp time.Time `json:"timestamp"` Timestamp time.Time `json:"timestamp"`
EditedTimestamp time.Time `json:"edited_timestamp"` EditedTimestamp time.Time `json:"edited_timestamp"`
@@ -224,6 +225,9 @@ func (bot *Bot) GetMessageFromChannel(messageid, channelid string) (*Message, er
// //
// https://bot.q.qq.com/wiki/develop/api/openapi/message/post_messages.html#%E9%80%9A%E7%94%A8%E5%8F%82%E6%95%B0 // https://bot.q.qq.com/wiki/develop/api/openapi/message/post_messages.html#%E9%80%9A%E7%94%A8%E5%8F%82%E6%95%B0
type MessagePost struct { type MessagePost struct {
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/send.html
Type MessageType `json:"msg_type"`
Seq int `json:"msg_seq,omitempty"` // 回复消息的序号,与 msg_id 联合使用避免相同消息id回复重复发送不填默认是1。相同的 msg_id + msg_seq 重复发送会失败。
Content string `json:"content,omitempty"` Content string `json:"content,omitempty"`
Embed *MessageEmbed `json:"embed,omitempty"` // https://bot.q.qq.com/wiki/develop/api/openapi/message/template/embed_message.html Embed *MessageEmbed `json:"embed,omitempty"` // https://bot.q.qq.com/wiki/develop/api/openapi/message/template/embed_message.html
Ark *MessageArk `json:"ark,omitempty"` // https://bot.q.qq.com/wiki/develop/api/openapi/message/message_template.html Ark *MessageArk `json:"ark,omitempty"` // https://bot.q.qq.com/wiki/develop/api/openapi/message/message_template.html
@@ -239,6 +243,13 @@ type MessagePost struct {
func (mp *MessagePost) String() string { func (mp *MessagePost) String() string {
sb := strings.Builder{} sb := strings.Builder{}
if mp.Seq > 0 {
sb.WriteString("[v2:")
sb.WriteString(mp.Type.String())
sb.WriteString("#")
sb.WriteString(strconv.Itoa(mp.Seq))
sb.WriteString("]")
}
if mp.Content == "" { if mp.Content == "" {
sb.WriteString("无文本") sb.WriteString("无文本")
} else { } else {

View File

@@ -10,6 +10,8 @@ type User struct {
Bot bool `json:"bot"` Bot bool `json:"bot"`
UnionOpenid string `json:"union_openid"` UnionOpenid string `json:"union_openid"`
UnionUserAccount string `json:"union_user_account"` UnionUserAccount string `json:"union_user_account"`
UserOpenID string `json:"user_openid"`
MemberOpenID string `json:"member_openid"`
} }
// At 返回 <@!u.ID> // At 返回 <@!u.ID>

View File

@@ -1,10 +1,5 @@
package nano package nano
type IDTimestampMessageResult struct {
ID string `json:"id"`
Timestamp int `json:"timestamp"`
}
// QQRobotStatus https://bot.q.qq.com/wiki/develop/api-231017/server-inter/group.html#%E4%BA%8B%E4%BB%B6 // QQRobotStatus https://bot.q.qq.com/wiki/develop/api-231017/server-inter/group.html#%E4%BA%8B%E4%BB%B6
type QQRobotStatus struct { type QQRobotStatus struct {
OpenID string `json:"openid"` OpenID string `json:"openid"`

View File

@@ -59,17 +59,17 @@ func (fp *FilePost) String() string {
// PostFileToQQUser 发送文件到 QQ 用户的 openid // PostFileToQQUser 发送文件到 QQ 用户的 openid
// //
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html#%E5%8F%91%E9%80%81%E5%88%B0%E5%8D%95%E8%81%8A // https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html#%E5%8F%91%E9%80%81%E5%88%B0%E5%8D%95%E8%81%8A
func (bot *Bot) PostFileToQQUser(id string, content *FilePost) (*IDTimestampMessageResult, error) { func (bot *Bot) PostFileToQQUser(id string, content *FilePost) (*Message, error) {
logrus.Infoln(getLogHeader(), "<= [Q]单:", id+",", content) logrus.Infoln(getLogHeader(), "<= [Q]单:", id+",", content)
content.MotherFuckingAlwaysTrue = true content.MotherFuckingAlwaysTrue = true
return bot.postOpenAPIofIDTimestampMessageResult("/v2/users/"+id+"/files", "", WriteBodyFromJSON(content)) return bot.postOpenAPIofMessage("/v2/users/"+id+"/files", "", WriteBodyFromJSON(content))
} }
// PostFileToQQGroup 发送文件到 QQ 群的 openid // PostFileToQQGroup 发送文件到 QQ 群的 openid
// //
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html#%E5%8F%91%E9%80%81%E5%88%B0%E7%BE%A4%E8%81%8A // https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/rich-text-media.html#%E5%8F%91%E9%80%81%E5%88%B0%E7%BE%A4%E8%81%8A
func (bot *Bot) PostFileToQQGroup(id string, content *FilePost) (*IDTimestampMessageResult, error) { func (bot *Bot) PostFileToQQGroup(id string, content *FilePost) (*Message, error) {
logrus.Infoln(getLogHeader(), "<= [Q]群:", id+",", content) logrus.Infoln(getLogHeader(), "<= [Q]群:", id+",", content)
content.MotherFuckingAlwaysTrue = true content.MotherFuckingAlwaysTrue = true
return bot.postOpenAPIofIDTimestampMessageResult("/v2/groups/"+id+"/files", "", WriteBodyFromJSON(content)) return bot.postOpenAPIofMessage("/v2/groups/"+id+"/files", "", WriteBodyFromJSON(content))
} }

View File

@@ -2,149 +2,49 @@ package nano
import ( import (
"strconv" "strconv"
"strings"
"time"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
type MessageTypeV2 int type MessageType int
const ( const (
MessageTypeV2Text MessageTypeV2 = iota MessageTypeText MessageType = iota
MessageTypeV2TextImage MessageTypeTextImage
MessageTypeV2Markdown MessageTypeMarkdown
MessageTypeV2Ark MessageTypeArk
MessageTypeV2Embed MessageTypeEmbed
) )
func (mt2 MessageTypeV2) String() string { func (mt2 MessageType) String() string {
switch mt2 { switch mt2 {
case MessageTypeV2Text: case MessageTypeText:
return "文本" return "文本"
case MessageTypeV2TextImage: case MessageTypeTextImage:
return "图文混排" return "图文混排"
case MessageTypeV2Markdown: case MessageTypeMarkdown:
return "MD" return "MD"
case MessageTypeV2Ark: case MessageTypeArk:
return "模版" return "模版"
case MessageTypeV2Embed: case MessageTypeEmbed:
return "嵌入" return "嵌入"
default: default:
return "未知类型" + strconv.Itoa(int(mt2)) return "未知类型" + strconv.Itoa(int(mt2))
} }
} }
type MessageV2 struct {
Author struct {
UserOpenID string `json:"user_openid"`
MemberOpenID string `json:"member_openid"`
} `json:"author"`
Content string `json:"content"`
ID string `json:"id"`
GroupOpenID string `json:"group_openid"`
Timestamp time.Time `json:"timestamp"`
Attachments []MessageAttachment `json:"attachments"`
}
// MessagePostV2 V2 发消息结构体
//
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/send.html
type MessagePostV2 struct {
Type MessageTypeV2 `json:"msg_type"`
Seq int `json:"msg_seq,omitempty"` // 回复消息的序号,与 msg_id 联合使用避免相同消息id回复重复发送不填默认是1。相同的 msg_id + msg_seq 重复发送会失败。
Content string `json:"content"`
ReplyEventID string `json:"event_id,omitempty"` // 前置收到的事件ID用于发送被动消息
ReplyMessageID string `json:"msg_id,omitempty"`
// image 否 【暂不支持】
MessageReference *MessageReference `json:"message_reference,omitempty"` // 【暂未支持】消息引用
Markdown *MessageMarkdown `json:"markdown,omitempty"`
KeyBoard *MessageKeyboard `json:"keyboard,omitempty"`
Ark *MessageArk `json:"ark,omitempty"`
Embed *MessageEmbed `json:"embed,omitempty"`
}
func (mp *MessagePostV2) String() string {
sb := strings.Builder{}
sb.WriteString("[v2.")
sb.WriteString(mp.Type.String())
sb.WriteString(".")
sb.WriteString(strconv.Itoa(mp.Seq))
sb.WriteString("]")
if mp.Content == "" {
sb.WriteString("无文本")
} else {
sb.WriteString("文本: ")
sb.WriteString(mp.Content)
}
if mp.ReplyMessageID != "" {
sb.WriteString(", 回应消息: ")
sb.WriteString(mp.ReplyMessageID)
}
if mp.ReplyEventID != "" {
sb.WriteString(", 回应事件: ")
sb.WriteString(mp.ReplyEventID)
}
if mp.Embed != nil {
sb.WriteString(", 嵌入: <标题:")
sb.WriteString(mp.Embed.Title)
sb.WriteString(",提示:")
sb.WriteString(mp.Embed.Prompt)
sb.WriteByte('>')
}
if mp.Ark != nil {
sb.WriteString(", 模版: ")
sb.WriteString(strconv.Itoa(mp.Ark.TemplateID))
}
if mp.MessageReference != nil {
sb.WriteString(", 回复: ")
sb.WriteString(mp.MessageReference.MessageID)
}
/*if mp.Image != "" {
sb.WriteString(", 图片URL: ")
sb.WriteString(mp.Image)
}
if mp.ImageFile != "" {
sb.WriteString(", 图片内容: ")
x := mp.ImageFile
if len(x) > 64 {
x = x[:64] + "..."
}
sb.WriteString(x)
}
if len(mp.ImageBytes) > 0 {
sb.WriteString(", 图片大小: ")
sb.WriteString(strconv.Itoa(len(mp.ImageBytes)))
}*/
if mp.Markdown != nil {
sb.WriteString(", MD模版: ")
sb.WriteString(strconv.Itoa(mp.Markdown.TemplateID))
}
if mp.KeyBoard != nil {
sb.WriteString(", KB模版: ")
sb.WriteString(mp.KeyBoard.ID)
}
return sb.String()
}
func (bot *Bot) postV2MessageTo(ep string, content *MessagePostV2) (*IDTimestampMessageResult, error) {
return bot.postOpenAPIofIDTimestampMessageResult(ep, "", WriteBodyFromJSON(content))
}
// PostMessageToQQUser 向 openid 指定的用户发送消息 // PostMessageToQQUser 向 openid 指定的用户发送消息
// //
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/send.html#%E5%8D%95%E8%81%8A // https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/send.html#%E5%8D%95%E8%81%8A
func (bot *Bot) PostMessageToQQUser(id string, content *MessagePostV2) (*IDTimestampMessageResult, error) { func (bot *Bot) PostMessageToQQUser(id string, content *MessagePost) (*Message, error) {
logrus.Infoln(getLogHeader(), "<= [Q]单:", id+",", content) logrus.Infoln(getLogHeader(), "<= [Q]单:", id+",", content)
return bot.postV2MessageTo("/v2/users/"+id+"/messages", content) return bot.postMessageTo("/v2/users/"+id+"/messages", content)
} }
// PostMessageToQQGroup 向 openid 指定的群发送消息 // PostMessageToQQGroup 向 openid 指定的群发送消息
// //
// https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/send.html#%E7%BE%A4%E8%81%8A // https://bot.q.qq.com/wiki/develop/api-231017/server-inter/message/send-receive/send.html#%E7%BE%A4%E8%81%8A
func (bot *Bot) PostMessageToQQGroup(id string, content *MessagePostV2) (*IDTimestampMessageResult, error) { func (bot *Bot) PostMessageToQQGroup(id string, content *MessagePost) (*Message, error) {
logrus.Infoln(getLogHeader(), "<= [Q]群:", id+",", content) logrus.Infoln(getLogHeader(), "<= [Q]群:", id+",", content)
return bot.postV2MessageTo("/v2/groups/"+id+"/messages", content) return bot.postMessageTo("/v2/groups/"+id+"/messages", content)
} }