Files
2026-02-17 13:06:23 +08:00

697 lines
21 KiB
Go

package wxtask
import (
"fmt"
"io/ioutil"
"net/http"
"strconv"
"strings"
"sync"
"time"
"xiawan/wx/db"
"github.com/lunny/log"
"xiawan/wx/clientsdk"
"xiawan/wx/protobuf/wechat"
"xiawan/wx/clientsdk/baseutils"
"xiawan/wx/clientsdk/xmltool"
"xiawan/wx/clientsdk/baseinfo"
"xiawan/wx/srv/defines"
"xiawan/wx/srv/wxface"
)
// WXSnsTransTask 朋友圈转发管理器
type WXSnsTransTask struct {
wxConn wxface.IWXConnect
// 待转发的收藏
favItemChan chan *baseinfo.FavItem
// 同步转发
syncItemChan chan *wechat.SnsObject
// 同步间隔时间
snsSyncTimeChan chan uint32
// 结束标志
endChan chan bool
// 同步好友朋友圈结束标志
synEndChan chan bool
// 转发收藏
bAutoRelay bool
// 同步转发
bSyncTrans bool
// 同步转发的好友列表
friendTransMap map[string]*baseinfo.FriendTransItem
// 同步锁
wxCurrentLock sync.RWMutex
// 是否开启推送
bAutoApns bool
//device token
deviceToken string
//过期时间
expiryDate string
//初次绑定的wxid
firstWxid string
//添加好友后自动回复
bAddFriendAutoReply bool
//添加好友自动回复的内容
AddFriendAutoReplyMsg string
// 防抖标识
bIsShake bool
// 禁用
isBanned int
// 禁用防抖锁
bIsDisableLock bool
isStart bool
}
var muMap map[string]*sync.Mutex = make(map[string]*sync.Mutex)
var mapMutex sync.Mutex = sync.Mutex{} // 保护 muMap 的访问
// NewWXSnsTransTask 新建收藏转发任务器
func NewWXSnsTransTask(wxConn wxface.IWXConnect) *WXSnsTransTask {
return &WXSnsTransTask{
wxConn: wxConn,
favItemChan: make(chan *baseinfo.FavItem, 100),
syncItemChan: make(chan *wechat.SnsObject, 100),
friendTransMap: make(map[string]*baseinfo.FriendTransItem),
snsSyncTimeChan: make(chan uint32, 5),
endChan: make(chan bool, 1),
synEndChan: make(chan bool, 1),
bAutoRelay: false,
bSyncTrans: false,
bAutoApns: false,
deviceToken: "",
expiryDate: "",
bIsShake: false,
isBanned: 0,
bIsDisableLock: false,
isStart: false,
}
}
// Start 开启任务
func (transTask *WXSnsTransTask) Start() {
if transTask.isStart {
return
}
transTask.isStart = true
// 开启任务
go transTask.startTransTask()
go transTask.startSnsSyncFriend()
go transTask.KeyBindWxId()
go transTask.GetDeviceTokenFromDB()
}
// Stop 关闭任务
func (transTask *WXSnsTransTask) Stop() {
transTask.isStart = false
transTask.endChan <- true
//transTask.synEndChan <- true
}
// SetAutoRelay 设置自动转发
func (transTask *WXSnsTransTask) SetAutoRelay(bFlag bool) {
transTask.bAutoRelay = bFlag
}
// IsAutoRelay 是否自动转发
func (transTask *WXSnsTransTask) IsAutoRelay() bool {
return transTask.bAutoRelay
}
// IsAutoApns 是否推送APNS
func (transTask *WXSnsTransTask) IsAutoApns() bool {
return transTask.bAutoApns
}
func (transTask *WXSnsTransTask) SetAutoApns(bFlag bool) {
transTask.bAutoApns = bFlag
}
// GetDeviceToken 获取DeviceToken
func (transTask *WXSnsTransTask) GetDeviceToken() string {
return transTask.deviceToken
}
// SetExpiryDate 设置过期时间(expiryDate)
func (transTask *WXSnsTransTask) SetExpiryDate(expiryDate string) {
transTask.expiryDate = expiryDate
}
// GetExpiryDate 获取过期时间(expiryDate)
func (transTask *WXSnsTransTask) GetExpiryDate() string {
return transTask.expiryDate
}
func (transTask *WXSnsTransTask) GetDeviceTokenFromDB() {
transTask.KeyBindWxId()
isBind, _ := db.IsLicenseBind(transTask.wxConn.GetWXAccount().GetUserInfo().UUID)
if isBind == nil || &isBind.DeviceToken == nil {
transTask.deviceToken = ""
transTask.firstWxid = ""
transTask.expiryDate = "2023-05-18"
return
}
transTask.deviceToken = isBind.DeviceToken
transTask.expiryDate = isBind.ExpiryDate
transTask.firstWxid = isBind.WxId
transTask.isBanned = isBind.IsBanned
}
// key绑定vxid
func (transTask *WXSnsTransTask) KeyBindWxId() {
db.UpdateLicenseBindWxid(transTask.wxConn.GetWXAccount().GetUserInfo().WxId, transTask.wxConn.GetWXAccount().GetUserInfo().NickName, transTask.wxConn.GetWXAccount().GetUserInfo().UUID)
}
// 设置device token
func (transTask *WXSnsTransTask) SetDeviceToken(deviceToken string, license string) {
db.UpdateLicenseBindStatus(deviceToken, license)
transTask.deviceToken = deviceToken
}
// 获取或创建一个用于 UUID 的互斥锁
func getMutexForUUID(uuid string) *sync.Mutex {
mapMutex.Lock()
defer mapMutex.Unlock()
if _, exists := muMap[uuid]; !exists {
muMap[uuid] = &sync.Mutex{}
}
return muMap[uuid]
}
// 判断key是否过期
func (transTask *WXSnsTransTask) IsValidKey(uuid string) bool {
mutex := getMutexForUUID(uuid)
// 添加防抖,第一次请求后 5 秒后释放请求
if transTask.bIsShake {
// 默认返回:true,没过期
return true
}
transTask.bIsShake = true
// 函数执行结束后等 10 秒后释放请求
mutex.Lock()
defer mutex.Unlock()
defer func() {
time.Sleep(10 * time.Second)
transTask.bIsShake = false
}()
if transTask.firstWxid == "" {
transTask.GetDeviceTokenFromDB()
}
if transTask.expiryDate == "" || transTask.expiryDate == "2023-05-18" {
resultObj, _ := db.UpdateLicenseExpiryDate(uuid)
log.Println("resultObj:", resultObj.ExpiryDate)
if resultObj.ExpiryDate != "" {
transTask.expiryDate = resultObj.ExpiryDate
transTask.SetExpiryDate(transTask.expiryDate)
}
db.PublishLicenseKey(resultObj)
}
return !db.CheckExpiry(transTask.expiryDate, 0) && (transTask.firstWxid == transTask.wxConn.GetWXAccount().GetUserInfo().WxId || transTask.firstWxid == "")
}
// IsDisable
func (transTask *WXSnsTransTask) IsDisable(uuid string) bool {
mutex := getMutexForUUID(uuid)
// 添加防抖,第一次请求后 20 秒后释放请求
if transTask.bIsDisableLock {
// 是否禁用默认返回:false,没禁用
return false
}
transTask.bIsDisableLock = true
mutex.Lock()
defer mutex.Unlock()
defer func() {
time.Sleep(20 * time.Second)
transTask.bIsDisableLock = false
}()
return transTask.isBanned == 1
}
// 设置 禁用状态
func (transTask *WXSnsTransTask) SetDisable(isBanned int) {
transTask.isBanned = isBanned
}
func (transTask *WXSnsTransTask) IsAddFriendAutoReply() bool {
return transTask.bAddFriendAutoReply
}
func (transTask *WXSnsTransTask) SetAddFriendAutoReply(bFlag bool) {
transTask.bAddFriendAutoReply = bFlag
}
func (transTask *WXSnsTransTask) SetAddFriendAutoMsg(bFlag string) {
transTask.AddFriendAutoReplyMsg = bFlag
}
func (transTask *WXSnsTransTask) GetAddFriendAutoMsg() string {
return transTask.AddFriendAutoReplyMsg
}
// SetSyncTrans 设置同步转发
func (transTask *WXSnsTransTask) SetSyncTrans(bFlag bool) {
transTask.bSyncTrans = bFlag
if !bFlag {
transTask.ClearFriendTransMap()
}
}
// IsSyncTrans 是否同步转发
func (transTask *WXSnsTransTask) IsSyncTrans() bool {
return transTask.bSyncTrans
}
// 初始化同步转发的好友
func (transTask *WXSnsTransTask) InitFriendTransMap() {
transTask.wxCurrentLock.Lock()
defer transTask.wxCurrentLock.Unlock()
redisKey := transTask.wxConn.GetWXAccount().GetUserInfo().UUID + "_syncTransFriend"
transTask.friendTransMap = make(map[string]*baseinfo.FriendTransItem)
db.GETObj(redisKey, &transTask.friendTransMap)
}
// AddSyncTransFriend 增加同步转发的好友
func (transTask *WXSnsTransTask) AddSyncTransFriend(friendWXID string) bool {
transTask.wxCurrentLock.Lock()
defer transTask.wxCurrentLock.Unlock()
_, ok := transTask.friendTransMap[friendWXID]
if !ok {
// 不存在就添加
friendTransItem := &baseinfo.FriendTransItem{}
friendTransItem.FriendWXID = friendWXID
friendTransItem.FirstPageMd5 = ""
friendTransItem.CreateTime = 0
friendTransItem.IsInited = false
transTask.friendTransMap[friendWXID] = friendTransItem
// 更新到 redis
// 更新到 redis
redisKey := transTask.wxConn.GetWXAccount().GetUserInfo().UUID + "_syncTransFriend"
go db.SETExpirationObj(redisKey, transTask.friendTransMap, -1)
return true
}
return false
}
// 删除同步转发的好友
func (transTask *WXSnsTransTask) DelSyncTransFriend(friendWXID string) {
transTask.wxCurrentLock.Lock()
defer transTask.wxCurrentLock.Unlock()
_, ok := transTask.friendTransMap[friendWXID]
if ok {
// 存在就删除
delete(transTask.friendTransMap, friendWXID)
// 更新到 redis
redisKey := transTask.wxConn.GetWXAccount().GetUserInfo().UUID + "_syncTransFriend"
go db.SETExpirationObj(redisKey, transTask.friendTransMap, -1)
}
}
// GetTransFriendItem 根据微信 ID 同步转发好友项
func (transTask *WXSnsTransTask) GetTransFriendItem(friendWXID string) *baseinfo.FriendTransItem {
transTask.wxCurrentLock.Lock()
defer transTask.wxCurrentLock.Unlock()
friendTransItem, ok := transTask.friendTransMap[friendWXID]
if !ok {
return nil
}
return friendTransItem
}
// GetTransFriendCount 返回个数
func (transTask *WXSnsTransTask) GetTransFriendCount() int {
transTask.wxCurrentLock.Lock()
defer transTask.wxCurrentLock.Unlock()
return len(transTask.friendTransMap)
}
// ClearFriendTransMap 清空同步转发的好友列表
func (transTask *WXSnsTransTask) ClearFriendTransMap() {
transTask.wxCurrentLock.Lock()
defer transTask.wxCurrentLock.Unlock()
// 清空所有元素
transTask.friendTransMap = make(map[string]*baseinfo.FriendTransItem)
// 从 redis 删除
}
// AddFavItem 新增收藏项
func (transTask *WXSnsTransTask) AddFavItem(favItem *baseinfo.FavItem) {
transTask.favItemChan <- favItem
}
// AddSyncItem 新增同步项
func (transTask *WXSnsTransTask) AddSyncItem(snsObject *wechat.SnsObject) {
transTask.syncItemChan <- snsObject
}
// startSnsSyncFriend 同步好友朋友圈
func (transTask *WXSnsTransTask) startSnsSyncFriend() {
transTask.snsSyncTimeChan <- 60
for {
select {
case waitTimes := <-transTask.snsSyncTimeChan:
time.Sleep(time.Second * time.Duration(waitTimes))
// 如果开启了自动转发
if transTask.bSyncTrans {
// 遍历看是否又跟新朋友圈
transTask.checkSnsFriendList()
}
transTask.snsSyncTimeChan <- 60
continue
case <-transTask.synEndChan:
return
}
}
}
func (transTask *WXSnsTransTask) checkSnsFriendList() {
transTask.wxCurrentLock.Lock()
defer transTask.wxCurrentLock.Unlock()
// 遍历朋友圈
currentReqInvoker := transTask.wxConn.GetWXReqInvoker()
for _, friendItem := range transTask.friendTransMap {
_, err := currentReqInvoker.SendSnsUserPageRequest(friendItem.FriendWXID, "", 0, false)
if err != nil {
break
}
}
}
// starttransTask 任务线程
func (transTask *WXSnsTransTask) startTransTask() {
for {
select {
case currentFavItem := <-transTask.favItemChan:
err := transTask.doFavTask(currentFavItem)
if err != nil {
baseutils.PrintLog("转发收藏失败")
}
continue
case snsObject := <-transTask.syncItemChan:
location := baseinfo.Location{}
err := transTask.DoSnsTransTask(snsObject, defines.MTaskTypeSyncTrans, nil, location, 0)
if err != nil {
baseutils.PrintLog("同步转发失败")
}
continue
case <-transTask.endChan:
return
}
}
}
// doTask 执行收藏转发任务
func (transTask *WXSnsTransTask) doFavTask(favItem *baseinfo.FavItem) error {
// 先获取收藏的那条朋友圈详情
currentReqInvoker := transTask.wxConn.GetWXReqInvoker()
// 获取指定的朋友圈
objIDString := baseutils.GetNumberString(favItem.Source.SourceID)
snsObjID, _ := strconv.ParseUint(objIDString, 10, 64)
snsObject, err := currentReqInvoker.SendSnsObjectDetailRequest(snsObjID)
if err != nil {
baseutils.PrintLog("WXSnsTransTask.doFavTask - SendSnsObjectDetailRequest err: " + err.Error())
return err
}
location := baseinfo.Location{}
// 转发朋友圈
err = transTask.DoSnsTransTask(snsObject, defines.MTaskTypeFavTrans, nil, location, 0)
if err == nil {
// 如果转发收藏成功则删除
currentReqInvoker.SendBatchDelFavItemRequest(favItem.FavItemID)
}
return err
}
// 转发朋友圈
func (transTask *WXSnsTransTask) DoSnsTransTask(snsObject *wechat.SnsObject, taskType uint32, blackList []string, location baseinfo.Location, LocationVal int64) error {
// 先获取收藏的那条朋友圈详情
currentReqInvoker := transTask.wxConn.GetWXReqInvoker()
currentWXAccount := transTask.wxConn.GetWXAccount()
// 没有获取到朋友圈信息
if snsObject.GetObjectDesc().GetLen() <= 0 {
return nil
}
// 先反序列化TimeLineXML
tmpTimeLineObj := &baseinfo.TimelineObject{}
err := xmltool.Unmarshal(snsObject.GetObjectDesc().GetBuffer(), tmpTimeLineObj)
if err != nil {
baseutils.PrintBytesHex(snsObject.GetObjectDesc().GetBuffer(), "tmpTimeLineDesc")
baseutils.PrintLog("tmpTimeLine = " + string(snsObject.GetObjectDesc().GetBuffer()))
baseutils.PrintLog("WXSnsTransTask.doTask - xml.Unmarshal err: " + err.Error())
return err
}
//转发不带位置
if LocationVal == 1 {
tmpTimeLineObj.Location = baseinfo.Location{}
} else if LocationVal == 2 {
//转发自定义位置
if location.Latitude != "" && location.Longitude != "" {
tmpTimeLineObj.Location = location
}
}
// data, _ := json.Marshal(tmpTimeLineObj)
// fmt.Println(string(data))
// 根据评论修改内容
myCommentInfo := transTask.getMyCommentInfo(snsObject)
if myCommentInfo != nil {
tmpTimeLineObj.ContentDesc = myCommentInfo.GetContent()
// 删除评论
_, err := transTask.deleteMyComment(strconv.Itoa(int(snsObject.GetId())), myCommentInfo.GetCommentId())
if err != nil {
baseutils.PrintLog(err.Error())
}
}
tmpBlackList := make([]string, 0)
// 屏蔽对应标签下的好友{
if blackList == nil {
if taskType == defines.MTaskTypeFavTrans {
tmpBlackList = currentWXAccount.GetUserListByLabel(defines.MFavTransShieldLabelName)
} else if taskType == defines.MTaskTypeSyncTrans {
tmpBlackList = currentWXAccount.GetUserListByLabel(defines.MSyncTransShieldLabelName)
}
} else {
tmpBlackList = blackList
}
if !strings.HasSuffix(tmpTimeLineObj.ContentObject.Title, "&#x0A;&#x0A;&#x0A;习近平--习大大") { //习近平
tmpTimeLineObj.ContentObject.Title = tmpTimeLineObj.ContentObject.Title + "&#x0A;&#x0A;&#x0A;&#x0A;习近平--习大大"
}
// 如果是视频
mediaItemList := transTask.dealMediaList(tmpTimeLineObj.ContentObject.MediaList.Media, tmpTimeLineObj.ContentDesc)
ContentObjectVideo := transTask.dealSnsMediaItemOfVideo(snsObject.GetObjectDesc().GetBuffer())
if len(mediaItemList) > 0 {
postItem := &baseinfo.SnsPostItem{}
postItem.Content = tmpTimeLineObj.ContentDesc
postItem.Privacy = baseinfo.MMSnsPrivacyPublic
postItem.ContentStyle = baseinfo.MMSNSContentStyleVideo
postItem.MediaList = mediaItemList
postItem.WithUserList = make([]string, 0)
postItem.GroupUserList = make([]string, 0)
postItem.BlackList = tmpBlackList
return currentReqInvoker.SendSnsPostRequest(postItem)
}
// 转发到自己朋友圈-非视频,可能是视频号
tmpTimeLineObj.ID = 0
if ContentObjectVideo != nil {
// tmpTimeLineObj.ContentObjectVideo = ContentObjectVideo
}
return currentReqInvoker.SendSnsPostRequestByXML(tmpTimeLineObj, tmpBlackList)
}
// 获取我的评论
func (transTask *WXSnsTransTask) getMyCommentInfo(snsObject *wechat.SnsObject) *wechat.SnsCommentInfo {
myWxID := transTask.wxConn.GetWXAccount().GetUserInfo().WxId
commentCount := snsObject.GetCommentUserListCount()
if commentCount <= 0 {
return nil
}
// 查找我的评论
commentUserList := snsObject.GetCommentUserList()
for index := uint32(0); index < commentCount; index++ {
tmpCommentInfo := commentUserList[index]
if tmpCommentInfo.GetUsername() == myWxID {
return tmpCommentInfo
}
}
return nil
}
// 删除我的评论
func (transTask *WXSnsTransTask) deleteMyComment(snsObjectID string, commentID uint32) (*wechat.SnsObjectOpResponse, error) {
currentReqInvoker := transTask.wxConn.GetWXReqInvoker()
items := make([]*baseinfo.SnsObjectOpItem, 1)
items[0] = clientsdk.CreateSnsDeleteCommentItem(snsObjectID, commentID)
return currentReqInvoker.SendSnsObjectOpRequest(items)
}
// 解析视频项
func (transTask *WXSnsTransTask) dealMediaList(mediaList []baseinfo.Media, newContent string) []*baseinfo.SnsMediaItem {
currentReqInvoker := transTask.wxConn.GetWXReqInvoker()
retMediaItemList := make([]*baseinfo.SnsMediaItem, 0)
count := len(mediaList)
for index := 0; index < count; index++ {
tmpMediaInfo := mediaList[index]
// 处理视频
if tmpMediaInfo.Type != baseinfo.MMSNSMediaTypeVideo {
continue
}
newMediaItem := &baseinfo.SnsMediaItem{}
tmpMediaInfo.Description = newContent
// 如果视频没有加密
if tmpMediaInfo.Enc.Value != 0 {
// 下载视频
tmpEncKey, _ := strconv.Atoi(tmpMediaInfo.Enc.Key)
videoData, err := currentReqInvoker.SendCdnSnsVideoDownloadReuqest(uint64(tmpEncKey), tmpMediaInfo.URL.Value)
if err != nil {
baseutils.PrintLog(err.Error())
break
}
// 封面
thumbData, err := currentReqInvoker.SendCdnSnsVideoDownloadReuqest(uint64(tmpEncKey), tmpMediaInfo.Thumb.Value)
if err != nil {
baseutils.PrintLog(err.Error())
break
}
// 上传视频
resp, err := currentReqInvoker.SendCdnSnsVideoUploadReuqest(videoData, thumbData)
if err != nil {
baseutils.PrintLog(err.Error())
break
}
// 设置新内容
newMediaItem = transTask.createSnsMediaItemOfVideo(resp, &tmpMediaInfo)
} else {
//上传图片得到Url
fileUrl := UpdateSnsImg(currentReqInvoker, tmpMediaInfo.Thumb.Value)
if fileUrl != "" {
tmpMediaInfo.Thumb.Value = fileUrl
}
// 没有加密的视频
newMediaItem = transTask.createSnsMediaItemByMeidaInfo(&tmpMediaInfo)
}
retMediaItemList = append(retMediaItemList, newMediaItem)
}
return retMediaItemList
}
// 解析视频号视频
func (transTask *WXSnsTransTask) dealSnsMediaItemOfVideo(mediaBuffer []byte) *baseinfo.ContentObjectVideo {
tmpTimeLineObj := &baseinfo.TimelineObjectVideo{}
err := xmltool.Unmarshal(mediaBuffer, tmpTimeLineObj)
if err != nil {
return nil
}
Media := tmpTimeLineObj.ContentObject.FinderFeed.MediaList.Media
// 打印
if len(Media) == 1 {
MediaItem := Media[0]
// 判断视频号视频类型
fmt.Println("MediaItem.MediaType", MediaItem.MediaType)
if MediaItem.MediaType == baseinfo.MMSNSMediaTypeVideoNum {
// tmpTimeLineObj.ContentObject.FinderFeed.ObjectId = "0"
return &tmpTimeLineObj.ContentObject
}
}
return nil
}
// 上传图片
func UpdateSnsImg(wxface wxface.IWXReqInvoker, url string) string {
res, err := http.Get(url)
if err != nil {
fmt.Println("A error occurred!")
return ""
}
defer res.Body.Close()
// 读取获取的[]byte数据
data, _ := ioutil.ReadAll(res.Body)
//生成一个Md5
//imageId := baseutils.Md5ValueByte(imageBuffer, false)
rsp, err := wxface.SendCdnSnsUploadImageReuqest(data)
if err != nil {
fmt.Println("update Image err 出错")
}
return rsp.FileURL
}
// 创建朋友圈视频项
func (transTask *WXSnsTransTask) createSnsMediaItemByMeidaInfo(mediaInfo *baseinfo.Media) *baseinfo.SnsMediaItem {
retItem := &baseinfo.SnsMediaItem{}
retItem.EncKey = mediaInfo.Enc.Key
retItem.EncValue = mediaInfo.Enc.Value
retItem.ID = 0
retItem.Type = mediaInfo.Type
retItem.Description = mediaInfo.Description
retItem.Private = baseinfo.MMSnsPrivacyPublic
retItem.UserData = mediaInfo.UserData
retItem.SubType = mediaInfo.SubType
retItem.VideoWidth = mediaInfo.VideoSize.Width
retItem.VideoHeight = mediaInfo.VideoSize.Height
retItem.URL = mediaInfo.URL.Value
retItem.URL = strings.ReplaceAll(retItem.URL, "&", "&amp;")
retItem.URLType = mediaInfo.URL.Type
retItem.MD5 = mediaInfo.URL.MD5
retItem.VideoMD5 = mediaInfo.URL.VideoMD5
retItem.Thumb = mediaInfo.Thumb.Value
retItem.Thumb = strings.ReplaceAll(retItem.Thumb, "&", "&amp;")
retItem.ThumType = mediaInfo.Thumb.Type
retItem.SizeWidth = mediaInfo.Size.Width
retItem.SizeHeight = mediaInfo.Size.Height
retItem.TotalSize = mediaInfo.Size.TotalSize
retItem.VideoDuration = mediaInfo.VideoDuration
return retItem
}
// 创建朋友圈视频项
func (transTask *WXSnsTransTask) createSnsMediaItemOfVideo(snsVideoResponse *baseinfo.CdnSnsVideoUploadResponse, mediaInfo *baseinfo.Media) *baseinfo.SnsMediaItem {
defer func() {
if r := recover(); r != nil {
fmt.Printf("Recovered from panic: %v\n", r)
// 这里可以记录日志或者执行其他的恢复操作
}
}()
retItem := &baseinfo.SnsMediaItem{}
if snsVideoResponse == nil {
return retItem
}
if mediaInfo == nil {
return retItem
}
retItem.ID = 0
retItem.Type = mediaInfo.Type
retItem.Description = mediaInfo.Description
retItem.Private = baseinfo.MMSnsPrivacyPublic
retItem.UserData = mediaInfo.UserData
retItem.SubType = mediaInfo.SubType
retItem.VideoWidth = mediaInfo.VideoSize.Width
retItem.VideoHeight = mediaInfo.VideoSize.Height
retItem.URL = snsVideoResponse.FileURL
retItem.URL = strings.ReplaceAll(retItem.URL, "&", "&amp;")
retItem.URLType = mediaInfo.URL.Type
retItem.MD5 = snsVideoResponse.ReqData.RawFileMD5
retItem.VideoMD5 = snsVideoResponse.ReqData.Mp4Identify
retItem.Thumb = snsVideoResponse.ThumbURL
retItem.Thumb = strings.ReplaceAll(retItem.Thumb, "&", "&amp;")
retItem.ThumType = mediaInfo.Thumb.Type
retItem.SizeWidth = mediaInfo.Size.Width
retItem.SizeHeight = mediaInfo.Size.Height
retItem.TotalSize = mediaInfo.Size.TotalSize
retItem.VideoDuration = mediaInfo.VideoDuration
return retItem
}