github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/client/decoders.go (about) 1 package client 2 3 import ( 4 "crypto/md5" 5 "fmt" 6 "net/netip" 7 "strconv" 8 "strings" 9 "sync" 10 "time" 11 12 "github.com/pkg/errors" 13 14 "github.com/Mrs4s/MiraiGo/binary" 15 "github.com/Mrs4s/MiraiGo/binary/jce" 16 "github.com/Mrs4s/MiraiGo/client/internal/auth" 17 "github.com/Mrs4s/MiraiGo/client/internal/network" 18 "github.com/Mrs4s/MiraiGo/client/internal/tlv" 19 "github.com/Mrs4s/MiraiGo/client/pb" 20 "github.com/Mrs4s/MiraiGo/client/pb/cmd0x352" 21 "github.com/Mrs4s/MiraiGo/client/pb/cmd0x6ff" 22 "github.com/Mrs4s/MiraiGo/client/pb/msg" 23 "github.com/Mrs4s/MiraiGo/client/pb/oidb" 24 "github.com/Mrs4s/MiraiGo/client/pb/profilecard" 25 "github.com/Mrs4s/MiraiGo/client/pb/structmsg" 26 "github.com/Mrs4s/MiraiGo/internal/proto" 27 "github.com/Mrs4s/MiraiGo/utils" 28 ) 29 30 var ( 31 groupJoinLock sync.Mutex 32 groupLeaveLock sync.Mutex 33 ) 34 35 // wtlogin.login 36 func decodeLoginResponse(c *QQClient, pkt *network.Packet) (any, error) { 37 reader := binary.NewReader(pkt.Payload) 38 reader.ReadUInt16() // sub command 39 t := reader.ReadByte() 40 reader.ReadUInt16() 41 m, err := tlv.NewDecoder(2, 2).DecodeRecordMap(reader.ReadAvailable()) 42 if err != nil { 43 return nil, err 44 } 45 if m.Exists(0x402) { 46 c.sig.Dpwd = []byte(utils.RandomString(16)) 47 c.sig.T402 = m[0x402] 48 h := md5.Sum(append(append(c.Device().Guid, c.sig.Dpwd...), c.sig.T402...)) 49 c.sig.G = h[:] 50 } 51 if m.Exists(0x546) { 52 c.sig.T547 = auth.CalcPow(m[0x546]) 53 } 54 // c.logger.Info("login response %v", t) 55 if t == 0 { // login success 56 // if t150, ok := m[0x150]; ok { 57 // c.t150 = t150 58 // } 59 // if t161, ok := m[0x161]; ok { 60 // c.decodeT161(t161) 61 // } 62 if m.Exists(0x403) { 63 c.sig.RandSeed = m[0x403] 64 } 65 c.decodeT119(m[0x119], c.Device().TgtgtKey) 66 return LoginResponse{ 67 Success: true, 68 }, nil 69 } 70 if t == 2 { 71 c.sig.T104 = m[0x104] 72 if m.Exists(0x192) { 73 return LoginResponse{ 74 Success: false, 75 Code: t, 76 VerifyUrl: string(m[0x192]), 77 Error: SliderNeededError, 78 }, nil 79 } 80 if m.Exists(0x165) { // image 81 imgData := binary.NewReader(m[0x105]) 82 signLen := imgData.ReadUInt16() 83 imgData.ReadUInt16() 84 sign := imgData.ReadBytes(int(signLen)) 85 return LoginResponse{ 86 Success: false, 87 Code: t, 88 Error: NeedCaptcha, 89 CaptchaImage: imgData.ReadAvailable(), 90 CaptchaSign: sign, 91 }, nil 92 } else { 93 return LoginResponse{ 94 Success: false, 95 Code: t, 96 Error: UnknownLoginError, 97 }, nil 98 } 99 } // need captcha 100 101 if t == 40 { 102 return LoginResponse{ 103 Success: false, 104 Code: t, 105 ErrorMessage: "账号被冻结", 106 Error: UnknownLoginError, 107 }, nil 108 } 109 110 if t == 160 || t == 239 { 111 if t174, ok := m[0x174]; ok { // 短信验证 112 c.sig.T104 = m[0x104] 113 c.sig.T174 = t174 114 c.sig.RandSeed = m[0x403] 115 phone := func() string { 116 r := binary.NewReader(m[0x178]) 117 r.ReadStringShort() 118 return r.ReadStringShort() 119 }() 120 if t204, ok := m[0x204]; ok { // 同时支持扫码验证 ? 121 return LoginResponse{ 122 Success: false, 123 Code: t, 124 Error: SMSOrVerifyNeededError, 125 VerifyUrl: string(t204), 126 SMSPhone: phone, 127 ErrorMessage: string(m[0x17e]), 128 }, nil 129 } 130 return LoginResponse{ 131 Success: false, 132 Code: t, 133 Error: SMSNeededError, 134 SMSPhone: phone, 135 ErrorMessage: string(m[0x17e]), 136 }, nil 137 } 138 139 if _, ok := m[0x17b]; ok { // 二次验证 140 c.sig.T104 = m[0x104] 141 return LoginResponse{ 142 Success: false, 143 Code: t, 144 Error: SMSNeededError, 145 }, nil 146 } 147 148 if t204, ok := m[0x204]; ok { // 扫码验证 149 return LoginResponse{ 150 Success: false, 151 Code: t, 152 Error: UnsafeDeviceError, 153 VerifyUrl: string(t204), 154 ErrorMessage: "", 155 }, nil 156 } 157 } 158 159 if t == 162 { 160 return LoginResponse{ 161 Code: t, 162 Error: TooManySMSRequestError, 163 }, nil 164 } 165 166 if t == 204 { 167 c.sig.T104 = m[0x104] 168 c.sig.RandSeed = m[0x403] 169 return c.sendAndWait(c.buildDeviceLockLoginPacket()) 170 } // drive lock 171 172 if t149, ok := m[0x149]; ok { 173 t149r := binary.NewReader(t149) 174 t149r.ReadBytes(2) 175 t149r.ReadStringShort() // title 176 return LoginResponse{ 177 Success: false, 178 Code: t, 179 Error: OtherLoginError, 180 ErrorMessage: t149r.ReadStringShort(), 181 }, nil 182 } 183 184 if t146, ok := m[0x146]; ok { 185 t146r := binary.NewReader(t146) 186 t146r.ReadBytes(4) // ver and code 187 t146r.ReadStringShort() // title 188 return LoginResponse{ 189 Success: false, 190 Code: t, 191 Error: OtherLoginError, 192 ErrorMessage: t146r.ReadStringShort(), 193 }, nil 194 } 195 c.debug("unknown login response: %v", t) 196 for k, v := range m { 197 c.debug("Type: %d Value: %x", k, v) 198 } 199 return nil, errors.Errorf("unknown login response: %v", t) // ? 200 } 201 202 // StatSvc.register 203 func decodeClientRegisterResponse(c *QQClient, pkt *network.Packet) (any, error) { 204 request := &jce.RequestPacket{} 205 request.ReadFrom(jce.NewJceReader(pkt.Payload)) 206 data := &jce.RequestDataVersion2{} 207 data.ReadFrom(jce.NewJceReader(request.SBuffer)) 208 svcRsp := &jce.SvcRespRegister{} 209 svcRsp.ReadFrom(jce.NewJceReader(data.Map["SvcRespRegister"]["QQService.SvcRespRegister"][1:])) 210 if svcRsp.Result != "" || svcRsp.ReplyCode != 0 { 211 if svcRsp.Result != "" { 212 c.error("reg error: %v", svcRsp.Result) 213 } 214 return nil, errors.New("reg failed") 215 } 216 return nil, nil 217 } 218 219 // wtlogin.exchange_emp 220 func decodeExchangeEmpResponse(c *QQClient, pkt *network.Packet) (any, error) { 221 reader := binary.NewReader(pkt.Payload) 222 cmd := reader.ReadUInt16() 223 t := reader.ReadByte() 224 reader.ReadUInt16() 225 m, err := tlv.NewDecoder(2, 2).DecodeRecordMap(reader.ReadAvailable()) 226 if err != nil { 227 return nil, err 228 } 229 if t != 0 { 230 return nil, errors.Errorf("exchange_emp failed: %v", t) 231 } 232 if cmd == 15 { 233 c.decodeT119R(m[0x119]) 234 } 235 if cmd == 11 { 236 h := md5.Sum(c.sig.D2Key) 237 c.decodeT119(m[0x119], h[:]) 238 } 239 return nil, nil 240 } 241 242 // wtlogin.trans_emp 243 func decodeTransEmpResponse(c *QQClient, pkt *network.Packet) (any, error) { 244 if len(pkt.Payload) < 48 { 245 return nil, errors.New("missing payload length") 246 } 247 reader := binary.NewReader(pkt.Payload) 248 reader.ReadBytes(5) // trans req head 249 reader.ReadByte() 250 reader.ReadUInt16() 251 cmd := reader.ReadUInt16() 252 reader.ReadBytes(21) 253 reader.ReadByte() 254 reader.ReadUInt16() 255 reader.ReadUInt16() 256 reader.ReadInt32() 257 reader.ReadInt64() 258 body := binary.NewReader(reader.ReadBytes(reader.Len() - 1)) 259 if cmd == 0x31 { 260 body.ReadUInt16() 261 body.ReadInt32() 262 code := body.ReadByte() 263 if code != 0 { 264 return nil, errors.Errorf("wtlogin.trans_emp sub cmd 0x31 error: %v", code) 265 } 266 sig := body.ReadBytesShort() 267 body.ReadUInt16() 268 m, err := tlv.NewDecoder(2, 2).DecodeRecordMap(body.ReadAvailable()) 269 if err != nil { 270 return nil, err 271 } 272 if m.Exists(0x17) { 273 return &QRCodeLoginResponse{ 274 State: QRCodeImageFetch, 275 ImageData: m[0x17], 276 Sig: sig, 277 }, nil 278 } 279 return nil, errors.Errorf("wtlogin.trans_emp sub cmd 0x31 error: image not found") 280 } 281 if cmd == 0x12 { 282 aVarLen := body.ReadUInt16() 283 if aVarLen != 0 { 284 aVarLen-- // 阴间的位移操作 285 if body.ReadByte() == 2 { 286 body.ReadInt64() // uin ? 287 aVarLen -= 8 288 } 289 } 290 if aVarLen > 0 { 291 body.ReadBytes(int(aVarLen)) 292 } 293 body.ReadInt32() // app id? 294 code := body.ReadByte() 295 if code != 0 { 296 if code == 0x30 { 297 return &QRCodeLoginResponse{State: QRCodeWaitingForScan}, nil 298 } 299 if code == 0x35 { 300 return &QRCodeLoginResponse{State: QRCodeWaitingForConfirm}, nil 301 } 302 if code == 0x36 { 303 return &QRCodeLoginResponse{State: QRCodeCanceled}, nil 304 } 305 if code == 0x11 { 306 return &QRCodeLoginResponse{State: QRCodeTimeout}, nil 307 } 308 return nil, errors.Errorf("wtlogin.trans_emp sub cmd 0x12 error: %v", code) 309 } 310 c.Uin = body.ReadInt64() 311 c.highwaySession.Uin = strconv.FormatInt(c.Uin, 10) 312 body.ReadInt32() // sig create time 313 body.ReadUInt16() 314 m, err := tlv.NewDecoder(2, 2).DecodeRecordMap(body.ReadAvailable()) 315 if err != nil { 316 return nil, err 317 } 318 if !m.Exists(0x18) || !m.Exists(0x1e) || !m.Exists(0x19) { 319 return nil, errors.New("wtlogin.trans_emp sub cmd 0x12 error: tlv error") 320 } 321 c.Device().TgtgtKey = m[0x1e] 322 return &QRCodeLoginResponse{State: QRCodeConfirmed, LoginInfo: &QRCodeLoginInfo{ 323 tmpPwd: m[0x18], 324 tmpNoPicSig: m[0x19], 325 tgtQR: m[0x65], 326 }}, nil 327 } 328 return nil, errors.Errorf("unknown trans_emp response: %v", cmd) 329 } 330 331 // ConfigPushSvc.PushReq 332 func decodePushReqPacket(c *QQClient, pkt *network.Packet) (any, error) { 333 request := &jce.RequestPacket{} 334 request.ReadFrom(jce.NewJceReader(pkt.Payload)) 335 data := &jce.RequestDataVersion2{} 336 data.ReadFrom(jce.NewJceReader(request.SBuffer)) 337 r := jce.NewJceReader(data.Map["PushReq"]["ConfigPush.PushReq"][1:]) 338 t := r.ReadInt32(1) 339 jceBuf := r.ReadBytes(2) 340 if len(jceBuf) > 0 { 341 switch t { 342 case 1: 343 ssoPkt := jce.NewJceReader(jceBuf) 344 servers := ssoPkt.ReadSsoServerInfos(1) 345 if len(servers) > 0 { 346 var adds []netip.AddrPort 347 for _, s := range servers { 348 if strings.Contains(s.Server, "com") { 349 continue 350 } 351 c.debug("got new server addr: %v location: %v", s.Server, s.Location) 352 addr, err := netip.ParseAddr(s.Server) 353 if err == nil { 354 adds = append(adds, netip.AddrPortFrom(addr, uint16(s.Port))) 355 } 356 } 357 f := true 358 for _, e := range c.eventHandlers.serverUpdatedHandlers { 359 cover(func() { 360 if !e(c, &ServerUpdatedEvent{Servers: servers}) { 361 f = false 362 } 363 }) 364 } 365 if f { 366 c.SetCustomServer(adds) 367 } 368 return nil, nil 369 } 370 case 2: 371 fmtPkt := jce.NewJceReader(jceBuf) 372 list := &jce.FileStoragePushFSSvcList{} 373 list.ReadFrom(fmtPkt) 374 c.debug("got file storage svc push.") 375 // c.fileStorageInfo = list 376 rsp := cmd0x6ff.C501RspBody{} 377 if err := proto.Unmarshal(list.BigDataChannel.PbBuf, &rsp); err == nil && rsp.RspBody != nil { 378 c.highwaySession.SigSession = rsp.RspBody.SigSession 379 c.highwaySession.SessionKey = rsp.RspBody.SessionKey 380 for _, srv := range rsp.RspBody.Addrs { 381 if srv.ServiceType.Unwrap() == 10 { 382 for _, addr := range srv.Addrs { 383 c.highwaySession.AppendAddr(addr.Ip.Unwrap(), addr.Port.Unwrap()) 384 } 385 } 386 /* 387 if srv.ServiceType.Unwrap() == 21 { 388 for _, addr := range srv.Addrs { 389 c.otherSrvAddrs = append(c.otherSrvAddrs, fmt.Sprintf("%v:%v", binary.UInt32ToIPV4Address(addr.Ip.Unwrap()), addr.Port.Unwrap())) 390 } 391 } 392 393 */ 394 } 395 } 396 } 397 } 398 399 seq := r.ReadInt64(3) 400 _, resp := c.buildConfPushRespPacket(t, seq, jceBuf) 401 return nil, c.sendPacket(resp) 402 } 403 404 // MessageSvc.PbGetMsg 405 func decodeMessageSvcPacket(c *QQClient, pkt *network.Packet) (any, error) { 406 rsp := msg.GetMessageResponse{} 407 err := proto.Unmarshal(pkt.Payload, &rsp) 408 if err != nil { 409 return nil, errors.Wrap(err, "failed to unmarshal protobuf message") 410 } 411 c.c2cMessageSyncProcessor(&rsp, pkt.Params) 412 return nil, nil 413 } 414 415 // MessageSvc.PushNotify 416 func decodeSvcNotify(c *QQClient, pkt *network.Packet) (any, error) { 417 request := &jce.RequestPacket{} 418 request.ReadFrom(jce.NewJceReader(pkt.Payload[4:])) 419 data := &jce.RequestDataVersion2{} 420 data.ReadFrom(jce.NewJceReader(request.SBuffer)) 421 if len(data.Map) == 0 { 422 _, err := c.sendAndWait(c.buildGetMessageRequestPacket(msg.SyncFlag_START, time.Now().Unix())) 423 return nil, err 424 } 425 notify := &jce.RequestPushNotify{} 426 notify.ReadFrom(jce.NewJceReader(data.Map["req_PushNotify"]["PushNotifyPack.RequestPushNotify"][1:])) 427 if decoder, typ := peekC2CDecoder(notify.MsgType); decoder != nil { 428 // notify.MsgType != 85 && notify.MsgType != 36 moves to _c2c_decoders.go [nonSvcNotifyTroopSystemMsgDecoders] 429 if typ == troopSystemMsgDecoders { 430 c.exceptAndDispatchGroupSysMsg() 431 return nil, nil 432 } 433 if typ == sysMsgDecoders { 434 _, pkt := c.buildSystemMsgNewFriendPacket() 435 return nil, c.sendPacket(pkt) 436 } 437 } 438 _, err := c.sendAndWait(c.buildGetMessageRequestPacket(msg.SyncFlag_START, time.Now().Unix())) 439 return nil, err 440 } 441 442 // SummaryCard.ReqSummaryCard 443 func decodeSummaryCardResponse(_ *QQClient, pkt *network.Packet) (any, error) { 444 request := &jce.RequestPacket{} 445 request.ReadFrom(jce.NewJceReader(pkt.Payload)) 446 data := &jce.RequestDataVersion2{} 447 data.ReadFrom(jce.NewJceReader(request.SBuffer)) 448 rsp := func() *jce.JceReader { 449 if r, ok := data.Map["RespSummaryCard"]["SummaryCard.RespSummaryCard"]; ok { 450 return jce.NewJceReader(r[1:]) 451 } 452 return jce.NewJceReader(data.Map["RespSummaryCard"]["SummaryCard_Old.RespSummaryCard"][1:]) 453 }() 454 info := &SummaryCardInfo{ 455 Sex: rsp.ReadByte(1), 456 Age: rsp.ReadByte(2), 457 Nickname: rsp.ReadString(3), 458 Level: rsp.ReadInt32(5), 459 City: rsp.ReadString(7), 460 Sign: rsp.ReadString(8), 461 Mobile: rsp.ReadString(11), 462 Uin: rsp.ReadInt64(23), 463 } 464 vipInfo := rsp.ReadMapIntVipInfo(29) // 1 -> vip, 3 -> svip 465 if v1, v3 := vipInfo[1], vipInfo[3]; v1 != nil || v3 != nil { 466 if v1.Open != 0 { 467 info.VipLevel = fmt.Sprintf("vip%d", v1.Level) 468 } 469 if v3.Open != 0 { 470 info.VipLevel = fmt.Sprintf("svip%d", v3.Level) 471 } 472 } 473 474 richSign := rsp.ReadBytes(32) 475 records, _ := tlv.NewDecoder(1, 1).Decode(richSign) 476 for _, r := range records { 477 if r.Tag == 3 { 478 info.Sign = string(r.Value) 479 } 480 } 481 482 info.LoginDays = rsp.ReadInt64(36) 483 services := rsp.ReadByteArrArr(46) 484 readService := func(buf []byte) (*profilecard.BusiComm, []byte) { 485 r := binary.NewReader(buf) 486 r.ReadByte() 487 l1 := r.ReadInt32() 488 l2 := r.ReadInt32() 489 comm := r.ReadBytes(int(l1)) 490 d := r.ReadBytes(int(l2)) 491 c := &profilecard.BusiComm{} 492 _ = proto.Unmarshal(comm, c) 493 return c, d 494 } 495 for _, buf := range services { 496 comm, payload := readService(buf) 497 if comm.Service.Unwrap() == 16 { 498 rsp := profilecard.GateVaProfileGateRsp{} 499 _ = proto.Unmarshal(payload, &rsp) 500 if rsp.QidInfo != nil { 501 info.Qid = rsp.QidInfo.Qid.Unwrap() 502 } 503 } 504 } 505 return info, nil 506 } 507 508 // friendlist.getFriendGroupList 509 func decodeFriendGroupListResponse(_ *QQClient, pkt *network.Packet) (any, error) { 510 request := &jce.RequestPacket{} 511 request.ReadFrom(jce.NewJceReader(pkt.Payload)) 512 data := &jce.RequestDataVersion3{} 513 data.ReadFrom(jce.NewJceReader(request.SBuffer)) 514 r := jce.NewJceReader(data.Map["FLRESP"][1:]) 515 totalFriendCount := r.ReadInt16(5) 516 friends := r.ReadFriendInfos(7) 517 l := make([]*FriendInfo, 0, len(friends)) 518 for _, f := range friends { 519 l = append(l, &FriendInfo{ 520 Uin: f.FriendUin, 521 Nickname: f.Nick, 522 Remark: f.Remark, 523 FaceId: f.FaceId, 524 }) 525 } 526 rsp := &FriendListResponse{ 527 TotalCount: int32(totalFriendCount), 528 List: l, 529 } 530 return rsp, nil 531 } 532 533 // friendlist.delFriend 534 func decodeFriendDeleteResponse(_ *QQClient, pkt *network.Packet) (any, error) { 535 request := &jce.RequestPacket{} 536 request.ReadFrom(jce.NewJceReader(pkt.Payload)) 537 data := &jce.RequestDataVersion3{} 538 data.ReadFrom(jce.NewJceReader(request.SBuffer)) 539 r := jce.NewJceReader(data.Map["DFRESP"][1:]) 540 if ret := r.ReadInt32(2); ret != 0 { 541 return nil, errors.Errorf("delete friend error: %v", ret) 542 } 543 return nil, nil 544 } 545 546 // friendlist.GetTroopListReqV2 547 func decodeGroupListResponse(c *QQClient, pkt *network.Packet) (any, error) { 548 request := &jce.RequestPacket{} 549 request.ReadFrom(jce.NewJceReader(pkt.Payload)) 550 data := &jce.RequestDataVersion3{} 551 data.ReadFrom(jce.NewJceReader(request.SBuffer)) 552 r := jce.NewJceReader(data.Map["GetTroopListRespV2"][1:]) 553 vecCookie := r.ReadBytes(4) 554 groups := r.ReadTroopNumbers(5) 555 l := make([]*GroupInfo, 0, len(groups)) 556 for _, g := range groups { 557 l = append(l, &GroupInfo{ 558 Uin: g.GroupUin, 559 Code: g.GroupCode, 560 Name: g.GroupName, 561 OwnerUin: g.GroupOwnerUin, 562 MemberCount: uint16(g.MemberNum), 563 MaxMemberCount: uint16(g.MaxGroupMemberNum), 564 client: c, 565 }) 566 } 567 if len(vecCookie) > 0 { 568 rsp, err := c.sendAndWait(c.buildGroupListRequestPacket(vecCookie)) 569 if err != nil { 570 return nil, err 571 } 572 l = append(l, rsp.([]*GroupInfo)...) 573 } 574 return l, nil 575 } 576 577 // friendlist.GetTroopMemberListReq 578 func decodeGroupMemberListResponse(_ *QQClient, pkt *network.Packet) (any, error) { 579 request := &jce.RequestPacket{} 580 request.ReadFrom(jce.NewJceReader(pkt.Payload)) 581 data := &jce.RequestDataVersion3{} 582 data.ReadFrom(jce.NewJceReader(request.SBuffer)) 583 r := jce.NewJceReader(data.Map["GTMLRESP"][1:]) 584 members := r.ReadTroopMemberInfos(3) 585 next := r.ReadInt64(4) 586 l := make([]*GroupMemberInfo, 0, len(members)) 587 for _, m := range members { 588 permission := Member 589 if m.Flag&1 != 0 { 590 permission = Administrator 591 } 592 l = append(l, &GroupMemberInfo{ 593 Uin: m.MemberUin, 594 Nickname: m.Nick, 595 Gender: m.Gender, 596 CardName: m.Name, 597 Level: uint16(m.MemberLevel), 598 JoinTime: m.JoinTime, 599 LastSpeakTime: m.LastSpeakTime, 600 SpecialTitle: m.SpecialTitle, 601 ShutUpTimestamp: m.ShutUpTimestap, 602 Permission: permission, 603 }) 604 } 605 return &groupMemberListResponse{ 606 NextUin: next, 607 list: l, 608 }, nil 609 } 610 611 // group_member_card.get_group_member_card_info 612 func decodeGroupMemberInfoResponse(c *QQClient, pkt *network.Packet) (any, error) { 613 rsp := pb.GroupMemberRspBody{} 614 if err := proto.Unmarshal(pkt.Payload, &rsp); err != nil { 615 return nil, errors.Wrap(err, "failed to unmarshal protobuf message") 616 } 617 if rsp.MemInfo == nil || (rsp.MemInfo.Nick == nil && rsp.MemInfo.Age == 0) { 618 return nil, errors.WithStack(ErrMemberNotFound) 619 } 620 group := c.FindGroup(rsp.GroupCode) 621 permission := Member 622 if rsp.MemInfo.Uin == group.OwnerUin { 623 permission = Owner 624 } 625 if rsp.MemInfo.Role == 2 { 626 permission = Administrator 627 } 628 return &GroupMemberInfo{ 629 Group: group, 630 Uin: rsp.MemInfo.Uin, 631 Gender: byte(rsp.MemInfo.Sex), 632 Nickname: string(rsp.MemInfo.Nick), 633 CardName: string(rsp.MemInfo.Card), 634 Level: uint16(rsp.MemInfo.Level), 635 JoinTime: rsp.MemInfo.Join, 636 LastSpeakTime: rsp.MemInfo.LastSpeak, 637 SpecialTitle: string(rsp.MemInfo.SpecialTitle), 638 Permission: permission, 639 }, nil 640 } 641 642 // LongConn.OffPicUp 643 func decodeOffPicUpResponse(_ *QQClient, pkt *network.Packet) (any, error) { 644 rsp := cmd0x352.RspBody{} 645 if err := proto.Unmarshal(pkt.Payload, &rsp); err != nil { 646 return nil, errors.Wrap(err, "failed to unmarshal protobuf message") 647 } 648 if rsp.FailMsg != nil { 649 return &imageUploadResponse{ 650 ResultCode: -1, 651 Message: string(rsp.FailMsg), 652 }, nil 653 } 654 if rsp.Subcmd.Unwrap() != 1 || len(rsp.TryupImgRsp) == 0 { 655 return &imageUploadResponse{ 656 ResultCode: -2, 657 }, nil 658 } 659 imgRsp := rsp.TryupImgRsp[0] 660 if imgRsp.Result.Unwrap() != 0 { 661 return &imageUploadResponse{ 662 ResultCode: int32(imgRsp.Result.Unwrap()), 663 Message: string(imgRsp.FailMsg), 664 }, nil 665 } 666 if imgRsp.FileExit.Unwrap() { 667 return &imageUploadResponse{ 668 IsExists: true, 669 ResourceId: string(imgRsp.UpResid), 670 }, nil 671 } 672 return &imageUploadResponse{ 673 ResourceId: string(imgRsp.UpResid), 674 UploadKey: imgRsp.UpUkey, 675 UploadIp: imgRsp.UpIp, 676 UploadPort: imgRsp.UpPort, 677 }, nil 678 } 679 680 // OnlinePush.PbPushTransMsg 681 func decodeOnlinePushTransPacket(c *QQClient, pkt *network.Packet) (any, error) { 682 info := msg.TransMsgInfo{} 683 err := proto.Unmarshal(pkt.Payload, &info) 684 if err != nil { 685 return nil, errors.Wrap(err, "failed to unmarshal protobuf message") 686 } 687 data := binary.NewReader(info.MsgData) 688 idStr := strconv.FormatInt(info.MsgUid.Unwrap(), 10) 689 if _, ok := c.transCache.Get(idStr); ok { 690 return nil, nil 691 } 692 c.transCache.Add(idStr, unit{}, time.Second*15) 693 if info.MsgType.Unwrap() == 34 { 694 data.ReadInt32() 695 data.ReadByte() 696 target := int64(uint32(data.ReadInt32())) 697 typ := int32(data.ReadByte()) 698 operator := int64(uint32(data.ReadInt32())) 699 if g := c.FindGroupByUin(info.FromUin.Unwrap()); g != nil { 700 groupLeaveLock.Lock() 701 defer groupLeaveLock.Unlock() 702 switch typ { 703 case 0x02: 704 if target == c.Uin { 705 c.GroupLeaveEvent.dispatch(c, &GroupLeaveEvent{Group: g}) 706 } else if m := g.FindMember(target); m != nil { 707 g.removeMember(target) 708 c.GroupMemberLeaveEvent.dispatch(c, &MemberLeaveGroupEvent{ 709 Group: g, 710 Member: m, 711 }) 712 } 713 case 0x03: 714 if err = c.ReloadGroupList(); err != nil { 715 return nil, err 716 } 717 if target == c.Uin { 718 c.GroupLeaveEvent.dispatch(c, &GroupLeaveEvent{ 719 Group: g, 720 Operator: g.FindMember(operator), 721 }) 722 } else if m := g.FindMember(target); m != nil { 723 g.removeMember(target) 724 c.GroupMemberLeaveEvent.dispatch(c, &MemberLeaveGroupEvent{ 725 Group: g, 726 Member: m, 727 Operator: g.FindMember(operator), 728 }) 729 } 730 case 0x82: 731 if m := g.FindMember(target); m != nil { 732 g.removeMember(target) 733 c.GroupMemberLeaveEvent.dispatch(c, &MemberLeaveGroupEvent{ 734 Group: g, 735 Member: m, 736 }) 737 } 738 case 0x83: 739 if m := g.FindMember(target); m != nil { 740 g.removeMember(target) 741 c.GroupMemberLeaveEvent.dispatch(c, &MemberLeaveGroupEvent{ 742 Group: g, 743 Member: m, 744 Operator: g.FindMember(operator), 745 }) 746 } 747 case 0x01, 0x81: // kosbot add: 群解散. 暂时这样 See https://github.com/lz1998/ricq/blob/064ddddca19aa0410e2514852e3a151fd9913371/ricq-core/src/command/online_push/decoder.rs#L86 748 c.GroupDisbandEvent.dispatch(c, &GroupDisbandEvent{ 749 Group: g, 750 Operator: g.FindMember(operator), 751 Time: int64(info.MsgTime.Unwrap()), 752 }) 753 if err = c.ReloadGroupList(); err != nil { 754 return nil, err 755 } 756 } 757 } 758 } 759 if info.MsgType.Unwrap() == 44 { 760 data.ReadBytes(5) 761 var4 := int32(data.ReadByte()) 762 var5 := int64(0) 763 target := int64(uint32(data.ReadInt32())) 764 if var4 != 0 && var4 != 1 { 765 var5 = int64(uint32(data.ReadInt32())) 766 } 767 if g := c.FindGroupByUin(info.FromUin.Unwrap()); g != nil { 768 if var5 == 0 && data.Len() == 1 { 769 newPermission := Member 770 if data.ReadByte() == 1 { 771 newPermission = Administrator 772 } 773 mem := g.FindMember(target) 774 if mem.Permission != newPermission { 775 old := mem.Permission 776 mem.Permission = newPermission 777 c.GroupMemberPermissionChangedEvent.dispatch(c, &MemberPermissionChangedEvent{ 778 Group: g, 779 Member: mem, 780 OldPermission: old, 781 NewPermission: newPermission, 782 }) 783 } 784 } 785 } 786 } 787 return nil, nil 788 } 789 790 // ProfileService.Pb.ReqSystemMsgNew.Friend 791 func decodeSystemMsgFriendPacket(c *QQClient, pkt *network.Packet) (any, error) { 792 rsp := structmsg.RspSystemMsgNew{} 793 if err := proto.Unmarshal(pkt.Payload, &rsp); err != nil { 794 return nil, errors.Wrap(err, "failed to unmarshal protobuf message") 795 } 796 if len(rsp.Friendmsgs) == 0 { 797 return nil, nil 798 } 799 st := rsp.Friendmsgs[0] 800 if st.Msg != nil { 801 c.NewFriendRequestEvent.dispatch(c, &NewFriendRequest{ 802 RequestId: st.MsgSeq, 803 Message: st.Msg.MsgAdditional, 804 RequesterUin: st.ReqUin, 805 RequesterNick: st.Msg.ReqUinNick, 806 client: c, 807 }) 808 } 809 return nil, nil 810 } 811 812 // MessageSvc.PushForceOffline 813 func decodeForceOfflinePacket(c *QQClient, pkt *network.Packet) (any, error) { 814 request := &jce.RequestPacket{} 815 request.ReadFrom(jce.NewJceReader(pkt.Payload)) 816 data := &jce.RequestDataVersion2{} 817 data.ReadFrom(jce.NewJceReader(request.SBuffer)) 818 r := jce.NewJceReader(data.Map["req_PushForceOffline"]["PushNotifyPack.RequestPushForceOffline"][1:]) 819 tips := r.ReadString(2) 820 c.Disconnect() 821 go c.DisconnectedEvent.dispatch(c, &ClientDisconnectedEvent{Message: tips}) 822 return nil, nil 823 } 824 825 // StatSvc.ReqMSFOffline 826 func decodeMSFOfflinePacket(c *QQClient, _ *network.Packet) (any, error) { 827 // c.lastLostMsg = "服务器端强制下线." 828 c.Disconnect() 829 // 这个decoder不能消耗太多时间, event另起线程处理 830 go c.DisconnectedEvent.dispatch(c, &ClientDisconnectedEvent{Message: "服务端强制下线."}) 831 return nil, nil 832 } 833 834 // OidbSvc.0xd79 835 func decodeWordSegmentation(_ *QQClient, pkt *network.Packet) (any, error) { 836 rsp := oidb.D79RspBody{} 837 err := unpackOIDBPackage(pkt.Payload, &rsp) 838 if err != nil { 839 return nil, err 840 } 841 if rsp.Content != nil { 842 return rsp.Content.SliceContent, nil 843 } 844 return nil, errors.New("no word received") 845 } 846 847 func decodeSidExpiredPacket(c *QQClient, pkt *network.Packet) (any, error) { 848 /* 849 _, err := c.sendAndWait(c.buildRequestChangeSigPacket(true)) 850 if err != nil { 851 return nil, errors.Wrap(err, "resign client error") 852 } 853 if err = c.registerClient(); err != nil { 854 return nil, errors.Wrap(err, "register error") 855 } 856 _ = c.sendPacket(c.uniPacketWithSeq(i.SequenceId, "OnlinePush.SidTicketExpired", EmptyBytes)) 857 */ 858 return nil, nil 859 } 860 861 /* unused 862 // LightAppSvc.mini_app_info.GetAppInfoById 863 func decodeAppInfoResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { 864 pkg := qweb.QWebRsp{} 865 rsp := qweb.GetAppInfoByIdRsp{} 866 if err := proto.Unmarshal(payload, &pkg); err != nil { 867 return nil, errors.Wrap(err, "failed to unmarshal protobuf message") 868 } 869 if pkg.RetCode.Unwrap() != 0 { 870 return nil, errors.New(pkg.ErrMsg.Unwrap()) 871 } 872 if err := proto.Unmarshal(pkg.BusiBuff, &rsp); err != nil { 873 return nil, errors.Wrap(err, "failed to unmarshal protobuf message") 874 } 875 return rsp.AppInfo, nil 876 } 877 */ 878 879 func ignoreDecoder(_ *QQClient, _ *network.Packet) (any, error) { 880 return nil, nil 881 }