diff --git a/client/client.go b/client/client.go index 29740438..9d9a0750 100644 --- a/client/client.go +++ b/client/client.go @@ -8,7 +8,6 @@ import ( "errors" "fmt" "io" - "log" "math" "math/rand" "net" @@ -1029,7 +1028,8 @@ func (c *QQClient) netLoop() { } rsp, err := decoder(c, pkt.SequenceId, payload) if err != nil { - log.Println("decode", pkt.CommandName, "error:", err) + c.Error("decode pkt %v error: %v", pkt.CommandName, err) + //log.Println("decode", pkt.CommandName, "error:", err) } if f, ok := c.handlers.Load(pkt.SequenceId); ok { c.handlers.Delete(pkt.SequenceId) diff --git a/client/decoders.go b/client/decoders.go index 2fca3b11..910e92b3 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -188,7 +188,7 @@ func decodeMessageSvcPacket(c *QQClient, _ uint16, payload []byte) (interface{}, if (int64(pairMsg.LastReadTime) & 4294967295) > int64(message.Head.MsgTime) { continue } - strKey := strconv.FormatInt(message.Head.MsgUid, 10) + strKey := fmt.Sprintf("%d%d%d%d", message.Head.FromUin, message.Head.ToUin, message.Head.MsgSeq, message.Head.MsgUid) if _, ok := c.msgSvcCache.Get(strKey); ok { continue } @@ -559,24 +559,7 @@ func decodeOnlinePushReqPacket(c *QQClient, seq uint16, payload []byte) (interfa } } if b.OptGeneralGrayTip != nil { - switch b.OptGeneralGrayTip.TemplId { - case 10043, 1136: // 戳一戳 - var sender int64 = 0 - receiver := c.Uin - for _, templ := range b.OptGeneralGrayTip.MsgTemplParam { - if templ.Name == "uin_str1" { - sender, _ = strconv.ParseInt(templ.Value, 10, 64) - } - if templ.Name == "uin_str2" { - receiver, _ = strconv.ParseInt(templ.Value, 10, 64) - } - } - c.dispatchGroupNotifyEvent(&GroupPokeNotifyEvent{ - GroupCode: groupId, - Sender: sender, - Receiver: receiver, - }) - } + c.grayTipProcessor(groupId, b.OptGeneralGrayTip) } if b.OptMsgRedTips != nil { if b.OptMsgRedTips.LuckyFlag == 1 { // 运气王提示 @@ -892,11 +875,19 @@ func decodeMultiApplyDownResponse(c *QQClient, _ uint16, payload []byte) (interf return nil, errors.New("not found") } rsp := body.MultimsgApplydownRsp[0] - i := binary.UInt32ToIPV4Address(uint32(rsp.Uint32DownIp[0])) - b, err := utils.HttpGetBytes(fmt.Sprintf("http://%s:%d%s", i, body.MultimsgApplydownRsp[0].Uint32DownPort[0], string(rsp.ThumbDownPara)), "") + prefix := func() string { + if rsp.MsgExternInfo != nil && rsp.MsgExternInfo.ChannelType == 2 { + return "https://ssl.htdata.qq.com" + } + return fmt.Sprintf("http://%s:%d", binary.UInt32ToIPV4Address(uint32(rsp.Uint32DownIp[0])), body.MultimsgApplydownRsp[0].Uint32DownPort[0]) + }() + b, err := utils.HttpGetBytes(fmt.Sprintf("%s%s", prefix, string(rsp.ThumbDownPara)), "") if err != nil { return nil, err } + if b[0] != 40 { + return nil, errors.New("unexpected body data") + } tea := binary.NewTeaCipher(body.MultimsgApplydownRsp[0].MsgKey) r := binary.NewReader(b[1:]) i1 := r.ReadInt32() diff --git a/client/entities.go b/client/entities.go index 7f4a64e1..5a91eccc 100644 --- a/client/entities.go +++ b/client/entities.go @@ -107,7 +107,6 @@ type ( IGroupNotifyEvent interface { From() int64 - Name() string Content() string } diff --git a/client/global.go b/client/global.go index 1da005dd..8d58060f 100644 --- a/client/global.go +++ b/client/global.go @@ -305,10 +305,6 @@ func (c *QQClient) parseGroupMessage(m *msg.Message) *message.GroupMessage { } // pre parse for _, elem := range m.Body.RichText.Elems { - // 为什么小程序会同时通过RichText和long text发送 - if elem.LightApp != nil { - break - } // is rich long msg if elem.GeneralFlags != nil && elem.GeneralFlags.LongTextResid != "" { if f := c.GetForwardMessage(elem.GeneralFlags.LongTextResid); f != nil && len(f.Nodes) == 1 { diff --git a/client/notify.go b/client/notify.go index 1b50118e..bfa90359 100644 --- a/client/notify.go +++ b/client/notify.go @@ -1,6 +1,10 @@ package client -import "fmt" +import ( + "fmt" + "github.com/Mrs4s/MiraiGo/client/pb/notify" + "strconv" +) type ( // GroupPokeNotifyEvent 群内戳一戳提示事件 @@ -16,16 +20,70 @@ type ( Sender int64 LuckyKing int64 } + + // MemberHonorChangedNotifyEvent 群成员荣誉变更提示事件 + MemberHonorChangedNotifyEvent struct { + GroupCode int64 + Honor HonorType + Uin int64 + Nick string + } ) +// grayTipProcessor 提取出来专门用于处理群内 notify tips +func (c *QQClient) grayTipProcessor(groupId int64, tipInfo *notify.GeneralGrayTipInfo) { + switch tipInfo.TemplId { + case 10043, 1136: // 戳一戳 + var sender int64 = 0 + receiver := c.Uin + for _, templ := range tipInfo.MsgTemplParam { + if templ.Name == "uin_str1" { + sender, _ = strconv.ParseInt(templ.Value, 10, 64) + } + if templ.Name == "uin_str2" { + receiver, _ = strconv.ParseInt(templ.Value, 10, 64) + } + } + c.dispatchGroupNotifyEvent(&GroupPokeNotifyEvent{ + GroupCode: groupId, + Sender: sender, + Receiver: receiver, + }) + case 1052, 1053, 1054, 1067: // 群荣誉 + var nick string + var uin int64 + for _, templ := range tipInfo.MsgTemplParam { + if templ.Name == "nick" { + nick = templ.Value + } + if templ.Name == "uin" { + uin, _ = strconv.ParseInt(templ.Value, 10, 64) + } + } + c.dispatchGroupNotifyEvent(&MemberHonorChangedNotifyEvent{ + GroupCode: groupId, + Honor: func() HonorType { + switch tipInfo.TemplId { + case 1052: + return Performer + case 1053, 1054: + return Talkative + case 1067: + return Emotion + default: + return 0 + } + }(), + Uin: uin, + Nick: nick, + }) + } +} + func (e *GroupPokeNotifyEvent) From() int64 { return e.GroupCode } -func (e *GroupPokeNotifyEvent) Name() string { - return "戳一戳" -} - func (e *GroupPokeNotifyEvent) Content() string { return fmt.Sprintf("%d戳了戳%d", e.Sender, e.Receiver) } @@ -34,10 +92,22 @@ func (e *GroupRedBagLuckyKingNotifyEvent) From() int64 { return e.GroupCode } -func (e *GroupRedBagLuckyKingNotifyEvent) Name() string { - return "运气王" -} - func (e *GroupRedBagLuckyKingNotifyEvent) Content() string { return fmt.Sprintf("%d发的红包被领完, %d是运气王", e.Sender, e.LuckyKing) } + +func (e *MemberHonorChangedNotifyEvent) From() int64 { + return e.GroupCode +} + +func (e *MemberHonorChangedNotifyEvent) Content() string { + switch e.Honor { + case Talkative: + return fmt.Sprintf("昨日 %s(%d) 在群 %d 内发言最积极, 获得 龙王 标识。", e.Nick, e.Uin, e.GroupCode) + case Performer: + return fmt.Sprintf("%s(%d) 在群 %d 里连续发消息超过7天, 获得 群聊之火 标识。", e.Nick, e.Uin, e.GroupCode) + case Emotion: + return fmt.Sprintf("%s(%d) 在群聊 %d 中连续发表情包超过3天,且累计数量超过20条,获得 快乐源泉 标识。", e.Nick, e.Uin, e.GroupCode) + } + return "ERROR" +}