...
 
Commits (72)
package country_e
import "git.hilo.cn/hilo-common/resource/mysql"
// 国家角色
type CountryMgrRole mysql.Type
const (
// 国家管理员
CountryMgrManager CountryMgrRole = 1
// 国家助理
CountryMgrAssistant CountryMgrRole = 2
)
// 角色权限
type ManagerPrivilegeItem mysql.Type
const (
// 重置用户头像
ManagerPrivilegeItemResetAvatar ManagerPrivilegeItem = 1
// 重置群组头像
ManagerPrivilegeItemResetFaceUrl ManagerPrivilegeItem = 2
// 删除广播
ManagerPrivilegeItemDeleteGlobalBroadcast ManagerPrivilegeItem = 3
)
package groupPower_e
import "git.hilo.cn/hilo-common/resource/mysql"
//国家势力状态
type GroupPowerStatus = mysql.Type
const (
//上架
GroupPowerUserHas GroupPowerStatus = 1
//未上架
GroupPowerUserNo GroupPowerStatus = 2
//解散
GroupPowerDissolve GroupPowerStatus = 3
)
//国家势力用户角色
type GroupPowerUserRole = mysql.Type
const (
// 普通用户
GroupPowerUserRoleUser GroupPowerUserRole = 1
// 势力主
GroupPowerUserRoleMgr GroupPowerUserRole = 2
// 管理员
GroupPowerUserRoleAdmin GroupPowerUserRole = 3
)
//国家势力日志操作类型
type GroupPowerUserLogType = mysql.Type
const (
//加入
GroupPowerUserLogTypeUserJoin GroupPowerUserLogType = 1
//用户自己离开
GroupPowerUserLogTypeUserLeave GroupPowerUserLogType = 2
//运营平台赋予管理者
GroupPowerUserLogTypeOwerJoin GroupPowerUserLogType = 3
//管理人让用户离开
GroupPowerUserLogTypeMgrLeave GroupPowerUserLogType = 4
//管理人解散
GroupPowerUserLogDissolve GroupPowerUserLogType = 5
)
type GroupPowerDiamondLogType = mysql.Type
const (
//群组原因加入
GroupPowerDiamondLogTypeByGroup GroupPowerDiamondLogType = 1
//群主原因加入
GroupPowerDiamondLogTypeByGroupOwer GroupPowerDiamondLogType = 2
)
type PowerSupportAwardState = uint
const (
PowerSuppportNo PowerSupportAwardState = 0 // 未达到要求
PowerSuppportAwarded PowerSupportAwardState = 1 // 已经领取
PowerSuppportWaiting PowerSupportAwardState = 2 // 待领取
)
package group_e
import "git.hilo.cn/hilo-common/resource/mysql"
type MsgStatusGroupUser = mysql.Type
const (
//正常: 灰点+震动
NormalMsgStatusGroupUser MsgStatusGroupUser = 0
//静音:灰点
MuteMsgStatusGroupUser MsgStatusGroupUser = 1
//免打扰:什么也没有
DoNotDisturbMsgStatusGroupUser MsgStatusGroupUser = 2
OverseaRoom = 1
LocalRoom = 2
)
// 公屏消息
type TypePublicScreenMsg = mysql.Type
const (
UserJoinPublicScreenMsg TypePublicScreenMsg = 1 // 加入群组
UserKickPublicScreenMsg TypePublicScreenMsg = 2 // 踢出房间
UserBannedPublicScreenMsg TypePublicScreenMsg = 3 // 拉黑用户
RoleAssignedPublicScreenMsg TypePublicScreenMsg = 4 // 添加角色
RoleRemovedPublicScreenMsg TypePublicScreenMsg = 5 // 移除角色
ClientSendMsgLocal TypePublicScreenMsg = 6 // 客户端占用
RollDiceMsg TypePublicScreenMsg = 7 // 掷骰子结果
GroupGiftMsg TypePublicScreenMsg = 8 //全服礼物
GroupSupportH5 TypePublicScreenMsg = 9 //群组支持H5
JumpMessage TypePublicScreenMsg = 10 // 可跳转的公屏消息
RocketAwardMsg TypePublicScreenMsg = 11 // 火箭获奖消息
LockyboxAwardMsg TypePublicScreenMsg = 12 // 幸运盒子公屏中奖
FruitMachineAwardMsg TypePublicScreenMsg = 13 // 水果机中奖
EnterRoomMsg TypePublicScreenMsg = 14 // 用户进入房间
)
// 信令消息(不显示公屏工,不记入消息历史,不影响未读数)
type TypeSignalMsg = mysql.Type
const (
GroupEditProfileSignal TypeSignalMsg = 1
GroupRoleChangeSignal TypeSignalMsg = 2
GroupMicChangeSignal TypeSignalMsg = 3 //保留
GroupMsgBannedSignal TypeSignalMsg = 4
GroupMemberRemoveSignal TypeSignalMsg = 5
GroupGiftSignal TypeSignalMsg = 6 //礼物
GroupMicInSignal TypeSignalMsg = 7
GroupMicOutSignal TypeSignalMsg = 8
GroupMicLockSignal TypeSignalMsg = 9
GroupMicUnLockSignal TypeSignalMsg = 10
GroupMicSpeechOpenSignal TypeSignalMsg = 11
GroupMicSpeechCloseSignal TypeSignalMsg = 12
GroupKickOut TypeSignalMsg = 13 //保留
GroupSocketMicOutSignal TypeSignalMsg = 14 //保留
GroupInviteMicInSignal TypeSignalMsg = 15 //邀请上麦保留
GroupInSignal TypeSignalMsg = 16 //进入房间,进房特效
GroupMicEmoji TypeSignalMsg = 17 //麦上表情
GroupLuckyWheel TypeSignalMsg = 18 //转盘的通知信令
GroupOutSignal TypeSignalMsg = 19 //离开房间
GroupRocketState TypeSignalMsg = 20 //火箭状态变化
GroupOnlineUser TypeSignalMsg = 21 //房间在线用户信息
GroupMicChange TypeSignalMsg = 22 //房间麦位上的变量
GroupMemberInvite TypeSignalMsg = 23 //房间-邀请用户成为会员
GroupRoleChange TypeSignalMsg = 24 //房间-用户群组身份变化
GroupClearScreen TypeSignalMsg = 25 //房间-清理公屏
GroupRoomGiftSignal TypeSignalMsg = 26 //全房间送礼物
)
//群组麦位数量类型
type GroupMicNumType = mysql.Type
const (
OneMicNumType GroupMicNumType = 5
TwoMicNumType GroupMicNumType = 10
ThreeMicNumType GroupMicNumType = 3
FourMicNumType GroupMicNumType = 4
SixMicNumType GroupMicNumType = 6
SevenMicNumType GroupMicNumType = 7
EightMicNumType GroupMicNumType = 8
NineMicNumType GroupMicNumType = 9
ElevenMicNumType GroupMicNumType = 11
TwelveMicNumType GroupMicNumType = 12
ThirteenMicNumType GroupMicNumType = 13
FourteenMicNumType GroupMicNumType = 14
FifteenMicNumType GroupMicNumType = 15
SixteenMicNumType GroupMicNumType = 16
SeventeenMicNumType GroupMicNumType = 17
EighteenMicNumType GroupMicNumType = 18
NineteenMicNumType GroupMicNumType = 19
TwentyMicNumType GroupMicNumType = 20
//5个麦位
FiveMicNumType GroupMicNumType = 1
//10个麦位
TenMicNumType GroupMicNumType = 2
//
SUPPORT_LEVEL_BOUNDARY_HOUR = 0
SUPPORT_LEVEL_PERIOD_DAY = 7
)
package user_e
import "git.hilo.cn/hilo-common/resource/mysql"
import (
"git.hilo.cn/hilo-common/resource/mysql"
)
type ThirdPartyType = mysql.Type
......@@ -12,6 +14,17 @@ const (
WeChat ThirdPartyType = 5
)
type CountType mysql.Type
const (
//我喜欢的数量
CountTypeLike CountType = 1
//我拉黑的数量
CountTypeBlock CountType = 2
//我被喜欢的次数
CountTypeLikeMe CountType = 3
)
type UserStatus mysql.Type
const (
......@@ -24,8 +37,33 @@ const (
type UserVipType = mysql.Type
const (
//
UserMan = 1
//
UserWomen = 2
//购买
UserVipTypeBuy UserVipType = 1
//赠送
UserVipTypeGive UserVipType = 2
)
type UserLikeOperateType = mysql.Type
const (
//增加喜欢
LikeAdd UserLikeOperateType = 1
//取消喜欢
LikeCancel UserLikeOperateType = 2
)
type UserLikeSceneType = mysql.Type
const (
Match UserLikeSceneType = 1
Video UserLikeSceneType = 2
)
type InteractionType = mysql.Type
const (
InteractPrivateGift InteractionType = 1
InteractVideo InteractionType = 2
)
package group_k
//在房间的人
const groupRoomLiving = "group_room_living"
func GetPrefixGroupRoomLiving() string {
return groupRoomLiving
}
......@@ -4,6 +4,8 @@ import (
"fmt"
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-user/_const/redis_key"
"strconv"
"strings"
)
const (
......@@ -28,3 +30,9 @@ func GetExternalIdToUidKey(externalId mysql.Str) string {
func GetCodeToUidKey(code mysql.Str) string {
return redis_key.ReplaceKey(UserCodeToUIdStr, code)
}
const syncTimHiloLock = "sync_tim_hilo_{userId}"
func GetKeySyncTimHilo(userId uint64) string {
return strings.Replace(syncTimHiloLock, "{userId}", strconv.FormatUint(userId, 10), -1)
}
package cp_corn
package cp_cron
import (
"git.hilo.cn/hilo-common/_const/enum/diamond_e"
......@@ -36,6 +36,7 @@ func CpInviteCancelInit() {
return
}
for _, v := range inviteList {
model := domain.CreateModelContext(model.MyContext)
model.Log.Infof("CpInviteCancelInit invite:%+v", v)
err = model.Transaction(func(model *domain.Model) error {
// 更新邀请记录
......@@ -54,7 +55,7 @@ func CpInviteCancelInit() {
})
if err != nil {
model.Log.Errorf("CpInviteCancelInit invite:%+v, err:%v", v, err)
return
continue
}
time.Sleep(time.Millisecond * 10)
}
......@@ -66,6 +67,7 @@ func CpInviteCancelInit() {
return
}
for _, v := range cancelList {
model := domain.CreateModelContext(model.MyContext)
model.Log.Infof("CpInviteCancelInit cancel:%+v", v)
err = model.Transaction(func(model *domain.Model) error {
// 更新解除记录
......@@ -84,7 +86,7 @@ func CpInviteCancelInit() {
})
if err != nil {
model.Log.Errorf("CpInviteCancelInit cancel:%+v, err:%v", v, err)
return
continue
}
time.Sleep(time.Millisecond * 10)
}
......
......@@ -2,18 +2,20 @@ package cron
import (
"git.hilo.cn/hilo-common/resource/config"
"hilo-user/corn/cp_corn"
"hilo-user/cron/cp_cron"
"hilo-user/cron/gift_cron"
"hilo-user/cron/user_cron"
)
func Init() {
user_cron.SyncGiftRecommendUsers() // 同步送礼推荐用户,多进程都需要执行
if !config.IsMaster() {
return
}
gift_cron.SendGiftEventInit() // 礼物消息
gift_cron.GiftRemark() // 礼物消息补偿
//gift_cron.SendGiftEventInit() // 礼物消息
//gift_cron.GiftRemark() // 礼物消息补偿
gift_cron.SendGiftEvent() // 送礼事件
cp_cron.ClearCpExpire() // 清理过期cp
cp_cron.CpAnniversaryNotice() // cp纪念日
cp_corn.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()
}
package cp_cv
import "hilo-user/cv/user_cv"
import (
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/user_cv"
)
// cp信息
type CvCp struct {
......@@ -18,3 +21,10 @@ type CvCpRelation struct {
CpUserId uint64 `json:"cpUserId"`
CpUserAvatar string `json:"cpUserAvatar,omitempty"`
}
// cp进场特效信息
type CvCpEntryEffect struct {
CpLevel cp_e.CpLevel `json:"cpLevel"`
CpUserAvatar string `json:"cpUserAvatar"`
CpEntryEffect bool `json:"cpEntryEffect"`
}
......@@ -6,12 +6,12 @@ import (
)
type CvCpRank struct {
CpId uint64 `json:"cpId"` // cpId
User1 *user_cv.CvUserBase `json:"user1"` // user1
User2 *user_cv.CvUserBase `json:"user2,omitempty"` // user2
Score uint32 `json:"score"` // 分值
CpLevel CvCpLevel `json:"cpLevel"` // cp等级
Ranking string `json:"ranking"` // 排名
CpId uint64 `json:"cpId"` // cpId
User1 *user_cv.CvUserLittle `json:"user1"` // user1
User2 *user_cv.CvUserLittle `json:"user2,omitempty"` // user2
Score uint32 `json:"score"` // 分值
CpLevel CvCpLevel `json:"cpLevel"` // cp等级
Ranking string `json:"ranking"` // 排名
}
type CvCpAchievement struct {
......
package invite_cv
import "git.hilo.cn/hilo-common/resource/mysql"
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"` // 贵族等级
}
type InviteApplyRes struct {
List []*InviteApply `json:"list"`
NumList []*InviteApplyNumRes `json:"numList"`
MyCode string `json:"myCode"`
}
type InviteApply struct {
NewUserCode string `json:"newUserCode"`
Platform string `json:"platform"`
Recharge string `json:"recharge"`
UserCode string `json:"userCode"`
CreateUnix int64 `json:"createUnix"`
Level string `json:"level"`
Status uint8 `json:"status"` // 状态0.未审核1.已通过2.已拒绝
Avatar string `json:"avatar"`
ExternalId string `json:"externalId"`
Reason int `json:"reason"` // 1.已申请2.待审核3.已通过4.已拒绝"
Country string `json:"country"`
PlatformId string `json:"platformId"`
}
type InviteApplyNumRes struct {
Type int `json:"type"` // 1.已申请2.待审核3.已通过4.已拒绝"
Num int `json:"num"`
}
type AgentPeriod struct {
Week []AgentPeriodWeek `json:"week"`
}
type AgentPeriodWeek struct {
StartDate string `json:"startDate"`
EndDate string `json:"endDate"`
}
......@@ -95,7 +95,7 @@ func GetPropertyById(resPropertyId mysql.ID) (CvProperty, error) {
}, nil
}
func GetPropertyAll(db *gorm.DB) (map[uint64]CvProperty, error) {
func GetPropertyAll(db *gorm.DB, area int) (map[uint64]CvProperty, error) {
rp := res_m.ResProperty{}
properties, err := rp.GetAll(mysql.Db)
if err != nil {
......@@ -103,7 +103,7 @@ func GetPropertyAll(db *gorm.DB) (map[uint64]CvProperty, error) {
}
//获取座驾头像
propertieAvatarMap, err := (&res_m.ResPropertyAvatar{}).GetAll(mysql.Db)
propertieAvatarMap, err := (&res_m.ResPropertyAvatar{Area: area}).GetAll(mysql.Db)
userIds := []uint64{}
for _, value := range propertieAvatarMap {
......
......@@ -16,6 +16,7 @@ type UserBag struct {
Count mysql.Num `json:"count"` // 拥有数量
RemainDays int `json:"remainDays"` // 有效天数
TextStyleList []*TextStyle `json:"textStyleList"` // 文本样式
HasGiftText bool `json:"hasGiftText"` // 是否有礼物文字
}
type TextStyle struct {
......
package user_cv
import (
"encoding/json"
"git.hilo.cn/hilo-common/_const/common"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/rpc"
"gorm.io/gorm"
"hilo-user/_const/enum/country_e"
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/headwear_cv"
"hilo-user/cv/medal_cv"
"hilo-user/cv/noble_cv"
......@@ -26,6 +30,7 @@ type UserTiny struct {
Country string `json:"country"`
CountryIcon string `json:"countryIcon"`
IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号
Birthday uint64 `json:"birthday"`
}
func UserToTiny(user user_m.User) *UserTiny {
......@@ -39,6 +44,7 @@ func UserToTiny(user user_m.User) *UserTiny {
Country: user.Country,
CountryIcon: user.CountryIcon,
IsPrettyCode: user.IsPrettyCode(),
Birthday: user.Birthday,
}
}
......@@ -79,7 +85,8 @@ type CvUserBase struct {
//邀请码
Code *string `json:"code"`
IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号
IsLogout bool `json:"isLogout"` //是否注销
IsNew bool `json:"isNew"` // 是否新用户
IsLogout bool `json:"isLogout"` // 是否注销
//生日,如果是其它人用户信息,年龄则按照是否展示显示,如果是本人,年龄则按照是否存在展示
Birthday *uint64 `json:"birthday"`
//是否展示年龄, 是本人才有数据,看其他用户均为nil
......@@ -97,10 +104,23 @@ type CvUserBase struct {
//VIP用户过期时间(只有自己查询自己,才返回)
VipExpireTime *int64 `json:"vipExpireTime"`
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
Medals []uint32 `json:"medals"` // 勋章列表
MedalInfo []medal_cv.CvMedal `json:"medalInfo"` // 勋章列表
Headwear *headwear_cv.CvHeadwear `json:"headwear"` // 当前使用的头饰
Ride property_cv.CvProperty `json:"ride"` // 当前使用的座驾
Noble noble_cv.CvNoble `json:"noble"` // 当前的
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"`
}
//批量获取用户基本信息
......@@ -146,7 +166,15 @@ func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error)
//rp := res_m.ResProperty{}
//properties, err := rp.GetAll(mysql.Db)
properties, err := GetPropertyAll(mysql.Db)
propertiesArea := make(map[int]map[uint64]property_cv.CvProperty)
for _, v := range []int{1, 2} {
properties, err := GetPropertyAll(mysql.Db, v)
if err != nil {
return nil, err
}
propertiesArea[v] = properties
}
areaMap, err := user_m.GetUserAreaMap(domain.CreateModelNil(), userIds)
if err != nil {
return nil, err
}
......@@ -156,7 +184,7 @@ func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error)
return nil, err
}
superManagerMap, err := GetSuperManagerMap(userIds)
superManagerMap, err := user_m.GetSuperManagerMap(userIds)
if err != nil {
return nil, err
}
......@@ -164,6 +192,7 @@ func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error)
cvUserBases := []*CvUserBase{}
for i := 0; i < len(users); i++ {
user := users[i]
properties := propertiesArea[areaMap[user.ID]]
invisible := IfLogout(user.LogoutTime)
invisibleAvatar := ""
invisibleNick := user.Code
......@@ -185,8 +214,10 @@ func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error)
CountryIcon: StrNil(user.CountryIcon),
Code: StrToString(&user.Code),
IsPrettyCode: user.IsPrettyCode(),
IsNew: user.IsNew(),
IsVip: vips[user.ID] != nil,
IsOfficialStaff: superManagerMap[user.ID],
Medals: IfLogoutMedals(IfLogout(user.LogoutTime), []uint32{}, medals[user.ID]),
MedalInfo: IfLogoutMedalInfo(invisible, []medal_cv.CvMedal{}, medalInfo[user.ID]),
Ride: IfLogoutRide(IfLogout(user.LogoutTime), property_cv.CvProperty{}, property_cv.CvProperty{
Id: rides[user.ID],
......@@ -223,6 +254,88 @@ func GetUserBases(userIds []mysql.ID, myUserId mysql.ID) ([]*CvUserBase, error)
return cvUserBases, nil
}
// 获取cp另一半基本信息
func GetUserBaseForCpMap(userIds []mysql.ID) (map[mysql.ID]*CvUserBase, error) {
var res = make(map[mysql.ID]*CvUserBase)
users, err := GetUserBasesForCp(userIds)
if err != nil {
return nil, err
}
for i, v := range users {
if v.Id != nil {
res[*v.Id] = users[i]
}
}
return res, nil
}
// 批量获取cp另一半基本信息
func GetUserBasesForCp(userIds []mysql.ID) ([]*CvUserBase, error) {
if len(userIds) == 0 {
return []*CvUserBase{}, nil
}
var users []user_m.User
if err := mysql.Db.Model(&user_m.User{}).Where("id in (?)", userIds).Find(&users).Error; err != nil {
return nil, myerr.WrapErr(err)
}
vips, err := user_m.BatchGetVips(userIds)
if err != nil {
return nil, myerr.WrapErr(err)
}
svips, err := rpc.MGetUserSvip(domain.CreateModelNil(), userIds)
if err != nil {
mylogrus.MyLog.Errorf("MGetUserSvip fail:%v", err)
}
headwearMap, err := headwear_cv.BatchGetCvHeadwears(userIds)
if err != nil {
return nil, err
}
nobles, err := noble_m.BatchGetActiveNoble(domain.CreateModelNil(), userIds)
if err != nil {
return nil, err
}
var cvUserBases []*CvUserBase
for i := 0; i < len(users); i++ {
user := users[i]
invisible := IfLogout(user.LogoutTime)
invisibleAvatar := ""
invisibleNick := user.Code
cvUserBase := &CvUserBase{
Id: &user.ID,
Avatar: StrNil(IfLogoutStr(invisible, invisibleAvatar, user.Avatar)),
DefaultAvatar: &user.DefaultAvatar,
ExternalId: StrToString(&user.ExternalId),
Nick: StrNil(IfLogoutNick(invisible, invisibleNick, user.Nick)),
Description: StrNil(IfLogoutStr(invisible, "", user.Description)),
Sex: TypeToUint8(&user.Sex),
Country: StrNil(user.Country),
CountryIcon: StrNil(user.CountryIcon),
Code: StrToString(&user.Code),
IsPrettyCode: user.IsPrettyCode(),
IsNew: user.IsNew(),
IsVip: vips[user.ID] != nil,
Noble: noble_cv.CvNoble{
Level: nobles[user.ID].Level,
EndTime: nobles[user.ID].EndTime.Unix(),
},
}
if cvUserBase.Noble.Level <= 0 {
cvUserBase.Noble.EndTime = 0
}
//
if headwear, flag := headwearMap[user.ID]; flag {
cvUserBase.Headwear = IfLogoutHeadwear(IfLogout(user.LogoutTime), nil, &headwear)
}
cvUserBase.Svip = svips[user.ID]
cvUserBases = append(cvUserBases, cvUserBase)
}
return cvUserBases, nil
}
func getMedalInfoMap(db *gorm.DB, medals map[uint64][]uint32) (map[uint64][]uint32, map[uint64][]medal_cv.CvMedal, error) {
resMedals, err := res_m.MedalGetAllMap(db)
if err != nil {
......@@ -251,7 +364,7 @@ func getMedalInfoMap(db *gorm.DB, medals map[uint64][]uint32) (map[uint64][]uint
return medalIds, medalMap, nil
}
func GetPropertyAll(db *gorm.DB) (map[uint64]property_cv.CvProperty, error) {
func GetPropertyAll(db *gorm.DB, area int) (map[uint64]property_cv.CvProperty, error) {
rp := res_m.ResProperty{}
properties, err := rp.GetAll(mysql.Db)
if err != nil {
......@@ -259,7 +372,7 @@ func GetPropertyAll(db *gorm.DB) (map[uint64]property_cv.CvProperty, error) {
}
//获取座驾头像
propertyAvatarMap, err := (&res_m.ResPropertyAvatar{}).GetAll(mysql.Db)
propertyAvatarMap, err := (&res_m.ResPropertyAvatar{Area: area}).GetAll(mysql.Db)
var userIds []uint64
for _, value := range propertyAvatarMap {
......@@ -309,25 +422,6 @@ func GetPropertyAll(db *gorm.DB) (map[uint64]property_cv.CvProperty, error) {
return result, nil
}
func GetSuperManagerMap(userIds []uint64) (map[uint64]bool, error) {
if len(userIds) == 0 {
return map[uint64]bool{}, nil
}
var superManagers []user_m.SuperManager
if err := mysql.Db.Model(&user_m.SuperManager{}).Where("user_id in (?)", userIds).Find(&superManagers).Error; err != nil {
return nil, myerr.WrapErr(err)
}
//转换成map
rs := map[uint64]bool{}
for i, _ := range userIds {
rs[userIds[i]] = false
}
for i, _ := range superManagers {
rs[superManagers[i].UserId] = true
}
return rs, nil
}
func GetUserBaseMap(userIds []mysql.ID, myUserId mysql.ID) (map[mysql.ID]*CvUserBase, error) {
userBases, err := GetUserBases(userIds, myUserId)
if err != nil {
......@@ -355,3 +449,169 @@ type CvUserTiny struct {
//生日,如果是其它人用户信息,年龄则按照是否展示显示,如果是本人,年龄则按照是否存在展示
Birthday *uint64 `json:"birthday"`
}
//用户详细信息
type CvUserDetail struct {
CvUserBase
//统计:我喜欢多少人
ILikeCount *uint32 `json:"iLikeCount"`
//统计:多少人喜欢你, (本才才有数据,不是本人,数据为nil)
LikeCount *uint32 `json:"likeCount"`
//统计:多少人访问你
VisitCount *uint32 `json:"visitCount"`
//消息提醒, 1:开启,2:关闭
IsPush *uint8 `json:"isPush"`
//钻石数量(本人才有数据,不是本人,数据为nil)
DiamondNum *uint32 `json:"diamondNum"`
//粉钻数量(本人才有数据,不是本人,数据为nil)
PinkDiamondNum *uint32 `json:"pinkDiamondNum"`
//是否喜欢(本人没有数据,//20210205 已废弃nil,产品说:可以自己喜欢自己)
IsLike *bool `json:"isLike"`
//ID
//ID *mysql.ID `json:"id,omitempty"`
//是否工会成员, 只有是自己查自己,这个才有值,其它全为nil
//IsTradeUnion *bool `json:"isTradeUnion"`
//工会成员,是否开启了,匹配通知,只有 isTradeUnion值为true,这里才有值,
//IsTradeUnionMatchNotification *bool `json:"isTradeUnionMatchNotification"`
//是否可以免费通话,自己本人没有数据
//IsVideoFreeCan *bool `json:"isVideoCanFree"`
//别人是否喜欢我,自己本人没有数据 (20210205 已废弃nil,产品说:可以自己喜欢自己)
IsLikeMe *bool `json:"isLikeMe"`
HeartValue uint32 `json:"heartValue"` // 与我之间永恒之心的值
HeartValueMax uint32 `json:"heartValueMax"` // 与我之间永恒之心的最大值(0代表没有永恒之心,即没有相互关注)
MeetDays uint `json:"meetDays"` // 成长关系建立的时间(天数)
WealthUserGrade uint32 `json:"wealthUserGrade"` //财富等级
CharmUserGrade uint32 `json:"charmUserGrade"` //魅力等级
ActivityUserGrade uint32 `json:"activityUserGrade"` //活跃等级
CurrentRoom string `json:"currentRoom"` // 当前用户所在房间(产品叫“群组”)
MyGroupPower uint64 `json:"myGroupPower"` // 当前用户所在势力
MyGroupPowerName string `json:"myGroupPowerName"` // 当前用户所在势力绑定群组的名称
GroupPower rpc.CvGroupPowerInfo `json:"groupPower"` // 家族
GroupId string `json:"groupId"` // 当前用户拥有的群组id(产品叫“群组”),如果没有则为空,拥有多个,返回第一个
PhoneInfo *user_m.UserPhoneInfo `json:"phoneInfo"` // 用户绑定的手机信息
ThirdList []int8 `json:"thirdList"` // 用户绑定的第三方平台列表;类型 1:phone, 2:google, 3:facebook 4:apple 5:wechat" Enums(1,2,3,4,5)
CountryManager *CVCountryManager `json:"countryManager,omitempty"` // 国家管理员
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国家管理人员
type CVCountryManager struct {
Country string `json:"country"` // 国家name
Role country_e.CountryMgrRole `json:"role" swaggertype:"integer"` // 角色 1:国家管理员 2:国家助理
}
// cp信息
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 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关系
type CvCpRelation struct {
CpId uint64 `json:"cpId"`
UserId uint64 `json:"userId"`
CpUserId uint64 `json:"cpUserId"`
CpUserAvatar string `json:"cpUserAvatar,omitempty"`
}
// cp等级
type CvCpLevel struct {
Level cp_e.CpLevel `json:"level"` // 等级 0:无称号 1:恋爱CP 2:甜蜜CP 3:忠诚CP 4:炽热CP 5:荣耀CP
Points uint32 `json:"points"` // CP值
Title string `json:"title,omitempty"` // 称号翻译
}
// 特权信息
type CvPrivilege struct {
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
}
......@@ -78,6 +78,13 @@ func IfLogout(logoutTime int64) bool {
return logoutTime > 0 && time.Now().Unix() > logoutTime
}
func IfLogoutMedals(condition bool, trueVal, falseVal []uint32) []uint32 {
if condition {
return trueVal
}
return falseVal
}
func IfLogoutMedalInfo(condition bool, trueVal, falseVal []medal_cv.CvMedal) []medal_cv.CvMedal {
if condition {
return trueVal
......
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT]
SECRET=hilo1632
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) {
if err != nil {
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结构体
......@@ -37,7 +37,7 @@ func GetJSON(model *domain.Model, key string, obj interface{}) (err error) {
defer func() {
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 {
// may redisV2.Nil
return
......@@ -59,7 +59,7 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
if time.Now().After(deadline) {
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 {
time.Sleep(time.Millisecond * 10)
} else {
......@@ -70,5 +70,5 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
// 解锁
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) {
if 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 {
return 0, err
}
......@@ -76,7 +76,7 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) {
if 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 {
return 0, err
}
......@@ -105,11 +105,11 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error {
// return err
//}
// 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
}
// 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
}
if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil {
......
package common
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-user/_const/redis_key"
"hilo-user/myerr"
"github.com/bluele/gcache"
"time"
)
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
bData, err := GetCache(redis_key.GetUserMedalMerge(userId))
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
}
// 改成lru
var userMedalMergeLru = gcache.New(10000).LRU().Build()
func GetCache(key string) ([]byte, error) {
data, err := redisCli.GetRedis().Get(context.Background(), key).Bytes()
if err != 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
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
if data, err := userMedalMergeLru.Get(userId); err == nil {
return data.([]uint32), nil
}
return nil
return nil, nil
}
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) error {
err := SetCache(redis_key.GetUserMedalMerge(userId), data, time.Hour*2)
if err != nil {
mylogrus.MyLog.Errorf("SetUserMedalMerge err:%s", err)
return myerr.WrapErr(err)
}
return nil
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) {
_ = userMedalMergeLru.SetWithExpire(userId, data, time.Minute*15)
}
package country_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/_const/enum/country_e"
"hilo-user/myerr"
)
type CountryMgrUser struct {
mysql.Entity
Country string
UserId mysql.ID
Role country_e.CountryMgrRole
}
// 获取国家管理人员
func GetCountryMgr(model *domain.Model, userId mysql.ID) (*CountryMgrUser, error) {
cmu := new(CountryMgrUser)
if err := model.Db.WithContext(model.MyContext.Context).Where("user_id = ?", userId).First(&cmu).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
} else {
return nil, myerr.WrapErr(err)
}
}
return cmu, nil
}
// 更新国家管理人员
func (cmu *CountryMgrUser) UpdateCountryMgr(userId mysql.ID, role country_e.CountryMgrRole, country string) *CountryMgrUser {
cmu.UserId, cmu.Role, cmu.Country = userId, role, country
return cmu
}
// 删除国家管理人员
func (cmu *CountryMgrUser) DeleteCountryMgr() {
cmu.SetDel()
}
......@@ -130,7 +130,21 @@ func GetCp(model *domain.Model, userId uint64) (*CpRelation, error) {
if err == gorm.ErrRecordNotFound {
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 res, nil
......
......@@ -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 {
var ranks []CpDayRank
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 {
model.Log.Errorf("PageCpDayRank fail:%v", err)
}
......
package diamond_m
import (
"fmt"
"git.hilo.cn/hilo-common/_const/enum/diamond_e"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
......@@ -37,6 +38,11 @@ type DiamondAccountDetail struct {
diamondAccount *DiamondAccount `gorm:"-"`
}
func (DiamondAccountDetail) TableName() string {
month := time.Now().Format("200601")
return fmt.Sprintf("diamond_account_detail_%s", month)
}
// 粉钻详情
type DiamondPinkAccountDetail struct {
mysql.Entity
......@@ -107,7 +113,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
var count int64
if diamondOperateSet.FrequencyDay == -1 {
if diamondOperateSet.FrequencyNum != -1 {
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{
diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId,
OperateType: operateType,
}).Count(&count)
......@@ -122,7 +128,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, myerr.WrapErr(err)
}
//一天的次数
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{
diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId,
OperateType: operateType,
}).Where("created_time >= ? ", beginTime).Count(&count)
......@@ -130,7 +136,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
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,代表值无效,由参数给与
......
......@@ -3,7 +3,6 @@ package diamond_m
import (
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/domain/model"
"hilo-user/myerr"
"strconv"
)
......@@ -32,7 +31,10 @@ func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional()
}
//持久化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)
}
//改变diamondAccount值
......
package groupPower_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/_const/enum/groupPower_e"
"hilo-user/domain/model/group_m"
"hilo-user/myerr"
)
type GroupPowerUser struct {
mysql.Entity
*domain.Model `gorm:"-"`
GroupPowerId mysql.ID
UserId mysql.ID
Role groupPower_e.GroupPowerUserRole
}
type GroupPower struct {
mysql.Entity
*domain.Model `gorm:"-"`
GroupUid mysql.Str
Name mysql.Str
Status groupPower_e.GroupPowerStatus
}
// 查询用户加入的国家势力ID及名称(势力绑定的群组的名称)
func GetUserGroupPower(model *domain.Model, userId uint64) (uint64, string, error) {
gpu, err := GetGroupPowerUserOrNil(model, userId)
if err != nil {
return 0, "", err
}
if gpu == nil || gpu.GroupPowerId == 0 {
return 0, "", nil
}
gp, err := GetGroupPowerOrErr(model, gpu.GroupPowerId)
if err != nil {
return 0, "", err
}
powerName := ""
if gp != nil && len(gp.GroupUid) > 0 {
gi, err := group_m.GetGroupInfo(model, gp.GroupUid)
if err != nil {
return 0, "", err
}
if gi != nil {
// 只要前15个字
s := []rune(gi.Name)
if len(s) <= 15 {
powerName = string(s)
} else {
powerName = string(s[0:15])
}
}
}
return gpu.GroupPowerId, powerName, nil
}
//获取用户所在的国家势力信息,不存在则为nil
func GetGroupPowerUserOrNil(model *domain.Model, userId mysql.ID) (*GroupPowerUser, error) {
groupPowerUser := GroupPowerUser{}
if err := model.Db.Where(&GroupPowerUser{
UserId: userId,
}).First(&groupPowerUser).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
} else {
return nil, myerr.WrapErr(err)
}
}
groupPowerUser.Model = model
return &groupPowerUser, nil
}
func GetGroupPowerOrErr(model *domain.Model, id uint64) (*GroupPower, error) {
groupPower := GroupPower{}
if err := model.Db.Model(&GroupPower{}).First(&groupPower, id).Error; err != nil {
return nil, myerr.WrapErr(err)
}
groupPower.Model = model
return &groupPower, nil
}
package group_m
import (
"git.hilo.cn/hilo-common/domain"
"gorm.io/gorm"
"hilo-user/_const/enum/group_e"
"hilo-user/myerr/bizerr"
"time"
)
type GroupInfo struct {
Id int64
ImGroupId string
TxGroupId string
Type uint16
Code string
OriginCode string
Owner uint64
Name string
Introduction string
Notification string
FaceUrl string
Country string
ChannelId string
Password string
EntryLevel uint32 // obsolete
MicOn bool
LoadHistory bool
ThemeId int16
MicNumType group_e.GroupMicNumType
TouristMic uint8 // 游客是否能上麦1是2否
TouristSendMsg uint8 // 游客是否能发消息1是2否
TouristSendPic uint8 // 游客是否能发图片1是2否
MemberFee uint64 // 加入会员需要黄钻数
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
func GetGroupInfo(model *domain.Model, groupId string) (*GroupInfo, error) {
if len(groupId) <= 0 {
return nil, bizerr.GroupNotFound
}
r := GroupInfo{}
err := model.Db.Where(&GroupInfo{ImGroupId: groupId}).First(&r).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
} else {
return nil, err
}
}
return &r, nil
}
func FindGroupByOwner(model *domain.Model, ownerId uint64) ([]GroupInfo, error) {
rows := make([]GroupInfo, 0)
err := model.Db.Where(&GroupInfo{Owner: ownerId}).Find(&rows).Error
if err != nil {
return nil, err
}
return rows, nil
}
func ToTxGroupId(model *domain.Model, imGroupId string) (string, error) {
if len(imGroupId) <= 0 {
return "", nil
}
gi, err := GetGroupInfo(model, imGroupId)
if err != nil {
return "", err
}
if gi == nil {
return "", bizerr.GroupNotFound
}
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) {
if len(txGroupId) <= 0 {
return "", nil
}
gi, err := GetInfoByTxGroupId(model, txGroupId)
if err != nil {
return "", err
}
if gi == nil {
return "", bizerr.GroupNotFound
}
return gi.ImGroupId, nil
}
func GetInfoByTxGroupId(model *domain.Model, txGroupId string) (*GroupInfo, error) {
if len(txGroupId) <= 0 {
return nil, bizerr.GroupNotFound
}
r := GroupInfo{}
err := model.Db.Where(&GroupInfo{TxGroupId: txGroupId}).First(&r).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
} else {
return nil, err
}
}
return &r, nil
}
package group_m
import (
"git.hilo.cn/hilo-common/_const/common"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
)
type GroupRoles struct {
mysql.Entity
UserId uint64
ImGroupId string
Role common.GroupRoleType
}
type GroupMember struct {
GroupId string
UserId uint64
}
func (gm *GroupMember) Find(db *gorm.DB) ([]GroupMember, error) {
rows := make([]GroupMember, 0)
if err := db.Where(gm).Order("created_time DESC").Find(&rows).Error; err != nil {
return nil, err
}
return rows, nil
}
func GetGroupRoleById(model *domain.Model, imGroupId string, userId uint64) (role common.GroupRoleType, err error) {
role = common.GROUP_VISITOR
roles, _, err := GetRolesInGroup(model, imGroupId)
if err != nil {
return
}
for u, r := range roles {
if u == userId {
role = r
return
}
}
isGroupMember, err := IsGroupMember(model.Db, imGroupId, userId)
if err != nil {
return
}
if isGroupMember {
role = common.GROUP_MEMBER
}
return
}
// 查询群组中所有有角色的成员,由级别高到低、创建时间由早到晚排列
func GetRolesInGroup(model *domain.Model, groupId string) (map[uint64]uint16, []uint64, error) {
data := make([]GroupRoles, 0)
err := model.Db.Where(&GroupRoles{ImGroupId: groupId}).Order("role DESC, created_time").Find(&data).Error
if err != nil {
return nil, nil, err
}
result := make(map[uint64]uint16, 0)
orders := make([]uint64, 0)
for _, i := range data {
orders = append(orders, i.UserId)
result[i.UserId] = i.Role
}
return result, orders, nil
}
func IsGroupMember(db *gorm.DB, groupId string, userId uint64) (bool, error) {
gm := GroupMember{
GroupId: groupId,
UserId: userId,
}
rows, err := gm.Find(db)
if err != nil {
return false, err
}
return len(rows) > 0, nil
}
package group_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-user/_const/redis_key/group_k"
"hilo-user/myerr"
"strconv"
"strings"
"time"
)
// 3天
const expireMinute = 60 * 60 * 24 * 3
//获取在房间的用户 返回值:map,key:userId, value:groupUuid
func RoomLivingUserIdFilter(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]string, error) {
userIdSet := map[mysql.ID]struct{}{}
for i, _ := range userIds {
userIdSet[userIds[i]] = struct{}{}
}
key := group_k.GetPrefixGroupRoomLiving()
if err := ClearExpired(model, key, expireMinute); err != nil {
return nil, myerr.WrapErr(err)
}
groupUserIdstrs, err := model.RedisCluster.ZRange(model, key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
resultUserSet := map[mysql.ID]string{}
for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
if _, flag := userIdSet[userId]; flag {
resultUserSet[userId] = tempGroupUid
}
}
return resultUserSet, nil
}
func ClearExpired(model *domain.Model, key string, expireSec int64) error {
return model.RedisCluster.ZRemRangeByScore(model, key,
"0", strconv.FormatInt(time.Now().Unix()-expireSec, 10)).Err()
}
func analysisMemberStr(memberStr string) (string, uint64) {
strs := strings.Split(memberStr, "_")
groupUid := strs[0]
userId, err := strconv.ParseUint(strs[1], 10, 64)
if err != nil {
mylogrus.MyLog.Errorf("analysisMemberStr memberStr:%v err:%+v", memberStr, err)
}
return groupUid, userId
}
package invite_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"time"
)
type InviteApply struct {
Id uint64 `json:"id"`
UserId uint64 `json:"user_id"`
NewUserId uint64 `json:"new_user_id"`
Platform string `json:"platform"`
PlatformId string `json:"platform_id"`
RechargeInfo string `json:"recharge_info"`
Status uint8 `json:"status"` // 状态0.未审核1.已通过2.已拒绝
VideoUrl string `json:"video_url"`
Level string `json:"level"`
CreatedTime time.Time `json:"created_time"`
Reason int `json:"reason"` // 1.已申请2.待审核3.已通过4.已拒绝"
SubUserId uint64 `json:"sub_user_id"` // 提交人
}
func CreateInviteApply(model *domain.Model, userId, newUserId, subUserId uint64, platform, platformId, recharge, videoUrl string) error {
err := model.DB().Create(&InviteApply{
UserId: userId, NewUserId: newUserId, Platform: platform, PlatformId: platformId, RechargeInfo: recharge, VideoUrl: videoUrl,
CreatedTime: time.Now(), SubUserId: subUserId}).Error
if err != nil {
model.Log.Errorf("CreateInviteApply err:%v", err)
return err
}
return nil
}
func GetApplyList(model *domain.Model, subUserId uint64, userIds []uint64, pageIndex, pageSize, gType int, beginTime,
endTime time.Time) ([]*InviteApply, int64, error) {
db := model.DB().Model(InviteApply{}).Where("user_id in (?) or sub_user_id = ?", userIds, subUserId).Where("created_time >= ? and created_time <= ?", beginTime, endTime)
switch gType { // 1.已申请2.待审核3.已通过4.已拒绝
case 2:
db = db.Where("`status` = ?", 0)
case 3:
db = db.Where("`status` = ?", 1)
case 4:
db = db.Where("`status` = ?", 2)
}
res := make([]*InviteApply, 0)
var count int64
err := db.Order("id desc").Offset((pageIndex - 1) * pageSize).Find(&res).Limit(-1).Offset(-1).Count(&count).Error
if err != nil {
model.Log.Errorf("GetApplyList err:%v", err)
return nil, 0, err
}
return res, count, nil
}
// 检查被邀请人是否存在
func IsInInviteApply(model *domain.Model, userId mysql.ID) (bool, error) {
var apply InviteApply
if err := model.Db.Model(InviteApply{}).Where("new_user_id = ?", userId).First(&apply).Error; err != nil {
if err != gorm.ErrRecordNotFound {
return false, err
}
return false, nil
}
// err == nil, record exists
return true, nil
}
// 检查被邀请人是否存在
func GetInviteApplyNumByType(model *domain.Model, gType int, beginTime, endTime time.Time, userIds []uint64, subUserId uint64) (int, error) {
var count int64
db := model.Db.Model(InviteApply{}).Where("user_id in (?) or sub_user_id = ?", userIds, subUserId).Where("created_time >= ? and created_time <= ?", beginTime, endTime)
switch gType { // 1.已申请2.待审核3.已通过4.已拒绝
case 2:
db = db.Where("`status` = ?", 0)
case 3:
db = db.Where("`status` = ?", 1)
case 4:
db = db.Where("`status` = ?", 2)
}
if err := db.Count(&count).Error; err != nil {
return 0, err
}
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
}
package promotion_m
import "git.hilo.cn/hilo-common/resource/mysql"
// 推广员
type PromotionAgent struct {
mysql.Entity
ManagerId mysql.ID
AgentId mysql.ID
}
// 邀请关系
type PromotionInvite struct {
mysql.Entity
ManagerId mysql.ID
AgentId mysql.ID
Invitee mysql.ID
Platform string
PlatformId string
Reason string
InviteDate string
}
// 邀请关系日志
type PromotionInviteLog struct {
mysql.Entity
AgentId mysql.ID
Invitee mysql.ID
AddReduce mysql.AddReduce
}
package promotion_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
)
// 获取推广员平台
func GetPromotionPlatforms(model *domain.Model) []string {
return []string{"Falla", "Yalla", "Whisper", "Ahlan", "Mashi", "YoYo", "Yoho", "Echo", "Hawa", "Yalla Ludo", "Hafla",
"Imo", "Ola Party", "ShareChat", "Viya", "Hello Yo", "Bigo Live", "Hago", "Oye Talk", "Tiktok", "Bigo", "Mr7ba"}
}
// 检查是否推广员
func IsPromotionAgent(model *domain.Model, userId mysql.ID) bool {
var promotionAgent PromotionAgent
if err := model.Db.Model(PromotionAgent{}).Where("agent_id = ?", userId).First(&promotionAgent).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("IsPromotionAgent fail:%v", err)
}
} else if promotionAgent.ID > 0 {
return true
}
return false
}
// 检查被邀请人是否存在
func IsPromotionInvitee(model *domain.Model, userId mysql.ID) (bool, error) {
var promotionInvite PromotionInvite
if err := model.Db.Model(PromotionInvite{}).Where("invitee = ?", userId).First(&promotionInvite).Error; err != nil {
if err != gorm.ErrRecordNotFound {
return false, err
}
return false, nil
}
// err == nil, record exists
return true, nil
}
// 检查是否推广经理
func IsPromotionManager(model *domain.Model, userId mysql.ID) bool {
var promotionAgent PromotionAgent
if err := model.Db.Model(PromotionAgent{}).Where("manager_id = ?", userId).First(&promotionAgent).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("IsPromotionManager fail:%v", err)
}
} else if promotionAgent.ID > 0 {
return true
}
return false
}
// 检查是否我的推广经理
func IsMyPromotionManager(model *domain.Model, userId, myUserId mysql.ID) bool {
var promotionAgent PromotionAgent
if err := model.Db.Model(PromotionAgent{}).Where("manager_id = ? and agent_id = ?", userId, myUserId).First(&promotionAgent).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("IsMyPromotionManager fail:%v", err)
}
} else if promotionAgent.ID > 0 {
return true
}
return false
}
// 获取推广经理拥有的所有推广员,包含自己
func GetPromotionManagerAgentList(model *domain.Model, userId mysql.ID) ([]uint64, error) {
uids := make([]uint64, 0)
if err := model.Db.Model(PromotionAgent{}).Where("manager_id = ?", userId).Select("agent_id").
Pluck("agent_id", &uids).Error; err != nil {
model.Log.Errorf("IsPromotionManager fail:%v", err)
return nil, err
}
return uids, nil
}
// 添加推广邀请关系
func AddPromotionInvite(model *domain.Model, managerId, agentId, invitee mysql.ID, platform, platformId, reason, inviteDate string) error {
if err := model.Db.Create(&PromotionInvite{
ManagerId: managerId,
AgentId: agentId,
Invitee: invitee,
Platform: platform,
PlatformId: platformId,
Reason: reason,
InviteDate: inviteDate,
}).Error; err != nil {
return err
}
return addPromotionInviteLog(model, agentId, invitee, mysql.ADD)
}
// 添加推广邀请关系-日志
func addPromotionInviteLog(model *domain.Model, agentId, invitee mysql.ID, addReduce mysql.AddReduce) error {
return model.Db.Create(&PromotionInviteLog{
AgentId: agentId,
Invitee: invitee,
AddReduce: addReduce,
}).Error
}
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
}
......@@ -22,6 +22,7 @@ type ResGift struct {
Together bool
Status mysql.UserYesNo
GiftType mysql.Type
HasGiftText bool
}
// 获取所有的礼物
......
......@@ -33,6 +33,7 @@ type ResPropertyAvatar struct {
Type res_e.ResPropertyAvatarType
SendUserId mysql.ID
ReceiverUserId mysql.ID
Area int
}
func InitResPropertyDiamond(model *domain.Model, resPropertyId mysql.ID, diamondNum mysql.Num, second mysql.Num) *ResPropertyDiamond {
......
package tim_m
import (
"encoding/json"
"git.hilo.cn/hilo-common/sdk/tencentyun"
)
type TimHiloInfo struct {
IsVip bool `json:"isVip"`
IsPretty bool `json:"isPretty"`
Medals []uint32 `json:"medals"`
PowerName string `json:"powerName"` // 用户加入的国家势力的绑定群组的名称
NobleLevel uint16 `json:"nobleLevel"`
}
func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32, groupPowerName string, nobleLevel uint16) error {
info := TimHiloInfo{IsVip: isVip, IsPretty: isPrettyCode, Medals: medals, PowerName: groupPowerName, NobleLevel: nobleLevel}
buf, err := json.Marshal(info)
if err != nil {
return err
}
if err = tencentyun.SetUserHiloInfo(extId, string(buf)); err != nil {
return err
}
return nil
}
package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-user/_const/enum/user_e"
)
//用户统计
type UserCount struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId mysql.ID
Type user_e.CountType
Num mysql.Num
isAdd bool `gorm:"-"`
isReduce bool `gorm:"-"`
addReduceNum mysql.Num `gorm:"-"`
}
package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/_const/enum/user_e"
"hilo-user/myerr"
)
//用户喜欢
type UserLike struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId mysql.ID
LikeUserId mysql.ID
SceneType user_e.UserLikeSceneType
}
type UserLikeOperate struct {
mysql.Entity
UserId mysql.ID
LikeUserId mysql.ID
Type user_e.UserLikeOperateType
SceneType user_e.UserLikeSceneType
}
func AddUserLikeOperate(model *domain.Model, userId mysql.ID, likeUserId mysql.ID, t user_e.UserLikeOperateType, sceneType user_e.UserLikeSceneType) (mysql.ID, error) {
userLikeOperate := UserLikeOperate{
UserId: userId,
LikeUserId: likeUserId,
Type: t,
SceneType: sceneType,
}
if err := model.Db.Create(&userLikeOperate).Error; err != nil {
return 0, myerr.WrapErr(err)
} else {
return userLikeOperate.ID, nil
}
}
func initUserLike(model *domain.Model, userId mysql.ID) *UserLike {
return &UserLike{
Model: model,
UserId: userId,
}
}
/*func GetUserLike(model *domain.Model, userId mysql.ID, likeUserId mysql.ID) (*UserLike, error) {
var userLike UserLike
err := model.Db.Where(&UserLike{
UserId: userId,
LikeUserId: likeUserId,
}).First(&userLike).Error
if err == nil {
return &userLike, nil
} else if err == gorm.ErrRecordNotFound {
return nil, nil
} else {
return nil, myerr.WrapErr(err)
}
}*/
//喜欢
func (userLike *UserLike) like(likeUserId mysql.ID, sceneType user_e.UserLikeSceneType) (*UserLike, mysql.ID, error) {
err := userLike.Db.Where(&UserLike{
UserId: userLike.UserId,
LikeUserId: likeUserId,
}).First(userLike).Error
//已经喜欢
if err == nil {
return nil, 0, myerr.NewWaring("已经标记喜欢")
} else if err == gorm.ErrRecordNotFound {
userLikeOperateId, err := AddUserLikeOperate(userLike.Model, userLike.UserId, likeUserId, user_e.LikeAdd, sceneType)
if err != nil {
return nil, 0, err
}
userLike.LikeUserId = likeUserId
userLike.SceneType = sceneType
return userLike, userLikeOperateId, nil
} else {
return nil, 0, myerr.WrapErr(err)
}
}
//取消喜欢
func (userLike *UserLike) likeCancel(likeUserId mysql.ID) (*UserLike, error) {
err := userLike.Db.Where(&UserLike{
UserId: userLike.UserId,
LikeUserId: likeUserId,
}).First(userLike).Error
//
if err == nil {
if _, err := AddUserLikeOperate(userLike.Model, userLike.UserId, likeUserId, user_e.LikeCancel, userLike.SceneType); err != nil {
return nil, err
}
userLike.SetDel()
return userLike, nil
} else if err == gorm.ErrRecordNotFound {
return nil, myerr.NewWaring("没有喜欢的记录")
} else {
return nil, myerr.WrapErr(err)
}
}
......@@ -61,8 +61,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
}
}
}
logger.Infof("maxGrade %+v", maxGrades)
logger.Infof("maxMedalIds %+v", maxMedalIds)
//logger.Infof("maxGrade %+v", maxGrades)
//logger.Infof("maxMedalIds %+v", maxMedalIds)
mIds := result
result = make([]uint32, 0)
......
package user_m
import (
"git.hilo.cn/hilo-common/_const/common"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/myerr"
"time"
)
type Relation struct {
// 永恒之心值
HeartValue uint32 `json:"heartValue"`
// 永恒之心的最大值(0代表没有永恒之心,即没有相互关注)
HeartValueMax uint32 `json:"heartValueMax"`
// 成长关系建立的时间(天数)
MeetDays uint `json:"meetDays"`
}
//用户成长关系
type UserRelation struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId_1 mysql.ID
UserId_2 mysql.ID
HeartValue uint32
}
// 查询成长关系
func GetRelation(model *domain.Model, userId1, userId2 mysql.ID) (Relation, error) {
result := Relation{0, 0, 0}
if userId1 == userId2 {
return result, nil
}
// 保证uid小的在前面
if userId1 > userId2 {
userId1, userId2 = userId2, userId1
}
rel := UserRelation{UserId_1: userId1, UserId_2: userId2, HeartValue: 0}
if err := model.DB().Model(&UserRelation{}).Where(&UserRelation{
UserId_1: userId1,
UserId_2: userId2,
}).First(&rel).Error; err != nil {
if err == gorm.ErrRecordNotFound {
// 没有成长关系的情况
return result, nil
} else {
return result, myerr.WrapErr(err)
}
}
result.HeartValueMax = common.HEART_VALUE_MAX
result.HeartValue = rel.HeartValue
if result.HeartValue > common.HEART_VALUE_MAX {
result.HeartValue = common.HEART_VALUE_MAX
}
d := uint(time.Since(rel.CreatedTime).Hours() / 24)
if d < 0 {
d = 0
}
result.MeetDays = d
return result, nil
}
// 批量查询成长关系
func BatchGetRelations(model *domain.Model, userId mysql.ID, others []mysql.ID) (map[mysql.ID]Relation, error) {
smaller := make([]mysql.ID, 0)
greater := make([]mysql.ID, 0)
for _, i := range others {
if i < userId {
smaller = append(smaller, i)
} else if i > userId {
greater = append(greater, i)
}
}
rows := make([]UserRelation, 0)
result := make(map[mysql.ID]Relation, 0)
var err error
if len(greater) > 0 {
if err = model.DB().Model(&UserRelation{}).Where("user_id_1 = ? AND user_id_2 IN ?", userId, greater).Find(&rows).Error; err != nil {
return result, err
}
}
for _, i := range rows {
if i.HeartValue > common.HEART_VALUE_MAX {
i.HeartValue = common.HEART_VALUE_MAX
}
d := uint(time.Since(i.CreatedTime).Hours() / 24)
if d < 0 {
d = 0
}
result[i.UserId_2] = Relation{HeartValue: i.HeartValue, HeartValueMax: common.HEART_VALUE_MAX, MeetDays: d}
}
rows = make([]UserRelation, 0)
if len(smaller) > 0 {
if err = model.DB().Model(&UserRelation{}).Where("user_id_1 IN ? AND user_id_2 = ?", smaller, userId).Find(&rows).Error; err != nil {
return result, err
}
}
for _, i := range rows {
if i.HeartValue > common.HEART_VALUE_MAX {
i.HeartValue = common.HEART_VALUE_MAX
}
d := uint(time.Since(i.CreatedTime).Hours() / 24)
if d < 0 {
d = 0
}
result[i.UserId_1] = Relation{HeartValue: i.HeartValue, HeartValueMax: common.HEART_VALUE_MAX, MeetDays: d}
}
// 补上没有成长关系的人
for _, u := range others {
if _, exists := result[u]; !exists {
result[u] = Relation{0, 0, 0}
}
}
return result, err
}
......@@ -65,15 +65,21 @@ func GetSuperManagerAll(model *domain.Model) ([]uint64, error) {
return userIds, nil
}
/*
func GetSuperManagerMap(model *domain.Model) (map[uint64]struct{}, error) {
userIds, err := GetSuperManagerAll(model)
if err != nil {
return nil, err
func GetSuperManagerMap(userIds []uint64) (map[uint64]bool, error) {
if len(userIds) == 0 {
return map[uint64]bool{}, nil
}
var superManagers []SuperManager
if err := mysql.Db.Model(&SuperManager{}).Where("user_id in (?)", userIds).Find(&superManagers).Error; err != nil {
return nil, myerr.WrapErr(err)
}
userIdMap := map[uint64]struct{}{}
//转换成map
rs := map[uint64]bool{}
for i, _ := range userIds {
userIdMap[userIds[i]] = struct{}{}
rs[userIds[i]] = false
}
return userIdMap, nil
}*/
for i, _ := range superManagers {
rs[superManagers[i].UserId] = true
}
return rs, nil
}
......@@ -52,6 +52,11 @@ func (u User) IsPrettyCode() bool {
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) {
var user User
......@@ -144,3 +149,34 @@ func GetUsers(model *domain.Model, ids []mysql.ID) ([]*User, error) {
}
return res, nil
}
//获取用户的国家,和所属的区域(是否阿语区)
func GetUserCountryArea(model *domain.Model, userId mysql.ID) (string, int, error) {
type info struct {
Name string
Area int
}
res := new(info)
if err := model.Db.WithContext(model.Context).Raw("select name, area from res_country where name = (select country from user where id = ?)", userId).First(&res).Error; err != nil {
return "", 0, myerr.WrapErr(err)
}
return res.Name, res.Area, nil
}
//获取用户的国家所属的区域(是否阿语区)
func GetUserAreaMap(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]int, error) {
type info struct {
Id mysql.ID
Area int
}
rows := make([]*info, 0)
sql := "select user.id, rc.area from user left join res_country rc on user.country = rc.name where user.id in (?);"
if err := model.DB().Raw(sql, userIds).Scan(&rows).Error; err != nil {
return nil, myerr.WrapErr(err)
}
res := make(map[mysql.ID]int)
for _, v := range rows {
res[v.Id] = v.Area
}
return res, nil
}
package user_m
import (
"git.hilo.cn/hilo-common/domain"
"time"
)
type UserBindInfo struct {
UserId uint64 `json:"user_id"`
Phone string `json:"phone"`
PhoneCountry string `json:"phone_country"`
Pwd string `json:"pwd"`
AreaCode string `json:"area_code"`
Icon string `json:"icon"`
CreateAt time.Time `json:"create_at"`
UpdateAt time.Time `json:"update_at"`
}
func (*UserBindInfo) TableName() string {
return "user_bind_info"
}
type UserPhoneInfo struct {
Phone string `json:"phone"`
PhoneCountry string `json:"phoneCountry"`
AreaCode string `json:"areaCode"`
Icon string `json:"icon"`
}
// 获取用户手机号绑定信息
func GetUserBindInfoByUserId(model *domain.Model, userId uint64) (*UserBindInfo, error) {
res := new(UserBindInfo)
err := model.DB().Where(&UserBindInfo{UserId: userId}).First(&res).Error
if err != nil {
return nil, err
}
return res, nil
}
package user_m
import (
"git.hilo.cn/hilo-common/domain"
"gorm.io/gorm"
"hilo-user/myerr"
)
type UserOauth struct {
UserId uint64 `json:"user_id"`
ThirdPartyId string `json:"third_party_id"`
ThirdPartyType int8 `json:"third_party_type"`
}
func (*UserOauth) TableName() string {
return "user_oauth"
}
// 根据id获取第三方登录信息
func GetUserOauthByUserId(model *domain.Model, userId uint64, thirdType uint8) ([]*UserOauth, error) {
res := make([]*UserOauth, 0)
db := model.DB().Where(&UserOauth{UserId: userId})
if thirdType > 0 {
db = db.Where(&UserOauth{ThirdPartyType: int8(thirdType)})
}
err := db.Find(&res).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
} else {
return nil, myerr.WrapErr(err)
}
}
return res, nil
}
package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-user/myerr"
)
type UserTradeUnion struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId mysql.ID
MatchNotification mysql.OpenClose
AgentId mysql.ID
StarchatId mysql.ID
Avatar string
}
func GetUserTradeUnion(userId mysql.ID) (*UserTradeUnion, error) {
var userTradeUnion UserTradeUnion
if err := mysql.Db.Where(UserTradeUnion{
UserId: userId,
}).First(&userTradeUnion).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
} else {
return nil, myerr.WrapErr(err)
}
}
return &userTradeUnion, nil
}
type AgentMgr struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId mysql.ID
AgentId mysql.ID
}
func IsAgent(userId uint64) bool {
data := AgentMgr{}
return mysql.Db.Where(&AgentMgr{UserId: userId}).First(&data).Error == nil
}
package visit_m
import "hilo-user/domain/model"
func (userVisit *UserVisit) Persistent() error {
return model.Persistent(userVisit.Db, userVisit)
}
package visit_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-user/myerr"
)
type UserVisit struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId mysql.ID
VisitUserId mysql.ID
N mysql.Num
}
func GetVisitInstanceOrInit(model *domain.Model, userId mysql.ID, visitUserId mysql.ID) (*UserVisit, error) {
var userVisit UserVisit
if err := model.Db.Where(&UserVisit{
UserId: userId,
VisitUserId: visitUserId,
}).FirstOrInit(&userVisit, UserVisit{
UserId: userId,
VisitUserId: visitUserId,
N: 0,
}).Error; err != nil {
return nil, myerr.WrapErr(err)
}
userVisit.Model = model
return &userVisit, nil
}
func (userVisit *UserVisit) UserVisitAdd() *UserVisit {
userVisit.N = userVisit.N + 1
return userVisit
}
package cp_s
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/cp_cv"
"hilo-user/cv/user_cv"
"hilo-user/domain/model/cp_m"
"time"
)
type CpService struct {
svc *domain.Service
}
func NewCpService(myContext *mycontext.MyContext) *CpService {
svc := domain.CreateService(myContext)
return &CpService{svc}
}
// 获取用户cp信息
func (s *CpService) GetUserCp(userId uint64, lang string) (*user_cv.CvCp, error) {
var model = domain.CreateModelContext(s.svc.MyContext)
cpLevel := cp_e.CpLevel0
cpRelation, exists := cp_m.GetCpRelation(model, userId)
if !exists {
return nil, nil
}
var myPrivilegeList []user_cv.CvPrivilege
level := cp_m.GetCpLevel(model, cpRelation.Id)
if level.ExpireAt.Before(time.Now()) {
level.ExpireAt = time.Now().AddDate(0, 1, 0)
}
cpLevel = level.Level
cpUserId := cpRelation.UserId2
if cpUserId == userId {
cpUserId = cpRelation.UserId1
}
userPrivileges, err := cp_m.MGetUserSvipPrivilege(model, []uint64{userId})
if err != nil {
return nil, err
}
privilegeList := cp_cv.CopyCpLevelPrivilegeList(level.Level, "en")
for i, v := range privilegeList {
if v.CanSwitch {
privilegeList[i].UserSwitch = userPrivileges[userId][v.Type]
}
}
// 我的特权,有开关并且打开才返回
for _, v := range privilegeList {
if !v.CanSwitch {
myPrivilegeList = append(myPrivilegeList, user_cv.CvPrivilege{Type: v.Type})
} else if v.UserSwitch {
myPrivilegeList = append(myPrivilegeList, user_cv.CvPrivilege{Type: v.Type})
}
}
userBases, err := user_cv.GetUserBaseForCpMap([]uint64{cpUserId})
if err != nil {
return nil, err
}
// 返回值
title := cp_cv.GetTranslate(237, lang)
if msgId, ok := cp_e.CpLevelTitle[level.Level]; ok {
title = cp_cv.GetTranslate(msgId, lang)
}
var oldScore uint32
if oldCp, _ := cp_m.GetOldConnectCp(model, cpRelation.UserId1, cpRelation.UserId2); oldCp != nil {
oldScore = uint32(oldCp.Score)
}
response := &user_cv.CvCp{
CpUserInfo: userBases[cpUserId],
CpLevel: user_cv.CvCpLevel{
Level: cpLevel,
Points: oldScore + cp_m.SumCpPoints(model, cpRelation.Id), // 历史分数
Title: title,
},
MyPrivilegeList: myPrivilegeList,
CpDays: int(time.Now().Sub(cpRelation.CreatedTime).Hours()/24) + 1,
CreatedUnix: cpRelation.CreatedTime.Unix(),
}
return response, nil
}
......@@ -130,22 +130,31 @@ func CancelCpRelation(myCtx *mycontext.MyContext, myUserId uint64, externalId, l
return err
}
// 自己没有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)
// 我和对方是否是cp,且cp关系存在
cpRelation, err := cp_m.GetCpByIds(model, myUserId, userRec.ID)
if err != nil {
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)
}
//// 自己没有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解除申请,且还未被处理
myCancel, err := cp_m.GetCpCancelWithMe(model, user.ID, cp_e.CpCancel)
......
package event_s
import (
"git.hilo.cn/hilo-common/domain"
"github.com/jinzhu/now"
"hilo-user/_const/enum/cp_e"
"hilo-user/domain/event/gift_ev"
"hilo-user/domain/model/cp_m"
"time"
)
// 送礼增加cp等级
// 送礼增加cp排行榜
//func CpGiftEvent() {
// gift_ev.AddSendGiftEventSync(func(model *domain.Model, event interface{}) error {
// sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
// if !ok {
// model.Log.Errorf("AddSendGiftEventAsync event type err")
// return nil
// }
// // 只处理cp礼物
// if !sendGiftEvent.ResGift.Cp {
// return nil
// }
// 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 nil // 业务场景允许提前break(cp是唯一的)
// }
// }
// return nil
// })
//}
// 漏掉加分数的送礼记录,补上cp增加分数
// 送礼增加cp等级
// 送礼增加cp排行榜
func CpGiftEvent() {
gift_ev.AddSendGiftEventSync(func(model *domain.Model, event interface{}) error {
sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
if !ok {
model.Log.Errorf("AddSendGiftEventAsync event type err")
return nil
}
// 只处理cp礼物
if !sendGiftEvent.ResGift.Cp {
return nil
}
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 nil // 业务场景允许提前break(cp是唯一的)
}
}
return nil
})
}
//func CompensateCpScore() {
// if !config.IsMaster() {
// return
// }
// model := domain.CreateModelNil()
// num, err := redisCli.IncrNumExpire("scirpt:compensateCpScore", 1, time.Hour*999)
// if err != nil {
// model.Log.Errorf("CompensateCpScore err:%v", err)
// }
// if num > 1 {
// model.Log.Errorf("CompensateCpScore 执行过了,退出")
// return
// }
// // 查找需要补分的送礼记录
// type GiftOperate struct {
// Id uint64 `json:"id"`
// ResGiftId uint64 `json:"res_gift_id"`
// GiftN int32 `json:"gift_n"`
// SendUserId uint64 `json:"send_user_id"`
// ReceiveUserId uint64 `json:"receive_user_id"`
// SendUserDiamond uint32 `json:"send_user_diamond"`
// SceneType int8 `json:"scene_type"`
// SceneUid string `json:"scene_uid"`
// CreatedTime time.Time `json:"created_time"`
// }
// rows := make([]*GiftOperate, 0)
// err = model.DB().Model(GiftOperate{}).
// Where("created_time < ?", "2023-06-22 11:20:15").
// Where("res_gift_id in (?)",
// []int{3561, 3571, 3581, 3591, 3601, 3611, 3621, 3631, 3641, 3651, 3661, 3671, 3681, 3691, 3701, 3711}).
// Find(&rows).Error
// if err != nil {
// model.Log.Errorf("CompensateCpScore err:%v", err)
// return
// }
// model.Log.Infof("CompensateCpScore len(rows):%v", len(rows))
//
// for idx, r := range rows {
// diamonds := r.SendUserDiamond
// // 有cp关系
// if cpRelation, exits := cp_m.GetCpRelationPair(model, r.SendUserId, r.ReceiveUserId); exits {
// if err := cp_m.AddCpLevelPoints(model, cpRelation, diamonds, gift_e.GiftOperateSceneType(r.SceneType), r.SceneUid); err != nil {
// model.Log.Errorf("CompensateCpScore AddCpLevelPoints fail:%v", err)
// return
// }
// if err := cp_m.AddCpDayRank(model, cpRelation, diamonds); err != nil {
// model.Log.Errorf("CompensateCpScore AddCpDayRank fail:%v", err)
// return
// }
// // 检查最新的等级
// 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("CompensateCpScore 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 = r.CreatedTime.Format("2006-01-02"), r.CreatedTime.Format("2006-01-02")
// cpAchievementType = cp_e.CpAchievementDayRank
// case "week":
// beginDate = now.With(r.CreatedTime).BeginningOfWeek().Format("2006-01-02")
// endDate = now.With(r.CreatedTime).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("CompensateCpScore UpdateCpAchievement fail:%v", err)
// }
// }
// }
// }
// model.Log.Infof("CompensateCpScore idx:%v", idx)
// if idx%1000 == 0 {
// time.Sleep(time.Millisecond * 100)
// }
// }
//
// model.Log.Infof("CompensateCpScore 补偿完毕")
//}
......@@ -14,7 +14,7 @@ import (
func EventInit() {
UserBagSendEvent()
CpGiftEvent()
//CpGiftEvent()
CpSpaceVisitEvent()
}
......
package user_s
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/rpc"
"gorm.io/gorm"
"hilo-user/_const/enum/user_e"
"hilo-user/cv/headwear_cv"
"hilo-user/cv/medal_cv"
"hilo-user/cv/noble_cv"
"hilo-user/cv/property_cv"
"hilo-user/cv/user_cv"
"hilo-user/domain/model/country_m"
"hilo-user/domain/model/diamond_m"
"hilo-user/domain/model/groupPower_m"
"hilo-user/domain/model/group_m"
"hilo-user/domain/model/noble_m"
"hilo-user/domain/model/user_m"
"hilo-user/domain/model/visit_m"
"hilo-user/domain/service/cp_s"
"hilo-user/myerr"
)
type UserService struct {
svc *domain.Service
}
func NewUserService(myContext *mycontext.MyContext) *UserService {
svc := domain.CreateService(myContext)
return &UserService{svc}
}
//用户基本信息
func (s *UserService) GetUserDetail(userId mysql.ID, myUserId mysql.ID, lang string) (*user_cv.CvUserDetail, error) {
model := domain.CreateModelContext(s.svc.MyContext)
model.Log.Infof("GetUserDetail %d begin", userId)
var user user_m.User
var err error
if err = model.DB().First(&user, userId).Error; err != nil {
return nil, myerr.WrapErr(err)
}
//统计喜欢
var likeN int64
if err := model.DB().Model(&user_m.UserLike{}).Where(&user_m.UserLike{
UserId: myUserId,
LikeUserId: userId,
}).Count(&likeN).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var likeMe int64
if err := model.DB().Model(&user_m.UserLike{}).Where(&user_m.UserLike{
UserId: userId,
LikeUserId: myUserId,
}).Count(&likeMe).Error; err != nil {
return nil, myerr.WrapErr(err)
}
rel := make(map[mysql.ID]user_m.Relation, 1)
rel[userId], _ = user_m.GetRelation(model, myUserId, userId)
var wealthUserScore user_m.MatchWealthUserScore
if err := model.DB().Model(&user_m.MatchWealthUserScore{}).Where(&user_m.MatchWealthUserScore{UserId: userId}).First(&wealthUserScore).Error; err != nil {
if err != nil {
if err == gorm.ErrRecordNotFound {
wealthUserScore = user_m.MatchWealthUserScore{
UserId: userId,
Score: 0,
Grade: 0,
}
} else {
return nil, myerr.WrapErr(err)
}
}
}
var charmUserScore user_m.MatchCharmUserScore
if err := model.DB().Model(&user_m.MatchCharmUserScore{}).Where(&user_m.MatchCharmUserScore{
UserId: userId,
}).First(&charmUserScore).Error; err != nil {
if err != nil {
if err == gorm.ErrRecordNotFound {
charmUserScore = user_m.MatchCharmUserScore{
UserId: userId,
Score: 0,
Grade: 0,
}
} else {
return nil, myerr.WrapErr(err)
}
}
}
var activityUserScore user_m.MatchActityUserScore
if err := model.DB().Model(&user_m.MatchActityUserScore{}).Where(&user_m.MatchActityUserScore{
UserId: userId,
}).First(&activityUserScore).Error; err != nil {
if err != nil {
if err == gorm.ErrRecordNotFound {
activityUserScore = user_m.MatchActityUserScore{
UserId: userId,
Score: 0,
Grade: 0,
}
} else {
return nil, myerr.WrapErr(err)
}
}
}
isVip, expireTime, err := user_m.IsVip(userId)
if err != nil {
return nil, myerr.WrapErr(err)
}
svip, err := rpc.GetUserSvip(model, userId)
if err != nil {
return nil, myerr.WrapErr(err)
}
headwear, err := headwear_cv.GetCvHeadwear(userId)
if err != nil {
return nil, err
}
medals := make(map[uint64][]uint32, 0)
medals[userId], err = user_m.GetUserMedalMerge(model.Log, mysql.Db, userId)
if err != nil {
return nil, err
}
medals, medalInfo, err := medal_cv.GetMedalInfoMap(mysql.Db, medals)
if err != nil {
return nil, err
}
rooms, err := group_m.RoomLivingUserIdFilter(model, []uint64{userId})
if err != nil {
return nil, err
}
// 2022-05-13 个人详情页:当用户在加锁的房间时,不显示进入房间的图标
if g, ok := rooms[userId]; ok {
gi, err := group_m.GetGroupInfo(model, g)
if err != nil {
return nil, err
}
if gi != nil && len(gi.Password) > 0 {
rooms[userId] = ""
}
}
cp, err := cp_s.NewCpService(s.svc.MyContext).GetUserCp(userId, lang)
if err != nil {
return nil, err
} else if cp != nil && cp.CpUserInfo != nil && cp.CpUserInfo.Avatar != nil && headwear != nil {
headwear.HeadwearIcon = *cp.CpUserInfo.Avatar
}
groupPowerId, groupPowerName, err := groupPower_m.GetUserGroupPower(model, userId)
if err != nil {
return nil, err
}
powers := map[mysql.ID]uint64{userId: groupPowerId}
powerNames := map[mysql.ID]string{userId: groupPowerName}
groupPower, _ := rpc.GetGroupPower(model, groupPowerId)
up := user_m.UserProperty{}
rides, err := up.BatchGet(mysql.Db, []uint64{userId})
if err != nil {
return nil, err
}
//rp := res_m.ResProperty{}
//properties, err := rp.GetAll(mysql.Db)
_, area, err := user_m.GetUserCountryArea(model, userId)
if err != nil {
return nil, err
}
properties, err := property_cv.GetPropertyAll(mysql.Db, area)
if err != nil {
return nil, err
}
ride := property_cv.CvProperty{
Id: rides[user.ID],
PicUrl: properties[rides[user.ID]].PicUrl,
EffectUrl: properties[rides[user.ID]].EffectUrl,
SenderAvatar: properties[rides[user.ID]].SenderAvatar,
ReceiverAvatar: properties[rides[user.ID]].ReceiverAvatar,
Using: true,
}
noble, err := noble_m.FindActiveNoble(mysql.Db, userId)
if err != nil {
return nil, err
}
//判断是不是工会
userTradeUnion, err := user_m.GetUserTradeUnion(myUserId)
if err != nil {
return nil, err
}
superManagerMap, err := user_m.GetSuperManagerMap([]uint64{userId})
if err != nil {
return nil, err
}
// 群组信息
myGroups, err := group_m.FindGroupByOwner(model, userId)
if err != nil {
return nil, err
}
// 手机绑定信息
// 第三方账号绑定信息
phoneInfo := new(user_m.UserPhoneInfo)
var thirdList []int8
if userId == myUserId {
thirdList = make([]int8, 0, 5)
// 手机绑定信息
bindInfo, err := user_m.GetUserBindInfoByUserId(model, userId)
if err != nil && err != gorm.ErrRecordNotFound {
return nil, err
}
if bindInfo != nil {
if len(bindInfo.Phone) > 2 {
phoneInfo.Phone = bindInfo.Phone[:2] + "****" + bindInfo.Phone[len(bindInfo.Phone)-2:]
}
phoneInfo.PhoneCountry = bindInfo.PhoneCountry
phoneInfo.AreaCode = bindInfo.AreaCode
phoneInfo.Icon = bindInfo.Icon
thirdList = append(thirdList, 1)
}
// 第三方账号绑定信息
thirdInfoList, err := user_m.GetUserOauthByUserId(model, userId, 0)
if err != nil {
return nil, err
}
if thirdInfoList != nil {
for _, v := range thirdInfoList {
thirdList = append(thirdList, v.ThirdPartyType)
}
}
}
// 国家管理员
countryManager, err := country_m.GetCountryMgr(model, userId)
if err != nil {
return nil, err
}
var cvCountryManager *user_cv.CVCountryManager
if countryManager != nil {
cvCountryManager = &user_cv.CVCountryManager{
Country: countryManager.Country,
Role: countryManager.Role,
}
}
return userToDetailOne(model, &user, myUserId, userTradeUnion, likeN > 0, likeMe > 0,
rel, isVip, expireTime, svip, headwear, ride, wealthUserScore.Grade, charmUserScore.Grade,
activityUserScore.Grade, medals[userId], medalInfo[userId], rooms[userId], powers[userId], powerNames[userId], groupPower,
noble, superManagerMap[userId], myGroups, phoneInfo, thirdList, cvCountryManager, cp)
}
// 单用户版,简化参数
func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.UserTradeUnion, isLike bool, likeMe bool, hvMap map[mysql.ID]user_m.Relation,
isVip bool, vipExpireTime *int64, svip rpc.CvSvip, headwear *headwear_cv.CvHeadwear, ride property_cv.CvProperty, wealthGrade uint32, charmGrade uint32, activityGrade uint32,
medals []uint32, medalInfo []medal_cv.CvMedal, room string, power uint64, powerName string, groupPower rpc.CvGroupPowerInfo, noble *noble_m.UserNoble, isOfficialStaff bool,
myGroups []group_m.GroupInfo, phoneInfo *user_m.UserPhoneInfo, thirdList []int8, countryManager *user_cv.CVCountryManager, cp *user_cv.CvCp) (*user_cv.CvUserDetail, error) {
room, err := group_m.ToTxGroupId(model, room)
if err != nil {
model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err)
room = ""
}
cvUserDetail := &user_cv.CvUserDetail{
CvUserBase: user_cv.CvUserBase{
Id: &user.ID,
Avatar: StrNil(IfLogoutStr(IfLogout(user.LogoutTime), "", user.Avatar)),
DefaultAvatar: &user.DefaultAvatar,
ExternalId: StrToString(&user.ExternalId),
Nick: StrNil(IfLogoutStr(IfLogout(user.LogoutTime), user.Code, user.Nick)),
Description: StrNil(IfLogoutStr(IfLogout(user.LogoutTime), "", user.Description)),
Sex: TypeToUint8(&user.Sex),
Country: StrNil(user.Country),
CountryIcon: StrNil(user.CountryIcon),
Code: StrToString(&user.Code),
IsPrettyCode: user.IsPrettyCode(),
IsNew: user.IsNew(),
IsVip: isVip,
IsOfficialStaff: isOfficialStaff,
VipExpireTime: vipExpireTime,
Svip: svip,
Medals: IfLogoutMedals(IfLogout(user.LogoutTime), []uint32{}, medals),
MedalInfo: IfLogoutMedalInfo(IfLogout(user.LogoutTime), []medal_cv.CvMedal{}, medalInfo),
Headwear: IfLogoutHeadwear(IfLogout(user.LogoutTime), nil, headwear),
Ride: IfLogoutRide(IfLogout(user.LogoutTime), property_cv.CvProperty{}, ride),
},
IsPush: TypeToUint8(&user.IsPush),
IsLike: &isLike,
IsLikeMe: &likeMe,
WealthUserGrade: wealthGrade,
CharmUserGrade: charmGrade,
ActivityUserGrade: activityGrade,
CurrentRoom: room,
MyGroupPower: power,
MyGroupPowerName: powerName,
GroupPower: groupPower,
PhoneInfo: phoneInfo,
ThirdList: thirdList,
CountryManager: countryManager,
Cp: cp,
}
if noble != nil {
cvUserDetail.Noble = noble_cv.CvNoble{
Level: noble.Level,
EndTime: noble.EndTime.Unix(),
}
}
//本人,计算,喜欢统计,钻石数量
if user.ID == myUserId {
cvUserDetail.IsShowAge = TypeToUint8((*mysql.Type)(&user.IsShowAge))
cvUserDetail.Birthday = BirthdayToUint64(&user.Birthday)
//喜欢统计
var userCount user_m.UserCount
err := model.DB().Where(&user_m.UserCount{
UserId: myUserId,
Type: user_e.CountTypeLikeMe,
}).First(&userCount).Error
if err != nil && err != gorm.ErrRecordNotFound {
return nil, myerr.WrapErr(err)
}
cvUserDetail.LikeCount = NumToUint32(&userCount.Num)
//我喜欢统计
var userILikeCount user_m.UserCount
err = mysql.Db.Where(&user_m.UserCount{
UserId: myUserId,
Type: user_e.CountTypeLike,
}).First(&userILikeCount).Error
if err != nil && err != gorm.ErrRecordNotFound {
return nil, myerr.WrapErr(err)
}
cvUserDetail.ILikeCount = NumToUint32(&userILikeCount.Num)
//访问统计
var visitCount int64
err = mysql.Db.Model(&visit_m.UserVisit{}).Where(&visit_m.UserVisit{
VisitUserId: myUserId,
}).Count(&visitCount).Error
if err != nil && err != gorm.ErrRecordNotFound {
return nil, myerr.WrapErr(err)
}
vc := uint32(visitCount)
cvUserDetail.VisitCount = NumToUint32((*mysql.Num)(&vc))
//钻石数量
cvDiamond, err := diamond_m.GetDiamondAccountByUserId(model, myUserId)
if err != nil {
return nil, err
}
cvUserDetail.DiamondNum = &cvDiamond.DiamondNum
cvUserDetail.PinkDiamondNum = &cvDiamond.PinkDiamondNum
isAgent := user_m.IsAgent(myUserId)
cvUserDetail.IsAgentMgr = &isAgent
} else {
//不是本人
if user.IsShowAge == mysql.OPEN {
cvUserDetail.Birthday = BirthdayToUint64(&user.Birthday)
}
}
if userTradeUnion == nil {
isTradeUnionFlag := false
cvUserDetail.IsTradeUnion = &isTradeUnionFlag
cvUserDetail.IsTradeUnionMatchNotification = nil
} else {
isTradeUnionFlag := true
cvUserDetail.IsTradeUnion = &isTradeUnionFlag
isTradeUnionMatchNotificationFlag := userTradeUnion.MatchNotification == mysql.OPEN
cvUserDetail.IsTradeUnionMatchNotification = &isTradeUnionMatchNotificationFlag
}
// 永恒之心的值
hv, ok := hvMap[user.ID]
if ok {
cvUserDetail.HeartValue = hv.HeartValue
cvUserDetail.HeartValueMax = hv.HeartValueMax
cvUserDetail.MeetDays = hv.MeetDays
} else {
cvUserDetail.HeartValueMax = 0
}
// 拥有的群组id
if len(myGroups) > 0 {
cvUserDetail.GroupId = myGroups[0].TxGroupId
}
return cvUserDetail, nil
}
package user_s
import (
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-user/cv/headwear_cv"
"hilo-user/cv/medal_cv"
"hilo-user/cv/property_cv"
"time"
)
//空字符串转成nil
func StrNil(msg string) *string {
if msg == "" {
return nil
}
return &msg
}
func TypeToUint8(t *mysql.Type) *uint8 {
if *t == 0 {
return nil
} else {
return (*uint8)(t)
}
}
func BirthdayToUint64(birthday *mysql.Timestamp) *uint64 {
if *birthday == 0 {
return nil
}
return (*uint64)(birthday)
}
func NumToUint32(num *mysql.Num) *uint32 {
return (*uint32)(num)
}
func TimeToUint64(t *time.Time) *uint64 {
a := uint64(t.Unix())
return &a
}
func StrToString(str *mysql.Str) *string {
return (*string)(str)
}
func IndexToUint16(i *mysql.Index) *uint16 {
return (*uint16)(i)
}
func IdToUint64(id *mysql.ID) *uint64 {
return (*uint64)(id)
}
func IfLogout(logoutTime int64) bool {
return logoutTime > 0 && time.Now().Unix() > logoutTime
}
func IfLogoutMedals(condition bool, trueVal, falseVal []uint32) []uint32 {
if condition {
return trueVal
}
return falseVal
}
func IfLogoutMedalInfo(condition bool, trueVal, falseVal []medal_cv.CvMedal) []medal_cv.CvMedal {
if condition {
return trueVal
}
return falseVal
}
func IfLogoutHeadwear(condition bool, trueVal, falseVal *headwear_cv.CvHeadwear) *headwear_cv.CvHeadwear {
if condition {
return trueVal
}
return falseVal
}
func IfLogoutRide(condition bool, trueVal, falseVal property_cv.CvProperty) property_cv.CvProperty {
if condition {
return trueVal
}
return falseVal
}
func IfLogoutStr(condition bool, trueVal, falseVal string) string {
if condition {
return trueVal
}
return falseVal
}
func IfLogoutNick(condition bool, code string, nick string) string {
if condition {
return "Hilo No." + code
}
return nick
}
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT]
SECRET=hilo1632
ISSUER_API=hiloApi
......
......@@ -3,6 +3,7 @@ package main
import (
"fmt"
"git.hilo.cn/hilo-common/resource/consul"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-user/cron"
"hilo-user/domain/service/event_s"
"hilo-user/route"
......@@ -17,6 +18,7 @@ const (
func main() {
cron.Init() // 开启定时任务
event_s.EventInit() // 注册事件(内部事件+mysql拟kafka)
redisCli.InitCluster() // redis集群
r := route.InitRouter() // 注册路由
consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册
r.Run(fmt.Sprintf(":%d", PORT)) // 启动服务
......
......@@ -6,6 +6,7 @@ import (
var (
// 一般性错误
HttpSecret = myerr.NewBusinessCode(1000, "http secret err", myerr.BusinessData{})
TokenInvalid = myerr.NewBusinessCode(1001, "token invalid", myerr.BusinessData{})
ExternalIdNoExist = myerr.NewBusinessCode(1003, "externalId no exist", myerr.BusinessData{})
CodeNoExist = myerr.NewBusinessCode(1005, "code no exist", myerr.BusinessData{})
......@@ -26,6 +27,11 @@ var (
// 群组
GroupNotFound = myerr.NewBusinessCode(14001, "Group not found", myerr.BusinessData{}) // 找不到该群
CpAlreadyInvite = myerr.NewBusinessCode(50120, "Already invited", myerr.BusinessData{}) // 已经发送过邀请了
CpHaveCancelNoDeal = myerr.NewBusinessCode(50121, "You have a cancel apply", myerr.BusinessData{}) // 有接触申请需要处理
CpAlreadyInvite = myerr.NewBusinessCode(50120, "Already invited", 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{}) // 该用户没有邀请权限
InviteApplyAlreadyInvited = myerr.NewBusinessCode(50123, "Already invited by someone else", myerr.BusinessData{}) // 已经被别人邀请了
InviteApplyCodeInvalid = myerr.NewBusinessCode(50124, "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{}) // 今日邀请次数太多
)
CREATE TABLE `invite_apply` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`user_id` bigint NOT NULL COMMENT '发起申请者',
`new_user_id` bigint NOT NULL COMMENT '被邀请的人',
`platform` varchar(20) NOT NULL COMMENT '来自平台',
`platform_id` varchar(150) NOT NULL COMMENT '平台id',
`recharge_info` varchar(50) NOT NULL COMMENT '新用户在其它平台充值的标志',
`status` tinyint unsigned NOT NULL COMMENT '状态0.未审核1.已通过2.已拒绝',
`level` varchar(5) NOT NULL DEFAULT '' COMMENT '申请等级(S,A,B,C)',
`video_url` varchar(400) NOT NULL COMMENT '上传的视频url',
`reason` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '拒绝原因',
`sub_user_id` bigint NOT NULL COMMENT '提交人',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`) USING BTREE,
KEY `new_user_id` (`new_user_id`) USING BTREE,
KEY `platform` (`platform`) USING BTREE,
KEY `platform_id` (`platform_id`) USING BTREE,
KEY `status` (`status`) USING BTREE,
KEY `created_time` (`created_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='新人邀请申请';
INSERT INTO hilo.res_msg_translate (`language`, title, content, icon_url, msg_type, `type`, action_type, action_url)
VALUES ('en', '', 'The welcome party application of user {nick} (ID: {diamondIncome}) has been approved, the welcome party level is: {dayNum} level, inviter {beanNum} (ID: {groupCode})', '', 1, 59, 0, ''),
('tr', '', '{nick} kullanıcısının (ID: {diamondIncome}) karşılama partisi uygulaması onaylandı, karşılama partisi seviyesi: {dayNum} seviyesi, davet eden {beanNum} (ID: {groupCode})', '', 1, 59, 0, ''),
('en', '', 'The welcome party application of user {nick} (ID: {diamondIncome}) has been rejected. The reason for the rejection is: {dayNum}, inviter {beanNum} (ID: {groupCode})', '', 1, 60, 0, ''),
('tr', '', '{nick} kullanıcısının (ID: {diamondIncome}) karşılama partisi başvurusu reddedildi. Reddedilme nedeni: {dayNum}, davet eden {beanNum} (ID: {groupCode})', '', 1, 60, 0, ''),
('en', '', 'Welcome party application, please click to enter', 'https://image.whoisamy.shop/hilo/manager/welcomeparty.png', 1, 61, 1, 'https://h5.whoisamy.shop/action/hiloHtml/2023Activity/2023_7_03WelcomeParty/index.html'),
('tr', '', 'hoşgeldin partisi uygulaması, girmek için lütfen tıklayınız', 'https://image.whoisamy.shop/hilo/manager/welcomeparty.png', 1, 61, 1, 'https://h5.whoisamy.shop/action/hiloHtml/2023Activity/2023_7_03WelcomeParty/index.html');
INSERT INTO mgr_permission_config (id, parent_id, name, method_url, `type`)
VALUES(3224, 2663, '欢迎派对审核', 'POST:/v1/mgr/invite/apply?$', 0),
(3225, 2663, '欢迎派对审核-列表', 'GET:/v1/mgr/invite/apply?$', 0);
[DATABASE]
MYSQL_HOST=ua4papc3hmgqf351pbej-rw4rm.rwlb.dubai.rds.aliyuncs.com
MYSQL_USERNAME=nextvideo
MYSQL_USERNAME=hilo_user
MYSQL_PASSWORD=ihlUwI4nhi9W88MI
MYSQL_DB=hilo
[DATABASECODE]
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=r-eb3btxn8vfdsuwdbuf.redis.dubai.rds.aliyuncs.com:6379
REDIS_PASSWORD=
REDIS_CLUSTER_HOST=r-eb3yt6k8zgxs62kjjs.redis.dubai.rds.aliyuncs.com:6379
REDIS_CLUSTER_PASSWORD=
[JWT]
SECRET=hilo1504
ISSUER_API=hiloApi
......
......@@ -3,6 +3,7 @@ package resp
import (
"encoding/json"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/utils"
"github.com/gin-gonic/gin"
"hilo-user/myerr"
"hilo-user/req"
......@@ -15,6 +16,7 @@ type Response struct {
MessageData interface{} `json:"messageData"` // 消息详情
OperationMessage interface{} `json:"operationMessage"` // 操作消息
Data interface{} `json:"data"` // 数据
Edata interface{} `json:"edata"` // 加密数据
}
type GameResponse struct {
......@@ -36,7 +38,12 @@ func ResponseOk(c *gin.Context, data interface{}) {
Code: myerr.GetSuccessCode(),
Message: myerr.GetSuccessMsg(),
OperationMessage: myerr.GetSuccessMsg(),
Data: data,
}
if _, ok := c.Get(mycontext.InnerEncrypt); ok {
//response.Edata = utils.EncryptionData(data, []byte("484194d4d0f968a7"))
response.Edata = utils.EncryptionData(data, []byte("hilo!@#$%^&*()_+"))
} else {
response.Data = data
}
printResponseBody(c, &response)
......@@ -50,6 +57,38 @@ func ResponsePageBaseOk(c *gin.Context, data interface{}, nextPageIndex int, has
if data == nil {
data = make([]interface{}, 0)
}
pageData := req.PageRespBase{
NextPageIndex: nextPageIndex,
HasNextPage: hasNextPage,
Data: data,
}
response := Response{
Code: myerr.GetSuccessCode(),
Message: myerr.GetSuccessMsg(),
OperationMessage: myerr.GetSuccessMsg(),
}
if _, ok := c.Get(mycontext.InnerEncrypt); ok {
//response.Edata = utils.EncryptionData(data, []byte("484194d4d0f968a7"))
response.Edata = utils.EncryptionData(pageData, []byte("hilo!@#$%^&*()_+"))
} else {
response.Data = pageData
}
c.JSON(http.StatusOK, response)
}
// 分页返回
// 客户端入参 req.PageReqBase
// 服务端返回 req.PageRespBase
func ResponsePageOk(c *gin.Context, data interface{}, total int64, pageSize, pageIndex int) {
if data == nil {
data = make([]interface{}, 0)
}
nextPageIndex := 0
hasNextPage := false
if (pageIndex-1)*pageSize+pageSize-1 < int(total) {
nextPageIndex = pageIndex + 1
hasNextPage = true
}
response := Response{
Code: myerr.GetSuccessCode(),
Message: myerr.GetSuccessMsg(),
......
......@@ -5,6 +5,7 @@ import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"github.com/gin-gonic/gin"
"github.com/jinzhu/now"
"hilo-user/_const/enum/cp_e"
......@@ -40,6 +41,12 @@ func CpRank(c *gin.Context) (*mycontext.MyContext, error) {
if pageReq.PageIndex == 0 {
pageReq.PageIndex = 1
}
appVersion, deviceType := c.GetHeader(mycontext.APP_VERSION), c.GetHeader(mycontext.DEVICETYPE)
if deviceType == "android" {
if lower, _ := utils.CompareVersion(appVersion, fmt.Sprintf("<= %s", "3.9.0")); lower {
pageReq.PageSize = 30
}
}
queryType := c.Param("queryType")
if queryType != "day" && queryType != "week" && queryType != "month" {
return myCtx, bizerr.InvalidParameter
......@@ -74,8 +81,8 @@ func CpRank(c *gin.Context) (*mycontext.MyContext, error) {
for i, rank := range ranks {
response = append(response, cp_cv.CvCpRank{
CpId: rank.CpId,
User1: userBase[rank.UserId1],
User2: userBase[rank.UserId2],
User1: user_cv.UserBaseToUserLittle(userBase[rank.UserId1]),
User2: user_cv.UserBaseToUserLittle(userBase[rank.UserId2]),
Score: rank.Score,
Ranking: fmt.Sprintf("%d", i+1+offset),
CpLevel: cp_cv.CvCpLevel{
......@@ -136,8 +143,8 @@ func CpTop3(c *gin.Context) (*mycontext.MyContext, error) {
if queryType == "day" {
response.Day = append(response.Day, cp_cv.CvCpRank{
CpId: rank.CpId,
User1: userBase[rank.UserId1],
User2: userBase[rank.UserId2],
User1: user_cv.UserBaseToUserLittle(userBase[rank.UserId1]),
User2: user_cv.UserBaseToUserLittle(userBase[rank.UserId2]),
Score: rank.Score,
Ranking: fmt.Sprintf("%d", i+1+offset),
CpLevel: cp_cv.CvCpLevel{
......@@ -147,8 +154,8 @@ func CpTop3(c *gin.Context) (*mycontext.MyContext, error) {
} else {
response.Week = append(response.Week, cp_cv.CvCpRank{
CpId: rank.CpId,
User1: userBase[rank.UserId1],
User2: userBase[rank.UserId2],
User1: user_cv.UserBaseToUserLittle(userBase[rank.UserId1]),
User2: user_cv.UserBaseToUserLittle(userBase[rank.UserId2]),
Score: rank.Score,
Ranking: fmt.Sprintf("%d", i+1+offset),
CpLevel: cp_cv.CvCpLevel{
......@@ -217,10 +224,10 @@ func CpMy(c *gin.Context) (*mycontext.MyContext, error) {
Score: scores,
}
if relation.UserId1 > 0 {
response.User1 = userBases[relation.UserId1]
response.User1 = user_cv.UserBaseToUserLittle(userBases[relation.UserId1])
}
if relation.UserId2 > 0 {
response.User2 = userBases[relation.UserId2]
response.User2 = user_cv.UserBaseToUserLittle(userBases[relation.UserId2])
response.Ranking = "30+"
ranks := cp_m.PageCpDayRank(model, beginDate, endDate, 0, 30)
for i, rank := range ranks {
......
package invite_r
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/utils"
"github.com/gin-gonic/gin"
"github.com/jinzhu/now"
"hilo-user/cv/invite_cv"
"hilo-user/domain/cache/user_c"
"hilo-user/domain/model/invite_m"
"hilo-user/domain/model/promotion_m"
"hilo-user/domain/model/user_m"
"hilo-user/myerr/bizerr"
"hilo-user/req"
"hilo-user/resp"
"time"
)
// @Tags 新人邀请
// @Summary 提交申请
// @Param newUserCode formData string true "被邀请人id"
// @Param platform formData string true "平台"
// @Param platformId formData string true "平台Id"
// @Param recharge formData string true "充值金额"
// @Param userCode formData string true "邀请人id"
// @Param videoUrl formData string true "充值金额"
// @Success 200
// @Router /v2/user/invite/apply [post]
func InviteApply(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
type paramStr struct {
NewUserCode string `form:"newUserCode" binding:"required"`
Platform string `form:"platform" binding:"required"`
PlatformId string `form:"platformId" binding:"required"`
Recharge string `form:"recharge" binding:"required"`
UserCode string `form:"userCode" binding:"required"`
VideoUrl string `form:"videoUrl" binding:"required"`
}
myUserId, err := req.GetUserId(c)
if err != nil {
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
if err := c.ShouldBind(&param); err != nil {
return myCtx, err
}
// 平台是否填写正确
platforms := promotion_m.GetPromotionPlatforms(model)
var existsPlatform bool
for _, v := range platforms {
if v == param.Platform {
existsPlatform = true
}
}
if !existsPlatform {
model.Log.Errorf("InviteApply param:%v", param)
return myCtx, bizerr.InvalidParameter
}
// code 是否存在
newUser, err := user_m.GetUserByCode(model, param.NewUserCode)
if err != nil {
model.Log.Errorf("InviteApply param:%v", param)
return myCtx, bizerr.InviteApplyNewCodeInvalid
}
user, err := user_m.GetUserByCode(model, param.UserCode)
if err != nil {
model.Log.Errorf("InviteApply param:%v", param)
return myCtx, bizerr.InviteApplyCodeInvalid
}
//if user.ID != myUserId { //只能自己提交
// return myCtx, bizerr.InvalidParameter
//}
if newUser.ID == 0 || user.ID == 0 {
model.Log.Errorf("InviteApply param:%v", param)
return myCtx, bizerr.InvalidParameter
}
// 邀请人是否有资格邀请
if !promotion_m.IsPromotionAgent(model, user.ID) {
model.Log.Errorf("InviteApply 没有邀请资格 param:%v", param)
return myCtx, bizerr.InviteApplyNoPermission
}
//if user.ID != myUserId && !promotion_m.IsMyPromotionManager(model, user.ID, myUserId) {
// model.Log.Errorf("InviteApply 没有邀请资格 param:%v", param)
// return myCtx, bizerr.InviteApplyNoPermission
//}
// 被邀请人是否已经被人提交过申请
isApply, err := invite_m.IsInInviteApply(model, newUser.ID)
if err != nil {
model.Log.Errorf("InviteApply param:%v, err:%v", param, err)
return myCtx, err
}
if isApply {
model.Log.Errorf("InviteApply 已经被别人邀请过了 param:%v", param)
return myCtx, bizerr.InviteApplyAlreadyInvited
}
// 被邀请人是否符合条件
isInvite, err := promotion_m.IsPromotionInvitee(model, newUser.ID)
if err != nil {
model.Log.Errorf("InviteApply param:%v", param)
return myCtx, err
}
if isInvite {
model.Log.Errorf("InviteApply 已经被别人邀请了 param:%v", param)
return myCtx, bizerr.InviteApplyAlreadyInvited
}
// 插入邀请表
err = invite_m.CreateInviteApply(model, user.ID, newUser.ID, myUserId, param.Platform, param.PlatformId, param.Recharge, param.VideoUrl)
if err != nil {
model.Log.Errorf("InviteApply param:%v", param)
return myCtx, err
}
resp.ResponseOk(c, nil)
return myCtx, nil
}
// @Tags 新人邀请
// @Summary 查询历史申请
// @Param pageIndex query int true "偏移值 默认:1" default(1)
// @Param pageSize query int true "请求数量 默认:10" default(10)
// @Param beginTime query string true "开始时间2006-01-02"
// @Param endTime query string true "结束时间2006-01-02"
// @Param type query int true "1.已申请2.待审核3.已通过4.已拒绝"
// @Success 200 {object} invite_cv.InviteApplyRes
// @Router /v2/user/invite/apply [get]
func InviteApplyList(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
type paramStr struct {
PageIndex int `form:"pageIndex" binding:"required"`
PageSize int `form:"pageSize" binding:"required"`
BeginTime time.Time `form:"beginTime" binding:"required" time_format:"2006-01-02"`
EndTime time.Time `form:"endTime" binding:"required" time_format:"2006-01-02"`
Type int `form:"type"`
}
var param paramStr
if err := c.ShouldBindQuery(&param); err != nil {
return myCtx, err
}
if param.Type < 0 || param.Type > 4 {
return myCtx, bizerr.InvalidParameter
}
//beginTime, err := time.ParseInLocation(utils.DATE_FORMAT, param.BeginTime, time.Local)
//if err != nil {
// return nil, myerr.WrapErr(err)
//}
//endTime, err := time.ParseInLocation(utils.DATE_FORMAT, param.EndTime, time.Local)
//if err != nil {
// return nil, myerr.WrapErr(err)
//}
param.EndTime = utils.GetDayEndTime(param.EndTime)
userId, err := req.GetUserId(c)
if err != nil {
return myCtx, err
}
var model = domain.CreateModelContext(myCtx)
agentIds := []uint64{userId}
if promotion_m.IsPromotionManager(model, userId) {
agentIds, err = promotion_m.GetPromotionManagerAgentList(model, userId)
if err != nil {
return myCtx, err
}
}
if param.Type == 0 { // 返回所有Type类型有多少条数
user, err := user_c.GetUserTinyById(model, userId)
if err != nil {
model.Log.Errorf("GetApplyList param:%v, err:%v", param, err)
return myCtx, bizerr.InvalidParameter
}
numList := make([]*invite_cv.InviteApplyNumRes, 0, 4)
for _, gType := range []int{1, 2, 3, 4} { // 1.已申请2.待审核3.已通过4.已拒绝
num, err := invite_m.GetInviteApplyNumByType(model, gType, param.BeginTime, param.EndTime, agentIds, userId)
if err != nil {
return myCtx, err
}
numList = append(numList, &invite_cv.InviteApplyNumRes{Type: gType, Num: num})
}
resp.ResponsePageOk(c, &invite_cv.InviteApplyRes{NumList: numList, MyCode: user.Code}, 0, 0, 0)
return myCtx, nil
}
list, total, err := invite_m.GetApplyList(model, userId, agentIds, param.PageIndex, param.PageSize, param.Type, param.BeginTime, param.EndTime)
if err != nil {
model.Log.Errorf("GetApplyList param:%v, err:%v", param, err)
return myCtx, err
}
uids := make([]uint64, 0, len(list)+1)
for _, v := range list {
uids = append(uids, v.UserId, v.NewUserId)
}
users, err := user_c.GetUserTinyMap(model, uids, true)
if err != nil {
model.Log.Errorf("GetApplyList param:%v, err:%v", param, err)
return myCtx, err
}
res := &invite_cv.InviteApplyRes{}
res.List = make([]*invite_cv.InviteApply, 0, len(list))
for _, v := range list {
res.List = append(res.List, &invite_cv.InviteApply{
NewUserCode: users[v.NewUserId].Code,
Platform: v.Platform,
Recharge: v.RechargeInfo,
UserCode: users[v.UserId].Code,
CreateUnix: v.CreatedTime.Unix(),
Level: v.Level,
Status: v.Status,
Avatar: users[v.NewUserId].Avatar,
ExternalId: users[v.NewUserId].ExternalId,
Reason: v.Reason,
Country: users[v.NewUserId].Country,
PlatformId: v.PlatformId,
})
}
resp.ResponsePageOk(c, res, total, param.PageSize, param.PageIndex)
return myCtx, nil
}
// @tags 新人邀请
// @Summary 平台列表
// @Success 200 {object} []string
// @Router /v2/user/invite/platform [get]
func PromotionPlatform(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
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", "Oye Talk", "Tiktok", "Bigo", "Mr7ba"})
return myCtx, nil
}
// @Tags 新人邀请
// @Summary 查询周期
// @Success 200 {object} invite_cv.AgentPeriod
// @Router /v2/user/invite/period [get]
func AgentPeriod(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
var response invite_cv.AgentPeriod
week := now.BeginningOfWeek().AddDate(0, 0, 1) // 周一开始
for i := 0; i < 12; i++ {
response.Week = append(response.Week, invite_cv.AgentPeriodWeek{
StartDate: week.Format("2006-01-02"),
EndDate: week.AddDate(0, 0, 6).Format("2006-01-02"),
})
week = week.AddDate(0, 0, -7)
}
resp.ResponseOk(c, response)
return myCtx, nil
}
......@@ -2,9 +2,12 @@ package route
import (
"bytes"
"crypto/md5"
"fmt"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/utils"
"github.com/gin-gonic/gin"
"hilo-user/myerr/bizerr"
"hilo-user/req"
......@@ -12,6 +15,7 @@ import (
"hilo-user/resp"
"io/ioutil"
"runtime/debug"
"strconv"
"strings"
"time"
)
......@@ -133,3 +137,66 @@ func LoggerHandle(c *gin.Context) {
latency := end.Sub(start)
mycontext.CreateMyContext(c.Keys).Log.Infof("request end fullPath:%v,url:%v, method: %v, traceId:%v, latency:%v userId:%v", c.FullPath(), reqUri, method, traceId, latency, userId)
}
// 加密Handle
func EncryptHandle(c *gin.Context) {
header := c.Request.Header
appVersion := header.Get("Appversion")
if len(appVersion) > 0 {
if high, _ := utils.CompareVersion(appVersion, "> 3.9.0"); high {
c.Set(mycontext.InnerEncrypt, true)
}
}
c.Next()
}
//http信息解密(web)
func HttpWebSecretHandle(c *gin.Context) {
traceId, _ := c.Keys[mycontext.TRACEID]
timestamp := c.GetHeader("timestamp") //时间戳,单位秒
nonce := c.GetHeader("nonce") //随机数字
signature := c.GetHeader("signature") //sha1加密结果
mylogrus.MyLog.Debugf("handle secret begin timestamp:%v, nonce:%v, signature:%v traceId:%v", timestamp, nonce, signature, traceId)
if nonce == "hilo" {
mylogrus.MyLog.Infof("no check http secret handle")
} else {
if timestamp == "" || nonce == "" || signature == "" {
resp.ResponseBusiness(c, bizerr.HttpSecret)
c.Abort()
return
}
timestampInt, err := strconv.ParseInt(timestamp, 10, 64)
if err != nil {
resp.ResponseBusiness(c, bizerr.HttpSecret)
c.Abort()
return
}
nowTimestamp := time.Now().Unix()
v := nowTimestamp - timestampInt
//10分钟内有效,改成60分钟,20210402产品让我改成60分钟,原因:依旧有用户时间戳不对,达到了30分钟
if v < -60*60 || v > 60*60 {
mylogrus.MyLog.Warnf("handle secret err, timestampInt:%v, nowTimestamp:%v, v:%v, traceId:%v", timestampInt, nowTimestamp, v, traceId)
//2021/11/05 产品让我关的,因为中东用户时间戳有问题
/* ResponseBusiness(c, bizerr.HttpSecret)
c.Abort()
return*/
}
str := timestamp + config.GetConfigApp().WEB_SECRET + nonce
//避免web的暴露,让用户知道app的api加密方式。
h := md5.New()
//h := sha1.New()
h.Write([]byte(str))
newSignature := fmt.Sprintf("%x", h.Sum(nil))
//newSignature := string(sha1.New().Sum([]byte(str))[:])
if signature != newSignature {
mylogrus.MyLog.Errorf("handle secret err signature:%v, newSignature:%v, traceId:%v", signature, newSignature, traceId)
resp.ResponseBusiness(c, bizerr.HttpSecret)
c.Abort()
return
}
}
c.Next()
}
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
}
......@@ -12,6 +12,8 @@ import (
"hilo-user/domain/model/msg_m"
"hilo-user/resp"
"hilo-user/route/cp_r"
"hilo-user/route/invite_r"
"hilo-user/route/recommend_r"
"hilo-user/route/user_r"
)
......@@ -28,6 +30,8 @@ func InitRouter() *gin.Engine {
{
user.GET("/nameplate", wrapper(user_r.UserNameplate))
user.GET("/bag/:resType", wrapper(user_r.UserBag))
user.GET("/detail", EncryptHandle, wrapper(user_r.UserDetail))
user.GET("/detail/:userExternalId", EncryptHandle, wrapper(user_r.UserDetailByExternalId))
}
cp := v2.Group("/cp")
{
......@@ -50,6 +54,19 @@ func InitRouter() *gin.Engine {
//cp.GET("/relation/detail", wrapper(cp_r.CpDetailPage))
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.POST("/invite/apply", wrapper(invite_r.InviteApply))
userV2.GET("/invite/apply", wrapper(invite_r.InviteApplyList))
userV2.GET("/invite/platform", wrapper(invite_r.PromotionPlatform))
userV2.GET("/invite/period", wrapper(invite_r.AgentPeriod))
userV2.GET("/detail/room", EncryptHandle, wrapper(user_r.GetUserDetailInRoom))
}
inner := r.Group("/inner")
inner.Use(ExceptionHandle, LoggerHandle)
innerUser := inner.Group("/user")
......@@ -59,6 +76,8 @@ func InitRouter() *gin.Engine {
innerUser.GET("/cp", wrapper(user_r.GetUserCp))
innerUser.GET("/cpRelations", wrapper(user_r.MGetUserCpRelation))
innerUser.GET("/cp/pair", wrapper(user_r.GetUserCpPair))
innerUser.GET("/cp/entryEffect", wrapper(user_r.GetUserCpEntryEffect)) // 获取cp进场特效信息,高频接口,需要额外处理
innerUser.GET("/svipNobleLevel", wrapper(user_r.MGetUserSvipNobleLevel)) // 获取用户svip/noble/level等信息
}
// 道具相关
innerProp := inner.Group("/prop")
......
......@@ -46,22 +46,24 @@ func UserBag(c *gin.Context) (*mycontext.MyContext, error) {
for _, bagGift := range userBagGifts {
if gift, ok := allGifts[bagGift.ResId]; ok {
info := user_cv.UserBag{
BagId: bagGift.ID,
ResType: res_e.ResUserBagGift,
ResId: gift.ID,
GiftId: gift.ID,
Name: gift.Name,
DiamondNum: gift.DiamondNum,
IconUrl: gift.IconUrl,
SvgaUrl: gift.SvagUrl,
Count: bagGift.Count,
RemainDays: int(bagGift.EndTime.Sub(time.Now()).Hours() / 24),
BagId: bagGift.ID,
ResType: res_e.ResUserBagGift,
ResId: gift.ID,
GiftId: gift.ID,
Name: gift.Name,
DiamondNum: gift.DiamondNum,
IconUrl: gift.IconUrl,
SvgaUrl: gift.SvagUrl,
Count: bagGift.Count,
RemainDays: int(bagGift.EndTime.Sub(time.Now()).Hours() / 24),
HasGiftText: gift.HasGiftText,
}
if gift.ID == cp_e.CpConfessionGiftId { // 如果是cp告白礼物
if gift.ID == cp_e.CpConfessionGiftId || gift.HasGiftText { // 如果是cp告白礼物
info.TextStyleList = make([]*user_cv.TextStyle, 0, 2)
info.TextStyleList = append(info.TextStyleList,
&user_cv.TextStyle{TextColor: "#ce0083", TextSize: 20, TextKey: "sender_name"},
&user_cv.TextStyle{TextColor: "#ce0083", TextSize: 20, TextKey: "receiver_name"},
&user_cv.TextStyle{TextColor: "#FFFFFF", TextSize: 40, TextKey: "gift_text"},
)
}
......
......@@ -4,10 +4,13 @@ import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/rpc"
"github.com/gin-gonic/gin"
"hilo-user/_const/enum/cp_e"
"hilo-user/cv/cp_cv"
"hilo-user/cv/noble_cv"
"hilo-user/cv/user_cv"
"hilo-user/domain/cache/user_c"
"hilo-user/domain/model/bag_m"
"hilo-user/domain/model/cp_m"
"hilo-user/domain/model/noble_m"
......@@ -55,6 +58,62 @@ func MGetUserLevels(c *gin.Context) (*mycontext.MyContext, error) {
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 {
BagId mysql.ID `form:"bagId" binding:"required"`
}
......@@ -260,3 +319,60 @@ func GetUserCpPair(c *gin.Context) (*mycontext.MyContext, error) {
resp.ResponseOk(c, response)
return myContext, nil
}
// @Tags 用户-内部
// @Summary 获取用户cpEffect
// @Param id query int true "用户id"
// @Param language query string true "语言"
// @Success 200 {object} cp_cv.CvCpEntryEffect
// @Router /inner/user/cp/entryEffect [get]
func GetUserCpEntryEffect(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
var model = domain.CreateModelContext(myContext)
var req GetUserCpReq
if err := c.ShouldBindQuery(&req); err != nil {
return myContext, err
}
userId := req.Id
var response cp_cv.CvCpEntryEffect
cpLevel := cp_e.CpLevel0
cpRelation, exists := cp_m.GetCpRelation(model, userId)
if !exists {
resp.ResponseOk(c, response)
return myContext, nil
}
level := cp_m.GetCpLevel(model, cpRelation.Id)
if level.ExpireAt.Before(time.Now()) {
level.ExpireAt = time.Now().AddDate(0, 1, 0)
}
cpLevel = level.Level
cpUserId := cpRelation.UserId2
if cpUserId == userId {
cpUserId = cpRelation.UserId1
}
response.CpLevel = cpLevel
userPrivileges, err := cp_m.MGetUserSvipPrivilege(model, []uint64{userId})
if err != nil {
return myContext, err
}
privilegeList := cp_cv.CopyCpLevelPrivilegeList(level.Level, "en")
for i, v := range privilegeList {
if v.CanSwitch {
privilegeList[i].UserSwitch = userPrivileges[userId][v.Type]
}
}
// 二级以上才有进场特效
if cpLevel >= cp_e.CpLevel2 {
for _, v := range privilegeList {
if v.Type == cp_e.CpPrivilegeRoomEffect && v.UserSwitch {
response.CpEntryEffect = true
}
}
}
if cpUser, _ := user_c.GetUserTinyById(model, cpUserId); cpUser != nil {
response.CpUserAvatar = cpUser.Avatar
}
resp.ResponseOk(c, response)
return myContext, nil
}
package user_r
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"github.com/gin-gonic/gin"
"hilo-user/_const/redis_key/user_k"
"hilo-user/cv/user_cv"
"hilo-user/domain/model/group_m"
"hilo-user/domain/model/tim_m"
"hilo-user/domain/service/user_s"
"hilo-user/req"
"hilo-user/resp"
"time"
)
// @Tags 用户
// @Summary 获取用户详细信息
// @Param token header string true "token"
// @Param timestamp header string true "时间戳"
// @Param nonce header string true "随机数字"
// @Param signature header string true "sha1加密结果"
// @Param deviceType header string true "系统类型 ios android"
// @Param deviceVersion header string true "系统版本"
// @Success 200 {object} user_cv.CvUserDetail
// @Router /v1/user/detail [get]
func UserDetail(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, lang, err := req.GetUserIdLang(c, myContext)
if err != nil {
return myContext, err
}
cvUserDetail, err := user_s.NewUserService(myContext).GetUserDetail(userId, userId, lang)
if err != nil {
return myContext, err
}
resp.ResponseOk(c, cvUserDetail)
return myContext, nil
}
// @Tags 用户
// @Summary 获取用户详细信息
// @Param token header string true "token"
// @Param timestamp header string true "时间戳"
// @Param nonce header string true "随机数字"
// @Param signature header string true "sha1加密结果"
// @Param deviceType header string true "系统类型 ios android"
// @Param deviceVersion header string true "系统版本"
// @Param userExternalId path string true "userExternalId"
// @Param groupId query string false "群组id,当传了该id,则返回该用户在该群组的身份"
// @Success 200 {object} user_cv.CvUserDetail
// @Router /v1/user/detail/{userExternalId} [get]
func UserDetailByExternalId(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, mysql.Str(c.Param("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, cvUserDetail)
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
}