github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/client/guild.go (about) 1 package client 2 3 import ( 4 "fmt" 5 "math/rand" 6 "sort" 7 "strconv" 8 "time" 9 10 "github.com/Mrs4s/MiraiGo/client/internal/network" 11 "github.com/Mrs4s/MiraiGo/topic" 12 13 "github.com/Mrs4s/MiraiGo/client/pb/qweb" 14 "github.com/Mrs4s/MiraiGo/internal/proto" 15 16 "github.com/pkg/errors" 17 18 "github.com/Mrs4s/MiraiGo/client/pb/channel" 19 "github.com/Mrs4s/MiraiGo/utils" 20 ) 21 22 type ( 23 // GuildService 频道模块内自身的信息 24 GuildService struct { 25 TinyId uint64 26 Nickname string 27 AvatarUrl string 28 GuildCount uint32 29 // Guilds 由服务器推送的频道列表 30 Guilds []*GuildInfo 31 32 c *QQClient 33 } 34 35 // GuildInfo 频道信息 36 GuildInfo struct { 37 GuildId uint64 38 GuildCode uint64 39 GuildName string 40 CoverUrl string 41 AvatarUrl string 42 Channels []*ChannelInfo 43 // Bots []*GuildMemberInfo 44 // Members []*GuildMemberInfo 45 // Admins []*GuildMemberInfo 46 } 47 48 // GuildMeta 频道数据 49 GuildMeta struct { 50 GuildId uint64 51 GuildName string 52 GuildProfile string 53 MaxMemberCount int64 54 MemberCount int64 55 CreateTime int64 56 MaxRobotCount int32 57 MaxAdminCount int32 58 OwnerId uint64 59 } 60 61 // GuildMemberInfo 频道成员信息, 仅通过频道成员列表API获取 62 GuildMemberInfo struct { 63 TinyId uint64 64 Title string 65 Nickname string 66 LastSpeakTime int64 67 Role uint64 68 RoleName string 69 } 70 71 // GuildUserProfile 频道系统用户资料 72 GuildUserProfile struct { 73 TinyId uint64 74 Nickname string 75 AvatarUrl string 76 JoinTime int64 // 只有 GetGuildMemberProfileInfo 函数才会有 77 Roles []*GuildRole 78 } 79 80 // GuildRole 频道身份组信息 81 GuildRole struct { 82 RoleId uint64 83 RoleName string 84 ArgbColor uint32 85 Independent bool 86 Num int32 87 Owned bool 88 Disabled bool 89 MaxNum int32 90 } 91 92 // ChannelInfo 子频道信息 93 ChannelInfo struct { 94 ChannelId uint64 95 ChannelName string 96 Time uint64 97 EventTime uint32 98 NotifyType uint32 99 ChannelType ChannelType 100 AtAllSeq uint64 101 Meta *ChannelMeta 102 103 fetchTime int64 104 } 105 106 ChannelMeta struct { 107 CreatorUin int64 108 CreatorTinyId uint64 109 CreateTime int64 110 GuildId uint64 111 VisibleType int32 112 TopMessageSeq uint64 113 TopMessageTime int64 114 TopMessageOperatorId uint64 115 CurrentSlowMode int32 116 TalkPermission int32 117 SlowModes []*ChannelSlowModeInfo 118 } 119 120 ChannelSlowModeInfo struct { 121 SlowModeKey int32 122 SpeakFrequency int32 123 SlowModeCircle int32 124 SlowModeText string 125 } 126 127 FetchGuildMemberListWithRoleResult struct { 128 Members []*GuildMemberInfo 129 NextIndex uint32 130 NextRoleId uint64 131 NextQueryParam string 132 Finished bool 133 } 134 135 ChannelType int32 136 ) 137 138 const ( 139 ChannelTypeText ChannelType = 1 140 ChannelTypeVoice ChannelType = 2 141 ChannelTypeLive ChannelType = 5 142 ChannelTypeTopic ChannelType = 7 143 ) 144 145 func init() { 146 decoders["trpc.group_pro.synclogic.SyncLogic.PushFirstView"] = decodeGuildPushFirstView 147 } 148 149 func (s *GuildService) FindGuild(guildId uint64) *GuildInfo { 150 for _, i := range s.Guilds { 151 if i.GuildId == guildId { 152 return i 153 } 154 } 155 return nil 156 } 157 158 func (g *GuildInfo) FindChannel(channelId uint64) *ChannelInfo { 159 for _, c := range g.Channels { 160 if c.ChannelId == channelId { 161 return c 162 } 163 } 164 return nil 165 } 166 167 func (g *GuildInfo) removeChannel(id uint64) { 168 i := sort.Search(len(g.Channels), func(i int) bool { 169 return g.Channels[i].ChannelId >= id 170 }) 171 if i >= len(g.Channels) || g.Channels[i].ChannelId != id { 172 return 173 } 174 g.Channels = append(g.Channels[:i], g.Channels[i+1:]...) 175 } 176 177 func (s *GuildService) GetUserProfile(tinyId uint64) (*GuildUserProfile, error) { 178 flags := proto.DynamicMessage{} 179 for i := 3; i <= 29; i++ { 180 flags[uint64(i)] = 1 181 } 182 flags[99] = 1 183 flags[100] = 1 184 payload := s.c.packOIDBPackageDynamically(3976, 1, proto.DynamicMessage{ 185 1: flags, 186 3: tinyId, 187 4: 0, 188 }) 189 rsp, err := s.c.sendAndWaitDynamic(s.c.uniPacket("OidbSvcTrpcTcp.0xfc9_1", payload)) 190 if err != nil { 191 return nil, errors.Wrap(err, "send packet error") 192 } 193 body := new(channel.ChannelOidb0Xfc9Rsp) 194 if err = unpackOIDBPackage(rsp, body); err != nil { 195 return nil, errors.Wrap(err, "decode packet error") 196 } 197 // todo: 解析个性档案 198 return &GuildUserProfile{ 199 TinyId: tinyId, 200 Nickname: body.Profile.Nickname.Unwrap(), 201 AvatarUrl: body.Profile.AvatarUrl.Unwrap(), 202 JoinTime: body.Profile.JoinTime.Unwrap(), 203 }, nil 204 } 205 206 // FetchGuildMemberListWithRole 获取频道成员列表 207 // 第一次请求: startIndex = 0 , roleIdIndex = 2 param = "" 208 // 后续请求请根据上次请求的返回值进行设置 209 func (s *GuildService) FetchGuildMemberListWithRole(guildId, channelId uint64, startIndex uint32, roleIdIndex uint64, param string) (*FetchGuildMemberListWithRoleResult, error) { 210 seq := s.c.nextSeq() 211 m := proto.DynamicMessage{ 212 1: guildId, // guild id 213 2: 3, 214 3: 0, 215 4: proto.DynamicMessage{ // unknown param, looks like flags 216 1: 1, 217 2: 1, 218 3: 1, 219 4: 1, 220 5: 1, 221 6: 1, 222 7: 1, 223 8: 1, 224 20: 1, 225 }, 226 6: startIndex, 227 8: 50, // count 228 12: channelId, 229 } 230 if param != "" { 231 m[13] = param 232 } 233 m[14] = roleIdIndex 234 packet := s.c.uniPacketWithSeq(seq, "OidbSvcTrpcTcp.0xf5b_1", s.c.packOIDBPackageDynamically(3931, 1, m)) 235 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 236 if err != nil { 237 return nil, errors.Wrap(err, "send packet error") 238 } 239 body := new(channel.ChannelOidb0Xf5BRsp) 240 if err = unpackOIDBPackage(rsp, body); err != nil { 241 return nil, errors.Wrap(err, "decode packet error") 242 } 243 var ret []*GuildMemberInfo 244 for _, memberWithRole := range body.MemberWithRoles { 245 for _, mem := range memberWithRole.Members { 246 ret = append(ret, &GuildMemberInfo{ 247 TinyId: mem.TinyId.Unwrap(), 248 Title: mem.Title.Unwrap(), 249 Nickname: mem.Nickname.Unwrap(), 250 LastSpeakTime: mem.LastSpeakTime.Unwrap(), 251 Role: memberWithRole.RoleId.Unwrap(), 252 RoleName: memberWithRole.RoleName.Unwrap(), 253 }) 254 } 255 } 256 for _, mem := range body.Members { 257 ret = append(ret, &GuildMemberInfo{ 258 TinyId: mem.TinyId.Unwrap(), 259 Title: mem.Title.Unwrap(), 260 Nickname: mem.Nickname.Unwrap(), 261 LastSpeakTime: mem.LastSpeakTime.Unwrap(), 262 Role: 1, 263 RoleName: "普通成员", 264 }) 265 } 266 return &FetchGuildMemberListWithRoleResult{ 267 Members: ret, 268 NextIndex: body.NextIndex.Unwrap(), 269 NextRoleId: body.NextRoleIdIndex.Unwrap(), 270 NextQueryParam: body.NextQueryParam.Unwrap(), 271 Finished: body.NextIndex.IsNone(), 272 }, nil 273 } 274 275 // FetchGuildMemberProfileInfo 获取单个频道成员资料 276 func (s *GuildService) FetchGuildMemberProfileInfo(guildId, tinyId uint64) (*GuildUserProfile, error) { 277 seq := s.c.nextSeq() 278 flags := proto.DynamicMessage{} 279 for i := 3; i <= 29; i++ { 280 flags[uint64(i)] = 1 281 } 282 flags[99] = 1 283 flags[100] = 1 284 payload := s.c.packOIDBPackageDynamically(3976, 1, proto.DynamicMessage{ 285 1: flags, 286 3: tinyId, 287 4: guildId, 288 }) 289 packet := s.c.uniPacketWithSeq(seq, "OidbSvcTrpcTcp.0xf88_1", payload) 290 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 291 if err != nil { 292 return nil, errors.Wrap(err, "send packet error") 293 } 294 body := new(channel.ChannelOidb0Xf88Rsp) 295 if err = unpackOIDBPackage(rsp, body); err != nil { 296 return nil, errors.Wrap(err, "decode packet error") 297 } 298 roles, err := s.fetchMemberRoles(guildId, tinyId) 299 if err != nil { 300 return nil, errors.Wrap(err, "fetch roles error") 301 } 302 // todo: 解析个性档案 303 return &GuildUserProfile{ 304 TinyId: tinyId, 305 Nickname: body.Profile.Nickname.Unwrap(), 306 AvatarUrl: body.Profile.AvatarUrl.Unwrap(), 307 JoinTime: body.Profile.JoinTime.Unwrap(), 308 Roles: roles, 309 }, nil 310 } 311 312 func (s *GuildService) GetGuildRoles(guildId uint64) ([]*GuildRole, error) { 313 seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x1019_1", 314 s.c.packOIDBPackageDynamically(4121, 1, proto.DynamicMessage{1: guildId})) 315 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 316 if err != nil { 317 return nil, errors.Wrap(err, "send packet error") 318 } 319 body := new(channel.ChannelOidb0X1019Rsp) 320 if err = unpackOIDBPackage(rsp, body); err != nil { 321 return nil, errors.Wrap(err, "decode packet error") 322 } 323 roles := make([]*GuildRole, 0, len(body.Roles)) 324 for _, role := range body.Roles { 325 roles = append(roles, &GuildRole{ 326 RoleId: role.RoleId.Unwrap(), 327 RoleName: role.Name.Unwrap(), 328 ArgbColor: role.ArgbColor.Unwrap(), 329 Independent: role.Independent.Unwrap() == 1, 330 Num: role.Num.Unwrap(), 331 Owned: role.Owned.Unwrap() == 1, 332 Disabled: role.Disabled.Unwrap() == 1, 333 MaxNum: role.MaxNum.Unwrap(), 334 }) 335 } 336 return roles, nil 337 } 338 339 func (s *GuildService) CreateGuildRole(guildId uint64, name string, color uint32, independent bool, initialUsers []uint64) (uint64, error) { 340 seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x1016_1", s.c.packOIDBPackageDynamically(4118, 1, proto.DynamicMessage{ 341 1: guildId, 342 2: proto.DynamicMessage{ // todo: 未知参数 343 1: 1, 344 2: 1, 345 3: 1, 346 }, 347 3: proto.DynamicMessage{ 348 1: name, 349 2: color, 350 3: independent, 351 }, 352 4: initialUsers, 353 })) 354 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 355 if err != nil { 356 return 0, errors.Wrap(err, "send packet error") 357 } 358 body := new(channel.ChannelOidb0X1016Rsp) 359 if err = unpackOIDBPackage(rsp, body); err != nil { 360 return 0, errors.Wrap(err, "decode packet error") 361 } 362 return body.RoleId.Unwrap(), nil 363 } 364 365 func (s *GuildService) DeleteGuildRole(guildId uint64, roleId uint64) error { 366 seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x100e_1", s.c.packOIDBPackageDynamically(4110, 1, proto.DynamicMessage{ 367 1: guildId, 368 2: roleId, 369 })) 370 _, err := s.c.sendAndWaitDynamic(seq, packet) 371 if err != nil { 372 return errors.Wrap(err, "send packet error") 373 } 374 return nil 375 } 376 377 func (s *GuildService) SetUserRoleInGuild(guildId uint64, set bool, roleId uint64, user []uint64) error { // remove => p2 = false 378 setOrRemove := proto.DynamicMessage{ 379 1: roleId, 380 } 381 if set { 382 setOrRemove[2] = user 383 } else { 384 setOrRemove[3] = user 385 } 386 seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x101a_1", s.c.packOIDBPackageDynamically(4122, 1, proto.DynamicMessage{ 387 1: guildId, 388 2: setOrRemove, 389 })) 390 _, err := s.c.sendAndWaitDynamic(seq, packet) 391 if err != nil { 392 return errors.Wrap(err, "send packet error") 393 } 394 return nil 395 } 396 397 func (s *GuildService) ModifyRoleInGuild(guildId uint64, roleId uint64, name string, color uint32, indepedent bool) error { 398 seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x100d_1", s.c.packOIDBPackageDynamically(4109, 1, proto.DynamicMessage{ 399 1: guildId, 400 2: roleId, 401 3: proto.DynamicMessage{ 402 1: 1, 403 2: 1, 404 3: 1, 405 }, 406 4: proto.DynamicMessage{ 407 1: name, 408 2: color, 409 3: indepedent, 410 }, 411 })) 412 _, err := s.c.sendAndWaitDynamic(seq, packet) 413 if err != nil { 414 return errors.Wrap(err, "send packet error") 415 } 416 return nil 417 } 418 419 func (s *GuildService) FetchGuestGuild(guildId uint64) (*GuildMeta, error) { 420 payload := s.c.packOIDBPackageDynamically(3927, 9, proto.DynamicMessage{ 421 1: proto.DynamicMessage{ 422 1: proto.DynamicMessage{ 423 2: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 11: 1, 12: 1, 13: 1, 14: 1, 45: 1, 424 18: 1, 19: 1, 20: 1, 22: 1, 23: 1, 5002: 1, 5003: 1, 5004: 1, 5005: 1, 10007: 1, 425 }, 426 2: proto.DynamicMessage{ 427 3: 1, 4: 1, 6: 1, 11: 1, 14: 1, 15: 1, 16: 1, 17: 1, 428 }, 429 }, 430 2: proto.DynamicMessage{ 431 1: guildId, 432 }, 433 }) 434 seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0xf57_9", payload) 435 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 436 if err != nil { 437 return nil, errors.Wrap(err, "send packet error") 438 } 439 body := new(channel.ChannelOidb0Xf57Rsp) 440 if err = unpackOIDBPackage(rsp, body); err != nil { 441 return nil, errors.Wrap(err, "decode packet error") 442 } 443 return &GuildMeta{ 444 GuildName: body.Rsp.Meta.Name.Unwrap(), 445 GuildProfile: body.Rsp.Meta.Profile.Unwrap(), 446 MaxMemberCount: body.Rsp.Meta.MaxMemberCount.Unwrap(), 447 MemberCount: body.Rsp.Meta.MemberCount.Unwrap(), 448 CreateTime: body.Rsp.Meta.CreateTime.Unwrap(), 449 MaxRobotCount: body.Rsp.Meta.RobotMaxNum.Unwrap(), 450 MaxAdminCount: body.Rsp.Meta.AdminMaxNum.Unwrap(), 451 OwnerId: body.Rsp.Meta.OwnerId.Unwrap(), 452 }, nil 453 } 454 455 func (s *GuildService) FetchChannelList(guildId uint64) (r []*ChannelInfo, e error) { 456 seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0xf5d_1", 457 s.c.packOIDBPackageDynamically(3933, 1, 458 proto.DynamicMessage{ 459 1: guildId, 460 3: proto.DynamicMessage{ 461 1: 1, 462 }, 463 })) 464 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 465 if err != nil { 466 return nil, errors.Wrap(err, "send packet error") 467 } 468 body := new(channel.ChannelOidb0Xf5DRsp) 469 if err = unpackOIDBPackage(rsp, body); err != nil { 470 return nil, errors.Wrap(err, "decode packet error") 471 } 472 for _, info := range body.Rsp.Channels { 473 r = append(r, convertChannelInfo(info)) 474 } 475 return 476 } 477 478 func (s *GuildService) FetchChannelInfo(guildId, channelId uint64) (*ChannelInfo, error) { 479 seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0xf55_1", s.c.packOIDBPackageDynamically(3925, 1, proto.DynamicMessage{1: guildId, 2: channelId})) 480 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 481 if err != nil { 482 return nil, errors.Wrap(err, "send packet error") 483 } 484 body := new(channel.ChannelOidb0Xf55Rsp) 485 if err = unpackOIDBPackage(rsp, body); err != nil { 486 return nil, errors.Wrap(err, "decode packet error") 487 } 488 return convertChannelInfo(body.Info), nil 489 } 490 491 func (s *GuildService) GetTopicChannelFeeds(guildId, channelId uint64) ([]*topic.Feed, error) { 492 guild := s.FindGuild(guildId) 493 if guild == nil { 494 return nil, errors.New("guild not found") 495 } 496 channelInfo := guild.FindChannel(channelId) 497 if channelInfo == nil { 498 return nil, errors.New("channel not found") 499 } 500 if channelInfo.ChannelType != ChannelTypeTopic { 501 return nil, errors.New("channel type error") 502 } 503 req, _ := proto.Marshal(&channel.StGetChannelFeedsReq{ 504 Count: proto.Uint32(12), 505 From: proto.Uint32(0), 506 ChannelSign: &channel.StChannelSign{ 507 GuildId: proto.Some(guildId), 508 ChannelId: proto.Some(channelId), 509 }, 510 FeedAttchInfo: proto.String(""), // isLoadMore 511 }) 512 payload, _ := proto.Marshal(&qweb.QWebReq{ 513 Seq: proto.Int64(s.c.nextQWebSeq()), 514 Qua: proto.String("V1_AND_SQ_8.8.50_2324_YYB_D"), 515 DeviceInfo: proto.String(s.c.getWebDeviceInfo()), 516 BusiBuff: req, 517 TraceId: proto.String(fmt.Sprintf("%v_%v_%v", s.c.Uin, time.Now().Format("0102150405"), rand.Int63())), 518 Extinfo: []*qweb.COMMEntry{ 519 { 520 Key: proto.String("fc-appid"), 521 Value: proto.String("96"), 522 }, 523 { 524 Key: proto.String("environment_id"), 525 Value: proto.String("production"), 526 }, 527 { 528 Key: proto.String("tiny_id"), 529 Value: proto.String(fmt.Sprint(s.TinyId)), 530 }, 531 }, 532 }) 533 seq, packet := s.c.uniPacket("QChannelSvr.trpc.qchannel.commreader.ComReader.GetChannelTimelineFeeds", payload) 534 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 535 if err != nil { 536 return nil, errors.New("send packet error") 537 } 538 pkg := new(qweb.QWebRsp) 539 body := new(channel.StGetChannelFeedsRsp) 540 if err = proto.Unmarshal(rsp, pkg); err != nil { 541 return nil, errors.Wrap(err, "failed to unmarshal protobuf message") 542 } 543 if err = proto.Unmarshal(pkg.BusiBuff, body); err != nil { 544 return nil, errors.Wrap(err, "failed to unmarshal protobuf message") 545 } 546 feeds := make([]*topic.Feed, 0, len(body.VecFeed)) 547 for _, f := range body.VecFeed { 548 feeds = append(feeds, topic.DecodeFeed(f)) 549 } 550 return feeds, nil 551 } 552 553 func (s *GuildService) PostTopicChannelFeed(guildId, channelId uint64, feed *topic.Feed) error { 554 guild := s.FindGuild(guildId) 555 if guild == nil { 556 return errors.New("guild not found") 557 } 558 channelInfo := guild.FindChannel(channelId) 559 if channelInfo == nil { 560 return errors.New("channel not found") 561 } 562 if channelInfo.ChannelType != ChannelTypeTopic { 563 return errors.New("channel type error") 564 } 565 feed.Poster = &topic.FeedPoster{ 566 TinyIdStr: strconv.FormatUint(s.TinyId, 10), 567 Nickname: s.Nickname, 568 } 569 feed.GuildId = guildId 570 feed.ChannelId = channelId 571 req, _ := proto.Marshal(&channel.StPublishFeedReq{ 572 ExtInfo: &channel.StCommonExt{ 573 MapInfo: []*channel.CommonEntry{ 574 { 575 Key: proto.String("clientkey"), Value: proto.String("GuildMain" + utils.RandomStringRange(14, "0123456789")), 576 }, 577 }, 578 }, 579 From: proto.Int32(0), 580 JsonFeed: proto.String(feed.ToSendingPayload(s.c.Uin)), 581 }) 582 payload, _ := proto.Marshal(&qweb.QWebReq{ 583 Seq: proto.Int64(s.c.nextQWebSeq()), 584 Qua: proto.String("V1_AND_SQ_8.8.50_2324_YYB_D"), 585 DeviceInfo: proto.String(s.c.getWebDeviceInfo()), 586 BusiBuff: req, 587 TraceId: proto.String(fmt.Sprintf("%v_%v_%v", s.c.Uin, time.Now().Format("0102150405"), rand.Int63())), 588 Extinfo: []*qweb.COMMEntry{ 589 { 590 Key: proto.String("fc-appid"), 591 Value: proto.String("96"), 592 }, 593 { 594 Key: proto.String("environment_id"), 595 Value: proto.String("production"), 596 }, 597 { 598 Key: proto.String("tiny_id"), 599 Value: proto.String(fmt.Sprint(s.TinyId)), 600 }, 601 }, 602 }) 603 seq, packet := s.c.uniPacket("QChannelSvr.trpc.qchannel.commwriter.ComWriter.PublishFeed", payload) 604 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 605 if err != nil { 606 return errors.New("send packet error") 607 } 608 pkg := new(qweb.QWebRsp) 609 body := new(channel.StPublishFeedRsp) 610 if err = proto.Unmarshal(rsp, pkg); err != nil { 611 return errors.Wrap(err, "failed to unmarshal protobuf message") 612 } 613 if err = proto.Unmarshal(pkg.BusiBuff, body); err != nil { 614 return errors.Wrap(err, "failed to unmarshal protobuf message") 615 } 616 if body.Feed != nil && body.Feed.Id.IsNone() { 617 return nil 618 } 619 return errors.New("post feed error") 620 } 621 622 func (s *GuildService) fetchMemberRoles(guildId uint64, tinyId uint64) ([]*GuildRole, error) { 623 seq, packet := s.c.uniPacket("OidbSvcTrpcTcp.0x1017_1", s.c.packOIDBPackageDynamically(4119, 1, proto.DynamicMessage{ 624 1: guildId, 625 2: tinyId, 626 4: proto.DynamicMessage{ 627 1: 1, 628 2: 1, 629 3: 1, 630 }, 631 })) 632 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 633 if err != nil { 634 return nil, errors.Wrap(err, "send packet error") 635 } 636 body := new(channel.ChannelOidb0X1017Rsp) 637 if err = unpackOIDBPackage(rsp, body); err != nil { 638 return nil, errors.Wrap(err, "decode packet error") 639 } 640 p1 := body.P1 641 if p1 == nil { 642 return nil, errors.New("packet OidbSvcTrpcTcp.0x1017_1: decode p1 error") 643 } 644 roles := make([]*GuildRole, 0, len(p1.Roles)) 645 for _, role := range p1.Roles { 646 roles = append(roles, &GuildRole{ 647 RoleId: role.RoleId.Unwrap(), 648 RoleName: role.Name.Unwrap(), 649 ArgbColor: role.ArgbColor.Unwrap(), 650 }) 651 } 652 return roles, nil 653 } 654 655 /* need analysis 656 func (s *GuildService) fetchChannelListState(guildId uint64, channels []*ChannelInfo) { 657 seq := s.c.nextSeq() 658 var ids []uint64 659 for _, info := range channels { 660 ids = append(ids, info.ChannelId) 661 } 662 payload := s.c.packOIDBPackageDynamically(4104, 1, binary.DynamicMessage{ 663 1: binary.DynamicMessage{ 664 1: guildId, 665 2: ids, 666 }, 667 }) 668 packet := packets.BuildUniPacket(s.c.Uin, seq, "OidbSvcTrpcTcp.0x1008_1", 1, s.c.SessionId, []byte{}, s.c.sigInfo.d2Key, payload) 669 rsp, err := s.c.sendAndWaitDynamic(seq, packet) 670 if err != nil { 671 return 672 } 673 pkg := new(oidb.OIDBSSOPkg) 674 if err = proto.Unmarshal(rsp, pkg); err != nil { 675 return //nil, errors.Wrap(err, "failed to unmarshal protobuf message") 676 } 677 } 678 */ 679 680 func convertChannelInfo(info *channel.GuildChannelInfo) *ChannelInfo { 681 meta := &ChannelMeta{ 682 CreatorUin: info.CreatorUin.Unwrap(), 683 CreatorTinyId: info.CreatorTinyId.Unwrap(), 684 CreateTime: info.CreateTime.Unwrap(), 685 GuildId: info.GuildId.Unwrap(), 686 VisibleType: info.VisibleType.Unwrap(), 687 CurrentSlowMode: info.CurrentSlowModeKey.Unwrap(), 688 TalkPermission: info.TalkPermission.Unwrap(), 689 } 690 if info.TopMsg != nil { 691 meta.TopMessageSeq = info.TopMsg.TopMsgSeq.Unwrap() 692 meta.TopMessageTime = info.TopMsg.TopMsgTime.Unwrap() 693 meta.TopMessageOperatorId = info.TopMsg.TopMsgOperatorTinyId.Unwrap() 694 } 695 for _, slow := range info.SlowModeInfos { 696 meta.SlowModes = append(meta.SlowModes, &ChannelSlowModeInfo{ 697 SlowModeKey: slow.SlowModeKey.Unwrap(), 698 SpeakFrequency: slow.SpeakFrequency.Unwrap(), 699 SlowModeCircle: slow.SlowModeCircle.Unwrap(), 700 SlowModeText: slow.SlowModeText.Unwrap(), 701 }) 702 } 703 return &ChannelInfo{ 704 ChannelId: info.ChannelId.Unwrap(), 705 ChannelName: info.ChannelName.Unwrap(), 706 NotifyType: uint32(info.FinalNotifyType.Unwrap()), 707 ChannelType: ChannelType(info.ChannelType.Unwrap()), 708 Meta: meta, 709 fetchTime: time.Now().Unix(), 710 } 711 } 712 713 func (c *QQClient) syncChannelFirstView() { 714 rsp, err := c.sendAndWaitDynamic(c.buildSyncChannelFirstViewPacket()) 715 if err != nil { 716 c.error("sync channel error: %v", err) 717 return 718 } 719 firstViewRsp := new(channel.FirstViewRsp) 720 if err = proto.Unmarshal(rsp, firstViewRsp); err != nil { 721 return 722 } 723 c.GuildService.TinyId = firstViewRsp.SelfTinyid.Unwrap() 724 c.GuildService.GuildCount = firstViewRsp.GuildCount.Unwrap() 725 if self, err := c.GuildService.GetUserProfile(c.GuildService.TinyId); err == nil { 726 c.GuildService.Nickname = self.Nickname 727 c.GuildService.AvatarUrl = self.AvatarUrl 728 } else { 729 c.error("get self guild profile error: %v", err) 730 } 731 } 732 733 func (c *QQClient) buildSyncChannelFirstViewPacket() (uint16, []byte) { 734 req := &channel.FirstViewReq{ 735 LastMsgTime: proto.Uint64(0), 736 Seq: proto.Uint32(0), 737 DirectMessageFlag: proto.Uint32(1), 738 } 739 payload, _ := proto.Marshal(req) 740 return c.uniPacket("trpc.group_pro.synclogic.SyncLogic.SyncFirstView", payload) 741 } 742 743 func decodeGuildPushFirstView(c *QQClient, pkt *network.Packet) (any, error) { 744 firstViewMsg := new(channel.FirstViewMsg) 745 if err := proto.Unmarshal(pkt.Payload, firstViewMsg); err != nil { 746 return nil, errors.Wrap(err, "failed to unmarshal protobuf message") 747 } 748 if len(firstViewMsg.GuildNodes) > 0 { 749 c.GuildService.Guilds = []*GuildInfo{} 750 for _, guild := range firstViewMsg.GuildNodes { 751 info := &GuildInfo{ 752 GuildId: guild.GuildId.Unwrap(), 753 GuildCode: guild.GuildCode.Unwrap(), 754 GuildName: utils.B2S(guild.GuildName), 755 CoverUrl: fmt.Sprintf("https://groupprocover-76483.picgzc.qpic.cn/%v", guild.GuildId.Unwrap()), 756 AvatarUrl: fmt.Sprintf("https://groupprohead-76292.picgzc.qpic.cn/%v", guild.GuildId.Unwrap()), 757 } 758 channels, err := c.GuildService.FetchChannelList(info.GuildId) 759 if err != nil { 760 c.warning("warning: fetch guild %v channel error %v. will use sync node to fill channel list field", guild.GuildId, err) 761 for _, node := range guild.ChannelNodes { 762 meta := new(channel.ChannelMsgMeta) 763 _ = proto.Unmarshal(node.Meta, meta) 764 info.Channels = append(info.Channels, &ChannelInfo{ 765 ChannelId: node.ChannelId.Unwrap(), 766 ChannelName: utils.B2S(node.ChannelName), 767 Time: node.Time.Unwrap(), 768 EventTime: node.EventTime.Unwrap(), 769 NotifyType: node.NotifyType.Unwrap(), 770 ChannelType: ChannelType(node.ChannelType.Unwrap()), 771 AtAllSeq: meta.AtAllSeq.Unwrap(), 772 }) 773 } 774 } else { 775 info.Channels = channels 776 } 777 // info.Bots, info.Members, info.Admins, _ = c.GuildService.GetGuildMembers(info.GuildId) 778 c.GuildService.Guilds = append(c.GuildService.Guilds, info) 779 } 780 } 781 // if len(firstViewMsg.ChannelMsgs) > 0 { // sync msg 782 // } 783 return nil, nil 784 }