diff --git a/client/events.go b/client/events.go index 143c8fb7..d90bd18c 100644 --- a/client/events.go +++ b/client/events.go @@ -14,6 +14,7 @@ type eventHandlers struct { groupMessageHandlers []func(*QQClient, *message.GroupMessage) selfPrivateMessageHandlers []func(*QQClient, *message.PrivateMessage) selfGroupMessageHandlers []func(*QQClient, *message.GroupMessage) + guildChannelMessageHandlers []func(*QQClient, *message.GuildChannelMessage) groupMuteEventHandlers []func(*QQClient, *GroupMuteEvent) groupRecalledHandlers []func(*QQClient, *GroupMessageRecalledEvent) friendRecalledHandlers []func(*QQClient, *FriendMessageRecalledEvent) @@ -68,6 +69,10 @@ func (c *QQClient) OnSelfGroupMessage(f func(*QQClient, *message.GroupMessage)) c.eventHandlers.selfGroupMessageHandlers = append(c.eventHandlers.selfGroupMessageHandlers, f) } +func (s *GuildService) OnGuildChannelMessage(f func(*QQClient, *message.GuildChannelMessage)) { + s.c.eventHandlers.guildChannelMessageHandlers = append(s.c.eventHandlers.guildChannelMessageHandlers, f) +} + func (c *QQClient) OnGroupMuted(f func(*QQClient, *GroupMuteEvent)) { c.eventHandlers.groupMuteEventHandlers = append(c.eventHandlers.groupMuteEventHandlers, f) } @@ -230,6 +235,17 @@ func (c *QQClient) dispatchGroupMessageSelf(msg *message.GroupMessage) { } } +func (c *QQClient) dispatchGuildChannelMessage(msg *message.GuildChannelMessage) { + if msg == nil { + return + } + for _, f := range c.eventHandlers.guildChannelMessageHandlers { + cover(func() { + f(c, msg) + }) + } +} + func (c *QQClient) dispatchGroupMuteEvent(e *GroupMuteEvent) { if e == nil { return diff --git a/client/guild.go b/client/guild.go index 12ad72ef..24868e94 100644 --- a/client/guild.go +++ b/client/guild.go @@ -2,6 +2,7 @@ package client import ( "fmt" + "github.com/Mrs4s/MiraiGo/message" "github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/client/pb/channel" @@ -80,28 +81,36 @@ type ( ) func init() { - decoders["trpc.group_pro.synclogic.SyncLogic.PushFirstView"] = decodeChannelPushFirstView - decoders["MsgPush.PushGroupProMsg"] = decodeChannelMessagePushPacket + decoders["trpc.group_pro.synclogic.SyncLogic.PushFirstView"] = decodeGuildPushFirstView + decoders["MsgPush.PushGroupProMsg"] = decodeGuildMessagePushPacket } -func (c *QQClient) syncChannelFirstView() { - rsp, err := c.sendAndWaitDynamic(c.buildSyncChannelFirstViewPacket()) - if err != nil { - c.Error("sync channel error: %v", err) - return +func (s *GuildService) FindGuild(guildId uint64) *GuildInfo { + for _, i := range s.Guilds { + if i.GuildId == guildId { + return i + } } - firstViewRsp := new(channel.FirstViewRsp) - if err = proto.Unmarshal(rsp, firstViewRsp); err != nil { - return + return nil +} + +func (g *GuildInfo) FindMember(tinyId uint64) *GuildMemberInfo { + for i := 0; i < len(g.Members); i++ { + if g.Members[i].TinyId == tinyId { + return g.Members[i] + } } - c.GuildService.TinyId = firstViewRsp.GetSelfTinyid() - c.GuildService.GuildCount = firstViewRsp.GetGuildCount() - if self, err := c.GuildService.GetUserProfile(c.GuildService.TinyId); err == nil { - c.GuildService.Nickname = self.Nickname - c.GuildService.AvatarUrl = self.AvatarUrl - } else { - c.Error("get self guild profile error: %v", err) + for i := 0; i < len(g.Admins); i++ { + if g.Admins[i].TinyId == tinyId { + return g.Admins[i] + } } + for i := 0; i < len(g.Bots); i++ { + if g.Bots[i].TinyId == tinyId { + return g.Bots[i] + } + } + return nil } func (s *GuildService) GetUserProfile(tinyId uint64) (*GuildUserProfile, error) { @@ -150,7 +159,7 @@ func (s *GuildService) GetGuildMembers(guildId uint64) (bots []*GuildMemberInfo, 1: u1, 2: u1, 3: u1, 4: u1, 5: u1, 6: u1, 7: u1, 8: u1, 20: u1, }, 6: uint32(0), - 8: uint32(500), // max response? + 8: uint32(500), // count 14: uint32(2), }) packet := packets.BuildUniPacket(s.c.Uin, seq, "OidbSvcTrpcTcp.0xf5b_1", 1, s.c.OutGoingPacketSessionId, []byte{}, s.c.sigInfo.d2Key, payload) @@ -289,6 +298,26 @@ func (s *GuildService) fetchChannelListState(guildId uint64, channels []*Channel } */ +func (c *QQClient) syncChannelFirstView() { + rsp, err := c.sendAndWaitDynamic(c.buildSyncChannelFirstViewPacket()) + if err != nil { + c.Error("sync channel error: %v", err) + return + } + firstViewRsp := new(channel.FirstViewRsp) + if err = proto.Unmarshal(rsp, firstViewRsp); err != nil { + return + } + c.GuildService.TinyId = firstViewRsp.GetSelfTinyid() + c.GuildService.GuildCount = firstViewRsp.GetGuildCount() + if self, err := c.GuildService.GetUserProfile(c.GuildService.TinyId); err == nil { + c.GuildService.Nickname = self.Nickname + c.GuildService.AvatarUrl = self.AvatarUrl + } else { + c.Error("get self guild profile error: %v", err) + } +} + func (c *QQClient) buildSyncChannelFirstViewPacket() (uint16, []byte) { seq := c.nextSeq() req := &channel.FirstViewReq{ @@ -301,11 +330,26 @@ func (c *QQClient) buildSyncChannelFirstViewPacket() (uint16, []byte) { return seq, packet } -func decodeChannelMessagePushPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGuildMessagePushPacket(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { + push := new(channel.MsgOnlinePush) + if err := proto.Unmarshal(payload, push); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal protobuf message") + } + for _, m := range push.Msgs { + if m.Head.ContentHead.GetType() == 3841 { + if m.Head.ContentHead.GetSubType() != 2 { + continue + } + continue + } + if cm := c.parseGuildChannelMessage(m); cm != nil { + c.dispatchGuildChannelMessage(cm) + } + } return nil, nil } -func decodeChannelPushFirstView(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { +func decodeGuildPushFirstView(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { firstViewMsg := new(channel.FirstViewMsg) if err := proto.Unmarshal(payload, firstViewMsg); err != nil { return nil, errors.Wrap(err, "failed to unmarshal protobuf message") @@ -335,7 +379,6 @@ func decodeChannelPushFirstView(c *QQClient, _ *incomingPacketInfo, payload []by } info.Bots, info.Members, info.Admins, _ = c.GuildService.GetGuildMembers(info.GuildId) c.GuildService.Guilds = append(c.GuildService.Guilds, info) - c.GuildService.FetchGuestGuild(info.GuildId) } } if len(firstViewMsg.ChannelMsgs) > 0 { // sync msg @@ -343,3 +386,23 @@ func decodeChannelPushFirstView(c *QQClient, _ *incomingPacketInfo, payload []by } return nil, nil } + +func (c *QQClient) parseGuildChannelMessage(msg *channel.ChannelMsgContent) *message.GuildChannelMessage { + guild := c.GuildService.FindGuild(msg.Head.RoutingHead.GetGuildId()) + if guild == nil { + return nil // todo: sync guild info + } + // mem := guild.FindMember(msg.Head.RoutingHead.GetFromTinyid()) + return &message.GuildChannelMessage{ + Id: msg.Head.ContentHead.GetSeq(), + InternalId: msg.Body.RichText.Attr.GetRandom(), + GuildId: msg.Head.RoutingHead.GetGuildId(), + ChannelId: msg.Head.RoutingHead.GetChannelId(), + Time: int64(msg.Head.ContentHead.GetTime()), + Sender: &message.GuildSender{ + TinyId: msg.Head.RoutingHead.GetFromTinyid(), + Nickname: string(msg.ExtInfo.GetFromNick()), + }, + Elements: message.ParseMessageElems(msg.Body.RichText.Elems), + } +} diff --git a/message/message.go b/message/message.go index 53b24c90..e8b76256 100644 --- a/message/message.go +++ b/message/message.go @@ -46,6 +46,16 @@ type ( // OriginalElements []*msg.Elem } + GuildChannelMessage struct { + Id uint64 + InternalId int32 + GuildId uint64 + ChannelId uint64 + Time int64 + Sender *GuildSender + Elements []IMessageElement + } + SendingMessage struct { Elements []IMessageElement } @@ -58,6 +68,11 @@ type ( IsFriend bool } + GuildSender struct { + TinyId uint64 + Nickname string + } + AnonymousInfo struct { AnonymousId string AnonymousNick string