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 := &notify.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  }