...
 
Commits (38)
...@@ -4,14 +4,17 @@ import ( ...@@ -4,14 +4,17 @@ import (
"git.hilo.cn/hilo-common/resource/config" "git.hilo.cn/hilo-common/resource/config"
"hilo-user/cron/cp_cron" "hilo-user/cron/cp_cron"
"hilo-user/cron/gift_cron" "hilo-user/cron/gift_cron"
"hilo-user/cron/user_cron"
) )
func Init() { func Init() {
user_cron.SyncGiftRecommendUsers() // 同步送礼推荐用户,多进程都需要执行
if !config.IsMaster() { if !config.IsMaster() {
return return
} }
gift_cron.SendGiftEventInit() // 礼物消息 //gift_cron.SendGiftEventInit() // 礼物消息
gift_cron.GiftRemark() // 礼物消息补偿 //gift_cron.GiftRemark() // 礼物消息补偿
gift_cron.SendGiftEvent() // 送礼事件
cp_cron.ClearCpExpire() // 清理过期cp cp_cron.ClearCpExpire() // 清理过期cp
cp_cron.CpAnniversaryNotice() // cp纪念日 cp_cron.CpAnniversaryNotice() // cp纪念日
cp_cron.CpInviteCancelInit() // cp邀请、解除到期结算 cp_cron.CpInviteCancelInit() // cp邀请、解除到期结算
......
package gift_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/jinzhu/now"
"hilo-user/_const/enum/cp_e"
"hilo-user/domain/cache/gift_c"
"hilo-user/domain/event/gift_ev"
"hilo-user/domain/model/cp_m"
"time"
)
// 送礼事件
func SendGiftEvent() {
//if !config.IsMaster() {
// return
//}
go func() {
for true {
model := domain.CreateModelNil()
if sendGiftEvent := gift_c.BLPopQueueSendGift(model); sendGiftEvent != nil {
cpGiftEvent(model, sendGiftEvent) // cp送礼
}
}
}()
}
// 送礼增加cp等级
// 送礼增加cp排行榜
func cpGiftEvent(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
// 只处理cp礼物
if !sendGiftEvent.ResGift.Cp {
return
}
for _, receiverUid := range sendGiftEvent.ReceiveUserIds {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum
// 有cp关系
if cpRelation, exits := cp_m.GetCpRelationPair(model, sendGiftEvent.SendUserId, receiverUid); exits {
if err := cp_m.AddCpLevelPoints(model, cpRelation, diamonds, sendGiftEvent.SceneType, sendGiftEvent.SceneUid); err != nil {
model.Log.Errorf("AddCpLevelPoints fail:%v", err)
}
if err := cp_m.AddCpDayRank(model, cpRelation, diamonds); err != nil {
model.Log.Errorf("AddCpDayRank fail:%v", err)
}
// 检查最新的等级
if cpLevel := cp_m.GetCpLevel(model, cpRelation.Id); cpLevel.CpId >= 0 {
points := cpLevel.Points + cp_e.CpLevelPoints[cpLevel.Level]
if err := cp_m.UpdateCpAchievement(model, cpLevel.CpId, cpRelation.UserId1, cpRelation.UserId2, cp_e.CpAchievementLevel, points); err != nil {
model.Log.Errorf("UpdateCpAchievement fail:%v", err)
}
}
// 检查最高的分数
for _, queryType := range []string{"day", "week", "month"} {
var beginDate, endDate string
var cpAchievementType cp_e.CpAchievement
switch queryType {
case "day":
beginDate, endDate = time.Now().Format("2006-01-02"), time.Now().Format("2006-01-02")
cpAchievementType = cp_e.CpAchievementDayRank
case "week":
beginDate = now.BeginningOfWeek().Format("2006-01-02")
endDate = now.EndOfWeek().Format("2006-01-02")
cpAchievementType = cp_e.CpAchievementWeekRank
case "month":
beginDate = now.BeginningOfMonth().Format("2006-01-02")
endDate = now.EndOfMonth().Format("2006-01-02")
cpAchievementType = cp_e.CpAchievementMonthRank
}
if data := cp_m.GetCpDayRank(model, beginDate, endDate, cpRelation.Id); data.Score > 0 {
if err := cp_m.UpdateCpAchievement(model, cpRelation.Id, cpRelation.UserId1, cpRelation.UserId2, cpAchievementType, data.Score); err != nil {
model.Log.Errorf("UpdateCpAchievement fail:%v", err)
}
}
}
// 检查最新日周月榜单
return // 业务场景允许提前break(cp是唯一的)
}
}
}
package user_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-user/domain/model/recommend_m"
)
// 定期同步礼物推荐用户
func SyncGiftRecommendUsers() {
go recommend_m.SyncPastTop50SendGiftUsers(domain.CreateModelNil()) // 启动先同步一次
c := cron.New()
spec := "0 */5 * * * ?"
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
recommend_m.SyncPastTop50SendGiftUsers(model)
})
c.Start()
}
...@@ -6,12 +6,12 @@ import ( ...@@ -6,12 +6,12 @@ import (
) )
type CvCpRank struct { type CvCpRank struct {
CpId uint64 `json:"cpId"` // cpId CpId uint64 `json:"cpId"` // cpId
User1 *user_cv.CvUserBase `json:"user1"` // user1 User1 *user_cv.CvUserLittle `json:"user1"` // user1
User2 *user_cv.CvUserBase `json:"user2,omitempty"` // user2 User2 *user_cv.CvUserLittle `json:"user2,omitempty"` // user2
Score uint32 `json:"score"` // 分值 Score uint32 `json:"score"` // 分值
CpLevel CvCpLevel `json:"cpLevel"` // cp等级 CpLevel CvCpLevel `json:"cpLevel"` // cp等级
Ranking string `json:"ranking"` // 排名 Ranking string `json:"ranking"` // 排名
} }
type CvCpAchievement struct { type CvCpAchievement struct {
......
...@@ -27,6 +27,8 @@ type InviteApply struct { ...@@ -27,6 +27,8 @@ type InviteApply struct {
Avatar string `json:"avatar"` Avatar string `json:"avatar"`
ExternalId string `json:"externalId"` ExternalId string `json:"externalId"`
Reason int `json:"reason"` // 1.已申请2.待审核3.已通过4.已拒绝" Reason int `json:"reason"` // 1.已申请2.待审核3.已通过4.已拒绝"
Country string `json:"country"`
PlatformId string `json:"platformId"`
} }
type InviteApplyNumRes struct { type InviteApplyNumRes struct {
......
package user_cv package user_cv
import ( import (
"encoding/json"
"git.hilo.cn/hilo-common/_const/common" "git.hilo.cn/hilo-common/_const/common"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
...@@ -29,6 +30,7 @@ type UserTiny struct { ...@@ -29,6 +30,7 @@ type UserTiny struct {
Country string `json:"country"` Country string `json:"country"`
CountryIcon string `json:"countryIcon"` CountryIcon string `json:"countryIcon"`
IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号 IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号
Birthday uint64 `json:"birthday"`
} }
func UserToTiny(user user_m.User) *UserTiny { func UserToTiny(user user_m.User) *UserTiny {
...@@ -42,6 +44,7 @@ func UserToTiny(user user_m.User) *UserTiny { ...@@ -42,6 +44,7 @@ func UserToTiny(user user_m.User) *UserTiny {
Country: user.Country, Country: user.Country,
CountryIcon: user.CountryIcon, CountryIcon: user.CountryIcon,
IsPrettyCode: user.IsPrettyCode(), IsPrettyCode: user.IsPrettyCode(),
Birthday: user.Birthday,
} }
} }
...@@ -82,7 +85,8 @@ type CvUserBase struct { ...@@ -82,7 +85,8 @@ type CvUserBase struct {
//邀请码 //邀请码
Code *string `json:"code"` Code *string `json:"code"`
IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号 IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号
IsLogout bool `json:"isLogout"` //是否注销 IsNew bool `json:"isNew"` // 是否新用户
IsLogout bool `json:"isLogout"` // 是否注销
//生日,如果是其它人用户信息,年龄则按照是否展示显示,如果是本人,年龄则按照是否存在展示 //生日,如果是其它人用户信息,年龄则按照是否展示显示,如果是本人,年龄则按照是否存在展示
Birthday *uint64 `json:"birthday"` Birthday *uint64 `json:"birthday"`
//是否展示年龄, 是本人才有数据,看其他用户均为nil //是否展示年龄, 是本人才有数据,看其他用户均为nil
...@@ -108,6 +112,17 @@ type CvUserBase struct { ...@@ -108,6 +112,17 @@ type CvUserBase struct {
GroupRole common.GroupRoleType `json:"groupRole"` // 在群组的角色 GroupRole common.GroupRoleType `json:"groupRole"` // 在群组的角色
} }
type CvUserLittle struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
}
//批量获取用户基本信息 //批量获取用户基本信息
func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error) { func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error) {
if len(userIds) == 0 { if len(userIds) == 0 {
...@@ -199,6 +214,7 @@ func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error) ...@@ -199,6 +214,7 @@ func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error)
CountryIcon: StrNil(user.CountryIcon), CountryIcon: StrNil(user.CountryIcon),
Code: StrToString(&user.Code), Code: StrToString(&user.Code),
IsPrettyCode: user.IsPrettyCode(), IsPrettyCode: user.IsPrettyCode(),
IsNew: user.IsNew(),
IsVip: vips[user.ID] != nil, IsVip: vips[user.ID] != nil,
IsOfficialStaff: superManagerMap[user.ID], IsOfficialStaff: superManagerMap[user.ID],
Medals: IfLogoutMedals(IfLogout(user.LogoutTime), []uint32{}, medals[user.ID]), Medals: IfLogoutMedals(IfLogout(user.LogoutTime), []uint32{}, medals[user.ID]),
...@@ -299,6 +315,7 @@ func GetUserBasesForCp(userIds []mysql.ID) ([]*CvUserBase, error) { ...@@ -299,6 +315,7 @@ func GetUserBasesForCp(userIds []mysql.ID) ([]*CvUserBase, error) {
CountryIcon: StrNil(user.CountryIcon), CountryIcon: StrNil(user.CountryIcon),
Code: StrToString(&user.Code), Code: StrToString(&user.Code),
IsPrettyCode: user.IsPrettyCode(), IsPrettyCode: user.IsPrettyCode(),
IsNew: user.IsNew(),
IsVip: vips[user.ID] != nil, IsVip: vips[user.ID] != nil,
Noble: noble_cv.CvNoble{ Noble: noble_cv.CvNoble{
Level: nobles[user.ID].Level, Level: nobles[user.ID].Level,
...@@ -477,6 +494,50 @@ type CvUserDetail struct { ...@@ -477,6 +494,50 @@ type CvUserDetail struct {
Cp *CvCp `json:"cp,omitempty"` // cp信息 Cp *CvCp `json:"cp,omitempty"` // cp信息
} }
//用户详细信息-在房间里面时需要的
type CvUserDetailRoom 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"`
//性别 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"` // 是否靓号
//生日,如果是其它人用户信息,年龄则按照是否展示显示,如果是本人,年龄则按照是否存在展示
Birthday *uint64 `json:"birthday"`
//是否展示年龄, 是本人才有数据,看其他用户均为nil
IsShowAge *uint8 `json:"isShowAge"`
//是否VIP用户
IsVip bool `json:"isVip"`
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
Medals []uint32 `json:"medals"` // 勋章列表
Noble noble_cv.CvNoble `json:"noble"` // 当前的
CountryManager *CVCountryManager `json:"countryManager,omitempty"` // 国家管理员
Headwear *headwear_cv.CvHeadwear `json:"headwear"` // 当前使用的头饰
WealthUserGrade uint32 `json:"wealthUserGrade"` //财富等级
CharmUserGrade uint32 `json:"charmUserGrade"` //魅力等级
ActivityUserGrade uint32 `json:"activityUserGrade"` //活跃等级
GroupPower rpc.CvGroupPowerInfo `json:"groupPower"` // 家族
//是否喜欢(本人没有数据,//20210205 已废弃nil,产品说:可以自己喜欢自己)
IsLike *bool `json:"isLike"`
//别人是否喜欢我,自己本人没有数据 (20210205 已废弃nil,产品说:可以自己喜欢自己)
IsLikeMe *bool `json:"isLikeMe"`
Cp *CvCpTiny `json:"cp,omitempty"` // cp信息
GroupRole common.GroupRoleType `json:"groupRole"` // 在群组的角色
}
// cv国家管理人员 // cv国家管理人员
type CVCountryManager struct { type CVCountryManager struct {
Country string `json:"country"` // 国家name Country string `json:"country"` // 国家name
...@@ -492,6 +553,33 @@ type CvCp struct { ...@@ -492,6 +553,33 @@ type CvCp struct {
CpDays int `json:"cpDays"` // cp天数 CpDays int `json:"cpDays"` // cp天数
} }
// cp信息
type CvCpTiny struct {
CpUserInfo *CvCpUser `json:"cpUserInfo"` // cp用户信息
CpLevel CvCpLevel `json:"cpLevel"` // cp等级
MyPrivilegeList []CvPrivilege `json:"myPrivilegeList"` // 等级特权
CreatedUnix int64 `json:"createdUnix"` // cp创建时间
CpDays int `json:"cpDays"` // cp天数
}
type CvCpUser struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
//性别 1:男 2:女,不存在为nil
Sex *uint8 `json:"sex"`
//邀请码
Code *string `json:"code"`
Headwear *headwear_cv.CvHeadwear `json:"headwear"` // 当前使用的头饰
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
Noble noble_cv.CvNoble `json:"noble"` // 当前的
}
// cp关系 // cp关系
type CvCpRelation struct { type CvCpRelation struct {
CpId uint64 `json:"cpId"` CpId uint64 `json:"cpId"`
...@@ -511,3 +599,19 @@ type CvCpLevel struct { ...@@ -511,3 +599,19 @@ type CvCpLevel struct {
type CvPrivilege struct { type CvPrivilege struct {
Type cp_e.CpPrivilege `json:"type"` // 特权id 1:空间 2:横幅 3:等级勋章 4:证书 5:进场特效 6:头像头饰 7:动态资料卡 8:麦位特效 Type cp_e.CpPrivilege `json:"type"` // 特权id 1:空间 2:横幅 3:等级勋章 4:证书 5:进场特效 6:头像头饰 7:动态资料卡 8:麦位特效
} }
func UserBaseToUserLittle(base *CvUserBase) *CvUserLittle {
return &CvUserLittle{
Id: base.Id,
Avatar: base.Avatar,
ExternalId: base.ExternalId,
Nick: base.Nick,
}
}
func CvUserDetailToCvUserDetailRoom(info *CvUserDetail) *CvUserDetailRoom {
res := new(CvUserDetailRoom)
jData, _ := json.Marshal(info)
_ = json.Unmarshal(jData, &res)
return res
}
...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=47.244.34.27:6379 REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT] [JWT]
SECRET=hilo1632 SECRET=hilo1632
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
package gift_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-user/domain/event/gift_ev"
"time"
)
const EventSendGiftHiloUserQueue = "send:gift:queue:hilo_user"
// redis pop event sendGift
func BLPopQueueSendGift(model *domain.Model) *gift_ev.SendGiftEvent {
var res *gift_ev.SendGiftEvent
queue := EventSendGiftHiloUserQueue
strs, err := model.RedisCluster.BLPop(model, time.Second, queue).Result()
if err != nil {
if err != redis.Nil {
model.Log.Errorf("BLPopQueueSendGift fail:%v", err)
}
return nil
}
if len(strs) >= 2 {
content := strs[1]
res = new(gift_ev.SendGiftEvent)
if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopQueueSendGift json fail:%v", err)
return nil
}
return res
}
return nil
}
...@@ -27,7 +27,7 @@ func SetJSON(model *domain.Model, key string, obj interface{}) (err error) { ...@@ -27,7 +27,7 @@ func SetJSON(model *domain.Model, key string, obj interface{}) (err error) {
if err != nil { if err != nil {
return err return err
} }
return model.Redis.Set(model.Context, key, value, DEFAULT_TTL).Err() return model.RedisCluster.Set(model.Context, key, value, DEFAULT_TTL).Err()
} }
// 获取redis中json结构体 // 获取redis中json结构体
...@@ -37,7 +37,7 @@ func GetJSON(model *domain.Model, key string, obj interface{}) (err error) { ...@@ -37,7 +37,7 @@ func GetJSON(model *domain.Model, key string, obj interface{}) (err error) {
defer func() { defer func() {
model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err) model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err)
}() }()
value, err = model.Redis.Get(model.Context, key).Bytes() value, err = model.RedisCluster.Get(model.Context, key).Bytes()
if err != nil { if err != nil {
// may redisV2.Nil // may redisV2.Nil
return return
...@@ -59,7 +59,7 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time ...@@ -59,7 +59,7 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
if time.Now().After(deadline) { if time.Now().After(deadline) {
return false return false
} }
flag, err := model.Redis.SetNX(model, key, "1", expireTimeout).Result() flag, err := model.RedisCluster.SetNX(model, key, "1", expireTimeout).Result()
if err != nil || !flag { if err != nil || !flag {
time.Sleep(time.Millisecond * 10) time.Sleep(time.Millisecond * 10)
} else { } else {
...@@ -70,5 +70,5 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time ...@@ -70,5 +70,5 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
// 解锁 // 解锁
func UnLock(model *domain.Model, key string) { func UnLock(model *domain.Model, key string) {
model.Redis.Del(model, key) model.RedisCluster.Del(model, key)
} }
...@@ -53,7 +53,7 @@ func ToUserId(model *domain.Model, externalId mysql.Str) (mysql.ID, error) { ...@@ -53,7 +53,7 @@ func ToUserId(model *domain.Model, externalId mysql.Str) (mysql.ID, error) {
if externalId == "" { if externalId == "" {
return 0, myerr.NewSysError("externalId 不能为空") return 0, myerr.NewSysError("externalId 不能为空")
} }
userId, err := model.Redis.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64() userId, err := model.RedisCluster.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64()
if err != nil && err != redisV8.Nil { if err != nil && err != redisV8.Nil {
return 0, err return 0, err
} }
...@@ -76,7 +76,7 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) { ...@@ -76,7 +76,7 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) {
if code == "" { if code == "" {
return 0, myerr.NewSysError("code 不能为空") return 0, myerr.NewSysError("code 不能为空")
} }
userId, err := model.Redis.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64() userId, err := model.RedisCluster.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64()
if err != nil && err != redisV8.Nil { if err != nil && err != redisV8.Nil {
return 0, err return 0, err
} }
...@@ -105,11 +105,11 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error { ...@@ -105,11 +105,11 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error {
// return err // return err
//} //}
// cache externalId->userId // cache externalId->userId
if err := model.Redis.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil { if err := model.RedisCluster.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err return err
} }
// cache code->userId // cache code->userId
if err := model.Redis.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil { if err := model.RedisCluster.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err return err
} }
if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil { if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil {
......
package common package common
import ( import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli" "github.com/bluele/gcache"
"hilo-user/_const/redis_key"
"hilo-user/myerr"
"time" "time"
) )
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) { // 改成lru
bData, err := GetCache(redis_key.GetUserMedalMerge(userId)) var userMedalMergeLru = gcache.New(10000).LRU().Build()
if err != nil {
return nil, myerr.WrapErr(err)
}
res := make([]uint32, 0)
err = json.Unmarshal(bData, &res)
if err != nil {
return nil, myerr.WrapErr(err)
}
return res, nil
}
func GetCache(key string) ([]byte, error) { func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
data, err := redisCli.GetRedis().Get(context.Background(), key).Bytes() if data, err := userMedalMergeLru.Get(userId); err == nil {
if err != nil { return data.([]uint32), nil
return nil, err
}
return data, nil
}
func SetCache(key string, data interface{}, expire time.Duration) error {
jData, err := json.Marshal(data)
if err != nil {
return err
}
err = redisCli.GetRedis().Set(context.Background(), key, jData, expire).Err()
if err != nil {
mylogrus.MyLog.Errorf("SetCache key:%s, data:%v, err:%s", key, data, err)
return err
} }
return nil return nil, nil
} }
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) error { func SetUserMedalMergeCache(userId mysql.ID, data []uint32) {
err := SetCache(redis_key.GetUserMedalMerge(userId), data, time.Hour*2) _ = userMedalMergeLru.SetWithExpire(userId, data, time.Minute*15)
if err != nil {
mylogrus.MyLog.Errorf("SetUserMedalMerge err:%s", err)
return myerr.WrapErr(err)
}
return nil
} }
...@@ -130,7 +130,21 @@ func GetCp(model *domain.Model, userId uint64) (*CpRelation, error) { ...@@ -130,7 +130,21 @@ func GetCp(model *domain.Model, userId uint64) (*CpRelation, error) {
if err == gorm.ErrRecordNotFound { if err == gorm.ErrRecordNotFound {
return res, nil return res, nil
} }
model.Log.Errorf("CreateCp userId:%d, err:%v", userId, err) model.Log.Errorf("GetCp userId:%d, err:%v", userId, err)
return nil, err
}
return res, nil
}
func GetCpByIds(model *domain.Model, userId1, userId2 uint64) (*CpRelation, error) {
ids := []uint64{userId1, userId2}
res := new(CpRelation)
err := model.DB().Model(CpRelation{}).Where("user_id1 in (?) and user_id2 in (?)", ids, ids).First(&res).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return res, nil
}
model.Log.Errorf("GetCpByIds userId1:%d, userId2:%d, err:%v", userId1, userId2, err)
return nil, err return nil, err
} }
return res, nil return res, nil
......
...@@ -41,7 +41,9 @@ func AddCpDayRank(model *domain.Model, cpRelation CpRelation, score mysql.Num) ( ...@@ -41,7 +41,9 @@ func AddCpDayRank(model *domain.Model, cpRelation CpRelation, score mysql.Num) (
func PageCpDayRank(model *domain.Model, beginDate, endDate string, offset, limit int) []CpDayRank { func PageCpDayRank(model *domain.Model, beginDate, endDate string, offset, limit int) []CpDayRank {
var ranks []CpDayRank var ranks []CpDayRank
if err := model.DB().Table("cp_day_rank r").Joins("INNER JOIN cp_relation c ON c.id = r.cp_id"). if err := model.DB().Table("cp_day_rank r").Joins("INNER JOIN cp_relation c ON c.id = r.cp_id").
Where("r.date BETWEEN ? AND ?", beginDate, endDate).Group("cp_id").Select("cp_id,r.user_id1,r.user_id2,SUM(r.score) score"). Where("r.date BETWEEN ? AND ?", beginDate, endDate).
Where("cp_id not in (1581, 12651, 5171, 9191, 39131, 28801, 181, 35221)").
Group("cp_id").Select("cp_id,r.user_id1,r.user_id2,SUM(r.score) score").
Order("score DESC").Offset(offset).Limit(limit).Find(&ranks).Error; err != nil { Order("score DESC").Offset(offset).Limit(limit).Find(&ranks).Error; err != nil {
model.Log.Errorf("PageCpDayRank fail:%v", err) model.Log.Errorf("PageCpDayRank fail:%v", err)
} }
......
package diamond_m package diamond_m
import ( import (
"fmt"
"git.hilo.cn/hilo-common/_const/enum/diamond_e" "git.hilo.cn/hilo-common/_const/enum/diamond_e"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
...@@ -37,6 +38,11 @@ type DiamondAccountDetail struct { ...@@ -37,6 +38,11 @@ type DiamondAccountDetail struct {
diamondAccount *DiamondAccount `gorm:"-"` diamondAccount *DiamondAccount `gorm:"-"`
} }
func (DiamondAccountDetail) TableName() string {
month := time.Now().Format("200601")
return fmt.Sprintf("diamond_account_detail_%s", month)
}
// 粉钻详情 // 粉钻详情
type DiamondPinkAccountDetail struct { type DiamondPinkAccountDetail struct {
mysql.Entity mysql.Entity
...@@ -107,7 +113,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon ...@@ -107,7 +113,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
var count int64 var count int64
if diamondOperateSet.FrequencyDay == -1 { if diamondOperateSet.FrequencyDay == -1 {
if diamondOperateSet.FrequencyNum != -1 { if diamondOperateSet.FrequencyNum != -1 {
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{ diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId, UserId: diamondAccount.UserId,
OperateType: operateType, OperateType: operateType,
}).Count(&count) }).Count(&count)
...@@ -122,7 +128,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon ...@@ -122,7 +128,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
//一天的次数 //一天的次数
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{ diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId, UserId: diamondAccount.UserId,
OperateType: operateType, OperateType: operateType,
}).Where("created_time >= ? ", beginTime).Count(&count) }).Where("created_time >= ? ", beginTime).Count(&count)
...@@ -130,7 +136,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon ...@@ -130,7 +136,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, bizerr.DiamondFrequency return nil, bizerr.DiamondFrequency
} }
//终极拦截,利用 //终极拦截,利用
diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from diamond_account_detail d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )") diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from " + DiamondAccountDetail{}.TableName() + " d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )")
} }
//-1,代表值无效,由参数给与 //-1,代表值无效,由参数给与
......
...@@ -3,7 +3,6 @@ package diamond_m ...@@ -3,7 +3,6 @@ package diamond_m
import ( import (
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm" "gorm.io/gorm"
"hilo-user/domain/model"
"hilo-user/myerr" "hilo-user/myerr"
"strconv" "strconv"
) )
...@@ -32,7 +31,10 @@ func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional() ...@@ -32,7 +31,10 @@ func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional()
} }
//持久化diamondAccountDetail //持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil { //if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err) return myerr.WrapErr(err)
} }
//改变diamondAccount值 //改变diamondAccount值
......
...@@ -76,6 +76,18 @@ func ToTxGroupId(model *domain.Model, imGroupId string) (string, error) { ...@@ -76,6 +76,18 @@ func ToTxGroupId(model *domain.Model, imGroupId string) (string, error) {
return gi.TxGroupId, nil return gi.TxGroupId, nil
} }
func ToTxGroupIdMap(model *domain.Model, imGroupIds []string) (map[string]string, error) {
var res = make(map[string]string)
var rows []GroupInfo
if err := model.DB().Model(GroupInfo{}).Where("im_group_id in ?", imGroupIds).Find(&rows).Error; err != nil {
return res, err
}
for _, v := range rows {
res[v.ImGroupId] = v.TxGroupId
}
return res, nil
}
func ToImGroupId(model *domain.Model, txGroupId string) (string, error) { func ToImGroupId(model *domain.Model, txGroupId string) (string, error) {
if len(txGroupId) <= 0 { if len(txGroupId) <= 0 {
return "", nil return "", nil
......
...@@ -4,7 +4,6 @@ import ( ...@@ -4,7 +4,6 @@ import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-user/_const/redis_key/group_k" "hilo-user/_const/redis_key/group_k"
"hilo-user/myerr" "hilo-user/myerr"
"strconv" "strconv"
...@@ -12,7 +11,8 @@ import ( ...@@ -12,7 +11,8 @@ import (
"time" "time"
) )
const expireMinute = 60 * 60 * 12 // 3天
const expireMinute = 60 * 60 * 24 * 3
//获取在房间的用户 返回值:map,key:userId, value:groupUuid //获取在房间的用户 返回值:map,key:userId, value:groupUuid
func RoomLivingUserIdFilter(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]string, error) { func RoomLivingUserIdFilter(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]string, error) {
...@@ -25,7 +25,7 @@ func RoomLivingUserIdFilter(model *domain.Model, userIds []mysql.ID) (map[mysql. ...@@ -25,7 +25,7 @@ func RoomLivingUserIdFilter(model *domain.Model, userIds []mysql.ID) (map[mysql.
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
groupUserIdstrs, err := redisCli.GetRedis().ZRange(model, key, 0, -1).Result() groupUserIdstrs, err := model.RedisCluster.ZRange(model, key, 0, -1).Result()
if err != nil { if err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
...@@ -33,7 +33,6 @@ func RoomLivingUserIdFilter(model *domain.Model, userIds []mysql.ID) (map[mysql. ...@@ -33,7 +33,6 @@ func RoomLivingUserIdFilter(model *domain.Model, userIds []mysql.ID) (map[mysql.
resultUserSet := map[mysql.ID]string{} resultUserSet := map[mysql.ID]string{}
for i, _ := range groupUserIdstrs { for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i]) tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
mylogrus.MyLog.Debugf("RoomLivingUserIdFilter, analysisMemberStr %s, %d", tempGroupUid, userId)
if _, flag := userIdSet[userId]; flag { if _, flag := userIdSet[userId]; flag {
resultUserSet[userId] = tempGroupUid resultUserSet[userId] = tempGroupUid
...@@ -43,7 +42,7 @@ func RoomLivingUserIdFilter(model *domain.Model, userIds []mysql.ID) (map[mysql. ...@@ -43,7 +42,7 @@ func RoomLivingUserIdFilter(model *domain.Model, userIds []mysql.ID) (map[mysql.
} }
func ClearExpired(model *domain.Model, key string, expireSec int64) error { func ClearExpired(model *domain.Model, key string, expireSec int64) error {
return model.Redis.ZRemRangeByScore(model, key, return model.RedisCluster.ZRemRangeByScore(model, key,
"0", strconv.FormatInt(time.Now().Unix()-expireSec, 10)).Err() "0", strconv.FormatInt(time.Now().Unix()-expireSec, 10)).Err()
} }
......
...@@ -3,6 +3,7 @@ package invite_m ...@@ -3,6 +3,7 @@ package invite_m
import ( import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm" "gorm.io/gorm"
"time" "time"
) )
...@@ -84,3 +85,17 @@ func GetInviteApplyNumByType(model *domain.Model, gType int, beginTime, endTime ...@@ -84,3 +85,17 @@ func GetInviteApplyNumByType(model *domain.Model, gType int, beginTime, endTime
} }
return int(count), nil return int(count), nil
} }
// 今日已提交次数
func TodayInviteApplyCount(model *domain.Model, userId mysql.ID) (int64, error) {
start, end := utils.DayStartEnd(time.Now())
var count int64
if err := model.Db.Model(InviteApply{}).
Where("user_id = ?", userId).
Where("created_time >= ? and created_time <= ?", start.Format(utils.DATETIME_FORMAT), end.Format(utils.DATETIME_FORMAT)).
Count(&count).Error; err != nil {
return 0, err
}
// err == nil, record exists
return count, nil
}
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
// 获取推广员平台 // 获取推广员平台
func GetPromotionPlatforms(model *domain.Model) []string { func GetPromotionPlatforms(model *domain.Model) []string {
return []string{"Falla", "Yalla", "Whisper", "Ahlan", "Mashi", "YoYo", "Yoho", "Echo", "Hawa", "Yalla Ludo", "Hafla", return []string{"Falla", "Yalla", "Whisper", "Ahlan", "Mashi", "YoYo", "Yoho", "Echo", "Hawa", "Yalla Ludo", "Hafla",
"Imo", "Ola Party", "ShareChat", "Viya", "Hello Yo", "Bigo Live", "Hago"} "Imo", "Ola Party", "ShareChat", "Viya", "Hello Yo", "Bigo Live", "Hago", "Oye Talk", "Tiktok", "Bigo", "Mr7ba"}
} }
// 检查是否推广员 // 检查是否推广员
......
package recommend_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"time"
)
// 推荐用户送礼
type recommendUserGift struct {
SendUserId mysql.ID
SendUserDiamond mysql.Num
}
var recommendUserGiftKey = "recommendUserGiftKey"
var recommendUserGiftCache = gcache.New(1).LRU().Build()
// 推荐最近送礼的50人,最近12小时赠送礼物大于100k的用户
func SyncPastTop50SendGiftUsers(model *domain.Model) {
limitUserIds, _ := GetBillboardLimitUserList(model)
var res []recommendUserGift
if err := model.DB().Table("gift_operate g").Joins("INNER JOIN user u ON u.id = g.send_user_id").Select("send_user_id,SUM(send_user_diamond) send_user_diamond").
Where("u.avatar <> ''").
Where("g.created_time >= ?", time.Now().Add(-time.Hour*12)).
Where("send_user_id NOT in ?", limitUserIds).
Group("send_user_id").
Having("send_user_diamond > 100000").Order("send_user_diamond DESC").Limit(34).Find(&res).Error; err != nil {
model.Log.Errorf("GetPastTop50SendGiftUsers fail:%v", err)
}
_ = recommendUserGiftCache.Set(recommendUserGiftKey, res)
}
// 只从缓存中拿
func GetPastTop50SendGiftUsers(model *domain.Model) []recommendUserGift {
if data, err := recommendUserGiftCache.Get(recommendUserGiftKey); err == nil {
return data.([]recommendUserGift)
}
return []recommendUserGift{}
}
// 榜单黑名单
func GetBillboardLimitUserList(model *domain.Model) ([]uint64, error) {
var userIds []uint64
if err := model.Db.Table("billboard_limit_user").Select("user_id").Find(&userIds).Error; err != nil {
return nil, err
}
return userIds, nil
}
...@@ -61,8 +61,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui ...@@ -61,8 +61,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
} }
} }
} }
logger.Infof("maxGrade %+v", maxGrades) //logger.Infof("maxGrade %+v", maxGrades)
logger.Infof("maxMedalIds %+v", maxMedalIds) //logger.Infof("maxMedalIds %+v", maxMedalIds)
mIds := result mIds := result
result = make([]uint32, 0) result = make([]uint32, 0)
......
...@@ -52,6 +52,11 @@ func (u User) IsPrettyCode() bool { ...@@ -52,6 +52,11 @@ func (u User) IsPrettyCode() bool {
return u.Code != u.OriginCode return u.Code != u.OriginCode
} }
// 七天内注册
func (u User) IsNew() bool {
return time.Now().Sub(u.CreatedTime).Hours() < 24*7
}
//获取用户 //获取用户
func GetUser(model *domain.Model, id mysql.ID) (*User, error) { func GetUser(model *domain.Model, id mysql.ID) (*User, error) {
var user User var user User
......
...@@ -130,22 +130,31 @@ func CancelCpRelation(myCtx *mycontext.MyContext, myUserId uint64, externalId, l ...@@ -130,22 +130,31 @@ func CancelCpRelation(myCtx *mycontext.MyContext, myUserId uint64, externalId, l
return err return err
} }
// 自己没有cp了 // 我和对方是否是cp,且cp关系存在
myCp, err := cp_m.GetCp(model, myUserId) cpRelation, err := cp_m.GetCpByIds(model, myUserId, userRec.ID)
if err != nil {
return err
}
if myCp.Id == 0 {
return myerr.WrapErr(bizerr.InvalidParameter)
}
// 对方没有cp了
inviCp, err := cp_m.GetCp(model, userRec.ID)
if err != nil { if err != nil {
return err return err
} }
if inviCp.Id == 0 { if cpRelation.Id == 0 {
model.Log.Errorf("CancelCpRelation cp关系不存在 id1:%v, id2:%v", myUserId, userRec.ID)
return myerr.WrapErr(bizerr.InvalidParameter) return myerr.WrapErr(bizerr.InvalidParameter)
} }
//// 自己没有cp了
//myCp, err := cp_m.GetCp(model, myUserId)
//if err != nil {
// return err
//}
//if myCp.Id == 0 {
// return myerr.WrapErr(bizerr.InvalidParameter)
//}
//// 对方没有cp了
//inviCp, err := cp_m.GetCp(model, userRec.ID)
//if err != nil {
// return err
//}
//if inviCp.Id == 0 {
// return myerr.WrapErr(bizerr.InvalidParameter)
//}
// 是否有关于我的cp解除申请,且还未被处理 // 是否有关于我的cp解除申请,且还未被处理
myCancel, err := cp_m.GetCpCancelWithMe(model, user.ID, cp_e.CpCancel) myCancel, err := cp_m.GetCpCancelWithMe(model, user.ID, cp_e.CpCancel)
......
This diff is collapsed.
...@@ -14,7 +14,7 @@ import ( ...@@ -14,7 +14,7 @@ import (
func EventInit() { func EventInit() {
UserBagSendEvent() UserBagSendEvent()
CpGiftEvent() //CpGiftEvent()
CpSpaceVisitEvent() CpSpaceVisitEvent()
} }
......
...@@ -285,6 +285,7 @@ func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, ...@@ -285,6 +285,7 @@ func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID,
CountryIcon: StrNil(user.CountryIcon), CountryIcon: StrNil(user.CountryIcon),
Code: StrToString(&user.Code), Code: StrToString(&user.Code),
IsPrettyCode: user.IsPrettyCode(), IsPrettyCode: user.IsPrettyCode(),
IsNew: user.IsNew(),
IsVip: isVip, IsVip: isVip,
IsOfficialStaff: isOfficialStaff, IsOfficialStaff: isOfficialStaff,
VipExpireTime: vipExpireTime, VipExpireTime: vipExpireTime,
......
...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=47.244.34.27:6379 REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT] [JWT]
SECRET=hilo1632 SECRET=hilo1632
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
...@@ -3,6 +3,7 @@ package main ...@@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"git.hilo.cn/hilo-common/resource/consul" "git.hilo.cn/hilo-common/resource/consul"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-user/cron" "hilo-user/cron"
"hilo-user/domain/service/event_s" "hilo-user/domain/service/event_s"
"hilo-user/route" "hilo-user/route"
...@@ -17,6 +18,7 @@ const ( ...@@ -17,6 +18,7 @@ const (
func main() { func main() {
cron.Init() // 开启定时任务 cron.Init() // 开启定时任务
event_s.EventInit() // 注册事件(内部事件+mysql拟kafka) event_s.EventInit() // 注册事件(内部事件+mysql拟kafka)
redisCli.InitCluster() // redis集群
r := route.InitRouter() // 注册路由 r := route.InitRouter() // 注册路由
consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册 consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册
r.Run(fmt.Sprintf(":%d", PORT)) // 启动服务 r.Run(fmt.Sprintf(":%d", PORT)) // 启动服务
......
...@@ -27,10 +27,11 @@ var ( ...@@ -27,10 +27,11 @@ var (
// 群组 // 群组
GroupNotFound = myerr.NewBusinessCode(14001, "Group not found", myerr.BusinessData{}) // 找不到该群 GroupNotFound = myerr.NewBusinessCode(14001, "Group not found", myerr.BusinessData{}) // 找不到该群
CpAlreadyInvite = myerr.NewBusinessCode(50120, "Already invited", myerr.BusinessData{}) // 已经发送过邀请了 CpAlreadyInvite = myerr.NewBusinessCode(50120, "Already invited", myerr.BusinessData{}) // 已经发送过邀请了
CpHaveCancelNoDeal = myerr.NewBusinessCode(50121, "You have a cancel apply", myerr.BusinessData{}) // 有接触申请需要处理 CpHaveCancelNoDeal = myerr.NewBusinessCode(50121, "You have a cancel apply", myerr.BusinessData{}) // 有接触申请需要处理
InviteApplyNoPermission = myerr.NewBusinessCode(50122, "This user does not have invitation permission", myerr.BusinessData{}) // 该用户没有邀请权限 InviteApplyNoPermission = myerr.NewBusinessCode(50122, "This user does not have invitation permission", myerr.BusinessData{}) // 该用户没有邀请权限
InviteApplyAlreadyInvited = myerr.NewBusinessCode(50123, "Already invited by someone else", myerr.BusinessData{}) // 已经被别人邀请了 InviteApplyAlreadyInvited = myerr.NewBusinessCode(50123, "Already invited by someone else", myerr.BusinessData{}) // 已经被别人邀请了
InviteApplyCodeInvalid = myerr.NewBusinessCode(50124, "user id invalid", myerr.BusinessData{}) // 邀请人用户id错误 InviteApplyCodeInvalid = myerr.NewBusinessCode(50124, "user id invalid", myerr.BusinessData{}) // 邀请人用户id错误
InviteApplyNewCodeInvalid = myerr.NewBusinessCode(50125, "user id invalid", myerr.BusinessData{}) // 被邀请人用户id错误 InviteApplyNewCodeInvalid = myerr.NewBusinessCode(50125, "user id invalid", myerr.BusinessData{}) // 被邀请人用户id错误
InviteApplyTimes = myerr.NewBusinessCode(50126, "Your application today has reached the upper limit, please wait for tomorrow to continue the application", myerr.BusinessData{}) // 今日邀请次数太多
) )
[DATABASE] [DATABASE]
MYSQL_HOST=ua4papc3hmgqf351pbej-rw4rm.rwlb.dubai.rds.aliyuncs.com MYSQL_HOST=ua4papc3hmgqf351pbej-rw4rm.rwlb.dubai.rds.aliyuncs.com
MYSQL_USERNAME=nextvideo MYSQL_USERNAME=hilo_user
MYSQL_PASSWORD=ihlUwI4nhi9W88MI MYSQL_PASSWORD=ihlUwI4nhi9W88MI
MYSQL_DB=hilo MYSQL_DB=hilo
[DATABASECODE] [DATABASECODE]
...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=r-eb3btxn8vfdsuwdbuf.redis.dubai.rds.aliyuncs.com:6379 REDIS_HOST=r-eb3btxn8vfdsuwdbuf.redis.dubai.rds.aliyuncs.com:6379
REDIS_PASSWORD= REDIS_PASSWORD=
REDIS_CLUSTER_HOST=r-eb3yt6k8zgxs62kjjs.redis.dubai.rds.aliyuncs.com:6379
REDIS_CLUSTER_PASSWORD=
[JWT] [JWT]
SECRET=hilo1504 SECRET=hilo1504
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
...@@ -81,8 +81,8 @@ func CpRank(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -81,8 +81,8 @@ func CpRank(c *gin.Context) (*mycontext.MyContext, error) {
for i, rank := range ranks { for i, rank := range ranks {
response = append(response, cp_cv.CvCpRank{ response = append(response, cp_cv.CvCpRank{
CpId: rank.CpId, CpId: rank.CpId,
User1: userBase[rank.UserId1], User1: user_cv.UserBaseToUserLittle(userBase[rank.UserId1]),
User2: userBase[rank.UserId2], User2: user_cv.UserBaseToUserLittle(userBase[rank.UserId2]),
Score: rank.Score, Score: rank.Score,
Ranking: fmt.Sprintf("%d", i+1+offset), Ranking: fmt.Sprintf("%d", i+1+offset),
CpLevel: cp_cv.CvCpLevel{ CpLevel: cp_cv.CvCpLevel{
...@@ -143,8 +143,8 @@ func CpTop3(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -143,8 +143,8 @@ func CpTop3(c *gin.Context) (*mycontext.MyContext, error) {
if queryType == "day" { if queryType == "day" {
response.Day = append(response.Day, cp_cv.CvCpRank{ response.Day = append(response.Day, cp_cv.CvCpRank{
CpId: rank.CpId, CpId: rank.CpId,
User1: userBase[rank.UserId1], User1: user_cv.UserBaseToUserLittle(userBase[rank.UserId1]),
User2: userBase[rank.UserId2], User2: user_cv.UserBaseToUserLittle(userBase[rank.UserId2]),
Score: rank.Score, Score: rank.Score,
Ranking: fmt.Sprintf("%d", i+1+offset), Ranking: fmt.Sprintf("%d", i+1+offset),
CpLevel: cp_cv.CvCpLevel{ CpLevel: cp_cv.CvCpLevel{
...@@ -154,8 +154,8 @@ func CpTop3(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -154,8 +154,8 @@ func CpTop3(c *gin.Context) (*mycontext.MyContext, error) {
} else { } else {
response.Week = append(response.Week, cp_cv.CvCpRank{ response.Week = append(response.Week, cp_cv.CvCpRank{
CpId: rank.CpId, CpId: rank.CpId,
User1: userBase[rank.UserId1], User1: user_cv.UserBaseToUserLittle(userBase[rank.UserId1]),
User2: userBase[rank.UserId2], User2: user_cv.UserBaseToUserLittle(userBase[rank.UserId2]),
Score: rank.Score, Score: rank.Score,
Ranking: fmt.Sprintf("%d", i+1+offset), Ranking: fmt.Sprintf("%d", i+1+offset),
CpLevel: cp_cv.CvCpLevel{ CpLevel: cp_cv.CvCpLevel{
...@@ -224,10 +224,10 @@ func CpMy(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -224,10 +224,10 @@ func CpMy(c *gin.Context) (*mycontext.MyContext, error) {
Score: scores, Score: scores,
} }
if relation.UserId1 > 0 { if relation.UserId1 > 0 {
response.User1 = userBases[relation.UserId1] response.User1 = user_cv.UserBaseToUserLittle(userBases[relation.UserId1])
} }
if relation.UserId2 > 0 { if relation.UserId2 > 0 {
response.User2 = userBases[relation.UserId2] response.User2 = user_cv.UserBaseToUserLittle(userBases[relation.UserId2])
response.Ranking = "30+" response.Ranking = "30+"
ranks := cp_m.PageCpDayRank(model, beginDate, endDate, 0, 30) ranks := cp_m.PageCpDayRank(model, beginDate, endDate, 0, 30)
for i, rank := range ranks { for i, rank := range ranks {
......
...@@ -43,12 +43,25 @@ func InviteApply(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -43,12 +43,25 @@ func InviteApply(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil { if err != nil {
return myCtx, err return myCtx, err
} }
model := domain.CreateModelContext(myCtx)
// 每日最多提交10次
noLimitTimesMap := map[uint64]struct{}{1770691: {}, 2264431: {}, 7283111: {}}
if _, ok := noLimitTimesMap[myUserId]; !ok {
// 今日提交次数
times, err := invite_m.TodayInviteApplyCount(model, myUserId)
if err != nil {
model.Log.Errorf("InviteApply myUserId:%v, err:%v", myUserId, err)
return myCtx, err
}
if times >= 15 {
return myCtx, bizerr.InviteApplyTimes
}
}
var param paramStr var param paramStr
if err := c.ShouldBind(&param); err != nil { if err := c.ShouldBind(&param); err != nil {
return myCtx, err return myCtx, err
} }
model := domain.CreateModelContext(myCtx)
// 平台是否填写正确 // 平台是否填写正确
platforms := promotion_m.GetPromotionPlatforms(model) platforms := promotion_m.GetPromotionPlatforms(model)
var existsPlatform bool var existsPlatform bool
...@@ -72,6 +85,9 @@ func InviteApply(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -72,6 +85,9 @@ func InviteApply(c *gin.Context) (*mycontext.MyContext, error) {
model.Log.Errorf("InviteApply param:%v", param) model.Log.Errorf("InviteApply param:%v", param)
return myCtx, bizerr.InviteApplyCodeInvalid return myCtx, bizerr.InviteApplyCodeInvalid
} }
//if user.ID != myUserId { //只能自己提交
// return myCtx, bizerr.InvalidParameter
//}
if newUser.ID == 0 || user.ID == 0 { if newUser.ID == 0 || user.ID == 0 {
model.Log.Errorf("InviteApply param:%v", param) model.Log.Errorf("InviteApply param:%v", param)
return myCtx, bizerr.InvalidParameter return myCtx, bizerr.InvalidParameter
...@@ -215,6 +231,8 @@ func InviteApplyList(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -215,6 +231,8 @@ func InviteApplyList(c *gin.Context) (*mycontext.MyContext, error) {
Avatar: users[v.NewUserId].Avatar, Avatar: users[v.NewUserId].Avatar,
ExternalId: users[v.NewUserId].ExternalId, ExternalId: users[v.NewUserId].ExternalId,
Reason: v.Reason, Reason: v.Reason,
Country: users[v.NewUserId].Country,
PlatformId: v.PlatformId,
}) })
} }
...@@ -229,7 +247,7 @@ func InviteApplyList(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -229,7 +247,7 @@ func InviteApplyList(c *gin.Context) (*mycontext.MyContext, error) {
func PromotionPlatform(c *gin.Context) (*mycontext.MyContext, error) { func PromotionPlatform(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys) myCtx := mycontext.CreateMyContext(c.Keys)
resp.ResponseOk(c, []string{"Falla", "Yalla", "Whisper", "Ahlan", "Mashi", "YoYo", "Yoho", "Echo", "Hawa", resp.ResponseOk(c, []string{"Falla", "Yalla", "Whisper", "Ahlan", "Mashi", "YoYo", "Yoho", "Echo", "Hawa",
"Yalla Ludo", "Hafla", "Imo", "Ola Party", "ShareChat", "Viya", "Hello Yo", "Bigo Live", "Hago"}) "Yalla Ludo", "Hafla", "Imo", "Ola Party", "ShareChat", "Viya", "Hello Yo", "Bigo Live", "Hago", "Oye Talk", "Tiktok", "Bigo", "Mr7ba"})
return myCtx, nil return myCtx, nil
} }
......
package recommend_r
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/gin-gonic/gin"
"hilo-user/cv/user_cv"
"hilo-user/domain/model/group_m"
"hilo-user/domain/model/recommend_m"
"hilo-user/domain/model/user_m"
"hilo-user/resp"
)
type RecommendUser struct {
User *user_cv.UserTiny `json:"user"`
CurrentRoom string `json:"currentRoom"` // 当前用户所在房间(产品叫“群组”)
}
// @Tags 用户推荐
// @Summary 推荐最近送礼的50人,最近12小时赠送礼物大于100k的用户
// @Param token header string true "token"
// @Success 200 {object} []RecommendUser
// @Router /v1/recommend/user/gift [get]
func UserRecommendGift(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
model := domain.CreateModelContext(myContext)
// 获取推荐
recommendUser := recommend_m.GetPastTop50SendGiftUsers(model)
var response = make([]RecommendUser, 0)
if len(recommendUser) <= 0 {
resp.ResponseOk(c, response)
return myContext, nil
}
var userIds []mysql.ID
for _, v := range recommendUser {
userIds = append(userIds, v.SendUserId)
}
users, err := user_m.GetUserMapByIds(model, userIds)
if err != nil {
return myContext, err
}
rooms, err := group_m.RoomLivingUserIdFilter(model, userIds)
if err != nil {
return nil, err
} else if len(rooms) > 0 {
// to txGroupIds
var imGroupIds []string
for _, imGroupId := range rooms {
imGroupIds = append(imGroupIds, imGroupId)
}
txGroupIdsMap, _ := group_m.ToTxGroupIdMap(model, imGroupIds)
for uid, room := range rooms {
rooms[uid] = txGroupIdsMap[room]
}
}
for _, v := range recommendUser {
response = append(response, RecommendUser{user_cv.UserToTiny(users[v.SendUserId]), rooms[v.SendUserId]})
}
resp.ResponseOk(c, response)
return myContext, nil
}
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"hilo-user/resp" "hilo-user/resp"
"hilo-user/route/cp_r" "hilo-user/route/cp_r"
"hilo-user/route/invite_r" "hilo-user/route/invite_r"
"hilo-user/route/recommend_r"
"hilo-user/route/user_r" "hilo-user/route/user_r"
) )
...@@ -53,12 +54,18 @@ func InitRouter() *gin.Engine { ...@@ -53,12 +54,18 @@ func InitRouter() *gin.Engine {
//cp.GET("/relation/detail", wrapper(cp_r.CpDetailPage)) //cp.GET("/relation/detail", wrapper(cp_r.CpDetailPage))
cp.GET("/im/check", wrapper(cp_r.CheckCpImExpire)) cp.GET("/im/check", wrapper(cp_r.CheckCpImExpire))
} }
recommend := v1.Group("recommend")
{
recommend.GET("/user/gift", wrapper(recommend_r.UserRecommendGift))
}
userV2 := v2.Group("/user") userV2 := v2.Group("/user")
{ {
userV2.POST("/invite/apply", wrapper(invite_r.InviteApply)) userV2.POST("/invite/apply", wrapper(invite_r.InviteApply))
userV2.GET("/invite/apply", wrapper(invite_r.InviteApplyList)) userV2.GET("/invite/apply", wrapper(invite_r.InviteApplyList))
userV2.GET("/invite/platform", wrapper(invite_r.PromotionPlatform)) userV2.GET("/invite/platform", wrapper(invite_r.PromotionPlatform))
userV2.GET("/invite/period", wrapper(invite_r.AgentPeriod)) userV2.GET("/invite/period", wrapper(invite_r.AgentPeriod))
userV2.GET("/detail/room", EncryptHandle, wrapper(user_r.GetUserDetailInRoom))
} }
inner := r.Group("/inner") inner := r.Group("/inner")
inner.Use(ExceptionHandle, LoggerHandle) inner.Use(ExceptionHandle, LoggerHandle)
...@@ -69,7 +76,8 @@ func InitRouter() *gin.Engine { ...@@ -69,7 +76,8 @@ func InitRouter() *gin.Engine {
innerUser.GET("/cp", wrapper(user_r.GetUserCp)) innerUser.GET("/cp", wrapper(user_r.GetUserCp))
innerUser.GET("/cpRelations", wrapper(user_r.MGetUserCpRelation)) innerUser.GET("/cpRelations", wrapper(user_r.MGetUserCpRelation))
innerUser.GET("/cp/pair", wrapper(user_r.GetUserCpPair)) innerUser.GET("/cp/pair", wrapper(user_r.GetUserCpPair))
innerUser.GET("/cp/entryEffect", wrapper(user_r.GetUserCpEntryEffect)) // 获取cp进场特效信息,高频接口,需要额外处理 innerUser.GET("/cp/entryEffect", wrapper(user_r.GetUserCpEntryEffect)) // 获取cp进场特效信息,高频接口,需要额外处理
innerUser.GET("/svipNobleLevel", wrapper(user_r.MGetUserSvipNobleLevel)) // 获取用户svip/noble/level等信息
} }
// 道具相关 // 道具相关
innerProp := inner.Group("/prop") innerProp := inner.Group("/prop")
......
...@@ -4,9 +4,11 @@ import ( ...@@ -4,9 +4,11 @@ import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/rpc"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"hilo-user/_const/enum/cp_e" "hilo-user/_const/enum/cp_e"
"hilo-user/cv/cp_cv" "hilo-user/cv/cp_cv"
"hilo-user/cv/noble_cv"
"hilo-user/cv/user_cv" "hilo-user/cv/user_cv"
"hilo-user/domain/cache/user_c" "hilo-user/domain/cache/user_c"
"hilo-user/domain/model/bag_m" "hilo-user/domain/model/bag_m"
...@@ -56,6 +58,62 @@ func MGetUserLevels(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -56,6 +58,62 @@ func MGetUserLevels(c *gin.Context) (*mycontext.MyContext, error) {
return myCtx, nil return myCtx, nil
} }
type MGetUserSvipVipLevelReq struct {
Ids []mysql.ID `form:"ids" binding:"required"`
}
// @Tags 用户-内部
// @Summary 批量获取用户等级
// @Param ids query string true "用户id,如:ids=1&ids=2&ids=3"
// @Success 200 {object} user_cv.CvUserDetail
// @Router /inner/user/svipNobleLevel [get]
func MGetUserSvipNobleLevel(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
var model = domain.CreateModelContext(myCtx)
var req MGetUserLevelReq
if err := c.ShouldBindQuery(&req); err != nil {
return myCtx, err
}
wealthGrade, err := user_m.MGetWealthGrade(model, req.Ids)
if err != nil {
return myCtx, err
}
charmGrade, err := user_m.MGetCharmGrade(model, req.Ids)
activeGrade, err := user_m.MGetActiveGrade(model, req.Ids)
nobleLevel, err := noble_m.BatchGetNobleLevel(model, req.Ids)
svip, err := rpc.MGetUserSvip(model, req.Ids)
users, err := user_m.GetUserMapByIds(model, req.Ids)
response := make(map[uint64]user_cv.CvUserDetail)
for _, userId := range req.Ids {
user := users[userId]
response[userId] = user_cv.CvUserDetail{
CvUserBase: user_cv.CvUserBase{
Id: &user.ID,
Avatar: &user.Avatar,
ExternalId: &user.ExternalId,
Nick: &user.Nick,
Sex: &user.Sex,
Country: &user.Country,
CountryIcon: &user.CountryIcon,
Code: &user.Code,
Birthday: &user.Birthday,
Svip: rpc.CvSvip{
SvipLevel: svip[userId].SvipLevel,
},
Noble: noble_cv.CvNoble{
Level: nobleLevel[userId],
},
},
WealthUserGrade: wealthGrade[userId],
CharmUserGrade: charmGrade[userId],
ActivityUserGrade: activeGrade[userId],
}
}
resp.ResponseOk(c, response)
return myCtx, nil
}
type GetUserBagReq struct { type GetUserBagReq struct {
BagId mysql.ID `form:"bagId" binding:"required"` BagId mysql.ID `form:"bagId" binding:"required"`
} }
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"git.hilo.cn/hilo-common/resource/redisCli" "git.hilo.cn/hilo-common/resource/redisCli"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"hilo-user/_const/redis_key/user_k" "hilo-user/_const/redis_key/user_k"
"hilo-user/cv/user_cv"
"hilo-user/domain/model/group_m" "hilo-user/domain/model/group_m"
"hilo-user/domain/model/tim_m" "hilo-user/domain/model/tim_m"
"hilo-user/domain/service/user_s" "hilo-user/domain/service/user_s"
...@@ -106,3 +107,64 @@ func UserDetailByExternalId(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -106,3 +107,64 @@ func UserDetailByExternalId(c *gin.Context) (*mycontext.MyContext, error) {
resp.ResponseOk(c, cvUserDetail) resp.ResponseOk(c, cvUserDetail)
return myContext, nil return myContext, nil
} }
// @Tags 用户
// @Summary 房间内获取用户信息
// @Param userExternalId query string true "userExternalId"
// @Param groupId query string false "群组id,当传了该id,则返回该用户在该群组的身份"
// @Success 200 {object} user_cv.CvUserDetailRoom
// @Router /v2/user/detail/room [get]
func GetUserDetailInRoom(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, lang, err := req.GetUserIdLang(c, myContext)
if err != nil {
return myContext, err
}
otherUserId, err := req.ToUserId(myContext, c.Query("userExternalId"))
if err != nil {
return nil, err
}
model := domain.CreateModelContext(myContext)
imGroupId := c.Query("groupId")
if imGroupId != "" {
imGroupId, err = group_m.ToImGroupId(model, imGroupId)
if err != nil {
return myContext, err
}
}
cvUserDetail, err := user_s.NewUserService(myContext).GetUserDetail(otherUserId, userId, lang)
if err != nil {
return myContext, err
}
if imGroupId != "" {
cvUserDetail.GroupRole, err = group_m.GetGroupRoleById(model, imGroupId, otherUserId)
if err != nil {
return myContext, err
}
}
if cvUserDetail != nil {
// 检查是否需要同步
if n, err := redisCli.GetRedis().Exists(model, user_k.GetKeySyncTimHilo(userId)).Result(); err == nil {
if n == 0 {
// FIXME:转异步执行
err = tim_m.FlushHiloInfo(*cvUserDetail.ExternalId, cvUserDetail.IsVip, cvUserDetail.IsPrettyCode,
cvUserDetail.Medals, cvUserDetail.MyGroupPowerName, cvUserDetail.Noble.Level)
if err == nil {
redisCli.GetRedis().Set(model, user_k.GetKeySyncTimHilo(userId), "1", time.Minute)
} else {
model.Log.Info("UserBaseByExternalId, FlushHiloInfo failed: ", err)
}
} else {
model.Log.Info("UserDetailByExternalId, no need to sync yet: ", userId)
}
} else {
model.Log.Info("UserDetailByExternalId, check KeySyncTimHilo failed", err)
}
}
resp.ResponseOk(c, user_cv.CvUserDetailToCvUserDetailRoom(cvUserDetail))
return myContext, nil
}