package service import ( "encoding/hex" "fmt" "strconv" "time" "xiawan/wx/api/req" "xiawan/wx/api/vo" "xiawan/wx/clientsdk/baseinfo" "xiawan/wx/clientsdk/baseutils" "xiawan/wx/clientsdk/proxynet" "xiawan/wx/db" "xiawan/wx/db/table" "xiawan/wx/protobuf/wechat" "xiawan/wx/srv/wxcore" "xiawan/wx/srv/wxface" "github.com/gin-gonic/gin" "github.com/gogo/protobuf/proto" ) // logOutService 退出登录 func LogOutService(queryKey string) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !connect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } // 在退出登录前,先清理WebSocket连接 currentTaskMgr := connect.GetWXTaskMgr() if taskMgr, ok := currentTaskMgr.(*wxcore.WXTaskMgr); ok { wsTask := taskMgr.SocketMsgTask userUUID := wxAccount.GetUserInfo().UUID // 清理WebSocket连接 existingConn := wsTask.GetWebSocket(userUUID) if existingConn != nil { fmt.Println("退出登录时清理WebSocket连接:", userUUID) existingConn.Close() wsTask.DeleteWebSocket(userUUID) } // 禁用WebSocket功能 wsTask.SetWebSocketEnabled(false) } reqInvoker := connect.GetWXReqInvoker() err := reqInvoker.SendLogoutRequest() if err != nil { return vo.NewFail(err.Error()) } return vo.NewSuccess(gin.H{}, "退出成功!") }) } // SendDelContactService 删除好友 func SendDelContactService(queryKey string, m req.DelContactModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !connect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := connect.GetWXReqInvoker() err := reqInvoker.SendDelContactRequest(m.DelUserName) if err != nil { return vo.NewFail(err.Error()) } return vo.NewSuccess(gin.H{}, "删除成功!") }) } // OnlineInfoService 获取登录设备信息 func OnlineInfoService(queryKey string) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } else if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState()))) } reqInvoker := iwxConnect.GetWXReqInvoker() resp, err := reqInvoker.SendOnlineInfo() if err != nil { return vo.NewFail(err.Error()) } deviceInfoList := make([]gin.H, 0) for _, deviceInfo := range resp.GetOnlineList() { deviceInfoList = append(deviceInfoList, gin.H{ "deviceType": deviceInfo.GetDeviceType(), "deviceId": hex.EncodeToString(deviceInfo.GetDeviceID()), "clientKey": deviceInfo.GetClientKey(), "onlineStatus": deviceInfo.GetOnlineStatus(), }) } return vo.NewSuccessObj(gin.H{ "onlineCount": resp.GetOnlineCount(), "onlineList": deviceInfoList, }, "") }) } // GetProfileService 获取个人资料详细信息 func GetProfileService(queryKey string) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } else if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState()))) } reqInvoker := iwxConnect.GetWXReqInvoker() /*err := reqInvoker.SendGetProfileRequest() if err != nil { return vo.NewFail("获取个人资料失败") }*/ profile, err := reqInvoker.SendGetProfileNewRequest() if err != nil { return vo.NewFail("获取个人资料失败") } return vo.NewSuccessObj(profile, "") }) } // SendModifyUserInfoRequest 修改资料 func SendModifyUserInfoRequestService(queryKey string, m req.ModifyUserInfo) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !connect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := connect.GetWXReqInvoker() err := reqInvoker.SendModifyUserInfoRequest(m.City, m.Country, m.NickName, m.Province, m.Signature, m.Sex, m.InitFlag) if err != nil { return vo.NewFail("修改资料失败!") } return vo.NewSuccessObj(nil, "修改资料成功!") }) } // 修改名称 func UpdateNickNameService(queryKey string, m req.UpdateNickNameModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !connect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := connect.GetWXReqInvoker() err := reqInvoker.SendUpdateNickNameRequest(m.Scene, m.Val) if err != nil { return vo.NewFail("修改名称失败!") } return vo.NewSuccessObj(nil, "修改成功!") }) } // 设置名称 func SetNickNameService(queryKey string, m req.UpdateNickNameModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !connect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := connect.GetWXReqInvoker() err := reqInvoker.SendUpdateNickNameRequest(m.Scene, m.Val) if err != nil { return vo.NewFail("修改失败!") } return vo.NewSuccessObj(nil, "修改成功!") }) } // 修改姓别 func SetSexService(queryKey string, m req.UpdateSexModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !connect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := connect.GetWXReqInvoker() err := reqInvoker.SetSexService(m.Sex, m.Country, m.City, m.Province) if err != nil { return vo.NewFail("修改失败!") } return vo.NewSuccessObj(nil, "修改成功!") }) } func GetRedisSyncMsgService(queryKey string) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(connect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := connect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } else if !connect.CheckOnLineStatus() { return vo.NewFail("账号离线,自动上线失败!loginState == " + strconv.Itoa(int(wxAccount.GetLoginState()))) } reqInvoker := connect.GetWXReqInvoker() resp, err := reqInvoker.SendWxSyncMsg(queryKey) // 如果没有同步到数据则返回 cmdList := resp.GetCmdList() syncCount := cmdList.GetCount() messageResp := new(table.SyncMessageResponse) // 遍历同步的信息和群 itemList := cmdList.GetItemList() for index := uint32(0); index < syncCount; index++ { item := itemList[index] itemID := item.GetCmdId() // 同步到消息 if itemID == baseinfo.CmdIDAddMsg { addMsg := &wechat.AddMsg{} err := proto.Unmarshal(item.CmdBuf.Data, addMsg) if err != nil { baseutils.PrintLog(err.Error()) continue } } messageResp.SetMessage(item.GetCmdBuf().GetData(), int32(itemID)) } //发布同步信息消息 if err != nil { return vo.NewFail(err.Error()) } messageResp.Key = resp.KeyBuf return vo.NewSuccessObj(*messageResp, "成功") }) } // SendChangePwdRequestService 更改密码 func SendChangePwdRequestService(queryKey string, m req.SendChangePwdRequestModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := iwxConnect.GetWXReqInvoker() resp, err := reqInvoker.SendChangePwdRequest(m.OldPass, m.NewPass, m.OpCode) if err != nil { return vo.NewFail("SendChangePwdRequestService err:" + err.Error()) } return vo.NewSuccessObj(resp, "") }) } // 上传头像 func UploadHeadImageService(queryKey string, m req.UploadHeadImageModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := iwxConnect.GetWXReqInvoker() resp, err := reqInvoker.UploadHeadImage(m.Base64) if err != nil { return vo.NewFail("SendChangePwdRequestService err:" + err.Error()) } return vo.NewSuccessObj(resp, "成功") }) } // endModifyRemarkRequestService 修改备注 func SendModifyRemarkRequestService(queryKey string, m req.SendModifyRemarkRequestModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := iwxConnect.GetWXReqInvoker() err := reqInvoker.SendModifyRemarkRequest(m.UserName, m.RemarkName) if err != nil { return vo.NewFail("SendChangePwdRequestService err:" + err.Error()) } return vo.NewSuccessObj(nil, "成功") }) } // UpdateAutoPassService 修改加好友需要验证属性 func UpdateAutoPassService(queryKey string, m req.UpdateAutopassModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := iwxConnect.GetWXReqInvoker() err := reqInvoker.UpdateAutopassRequest(m.SwitchType) if err != nil { return vo.NewFail("UpdateAutoPassService err:" + err.Error()) } return vo.NewSuccessObj(nil, "成功") }) } // 设置微信号 func SetWechatService(queryKey string, m req.AlisaModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := iwxConnect.GetWXReqInvoker() rsp, err := reqInvoker.SetWechatRequest(m.Alisa) if err != nil { return vo.NewFail("UpdateAutoPassService err:" + err.Error()) } return vo.NewSuccessObj(rsp, "成功") }) } // 修改步数 func UpdateStepNumberService(queryKey string, m req.UpdateStepNumberModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := iwxConnect.GetWXReqInvoker() rsp, err := reqInvoker.UpdateStepNumberRequest(m.Number) if err != nil { return vo.NewFail("UpdateStepNumberService err:" + err.Error()) } return vo.NewSuccessObj(rsp, "成功") }) } // 获取步数 func GetUserRankLikeCountService(queryKey string, m req.UserRankLikeModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := iwxConnect.GetWXReqInvoker() rsp, err := reqInvoker.SendGetUserRankLikeCountRequest(m.RankId) if err != nil { return vo.NewFail("UpdateStepNumberService err:" + err.Error()) } return vo.NewSuccessObj(rsp, "成功") }) } // 设置添加我的方式 func SetFunctionSwitchService(queryKey string, m req.WxFunctionSwitchModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := iwxConnect.GetWXReqInvoker() req := &wechat.FunctionSwitch{ FunctionId: proto.Uint32(m.Function), SwitchValue: proto.Uint32(m.Value), } buffer, err := proto.Marshal(req) cmdItem := baseinfo.ModifyItem{ CmdID: 0x17, Len: uint32(len(buffer)), Data: buffer, } var cmdItems []*baseinfo.ModifyItem cmdItems = append(cmdItems, &cmdItem) err = reqInvoker.SendOplogRequest(cmdItems) if err != nil { return vo.NewFail("SetFunctionSwitchService err:" + err.Error()) } return vo.NewSuccessObj("ok", "成功") }) } // 设置拍一拍名称 func SetSendPatService(queryKey string, m req.SetSendPatModel) vo.DTO { return checkExIdPerformNoCreateConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { wxAccount := iwxConnect.GetWXAccount() loginState := wxAccount.GetLoginState() //判断在线情况 if !iwxConnect.CheckOnLineStatus() { return vo.NewFail("你已退出登录") } else if loginState == baseinfo.MMLoginStateNoLogin { return vo.NewFail("该账号需要重新登录!loginState == MMLoginStateNoLogin ") } reqInvoker := iwxConnect.GetWXReqInvoker() req := &wechat.PatMod{ Value: proto.Int64(8), Name: proto.String(m.Value), } buffer, err := proto.Marshal(req) cmdItem := baseinfo.ModifyItem{ CmdID: 222, Len: uint32(len(buffer)), Data: buffer, } var cmdItems []*baseinfo.ModifyItem cmdItems = append(cmdItems, &cmdItem) err = reqInvoker.SendOplogRequest(cmdItems) if err != nil { return vo.NewFail("SetSendPatService err:" + err.Error()) } return vo.NewSuccessObj("ok", "成功") }) } // SetProxyService 修改socks5代理 func SetProxyService(queryKey string, model req.GetLoginQrCodeModel) vo.DTO { key := fmt.Sprintf("%s%s", "wechat:Proxy:", queryKey) // 判断代理为空,清除 redis 缓存 if len(model.Proxy) == 0 { //删除缓存 db.DelObj(key) } return getExistWxConnect(queryKey, func(iwxConnect wxface.IWXConnect, newIWXConnect bool) vo.DTO { if iwxConnect == nil { return vo.NewFail("链接不存在! 但代理缓存已重置!Proxy:【" + model.Proxy + "】") } wxAccount := iwxConnect.GetWXAccount() errMsg := "" newProxyUrl := "" oldProxyUrl := wxAccount.GetUserInfo().GetProxyUrl() // 断开连接后 之后重新使用新代理建立连接 iwxConnect.Stop() // 等待 500 毫秒 time.Sleep(time.Millisecond * 500) // 判断是否删除代理 if len(model.Proxy) == 0 { // 删除代理 wxAccount.GetUserInfo().RemoveProxy() newProxyUrl = "" } else { // 修改代理 proxyInfo := proxynet.ParseWXProxyInfo(model.Proxy) dialer := proxyInfo.GetDialer() if dialer != nil { wxAccount := iwxConnect.GetWXAccount() wxAccount.GetUserInfo().SetProxy(proxyInfo) newProxyUrl = wxAccount.GetUserInfo().GetProxyUrl() } else { errMsg = "代理链接格式错误, 正确示例:socks5://username:password@ipv4:port" } } if len(errMsg) > 0 { return vo.NewFail(errMsg) } // 重新二次登录 go func() { defer func() { if r := recover(); r != nil { fmt.Printf("设置代理: %v\n", r) } }() // 等 500 毫秒后重新初始化 time.Sleep(time.Millisecond * 500) InitLoginStatusService(queryKey, false, true, model) //存redis缓存 error := db.SETObj(key, model) if error != nil { } }() return vo.NewSuccess(gin.H{ "oldProxyUrl": oldProxyUrl, "newProxyUrl": newProxyUrl, }, errMsg) }) }