package wxtask import ( "fmt" "math/rand" "strconv" "strings" "time" "xiawan/wx/clientsdk/baseinfo" "xiawan/wx/protobuf/wechat" "xiawan/wx/srv/wxface" ) // WXFriendTask 微信好友任务 type WXFriendTask struct { wxConn wxface.IWXConnect friendForList []*wechat.ModContact friendForZombieFansList []*wechat.ModContact labels []*wechat.LabelPair waitTimes uint32 // 毫秒 isZombieFansDet bool // 检测僵死粉任务 isZombieFansDel bool // 删除僵死粉任务 } // NewWXFriendTask 新建一个好友任务 func NewWXFriendTask(wxConn wxface.IWXConnect) *WXFriendTask { return &WXFriendTask{ wxConn: wxConn, friendForList: make([]*wechat.ModContact, 0), friendForZombieFansList: make([]*wechat.ModContact, 0), labels: make([]*wechat.LabelPair, 0), isZombieFansDet: false, isZombieFansDel: false, waitTimes: uint32(1000), // 间隔 1000 毫秒 } } // 获取下一个待验证的好友 func (gpt *WXFriendTask) getNextFriendForContact() *wechat.ModContact { if len(gpt.friendForList) <= 0 { return nil } retContact := gpt.friendForList[0] gpt.friendForList = gpt.friendForList[1:] return retContact } // 获取 1500 - 2500 毫秒的随机数 func (gpt *WXFriendTask) getRandWaitTimes() int { // 设置随机数种子 rand.Seed(time.Now().UnixNano()) // 生成 [1500, 2500] 之间的随机数 min := 1500 max := 2500 randomNumber := rand.Intn(max-min+1) + min return randomNumber } // 获取 2000 - 4000 毫秒的随机数 func (gpt *WXFriendTask) getRandWaitTimes2() int { // 设置随机数种子 rand.Seed(time.Now().UnixNano()) // 生成 [2000, 4000] 之间的随机数 min := 2000 max := 4000 randomNumber := rand.Intn(max-min+1) + min return randomNumber } // 获取 5000 - 12000 毫秒的随机数(5秒 - 12秒) func (gpt *WXFriendTask) getRandWaitTimes3() int { // 设置随机数种子 rand.Seed(time.Now().UnixNano()) // 生成 [5000, 12000] 之间的随机数 min := 5000 max := 12000 randomNumber := rand.Intn(max-min+1) + min return randomNumber } // 10 - 20秒 删除一个 // 获取 10000 - 20000 毫秒的随机数 func (gpt *WXFriendTask) getRandWaitTimes4() int { // 设置随机数种子 rand.Seed(time.Now().UnixNano()) // 生成 [10000, 20000] 之间的随机数 min := 10000 max := 20000 randomNumber := rand.Intn(max-min+1) + min return randomNumber } // 添加至标签 删除我的人 拉黑我的人 func (gpt *WXFriendTask) addTagForContact(labeName string, friendWxids []string) { currentWXReqInvoker := gpt.wxConn.GetWXReqInvoker() // 判断存在则删除,不存在则添加 labels := gpt.getTagForList() // 当前标签 currentLabel := make([]*wechat.LabelPair, 0) for _, label := range labels { if label.GetLabelName() == labeName { // 删除 currentWXReqInvoker.SendDelContactLabelRequest(strconv.FormatUint(uint64(label.GetLabelId()), 10)) break } } if len(currentLabel) <= 0 { // 添加标签 labelNames := make([]string, 0) labelNames = append(labelNames, labeName) resp, err := currentWXReqInvoker.SendAddContactLabelRequest(labelNames, true) if err != nil { return } currentLabel = resp.GetLabelPairList() } // 修改标签 if len(currentLabel) > 0 { UserLabelList := make([]baseinfo.UserLabelInfoItem, 0) for _, friendWxid := range friendWxids { userLabel := baseinfo.UserLabelInfoItem{ UserName: friendWxid, LabelIDList: strconv.FormatUint(uint64(currentLabel[0].GetLabelId()), 10), } UserLabelList = append(UserLabelList, userLabel) } currentWXReqInvoker.SendModifyLabelRequest(UserLabelList) } } // 获取全部标签 func (gpt *WXFriendTask) getTagForList() []*wechat.LabelPair { currentWXReqInvoker := gpt.wxConn.GetWXReqInvoker() // 获取标签 resp, err := currentWXReqInvoker.SendGetContactLabelListRequest(true) if err != nil { return make([]*wechat.LabelPair, 0) } return resp.GetLabelPairList() } // 获取剩余僵死粉数量 // GetLessCount 获取剩余群聊数量 func (gpt *WXFriendTask) GetLessCount() uint32 { return uint32(len(gpt.friendForZombieFansList)) } // StartFriendTask 开启好友检测任务 func (gpt *WXFriendTask) StartFriendTask(taskType int) bool { // currentWXAccount := gpt.wxConn.GetWXAccount() currentWXReqInvoker := gpt.wxConn.GetWXReqInvoker() currentWXFileHelperMgr := gpt.wxConn.GetWXFileHelperMgr() // 如果正在执行执行任务,则返回 if gpt.isZombieFansDet { tipText := "正在检测僵死粉,请稍后" currentWXFileHelperMgr.AddNewTipMsg(tipText) return false } // 如果正在执行删除任务,则返回 if gpt.isZombieFansDel { tipText := "正在清理僵死粉,请稍后" currentWXFileHelperMgr.AddNewTipMsg(tipText) return false } if taskType == 1 { gpt.isZombieFansDet = true tmpTip := "执行检测僵死粉\n开始加载好友列表……" currentWXFileHelperMgr.AddNewTipMsg(tmpTip) } if taskType == 2 { gpt.isZombieFansDel = true tmpTip := "执行清理僵死粉\n开始加载好友……" currentWXFileHelperMgr.AddNewTipMsg(tmpTip) } gpt.friendForList = make([]*wechat.ModContact, 0) gpt.friendForZombieFansList = make([]*wechat.ModContact, 0) friendWxids := gpt.GetFriendWxidList() // friendList := make([]*wechat.ModContact, 0) go func() { if len(friendWxids) <= 0 { tipText := "好友检索完成,总数 0 个,无需操作" currentWXFileHelperMgr.AddNewTipMsg(tipText) gpt.isZombieFansDel = false gpt.isZombieFansDet = false return } // 好友检索完成,好友总数: tipText := "好友加载完成!!\n开始检测好友,请耐心等待……" currentWXFileHelperMgr.AddNewTipMsg(tipText) for i := 0; i < len(friendWxids); i += 1 { // 获取详情 friend := new(wechat.ModContact) friend.UserName = new(wechat.SKBuiltinString) friend.Remark = new(wechat.SKBuiltinString) friend.UserName.Str = new(string) *friend.UserName.Str = friendWxids[i] gpt.friendForList = append(gpt.friendForList, friend) } temFriendCount := 0 for { // 先判断是否还处于链接当中 if !gpt.wxConn.IsConnected() { gpt.isZombieFansDel = false gpt.isZombieFansDet = false return } // 获取下一个好友 tmpModContact := gpt.getNextFriendForContact() temFriendCount++ if tmpModContact == nil { zembieFansCount := len(gpt.friendForZombieFansList) friendForZombieFansList := make([]*wechat.ModContact, 0) friendNamesDel := "" friendWxidsDel := make([]string, 0) // 拉黑我的人 friendFroBlack := "" friendWxidsBlack := make([]string, 0) if zembieFansCount > 0 { // jsonStr0, _ := json.Marshal(gpt.friendForList) // fmt.Println(string(jsonStr0)) for i := 0; i < zembieFansCount; i += 20 { end := i + 20 if end > len(gpt.friendForZombieFansList) { end = len(gpt.friendForZombieFansList) } oldFriends := gpt.friendForZombieFansList[i:end] friendWxids := make([]string, 0) for _, tmpFriend := range oldFriends { friendWxids = append(friendWxids, tmpFriend.GetUserName().GetStr()) } // 获取详情 contactList, err := currentWXReqInvoker.SendGetContactRequestForList(friendWxids, nil) if err != nil { fmt.Println("获取好友详情失败:", err) continue } // 先判断是否还处于链接当中 if !gpt.wxConn.IsConnected() { gpt.isZombieFansDel = false gpt.isZombieFansDet = false return } // friends := contactList.GetContactList() verifyUserList := contactList.GetVerifyUserValidTicketList() friends := contactList.GetContactList() // 转 json 并写入文件 // jsonStr, _ := json.Marshal(friends) // fmt.Println(string(jsonStr)) // jsonStr2, _ := json.Marshal(verifyUserList) // fmt.Println(string(jsonStr2)) count := len(friends) for index := 0; index < count; index++ { friendItem := friends[index] verifyUserItem := verifyUserList[index] CardWxId := friendItem.GetUserName().GetStr() CardNickName := friendItem.GetNickName().GetStr() // CardAlias := friendItem.GetAlias() // 联系人 // 如果是僵死粉 if strings.HasPrefix(verifyUserItem.GetAntispamticket(), "v4_") && friendItem.GetHeadImgMd5() != "" { if friendNamesDel != "" { friendNamesDel += "\n" } friendItem.Remark = new(wechat.SKBuiltinString) friendItem.Remark.Str = new(string) *friendItem.Remark.Str = "删除我的人" friendNamesDel += "删除我的人" friendNamesDel += ("【" + CardNickName + "】") friendWxidsDel = append(friendWxidsDel, CardWxId) // baseutils.PrintLog("僵尸粉:" + tmpContact.GetNickName().GetStr()) } else { // 拉黑 if friendFroBlack != "" { friendFroBlack += "\n" } friendItem.Remark = new(wechat.SKBuiltinString) friendItem.Remark.Str = new(string) *friendItem.Remark.Str = "拉黑我的人" friendFroBlack += "拉黑我的人" friendFroBlack += ("【" + CardNickName + "】") friendWxidsBlack = append(friendWxidsBlack, CardWxId) } friendForZombieFansList = append(friendForZombieFansList, friendItem) } // 暂停 1.5 - 2.5 秒 randWaitTime := gpt.getRandWaitTimes() time.Sleep(time.Duration(randWaitTime) * time.Millisecond) } } // 添加到标签 // 发送名单列表 if friendNamesDel != "" { gpt.addTagForContact("删除我的人", friendWxidsDel) currentWXFileHelperMgr.AddNewTipMsg(friendNamesDel) } if friendFroBlack != "" { gpt.addTagForContact("拉黑我的人", friendWxidsBlack) currentWXFileHelperMgr.AddNewTipMsg(friendFroBlack) } tipText := "检测完成 \n" tipText += "删除我的人 - 【" + strconv.Itoa(len(friendWxidsDel)) + "】个\n" tipText += "拉黑我的人 - 【" + strconv.Itoa(len(friendWxidsBlack)) + "】个\n" tipText += "僵死粉已标记到标签中,以便查看" currentWXFileHelperMgr.AddNewTipMsg(tipText) gpt.isZombieFansDet = false if gpt.isZombieFansDel { tipText := "由于官方限制,删除好友所需时间较长,请耐心等待……,请勿退出 Ipad 登录!!" currentWXFileHelperMgr.AddNewTipMsg(tipText) // 暂停 1 - 2 分钟 randWaitTime := gpt.getRandWaitTimes3() time.Sleep(time.Duration(randWaitTime) * time.Millisecond) // 删除僵死粉 for _, friendWxid := range friendWxidsDel { // 删除 err := currentWXReqInvoker.SendDelContactRequest(friendWxid) if err != nil { gpt.isZombieFansDet = false gpt.isZombieFansDel = false fmt.Printf("删除好友 del friend err %+v", err) return } for _, friendRemak := range friendForZombieFansList { if friendRemak.GetUserName().GetStr() == friendWxid { tipText := "删除-删除我的人【" + friendRemak.GetNickName().GetStr() + "】" currentWXFileHelperMgr.AddNewTipMsg(tipText) } } // 暂停 10s - 20s randWaitTime := gpt.getRandWaitTimes4() time.Sleep(time.Duration(randWaitTime) * time.Millisecond) } for _, friendWxid := range friendWxidsBlack { // 删除 err := currentWXReqInvoker.SendDelContactRequest(friendWxid) if err != nil { gpt.isZombieFansDet = false gpt.isZombieFansDel = false fmt.Printf("删除好友 del friend err %+v", err) return } for _, friendRemak := range friendForZombieFansList { if friendRemak.GetUserName().GetStr() == friendWxid { tipText := "删除-拉黑我的人【" + friendRemak.GetNickName().GetStr() + "】" currentWXFileHelperMgr.AddNewTipMsg(tipText) } } // 暂停 2 - 5 分钟 randWaitTime := gpt.getRandWaitTimes3() time.Sleep(time.Duration(randWaitTime) * time.Millisecond) } gpt.isZombieFansDet = false gpt.isZombieFansDel = false tipText = "清理完成【已清理】:" + strconv.Itoa(len(friendWxidsDel)+len(friendWxidsBlack)) currentWXFileHelperMgr.AddNewTipMsg(tipText) } return } // 判断每次超过 25 个好友,则返回%分比进度 if temFriendCount%25 == 0 { // 取整 temFriendCount / len(friendWxids) * 100 去掉小数点 numCount := int(float64(temFriendCount) / float64(len(friendWxids)) * 100) tipText := "已检测【" + strconv.Itoa(numCount) + "%】好友" currentWXFileHelperMgr.AddNewTipMsg(tipText) } // 获取好友关系请求 friendUserName := tmpModContact.GetUserName().GetStr() // 微信团队跳过 if friendUserName == "Weixin" { continue } // 判断是否是僵死粉 resp, err := currentWXReqInvoker.SendGetFriendRelationRequest(friendUserName) if err != nil { continue } if resp.GetFriendRelation() == 0 { continue } // 1:删除 4:自己拉黑 5:被拉黑 if resp.GetFriendRelation() == 1 { tmpModContact.Remark.Str = new(string) *tmpModContact.Remark.Str = "删除我的人" // 添加到僵尸粉列表 gpt.friendForZombieFansList = append(gpt.friendForZombieFansList, tmpModContact) } if resp.GetFriendRelation() == 5 { tmpModContact.Remark.Str = new(string) *tmpModContact.Remark.Str = "拉黑我的人" // 添加到僵尸粉列表 gpt.friendForZombieFansList = append(gpt.friendForZombieFansList, tmpModContact) } // 暂停 1.5 - 2.5 秒 randWaitTime := gpt.getRandWaitTimes() time.Sleep(time.Duration(randWaitTime) * time.Millisecond) } }() return true } // 获取联系人 func (gpt *WXFriendTask) GetFriendWxidList() []string { currentWXReqInvoker := gpt.wxConn.GetWXReqInvoker() currentWXFileHelperMgr := gpt.wxConn.GetWXFileHelperMgr() CurrentWxcontactSeq := uint32(0) CurrentChatRoomContactSeq := uint32(0) friendUserNames := make([]string, 0) pages := 0 // 死循环 for { pages++ resp, err := currentWXReqInvoker.SendGetContactListPageRequest(CurrentWxcontactSeq, CurrentChatRoomContactSeq) if err != nil { return friendUserNames } UserNameList := resp.GetContactUsernameList() if resp.GetContactUsernameList() == nil { return friendUserNames } if len(UserNameList) == 0 { return friendUserNames } tipText := "正在加载第 " + strconv.Itoa(pages) + " 页" currentWXFileHelperMgr.AddNewTipMsg(tipText) for _, contactUserName := range UserNameList { if contactUserName == "weixin" || contactUserName == "fmessage" || contactUserName == "medianote" || contactUserName == "floatbottle" || contactUserName == "qqmail" || contactUserName == "filehelper" || contactUserName == "mphelper" || contactUserName == "qmessage" { continue } // 判断 gh 开头 if strings.HasPrefix(contactUserName, "gh_") { continue } // 判断 @chatroom 结尾 if strings.HasSuffix(contactUserName, "@chatroom") { continue } friendUserNames = append(friendUserNames, contactUserName) } CurrentWxcontactSeq = resp.GetCurrentWxcontactSeq() CurrentChatRoomContactSeq = resp.GetCurrentChatRoomContactSeq() // 暂停 1.5 - 2.5 秒 randWaitTime := gpt.getRandWaitTimes() time.Sleep(time.Duration(randWaitTime) * time.Millisecond) } }