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

supported GroupInvitedEvent and UserJoinGroupRequestEvent.

This commit is contained in:
Mrs4s 2020-07-16 03:18:12 +08:00
parent 73ae45edf6
commit 6edec8d4d6
8 changed files with 3498 additions and 13 deletions

View File

@ -33,7 +33,8 @@ qq-android协议的golang实现 移植于Mirai
- [x] 群消息撤回 - [x] 群消息撤回
- [x] 群禁言 - [x] 群禁言
- [x] 群成员权限变更 - [x] 群成员权限变更
- [ ] 被邀请进群 - [x] 收到邀请进群通知
- [x] 收到其他用户进群请求
- [ ] 新好友 - [ ] 新好友
#### 主动操作 #### 主动操作

View File

@ -6,6 +6,7 @@ import (
"github.com/Mrs4s/MiraiGo/binary/jce" "github.com/Mrs4s/MiraiGo/binary/jce"
"github.com/Mrs4s/MiraiGo/client/pb" "github.com/Mrs4s/MiraiGo/client/pb"
"github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/msg"
"github.com/Mrs4s/MiraiGo/client/pb/structmsg"
"github.com/Mrs4s/MiraiGo/message" "github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/MiraiGo/protocol/crypto" "github.com/Mrs4s/MiraiGo/protocol/crypto"
"github.com/Mrs4s/MiraiGo/protocol/packets" "github.com/Mrs4s/MiraiGo/protocol/packets"
@ -109,6 +110,7 @@ func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byt
return seq, packet return seq, packet
} }
// StatSvc.register
func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) { func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
svc := &jce.SvcReqRegister{ svc := &jce.SvcReqRegister{
@ -156,6 +158,7 @@ func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) {
return seq, packet return seq, packet
} }
// ConfigPushSvc.PushResp
func (c *QQClient) buildConfPushRespPacket(t int32, pktSeq int64, jceBuf []byte) (uint16, []byte) { func (c *QQClient) buildConfPushRespPacket(t int32, pktSeq int64, jceBuf []byte) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
req := jce.NewJceWriter() req := jce.NewJceWriter()
@ -179,6 +182,7 @@ func (c *QQClient) buildConfPushRespPacket(t int32, pktSeq int64, jceBuf []byte)
return seq, packet return seq, packet
} }
// friendlist.getFriendGroupList
func (c *QQClient) buildFriendGroupListRequestPacket(friendStartIndex, friendListCount, groupStartIndex, groupListCount int16) (uint16, []byte) { func (c *QQClient) buildFriendGroupListRequestPacket(friendStartIndex, friendListCount, groupStartIndex, groupListCount int16) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
d50, _ := proto.Marshal(&pb.D50ReqBody{ d50, _ := proto.Marshal(&pb.D50ReqBody{
@ -238,6 +242,7 @@ func (c *QQClient) buildFriendGroupListRequestPacket(friendStartIndex, friendLis
return seq, packet return seq, packet
} }
// friendlist.GetTroopListReqV2
func (c *QQClient) buildGroupListRequestPacket() (uint16, []byte) { func (c *QQClient) buildGroupListRequestPacket() (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
req := &jce.TroopListRequest{ req := &jce.TroopListRequest{
@ -270,6 +275,7 @@ func (c *QQClient) buildGroupListRequestPacket() (uint16, []byte) {
return seq, packet return seq, packet
} }
// friendlist.GetTroopMemberListReq
func (c *QQClient) buildGroupMemberListRequestPacket(groupUin, groupCode, nextUin int64) (uint16, []byte) { func (c *QQClient) buildGroupMemberListRequestPacket(groupUin, groupCode, nextUin int64) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
req := &jce.TroopMemberListRequest{ req := &jce.TroopMemberListRequest{
@ -297,6 +303,7 @@ func (c *QQClient) buildGroupMemberListRequestPacket(groupUin, groupCode, nextUi
return seq, packet return seq, packet
} }
// MessageSvc.PbGetMsg
func (c *QQClient) buildGetMessageRequestPacket(flag msg.SyncFlag, msgTime int64) (uint16, []byte) { func (c *QQClient) buildGetMessageRequestPacket(flag msg.SyncFlag, msgTime int64) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
cook := c.syncCookie cook := c.syncCookie
@ -332,6 +339,7 @@ func (c *QQClient) buildStopGetMessagePacket(msgTime int64) []byte {
return pkt return pkt
} }
// MessageSvc.PbDeleteMsg
func (c *QQClient) buildDeleteMessageRequestPacket(msg []*pb.MessageItem) (uint16, []byte) { func (c *QQClient) buildDeleteMessageRequestPacket(msg []*pb.MessageItem) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
req := &pb.DeleteMessageRequest{Items: msg} req := &pb.DeleteMessageRequest{Items: msg}
@ -340,6 +348,7 @@ func (c *QQClient) buildDeleteMessageRequestPacket(msg []*pb.MessageItem) (uint1
return seq, packet return seq, packet
} }
// OnlinePush.RespPush
func (c *QQClient) buildDeleteOnlinePushPacket(uin int64, seq uint16, delMsg []jce.PushMessageInfo) []byte { func (c *QQClient) buildDeleteOnlinePushPacket(uin int64, seq uint16, delMsg []jce.PushMessageInfo) []byte {
req := &jce.SvcRespPushMsg{Uin: uin} req := &jce.SvcRespPushMsg{Uin: uin}
for _, m := range delMsg { for _, m := range delMsg {
@ -367,6 +376,7 @@ func (c *QQClient) buildDeleteOnlinePushPacket(uin int64, seq uint16, delMsg []j
return packets.BuildUniPacket(c.Uin, seq, "OnlinePush.RespPush", 1, c.OutGoingPacketSessionId, []byte{}, c.sigInfo.d2Key, pkt.ToBytes()) return packets.BuildUniPacket(c.Uin, seq, "OnlinePush.RespPush", 1, c.OutGoingPacketSessionId, []byte{}, c.sigInfo.d2Key, pkt.ToBytes())
} }
// MessageSvc.PbSendMsg
func (c *QQClient) buildGroupSendingPacket(groupCode int64, r int32, m *message.SendingMessage) (uint16, []byte) { func (c *QQClient) buildGroupSendingPacket(groupCode int64, r int32, m *message.SendingMessage) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
req := &msg.SendMessageRequest{ req := &msg.SendMessageRequest{
@ -388,6 +398,7 @@ func (c *QQClient) buildGroupSendingPacket(groupCode int64, r int32, m *message.
return seq, packet return seq, packet
} }
// ImgStore.GroupPicUp
func (c *QQClient) buildGroupImageStorePacket(groupCode int64, md5 [16]byte, size int32) (uint16, []byte) { func (c *QQClient) buildGroupImageStorePacket(groupCode int64, md5 [16]byte, size int32) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
name := utils.RandomString(16) + ".gif" name := utils.RandomString(16) + ".gif"
@ -460,3 +471,35 @@ func (c *QQClient) buildImageUploadPacket(data, updKey []byte, commandId int32,
}) })
return return
} }
// ProfileService.Pb.ReqSystemMsgNew.Group
func (c *QQClient) buildSystemMsgNewGroupPacket() (uint16, []byte) {
seq := c.nextSeq()
req := &structmsg.ReqSystemMsgNew{
MsgNum: 5,
Version: 100,
Checktype: 3,
Flag: &structmsg.FlagInfo{
GrpMsgKickAdmin: 1,
GrpMsgHiddenGrp: 1,
GrpMsgWordingDown: 1,
GrpMsgGetOfficialAccount: 1,
GrpMsgGetPayInGroup: 1,
FrdMsgDiscuss2ManyChat: 1,
GrpMsgNotAllowJoinGrpInviteNotFrd: 1,
FrdMsgNeedWaitingMsg: 1,
FrdMsgUint32NeedAllUnreadMsg: 1,
GrpMsgNeedAutoAdminWording: 1,
GrpMsgGetTransferGroupMsgFlag: 1,
GrpMsgGetQuitPayGroupMsgFlag: 1,
GrpMsgSupportInviteAutoJoin: 1,
GrpMsgMaskInviteAutoJoin: 1,
GrpMsgGetDisbandedByAdmin: 1,
GrpMsgGetC2CInviteJoinGroup: 1,
},
FriendMsgTypeFlag: 1,
}
payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "ProfileService.Pb.ReqSystemMsgNew.Group", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet
}

View File

@ -107,6 +107,7 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
"friendlist.GetTroopListReqV2": decodeGroupListResponse, "friendlist.GetTroopListReqV2": decodeGroupListResponse,
"friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse, "friendlist.GetTroopMemberListReq": decodeGroupMemberListResponse,
"ImgStore.GroupPicUp": decodeGroupImageStoreResponse, "ImgStore.GroupPicUp": decodeGroupImageStoreResponse,
"ProfileService.Pb.ReqSystemMsgNew.Group": decodeSystemMsgGroupPacket,
}, },
handlers: map[uint16]func(interface{}, error){}, handlers: map[uint16]func(interface{}, error){},
sigInfo: &loginSigInfo{}, sigInfo: &loginSigInfo{},

View File

@ -6,6 +6,7 @@ import (
"github.com/Mrs4s/MiraiGo/binary/jce" "github.com/Mrs4s/MiraiGo/binary/jce"
"github.com/Mrs4s/MiraiGo/client/pb" "github.com/Mrs4s/MiraiGo/client/pb"
"github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/msg"
"github.com/Mrs4s/MiraiGo/client/pb/structmsg"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"sync" "sync"
"time" "time"
@ -181,6 +182,9 @@ func decodeMessageSvcPacket(c *QQClient, _ uint16, payload []byte) (interface{},
} }
} }
groupJoinLock.Unlock() groupJoinLock.Unlock()
case 84, 87:
_, pkt := c.buildSystemMsgNewGroupPacket()
_ = c.send(pkt)
case 141: // 临时会话 case 141: // 临时会话
if message.Head.C2CTmpMsgHead == nil { if message.Head.C2CTmpMsgHead == nil {
continue continue
@ -514,3 +518,37 @@ func decodeOnlinePushTransPacket(c *QQClient, _ uint16, payload []byte) (interfa
} }
return nil, nil return nil, nil
} }
func decodeSystemMsgGroupPacket(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
rsp := structmsg.RspSystemMsgNew{}
if err := proto.Unmarshal(payload, &rsp); err != nil {
return nil, err
}
if len(rsp.Groupmsgs) == 0 {
return nil, nil
}
st := rsp.Groupmsgs[0]
// 其他SubType不关心
if st.Msg.SubType == 1 {
switch st.Msg.C2CInviteJoinGroupFlag {
case 0: //成员申请
c.dispatchJoinGroupRequest(&UserJoinGroupRequest{
RequestId: st.MsgSeq,
Message: st.Msg.MsgAdditional,
RequesterUin: st.ReqUin,
RequesterNick: st.Msg.ReqUinNick,
GroupCode: st.Msg.GroupCode,
GroupName: st.Msg.GroupName,
})
case 1: // 被邀请
c.dispatchGroupInvitedEvent(&GroupInvitedEvent{
EventId: st.MsgSeq,
InvitorUin: st.Msg.ActionUin,
InvitorNick: st.Msg.ActionUinNick,
GroupCode: st.Msg.GroupCode,
GroupName: st.Msg.GroupName,
})
}
}
return nil, nil
}

View File

@ -104,6 +104,23 @@ type (
NewPermission MemberPermission NewPermission MemberPermission
} }
GroupInvitedEvent struct {
EventId int64
InvitorUin int64
InvitorNick string
GroupCode int64
GroupName string
}
UserJoinGroupRequest struct {
RequestId int64
Message string
RequesterUin int64
RequesterNick string
GroupCode int64
GroupName string
}
groupMemberListResponse struct { groupMemberListResponse struct {
NextUin int64 NextUin int64
list []*GroupMemberInfo list []*GroupMemberInfo

View File

@ -16,6 +16,8 @@ type eventHandlers struct {
memberJoinedHandlers []func(*QQClient, *MemberJoinGroupEvent) memberJoinedHandlers []func(*QQClient, *MemberJoinGroupEvent)
memberLeavedHandlers []func(*QQClient, *MemberLeaveGroupEvent) memberLeavedHandlers []func(*QQClient, *MemberLeaveGroupEvent)
permissionChangedHandlers []func(*QQClient, *MemberPermissionChangedEvent) permissionChangedHandlers []func(*QQClient, *MemberPermissionChangedEvent)
groupInvitedHandlers []func(*QQClient, *GroupInvitedEvent)
joinRequestHandlers []func(*QQClient, *UserJoinGroupRequest)
groupMessageReceiptHandlers sync.Map groupMessageReceiptHandlers sync.Map
} }
@ -67,6 +69,14 @@ func (c *QQClient) OnGroupMessageRecalled(f func(*QQClient, *GroupMessageRecalle
c.eventHandlers.groupRecalledHandlers = append(c.eventHandlers.groupRecalledHandlers, f) c.eventHandlers.groupRecalledHandlers = append(c.eventHandlers.groupRecalledHandlers, f)
} }
func (c *QQClient) OnGroupInvited(f func(*QQClient, *GroupInvitedEvent)) {
c.eventHandlers.groupInvitedHandlers = append(c.eventHandlers.groupInvitedHandlers, f)
}
func (c *QQClient) OnUserWantJoinGroup(f func(*QQClient, *UserJoinGroupRequest)) {
c.eventHandlers.joinRequestHandlers = append(c.eventHandlers.joinRequestHandlers, f)
}
func NewUinFilterPrivate(uin int64) func(*message.PrivateMessage) bool { func NewUinFilterPrivate(uin int64) func(*message.PrivateMessage) bool {
return func(msg *message.PrivateMessage) bool { return func(msg *message.PrivateMessage) bool {
return msg.Sender.Uin == uin return msg.Sender.Uin == uin
@ -198,6 +208,28 @@ func (c *QQClient) dispatchGroupMessageReceiptEvent(e *groupMessageReceiptEvent)
}) })
} }
func (c *QQClient) dispatchGroupInvitedEvent(e *GroupInvitedEvent) {
if e == nil {
return
}
for _, f := range c.eventHandlers.groupInvitedHandlers {
cover(func() {
f(c, e)
})
}
}
func (c *QQClient) dispatchJoinGroupRequest(r *UserJoinGroupRequest) {
if r == nil {
return
}
for _, f := range c.eventHandlers.joinRequestHandlers {
cover(func() {
f(c, r)
})
}
}
func cover(f func()) { func cover(f func()) {
defer func() { defer func() {
if pan := recover(); pan != nil { if pan := recover(); pan != nil {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,241 @@
syntax = "proto3";
option go_package = ".;structmsg";
message AddFrdSNInfo {
int32 notSeeDynamic = 1;
int32 setSn = 2;
}
message FlagInfo {
int32 grpMsgKickAdmin = 1;
int32 grpMsgHiddenGrp = 2;
int32 grpMsgWordingDown = 3;
int32 frdMsgGetBusiCard = 4;
int32 grpMsgGetOfficialAccount = 5;
int32 grpMsgGetPayInGroup = 6;
int32 frdMsgDiscuss2ManyChat = 7;
int32 grpMsgNotAllowJoinGrpInviteNotFrd = 8;
int32 frdMsgNeedWaitingMsg = 9;
int32 frdMsgUint32NeedAllUnreadMsg = 10;
int32 grpMsgNeedAutoAdminWording = 11;
int32 grpMsgGetTransferGroupMsgFlag = 12;
int32 grpMsgGetQuitPayGroupMsgFlag = 13;
int32 grpMsgSupportInviteAutoJoin = 14;
int32 grpMsgMaskInviteAutoJoin = 15;
int32 grpMsgGetDisbandedByAdmin = 16;
int32 grpMsgGetC2cInviteJoinGroup = 17;
}
message FriendInfo {
string msgJointFriend = 1;
string msgBlacklist = 2;
}
message GroupInfo {
int32 groupAuthType = 1;
int32 displayAction = 2;
string msgAlert = 3;
string msgDetailAlert = 4;
string msgOtherAdminDone = 5;
int32 appPrivilegeFlag = 6;
}
message MsgInviteExt {
int32 srcType = 1;
int64 srcCode = 2;
int32 waitState = 3;
}
message MsgPayGroupExt {
int64 joinGrpTime = 1;
int64 quitGrpTime = 2;
}
message ReqNextSystemMsg {
int32 msgNum = 1;
int64 followingFriendSeq = 2;
int64 followingGroupSeq = 3;
int32 checktype = 4;
FlagInfo flag = 5;
int32 language = 6;
int32 version = 7;
int64 friendMsgTypeFlag = 8;
}
message ReqSystemMsg {
int32 msgNum = 1;
int64 latestFriendSeq = 2;
int64 latestGroupSeq = 3;
int32 version = 4;
int32 language = 5;
}
message ReqSystemMsgAction {
int32 msgType = 1;
int64 msgSeq = 2;
int64 reqUin = 3;
int32 subType = 4;
int32 srcId = 5;
int32 subSrcId = 6;
int32 groupMsgType = 7;
SystemMsgActionInfo actionInfo = 8;
int32 language = 9;
}
message ReqSystemMsgNew {
int32 msgNum = 1;
int64 latestFriendSeq = 2;
int64 latestGroupSeq = 3;
int32 version = 4;
int32 checktype = 5;
FlagInfo flag = 6;
int32 language = 7;
bool isGetFrdRibbon = 8;
bool isGetGrpRibbon = 9;
int64 friendMsgTypeFlag = 10;
}
message ReqSystemMsgRead {
int64 latestFriendSeq = 1;
int64 latestGroupSeq = 2;
int32 type = 3;
int32 checktype = 4;
}
message RspHead {
int32 result = 1;
string msgFail = 2;
}
message RspNextSystemMsg {
RspHead head = 1;
repeated StructMsg msgs = 2;
int64 followingFriendSeq = 3;
int64 followingGroupSeq = 4;
int32 checktype = 5;
string gameNick = 100;
bytes undecidForQim = 101;
int32 unReadCount3 = 102;
}
message RspSystemMsg {
RspHead head = 1;
repeated StructMsg msgs = 2;
int32 unreadCount = 3;
int64 latestFriendSeq = 4;
int64 latestGroupSeq = 5;
int64 followingFriendSeq = 6;
int64 followingGroupSeq = 7;
string msgDisplay = 8;
}
message RspSystemMsgAction {
RspHead head = 1;
string msgDetail = 2;
int32 type = 3;
string msgInvalidDecided = 5;
int32 remarkResult = 6;
}
message RspSystemMsgNew {
RspHead head = 1;
int32 unreadFriendCount = 2;
int32 unreadGroupCount = 3;
int64 latestFriendSeq = 4;
int64 latestGroupSeq = 5;
int64 followingFriendSeq = 6;
int64 followingGroupSeq = 7;
repeated StructMsg friendmsgs = 9;
repeated StructMsg groupmsgs = 10;
StructMsg msgRibbonFriend = 11;
StructMsg msgRibbonGroup = 12;
string msgDisplay = 13;
string grpMsgDisplay = 14;
int32 over = 15;
int32 checktype = 20;
string gameNick = 100;
bytes undecidForQim = 101;
int32 unReadCount3 = 102;
}
message RspSystemMsgRead {
RspHead head = 1;
int32 type = 2;
int32 checktype = 3;
}
message StructMsg {
int32 version = 1;
int32 msgType = 2;
int64 msgSeq = 3;
int64 msgTime = 4;
int64 reqUin = 5;
int32 unreadFlag = 6;
SystemMsg msg = 50;
}
message SystemMsg {
int32 subType = 1;
string msgTitle = 2;
string msgDescribe = 3;
string msgAdditional = 4;
string msgSource = 5;
string msgDecided = 6;
int32 srcId = 7;
int32 subSrcId = 8;
repeated SystemMsgAction actions = 9;
int64 groupCode = 10;
int64 actionUin = 11;
int32 groupMsgType = 12;
int32 groupInviterRole = 13;
FriendInfo friendInfo = 14;
GroupInfo groupInfo = 15;
int64 actorUin = 16;
string msgActorDescribe = 17;
string msgAdditionalList = 18;
int32 relation = 19;
int32 reqsubtype = 20;
int64 cloneUin = 21;
int64 discussUin = 22;
int64 eimGroupId = 23;
MsgInviteExt msgInviteExtinfo = 24;
MsgPayGroupExt msgPayGroupExtinfo = 25;
int32 sourceFlag = 26;
bytes gameNick = 27;
bytes gameMsg = 28;
int32 groupFlagext3 = 29;
int64 groupOwnerUin = 30;
int32 doubtFlag = 31;
bytes warningTips = 32;
bytes nameMore = 33;
int32 reqUinFaceid = 50;
string reqUinNick = 51;
string groupName = 52;
string actionUinNick = 53;
string msgQna = 54;
string msgDetail = 55;
int32 groupExtFlag = 57;
string actorUinNick = 58;
string picUrl = 59;
string cloneUinNick = 60;
string reqUinBusinessCard = 61;
string eimGroupIdName = 63;
string reqUinPreRemark = 64;
string actionUinQqNick = 65;
string actionUinRemark = 66;
int32 reqUinGender = 67;
int32 reqUinAge = 68;
int32 c2cInviteJoinGroupFlag = 69;
int32 cardSwitch = 101;
}
message SystemMsgAction {
string name = 1;
string result = 2;
int32 action = 3;
SystemMsgActionInfo actionInfo = 4;
string detailName = 5;
}
message SystemMsgActionInfo {
int32 type = 1;
int64 groupCode = 2;
bytes sig = 3;
string msg = 50;
int32 groupId = 51;
string remark = 52;
bool blacklist = 53;
AddFrdSNInfo addFrdSNInfo = 54;
}