1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 19:17:38 +08:00

feat: channel info support

This commit is contained in:
Mrs4s 2021-11-06 03:04:04 +08:00
parent ddf1e5e371
commit 5e371689e6
No known key found for this signature in database
GPG Key ID: 3186E98FA19CE3A7
7 changed files with 3864 additions and 1 deletions

101
client/channel.go Normal file
View File

@ -0,0 +1,101 @@
package client
import (
"github.com/Mrs4s/MiraiGo/client/pb/channel"
"github.com/Mrs4s/MiraiGo/internal/packets"
"github.com/Mrs4s/MiraiGo/utils"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
)
// ChannelSelfInfo 频道模块内自身的信息
type ChannelSelfInfo struct {
TinyId uint64
ChannelCount uint32
// Guilds 由服务器推送的频道列表
Guilds []*GuildInfo
}
// GuildInfo 频道信息
type GuildInfo struct {
GuildId uint64
GuildCode uint64
GuildName string
Channels []*ChannelInfo
}
// ChannelInfo 子频道信息
type ChannelInfo struct {
ChannelId uint64
ChannelName string
Time uint64
EventTime uint32
NotifyType uint32
ChannelType uint32
AtAllSeq uint64
}
func init() {
decoders["trpc.group_pro.synclogic.SyncLogic.PushFirstView"] = decodeChannelPushFirstView
}
func (c *QQClient) syncChannelFirstView() {
rsp, err := c.sendAndWaitDynamic(c.buildSyncChannelFirstViewPacket())
if err != nil {
c.Error("sync channel error: %v", err)
return
}
firstViewRsp := new(channel.FirstViewRsp)
if err = proto.Unmarshal(rsp, firstViewRsp); err != nil {
return
}
c.ChannelSelf.TinyId = firstViewRsp.GetSelfTinyid()
c.ChannelSelf.ChannelCount = firstViewRsp.GetGuildCount()
}
func (c *QQClient) buildSyncChannelFirstViewPacket() (uint16, []byte) {
seq := c.nextSeq()
req := &channel.FirstViewReq{
LastMsgTime: proto.Uint64(0),
Seq: proto.Uint32(0),
DirectMessageFlag: proto.Uint32(1),
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "trpc.group_pro.synclogic.SyncLogic.SyncFirstView", 1, c.OutGoingPacketSessionId, []byte{}, c.sigInfo.d2Key, payload)
return seq, packet
}
func decodeChannelPushFirstView(c *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) {
firstViewMsg := new(channel.FirstViewMsg)
if err := proto.Unmarshal(payload, firstViewMsg); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal protobuf message")
}
if len(firstViewMsg.GuildNodes) > 0 {
c.ChannelSelf.Guilds = []*GuildInfo{}
for _, guild := range firstViewMsg.GuildNodes {
info := &GuildInfo{
GuildId: guild.GetGuildId(),
GuildCode: guild.GetGuildCode(),
GuildName: utils.B2S(guild.GuildName),
}
for _, node := range guild.ChannelNodes {
meta := new(channel.ChannelMsgMeta)
_ = proto.Unmarshal(node.Meta, meta)
info.Channels = append(info.Channels, &ChannelInfo{
ChannelId: node.GetChannelId(),
ChannelName: utils.B2S(node.ChannelName),
Time: node.GetTime(),
EventTime: node.GetEventTime(),
NotifyType: node.GetNotifyType(),
ChannelType: node.GetChannelType(),
AtAllSeq: meta.GetAtAllSeq(),
})
}
c.ChannelSelf.Guilds = append(c.ChannelSelf.Guilds, info)
}
}
if len(firstViewMsg.ChannelMsgs) > 0 { // sync msg
}
return nil, nil
}

View File

@ -44,6 +44,7 @@ type QQClient struct {
OnlineClients []*OtherClientInfo OnlineClients []*OtherClientInfo
Online bool Online bool
QiDian *QiDianAccountInfo QiDian *QiDianAccountInfo
ChannelSelf *ChannelSelfInfo
// protocol public field // protocol public field
SequenceId int32 SequenceId int32
@ -199,6 +200,7 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
RandomKey: make([]byte, 16), RandomKey: make([]byte, 16),
OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B}, OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B},
TCP: &utils.TCPListener{}, TCP: &utils.TCPListener{},
ChannelSelf: &ChannelSelfInfo{},
sigInfo: &loginSigInfo{}, sigInfo: &loginSigInfo{},
requestPacketRequestID: 1921334513, requestPacketRequestID: 1921334513,
groupSeq: int32(rand.Intn(20000)), groupSeq: int32(rand.Intn(20000)),
@ -451,6 +453,7 @@ func (c *QQClient) init(tokenLogin bool) error {
} }
seq, pkt := c.buildGetMessageRequestPacket(msg.SyncFlag_START, time.Now().Unix()) seq, pkt := c.buildGetMessageRequestPacket(msg.SyncFlag_START, time.Now().Unix())
_, _ = c.sendAndWait(seq, pkt, requestParams{"used_reg_proxy": true, "init": true}) _, _ = c.sendAndWait(seq, pkt, requestParams{"used_reg_proxy": true, "init": true})
c.syncChannelFirstView()
return nil return nil
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
syntax = "proto2";
package channel;
option go_package = "pb/channel;channel";
import "pb/msg/msg.proto";
message ChannelContentHead {
optional uint64 type = 1;
optional uint64 subType = 2;
optional uint64 random = 3;
optional uint64 seq = 4;
optional uint64 cntSeq = 5;
optional uint64 time = 6;
optional bytes meta = 7;
}
message DirectMessageMember {
optional uint64 uin = 1;
optional uint64 tinyid = 2;
optional uint64 sourceGuildId = 3;
optional bytes sourceGuildName = 4;
optional bytes nickName = 5;
optional bytes memberName = 6;
optional uint32 notifyType = 7;
}
message ChannelEvent {
optional uint64 type = 1;
optional uint64 version = 2;
optional ChannelMsgOpInfo opInfo = 3;
}
message ChannelExtInfo {
optional bytes fromNick = 1;
optional bytes guildName = 2;
optional bytes channelName = 3;
optional uint32 visibility = 4;
optional uint32 notifyType = 5;
optional uint32 offlineFlag = 6;
optional uint32 nameType = 7;
optional bytes memberName = 8;
optional uint32 timestamp = 9;
optional uint64 eventVersion = 10;
repeated ChannelEvent events = 11;
optional ChannelRole fromRoleInfo = 12;
optional ChannelFreqLimitInfo freqLimitInfo = 13;
repeated DirectMessageMember directMessageMember = 14;
}
message ChannelFreqLimitInfo {
optional uint32 isLimited = 1;
optional uint32 leftCount = 2;
optional uint64 limitTimestamp = 3;
}
message ChannelInfo {
optional uint64 id = 1;
optional bytes name = 2;
optional uint32 color = 3;
optional uint32 hoist = 4;
}
message ChannelLoginSig {
optional uint32 type = 1;
optional bytes sig = 2;
optional uint32 appid = 3;
}
message ChannelMeta {
optional uint64 fromUin = 1;
optional ChannelLoginSig loginSig = 2;
}
message ChannelMsgContent {
optional ChannelMsgHead head = 1;
optional ChannelMsgCtrlHead ctrlHead = 2;
optional msg.MessageBody body = 3;
optional ChannelExtInfo extInfo = 4;
}
message ChannelMsgCtrlHead {
repeated uint64 includeUin = 1;
repeated uint64 excludeUin = 2;
repeated uint64 featureid = 3;
optional uint32 offlineFlag = 4;
optional uint32 visibility = 5;
optional uint64 ctrlFlag = 6;
repeated ChannelEvent events = 7;
optional uint64 level = 8;
repeated PersonalLevel personalLevels = 9;
optional uint64 guildSyncSeq = 10;
optional uint32 memberNum = 11;
optional uint32 channelType = 12;
optional uint32 privateType = 13;
}
message ChannelMsgHead {
optional ChannelRoutingHead routingHead = 1;
optional ChannelContentHead contentHead = 2;
}
message ChannelMsgMeta {
optional uint64 atAllSeq = 1;
}
message ChannelMsgOpInfo {
optional uint64 operatorTinyid = 1;
optional uint64 operatorRole = 2;
optional uint64 reason = 3;
optional uint64 timestamp = 4;
optional uint64 atType = 5;
}
message PersonalLevel {
optional uint64 toUin = 1;
optional uint64 level = 2;
}
message ChannelRole {
optional uint64 id = 1;
optional bytes info = 2;
optional uint32 flag = 3;
}
message ChannelRoutingHead {
optional uint64 guildId = 1;
optional uint64 channelId = 2;
optional uint64 fromUin = 3;
optional uint64 fromTinyid = 4;
optional uint64 guildCode = 5;
optional uint64 fromAppid = 6;
optional uint32 directMessageFlag = 7;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,134 @@
syntax = "proto2";
package channel;
option go_package = "pb/channel;channel";
import "pb/channel/common.proto";
message ChannelMsg {
optional uint64 guildId = 1;
optional uint64 channelId = 2;
optional uint32 result = 3;
optional uint64 rspBeginSeq = 4;
optional uint64 rspEndSeq = 5;
repeated ChannelMsgContent msgs = 6;
}
message ChannelMsgReq {
optional ChannelParam channelParam = 1;
optional uint32 withVersionFlag = 2;
optional uint32 directMessageFlag = 3;
}
message ChannelMsgRsp {
optional uint32 result = 1;
optional bytes errMsg = 2;
optional ChannelMsg channelMsg = 3;
optional uint32 withVersionFlag = 4;
optional uint64 getMsgTime = 5;
}
message ChannelNode {
optional uint64 channelId = 1;
optional uint64 seq = 2;
optional uint64 cntSeq = 3;
optional uint64 time = 4;
optional uint64 memberReadMsgSeq = 5;
optional uint64 memberReadCntSeq = 6;
optional uint32 notifyType = 7;
optional bytes channelName = 8;
optional uint32 channelType = 9;
optional bytes meta = 10;
optional bytes readMsgMeta = 11;
optional uint32 eventTime = 12;
}
message ChannelParam {
optional uint64 guildId = 1;
optional uint64 channelId = 2;
optional uint64 beginSeq = 3;
optional uint64 endSeq = 4;
optional uint64 time = 5;
repeated uint64 version = 6;
repeated MsgCond seqs = 7;
}
message DirectMessageSource {
optional uint64 tinyId = 1;
optional uint64 guildId = 2;
optional bytes guildName = 3;
optional bytes memberName = 4;
optional bytes nickName = 5;
}
message FirstViewMsg {
optional uint32 pushFlag = 1;
optional uint32 seq = 2;
repeated GuildNode guildNodes = 3;
repeated ChannelMsg channelMsgs = 4;
optional uint64 getMsgTime = 5;
repeated GuildNode directMessageGuildNodes = 6;
}
message FirstViewReq {
optional uint64 lastMsgTime = 1;
optional uint32 udcFlag = 2;
optional uint32 seq = 3;
optional uint32 directMessageFlag = 4;
}
message FirstViewRsp {
optional uint32 result = 1;
optional bytes errMsg = 2;
optional uint32 seq = 3;
optional uint32 udcFlag = 4;
optional uint32 guildCount = 5;
optional uint64 selfTinyid = 6;
optional uint32 directMessageSwitch = 7;
optional uint32 directMessageGuildCount = 8;
}
message GuildNode {
optional uint64 guildId = 1;
optional uint64 guildCode = 2;
repeated ChannelNode channelNodes = 3;
optional bytes guildName = 4;
optional DirectMessageSource peerSource = 5;
}
message MsgCond {
optional uint64 seq = 1;
optional uint64 eventVersion = 2;
}
message MultiChannelMsg {
optional uint32 pushFlag = 1;
optional uint32 seq = 2;
repeated ChannelMsg channelMsgs = 3;
optional uint64 getMsgTime = 4;
}
message MultiChannelMsgReq {
repeated ChannelParam channelParams = 1;
optional uint32 seq = 2;
optional uint32 directMessageFlag = 3;
}
message MultiChannelMsgRsp {
optional uint32 result = 1;
optional bytes errMsg = 2;
optional uint32 seq = 3;
}
message ReqBody {
optional ChannelParam channelParam = 1;
optional uint32 directMessageFlag = 2;
}
message RspBody {
optional uint32 result = 1;
optional bytes errMsg = 2;
optional ChannelMsg channelMsg = 3;
}

View File

@ -1,6 +1,8 @@
syntax = "proto2"; syntax = "proto2";
option go_package = "./;msg"; package msg;
option go_package = "github.com/Mrs4s/MiraiGo/client/pb/msg;msg";
message GetMessageRequest { message GetMessageRequest {
optional SyncFlag syncFlag = 1; optional SyncFlag syncFlag = 1;