Files

897 lines
28 KiB
Go
Raw Permalink Normal View History

2026-02-17 13:06:23 +08:00
package clientsdk
import (
"encoding/hex"
"errors"
"fmt"
"hash/crc32"
"net/url"
"strconv"
"strings"
"time"
"xiawan/wx/clientsdk/android"
"xiawan/wx/clientsdk/android/mmproto"
"xiawan/wx/clientsdk/baseinfo"
"xiawan/wx/clientsdk/baseutils"
"xiawan/wx/clientsdk/extinfo"
"xiawan/wx/protobuf/wechat"
"github.com/golang/protobuf/proto"
"github.com/micro/go-micro/util/log"
)
// GetClientCheckData 获取ClientCheckData
// func GetClientCheckData(userInfo *baseinfo.UserInfo) []byte {
// retData, err := ccdata.CreateClientCheckData(userInfo.DeviceInfo.ClientCheckDataXML)
// if err != nil {
// log.Info(err)
// return retData
// }
// // DeviceRunningInfo
// deviceRuntimInfo := &wechat.DeviceRunningInfo{}
// mode := uint32(1)
// deviceRuntimInfo.Mode = &mode
// deviceRuntimInfo.Type = []byte("00000003")
// deviceRuntimInfo.Data = retData
// // 序列化
// finalData, err := proto.Marshal(deviceRuntimInfo)
// if err != nil {
// log.Info(err)
// }
// return finalData
// }
// GetExtSpamInfoData 获取ExtSpamInfo
// func GetExtSpamInfoData(userInfo *baseinfo.UserInfo) []byte {
// ccdata := GetClientCheckData(userInfo)
// // WCExtInfoLod
// extInfo := &wechat.WCExtInfo{}
// // ccDataBuffer
// var ccDataBuffer wechat.SKBuiltinString_
// tmpLen := uint32(len(ccdata))
// ccDataBuffer.Len = &tmpLen
// ccDataBuffer.Buffer = ccdata
// extInfo.CcData = &ccDataBuffer
// // 序列化
// retData, err := proto.Marshal(extInfo)
// if err != nil {
// log.Info(err)
// }
// return retData
// }
func GetExtPBSpamInfoDataA16(userInfo *baseinfo.UserInfo, wxId ...string) []byte {
wxId_ := ""
if len(wxId) == 0 {
wxId_ = userInfo.GetUserName()
} else {
wxId_ = wxId[0]
}
ccd1 := GetCCD1(wxId_)
ccd1PB, _ := proto.Marshal(ccd1)
ccd2 := GetCCD2()
ccd2PB, _ := proto.Marshal(ccd2)
ccd3 := GetCCD3(*userInfo.DeviceInfoA16)
ccd3PB, _ := proto.Marshal(ccd3)
devicetoken := GetDeviceToken(userInfo.DeviceInfoA16.DeviceIdStr)
dtPB, _ := proto.Marshal(devicetoken)
spamdatabody := &mmproto.SpamDataBody{
Ccd1: &mmproto.SpamDataSubBody{
Ilen: proto.Uint32(uint32(len(ccd1PB))),
Ztdata: ccd1,
},
Ccd2: &mmproto.SpamDataSubBody{
Ilen: proto.Uint32(uint32(len(ccd2PB))),
Ztdata: ccd2,
},
Ccd3: &mmproto.SpamDataSubBody{
Ilen: proto.Uint32(uint32(len(ccd3PB))),
Ztdata: ccd3,
},
Dt: &mmproto.DeviceTokenBody{
Ilen: proto.Uint32(uint32(len(dtPB))),
DeviceToken: devicetoken,
},
}
retData, err := proto.Marshal(spamdatabody)
if err != nil {
log.Info(err)
}
return retData
}
func GetCCD1(UserName string) *mmproto.ZTData {
return android.AndroidWcstf(UserName)
}
func GetCCD2() *mmproto.ZTData {
// return android.AndroidWcste(384214787666497617, 384002236977512448)
return android.AndroidWcste(0, 0)
}
// 算法
func GetCCD3(accoutInfo baseinfo.AndroidDeviceInfo) *mmproto.ZTData {
curtime := uint32(time.Now().Unix())
ccd3body := &mmproto.Ccd3Body{
KernelReleaseNumber: proto.String(accoutInfo.KernelReleaseNumber),
UsbState: proto.Uint32(0),
Sign: proto.String(accoutInfo.PackageSign),
PackageFlag: proto.Uint32(14),
AccessFlag: proto.Uint32(364604),
Unkonwn: proto.Uint32(3),
TbVersionCrc: proto.Uint32(553983350),
SfMD5: proto.String("d001b450158a85142c953011c66d531d"),
SfArmMD5: proto.String("bf7f84d081f1dffd587803c233d4e235"),
SfArm64MD5: proto.String("85801b3939f277ad31c9f89edd9dd008"),
SbMD5: proto.String("683e7beb7a44017ca2e686e3acedfb9f"),
SoterId2: proto.String(""),
TimeCheck: proto.Uint32(0),
NanoTime: proto.Uint32(455583),
}
pb, _ := proto.Marshal(ccd3body)
crc := crc32.ChecksumIEEE(pb)
ccd3 := &mmproto.Ccd3{
Crc: &crc,
TimeStamp: &curtime,
Body: nil,
}
pb, _ = proto.Marshal(ccd3)
// var b bytes.Buffer
// w := zlib.NewWriter(&b)
// w.Write(pb)
// w.Close()
// zt := new(android.ZT)
// zt.Init()
// encData := zt.Encrypt(b.Bytes())
compressData := android.DoZlibCompress(pb)
encData := android.SaeEncrypt07(compressData)
Ztdata := &mmproto.ZTData{
Version: proto.String("00000007\x00"),
Encrypted: proto.Uint32(1),
Data: encData,
TimeStamp: &curtime,
Optype: proto.Uint32(5),
Uin: proto.Uint32(0),
}
// MS, _ := proto.Marshal(Ztdata)
// return MS
return Ztdata
}
func GetDeviceToken(devicetoken string) *mmproto.DeviceToken {
curtime := uint32(time.Now().Unix())
return &mmproto.DeviceToken{
Version: proto.String(""),
Encrypted: proto.Uint32(1),
Data: &mmproto.SKBuiltinStringt{
String_: &devicetoken,
},
TimeStamp: &curtime,
Optype: proto.Uint32(2),
Uin: proto.Uint32(0),
}
}
func GetExtPBSpamInfoDataIpad(userInfo *baseinfo.UserInfo, wxId ...string) []byte {
wxId_ := ""
if len(wxId) == 0 {
wxId_ = userInfo.GetUserName()
} else {
wxId_ = wxId[0]
}
retData, err := extinfo.GetCCDPbLib(
userInfo.DeviceInfo.OsTypeNumber,
userInfo.DeviceInfo.OsType,
userInfo.DeviceInfo.UUIDTwo,
userInfo.DeviceInfo.UUIDTwo,
userInfo.DeviceInfo.DeviceName,
userInfo.DeviceInfo.DeviceToken,
hex.EncodeToString(userInfo.DeviceInfo.DeviceID),
wxId_,
userInfo.DeviceInfo.GUID2,
)
if err != nil {
log.Info(err)
}
return retData
}
func GetExtPBSpamInfoDataLogin(userInfo *baseinfo.UserInfo, wxId ...string) []byte {
wxId_ := ""
if len(wxId) == 0 {
wxId_ = userInfo.GetUserName()
} else {
wxId_ = wxId[0]
}
retData, err := extinfo.GetCCDPbLibLogin(
userInfo.DeviceInfo.OsTypeNumber,
userInfo.DeviceInfo.OsType,
userInfo.DeviceInfo.UUIDTwo,
userInfo.DeviceInfo.UUIDTwo,
userInfo.DeviceInfo.DeviceName,
userInfo.DeviceInfo.DeviceToken,
hex.EncodeToString(userInfo.DeviceInfo.DeviceID),
wxId_,
userInfo.DeviceInfo.GUID2,
)
if err != nil {
log.Info(err)
}
return retData
}
func GetExtPBSpamInfoDataIPhone(userInfo *baseinfo.UserInfo, wxId ...string) []byte {
wxId_ := ""
if len(wxId) == 0 {
wxId_ = userInfo.GetUserName()
} else {
wxId_ = wxId[0]
}
retData, err := extinfo.GetCCDPbLibIPhone(
userInfo.DeviceInfo.OsTypeNumber,
userInfo.DeviceInfo.OsType,
userInfo.DeviceInfo.UUIDTwo,
userInfo.DeviceInfo.UUIDTwo,
userInfo.DeviceInfo.DeviceName,
userInfo.DeviceInfo.DeviceToken,
hex.EncodeToString(userInfo.DeviceInfo.DeviceID),
wxId_,
userInfo.DeviceInfo.GUID2,
)
if err != nil {
log.Info(err)
}
return retData
}
// GetAutoAuthRsaReqDataMarshal 生成自动登陆rsareq项
func GetAutoAuthRsaReqDataMarshal(userInfo *baseinfo.UserInfo) []byte {
var rsaReqData wechat.AutoAuthRsaReqData
// AesEncyptKey
var aesEncryptKey wechat.SKBuiltinString_
aesEncryptKey.Buffer = []byte(userInfo.SessionKey)
var aesKeyLen = uint32(len(userInfo.SessionKey))
aesEncryptKey.Len = &aesKeyLen
rsaReqData.AesEncryptKey = &aesEncryptKey
// ecdh
var ecdhKey wechat.ECDHKey
var tmpNid = uint32(713)
ecdhKey.Nid = &tmpNid
// ecdhKey
var ecdhKeyBuffer wechat.SKBuiltinString_
var ecdhKeyLen = uint32(len(userInfo.EcPublicKey))
ecdhKeyBuffer.Len = &ecdhKeyLen
ecdhKeyBuffer.Buffer = userInfo.EcPublicKey
ecdhKey.Key = &ecdhKeyBuffer
rsaReqData.PubEcdhKey = &ecdhKey
retData, err := proto.Marshal(&rsaReqData)
if err != nil {
log.Info("proto.Marshal AutoAuthRsaReqData failed: ", err)
}
return retData
}
// GetAutoAuthAesReqDataMarshal 生成自动登陆aesreq项
func GetAutoAuthAesReqDataMarshal(userInfo *baseinfo.UserInfo) []byte {
var zeroUint32 = uint32(0)
var emptyString = string("")
var aesReqData wechat.AutoAuthAesReqData
baseReq := GetBaseRequest(userInfo)
var tmpScene uint32 = 2
baseReq.Scene = &tmpScene
baseReq.SessionKey = []byte{}
aesReqData.BaseRequest = baseReq
// autoauthkey
tmpAuthKeyLen := uint32(len(userInfo.AutoAuthKey))
var tmpAutoAuthKey wechat.SKBuiltinString_
tmpAutoAuthKey.Buffer = userInfo.AutoAuthKey
tmpAutoAuthKey.Len = &tmpAuthKeyLen
aesReqData.AutoAuthKey = &tmpAutoAuthKey
// BaseAuthReqInfo
var baseReqInfo wechat.BaseAuthReqInfo
baseReqInfo.AuthReqFlag = &zeroUint32
baseReqInfo.AuthTicket = &emptyString
aesReqData.BaseReqInfo = &baseReqInfo
if userInfo.DeviceInfo == nil {
//return GetManualAuthAesReqDataA16Protobuf(userInfo)
aesReqData.Imei = proto.String(userInfo.DeviceInfoA16.AndriodImei(userInfo.DeviceInfoA16.DeviceIdStr))
aesReqData.SoftType = proto.String(userInfo.DeviceInfoA16.AndriodGetSoftType(userInfo.DeviceInfoA16.DeviceIdStr))
aesReqData.ClientSeqId = proto.String(fmt.Sprintf("%s_%d", userInfo.DeviceInfoA16.DeviceIdStr, (time.Now().UnixNano() / 1e6)))
aesReqData.DeviceName = proto.String(userInfo.DeviceInfoA16.AndroidManufacturer(userInfo.DeviceInfoA16.DeviceIdStr) + "-" + userInfo.DeviceInfoA16.AndroidPhoneModel(userInfo.DeviceInfoA16.DeviceIdStr))
aesReqData.Language = proto.String("Zh")
aesReqData.TimeZone = proto.String("8.0")
aesReqData.Channel = &zeroUint32
// TimeStamp
aesReqData.Signature = proto.String(userInfo.DeviceInfoA16.AndriodPackageSign(userInfo.DeviceInfoA16.DeviceIdStr))
aesReqData.BuiltinIpSeq = &zeroUint32
ext, err := GetExtSpamInfoAndroid(userInfo)
if err != nil {
log.Error("Android extSpam err", err.Error())
}
// extSpamInfo
var extSpamInfo wechat.SKBuiltinString_
extSpamInfo.Buffer = ext
extSpamInfoLen := uint32(len(extSpamInfo.Buffer))
extSpamInfo.Len = &extSpamInfoLen
aesReqData.ExtSpamInfo = &extSpamInfo
reqData, _ := proto.Marshal(&aesReqData)
return reqData
} else {
// imei
aesReqData.Imei = &userInfo.DeviceInfo.Imei
aesReqData.TimeZone = &userInfo.DeviceInfo.TimeZone
aesReqData.DeviceName = &userInfo.DeviceInfo.DeviceName
aesReqData.Language = &userInfo.DeviceInfo.Language
aesReqData.BuiltinIpSeq = &zeroUint32
aesReqData.Signature = &emptyString
aesReqData.SoftType = &userInfo.DeviceInfo.SoftTypeXML
tmpTime := int(time.Now().UnixNano() / 1000000000)
tmpTimeStr := strconv.Itoa(tmpTime)
var strClientSeqID = string(userInfo.DeviceInfo.Imei + "-" + tmpTimeStr)
aesReqData.ClientSeqId = &strClientSeqID
aesReqData.Channel = &zeroUint32
// extSpamInfo
var extSpamInfo wechat.SKBuiltinString_
extSpamInfo.Buffer = GetExtPBSpamInfoDataLogin(userInfo)
extSpamInfoLen := uint32(len(extSpamInfo.Buffer))
extSpamInfo.Len = &extSpamInfoLen
aesReqData.ExtSpamInfo = &extSpamInfo
retData, err := proto.Marshal(&aesReqData)
if err != nil {
log.Info("proto.Marshal AutoAuthAesReqData failed: ", err)
}
return retData
}
}
// GetManualAuthAesReqDataMarshal 生成自动登陆aesreq项
func GetManualAuthAesReqDataMarshal(userInfo *baseinfo.UserInfo) []byte {
zeroUint32 := uint32(0)
zeroInt32 := int32(0)
emptyString := string("")
var aesRequest wechat.ManualAuthAesReqData
// BaseRequest
baseReq := GetBaseRequest(userInfo)
var tmpScene uint32 = 1
baseReq.Scene = &tmpScene
baseReq.SessionKey = []byte{}
aesRequest.BaseRequest = baseReq
// imei
aesRequest.Imei = &userInfo.DeviceInfo.Imei
aesRequest.TimeZone = &userInfo.DeviceInfo.TimeZone
aesRequest.DeviceName = &userInfo.DeviceInfo.DeviceName
aesRequest.DeviceType = &userInfo.DeviceInfo.DeviceName
aesRequest.Channel = &zeroInt32
aesRequest.Language = &userInfo.DeviceInfo.Language
aesRequest.BuiltinIpseq = &zeroUint32
aesRequest.Signature = &emptyString
aesRequest.SoftType = &userInfo.DeviceInfo.SoftTypeXML
aesRequest.DeviceBrand = &userInfo.DeviceInfo.DeviceBrand
aesRequest.RealCountry = &userInfo.DeviceInfo.RealCountry
aesRequest.BundleId = &userInfo.DeviceInfo.BundleID
aesRequest.AdSource = &userInfo.DeviceInfo.AdSource
inputType := uint32(2)
aesRequest.InputType = &inputType
// ClientSeqId
tmpTime := int(time.Now().UnixNano() / 1000000000)
tmpTimeStr := strconv.Itoa(tmpTime)
var strClientSeqID = string(userInfo.DeviceInfo.Imei + "-" + tmpTimeStr)
aesRequest.ClientSeqId = &strClientSeqID
// TimeStamp
tmpTime2 := uint32(time.Now().UnixNano() / 1000000000)
aesRequest.TimeStamp = &tmpTime2
// extSpamInfo
var extSpamInfo wechat.SKBuiltinString_
extSpamInfo.Buffer = GetExtPBSpamInfoDataLogin(userInfo)
extSpamInfoLen := uint32(len(extSpamInfo.Buffer))
extSpamInfo.Len = &extSpamInfoLen
aesRequest.ExtSpamInfo = &extSpamInfo
retData, err := proto.Marshal(&aesRequest)
if err != nil {
log.Info("proto.Marshal AutoAuthAesReqData failed: ", err)
}
return retData
}
// ParseHongBaoURL 解析红包URL
func ParseHongBaoURL(hongBaoURL string, senderUserName string) (*baseinfo.HongBaoURLItem, error) {
// 捕获错误返回 nil
if len(hongBaoURL) == 0 {
return nil, errors.New("ParseHongBaoURL hongbao url is empty")
}
retURL, err := url.Parse(hongBaoURL)
if err != nil {
return nil, err
}
retMaps, err := url.ParseQuery(retURL.RawQuery)
if err != nil {
return nil, err
}
//retMaps 下面可能不存在 数据,所以需要判断
if len(retMaps["msgtype"]) == 0 || len(retMaps["channelid"]) == 0 || len(retMaps["sendid"]) == 0 || len(retMaps["ver"]) == 0 || len(retMaps["sign"]) == 0 {
return nil, errors.New("ParseHongBaoURL hongbao url is invalid")
}
retItem := &baseinfo.HongBaoURLItem{}
retItem.MsgType = retMaps["msgtype"][0]
retItem.ChannelID = retMaps["channelid"][0]
retItem.SendID = retMaps["sendid"][0]
retItem.Ver = retMaps["ver"][0]
retItem.Sign = retMaps["sign"][0]
retItem.SendUserName = senderUserName
return retItem, nil
}
// CreateMediaItemXML 将mediaItem转换成XML
func CreateMediaItemXML(mediaItem *baseinfo.SnsMediaItem) string {
retString := string("<media>")
if mediaItem.EncKey != "" {
retString = retString + "<enc key=\"" + mediaItem.EncKey + "\">" + strconv.Itoa(int(mediaItem.EncValue)) + "</enc>"
}
retString = retString + "<id>" + strconv.Itoa(int(mediaItem.ID)) + "</id>"
retString = retString + "<type>" + strconv.Itoa(int(mediaItem.Type)) + "</type>"
// title
titleString := "<title/>"
if len(mediaItem.Title) > 0 {
titleString = "<title>" + mediaItem.Title + "</title>"
}
retString = retString + titleString
// description
descriptionString := "<description/>"
if len(mediaItem.Description) > 0 {
descriptionString = "<description>" + mediaItem.Description + "</description>"
}
retString = retString + descriptionString
// private
retString = retString + "<private>" + strconv.Itoa(int(mediaItem.Private)) + "</private>"
// userData
userDataString := "<userData/>"
if len(mediaItem.UserData) > 0 {
userDataString = "<userData>" + mediaItem.UserData + "</userData>"
}
retString = retString + userDataString
// subType
retString = retString + "<subType>" + strconv.Itoa(int(mediaItem.SubType)) + "</subType>"
// videoSize
retString = retString + "<videoSize width=\"" + mediaItem.VideoWidth + "\" height=\"" + mediaItem.VideoHeight + "\"/>"
// url
retString = retString + "<url type=\"" + mediaItem.URLType + "\" md5=\"" + mediaItem.MD5 + "\" videomd5=\"" + mediaItem.VideoMD5 + "\">"
retString = retString + mediaItem.URL + "</url>"
// thumb
retString = retString + "<thumb type=\"" + mediaItem.ThumType + "\">"
retString = retString + mediaItem.Thumb + "</thumb>"
// size
retString = retString + "<size width=\"" + mediaItem.SizeWidth + "\" height=\"" + mediaItem.SizeHeight + "\" totalSize=\"" + mediaItem.TotalSize + "\"/>"
// videoDuration 如果是视频
if mediaItem.Type == baseinfo.MMSNSMediaTypeVideo {
// 格式化
tmpValue := strconv.FormatFloat(mediaItem.VideoDuration, 'f', 6, 64)
retString = retString + "<videoDuration>" + tmpValue + "</videoDuration>"
}
retString = retString + "</media>"
return retString
}
// CreateSnsPostItemXML 转成xml字符串字节数组
func CreateSnsPostItemXML(userName string, postItem *baseinfo.SnsPostItem) []byte {
// createTime
tmpTime := int(time.Now().UnixNano() / 1000000000)
tmpTimeStr := strconv.Itoa(tmpTime)
// start
retString := string("<TimelineObject>")
retString = retString + "<id><![CDATA[0]]></id>"
retString = retString + "<username><![CDATA[" + userName + "]]></username>"
retString = retString + "<createTime><![CDATA[" + tmpTimeStr + "]]></createTime>"
retString = retString + "<contentDesc><![CDATA[" + postItem.Content + "]]></contentDesc>"
retString = retString + "<contentDescShowType><![CDATA[0]]></contentDescShowType>"
retString = retString + "<contentDescScene><![CDATA[" + strconv.Itoa(0) + "]]></contentDescScene>"
retString = retString + "<private>" + strconv.Itoa(int(postItem.Privacy)) + "</private>"
retString = retString + "<sightFolded>" + strconv.Itoa(0) + "</sightFolded>"
retString = retString + "<showFlag>" + strconv.Itoa(0) + "</showFlag>"
// location
// appInfo
retString = retString + "<appInfo>"
retString = retString + "<id/>"
retString = retString + "<version/>"
retString = retString + "<appName/>"
retString = retString + "<installUrl/>"
retString = retString + "<fromUrl/>"
retString = retString + "<isForceUpdate>" + strconv.Itoa(0) + "</isForceUpdate>"
retString = retString + "</appInfo>"
retString = retString + "<sourceUserName/>"
retString = retString + "<sourceNickName/>"
retString = retString + "<statisticsData/>"
retString = retString + "<statExtStr/>"
// ContentObject
/*retString = retString + "<ContentObject>"
retString = retString + "<contentStyle>" + strconv.Itoa(int(postItem.ContentStyle)) + "</contentStyle>"
retString = retString + "<title>&#x0A;&#x0A;&#x0A;习近平<title/>"
retString = retString + "<description/>"*/
// location
if postItem.LocationInfo != nil {
// float, int 转成string
longitudeStr := postItem.LocationInfo.Longitude
latitudeStr := postItem.LocationInfo.Latitude
poiScaleStr := strconv.Itoa(int(postItem.LocationInfo.PoiScale))
poiClassfyTypeStr := strconv.Itoa(int(postItem.LocationInfo.PoiClassifyType))
poiClickableStatusStr := strconv.Itoa(int(postItem.LocationInfo.PoiClickableStatus))
// 增加 LocationXml
retString = retString + "<location "
retString = retString + "city = \"" + postItem.LocationInfo.City + "\" "
retString = retString + "longitude = \"" + longitudeStr + "\" "
retString = retString + "latitude = \"" + latitudeStr + "\" "
retString = retString + "poiName = \"" + postItem.LocationInfo.PoiName + "\" "
retString = retString + "poiAddress = \"" + postItem.LocationInfo.PoiAddress + "\" "
retString = retString + "poiScale = \"" + poiScaleStr + "\" "
retString = retString + "poiInfoUrl = \"" + postItem.LocationInfo.PoiInfoURL + "\" "
retString = retString + "poiClassifyId = \"" + postItem.LocationInfo.PoiClassifyID + "\" "
retString = retString + "poiClassifyType = \"" + poiClassfyTypeStr + "\" "
retString = retString + "poiClickableStatus = \"" + poiClickableStatusStr + "\" "
retString = retString + "></location>"
}
retString = retString + "<ContentObject>"
if postItem.ContentUrl != "" {
retString = retString + "<contentUrl><![CDATA[" + postItem.ContentUrl + "]]></contentUrl>"
}
retString = retString + "<contentStyle><![CDATA[" + strconv.Itoa(int(postItem.ContentStyle)) + "]]></contentStyle>"
if len(postItem.MediaList) > 0 && postItem.ContentUrl != "" {
retString = retString + "<title><![CDATA[" + postItem.MediaList[0].Title + "]]>&#x0A;&#x0A;&#x0A;习近平--习大大</title>" //习近平
} else {
retString = retString + "<title>&#x0A;&#x0A;&#x0A;习近平;习大大</title>" //习近平
}
if postItem.Description != "" {
retString = retString + "<description>![CDATA[" + postItem.Description + "]]></description>"
} else {
retString = retString + "<description></description>"
}
// mediaList
mediaListString := "<mediaList/>"
mediaCount := len(postItem.MediaList)
if mediaCount > 0 {
mediaListString = "<mediaList>"
for index := 0; index < mediaCount; index++ {
mediaListString = mediaListString + CreateMediaItemXML(postItem.MediaList[index])
}
mediaListString = mediaListString + "</mediaList>"
}
retString = retString + mediaListString
retString = retString + "</ContentObject>"
// end
retString = retString + "</TimelineObject>"
// fmt.Println(retString)
return []byte(retString)
}
// CreateSnsMediaItem 创建媒体项
// privacy公开/不公开
// description描述
func CreateSnsMediaItem(snsImgResponse *baseinfo.CdnSnsImageUploadResponse, privacy uint32, description string) *baseinfo.SnsMediaItem {
mediaItem := &baseinfo.SnsMediaItem{}
mediaItem.ID = 0
mediaItem.Type = baseinfo.MMSNSMediaTypeImage
mediaItem.Title = ""
mediaItem.Description = description
mediaItem.Private = privacy
mediaItem.UserData = ""
mediaItem.SubType = 0
mediaItem.URL = snsImgResponse.FileURL
mediaItem.URLType = "1"
mediaItem.Thumb = snsImgResponse.ThumbURL
mediaItem.ThumType = "1"
mediaItem.MD5 = snsImgResponse.ImageMD5
mediaItem.VideoMD5 = ""
mediaItem.VideoWidth = strconv.Itoa(int(snsImgResponse.ImageWidth))
mediaItem.VideoHeight = strconv.Itoa(int(snsImgResponse.ImageHeight))
tmpWidth := float64(snsImgResponse.ImageWidth)
tmpHeight := float64(snsImgResponse.ImageHeight)
mediaItem.SizeWidth = strconv.FormatFloat(tmpWidth, 'f', 6, 64)
mediaItem.SizeHeight = strconv.FormatFloat(tmpHeight, 'f', 6, 64)
mediaItem.TotalSize = "0"
return mediaItem
}
// CreateSnsCommentLikeItem 创建评论项:朋友圈点赞
func CreateSnsCommentLikeItem(itemID uint64, toUserName string) *baseinfo.SnsCommentItem {
retItem := &baseinfo.SnsCommentItem{}
retItem.OpType = baseinfo.MMSnsCommentTypeLike
retItem.ItemID = itemID
retItem.ToUserName = toUserName
retItem.CreateTime = uint32(time.Now().UnixNano() / 1000000000)
retItem.Content = ""
retItem.ReplyCommentID = 0
retItem.ReplyItem = nil
return retItem
}
// CreateSnsCommentItem 创建评论项:朋友圈评论
func CreateSnsCommentItem(itemID uint64, toUserName string, content string, replyComment *wechat.SnsCommentInfo) *baseinfo.SnsCommentItem {
retItem := &baseinfo.SnsCommentItem{}
retItem.OpType = baseinfo.MMSnsCommentTypeComment
retItem.ItemID = itemID
retItem.ToUserName = toUserName
retItem.CreateTime = uint32(time.Now().UnixNano() / 1000000000)
retItem.Content = content
retItem.ReplyCommentID = 0
retItem.ReplyItem = nil
// 回复
if replyComment != nil {
retItem.ReplyItem = &baseinfo.ReplyCommentItem{}
retItem.ReplyItem.UserName = replyComment.GetUsername()
retItem.ReplyItem.NickName = replyComment.GetNickname()
retItem.ReplyCommentID = replyComment.GetCommentId()
retItem.ReplyItem.OpType = replyComment.GetType()
retItem.ReplyItem.Source = replyComment.GetSource()
}
return retItem
}
// CreateSnsLocationInfo 创建朋友圈项: 发送朋友圈地址
func CreateSnsLocationInfo(lbsLife *wechat.LbsLife, cityName string, longitude string, latitude string) *baseinfo.SnsLocationInfo {
retLocationInfo := &baseinfo.SnsLocationInfo{}
retLocationInfo.City = cityName
retLocationInfo.Longitude = longitude
retLocationInfo.Latitude = latitude
retLocationInfo.PoiName = lbsLife.GetTitle()
retLocationInfo.PoiAddress = ""
retLocationInfo.PoiScale = 11.0
retLocationInfo.PoiInfoURL = lbsLife.GetPoiUrl()
retLocationInfo.PoiClassifyID = lbsLife.GetBid()
retLocationInfo.PoiClassifyType = 1
if lbsLife.GetType() == 1 {
retLocationInfo.PoiClassifyType = 2
}
retLocationInfo.PoiClickableStatus = 0
return retLocationInfo
}
// CreateGetLbsLifeListItem 创建GetLbsLifeListItem项
func CreateGetLbsLifeListItem(longitude float64, latitude float64, buff []byte, keyWord string) *baseinfo.GetLbsLifeListItem {
// 获取Lbs地址列表
lbsLifeListItem := &baseinfo.GetLbsLifeListItem{}
lbsLifeListItem.Opcode = baseinfo.MMLbsLifeOpcodeNormal
lbsLifeListItem.Buffer = buff
lbsLifeListItem.Longitude = float32(longitude)
lbsLifeListItem.Latitude = float32(latitude)
lbsLifeListItem.KeyWord = keyWord
return lbsLifeListItem
}
// CreateCDNUploadMsgImgPrepareRequest 创建 CreateCDNUploadMsgImgPrepareRequest请求
// prepareRequestItem: 请求项
func CreateCDNUploadMsgImgPrepareRequest(userInfo *baseinfo.UserInfo, prepareRequestItem *baseinfo.CDNUploadMsgImgPrepareRequestItem) []byte {
var request wechat.CDNUploadMsgImgPrepareRequest
var emptyString = string("")
var zeroValue32 = int32(0)
// FromUserName
request.FromUserName = &userInfo.WxId
// ToUserName
request.ToUserName = &prepareRequestItem.ToUser
// ClientImgId
clientImgID := prepareRequestItem.ToUser + prepareRequestItem.LocalName + "_" + strconv.Itoa(int(prepareRequestItem.CreateTime))
request.ClientImgId = &clientImgID
// ThumbWidth
request.ThumbWidth = &prepareRequestItem.ThumbWidth
// ThumbHeight
request.ThumbHeight = &prepareRequestItem.ThumbHeight
// encryVer
request.EncryVer = &zeroValue32
// Scene
request.Scene = &zeroValue32
// Crc32
request.Crc32 = &prepareRequestItem.Crc32
// Aeskey
aesKey := baseutils.BytesToHexString(prepareRequestItem.AesKey, false)
request.Aeskey = &aesKey
// MsgForwardType
msgForwardType := uint32(1)
request.MsgForwardType = &msgForwardType
// AttachedContent
request.AttachedContent = &emptyString
// Longitude
longitude := float32(0.0)
request.Longitude = &longitude
// Latitude
request.Latitude = &longitude
// Source
source := uint32(2)
request.Source = &source
// Appid
request.Appid = &emptyString
// MessageAction
request.MessageAction = &emptyString
// MessageExt
request.MeesageExt = &emptyString
// MediaTagName
request.MediaTagName = &emptyString
// 打包
srcData, _ := proto.Marshal(&request)
retData := Pack(userInfo, srcData, 625, 5)
return retData
}
// CreateSendEmojiMsgXMl 生成表情xml
func CreateSendEmojiMsgXMl(md5 string, totallen int32) string {
retString := strings.Builder{}
retString.WriteString("<appmsg appid=\"\" sdkver=\"0\">")
retString.WriteString("<title></title>")
retString.WriteString("<des></des>")
retString.WriteString("<action></action>")
retString.WriteString("<type>8</type>") // 发送表情 type8
retString.WriteString("<showtype>0</showtype>")
retString.WriteString("<soundtype>0</soundtype>")
retString.WriteString("<mediatagname></mediatagname>")
retString.WriteString("<messageext></messageext>")
retString.WriteString("<messageaction></messageaction>")
retString.WriteString("<content></content>")
retString.WriteString("<contentattr>0</contentattr>")
retString.WriteString("<url></url>")
retString.WriteString("<lowurl></lowurl>")
retString.WriteString("<dataurl></dataurl>")
retString.WriteString("<lowdataurl></lowdataurl>")
retString.WriteString("<songalbumurl></songalbumurl>")
retString.WriteString("<songlyric></songlyric>")
retString.WriteString("<appattach>")
retString.WriteString(fmt.Sprintf("<totallen>%d</totallen>", totallen))
retString.WriteString(fmt.Sprintf("<attachid>0:0:%s</attachid>", md5))
retString.WriteString(fmt.Sprintf("<emoticonmd5>%s</emoticonmd5>", md5))
retString.WriteString("<fileext>pic</fileext>")
retString.WriteString("<cdnthumbaeskey></cdnthumbaeskey>" +
"<aeskey></aeskey>" +
"</appattach>" +
"<extinfo></extinfo>" +
"<sourceusername></sourceusername>" +
"<sourcedisplayname></sourcedisplayname>" +
"<thumburl></thumburl>" +
"<md5></md5>" +
"<statextstr></statextstr>" +
"<directshare>0</directshare>" +
"</appmsg>" +
"<fromusername></fromusername>")
return retString.String()
}
// CreateCDNUploadMsgImgPrepareRequestWithSource 创建 CDN 上传图片准备请求
func CreateCDNUploadMsgImgPrepareRequestWithSource(userInfo *baseinfo.UserInfo, prepareRequestItem *baseinfo.CDNUploadMsgImgPrepareRequestItem, sourceValue uint32) []byte {
var request wechat.CDNUploadMsgImgPrepareRequest
var emptyString = string("")
var zeroValue32 = int32(0)
// FromUserName
request.FromUserName = &userInfo.WxId
toUserName := prepareRequestItem.ToUser
if toUserName == "" || toUserName == "filehelper" {
toUserName = userInfo.WxId
}
request.ToUserName = &toUserName
// ClientImgId
clientImgID := toUserName + prepareRequestItem.LocalName + "_" + strconv.Itoa(int(prepareRequestItem.CreateTime))
request.ClientImgId = &clientImgID
// ThumbWidth
request.ThumbWidth = &prepareRequestItem.ThumbWidth
// ThumbHeight
request.ThumbHeight = &prepareRequestItem.ThumbHeight
// encryVer
request.EncryVer = &zeroValue32
// Scene
request.Scene = &zeroValue32
// Crc32
request.Crc32 = &prepareRequestItem.Crc32
// Aeskey
aesKey := baseutils.BytesToHexString(prepareRequestItem.AesKey, false)
request.Aeskey = &aesKey
// MsgForwardType
msgForwardType := uint32(1)
request.MsgForwardType = &msgForwardType
// AttachedContent
request.AttachedContent = &emptyString
// Longitude
longitude := float32(0.0)
request.Longitude = &longitude
// Latitude
request.Latitude = &longitude
// Source - 使用传入的值
request.Source = &sourceValue
// Appid
request.Appid = &emptyString
// MessageAction
request.MessageAction = &emptyString
// MessageExt
request.MeesageExt = &emptyString
// MediaTagName
request.MediaTagName = &emptyString
// 打包
srcData, _ := proto.Marshal(&request)
retData := Pack(userInfo, srcData, 625, 5)
return retData
}