first commit

This commit is contained in:
2026-02-17 13:06:23 +08:00
commit 7cbd3d061d
349 changed files with 126558 additions and 0 deletions
+469
View File
@@ -0,0 +1,469 @@
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)
}
}