package rpc import ( "encoding/json" "errors" "fmt" "git.hilo.cn/hilo-common/_const/common" "git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/resource/consul" "git.hilo.cn/hilo-common/resource/mysql" "math/rand" ) const ( defaultUserConsulName = "hiloUser" defaultUserServerScheme = "http" defaultUserServerAddr = "127.0.0.1:9040" // 默认内网转发,本地回环 ) var UserServerHost = []string{defaultUserServerAddr} func init() { go func() { consul.RegisterWatcher(defaultUserConsulName, func(addr []string) { if len(addr) > 0 { UserServerHost = addr } }) }() } type CvUserLevel struct { UserId mysql.ID `json:"userId"` // 用户id WealthUserGrade uint32 `json:"wealthUserGrade"` //财富等级 CharmUserGrade uint32 `json:"charmUserGrade"` //魅力等级 ActiveUserGrade uint32 `json:"activeUserGrade"` // 活跃等级 NobleLevel uint16 `json:"nobleLevel"` // 贵族等级 } // 获取用户等级 func GetUserLevel(model *domain.Model, userId mysql.ID) (CvUserLevel, error) { level, err := MGetUserLevel(model, []mysql.ID{userId}) if err != nil { return CvUserLevel{}, nil } return level[userId], nil } // 批量获取用户等级 func MGetUserLevel(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]CvUserLevel, error) { type Response struct { Code int `json:"code"` Message string `json:"message"` Data map[mysql.ID]CvUserLevel `json:"data"` } var res = make(map[mysql.ID]CvUserLevel) if len(userIds) <= 0 { return res, nil } var userIdsStr []string for _, userId := range userIds { userIdsStr = append(userIdsStr, fmt.Sprintf("%d", userId)) } _url := fmt.Sprintf("%v://%v/inner/user/levels", defaultUserServerScheme, getUserHost()) resp, err := HttpGet(model, _url, nil, map[string][]string{ "ids": userIdsStr, }) if err != nil { model.Log.Errorf("MGetUserLevel fail:%v", err) return res, err } response := new(Response) if err = json.Unmarshal(resp, response); err != nil { model.Log.Errorf("MGetUserLevel json fail:%v", err) return res, err } for userId, level := range response.Data { res[userId] = CvUserLevel{ UserId: level.UserId, WealthUserGrade: level.WealthUserGrade, CharmUserGrade: level.CharmUserGrade, ActiveUserGrade: level.ActiveUserGrade, NobleLevel: level.NobleLevel, } } return res, nil } type CvUserBag struct { BagId mysql.ID `json:"bagId"` // 背包id ResType mysql.Type `json:"resType"` // 道具类型 1:礼物道具 ResId mysql.ID `json:"resId"` // 道具资源id Name string `json:"name"` // 资源名称 DiamondNum mysql.Num `json:"diamondNum"` // 钻石数量 IconUrl string `json:"iconUrl"` // icon url SvgaUrl string `json:"svgaUrl"` // svga url Count mysql.Num `json:"count"` // 拥有数量 RemainDays int `json:"remainDays"` // 有效天数 } // 根据bagId获取用户背包 func GetUserBagId(model *domain.Model, bagId mysql.ID) (CvUserBag, error) { type Response struct { Code int `json:"code"` Message string `json:"message"` Data CvUserBag `json:"data"` } _url := fmt.Sprintf("%v://%v/inner/user/bag/id", defaultUserServerScheme, getUserHost()) resp, err := HttpGet(model, _url, nil, map[string][]string{ "bagId": {fmt.Sprintf("%d", bagId)}, }) if err != nil { model.Log.Errorf("GetUserBag fail:%v", err) return CvUserBag{}, err } response := new(Response) if err = json.Unmarshal(resp, response); err != nil { model.Log.Errorf("GetUserBag json fail:%v", err) return CvUserBag{}, err } return response.Data, nil } // 发送用户背包 // param resType 1:礼物 // param resId 礼物id // param count 数量 // param day 天数 // param reason 原因 func SendUserBag(model *domain.Model, userId mysql.ID, resType, resId mysql.ID, count, day mysql.Num, reason string) error { type Response struct { Code int `json:"code"` Message string `json:"message"` } _url := fmt.Sprintf("%v://%v/inner/prop/bag/send", defaultUserServerScheme, getUserHost()) resp, err := HttpPostForm(model, _url, nil, map[string]string{ "userId": fmt.Sprintf("%d", userId), "resType": fmt.Sprintf("%d", resType), "resId": fmt.Sprintf("%d", resId), "count": fmt.Sprintf("%d", count), "day": fmt.Sprintf("%d", day), "reason": reason, }) if err != nil { model.Log.Errorf("SendUserBag fail:%v", err) return err } response := new(Response) if err = json.Unmarshal(resp, response); err != nil { model.Log.Errorf("SendUserBag json fail:%v", err) return err } if response.Code != 200 { model.Log.Errorf("SendUserBag fail:%v", *response) return errors.New(response.Message) } return nil } // 发送用户贵族 func SendUserNoble(model *domain.Model, userId mysql.ID, level int, day mysql.Num) error { type Response struct { Code int `json:"code"` Message string `json:"message"` } _url := fmt.Sprintf("%v://%v/inner/prop/noble/send", defaultUserServerScheme, getUserHost()) resp, err := HttpPostForm(model, _url, nil, map[string]string{ "userId": fmt.Sprintf("%d", userId), "level": fmt.Sprintf("%d", level), "day": fmt.Sprintf("%d", day), }) if err != nil { model.Log.Errorf("SendUserNoble fail:%v", err) return err } response := new(Response) if err = json.Unmarshal(resp, response); err != nil { model.Log.Errorf("SendUserNoble json fail:%v", err) return err } if response.Code != 200 { model.Log.Errorf("SendUserNoble fail:%v", *response) return errors.New(response.Message) } return nil } // 发送用户头饰 func SendUserHeadwear(model *domain.Model, userId mysql.ID, headwearId mysql.ID, day mysql.Num) error { type Response struct { Code int `json:"code"` Message string `json:"message"` } _url := fmt.Sprintf("%v://%v/inner/prop/headwear/send", defaultUserServerScheme, getUserHost()) resp, err := HttpPostForm(model, _url, nil, map[string]string{ "userId": fmt.Sprintf("%d", userId), "headwearId": fmt.Sprintf("%d", headwearId), "day": fmt.Sprintf("%d", day), }) if err != nil { model.Log.Errorf("SendUserHeadwear fail:%v", err) return err } response := new(Response) if err = json.Unmarshal(resp, response); err != nil { model.Log.Errorf("SendUserHeadwear json fail:%v", err) return err } if response.Code != 200 { model.Log.Errorf("SendUserHeadwear fail:%v", *response) return errors.New(response.Message) } return nil } // 发送用户座驾 func SendUserRide(model *domain.Model, userId mysql.ID, rideId mysql.ID, day mysql.Num) error { type Response struct { Code int `json:"code"` Message string `json:"message"` } _url := fmt.Sprintf("%v://%v/inner/prop/ride/send", defaultUserServerScheme, getUserHost()) resp, err := HttpPostForm(model, _url, nil, map[string]string{ "userId": fmt.Sprintf("%d", userId), "rideId": fmt.Sprintf("%d", rideId), "day": fmt.Sprintf("%d", day), }) if err != nil { model.Log.Errorf("SendUserRide fail:%v", err) return err } response := new(Response) if err = json.Unmarshal(resp, response); err != nil { model.Log.Errorf("SendUserRide json fail:%v", err) return err } if response.Code != 200 { model.Log.Errorf("SendUserRide fail:%v", *response) return errors.New(response.Message) } return nil } // 获取指定cp对 func MGetUserCpPairs(model *domain.Model, userIds []mysql.ID) ([][3]mysql.ID, error) { type Response struct { Code int `json:"code"` Message string `json:"message"` Data [][3]mysql.ID `json:"data"` } var res [][3]mysql.ID if len(userIds) <= 0 { return res, nil } var userIdsStr []string for _, userId := range userIds { userIdsStr = append(userIdsStr, fmt.Sprintf("%d", userId)) } _url := fmt.Sprintf("%v://%v/inner/user/cp/pair", defaultUserServerScheme, getUserHost()) resp, err := HttpGet(model, _url, nil, map[string][]string{ "ids": userIdsStr, }) if err != nil { model.Log.Errorf("MGetUserLevel fail:%v", err) return res, err } response := new(Response) if err = json.Unmarshal(resp, response); err != nil { model.Log.Errorf("MGetUserLevel json fail:%v", err) return res, err } else { res = response.Data } return res, nil } func getUserHost() string { l := len(UserServerHost) r := rand.Intn(l) // 随机一个 mylogrus.MyLog.Infof("getHostUser:%v---%v", r, UserServerHost[r]) return UserServerHost[r] } // cp关系 type CvCpRelation struct { CpId uint64 `json:"cpId"` UserId uint64 `json:"userId"` CpUserId uint64 `json:"cpUserId"` CpUserAvatar string `json:"cpUserAvatar"` } // 批量获取用户cpRelation func MGetUserCpRelations(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]CvCpRelation, error) { type Response struct { Code int `json:"code"` Message string `json:"message"` Data map[mysql.ID]CvCpRelation `json:"data"` } var res = make(map[mysql.ID]CvCpRelation) if len(userIds) <= 0 { return res, nil } var userIdsStr []string for _, userId := range userIds { userIdsStr = append(userIdsStr, fmt.Sprintf("%d", userId)) } _url := fmt.Sprintf("%v://%v/inner/user/cpRelations", defaultUserServerScheme, getUserHost()) resp, err := HttpGet(model, _url, nil, map[string][]string{ "ids": userIdsStr, }) if err != nil { model.Log.Errorf("MGetUserSvip fail:%v", err) return res, err } response := new(Response) if err = json.Unmarshal(resp, response); err != nil { model.Log.Errorf("MGetUserSvip json fail:%v", err) return res, err } return response.Data, nil } // 获取用户cpRelation func GetUserCpRelation(model *domain.Model, userId mysql.ID) (CvCpRelation, error) { res, err := MGetUserCpRelations(model, []uint64{userId}) if err != nil { return CvCpRelation{}, err } return res[userId], nil } type CvCp struct { CpUserInfo *CvUserBase `json:"cpUserInfo"` // cp用户信息 CpLevel CvCpLevel `json:"cpLevel"` // cp等级 MyPrivilegeList []CvPrivilege `json:"myPrivilegeList"` // 等级特权 CreatedUnix int64 `json:"createdUnix"` // cp创建时间 CpDays int `json:"cpDays"` // cp天数 } // cp等级 type CvCpLevel struct { Level int `json:"level"` // 等级 0:无称号 1:恋爱CP 2:甜蜜CP 3:忠诚CP 4:炽热CP 5:荣耀CP Points uint32 `json:"points"` // CP值 Title string `json:"title"` } // 特权信息 type CvPrivilege struct { Type int `json:"type"` // 特权id 1:空间 2:横幅 3:等级勋章 4:证书 5:进场特效 6:头像头饰 7:动态资料卡 8:麦位特效 } //用户基本信息 type CvUserBase struct { //不会有返回值 Id *mysql.ID `json:"id,omitempty"` //头像,不存在为nil Avatar *string `json:"avatar"` //是否默认头像 true:是 false:不是 DefaultAvatar *bool `json:"defaultAvatar"` //用户对外ID ExternalId *string `json:"externalId"` //昵称,不存在为nil Nick *string `json:"nick"` //签名,不存在为nil Description *string `json:"description"` //性别 1:男 2:女,不存在为nil Sex *uint8 `json:"sex"` //国家,不存在为nil Country *string `json:"country"` //国旗图标,不存在为nil CountryIcon *string `json:"countryIcon"` //邀请码 Code *string `json:"code"` IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号 IsLogout bool `json:"isLogout"` //是否注销 //生日,如果是其它人用户信息,年龄则按照是否展示显示,如果是本人,年龄则按照是否存在展示 Birthday *uint64 `json:"birthday"` //是否展示年龄, 是本人才有数据,看其他用户均为nil IsShowAge *uint8 `json:"isShowAge"` //是否工会成员, 只有是自己查自己,这个才有值,其它全为nil, 20220329 数据开放:原因:产品1对1视频聊天中,公会用户视频需要送礼物。改为: 全部人可以知道是否是公会用户。 IsTradeUnion *bool `json:"isTradeUnion"` //是否代理管理员, 只有自己查自己的时候才有值,其他情况为nil IsAgentMgr *bool `json:"isAgentMgr"` //工会成员,是否开启了,匹配通知,只有 isTradeUnion值为true,这里才有值, IsTradeUnionMatchNotification *bool `json:"isTradeUnionMatchNotification"` //是否VIP用户 IsVip bool `json:"isVip"` //是否是官方人员 IsOfficialStaff bool `json:"isOfficialStaff"` //VIP用户过期时间(只有自己查询自己,才返回) VipExpireTime *int64 `json:"vipExpireTime"` Svip CvSvip `json:"svip"` // svip结构,等级+权限 Medals []uint32 `json:"medals"` // 勋章列表 TODO: 删除 MedalInfo []CvMedal `json:"medalInfo"` // 勋章列表 Headwear *CvHeadwear `json:"headwear"` // 当前使用的头饰 Ride CvProperty `json:"ride"` // 当前使用的座驾 Noble CvNoble `json:"noble"` // 当前的 GroupRole common.GroupRoleType `json:"groupRole"` // 在群组的角色 } type CvMedal struct { Id uint32 `json:"id"` PicUrl mysql.Str `json:"picUrl"` EffectUrl mysql.Str `json:"effectUrl"` } type CvHeadwear struct { Id uint64 `json:"id"` Using bool `json:"using"` PicUrl mysql.Str `json:"picUrl"` EffectUrl mysql.Str `json:"effectUrl"` TimeLeft int64 `json:"timeLeft"` // 离到期还有多少秒(过期则是负数) } type CvProperty struct { Id uint64 `json:"id"` PicUrl mysql.Str `json:"picUrl"` EffectUrl mysql.Str `json:"effectUrl"` Using bool `json:"using"` TimeLeft int64 `json:"timeLeft"` // 离到期还有多少秒(过期则是负数) SenderAvatar string `json:"senderAvatar"` ReceiverAvatar string `json:"receiverAvatar"` } type CvNoble struct { Level uint16 `json:"level"` EndTime int64 `json:"endTime"` } // 获取用户cp func GetUserCp(model *domain.Model, userId mysql.ID) (*CvCp, error) { type Response struct { Code int `json:"code"` Message string `json:"message"` Data *CvCp `json:"data"` } header := map[string]string{ mycontext.TRACEID: model.GetTraceId(), } _url := fmt.Sprintf("%v://%v/inner/user/cp", defaultUserServerScheme, getUserHost()) resp, err := HttpGet(model, _url, header, map[string][]string{ "id": {fmt.Sprintf("%d", userId)}, }) if err != nil { model.Log.Errorf("GetUserCp fail:%v", err) return nil, err } response := new(Response) if err = json.Unmarshal(resp, response); err != nil { model.Log.Errorf("GetUserCp json fail:%v", err) return nil, err } if response.Data != nil && response.Data.CpUserInfo != nil { return response.Data, nil } return nil, nil } // cp进场特效信息 type CvCpEntryEffect struct { CpLevel int `json:"cpLevel"` CpUserAvatar string `json:"cpUserAvatar"` CpEntryEffect bool `json:"cpEntryEffect"` } // 获取用户cp进房特效 func GetUserCpEntryEffect(model *domain.Model, userId mysql.ID) (*CvCpEntryEffect, error) { type Response struct { Code int `json:"code"` Message string `json:"message"` Data *CvCpEntryEffect `json:"data"` } header := map[string]string{ mycontext.TRACEID: model.GetTraceId(), } _url := fmt.Sprintf("%v://%v/inner/user/cp/entryEffect", defaultUserServerScheme, getUserHost()) resp, err := HttpGet(model, _url, header, map[string][]string{ "id": {fmt.Sprintf("%d", userId)}, }) if err != nil { model.Log.Errorf("GetUserCp fail:%v", err) return nil, err } response := new(Response) if err = json.Unmarshal(resp, response); err != nil { model.Log.Errorf("GetUserCp json fail:%v", err) return nil, err } if response.Data != nil { return response.Data, nil } return nil, nil }