diff --git a/binary/jce/writer.go b/binary/jce/writer.go index d5d803c8..3153fbdb 100644 --- a/binary/jce/writer.go +++ b/binary/jce/writer.go @@ -34,7 +34,7 @@ func (w *JceWriter) WriteByte(b, tag byte) *JceWriter { } func (w *JceWriter) WriteBool(b bool, tag byte) { - var by byte = 0 + var by byte if b { by = 1 } diff --git a/binary/protobuf.go b/binary/protobuf.go index 30573eac..51c5b278 100644 --- a/binary/protobuf.go +++ b/binary/protobuf.go @@ -14,6 +14,8 @@ type encoder struct { func (msg DynamicProtoMessage) Encode() []byte { en := &encoder{} + + //nolint:staticcheck for id, value := range msg { key := id << 3 switch v := value.(type) { diff --git a/binary/reader.go b/binary/reader.go index 0ddd86af..05bb2d77 100644 --- a/binary/reader.go +++ b/binary/reader.go @@ -97,11 +97,12 @@ func (r *Reader) ReadTlvMap(tagSize int) (m TlvMap) { return m } var k uint16 - if tagSize == 1 { + switch tagSize { + case 1: k = uint16(r.ReadByte()) - } else if tagSize == 2 { + case 2: k = r.ReadUInt16() - } else if tagSize == 4 { + case 4: k = uint16(r.ReadInt32()) } if k == 255 { diff --git a/binary/tea.go b/binary/tea.go index 455933f2..1966935d 100644 --- a/binary/tea.go +++ b/binary/tea.go @@ -29,7 +29,7 @@ func (t TEA) Encrypt(src []byte) (dst []byte) { block := binary.BigEndian.Uint64(dst[i:]) holder = block ^ iv1 iv1 = t.encode(holder) - iv1 = iv1 ^ iv2 + iv1 ^= iv2 iv2 = holder binary.BigEndian.PutUint64(dst[i:], iv1) } diff --git a/client/builders.go b/client/builders.go index c6a543f8..69a0d1c5 100644 --- a/client/builders.go +++ b/client/builders.go @@ -3,7 +3,6 @@ package client import ( "crypto/md5" "encoding/hex" - "fmt" "math/rand" "time" @@ -14,7 +13,6 @@ import ( "github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/oidb" "github.com/Mrs4s/MiraiGo/client/pb/profilecard" - "github.com/Mrs4s/MiraiGo/client/pb/qweb" "github.com/Mrs4s/MiraiGo/client/pb/structmsg" "github.com/Mrs4s/MiraiGo/internal/crypto" "github.com/Mrs4s/MiraiGo/internal/packets" @@ -1080,6 +1078,7 @@ func (c *QQClient) buildQuitGroupPacket(groupCode int64) (uint16, []byte) { return seq, packet } +/* this function is unused // LightAppSvc.mini_app_info.GetAppInfoById func (c *QQClient) buildAppInfoRequestPacket(id string) (uint16, []byte) { seq := c.nextSeq() @@ -1099,6 +1098,7 @@ func (c *QQClient) buildAppInfoRequestPacket(id string) (uint16, []byte) { packet := packets.BuildUniPacket(c.Uin, seq, "LightAppSvc.mini_app_info.GetAppInfoById", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } +*/ func (c *QQClient) buildWordSegmentationPacket(data []byte) (uint16, []byte) { seq := c.nextSeq() diff --git a/client/client.go b/client/client.go index 4f5f358b..03e0879b 100644 --- a/client/client.go +++ b/client/client.go @@ -95,11 +95,9 @@ type QQClient struct { fileStorageInfo *jce.FileStoragePushFSSvcList // message state - lastMessageSeq int32 msgSvcCache *utils.Cache lastC2CMsgTime int64 transCache *utils.Cache - lastLostMsg string groupSysMsgCache *GroupSystemMessages groupMsgBuilders sync.Map onlinePushCache *utils.Cache @@ -107,7 +105,6 @@ type QQClient struct { groupSeq int32 friendSeq int32 heartbeatEnabled bool - groupDataTransSeq int32 highwayApplyUpSeq int32 eventHandlers *eventHandlers @@ -150,6 +147,13 @@ type handlerInfo struct { params requestParams } +func (h *handlerInfo) getParams() requestParams { + if h == nil { + return nil + } + return h.params +} + var decoders = map[string]func(*QQClient, *incomingPacketInfo, []byte) (interface{}, error){ "wtlogin.login": decodeLoginResponse, "wtlogin.exchange_emp": decodeExchangeEmpResponse, @@ -174,7 +178,6 @@ var decoders = map[string]func(*QQClient, *incomingPacketInfo, []byte) (interfac "OidbSvc.0xd79": decodeWordSegmentation, "OidbSvc.0x990": decodeTranslateResponse, "SummaryCard.ReqSummaryCard": decodeSummaryCardResponse, - "LightAppSvc.mini_app_info.GetAppInfoById": decodeAppInfoResponse, } func init() { @@ -866,10 +869,6 @@ func (c *QQClient) nextQWebSeq() int64 { return atomic.AddInt64(&c.qwebSeq, 1) } -func (c *QQClient) nextGroupDataTransSeq() int32 { - return atomic.AddInt32(&c.groupDataTransSeq, 2) -} - func (c *QQClient) nextHighwayApplySeq() int32 { return atomic.AddInt32(&c.highwayApplyUpSeq, 2) } diff --git a/client/decoders.go b/client/decoders.go index 768a69a7..731fff34 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -20,7 +20,6 @@ import ( "github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/oidb" "github.com/Mrs4s/MiraiGo/client/pb/profilecard" - "github.com/Mrs4s/MiraiGo/client/pb/qweb" "github.com/Mrs4s/MiraiGo/client/pb/structmsg" "github.com/Mrs4s/MiraiGo/internal/proto" "github.com/Mrs4s/MiraiGo/utils" @@ -794,6 +793,7 @@ func decodeWordSegmentation(_ *QQClient, _ *incomingPacketInfo, payload []byte) return nil, errors.New("no word received") } +/* unused // LightAppSvc.mini_app_info.GetAppInfoById func decodeAppInfoResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) (interface{}, error) { pkg := qweb.QWebRsp{} @@ -809,6 +809,7 @@ func decodeAppInfoResponse(_ *QQClient, _ *incomingPacketInfo, payload []byte) ( } return rsp.AppInfo, nil } +*/ func ignoreDecoder(_ *QQClient, _ *incomingPacketInfo, _ []byte) (interface{}, error) { return nil, nil diff --git a/client/guild_msg.go b/client/guild_msg.go index 45023b13..baea4a3b 100644 --- a/client/guild_msg.go +++ b/client/guild_msg.go @@ -22,20 +22,18 @@ import ( "github.com/Mrs4s/MiraiGo/utils" ) -type ( - guildImageUploadResponse struct { - UploadKey []byte - UploadIp []uint32 - UploadPort []uint32 - Width int32 - Height int32 - Message string - DownloadIndex string - FileId int64 - ResultCode int32 - IsExists bool - } -) +type guildImageUploadResponse struct { + UploadKey []byte + UploadIp []uint32 + UploadPort []uint32 + Width int32 + Height int32 + Message string + DownloadIndex string + FileId int64 + ResultCode int32 + IsExists bool +} func init() { decoders["ImgStore.QQMeetPicUp"] = decodeGuildImageStoreResponse @@ -201,20 +199,18 @@ func (s *GuildService) pullChannelMessages(guildId, channelId, beginSeq, endSeq, param.Version = []uint64{eventVersion} } + withVersionFlag := uint32(0) + if eventVersion != 0 { + withVersionFlag = 1 + } + directFlag := uint32(0) + if direct { + directFlag = 1 + } payload, _ := proto.Marshal(&channel.ChannelMsgReq{ - ChannelParam: param, - WithVersionFlag: proto.Uint32(func() uint32 { - if eventVersion != 0 { - return 1 - } - return 0 - }()), - DirectMessageFlag: proto.Uint32(func() uint32 { - if direct { - return 1 - } - return 0 - }()), + ChannelParam: param, + WithVersionFlag: &withVersionFlag, + DirectMessageFlag: &directFlag, }) seq := s.c.nextSeq() packet := packets.BuildUniPacket(s.c.Uin, seq, "trpc.group_pro.synclogic.SyncLogic.GetChannelMsg", 1, s.c.OutGoingPacketSessionId, []byte{}, s.c.sigInfo.d2Key, payload) diff --git a/client/http_api.go b/client/http_api.go index 03ecda5e..118daf0d 100644 --- a/client/http_api.go +++ b/client/http_api.go @@ -124,10 +124,9 @@ func (c *QQClient) GetGroupHonorInfo(groupCode int64, honorType HonorType) (*Gro /* -------- TextToSpeech -------- */ func (c *QQClient) GetTts(text string) ([]byte, error) { - url := "https://textts.qq.com/cgi-bin/tts" - bt, _ := json.Marshal(text) - data := fmt.Sprintf(`{"appid": "201908021016","sendUin": %v,"text": %s}`, c.Uin, bt) - rsp, err := utils.HttpPostBytesWithCookie(url, []byte(data), c.getCookies()) + apiUrl := "https://textts.qq.com/cgi-bin/tts" + data := fmt.Sprintf(`{"appid": "201908021016","sendUin": %v,"text": %q}`, c.Uin, text) + rsp, err := utils.HttpPostBytesWithCookie(apiUrl, []byte(data), c.getCookies()) if err != nil { return nil, errors.Wrap(err, "failed to post to tts server") } diff --git a/client/image.go b/client/image.go index 0db3036b..54edfacb 100644 --- a/client/image.go +++ b/client/image.go @@ -32,27 +32,25 @@ func init() { var imgWaiter = utils.NewUploadWaiter() -type ( - imageUploadResponse struct { - UploadKey []byte - UploadIp []uint32 - UploadPort []uint32 - ResourceId string - Message string - FileId int64 - Width int32 - Height int32 - ResultCode int32 - IsExists bool - } -) +type imageUploadResponse struct { + UploadKey []byte + UploadIp []uint32 + UploadPort []uint32 + ResourceId string + Message string + FileId int64 + Width int32 + Height int32 + ResultCode int32 + IsExists bool +} func (c *QQClient) UploadGroupImage(groupCode int64, img io.ReadSeeker) (*message.GroupImageElement, error) { _, _ = img.Seek(0, io.SeekStart) // safe fh, length := utils.ComputeMd5AndLength(img) _, _ = img.Seek(0, io.SeekStart) - key := hex.EncodeToString(fh) + key := string(fh) imgWaiter.Wait(key) defer imgWaiter.Done(key) diff --git a/client/multimsg.go b/client/multimsg.go index c2d3f478..b5e7696c 100644 --- a/client/multimsg.go +++ b/client/multimsg.go @@ -95,12 +95,13 @@ func decodeMultiApplyDownResponse(_ *QQClient, _ *incomingPacketInfo, payload [] return nil, errors.New("not found") } rsp := body.MultimsgApplydownRsp[0] - prefix := func() string { - if rsp.MsgExternInfo != nil && rsp.MsgExternInfo.ChannelType == 2 { - return "https://ssl.htdata.qq.com" - } - return fmt.Sprintf("http://%s:%d", binary.UInt32ToIPV4Address(uint32(rsp.Uint32DownIp[0])), body.MultimsgApplydownRsp[0].Uint32DownPort[0]) - }() + + var prefix string + if rsp.MsgExternInfo != nil && rsp.MsgExternInfo.ChannelType == 2 { + prefix = "https://ssl.htdata.qq.com" + } else { + prefix = fmt.Sprintf("http://%s:%d", binary.UInt32ToIPV4Address(uint32(rsp.Uint32DownIp[0])), body.MultimsgApplydownRsp[0].Uint32DownPort[0]) + } b, err := utils.HttpGetBytes(fmt.Sprintf("%s%s", prefix, string(rsp.ThumbDownPara)), "") if err != nil { return nil, errors.Wrap(err, "failed to download by multi apply down") diff --git a/client/network.go b/client/network.go index 77cae726..9018696e 100644 --- a/client/network.go +++ b/client/network.go @@ -75,7 +75,7 @@ func (c *QQClient) ConnectionQualityTest() *ConnectionQualityInfo { }() start := time.Now() if _, err := utils.HttpGetBytes("https://ssl.htdata.qq.com", ""); err == nil { - r.LongMessageServerResponseLatency = time.Now().Sub(start).Milliseconds() + r.LongMessageServerResponseLatency = time.Since(start).Milliseconds() } else { c.Error("test long message server response latency error: %v", err) r.LongMessageServerResponseLatency = 9999 @@ -335,12 +335,7 @@ func (c *QQClient) netLoop() { decoded, err = decoder(c, &incomingPacketInfo{ SequenceId: pkt.SequenceId, CommandName: pkt.CommandName, - Params: func() requestParams { - if !ok { - return nil - } - return info.params - }(), + Params: info.getParams(), }, pkt.Payload) if err != nil { c.Debug("decode pkt %v error: %+v", pkt.CommandName, err) diff --git a/client/private_msg.go b/client/private_msg.go index 87c5ca56..4aa9b30a 100644 --- a/client/private_msg.go +++ b/client/private_msg.go @@ -131,6 +131,7 @@ func (s *TempSessionInfo) SendMessage(m *message.SendingMessage) (*message.TempM } } +/* this function is unused func (c *QQClient) buildGetOneDayRoamMsgRequest(target, lastMsgTime, random int64, count uint32) (uint16, []byte) { seq := c.nextSeq() req := &msg.PbGetOneDayRoamMsgReq{ @@ -143,6 +144,7 @@ func (c *QQClient) buildGetOneDayRoamMsgRequest(target, lastMsgTime, random int6 packet := packets.BuildUniPacket(c.Uin, seq, "MessageSvc.PbGetOneDayRoamMsg", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) return seq, packet } +*/ // MessageSvc.PbSendMsg func (c *QQClient) buildFriendSendingPacket(target int64, msgSeq, r, pkgNum, pkgIndex, pkgDiv int32, time int64, m []message.IMessageElement) (uint16, []byte) { diff --git a/client/ptt.go b/client/ptt.go index 76ac4fd4..39e007e1 100644 --- a/client/ptt.go +++ b/client/ptt.go @@ -35,7 +35,7 @@ func (c *QQClient) UploadGroupPtt(groupCode int64, voice io.ReadSeeker) (*messag pttWaiter.Wait(key) defer pttWaiter.Done(key) - ext := c.buildGroupPttStoreBDHExt(groupCode, fh[:], int32(length), 0, int32(length)) + ext := c.buildGroupPttStoreBDHExt(groupCode, fh, int32(length), 0, int32(length)) rsp, err := c.highwaySession.UploadBDH(highway.BdhInput{ CommandID: 29, Body: voice, @@ -60,8 +60,8 @@ func (c *QQClient) UploadGroupPtt(groupCode int64, voice io.ReadSeeker) (*messag Ptt: &msg.Ptt{ FileType: proto.Int32(4), SrcUin: &c.Uin, - FileMd5: fh[:], - FileName: proto.String(hex.EncodeToString(fh[:]) + ".amr"), + FileMd5: fh, + FileName: proto.String(hex.EncodeToString(fh) + ".amr"), FileSize: proto.Int32(int32(length)), GroupFileKey: pkt.TryupPttRsp[0].FileKey, BoolValid: proto.Bool(true), @@ -81,7 +81,7 @@ func (c *QQClient) UploadPrivatePtt(target int64, voice io.ReadSeeker) (*message pttWaiter.Wait(key) defer pttWaiter.Done(key) - ext := c.buildC2CPttStoreBDHExt(target, fh[:], int32(length), int32(length)) + ext := c.buildC2CPttStoreBDHExt(target, fh, int32(length), int32(length)) rsp, err := c.highwaySession.UploadBDH(highway.BdhInput{ CommandID: 26, Body: voice, @@ -107,8 +107,8 @@ func (c *QQClient) UploadPrivatePtt(target int64, voice io.ReadSeeker) (*message FileType: proto.Int32(4), SrcUin: &c.Uin, FileUuid: pkt.ApplyUploadRsp.Uuid, - FileMd5: fh[:], - FileName: proto.String(hex.EncodeToString(fh[:]) + ".amr"), + FileMd5: fh, + FileName: proto.String(hex.EncodeToString(fh) + ".amr"), FileSize: proto.Int32(int32(length)), // Reserve: constructPTTExtraInfo(1, int32(len(voice))), // todo length BoolValid: proto.Bool(true), diff --git a/client/richmsg.go b/client/richmsg.go index 801b6de0..b5125eb2 100644 --- a/client/richmsg.go +++ b/client/richmsg.go @@ -101,15 +101,14 @@ func (c *QQClient) SendGuildMusicShare(guildID, channelID uint64, msg *message.M func (c *QQClient) buildRichMsgSendingPacket(guild uint64, target int64, msg *message.MusicShareElement, sendType uint32) (uint16, []byte) { seq := c.nextSeq() tp := musicType[msg.MusicType] // MusicType + msgStyle := uint32(0) + if msg.MusicUrl != "" { + msgStyle = 4 + } body := &oidb.DB77ReqBody{ - AppId: tp.appID, - AppType: tp.appType, - MsgStyle: func() uint32 { - if msg.MusicUrl == "" { - return 0 - } - return 4 - }(), + AppId: tp.appID, + AppType: tp.appType, + MsgStyle: msgStyle, ClientInfo: &oidb.DB77ClientInfo{ Platform: tp.platform, SdkVersion: tp.sdkVersion, diff --git a/client/system_msg.go b/client/system_msg.go index bfb35c87..33e9e3ed 100644 --- a/client/system_msg.go +++ b/client/system_msg.go @@ -138,31 +138,26 @@ func (c *QQClient) buildSystemMsgNewGroupPacket(suspicious bool) (uint16, []byte // ProfileService.Pb.ReqSystemMsgAction.Group func (c *QQClient) buildSystemMsgGroupActionPacket(reqID, requester, group int64, msgType int32, isInvite, accept, block bool, reason string) (uint16, []byte) { seq := c.nextSeq() + subSrcId := int32(31) + groupMsgType := int32(1) + if isInvite { + subSrcId = 10016 + groupMsgType = 2 + } + infoType := int32(12) + if accept { + infoType = 11 + } req := &structmsg.ReqSystemMsgAction{ - MsgType: msgType, - MsgSeq: reqID, - ReqUin: requester, - SubType: 1, - SrcId: 3, - SubSrcId: func() int32 { - if isInvite { - return 10016 - } - return 31 - }(), - GroupMsgType: func() int32 { - if isInvite { - return 2 - } - return 1 - }(), + MsgType: msgType, + MsgSeq: reqID, + ReqUin: requester, + SubType: 1, + SrcId: 3, + SubSrcId: subSrcId, + GroupMsgType: groupMsgType, ActionInfo: &structmsg.SystemMsgActionInfo{ - Type: func() int32 { - if accept { - return 11 - } - return 12 - }(), + Type: infoType, GroupCode: group, Blacklist: block, Msg: reason, @@ -178,6 +173,10 @@ func (c *QQClient) buildSystemMsgGroupActionPacket(reqID, requester, group int64 // ProfileService.Pb.ReqSystemMsgAction.Friend func (c *QQClient) buildSystemMsgFriendActionPacket(reqID, requester int64, accept bool) (uint16, []byte) { seq := c.nextSeq() + infoType := int32(3) + if accept { + infoType = 2 + } req := &structmsg.ReqSystemMsgAction{ MsgType: 1, MsgSeq: reqID, @@ -186,12 +185,7 @@ func (c *QQClient) buildSystemMsgFriendActionPacket(reqID, requester int64, acce SrcId: 6, SubSrcId: 7, ActionInfo: &structmsg.SystemMsgActionInfo{ - Type: func() int32 { - if accept { - return 2 - } - return 3 - }(), + Type: infoType, Blacklist: false, AddFrdSNInfo: &structmsg.AddFrdSNInfo{}, }, diff --git a/message/elements.go b/message/elements.go index 5f4a59cd..eaa29969 100644 --- a/message/elements.go +++ b/message/elements.go @@ -200,12 +200,12 @@ func NewUrlShare(url, title, content, image string) *ServiceElement { } } -func NewRichXml(template string, ResId int64) *ServiceElement { - if ResId == 0 { - ResId = 60 // 默认值60 +func NewRichXml(template string, resID int64) *ServiceElement { + if resID == 0 { + resID = 60 // 默认值60 } return &ServiceElement{ - Id: int32(ResId), + Id: int32(resID), Content: template, SubType: "xml", } diff --git a/message/image.go b/message/image.go index 80018ceb..41b11100 100644 --- a/message/image.go +++ b/message/image.go @@ -138,8 +138,7 @@ func (e *GroupImageElement) Pack() (r []*msg.Elem) { return []*msg.Elem{elem} } -func (e *FriendImageElement) Pack() (r []*msg.Elem) { - r = []*msg.Elem{} +func (e *FriendImageElement) Pack() []*msg.Elem { image := &msg.NotOnlineImage{ FilePath: &e.ImageId, ResId: &e.ImageId, diff --git a/message/message.go b/message/message.go index 4531aa8c..78c289bf 100644 --- a/message/message.go +++ b/message/message.go @@ -423,11 +423,9 @@ func ParseMessageElems(elems []*msg.Elem) []IMessageElement { if isOk := strings.Contains(content, "