github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/client/online_push.go (about) 1 package client 2 3 import ( 4 "fmt" 5 "strconv" 6 "time" 7 8 "github.com/pkg/errors" 9 10 "github.com/Mrs4s/MiraiGo/binary" 11 "github.com/Mrs4s/MiraiGo/binary/jce" 12 "github.com/Mrs4s/MiraiGo/client/internal/network" 13 "github.com/Mrs4s/MiraiGo/client/pb" 14 "github.com/Mrs4s/MiraiGo/client/pb/msgtype0x210" 15 "github.com/Mrs4s/MiraiGo/client/pb/notify" 16 "github.com/Mrs4s/MiraiGo/internal/proto" 17 ) 18 19 var msg0x210Decoders = map[int64]func(*QQClient, []byte) error{ 20 0x8A: msgType0x210Sub8ADecoder, 0x8B: msgType0x210Sub8ADecoder, 0xB3: msgType0x210SubB3Decoder, 21 0xD4: msgType0x210SubD4Decoder, 0x27: msgType0x210Sub27Decoder, 0x122: msgType0x210Sub122Decoder, 22 0x123: msgType0x210Sub122Decoder, 0x44: msgType0x210Sub44Decoder, 23 } 24 25 // OnlinePush.ReqPush 26 func decodeOnlinePushReqPacket(c *QQClient, pkt *network.Packet) (any, error) { 27 request := &jce.RequestPacket{} 28 request.ReadFrom(jce.NewJceReader(pkt.Payload)) 29 data := &jce.RequestDataVersion2{} 30 data.ReadFrom(jce.NewJceReader(request.SBuffer)) 31 jr := jce.NewJceReader(data.Map["req"]["OnlinePushPack.SvcReqPushMsg"][1:]) 32 uin := jr.ReadInt64(0) 33 msgInfos := jr.ReadPushMessageInfos(2) 34 _ = c.sendPacket(c.buildDeleteOnlinePushPacket(uin, 0, nil, pkt.SequenceId, msgInfos)) 35 for _, m := range msgInfos { 36 k := fmt.Sprintf("%v%v%v", m.MsgSeq, m.MsgTime, m.MsgUid) 37 if _, ok := c.onlinePushCache.Get(k); ok { 38 continue 39 } 40 c.onlinePushCache.Add(k, unit{}, time.Second*30) 41 // 0x2dc 42 if m.MsgType == 732 { 43 r := binary.NewReader(m.VMsg) 44 groupCode := int64(uint32(r.ReadInt32())) 45 iType := r.ReadByte() 46 r.ReadByte() 47 switch iType { 48 case 0x0c: // 群内禁言 49 operator := int64(uint32(r.ReadInt32())) 50 if operator == c.Uin { 51 continue 52 } 53 r.ReadBytes(6) 54 target := int64(uint32(r.ReadInt32())) 55 t := r.ReadInt32() 56 57 if target != 0 { 58 member := c.FindGroup(groupCode).FindMember(target) 59 if t > 0 { 60 member.ShutUpTimestamp = time.Now().Add(time.Second * time.Duration(t)).Unix() 61 } else { 62 member.ShutUpTimestamp = 0 63 } 64 } 65 66 c.GroupMuteEvent.dispatch(c, &GroupMuteEvent{ 67 GroupCode: groupCode, 68 OperatorUin: operator, 69 TargetUin: target, 70 Time: t, 71 }) 72 case 0x10, 0x11, 0x14, 0x15: // group notify msg 73 r.ReadByte() 74 b := notify.NotifyMsgBody{} 75 _ = proto.Unmarshal(r.ReadAvailable(), &b) 76 if b.OptMsgRecall != nil { 77 for _, rm := range b.OptMsgRecall.RecalledMsgList { 78 if rm.MsgType == 2 { 79 continue 80 } 81 c.GroupMessageRecalledEvent.dispatch(c, &GroupMessageRecalledEvent{ 82 GroupCode: groupCode, 83 OperatorUin: b.OptMsgRecall.Uin, 84 AuthorUin: rm.AuthorUin, 85 MessageId: rm.Seq, 86 Time: rm.Time, 87 }) 88 } 89 } 90 if b.OptGeneralGrayTip != nil { 91 c.grayTipProcessor(groupCode, b.OptGeneralGrayTip) 92 } 93 if b.OptMsgRedTips != nil { 94 if b.OptMsgRedTips.LuckyFlag == 1 { // 运气王提示 95 c.GroupNotifyEvent.dispatch(c, &GroupRedBagLuckyKingNotifyEvent{ 96 GroupCode: groupCode, 97 Sender: int64(b.OptMsgRedTips.SenderUin), 98 LuckyKing: int64(b.OptMsgRedTips.LuckyUin), 99 }) 100 } 101 } 102 if b.QqGroupDigestMsg != nil { 103 digest := b.QqGroupDigestMsg 104 c.GroupDigestEvent.dispatch(c, &GroupDigestEvent{ 105 GroupCode: int64(digest.GroupCode), 106 MessageID: int32(digest.Seq), 107 InternalMessageID: int32(digest.Random), 108 OperationType: digest.OpType, 109 OperateTime: digest.OpTime, 110 SenderUin: int64(digest.Sender), 111 OperatorUin: int64(digest.DigestOper), 112 SenderNick: string(digest.SenderNick), 113 OperatorNick: string(digest.OperNick), 114 }) 115 } 116 if b.OptMsgGrayTips != nil { 117 c.msgGrayTipProcessor(groupCode, b.OptMsgGrayTips) 118 } 119 } 120 } 121 // 0x210 122 if m.MsgType == 528 { 123 vr := jce.NewJceReader(m.VMsg) 124 subType := vr.ReadInt64(0) 125 if decoder, ok := msg0x210Decoders[subType]; ok { 126 protobuf := vr.ReadBytes(10) 127 if err := decoder(c, protobuf); err != nil { 128 return nil, errors.Wrap(err, "decode online push 0x210 error") 129 } 130 } else { 131 c.debug("unknown online push 0x210 sub type 0x%v", strconv.FormatInt(subType, 16)) 132 } 133 } 134 } 135 return nil, nil 136 } 137 138 func msgType0x210Sub8ADecoder(c *QQClient, protobuf []byte) error { 139 s8a := pb.Sub8A{} 140 if err := proto.Unmarshal(protobuf, &s8a); err != nil { 141 return errors.Wrap(err, "failed to unmarshal protobuf message") 142 } 143 for _, m := range s8a.MsgInfo { 144 if m.ToUin == c.Uin { 145 c.FriendMessageRecalledEvent.dispatch(c, &FriendMessageRecalledEvent{ 146 FriendUin: m.FromUin, 147 MessageId: m.MsgSeq, 148 Time: m.MsgTime, 149 }) 150 } 151 } 152 return nil 153 } 154 155 func msgType0x210SubB3Decoder(c *QQClient, protobuf []byte) error { 156 b3 := pb.SubB3{} 157 if err := proto.Unmarshal(protobuf, &b3); err != nil { 158 return errors.Wrap(err, "failed to unmarshal protobuf message") 159 } 160 frd := &FriendInfo{ 161 Uin: b3.MsgAddFrdNotify.Uin, 162 Nickname: b3.MsgAddFrdNotify.Nick, 163 } 164 c.FriendList = append(c.FriendList, frd) 165 c.NewFriendEvent.dispatch(c, &NewFriendEvent{Friend: frd}) 166 return nil 167 } 168 169 func msgType0x210SubD4Decoder(c *QQClient, protobuf []byte) error { 170 d4 := pb.SubD4{} 171 if err := proto.Unmarshal(protobuf, &d4); err != nil { 172 return errors.Wrap(err, "failed to unmarshal protobuf message") 173 } 174 groupLeaveLock.Lock() 175 if g := c.FindGroup(d4.Uin); g != nil { 176 if err := c.ReloadGroupList(); err != nil { 177 groupLeaveLock.Unlock() 178 return err 179 } 180 c.GroupLeaveEvent.dispatch(c, &GroupLeaveEvent{Group: g}) 181 } 182 groupLeaveLock.Unlock() 183 return nil 184 } 185 186 func msgType0x210Sub27Decoder(c *QQClient, protobuf []byte) error { 187 s27 := msgtype0x210.SubMsg0X27Body{} 188 if err := proto.Unmarshal(protobuf, &s27); err != nil { 189 return errors.Wrap(err, "failed to unmarshal protobuf message") 190 } 191 for _, m := range s27.ModInfos { 192 if m.ModGroupProfile != nil { 193 for _, info := range m.ModGroupProfile.GroupProfileInfos { 194 if info.Field.Unwrap() == 1 { 195 if g := c.FindGroup(int64(m.ModGroupProfile.GroupCode.Unwrap())); g != nil { 196 old := g.Name 197 g.Name = string(info.Value) 198 c.GroupNameUpdatedEvent.dispatch(c, &GroupNameUpdatedEvent{ 199 Group: g, 200 OldName: old, 201 NewName: g.Name, 202 OperatorUin: int64(m.ModGroupProfile.CmdUin.Unwrap()), 203 }) 204 } 205 } 206 } 207 } 208 if m.DelFriend != nil { 209 frdUin := m.DelFriend.Uins[0] 210 if frd := c.FindFriend(int64(frdUin)); frd != nil { 211 c.DeleteFriendEvent.dispatch(c, &DeleteFriendEvent{ 212 Uin: frd.Uin, 213 Nickname: frd.Nickname, 214 }) 215 if err := c.ReloadFriendList(); err != nil { 216 return errors.Wrap(err, "failed to reload friend list") 217 } 218 } 219 } 220 } 221 return nil 222 } 223 224 func msgType0x210Sub122Decoder(c *QQClient, protobuf []byte) error { 225 t := ¬ify.GeneralGrayTipInfo{} 226 _ = proto.Unmarshal(protobuf, t) 227 var sender, receiver int64 228 for _, templ := range t.MsgTemplParam { 229 if templ.Name == "uin_str1" { 230 sender, _ = strconv.ParseInt(templ.Value, 10, 64) 231 } else if templ.Name == "uin_str2" { 232 receiver, _ = strconv.ParseInt(templ.Value, 10, 64) 233 } 234 } 235 if sender == 0 { 236 return nil 237 } 238 if receiver == 0 { 239 receiver = c.Uin 240 } 241 c.FriendNotifyEvent.dispatch(c, &FriendPokeNotifyEvent{ 242 Sender: sender, 243 Receiver: receiver, 244 }) 245 return nil 246 } 247 248 func msgType0x210Sub44Decoder(c *QQClient, protobuf []byte) error { 249 s44 := pb.Sub44{} 250 if err := proto.Unmarshal(protobuf, &s44); err != nil { 251 return errors.Wrap(err, "failed to unmarshal protobuf message") 252 } 253 if s44.GroupSyncMsg == nil { 254 return nil 255 } 256 groupJoinLock.Lock() 257 defer groupJoinLock.Unlock() 258 if s44.GroupSyncMsg.GrpCode == 0 { // member sync 259 return errors.New("invalid group code") 260 } 261 c.debug("syncing members.") 262 if group := c.FindGroup(s44.GroupSyncMsg.GrpCode); group != nil { 263 group.lock.Lock() 264 defer group.lock.Unlock() 265 266 var lastJoinTime int64 = 0 267 for _, m := range group.Members { 268 if lastJoinTime < m.JoinTime { 269 lastJoinTime = m.JoinTime 270 } 271 } 272 273 if newMem, err := c.GetGroupMembers(group); err == nil { 274 group.Members = newMem 275 for _, m := range newMem { 276 if lastJoinTime < m.JoinTime { 277 c.GroupMemberJoinEvent.dispatch(c, &MemberJoinGroupEvent{ 278 Group: group, 279 Member: m, 280 }) 281 } 282 } 283 } 284 } 285 return nil 286 }