...
 
Commits (296)
package groupPower_e
import "git.hilo.cn/hilo-common/resource/mysql"
//国家势力状态
type GroupPowerStatus = mysql.Type
type GroupPowerStatus = uint8
const (
//上架
......@@ -15,7 +13,7 @@ const (
)
//国家势力用户角色
type GroupPowerUserRole = mysql.Type
type GroupPowerUserRole = uint8
const (
//普通用户
......@@ -27,7 +25,7 @@ const (
)
//国家势力排行榜类型
type GroupPowerRankType = mysql.Type
type GroupPowerRankType = uint8
const (
GroupPowerRankTypeFamous GroupPowerRankType = 1
......@@ -36,7 +34,7 @@ const (
)
//国家势力日志操作类型
type GroupPowerUserLogType = mysql.Type
type GroupPowerUserLogType = uint8
const (
//加入
......@@ -51,7 +49,7 @@ const (
GroupPowerUserLogDissolve GroupPowerUserLogType = 5
)
type GroupPowerDiamondLogType = mysql.Type
type GroupPowerDiamondLogType = uint8
const (
//群组原因加入
......@@ -67,3 +65,7 @@ const (
PowerSuppportAwarded PowerSupportAwardState = 1 // 已经领取
PowerSuppportWaiting PowerSupportAwardState = 2 // 待领取
)
const (
LongestNameplate = 15
)
......@@ -156,3 +156,11 @@ var GROUP_NOBLE4_JOIN_LIMIT uint = 1000
var GROUP_ROLE_PERSONAL_VIEW_LIMIT = 5
var GROUP_MANAGER_LIMIT uint = 30
var GROUP_ADMIN_LIMIT uint = 50
type GroupProvider = uint8
const (
// 群组声音供应商
GroupProvider_SW GroupProvider = 0 // 声网
GroupProvider_TRTC GroupProvider = 1 // 腾讯trtc
)
package groupPower_k
import (
"fmt"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key"
)
// 家族之星榜单
// type: 1:送礼 2:活跃 3:收礼
// date:天/周/月的开始时间
const GroupPowerStarPrefix = "groupPowerStar:${type}:${period}:${groupPowerId}:${date}" // zset member:userId score:分数
func GetGroupPowerStarRankKey(_type groupPower_e.GroupPowerStarType, period string, groupPowerId uint64, date string) string {
return redis_key.ReplaceKey(GroupPowerStarPrefix,
fmt.Sprintf("%d", _type), period, fmt.Sprintf("%d", groupPowerId), date)
}
package group_k
import (
"fmt"
"hilo-group/_const/redis_key"
)
// 用户进房的key
const (
UserEnterRoomPrefix = "uer:"
UserEnterRoomUserKey = UserEnterRoomPrefix + "u:${user_id}"
UserEnterRoomGroupKey = UserEnterRoomPrefix + "g:${group_id}"
)
func GetUserEnterRoomUserKey(userId uint64) string {
return redis_key.ReplaceKey(UserEnterRoomUserKey, fmt.Sprintf("%d", userId))
}
func GetUserEnterRoomGroupKey(groupId string) string {
return redis_key.ReplaceKey(UserEnterRoomGroupKey, groupId)
}
......@@ -10,9 +10,33 @@ import (
const (
MicPrefix = "mic:"
MicDayInvite = MicPrefix + "day:invite:${userId}:${date}" // string 自动被邀请上麦,1天一次,TTL:24H
MicGroupPowerOnMic = MicPrefix + "groupPower:${userId}:${date}" // 家族内群上麦分钟数
MicUserOnMic = MicPrefix + "user:onMic:${tz}:${userId}:${date}"
MicGroupOnMic = MicPrefix + "group:onMic:${groupId}" // 在群组麦位上的人 hset field:micIndex member:userId
)
func GetUserMicDayInvite(userId mysql.ID) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicDayInvite, fmt.Sprintf("%d", userId), date)
}
// 家族内群上麦分钟数
func GetMicGroupPowerOnMic(userId uint64) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicGroupPowerOnMic, fmt.Sprintf("%d", userId), date)
}
// 获取用户上麦时间
// 北京、沙特时间
func GetUserOnMicKey(userId uint64, tz, date string) string {
return redis_key.ReplaceKey(MicUserOnMic, tz, fmt.Sprintf("%d", userId), date)
}
// 获取群组麦位上的人
// 可能会有数据不一致,已原来麦位的key为准
// 这里用户快速获取群上麦位的人用,代替大量mget命令慢查询
func GetGroupOnMicUser(groupId string) string {
return redis_key.ReplaceKey(MicGroupOnMic, groupId)
}
package mic_k
// onMic异步入库
const (
OnMicQueue = "onMic:hilo_group"
)
func GetOnMicQueue() string {
return OnMicQueue
}
......@@ -249,6 +249,9 @@ const groupInUserDuration = "group_in_user_duration_{groupUuid}"
// 15天内进入房间的人数
const roomVisitCount = "room_visit_count"
// 15天内进入房间的人数 member groupId score 麦位有人的数量
const roomVisitCountZSet = "room_visit_count_zset"
// 用户进入过的房间及时间
const userEnterRoom = "enter_room_{userId}"
......@@ -261,6 +264,9 @@ const groupPowerDiamond = "group_diamond_{period}"
// 国家Icon
const countryIcon = "contry_icon"
// 国家Area
const countryArea = "contry:area"
// 群贡献前三
const groupTop3Consume = "group_top3_consume_{period}_{groupId}"
......@@ -754,18 +760,27 @@ func GetPrefixGroupMicNumType(groupUuid string) string {
return strings.Replace(groupMicNumType, "{groupUuid}", groupUuid, -1)
}
// Deprecated: 用户进房时间
// 用 uer:g:${group_id}代替
func GetPrefixGroupInUserDuration(groupUuid string) string {
return strings.Replace(groupInUserDuration, "{groupUuid}", groupUuid, -1)
}
// Deprecated: 用户进房时间
// 可用 uer:u:${user_id}代替
func GetUserEnterRoomKey(userId uint64) string {
return strings.Replace(userEnterRoom, "{userId}", strconv.FormatUint(userId, 10), -1)
}
// Deprecated: 用redis集群中的zset代替
func GetPrefixRoomVisitCount() string {
return roomVisitCount
}
func GetPrefixRoomVisitCountZset() string {
return roomVisitCountZSet
}
func GetPrefixSupportLevel(date string) string {
return strings.Replace(supportLevel, "{date}", date, -1)
}
......@@ -778,6 +793,10 @@ func GetCountryIconKey() string {
return countryIcon
}
func GetCountryAreaKey() string {
return countryArea
}
func GetGroupTop3ConsumeKey(period string, groupId string) string {
return strings.Replace(strings.Replace(groupTop3Consume, "{period}", period, -1), "groupId", groupId, -1)
}
......
......@@ -107,6 +107,9 @@ const (
MSG_ID_BUY_FROM_FAMILY MsgIdType = 167 // 请向本家族代理购买钻石
MSG_ID_NEED_JOIN_FAMILY MsgIdType = 168 // 请加入代理的家族后进行购买
MSG_ID_SET_FAMILY_NAMEPL MsgIdType = 169 // 等级不够不能修改家族铭牌
MSG_ID_CHARGE_NO_AREA MsgIdType = 181 // 充值(代理转账,用户给代理充值),失败,不是本区域用户
MSG_ID_BAN_MIC_NOBLE_5 MsgIdType = 188 //无法禁言VIP5和vip6
MSG_ID_KICK_NOBLE_5 MsgIdType = 189 //无法踢出VIP5和vip6
ADD_GROUP_FAILED AddGroupResultType = 0
ADD_GROUP_DONE AddGroupResultType = 1
......
......@@ -5,14 +5,24 @@ import (
"hilo-group/cron/gift_cron"
"hilo-group/cron/group_cron"
"hilo-group/cron/mic_cron"
"hilo-group/cron/user_cron"
)
func Init() {
user_cron.LoadSvipVipNoble() // 加载用户特权
if !config.IsMaster() {
return
}
gift_cron.SendGiftEventInit() // 礼物消息
gift_cron.GiftRemark() // 礼物消息补偿
//gift_cron.SendGiftEventInit() // 礼物消息
//gift_cron.GiftRemark() // 礼物消息补偿
gift_cron.SendGiftEvent() // 礼物事件
mic_cron.OnMicCheck() // 检查上麦
mic_cron.OnMicQueue() // 检查上麦-队列操作
group_cron.GroupPowerExpClear() // 清理家族经验/等级
group_cron.GroupPowerMonthRankAct()
//group_cron.GroupInEventInit() // 进房事件
//group_cron.CreateGroup() //
group_cron.CalcGroupSupport() // 群组扶持计算
//group_cron.CalcGroupSupport_OldData()
group_cron.GroupCountryListSort()
}
......@@ -30,6 +30,7 @@ func GiftRemark() {
Payload: unmark.Payload,
MarkHiloGroup: unmark.MarkHiloGroup,
Mark: unmark.Mark, // 不能影响别的服务的mark状态
MarkHiloUser: unmark.MarkHiloUser,
}); err != nil {
model.Log.Errorf("FetchUnMarkEvent add unmark fail:%v", err)
continue
......
package gift_cron
import (
"context"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/domain/cache/gift_c"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/event/gift_ev"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m"
"time"
)
// 送礼事件
func SendGiftEvent() {
//if !config.IsMaster() {
// return
//}
go func() {
for true {
model := domain.CreateModelNil()
if sendGiftEvent := gift_c.BLPopQueueSendGift(model); sendGiftEvent != nil {
groupPowerGrade(model, sendGiftEvent) // 家族经验
groupPowerStar(model, sendGiftEvent) // 家族之星
groupSupportAddConsume(model, sendGiftEvent) // 群组扶持
}
}
}()
}
// 群组势力经验
func groupPowerGrade(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent)
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return
}
exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId)
if err != nil {
model.Log.Infof("CheckGroupPowerUser fail %+v", err)
return
}
if exist {
exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum
//return model.Transaction(func(model *domain.Model) error {
// return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
//})
//return groupPower_c.QueueGroupPowerGradeExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
if err := model.Transaction(func(model *domain.Model) error {
return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
}); err != nil {
model.Log.Errorf("IncrGroupPowerExp fail,data:%v-err:%v", *sendGiftEvent, err)
} else {
model.Log.Infof("IncrGroupPowerExp success,data:%v", *sendGiftEvent)
}
}
}
// 家族之星
func groupPowerStar(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return
}
var userIds = []mysql.ID{sendGiftEvent.SendUserId}
userIds = append(userIds, sendGiftEvent.ReceiveUserIds...)
groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds)
if err != nil {
model.Log.Errorf("AddSendGiftEventAsync fail:%v", err)
return
}
// 送礼加分
if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
if err := groupPower_c.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId,
groupPower_e.GroupPowerStarTypeFamous, diamonds); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore famous fail:%v", err)
}
}
// 收礼加分
for _, userId := range sendGiftEvent.ReceiveUserIds {
if data, ok := groupPowers[userId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum
if err := groupPower_c.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId,
groupPower_e.GroupPowerStarTypeCharm, diamonds); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore charm fail:%v", err)
}
}
}
return
}
// 群组扶持增加流水数据
func groupSupportAddConsume(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
if time.Now().Unix() <= 1693275900 {
return
}
model.Log.Infof("groupSupportAddConsume UserId:%d, sendGiftEvent:%+v", sendGiftEvent.SendUserId, sendGiftEvent)
if sendGiftEvent.SceneType != gift_e.GroupSceneType || sendGiftEvent.SceneUid == "" {
model.Log.Infof("groupSupportAddConsume UserId:%d, sendGiftEvent:%+v", sendGiftEvent.SendUserId, sendGiftEvent)
return
}
_, _, period := group_m.GetSupportLevelTime(time.Now())
// 钻石数
diamond := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
_, err := model.RedisCluster.ZIncrBy(context.Background(), keyDiamond, float64(diamond), sendGiftEvent.SceneUid).Result()
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, val:%d, member:%s, err:%v",
keyDiamond, diamond, sendGiftEvent.SceneUid, err)
}
err = redisCli.SetExpire(model.RedisCluster, keyDiamond, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, val:%d, member:%s, err:%v",
keyDiamond, diamond, sendGiftEvent.SceneUid, err)
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, sendGiftEvent.SceneUid)
err = model.RedisCluster.SAdd(context.Background(), keySupportNum, sendGiftEvent.SendUserId).Err()
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, UserId:%d, err:%v", keySupportNum, sendGiftEvent.SendUserId, err)
}
err = redisCli.SetExpire(model.RedisCluster, keySupportNum, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, UserId:%d, err:%v", keySupportNum, sendGiftEvent.SendUserId, err)
}
return
}
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/_const/enum/group_e"
"hilo-group/domain/service/group_s"
)
func CreateGroup() {
if !config.IsMaster() {
return
}
c := cron.New()
spec := "0 15 15 16 8 ?"
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
userId := uint64(7687)
num := 20
if config.AppIsRelease() {
userId = 8350311
num = 1000
}
err := group_s.NewGroupService(model.MyContext).CreateGroupMulByUid(userId, num, group_e.TwoMicNumType)
if err != nil {
model.Log.Errorf("CreateGroupMulByUid fail:%v", err)
}
})
c.Start()
}
package group_cron
import (
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"hilo-group/domain/service/event_s"
"time"
)
// 进房事件
func GroupInEventInit() {
if !config.IsMaster() {
return
}
mylogrus.MyLog.Infof("GroupInEventInit")
go func() {
ticker := time.NewTicker(time.Millisecond * 500)
defer ticker.Stop()
for {
select {
case <-ticker.C:
//start := time.Now()
myCtx := mycontext.CreateMyContext(nil)
// 消费进房事件
if err := event_s.NewGroupInEventService(myCtx).Consume(); err != nil {
myCtx.Log.Errorf("groupInEvent consume fail:%v", err)
} else {
//myCtx.Log.Infof("groupInEvent consume success,cost:%v", time.Now().Sub(start))
}
}
}
}()
}
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/domain/service/group_s"
)
// 清理家族经验和等级
func GroupCountryListSort() {
// 常用国家-每15分钟计算国家房间列表排序 /v1/imGroup/country [get] 接口
spec := "0 */15 * * * ?"
c := cron.New()
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
model.Log.Infof("GroupCountryListSort Common start")
group_s.SortGroupCommonCountryList(model)
model.Log.Infof("GroupCountryListSort Common end")
})
// 非常用国家-每60分钟计算国家房间列表排序 /v1/imGroup/country [get] 接口
spec2 := "0 59 * * * ?"
_ = c.AddFunc(spec2, func() {
var model = domain.CreateModelNil()
model.Log.Infof("GroupCountryListSort not Common start")
group_s.SortGroupNotCommonCountryList(model)
model.Log.Infof("GroupCountryListSort not Common end")
})
c.Start()
}
......@@ -2,7 +2,6 @@ package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/domain/event/group_power_ev"
"hilo-group/domain/model/groupPower_m"
......@@ -30,9 +29,6 @@ func GroupPowerExpClear() {
})
// 每月20号发家族即将过期通知
spec = "0 0 0 20 * ?"
if !config.AppIsRelease() {
spec = "0 0 */1 * * ?"
}
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
_ = group_power_ev.PublishGroupPowerExpireNotice(model, &group_power_ev.GroupPowerExpireNoticeEvent{})
......
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/domain/service/group_power_s"
)
// 家族贡献月度排行榜发奖
func GroupPowerMonthRankAct() {
if !config.IsMaster() {
return
}
c := cron.New()
// 每月1号0:01结算发奖
spec := "0 1 0 1 * ?"
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
if err := group_power_s.CalcGroupPowerMonthRankAct(model); err != nil {
model.Log.Errorf("GroupPowerMonthRankAct fail:%v", err)
}
})
c.Start()
}
//func BufaGroupPowerMonthRankAct() {
// c := cron.New()
// spec := "0 50 15 1 * ?"
// _ = c.AddFunc(spec, func() {
// var model = domain.CreateModelNil()
// if err := group_power_s.BufaCalcGroupPowerMonthRankAct(model); err != nil {
// model.Log.Errorf("BufaGroupPowerMonthRankAct fail:%v", err)
// }
// })
//
// c.Start()
//}
package group_cron
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/sdk/tencentyun"
"git.hilo.cn/hilo-common/utils"
"github.com/robfig/cron"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/group_e"
"hilo-group/domain/model/gift_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/service/group_s"
"time"
)
// 群组扶持计算
func CalcGroupSupport() {
if !config.IsMaster() {
return
}
c := cron.New()
//北京时间周一0点,过了一秒后,
spec := "1 0 0 * * 1"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("cron CalcGroupSupport start")
calcTime := time.Now().AddDate(0, 0, -1)
if err := group_s.NewGroupService(model.MyContext).GroupSupportResult(calcTime); err != nil {
model.Log.Errorf("cron CalcGroupSupport faild calcTime:%v, err:%v", calcTime, err)
return
}
model.Log.Infof("cron CalcGroupSupport after GroupSupportResult")
//全服发送H5
if err := sendGroupSupportH5(domain.CreateModelContext(model.MyContext)); err != nil {
model.Log.Errorf("cron CalcGroupSupport err:%v", err)
} else {
model.Log.Infof("cron CalcGroupSupport success")
}
})
c.Start()
}
func sendGroupSupportH5(model *domain.Model) error {
groupIds, err := group_m.GetAllGroupsSorted(model)
if err != nil {
return err
}
model.Log.Infof("SendGroupSupportH5 groupIds:%v", groupIds)
groupSupportH5 := group_m.GroupSupportH5{
CommonPublicMsg: group_m.CommonPublicMsg{
Type: group_e.GroupSupportH5,
},
H5: config.GetH5Config().GROUP_SUPPORT,
}
buffer, err := json.Marshal(groupSupportH5)
if err != nil {
model.Log.Errorf("publicScreenMsg AddSendGiftAsync json.Marshal(giftContent) err:%v", err)
return err
}
content := string(buffer)
//策略1:for循环,没有开启协程,100个停一下
for i, _ := range groupIds {
func(groupId string, content string) {
defer utils.CheckGoPanic()
model.Log.Infof("SendGroupSupportH5 groupId:%v", groupId)
txGroupId, err := group_m.ToTxGroupId(model, groupId)
// 公屏消息
if err == nil {
tencentyun.SendCustomMsg(model.Log, txGroupId, nil, content, "")
}
}(groupIds[i], content)
if i != 0 && i%100 == 0 {
//躺平1秒
time.Sleep(1 * time.Second)
}
}
return nil
}
// 群组扶持计算-旧数据
func CalcGroupSupport_OldData() {
if !config.IsMaster() {
return
}
c := cron.New()
spec := "0 27 10 29 8 ?"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("CalcGroupSupport_OldData start")
//beginTime, endTime, period := group_m.GetSupportLevelTime(time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
beginTime, _, period := group_m.GetSupportLevelTime(time.Now())
endTime := time.Unix(1693275900, 0)
g := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, Model: model}
records, err := g.BatchGetConsumeByRange(beginTime, endTime)
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData beginTime:%v, endTime:%v, err:%v", beginTime, endTime, err)
return
}
// 流水写入redis
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
for _, r := range records {
if r.SceneUid == "" || r.Consume <= 0 {
continue
}
_, err = model.RedisCluster.ZIncrBy(context.Background(), keyDiamond, float64(r.Consume), r.SceneUid).Result()
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, val:%d, member:%s, err:%v",
keyDiamond, r.Consume, r.SceneUid, err)
}
}
err = redisCli.SetExpire(model.RedisCluster, keyDiamond, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, err:%v", keyDiamond, err)
return
}
// 支持者写入redis
for _, r := range records {
if r.SceneUid == "" || r.C <= 0 {
continue
}
// 支持者列表
support := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, SceneUid: r.SceneUid, Model: model}
uids, err := support.BatchGetSupportList(model, beginTime, endTime)
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData beginTime:%v, endTime:%v, imGroupId:%v, err:%v", beginTime, endTime, r.SceneUid, err)
continue
}
if len(uids) <= 0 {
continue
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, r.SceneUid)
for _, uid := range uids {
err = model.RedisCluster.SAdd(context.Background(), keySupportNum, uid).Err()
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, UserId:%d, err:%v", keySupportNum, uid, err)
}
}
err = redisCli.SetExpire(model.RedisCluster, keySupportNum, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("AddSendGiftEventAsync groupSupport key:%s, err:%v", keySupportNum, err)
}
}
model.Log.Infof("CalcGroupSupport_OldData end")
})
c.Start()
}
package mic_cron
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/cache/mic_c"
"hilo-group/domain/event/mic_ev"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/mic_m"
"hilo-group/domain/service/group_mic_s"
"time"
)
func OnMicCheck() {
c := cron.New()
//一分钟执行一次
spec := "0 */1 * * * ?"
spec := "30 */1 * * * ?"
_ = c.AddFunc(spec, func() {
//获取麦上的所有人
var model = domain.CreateModelNil()
......@@ -20,14 +26,15 @@ func OnMicCheck() {
return
}
for _, groupId := range groupIds {
onGroupMicKey := mic_k.GetGroupOnMicUser(groupId) // 同步在mic上的人
//遍历每个麦位
for i := 1; i <= 30; i++ {
for i := 1; i <= group_m.MaxMicNum; i++ {
micUser, err := group_m.GetMicUser(model, groupId, i)
if err != nil {
model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err)
}
if micUser != nil {
if err := mic_ev.PublishOnMicEvent(model, &mic_ev.OnMicEvent{
if err := mic_c.QueueOnMic(model, &mic_ev.OnMicEvent{
GroupUuid: micUser.GroupUuid,
I: micUser.I,
ExternalId: micUser.ExternalId,
......@@ -35,11 +42,43 @@ func OnMicCheck() {
Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp,
}); err != nil {
model.Log.Errorf("PublishOnMicEvent fail:%v", err)
model.Log.Errorf("QueueOnMic fail:%v", err)
}
// 设置mic上的人
model.Redis.HSet(model, onGroupMicKey, i, micUser.UserId)
} else {
// 删除mic上的人
model.Redis.HDel(model, onGroupMicKey, fmt.Sprintf("%d", i))
}
}
}
})
c.Start()
}
func OnMicQueue() {
for i := 0; i < 4; i++ {
go func() {
for true {
model := domain.CreateModelNil()
if onMic := mic_c.BLPopQueueOnMic(model); onMic != nil {
start := time.Now()
// 群组上麦经验
if err := group_mic_s.NewGroupPowerService(model.MyContext).IncrGroupPowerOnMicExpAndTime(onMic.GroupUuid, onMic.UserId, onMic.Timestamp); err != nil {
model.Log.Errorf("cron micIn GroupPowerOnMicExp err:%v", err)
} else {
model.Log.Infof("cron micIn GroupPowerOnMicExp success, groupId:%v, userId:%v,cost:%vs", onMic.GroupUuid, onMic.UserId, time.Now().Sub(start).Seconds())
}
// 用户上麦
//if err := mic_m.IncrUserOnMic(model, onMic.UserId, onMic.Timestamp); err != nil {
//if err := mic_m.IncrUserOnMicV2(model, onMic.UserId); err != nil {
if err := mic_m.IncrUserOnMicV3(model, onMic.UserId); err != nil {
model.Log.Errorf("cron micIn IncrUserOnMic err:%v", err)
} else {
}
}
}
}()
}
}
package user_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/domain/cache/user_c"
)
// 加载数据到lru
func LoadSvipVipNoble() {
go user_c.LoadAllSvipVipNoble(domain.CreateModelNil()) // 启动先执行一次
c := cron.New()
spec := "0 */30 * * * ?"
_ = c.AddFunc(spec, func() {
model := domain.CreateModelNil()
user_c.LoadAllSvipVipNoble(model)
})
c.Start()
}
......@@ -22,7 +22,15 @@ type BillboardUserInfo struct {
Num uint64 `json:"num"`
}
func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]BillboardUserInfo, error) {
//榜单中用户信息
type GroupTop3ConsumeUser struct {
//用户基本信息
UserBase user_cv.TopConsumersUser `json:"userBase"`
//数值
Num uint64 `json:"num"`
}
func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]GroupTop3ConsumeUser, error) {
now := time.Now()
period := now.Format(utils.COMPACT_MONTH_FORMAT)
data, err := getGroupTop3Consume(period, groupId)
......@@ -59,7 +67,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
ret, err := saveGroupTop3Consume(period, groupId, diamonds)
model.Log.Infof("GetGroupTop3Consume SAVE ret = %d, err: %v", ret, err)
return result, nil
list := make([]GroupTop3ConsumeUser, 0, len(result))
for _, v := range result {
list = append(list, GroupTop3ConsumeUser{
UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick},
})
}
return list, nil
}
userIds := make([]uint64, 0)
......@@ -86,7 +102,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
})
}
}
return result, nil
list := make([]GroupTop3ConsumeUser, 0, len(result))
for _, v := range result {
list = append(list, GroupTop3ConsumeUser{
UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick},
})
}
return list, nil
}
func getGroupTop3Consume(period string, groupId string) (map[string]string, error) {
......
package diamond_cv
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
. "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model/bean_m"
"hilo-group/domain/model/diamond_m"
"hilo-group/myerr"
"strconv"
)
type CvDiamond struct {
......@@ -26,33 +20,6 @@ type CvDiamondBean struct {
BeanNum string `json:"beanNum"`
}
func GetDiamondBean(userId mysql.ID) (*CvDiamondBean, error) {
var diamondAccount diamond_m.DiamondAccount
err := mysql.Db.Where(&diamond_m.DiamondAccount{
UserId: userId,
}).First(&diamondAccount).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
diamondAccount = diamond_m.DiamondAccount{
DiamondNum: 0,
}
}
return nil, err
}
var beanAccount bean_m.BeanAccount
err = mysql.Db.Where(&bean_m.BeanAccount{
UserId: userId,
}).First(&beanAccount).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
beanAccount = bean_m.BeanAccount{
BeanNum: 0,
}
}
}
return &CvDiamondBean{DiamondNum: diamondAccount.DiamondNum, BeanNum: strconv.FormatFloat(float64(beanAccount.BeanNum)/100, 'f', 2, 64)}, nil
}
type CvDiamondDetail struct {
//1:增加 2:减少
......@@ -74,113 +41,4 @@ func GetDiamond(userId mysql.ID) (*CvDiamond, error) {
return nil, err
}
return &CvDiamond{DiamondNum: NumToUint32(&diamondAccount.DiamondNum), PinkDiamondNum: NumToUint32(&diamondAccount.PinkDiamondNum)}, nil
}
func GetDiamondBalances(userIds []mysql.ID) (map[mysql.ID]mysql.Num, error) {
result := make(map[mysql.ID]mysql.Num, len(userIds))
data := make([]diamond_m.DiamondAccount, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&data).Error
if err != nil {
return nil, err
}
for _, i := range data {
result[i.UserId] = i.DiamondNum
}
return result, nil
}
//充值记录
func GetDiamondBuyList(userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
var diamondAccountDetails []diamond_m.DiamondAccountDetail
if err := mysql.Db.Model(&diamond_m.DiamondAccountDetail{}).
Where("user_id = ? AND operate_type in (?)", userId, []uint8{diamond_e.BuyDiamond, diamond_e.DealerTransfer, diamond_e.Checkout, diamond_e.PayerMax, diamond_e.Paypal}).
Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
return nil, err
}
var cvDiamondDetails []*CvDiamondDetail
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
//钻石明细,不包括充值
func GetDiamondDetailList(model *domain.Model, userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
diamondAccountDetails := make([]*diamond_m.DiamondAccountDetail, 0)
offset := (pageIndex - 1) * pageSize
optList := []int{int(diamond_e.BuyDiamond), int(diamond_e.DealerTransfer), int(diamond_e.Checkout), int(diamond_e.PayerMax)}
details := make([]*diamond_m.DiamondAccountDetail, 0)
if offset == 0 { // 首页请求数据,获取 pageSize*3 条过滤返回
sql := "select * from diamond_account_detail where user_id = ? order by id desc limit ?"
if err := mysql.Db.WithContext(model).Raw(sql, userId, pageSize*3).Find(&details).Error; err != nil {
return nil, myerr.WrapErr(err)
}
notInMap := make(map[int]bool)
for _, v := range optList {
notInMap[v] = true
}
for _, v := range details {
if _, ok := notInMap[int(v.OperateType)]; !ok {
diamondAccountDetails = append(diamondAccountDetails, v)
}
}
if len(diamondAccountDetails) > pageSize {
diamondAccountDetails = diamondAccountDetails[:pageSize]
}
}
// 非首页,或者首页没取满 pageSize 条
if offset > 0 || (len(details) == pageSize*3 && len(diamondAccountDetails) < pageSize) {
diamondAccountDetails = make([]*diamond_m.DiamondAccountDetail, 0)
sql := "select * from diamond_account_detail where user_id = ? and operate_type not in (?) order by id desc limit ?,?"
if err := mysql.Db.WithContext(model).Raw(sql, userId, optList, offset, pageSize).
Find(&diamondAccountDetails).Error; err != nil {
return nil, myerr.WrapErr(err)
}
}
//if err := mysql.Db.Table("diamond_account_detail FORCE INDEX(Index_1)").
// Where("user_id = ? AND operate_type not in (?)", userId,
// []int{int(diamond_m2.BuyDiamond), int(diamond_m2.DealerTransfer), int(diamond_m2.Checkout), int(diamond_m2.PayerMax)}).
// Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
// return nil, myerr.WrapErr(err)
//}
cvDiamondDetails := []*CvDiamondDetail{}
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
//粉钻流水,包含充值
func GetPinkDiamondDetailList(userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
var diamondAccountDetails []diamond_m.DiamondPinkAccountDetail
if err := mysql.Db.Model(&diamond_m.DiamondPinkAccountDetail{}).
Where("user_id = ?", userId).
Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var cvDiamondDetails []*CvDiamondDetail
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
}
\ No newline at end of file
This diff is collapsed.
......@@ -40,10 +40,20 @@ type CvGroupPowerRank struct {
Items []CvGroupPowerRankData `json:"items"` // 列表
}
// 家族月度排行活动榜单
type CvGroupPowerRankMontAct struct {
MyGroupPower *CvGroupPowerRankData `json:"myGroupPower"` // 我的家族排名
Items []CvGroupPowerRankData `json:"items"` // 列表
MyGroupPowerLast *CvGroupPowerRankData `json:"myGroupPowerLast"` // 我的家族排名(上月)
ItemsLast []CvGroupPowerRankData `json:"itemsLast"` // 列表(上月)
LeftSecond int64 `json:"leftSecond"` // 活动倒计时
}
type CvGroupPowerRankData struct {
CvGroupPowerBase `json:",inline"`
CvGroupPowerGrade `json:",inline"`
Rank int `json:"rank"` // 排名
Rank int `json:"rank"` // 排名
StarList []*CvGroupPowerStarData `json:"starList"` // 家族贡献top10
}
// 家族之星
......@@ -108,6 +118,6 @@ var GroupPowerGradePrivilegeNum = map[groupPower_e.GroupPowerGrade][]CvPrivilege
{groupPower_e.GroupPowerPrivilegeNameplate, 1, "https://image.whoisamy.shop/hilo/resource/family/nameplate_yellow.png"},
{groupPower_e.GroupPowerPrivilegeMedal, 1, "https://image.whoisamy.shop/hilo/resource/family/privilege_yellow.png"},
{groupPower_e.GroupPowerPrivilegeNameplateEdit, 1, "https://image.whoisamy.shop/hilo/resource/family/edit_yellow.png"},
{groupPower_e.GroupPowerPrivilegeNameplateHeadwear, 1,"https://image.whoisamy.shop/hilo/resource/family/headwear_yellow.png"},
{groupPower_e.GroupPowerPrivilegeNameplateHeadwear, 1, "https://image.whoisamy.shop/hilo/resource/family/headwear_yellow.png"},
},
}
package user_cv
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
......@@ -69,6 +70,25 @@ type CvUserDetail struct {
CountryManager *country_cv.CVCountryManager `json:"countryManager,omitempty"` // 国家管理员
}
type RoomInfoOwner struct {
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号
//是否VIP用户
IsVip bool `json:"isVip"`
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
Medals []uint32 `json:"medals"` // 勋章列表
Noble noble_cv.CvNoble `json:"noble"` // 当前的
WealthUserGrade uint32 `json:"wealthUserGrade"` //财富等级
CharmUserGrade uint32 `json:"charmUserGrade"` //魅力等级
MyGroupPowerName string `json:"myGroupPowerName"` // 当前用户所在势力绑定群组的名称
GroupPower GroupPower `json:"groupPower"` // 当前用户势力信息
}
type GroupPower struct {
Id uint64 `json:"id"` // 群主所在的势力ID
Icon string `json:"icon"` // 家族头像
......@@ -150,6 +170,45 @@ type CvUserExtend struct {
ActiveGrade uint32 `json:"activityUserGrade"`
}
type CvGroupMember struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//是否默认头像 true:是 false:不是
DefaultAvatar *bool `json:"defaultAvatar"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
//签名,不存在为nil
Description *string `json:"description"`
Birthday *uint64 `json:"birthday"`
//邀请码
Code *string `json:"code"`
//国家,不存在为nil
Country *string `json:"country"`
//国旗图标,不存在为nil
CountryIcon *string `json:"countryIcon"`
Sex *uint8 `json:"sex"`
//是否代理管理员, 只有自己查自己的时候才有值,其他情况为nil
IsAgentMgr *bool `json:"isAgentMgr"`
//是否展示年龄, 是本人才有数据,看其他用户均为nil
IsShowAge *uint8 `json:"isShowAge"`
//是否工会成员, 只有是自己查自己,这个才有值,其它全为nil, 20220329 数据开放:原因:产品1对1视频聊天中,公会用户视频需要送礼物。改为: 全部人可以知道是否是公会用户。
IsTradeUnion *bool `json:"isTradeUnion"`
//工会成员,是否开启了,匹配通知,只有 isTradeUnion值为true,这里才有值,
IsTradeUnionMatchNotification *bool `json:"isTradeUnionMatchNotification"`
//是否VIP用户
IsVip bool `json:"isVip"`
Ride property_cv.CvProperty `json:"ride"` // 当前使用的座驾
Noble noble_cv.CvNoble `json:"noble"` // 当前的
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
WealthGrade uint32 `json:"wealthUserGrade"`
CharmGrade uint32 `json:"charmUserGrade"`
ActiveGrade uint32 `json:"activityUserGrade"`
}
// 批量获取用户tiny信息
func GetUserTinyMap(userIds []mysql.ID) (map[mysql.ID]CvUserTiny, error) {
userTinys, _, err := GetUserTinys(userIds)
......@@ -849,16 +908,122 @@ func GetUserDetail(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*Cv
noble, superManagerMap[userId], myGroups, phoneInfo, thirdList, cvCountryManager)
}
//群主信息
func GetRoomInfoOwner(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*CvUserDetail, error) {
model.Log.Infof("GetUserDetail %d begin", userId)
var user user_m.User
var err error
if err = mysql.Db.First(&user, userId).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var wealthUserScore user_m.MatchWealthUserScore
if err := mysql.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 := mysql.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)
}
}
}
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)
}
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
}
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}
groupPowerInfos, err := groupPower_m.MGetGroupPowerInfoMap(model, []mysql.ID{groupPowerId})
groupPowerGrades, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{groupPowerId})
groupPowerUsers, err := groupPower_m.MGetGroupPowerUsers(model, []mysql.ID{groupPowerId})
var memberMax int
grade := groupPowerGrades[groupPowerId].Grade
if grade >= groupPower_e.GroupPowerGrade0 && grade <= groupPower_e.GroupPowerGradeMax {
if grade == groupPower_e.GroupPowerGrade0 {
memberMax = 300
}
if grade == groupPower_e.GroupPowerGrade1 {
memberMax = 500
}
if grade == groupPower_e.GroupPowerGrade2 {
memberMax = 800
}
if grade == groupPower_e.GroupPowerGrade3 {
memberMax = 1200
}
}
memberNum := len(groupPowerUsers[groupPowerId])
if memberNum > memberMax {
memberMax = memberNum
}
groupPowerMembers := [2]int{memberNum, memberMax} // 0->memberNum 1->memberLimit
noble, err := noble_m.FindActiveNoble(mysql.Db, userId)
if err != nil {
return nil, err
}
return userToDetailOne(model, &user, myUserId, nil, false, false,
map[mysql.ID]Relation{}, isVip, expireTime, svip, nil, property_cv.CvProperty{}, wealthUserScore.Grade, charmUserScore.Grade,
0, medals[userId], medalInfo[userId], "", powers[userId], powerNames[userId], groupPowerInfos[groupPowerId], groupPowerGrades[groupPowerId], groupPowerMembers,
noble, false, nil, nil, nil, nil)
}
// 单用户版,简化参数
func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.UserTradeUnion, isLike bool, likeMe bool, hvMap map[mysql.ID]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, powerInfo groupPower_m.GroupPowerInfo, grade groupPower_m.GroupPowerGrade, members [2]int, noble *noble_m.UserNoble, isOfficialStaff bool,
myGroups []group_m.GroupInfo, phoneInfo *user_m.UserPhoneInfo, thirdList []int8, countryManager *country_cv.CVCountryManager) (*CvUserDetail, error) {
room, err := group_m.ToTxGroupId(model, room)
if err != nil {
model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err)
room = ""
if len(room) > 0 {
var err error
room, err = group_m.ToTxGroupId(model, room)
if err != nil {
model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err)
room = ""
}
}
cvUserDetail := &CvUserDetail{
......@@ -1288,3 +1453,38 @@ func getMedalInfo(db *gorm.DB, medals []uint32) ([]uint32, []medal_cv.CvMedal, e
}
return validMedals, medalInfo, nil
}
func UserDetailToRoomInfoOwner(user *CvUserDetail) *RoomInfoOwner {
return &RoomInfoOwner{
Avatar: user.Avatar,
ExternalId: user.ExternalId,
Nick: user.Nick,
IsPrettyCode: user.IsPrettyCode,
IsVip: user.IsVip,
Svip: user.Svip,
Medals: user.Medals,
Noble: user.Noble,
WealthUserGrade: user.WealthUserGrade,
CharmUserGrade: user.CharmUserGrade,
MyGroupPowerName: user.MyGroupPowerName,
GroupPower: user.GroupPower,
}
}
type TopConsumersUser struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
}
func CvUserExtendToCvGroupMember(detail CvUserExtend) CvGroupMember {
jData, _ := json.Marshal(detail)
res := CvGroupMember{}
_ = json.Unmarshal(jData, &res)
return res
}
......@@ -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
......@@ -72,6 +74,9 @@ APP_CERTIFICATE=ff29c100a613433db82324e8411eabc8
CUSTOMER_KEY=6b132c0ff7164560a2bc53fda06ea85a
CUSTOMER_SECRET=eedad2cd16d24834990d5450ace9f1ce
CALLBACK_SECRET=n_ZizS_N8
[TRTC]
APP_ID=1400548270
APP_CERTIFICATE=321bd60f73096b059c7350f1cd97d51028850b34fa58c5c0d26bb4a19e783de8
[CHECKOUT]
AUTHORIZATION=sk_test_9b5e771c-5a3f-4a8d-a4da-31b19bd43d83
URL=https://api.sandbox.checkout.com/hosted-payments
......@@ -114,6 +119,8 @@ NOBLE_BUY_IOS=https://h5.whoisamy.shop/action/hiloHtml/22_05_26_buy_nobility/pag
GUILD_DATA_URL=https://test.chathot.me/action/hiloHtml/22_10_18_app_data_coins/index.html
MGR_GUILD_DATA_URL=https://test.chathot.me/action/hiloHtml/22_10_18_app_data_coins/union.html
RANKING_PINK_DIAMOND_URL=https://test.chathot.me/action/activitiesPage/2022_10_17HiloLiveH5/index.html
AGENT_SHARE_URL=https://test.chathot.me/action/hiloHtml/22_05_30_recharge/topup.html?external_id=
AGENT_SHARE_ICON=https://image.whoisamy.shop/hilo/resource/user_transfer1.png
[GROUPIM]
MSG_SORT_EXPIRE=21600
MSG_SORT_SNAP=300
......
......@@ -9,15 +9,18 @@ import (
)
type gameAutoJoinMsg struct {
TraceId string
Token string
EnterType string
GameCode string
TraceId string
Token string
EnterType string
GameCode string
Is1V1 string
GameMode string
Is1V1Robot string
}
func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode string) error {
func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode, is1V1, gameMode, is1V1Robot string) error {
key := game_e.GetAutoMathEnterRoom(userId, imGroupId)
info := gameAutoJoinMsg{traceId, token, enterType, gameCode}
info := gameAutoJoinMsg{traceId, token, enterType, gameCode, is1V1, gameMode, is1V1Robot}
data, err := json.Marshal(info)
if err != nil {
return err
......@@ -26,7 +29,7 @@ func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, g
if err != nil {
return err
}
redisCli.GetRedis().Expire(context.Background(), key, time.Second*3)
redisCli.GetRedis().Expire(context.Background(), key, time.Second*10)
return nil
}
......
package gift_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/domain/event/gift_ev"
"time"
)
const EventSendGiftHiloGroupQueue = "send:gift:queue:hilo_group"
// redis pop event sendGift
func BLPopQueueSendGift(model *domain.Model) *gift_ev.SendGiftEvent {
var res *gift_ev.SendGiftEvent
queue := EventSendGiftHiloGroupQueue
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
}
package groupPower_c
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/go-redis/redis/v8"
"github.com/jinzhu/now"
"github.com/pkg/errors"
"github.com/spf13/cast"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/groupPower_k"
"time"
)
// 家族之星-排名
type GroupPowerStarRank struct {
Period string
GroupPowerId mysql.ID
UserId mysql.ID
Type groupPower_e.GroupPowerStarType
Score mysql.Num
}
// 增加家族之星分数
func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num) error {
ttl := map[string]time.Duration{
"day": time.Hour * 24 * 7,
"week": time.Hour * 24 * 7 * 30,
"month": time.Hour * 24 * 7 * 30 * 2,
}
for _, period := range []string{"day", "week", "month"} {
date := ""
switch period {
case "day":
date = time.Now().Format("2006-01-02")
case "week":
date = now.BeginningOfWeek().Format("2006-01-02")
case "month":
date = now.BeginningOfMonth().Format("2006-01-02")
}
key := groupPower_k.GetGroupPowerStarRankKey(_type, period, groupPowerId, date)
model.RedisCluster.ZIncrBy(model, key, float64(score), fmt.Sprintf("%d", userId))
model.RedisCluster.Expire(model, key, ttl[period])
}
return nil
}
// 获取家族之星排行
// param period: day|week|month
func GetGroupPowerStarRankPeriod(model *domain.Model, period string, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, targetDate ...string) ([]*GroupPowerStarRank, error) {
var res []*GroupPowerStarRank
date := ""
switch period {
case "day":
date = time.Now().Format("2006-01-02")
case "week":
date = now.BeginningOfWeek().Format("2006-01-02")
case "month":
date = now.BeginningOfMonth().Format("2006-01-02")
}
if len(date) <= 0 {
return res, errors.New("illegal date")
}
if len(targetDate) > 0 {
date = targetDate[0]
}
key := groupPower_k.GetGroupPowerStarRankKey(_type, period, groupPowerId, date)
rows, err := model.RedisCluster.ZRevRangeByScoreWithScores(model, key, &redis.ZRangeBy{
Min: "-inf",
Max: "+inf",
Offset: int64(offset),
Count: int64(limit),
}).Result()
if err != nil {
model.Log.Errorf("GetGroupPowerStarRankPeriod fail:%v", err)
return res, err
}
for _, v := range rows {
res = append(res, &GroupPowerStarRank{
Period: period,
GroupPowerId: groupPowerId,
UserId: cast.ToUint64(v.Member),
Type: _type,
Score: mysql.Num(v.Score),
})
}
return res, nil
}
// 获取家族之星三个排行榜的各自第一名
func GetGroupPowerMonthStartTop1(model *domain.Model, groupPowerId mysql.ID) ([]*GroupPowerStarRank, error) {
var res []*GroupPowerStarRank
r1, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeFamous, 0, 1)
if err != nil {
return res, err
}
r2, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeActive, 0, 1)
if err != nil {
return res, err
}
r3, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeCharm, 0, 1)
if err != nil {
return res, err
}
res = append(res, r1...)
res = append(res, r2...)
res = append(res, r3...)
return res, nil
}
package group_c
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key/group_k"
"strconv"
"time"
)
// 用户进房
func ZAddUserEnterRoom(model *domain.Model, userId uint64, imGroupId string) {
userKey := group_k.GetUserEnterRoomUserKey(userId)
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
if err := model.Redis.ZAdd(model, userKey, &redis.Z{
Score: float64(time.Now().Unix()),
Member: imGroupId,
}).Err(); err != nil {
model.Log.Errorf("ZAddUserEnterRoom user fail:%v", err)
}
if err := model.Redis.ZAdd(model, groupKey, &redis.Z{
Score: float64(time.Now().Unix()),
Member: userId,
}).Err(); err != nil {
model.Log.Errorf("ZAddUserEnterRoom room fail:%v", err)
}
}
// 获取最近房间访客
// 15天
func GetLastRoomVisitors(model *domain.Model, imGroupId string) (userIds []uint64) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
res, err := model.Redis.ZRangeByScore(model, groupKey, &redis.ZRangeBy{
Min: fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix()),
Max: "+inf",
}).Result()
if err != nil {
return
}
for _, u := range res {
uid, _ := strconv.ParseUint(u, 10, 64)
if uid > 0 {
userIds = append(userIds, uid)
}
}
return
}
// 获取最近进入的房间
// 3个月
func GetUserRecentRooms(model *domain.Model, userId uint64, offset, limit int64) (imGroupIds []string, roomEnterTime map[string]int64) {
roomEnterTime = make(map[string]int64)
userKey := group_k.GetUserEnterRoomUserKey(userId)
res, err := model.Redis.ZRevRangeByScoreWithScores(model, userKey, &redis.ZRangeBy{
Min: fmt.Sprintf("%d", time.Now().AddDate(0, -3, 0).Unix()),
Max: "+inf",
Offset: offset,
Count: limit,
}).Result()
if err != nil {
return
}
for _, v := range res {
imGroupId := cast.ToString(v.Member)
imGroupIds = append(imGroupIds, imGroupId)
roomEnterTime[imGroupId] = int64(v.Score)
}
return
}
// 清理房间访客
// 15天前访问的
func RemoveRoomVisitors(model *domain.Model, imGroupId string) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
n, err := model.Redis.ZRemRangeByScore(model, groupKey, "-inf", fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix())).Result()
if err != nil {
model.Log.Errorf("RemoveRoomVisitors fail:%v", err)
} else {
model.Log.Infof("RemoveRoomVisitors key:%v,n:%v", groupKey, n)
}
}
......@@ -14,6 +14,10 @@ import (
"time"
)
func init() {
group_m.FuncAddEditGroupCd = AddEditGroupCd
}
func GetGroupMemberCount(groupId string) (int, error) {
key := redis_key.GetGroupMemCountKey(groupId)
return redisCli.RedisClient.Get(context.Background(), key).Int()
......@@ -79,17 +83,17 @@ func SetGroupMemberTTL(groupId string, ttl time.Duration) (bool, error) {
func GetGroupConsume(groupId string) (uint64, error) {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Get(context.Background(), key).Uint64()
return redisCli.RedisClusterClient.Get(context.Background(), key).Uint64()
}
func SetGroupConsume(groupId string, consume uint64, ttl time.Duration) error {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Set(context.Background(), key, consume, ttl).Err()
return redisCli.RedisClusterClient.Set(context.Background(), key, consume, ttl).Err()
}
func ClearGroupConsume(groupId string) error {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Del(context.Background(), key).Err()
return redisCli.RedisClusterClient.Del(context.Background(), key).Err()
}
// 增加编辑用户cd
......
package mic_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/mic_ev"
"time"
)
// redis queue on mic
func QueueOnMic(model *domain.Model, onMic *mic_ev.OnMicEvent) error {
queue := mic_k.GetOnMicQueue()
onMic.Ts = time.Now().UnixNano() // 给一个时间戳
body, _ := json.Marshal(onMic)
return model.RedisCluster.RPush(model, queue, string(body)).Err()
}
// redis pop on mic
func BLPopQueueOnMic(model *domain.Model) *mic_ev.OnMicEvent {
var res *mic_ev.OnMicEvent
queue := mic_k.GetOnMicQueue()
strs, err := model.RedisCluster.BLPop(model, time.Second, queue).Result()
if err != nil {
if err != redis.Nil {
model.Log.Errorf("BLPopQueueOnMic fail:%v", err)
}
return nil
}
if len(strs) >= 2 {
content := strs[1]
res = new(mic_ev.OnMicEvent)
if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopQueueOnMic json fail:%v", err)
return nil
}
return res
}
return nil
}
......@@ -27,17 +27,17 @@ 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结构体
// return err: may redisV8.Nil
func GetJSON(model *domain.Model, key string, obj interface{}) (err error) {
var value []byte
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()
//defer func() {
// model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err)
//}()
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)
}
package res_c
import (
"context"
"git.hilo.cn/hilo-common/domain"
"hilo-group/_const/redis_key"
"github.com/bluele/gcache"
"hilo-group/domain/model/res_m"
"time"
)
// 统一改成lru
var countryIconLru = gcache.New(1000).LRU().Build()
var countryIconKey = "country:icon"
var countryAreaLru = gcache.New(1000).LRU().Build()
var countryAreaKey = "country:area"
func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
m, err := GetAllCountryIcon(model)
if err != nil || len(m) <= 0 {
......@@ -24,15 +30,54 @@ func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
}
func GetAllCountryIcon(model *domain.Model) (map[string]string, error) {
key := redis_key.GetCountryIconKey()
return model.Redis.HGetAll(context.Background(), key).Result()
//key := redis_key.GetCountryIconKey()
if data, err := countryIconLru.Get(countryIconKey); err == nil {
return data.(map[string]string), nil
}
//return model.Redis.HGetAll(context.Background(), key).Result()
return map[string]string{}, nil
}
func SaveAllCountryIcon(model *domain.Model, icons map[string]string) {
//key := redis_key.GetCountryIconKey()
//ret, err := model.Redis.HSet(context.Background(), key, icons).Result()
//if err == nil {
// model.Redis.Expire(context.Background(), key, time.Minute*10)
//}
//return ret, err
_ = countryIconLru.SetWithExpire(countryIconKey, icons, time.Minute*10)
}
func GetCountryAreaMap(model *domain.Model) (map[string]string, error) {
m, err := GetAllCountryArea(model)
if err != nil || len(m) <= 0 {
m, err = res_m.GetAllCountriesArea(model)
if err != nil {
return nil, err
}
if len(m) <= 0 {
return map[string]string{}, nil
}
SaveAllCountryArea(model, m)
}
return m, nil
}
func SaveAllCountryIcon(model *domain.Model, icons map[string]string) (int64, error) {
key := redis_key.GetCountryIconKey()
ret, err := model.Redis.HSet(context.Background(), key, icons).Result()
if err == nil {
model.Redis.Expire(context.Background(), key, time.Minute*10)
func GetAllCountryArea(model *domain.Model) (map[string]string, error) {
//key := redis_key.GetCountryAreaKey()
//return model.Redis.HGetAll(context.Background(), key).Result()
if data, err := countryAreaLru.Get(countryAreaKey); err == nil {
return data.(map[string]string), nil
}
return ret, err
return map[string]string{}, nil
}
func SaveAllCountryArea(model *domain.Model, data map[string]string) {
//key := redis_key.GetCountryAreaKey()
//ret, err := model.Redis.HSet(context.Background(), key, data).Result()
//if err == nil {
// model.Redis.Expire(context.Background(), key, time.Minute*10)
//}
//return ret, err
_ = countryAreaLru.SetWithExpire(countryAreaKey, data, time.Minute*10)
}
......@@ -2,42 +2,44 @@ package room_c
import (
"context"
"errors"
"fmt"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli"
"github.com/bluele/gcache"
redis2 "github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key"
"strconv"
"hilo-group/_const/redis_key/group_k"
"time"
)
// 处理访问房间的相关缓存
func ProcessRoomVisit(groupId string, userId uint64) error {
key := redis_key.GetPrefixGroupInUserDuration(groupId)
now := time.Now()
ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
Score: float64(now.Unix()),
Member: userId,
}).Result()
if err != nil {
return err
}
mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret)
// 每群定时清一次数据可以了
if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL))
if err == nil {
mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc)
} else {
mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error())
}
}
//key := redis_key.GetPrefixGroupInUserDuration(groupId)
//now := time.Now()
//ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
// Score: float64(now.Unix()),
// Member: userId,
//}).Result()
//if err != nil {
// return err
//}
//mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret)
//
//// 每群定时清一次数据可以了
//if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
// rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL))
// if err == nil {
// mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc)
// } else {
// mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error())
// }
//}
// 马上更新roomVisitCount
if _, err := GetSetRoomVisitCount(groupId); err != nil {
mylogrus.MyLog.Warnf("ProcessRoomVisit, failed for key %s, err: %s", key, err.Error())
mylogrus.MyLog.Errorf("ProcessRoomVisit, failed for groupId %s, err: %s", groupId, err.Error())
}
return nil
......@@ -59,15 +61,17 @@ func ProcessUserRoomVisit(userId uint64, groupId string) error {
}
// 查询用户访问过的房间及其时间
// todo 去掉查询,redis性能
func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
result := make(map[string]int64, 0)
return result, nil
key := redis_key.GetUserEnterRoomKey(userId)
ret, err := redisCli.GetRedis().ZRangeWithScores(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, err
}
mylogrus.MyLog.Infof("GetUserRoomVisit, ZRangeWithScores %s, return %v", key, ret)
//mylogrus.MyLog.Infof("GetUserRoomVisit, ZRangeWithScores %s, return %v", key, ret)
result := make(map[string]int64, 0)
for _, i := range ret {
result[i.Member.(string)] = int64(i.Score)
}
......@@ -75,53 +79,63 @@ func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
}
// 批量获取房间访问人数
// 带上lru
var roomVisitCountLru = gcache.New(100).LRU().Build()
func MGetRoomVisitCount(groupIds []string) (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
visit := make(map[string]string)
if len(groupIds) <= 0 {
return visit, nil
}
res, err := redisCli.GetRedis().HMGet(context.Background(), key, groupIds...).Result()
lKey := "room:visit:count"
if data, err := roomVisitCountLru.Get(lKey); err == nil {
return data.(map[string]string), nil
}
// 用redisCluster中的zset代替,只是取出大于10的
zKey := redis_key.GetPrefixRoomVisitCountZset()
cnt := 10
if !config.AppIsRelease() {
cnt = 0
}
zRes, err := redisCli.GetClusterRedis().ZRevRangeByScoreWithScores(context.Background(), zKey, &redis2.ZRangeBy{
Min: fmt.Sprintf("%d", cnt),
Max: "+inf",
}).Result()
if err != nil {
mylogrus.MyLog.Errorf("MGetRoomVisitCount zset fail:%v", err)
return visit, err
}
if len(res) != len(groupIds) {
return visit, errors.New(fmt.Sprintf("MGetRoomVisitCount fail,miss match len,%v-%v", len(res), len(groupIds)))
}
for i, groupId := range groupIds {
if cnt, ok := res[i].(string); ok {
visit[groupId] = cnt
}
for _, v := range zRes {
visit[cast.ToString(v.Member)] = cast.ToString(v.Score)
}
_ = roomVisitCountLru.SetWithExpire(lKey, visit, time.Minute*15)
return visit, nil
}
func GetSetRoomVisitCount(groupId string) (int64, error) {
key := redis_key.GetPrefixGroupInUserDuration(groupId)
//key := redis_key.GetPrefixGroupInUserDuration(groupId)
key := group_k.GetUserEnterRoomGroupKey(groupId)
vc, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
// 查到合法值后,更新二级缓存
if err == nil && vc >= 0 {
ret, err := saveRoomVisitCount(groupId, vc)
mylogrus.MyLog.Infof("saveRoomVisitCount %s, ret = %d, err: %v", groupId, ret, err)
if err := saveRoomVisitCount(groupId, vc); err != nil {
mylogrus.MyLog.Errorf("saveRoomVisitCount %s, err: %v", groupId, err)
}
}
return vc, err
}
func saveRoomVisitCount(groupId string, count int64) (int64, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result()
}
func clearRoomVisit(groupId string, t time.Time) (int64, error) {
value := strconv.FormatInt(t.Unix(), 10)
ret, err := redisCli.GetRedis().ZRemRangeByScore(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId), "0", value).Result()
if err != nil {
return 0, err
func saveRoomVisitCount(groupId string, count int64) error {
//key := redis_key.GetPrefixRoomVisitCount()
zKey := redis_key.GetPrefixRoomVisitCountZset()
// zset同步存一份到redis集群
if err := redisCli.GetClusterRedis().ZAdd(context.Background(), zKey, &redis2.Z{
Score: float64(count),
Member: groupId,
}).Err(); err != nil {
mylogrus.MyLog.Errorf("GetPrefixRoomVisitCountZset fail %s", err.Error())
return err
}
return ret, nil
}
func GetAllRoomVisitCount() (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HGetAll(context.Background(), key).Result()
return nil
//return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result()
}
package user_c
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"sync"
"time"
)
type UserLevel struct {
UserId mysql.ID
Level int
}
var svipVipNobleLock sync.RWMutex
var svipLevel = make(map[mysql.ID]int) // userId->svipLevel
var nobleLevel = make(map[mysql.ID]uint16) // userId->nobleLevel
var userVips = make(map[mysql.ID]bool) // userId->isVip
// 加载数据到lru
func LoadAllSvipVipNoble(model *domain.Model) {
start := time.Now()
var svips []UserLevel
svipMap := make(map[mysql.ID]int)
if err := model.DB().Table("user_svip").Select("user_id,level").Where("level > 0").Find(&svips).Error; err != nil {
model.Log.Errorf("LoadAllSvip fail:%v", err)
} else {
for _, v := range svips {
svipMap[v.UserId] = v.Level
}
}
var nobles []UserLevel
nobleMap := make(map[mysql.ID]uint16)
if err := model.DB().Table("user_noble").Select("user_id,MAX(level) level").
Where("level > 0 AND end_time > ?", time.Now()).Group("user_id").Find(&nobles).Error; err != nil {
model.Log.Errorf("LoadAllNoble fail:%v", err)
} else {
for _, v := range nobles {
nobleMap[v.UserId] = uint16(v.Level)
}
}
var vips []UserLevel
vipMap := make(map[mysql.ID]bool)
if err := model.DB().Table("user_vip").Select("user_id").
Where("expire_at > ?", time.Now()).Find(&vips).Error; err != nil {
model.Log.Errorf("LoadAllVip fail:%v", err)
} else {
for _, v := range vips {
vipMap[v.UserId] = true
}
}
// 上锁赋值
svipVipNobleLock.Lock()
svipLevel = svipMap
nobleLevel = nobleMap
userVips = vipMap
svipVipNobleLock.Unlock()
model.Log.Infof("LoadAllSvipVipNoble svip:%v,vip:%v,noble:%v,cost:%vs", len(svipMap), len(vipMap), len(nobleMap), time.Now().Sub(start).Seconds())
}
func BatchGetNobleLevel(model *domain.Model, userIds []uint64) map[uint64]uint16 {
res := make(map[uint64]uint16)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
res[userId] = nobleLevel[userId]
}
return res
}
func MGetUserSvipLevel(model *domain.Model, userIds []uint64) map[uint64]int {
res := make(map[uint64]int)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
res[userId] = svipLevel[userId]
}
return res
}
func BatchGetVips(model *domain.Model, userIds []uint64) map[uint64]*int64 {
res := make(map[uint64]*int64)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
vip := int64(1)
if userVips[userId] {
res[userId] = &vip
}
}
return res
}
......@@ -38,6 +38,36 @@ func GetUserTinyById(model *domain.Model, userId mysql.ID) (*user_m.UserTiny, er
return userTiny, nil
}
// 获取用户简要信息
// param userId 用户id
func MGetUserTinyById(model *domain.Model, userIds []mysql.ID) []*user_m.UserTiny {
var users []*user_m.UserTiny
for _, userId := range userIds {
if user, _ := GetUserTinyById(model, userId); user != nil {
users = append(users, user)
}
}
return users
}
// 获取用户externalIds
// return []externalIds map[userId]extId map[userId]code
func GetUserExternalIds(model *domain.Model, userIds []mysql.ID) ([]string, map[uint64]string, map[uint64]string) {
var res []string
var m = make(map[uint64]string)
var c = make(map[uint64]string)
if len(userIds) <= 0 {
return res, m, c
}
users := MGetUserTinyById(model, userIds)
for _, u := range users {
res = append(res, u.ExternalId)
m[u.ID] = u.ExternalId
c[u.ID] = u.Code
}
return res, m, c
}
// 获取用户简要信息By ExternalId
func GetUserByExternalId(model *domain.Model, externalId mysql.Str) (*user_m.UserTiny, error) {
userId, err := ToUserId(model, externalId)
......@@ -52,7 +82,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
}
......@@ -75,7 +105,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
}
......@@ -104,11 +134,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 group_ev
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
)
var txGroupInListen = new(domain.EventBase)
// 进房事件
type TxGroupInEvent struct {
GroupId string // imGroupId
UserId mysql.ID
ExternalId string
Nick string
Avatar string
IsMember bool //是否永久成员
IsVip bool
NobleLevel uint16
}
func AddTxGroupInEventSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(txGroupInListen, callback)
}
func AddTxGroupInEventAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(txGroupInListen, callback)
}
func PublishTxGroupInEvent(model *domain.Model, event interface{}) error {
return domain.PublishEvent(txGroupInListen, model, event)
}
......@@ -14,6 +14,8 @@ type OnMicEvent struct {
UserId uint64 // 麦中的人
Forbid bool // 静音 true:静音,false:没有静音
Timestamp int64 // 上麦的的时间戳
Ts int64
}
func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) {
......
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"
"git.hilo.cn/hilo-common/utils"
"hilo-group/_const/redis_key"
"hilo-group/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)
}
// 改成lru
var userMedalMergeLru = gcache.New(10000).LRU().Build()
res := make([]uint32, 0)
err = json.Unmarshal(bData, &res)
if err != nil {
return nil, myerr.WrapErr(err)
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
if data, err := userMedalMergeLru.Get(userId); err == nil {
return data.([]uint32), nil
}
return res, 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)
}
// 删除勋章缓存, 延迟删除
......@@ -44,41 +30,6 @@ func DelUserMedalMergeCacheDelay(userId mysql.ID) {
}()
}
func DelUserMedalMergeCache(userId mysql.ID) error {
err := DelCache(redis_key.GetUserMedalMerge(userId))
if err != nil {
mylogrus.MyLog.Errorf("DetUserMedalMerge err:%s, userId:%v", err, userId)
return myerr.WrapErr(err)
}
return nil
}
func DelCache(key string) error {
err := redisCli.GetRedis().Del(context.Background(), key).Err()
if err != nil {
mylogrus.MyLog.Errorf("DelCache key:%s, err:%s", key, err)
return err
}
return nil
}
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
}
return nil
func DelUserMedalMergeCache(userId mysql.ID) {
userMedalMergeLru.Remove(userId)
}
package diamond_m
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
"strconv"
......@@ -40,6 +40,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
......@@ -110,7 +115,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)
......@@ -125,7 +130,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)
......@@ -133,7 +138,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,代表值无效,由参数给与
......@@ -197,7 +202,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值
......@@ -245,7 +253,10 @@ func (diamondAccountDetail *DiamondAccountDetail) Persistent() error {
}
//持久化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 event_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
)
// 进房事件消息
type EventGroupIn struct {
mysql.Entity
*domain.Model `gorm:"-"`
Proto mysql.Type
Payload []byte
Mark mysql.YesNo
MarkHiloGroup mysql.YesNo
}
func (EventGroupIn) TableName() string {
return "event_group_in"
}
// 偏移值
type EventGroupInOffsetHiloGroup struct {
mysql.Entity
*domain.Model `gorm:"-"`
MarkOffset mysql.ID
}
// 获取当前偏移值
func GroupOffset(model *domain.Model) (*EventGroupInOffsetHiloGroup, error) {
offset := new(EventGroupInOffsetHiloGroup)
if err := model.Db.WithContext(model).First(offset).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("Offset fail:%v", err)
return nil, err
}
// gorm.ErrRecordNotFound
}
offset.Model = model
return offset, nil
}
// 批量获取进房事件
func FetchEventGroupIn(model *domain.Model, limit int) ([]*EventGroupIn, *EventGroupInOffsetHiloGroup, error) {
offset, err := GroupOffset(model)
if err != nil {
return nil, nil, err
}
var events []*EventGroupIn
if err := model.Db.WithContext(model).Model(EventGroupIn{}).
Where("id > ?", offset.MarkOffset).
Order("id asc").Limit(limit).Find(&events).Error; err != nil {
model.Log.Errorf("FetchEventGroupIn fail:%v", err)
return nil, nil, err
}
return events, offset, nil
}
// 标记已完成
func (p *EventGroupIn) MarkDone() error {
p.MarkHiloGroup = mysql.YES
return p.Db.WithContext(p.Model).Model(EventGroupIn{}).Where("id = ?", p.ID).Update("mark_hilo_group", p.MarkHiloGroup).Limit(1).Error
}
......@@ -9,3 +9,7 @@ func (p *EventGiftSendOffsetHiloGroup) Persistence() error {
func (p *EventGiftSend) Persistence() error {
return model.Persistent(p.Db, p)
}
func (p *EventGroupInOffsetHiloGroup) Persistence() error {
return model.Persistent(p.Db, p)
}
\ No newline at end of file
......@@ -16,10 +16,11 @@ type EventGiftSend struct {
Payload []byte
Mark mysql.YesNo
MarkHiloGroup mysql.YesNo
MarkHiloUser mysql.YesNo
}
func (EventGiftSend) TableName() string {
return "event_gift_send2"
return "event_gift_send"
}
// 偏移值
......
......@@ -29,8 +29,9 @@ type GameInfo struct {
}
type GameConfig struct {
Ludo *GameConfigDiamond `json:"ludo"`
Uno *GameConfigDiamond `json:"uno"`
Ludo *GameConfigDiamond `json:"ludo"`
Uno *GameConfigDiamond `json:"uno"`
Domino *GameConfigDiamond `json:"domino"`
}
type GameConfigDiamond struct {
......
......@@ -127,6 +127,40 @@ func (g *GiftOperate) GetConsumeByRange(beginTime, endTime time.Time) (uint32, u
if len(rows) <= 0 {
return 0, 0, nil
}
//if beginTime.Unix() >= 1691337600 && beginTime.Unix() < 1691942400 { // 因为这周水果机被部分人刷币,所以这里做了特殊的处理
// reduceMap := map[string]uint64{
// "HTGS#a63226380": 20000000,
// //"HTGS#a42641278": 10000000,
// "@TGS#3ZZ5GZLHA": 27141539,
// "HTGS#a81630128": 8955410,
// "HTGS#a42300598": 50211301,
// "HTGS#a40088696": 10000000,
// "HTGS#a21700997": 14352310,
// "HTGS#a83608384": 49644203,
// "@TGS#33GDXTSIH": 50000000,
// "HTGS#a50538513": 15000000,
// "HTGS#a77282385": 15000000,
// "HTGS#a59437326": 10000000,
// "HTGS#a16909405": 10000000,
// "HTGS#a44104431": 16861206,
// "HTGS#a56794634": 59591313,
// "HTGS#a11286025": 31232311,
// "HTGS#a17238550": 52309338,
// "HTGS#a83592361": 79545067,
// "HTGS#a39882521": 10255093,
// }
// if reduceNum, ok := reduceMap[g.SceneUid]; ok {
// if g.Log != nil {
// g.Log.Infof("fruit diamond reduceMap,groupId:%v,reduceNum:%v", g.SceneUid, reduceNum)
// }
// if rows[0].Consume >= reduceNum {
// rows[0].Consume -= reduceNum
// } else {
// rows[0].Consume = 0
// }
// }
//}
return rows[0].C, rows[0].Consume, nil
}
......@@ -148,6 +182,17 @@ func (g *GiftOperate) BatchGetConsumeByRange(beginTime, endTime time.Time) ([]Sc
return rows, nil
}
func (g *GiftOperate) BatchGetSupportList(model *domain.Model, beginTime, endTime time.Time) ([]uint64, error) {
userIds := make([]uint64, 0)
err := model.DB().Model(g).
Select("DISTINCT(send_user_id) AS user_id").
Where(g).Where("created_time BETWEEN ? AND ?", beginTime, endTime).Pluck("user_id", &userIds).Error
if err != nil {
return nil, err
}
return userIds, nil
}
func SumSendGift(model *domain.Model, sendUserId mysql.ID, giftId mysql.ID) (uint32, error) {
type Result struct {
N uint32
......
......@@ -140,8 +140,8 @@ func UpdateFamily(model *domain.Model, familyId uint64, name, nameplate, declara
if groupPower.ModifyNameplate != mysql.YES {
// 同步修改铭牌
n := len([]rune(name))
if n > 6 {
n = 6
if n > groupPower_e.LongestNameplate {
n = groupPower_e.LongestNameplate
}
updateMap["nameplate"] = string([]rune(name[0:n]))
}
......
......@@ -43,6 +43,17 @@ type GroupPowerUser struct {
Role groupPower_e.GroupPowerUserRole
}
type ActFamilyMonthRankLog struct {
Id uint64 `json:"id"`
Period string `json:"period"`
FamilyId uint64 `json:"family_id"`
RankFamily int `json:"rank_family"`
RankUser int `json:"rank_user"`
UserId uint64 `json:"user_id"`
Award string `json:"award"`
Area int `json:"area"`
}
func (gpu *GroupPowerUser) Get(db *gorm.DB) ([]GroupPowerUser, error) {
rows := make([]GroupPowerUser, 0)
err := db.Where(gpu).Find(&rows).Error
......@@ -64,6 +75,22 @@ func GetPowerOwner(db *gorm.DB, powerId uint64) (uint64, error) {
return records[0].UserId, nil
}
func GetPowerOwnerMap(model *domain.Model, powerIds []uint64) (map[uint64]uint64, error) {
rows := make([]GroupPowerUser, 0)
if len(powerIds) > 0 {
if err := model.DB().Model(&GroupPowerUser{}).
Where("group_power_id IN ? and role = ?", powerIds, groupPower_e.GroupPowerUserRoleMgr).
Find(&rows).Error; err != nil {
return nil, err
}
}
result := make(map[uint64]uint64, 0)
for _, i := range rows {
result[i.GroupPowerId] = i.UserId
}
return result, nil
}
func GetMyPowerId(db *gorm.DB, userId uint64) (uint64, error) {
gpu := GroupPowerUser{UserId: userId, Role: groupPower_e.GroupPowerUserRoleMgr}
records, err := gpu.Get(db)
......@@ -707,3 +734,7 @@ func BatchGetGroupPowerUser(model *domain.Model, userIds []mysql.ID) (map[mysql.
}
return res, nil
}
func CreateActFamilyMonthRankLog(model *domain.Model, list []*ActFamilyMonthRankLog) error {
return model.DB().CreateInBatches(&list, 50).Error
}
......@@ -8,6 +8,7 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/group_power_ev"
"time"
)
......@@ -40,25 +41,6 @@ type GroupPowerExpDetail struct {
Remark string
}
type GroupPowerOnMic struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Seconds int64
LastCalTs int64
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
type GroupPowerOnMicDetail struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Minute int
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
// 增加家族经验
// 达到经验值之后升级
// 单进程同步执行,不考虑并发
......@@ -82,17 +64,34 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return err
}
// 增加家族经验-总
gpg := &GroupPowerGrade{
GroupPowerId: groupPowerId,
Exp: exp,
Grade: 0,
ExpireAt: time.Time{},
}
if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil {
return err
gpg := new(GroupPowerGrade)
// insert
if err := txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(gpg).Error; err != nil {
if err != gorm.ErrRecordNotFound {
return err
}
// gorm.ErrRecordNotFound
gpg = &GroupPowerGrade{
GroupPowerId: groupPowerId,
Exp: exp,
Grade: 0,
ExpireAt: time.Time{},
}
if err = txModel.DB().Create(gpg).Error; err != nil {
return err
}
} else {
// or update
if err := txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).
UpdateColumn("exp", gorm.Expr("exp + ?", exp)).Error; err != nil {
return err
}
}
//if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}},
// DoUpdates: clause.Assignments(map[string]interface{}{
// "exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil {
// return err
//}
// 当前写后读
latestGrade := new(GroupPowerGrade)
if err = txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(latestGrade).Error; err != nil {
......@@ -135,154 +134,24 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return nil
}
// 获取势力用户上麦加经验记录
func GetGroupPowerUserOnMicDetails(model *domain.Model, groupPowerId, userId mysql.ID) ([]*GroupPowerOnMicDetail, error) {
var res []*GroupPowerOnMicDetail
date := time.Now().Format("2006-01-02")
if err := model.DB().Model(GroupPowerOnMicDetail{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).Find(&res).Error; err != nil {
return res, err
}
return res, nil
}
// 获取势力用户上麦记录
func GetGroupPowerOnMic(model *domain.Model, groupPowerId, userId mysql.ID) (*GroupPowerOnMic, error) {
gpom := new(GroupPowerOnMic)
date := time.Now().Format("2006-01-02")
if err := model.DB().Model(GroupPowerOnMic{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).First(gpom).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return &GroupPowerOnMic{Date: date, GroupPowerId: groupPowerId, UserId: userId}, nil
}
return nil, err
}
return gpom, nil
}
const MaxMinuteTimes = 18
// 增加势力上麦经验
// 事务操作
func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 获取用户上麦奖励历史
onMicDetails, err := GetGroupPowerUserOnMicDetails(model, groupPowerId, userId)
if err != nil {
return err
}
numDetails := len(onMicDetails)
if numDetails >= MaxMinuteTimes {
// 上麦经验贡献值最多1800,1分钟100
return nil
}
onMic, err := GetGroupPowerOnMic(model, groupPowerId, userId)
if err != nil {
return err
}
nowTs := time.Now().Unix()
curTs := joinMicTimestamp
day0Ts := utils.GetZeroTime(time.Now()).Unix()
if joinMicTimestamp < onMic.LastCalTs {
curTs = onMic.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
onMicSeconds := nowTs - curTs
var moreDetails []*GroupPowerOnMicDetail
totalMinuteTimes := int((onMic.Seconds + onMicSeconds) / 600) // 今天实际能加经验次数
if totalMinuteTimes >= MaxMinuteTimes {
totalMinuteTimes = MaxMinuteTimes
}
if totalMinuteTimes > numDetails {
// 续上上一次的时间,从numDetails开始
for mt := numDetails + 1; mt <= totalMinuteTimes; mt++ {
moreDetails = append(moreDetails, &GroupPowerOnMicDetail{
Date: time.Now().Format("2006-01-02"),
GroupPowerId: groupPowerId,
UserId: userId,
Minute: mt * 10, // 转换分钟
})
}
}
// 有更多麦上10分钟,可以加经验
if len(moreDetails) > 0 {
for _, detail := range moreDetails {
// 添加明细,避免重复计算
if err := model.DB().Model(GroupPowerOnMicDetail{}).Create(detail).Error; err != nil {
return err
}
// 每10分钟增加100点经验
if err := IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟"); err != nil {
return err
}
}
// 更新micExp信息
onMic.Seconds = onMic.Seconds + onMicSeconds
onMic.LastCalTs = nowTs
if err := model.DB().Model(GroupPowerOnMic{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "date"}, {Name: "group_power_id"}},
DoUpdates: clause.Assignments(
map[string]interface{}{
"seconds": onMic.Seconds,
"last_cal_ts": nowTs,
},
)}).
Create(onMic).Error; err != nil {
return err
}
}
return nil
})
}
// 增加势力上麦时长-家族之星
// 事务操作
func IncrGroupPowerStarOnMicMonth(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 月统计
star, err := GetGroupPowerMonthStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
month0Ts := now.BeginningOfMonth().Unix()
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨月
if curTs < month0Ts {
curTs = month0Ts
}
score := nowTs - curTs
err = IncrGroupPowerMonthStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID) error {
key := mic_k.GetMicGroupPowerOnMic(userId)
minutes, err := model.Redis.IncrBy(model, key, 1).Result()
if err != nil {
model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err)
return err
})
}
// 增加势力上麦时长-家族之星
// 事务操作
func IncrGroupPowerStarOnMicDay(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 日统计
star, err := GetGroupPowerDayStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
day0Ts := now.BeginningOfDay().Unix()
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
err = IncrGroupPowerDayStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
return err
})
}
model.Redis.Expire(model, key, time.Hour*24) // ttl 一天
// 每日最多1800经验 = 18个10分钟 = 180分钟
if minutes > 180 {
return nil
}
if minutes%10 == 0 {
return IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟")
}
return nil
}
// 清理所有家族的经验
......
......@@ -2,6 +2,7 @@ package groupPower_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/common"
"hilo-group/myerr"
......@@ -88,3 +89,16 @@ func DelGroupPowerApplyJoinNoDeal(model *domain.Model, userId uint64) error {
}
return nil
}
// 获取家族申请人数
// param: isAccept 0:未审核 1:通过 2:拒绝
func CountGroupPowerApply(model *domain.Model, groupPowerId mysql.ID, isAccept int) (int64, error) {
var cnt int64
if err := model.DB().Model(GroupPowerApplyJoin{}).
Where("group_power_id = ?", groupPowerId).
Where("is_accept = ?", isAccept).Count(&cnt).Error; err != nil {
model.Log.Errorf("CountGroupPowerApply fail:%v", err)
return cnt, err
}
return cnt, nil
}
......@@ -4,6 +4,7 @@ import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/_const/enum/groupPower_e"
)
type GroupPowerExpRank struct {
......@@ -14,10 +15,20 @@ type GroupPowerExpRank struct {
// 获取家族经验排行榜
// param limit: 排行榜人数
func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int) ([]GroupPowerExpRank, error) {
// 10166 线上员工,对应的势力不上榜,groupPowerId=8951
func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int, gpStatus groupPower_e.GroupPowerStatus, area int) ([]GroupPowerExpRank, error) {
var res []GroupPowerExpRank
if err := model.DB().Table("group_power_day_exp").Select("group_power_id,SUM(exp) as exp").
Where("date BETWEEN ? AND ?", beginDate, endDate).Group("group_power_id").Order("exp DESC").Limit(limit).Find(&res).Error; err != nil {
db := model.DB().Table("group_power_day_exp gpd").Select("gpd.group_power_id,SUM(gpd.exp) as exp").
Where("gpd.group_power_id <> 8951").
Where("gpd.date BETWEEN ? AND ?", beginDate, endDate)
if gpStatus > 0 {
db = db.Joins("left join group_power gp on gpd.group_power_id = gp.id").Where("gp.status = ?", gpStatus)
if area > 0 {
db = db.Joins("left join group_info gi on gp.group_uid = gi.im_group_id left join res_country rs on gi.country = rs.name").
Where("rs.area = ?", area)
}
}
if err := db.Group("gpd.group_power_id").Order("exp DESC").Limit(limit).Find(&res).Error; err != nil {
model.Log.Errorf("GetGroupPowerExpRank fail:%v", err)
return res, err
}
......
......@@ -35,6 +35,7 @@ type GroupPowerDayStar struct {
}
// 增加家族之星分数
// Deprecated: 用redis
func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
month := time.Now().Format("200601")
star := &GroupPowerMonthStar{
......@@ -59,6 +60,7 @@ func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysq
}
// 增加家族之星分数
// Deprecated: 用redis代替
func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
star := &GroupPowerDayStar{
Date: time.Now(),
......@@ -81,32 +83,11 @@ func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.
return nil
}
// 获取家族之星分数
// 允许返回gorm.ErrRecordNotFound
func GetGroupPowerDayStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerDayStar, error) {
res := new(GroupPowerDayStar)
date := time.Now()
if err := model.DB().Where("date = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", date.Format("2006-01-02"), groupPowerId, userId, _type).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 获取家族之星分数
// 允许返回gorm.ErrRecordNotFound
func GetGroupPowerMonthStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerMonthStar, error) {
res := new(GroupPowerMonthStar)
month := time.Now().Format("200601")
if err := model.DB().Where("month = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", month, groupPowerId, userId, _type).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 获取家族之星排行
func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int) ([]*GroupPowerMonthStar, error) {
// Deprecated: 用redis
func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*GroupPowerMonthStar, error) {
var res []*GroupPowerMonthStar
month := time.Now().Format("200601")
//month := time.Now().Format("200601")
if err := model.DB().Model(GroupPowerMonthStar{}).Where("month = ? AND group_power_id = ? AND `type` = ?", month, groupPowerId, _type).
Order("score desc").Offset(offset).Limit(limit).Find(&res).Error; err != nil {
model.Log.Errorf("GetGroupPowerMonthStarRank fail:%v", err)
......
......@@ -13,6 +13,7 @@ import (
"gorm.io/gorm"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/myerr"
"strconv"
"strings"
......@@ -242,6 +243,20 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if len(groupIds) <= 0 {
return result, nil
}
// 获取群组中上麦用户
for _, groupId := range groupIds {
groupMicUserKey := mic_k.GetGroupOnMicUser(groupId)
userIds, err := model.Redis.HVals(model, groupMicUserKey).Result()
if err != nil {
model.Log.Errorf("BatchGetAllMicUser fail:%v", err)
}
for _, userIdStr := range userIds {
if userId, _ := strconv.ParseUint(userIdStr, 10, 64); userId > 0 {
result[groupId] = append(result[groupId], userId)
}
}
}
return result, nil
keys := make([]string, 0)
for _, g := range groupIds {
......@@ -253,7 +268,7 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if err != nil {
return nil, err
}
model.Log.Infof("BatchGetAllMicUser redis return size = %d, mics: %v", len(mics), mics)
//model.Log.Infof("BatchGetAllMicUser redis return size = %d, mics: %v", len(mics), mics)
if len(mics) >= len(groupIds) {
for i, g := range groupIds {
......@@ -432,7 +447,7 @@ func GetMicUserByExternalId(model *domain.Model, externalId string) (*MicUser, e
//麦位上没人,返回nil
func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error) {
if i < 1 || i > 30 {
if i < 1 || i > MaxMicNum {
return nil, myerr.NewSysErrorF("麦序不对,不在范围值内 i:%v", i)
}
str, err := redisCli.GetRedis().Get(context.Background(), redis_key.GetPrefixGroupMicUser(groupUuid, i)).Result()
......@@ -455,6 +470,7 @@ func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error)
I: i,
ExternalId: micUser.ExternalId,
UserId: micUser.UserId,
CpUserId: micUser.CpUserId,
Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp,
}, nil
......
......@@ -3,6 +3,8 @@ package group_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"time"
)
type GroupBanned struct {
......@@ -24,12 +26,19 @@ func (banned *GroupBanned) Delete(model *domain.Model) error {
return model.Db.Where(banned).Delete(&GroupBanned{}).Error
}
var bannedGroupCache = gcache.New(100).LRU().Build()
func GetBannedGroups(model *domain.Model) ([]GroupBanned, error) {
key := "banned"
if data, err := bannedGroupCache.Get(key); err == nil {
return data.([]GroupBanned), nil
}
result := make([]GroupBanned, 0)
err := model.Db.Find(&result).Error
err := model.DB().Find(&result).Error
if err != nil {
return nil, err
}
bannedGroupCache.SetWithExpire(key, result, time.Minute*5)
return result, nil
}
......
package group_m
import "git.hilo.cn/hilo-common/domain"
// 获取游戏房
func GetGameGroupsMap(model *domain.Model) map[string]bool {
res := make(map[string]bool)
var rows []GroupInfo
if err := model.DB().Model(GroupInfo{}).Where("is_game_room = 1").Find(&rows).Error; err != nil {
model.Log.Errorf("GetGameGroupsMap fail:%v", err)
return res
}
for _, v := range rows {
res[v.ImGroupId] = true
}
return res
}
......@@ -7,6 +7,7 @@ import (
"git.hilo.cn/hilo-common/utils"
"github.com/bluele/gcache"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/enum/group_e"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
......@@ -46,6 +47,7 @@ type GroupInfo struct {
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
VisitCount int64 `gorm:"-"` // 热度
IsGameRoom uint8 // 是否1v1游戏房
}
func GenerateGroupCode(n uint16) string {
......@@ -566,3 +568,45 @@ func GetFamilyRooms(model *domain.Model, familyId uint64, pageSize, pageIndex in
return res, nextIdx, hasNext, nil
}
func IsUseTRTC(model *domain.Model, imGroupId string) bool {
var count int64
if err := model.DB().Table("group_trtc").Where("im_group_id=?", imGroupId).Count(&count).Error; err != nil {
model.Log.Errorf("IsUseTRTC err:%v, groupId:%s", err, imGroupId)
return false
}
return count > 0
}
type GroupTrtc struct {
mysql.Entity
ImGroupId mysql.Str
}
// 初始化trtc房间
func InitTRTC(model *domain.Model, imGroupId string) error {
if err := model.DB().Model(GroupTrtc{}).Clauses(clause.OnConflict{DoNothing: true}).Create(&GroupTrtc{ImGroupId: imGroupId}).Error; err != nil {
model.Log.Errorf("InitTRTC err:%v, groupId:%s", err, imGroupId)
return err
}
return nil
}
// 初始化trtc房间
func DeleteTRTC(model *domain.Model, imGroupId string) error {
model.Log.Infof("DeleteTRTC , groupId:%s", imGroupId)
if err := model.DB().Model(GroupTrtc{}).Where("im_group_id = ?", imGroupId).Delete(&GroupTrtc{}).Error; err != nil {
model.Log.Errorf("DeleteTRTC err:%v, groupId:%s", err, imGroupId)
return err
}
return nil
}
func CountTRTC(model *domain.Model) int64 {
var total int64
if err := model.DB().Model(GroupTrtc{}).Count(&total).Error; err != nil {
model.Log.Errorf("CountTRTC fail:%v", err)
}
model.Log.Infof("CountTRTC , total:%v", total)
return total
}
......@@ -3,9 +3,11 @@ package group_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/myerr"
"time"
)
//群组勋章
......@@ -30,7 +32,6 @@ func (groupInfo *GroupInfo) GroupMedalMgrAdd(model *domain.Model, resMedalId uin
}
}
func GetGroupMedalOrErr(model *domain.Model, id mysql.ID) (*GroupMedal, error) {
groupMedal := GroupMedal{}
if err := model.Db.Model(&GroupMedal{}).First(&groupMedal, id).Error; err != nil {
......@@ -65,7 +66,11 @@ func BatchGetMedals(db *gorm.DB, groupIds []string) (map[string][]uint64, error)
return nil, nil
}
rows := make([]GroupMedal, 0)
if err := db.Model(&GroupMedal{}).Where("im_group_id IN ?", groupIds).Find(&rows).Error; err != nil {
if err := db.Model(GroupMedal{}).Joins("left join res_medal rm on group_medal.res_medal_id = rm.id").
Where("group_medal.im_group_id IN ?", groupIds).
Where("(group_medal.expire_at is null or group_medal.expire_at > ?)", time.Now().Format(utils.DATETIME_FORMAT)).
Order("rm.sort").
Find(&rows).Error; err != nil {
return nil, err
}
result := make(map[string][]uint64, 0)
......
......@@ -64,6 +64,20 @@ func IsHiddenGroup(db *gorm.DB, groupId string) (bool, error) {
}
}
func IsHiddenGroupBy(model *domain.Model, imGroupId string) bool {
info := new(GroupSetting)
if err := model.DB().Model(GroupSetting{}).Where("group_id = ? and is_hidden = 1", imGroupId).First(&info).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return false
}
return false
}
if info != nil && info.ID > 0 {
return true
}
return false
}
func (gs *GroupSetting) Get(db *gorm.DB) error {
return db.Where(gs).First(gs).Error
}
......
......@@ -23,9 +23,13 @@ func (g *GroupTop) Delete(model *domain.Model) error {
return model.Db.Where(g).Delete(&GroupTop{}).Error
}
func GroupTopGetAll(model *domain.Model) ([]string, error) {
func GroupTopGetAll(model *domain.Model, area int) ([]string, error) {
rows := make([]GroupTop, 0)
err := model.Db.Order("id").Find(&rows).Error
err := model.DB().Table("group_top").
Joins("left join group_info gi on group_top.im_group_id = gi.im_group_id "+
"left join res_country rc on gi.country = rc.name").
Where("rc.area = ?", area).
Order("group_top.id").Find(&rows).Error
if err != nil {
return nil, err
}
......
package group_m
import (
"git.hilo.cn/hilo-common/domain"
"hilo-group/_const/enum/group_e"
"hilo-group/myerr"
"math/rand"
"time"
)
type GroupIm struct {
Id uint64
Provider group_e.GroupProvider
Prob int
StartIdx int `gorm:"-"'`
EndIdx int `gorm:"-"`
}
type GroupImLog struct {
ImGroupId string
Provider group_e.GroupProvider
}
func GetGroupImConf(model *domain.Model) ([]*GroupIm, error) {
rows := make([]*GroupIm, 0)
if err := model.Db.Table("group_im").Find(&rows).Error; err != nil {
return nil, myerr.WrapErr(err)
}
return rows, nil
}
func GetRandomImProvider(model *domain.Model) group_e.GroupProvider {
var res group_e.GroupProvider
confList, err := GetGroupImConf(model)
if err != nil {
model.Log.Errorf("GetRandomImProvider err:%v", err)
return res
}
conf := GetRandomGroupImConf(confList)
return conf.Provider
}
func GetRandomGroupImConf(confList []*GroupIm) *GroupIm {
var res *GroupIm
var max int
for i, v := range confList {
if v.Prob > 0 {
confList[i].StartIdx = max
max += v.Prob
confList[i].EndIdx = max
}
}
rand.Seed(time.Now().UnixNano())
randNum := rand.Intn(max)
for _, v := range confList {
if v.StartIdx <= randNum && randNum < v.EndIdx {
res = v
}
}
return res
}
func CreateGroupImLog(model *domain.Model, imGroupId string, provider group_e.GroupProvider) error {
if err := model.Db.Model(GroupImLog{}).Create(GroupImLog{ImGroupId: imGroupId, Provider: provider}).Error; err != nil {
return myerr.WrapErr(err)
}
return nil
}
This diff is collapsed.
This diff is collapsed.
......@@ -14,6 +14,7 @@ import (
"gorm.io/gorm/clause"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/group_k"
"hilo-group/domain/cache/room_c"
"hilo-group/domain/model/user_m"
"hilo-group/myerr"
......@@ -49,14 +50,14 @@ func RoomLivingExpire(model *domain.Model, groupUid string, userId uint64) {
model.Log.Infof("room RoomLivingExpire userId:%v, groupUid:%v", userId, groupUid)
//
key := redis_key.GetPrefixGroupRoomLiving()
i, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
_, err := model.RedisCluster.ZAdd(context.Background(), key, &redis2.Z{
Score: float64(time.Now().Unix()),
Member: getMemberStr(groupUid, userId),
}).Result()
if err != nil {
model.Log.Errorf("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err)
} else {
model.Log.Infof("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
//model.Log.Infof("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
}
}
......@@ -69,17 +70,18 @@ func RoomLivingIn(model *domain.Model, groupUid string, userId uint64, externalI
}
//
key := redis_key.GetPrefixGroupRoomLiving()
i, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
_, err := model.RedisCluster.ZAdd(context.Background(), key, &redis2.Z{
Score: float64(time.Now().Unix()),
Member: getMemberStr(groupUid, userId),
}).Result()
if err != nil {
model.Log.Errorf("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err)
} else {
model.Log.Infof("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
//model.Log.Infof("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
}
go func(myContext *mycontext.MyContext, groupId string) {
model := domain.CreateModelContext(myContext) // 野协程给新的model.Db
roomOnlineUser, err := GetRoomOnlineUser(myContext, groupId)
if err != nil {
myContext.Log.Errorf("room RoomLivingIn roomOnlineUser err:%+v, groupUid:%v", err, groupId)
......@@ -110,11 +112,11 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err)
}
data, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result()
data, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
......@@ -123,12 +125,12 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri
for i, _ := range data {
gid, uid := analysisMemberStr(data[i])
if uid == userId && (groupId == "" || gid == groupId) {
if _, err := redisCli.GetRedis().ZRem(context.Background(), key, getMemberStr(gid, uid)).Result(); err != nil {
if _, err := model.RedisCluster.ZRem(context.Background(), key, getMemberStr(gid, uid)).Result(); err != nil {
model.Log.Errorf("RoomLivingLeave ZRem key:%s, groupId:%s, userId:%d, err:%v", key, gid, uid, err)
return nil, myerr.WrapErr(err)
} else {
groupIds = append(groupIds, gid)
model.Log.Infof("RoomLivingLeave ZRem success key:%s, groupId:%s, userId:%d", key, gid, uid)
//model.Log.Infof("RoomLivingLeave ZRem success key:%s, groupId:%s, userId:%d", key, gid, uid)
}
// 发信令,让前端重新拉取,接受容错,
......@@ -207,7 +209,7 @@ func RoomLivingLeaveByKick(model *domain.Model, groupUuid string, beKickuserId u
Target: beKickExternalId,
}, false)*/
MicGroupKickOutRPush(model, groupUuid, userExternalId, beKickExternalId)
MicGroupKickOutRPush(model, groupUuid, userExternalId, beKickExternalId, beKickuserId)
return roomLivingLeave(model, beKickuserId, groupUuid)
}
......@@ -270,15 +272,15 @@ func RoomLivingExistsUserId(groupUid string) ([]uint64, error) {
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
var model = domain.CreateModelNil()
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err)
}
groupUserIdstrs, err := redisCli.GetRedis().ZRevRange(context.Background(), key, 0, -1).Result()
groupUserIdstrs, err := model.RedisCluster.ZRevRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
mylogrus.MyLog.Infof("group_room_living RoomLivingExistsUserId groupUserIdstrs:%v", groupUserIdstrs)
//mylogrus.MyLog.Infof("group_room_living RoomLivingExistsUserId groupUserIdstrs:%v", groupUserIdstrs)
userIds := make([]uint64, 0, len(groupUserIdstrs))
for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
......@@ -298,11 +300,11 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) {
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
model := domain.CreateModelNil()
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err)
}
groupUserIdstrs, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result()
groupUserIdstrs, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
......@@ -323,16 +325,16 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) {
func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{}, error) {
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
model.Log.Infof("RoomLivingExistsGroup: err:%v", err)
return nil, myerr.WrapErr(err)
}
groupUserIdstrs, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result()
groupUserIdstrs, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
model.Log.Infof("group_room_living RoomLivingExistsGroup groupUserIdstrs:%v", groupUserIdstrs)
//model.Log.Infof("group_room_living RoomLivingExistsGroup groupUserIdstrs:%v", groupUserIdstrs)
groupGroup := map[string]map[uint64]struct{}{}
for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
......@@ -342,7 +344,7 @@ func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{},
groupGroup[tempGroupUid] = map[uint64]struct{}{userId: {}}
}
}
model.Log.Infof("RoomLivingExistsGroup size = %d", len(groupGroup))
//model.Log.Infof("RoomLivingExistsGroup size = %d", len(groupGroup))
return groupGroup, nil
}
......@@ -388,18 +390,8 @@ func GetAllGroupsSorted(model *domain.Model) ([]string, error) {
// 取房间最近N天的访问人数
func GetRoomVisitCount(groupId string) (int64, error) {
// 每群定时请一次数据可以了
now := time.Now()
if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
// 先移除(N天之前的),后统计
if _, err := redisCli.GetRedis().ZRemRangeByScore(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId),
"0", strconv.FormatInt(time.Now().AddDate(0, 0, -redis_key.GroupInDurationTTL).Unix(), 10)).
Result(); err != nil {
return 0, err
}
}
visitCount, err := redisCli.GetRedis().ZCard(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId)).Result()
key := group_k.GetUserEnterRoomGroupKey(groupId)
visitCount, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
if err != nil {
return 0, err
}
......@@ -428,15 +420,12 @@ func BatchGetRoomVisitCount(logE *logrus.Entry, groupIds []string) (map[string]i
if err != nil {
return nil, err
}
logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
visitCount := make(map[string]int64)
for _, groupId := range groupIds {
// 先从二级缓存中找
if c, ok := roomVisitCount[groupId]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
logE.Debugf("GetRoomVisitCount, from roomVisitCount %s - %d", groupId, vc)
visitCount[groupId] = vc
}
} else {
......@@ -463,7 +452,7 @@ func BatchGetRoomVisitCountList(logE *logrus.Entry, groupIds []string) (map[stri
if err != nil {
return nil, nil, err
}
logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
//logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
res := make([]*RoomVisit, 0, len(groupIds))
visitCount := make(map[string]int64)
......@@ -504,7 +493,8 @@ func (uer *UserEnterRoom) Save(db *gorm.DB) error {
func (uer *UserEnterRoom) Find(db *gorm.DB) ([]UserEnterRoom, error) {
rows := make([]UserEnterRoom, 0)
if err := db.Where(uer).Order("enter_time DESC").Find(&rows).Error; err != nil {
t := time.Now().AddDate(0, 0, -15)
if err := db.Where(uer).Where("enter_time >= ?", t).Order("enter_time DESC").Find(&rows).Error; err != nil {
return nil, err
}
return rows, nil
......
......@@ -57,6 +57,24 @@ func GetAllGroupSupportResult(db *gorm.DB, period string) (map[string]uint8, err
return result, nil
}
func GetGroupSupportResult(db *gorm.DB, period string, groupIds []string) (map[string]uint8, error) {
if len(period) <= 0 {
return nil, nil
}
gsr := GroupSupportResult{
Period: period,
}
rows := make([]GroupSupportResult, 0)
if err := db.Where(gsr).Where("group_uid in (?)", groupIds).Find(&rows).Error; err != nil {
return nil, err
}
result := make(map[string]uint8)
for _, i := range rows {
result[i.GroupUid] = i.Grade
}
return result, nil
}
//群组扶持奖励,利益分配者
type GroupSupportAwardAdmin struct {
mysql.Entity
......@@ -102,14 +120,14 @@ func (gsa *GroupSupportAwardMgr) Get(db *gorm.DB) ([]GroupSupportAwardMgr, error
}
//添加记录
func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mysql.ID, resGroupSupportId mysql.ID, userIds []mysql.ID, period string) (*GroupSupportAwardAdmin, []GroupSupportAwardMgr, error) {
//资源获取
resGroupSupport, err := res_m.GetResGroupSupportById(model, resGroupSupportId)
if err != nil {
return nil, nil, err
}
if int(resGroupSupport.MgrNum) < len(userIds) {
return nil, nil, myerr.NewSysErrorF("AddGroupSupportAward mgrNum:%v 同 len(userIds)=%v 不一致", resGroupSupport.MgrNum, len(userIds))
func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mysql.ID, resSupport *res_m.ResGroupSupport, userIds []mysql.ID, period string) (*GroupSupportAwardAdmin, []GroupSupportAwardMgr, error) {
////资源获取
//resGroupSupport, err := res_m.GetResGroupSupportById(model, resGroupSupportId)
//if err != nil {
// return nil, nil, err
//}
if int(resSupport.MgrNum) < len(userIds) {
return nil, nil, myerr.NewSysErrorF("AddGroupSupportAward mgrNum:%v 同 len(userIds)=%v 不一致", resSupport.MgrNum, len(userIds))
}
//增加群主奖励
......@@ -118,9 +136,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys
GroupUid: groupUid,
IssuerUserId: issuerUserId,
UserId: issuerUserId,
DiamondNum: resGroupSupport.AdminAward,
Grade: resGroupSupport.Grade,
ResGroupSupportId: resGroupSupport.ID,
DiamondNum: resSupport.AdminAward,
Grade: resSupport.Grade,
ResGroupSupportId: resSupport.ID,
Period: period,
}
......@@ -133,9 +151,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys
GroupUid: groupUid,
IssuerUserId: issuerUserId,
UserId: userIds[i],
DiamondNum: resGroupSupport.MgrAward,
Grade: resGroupSupport.Grade,
ResGroupSupportId: resGroupSupport.ID,
DiamondNum: resSupport.MgrAward,
Grade: resSupport.Grade,
ResGroupSupportId: resSupport.ID,
Period: period,
})
}
......
......@@ -103,7 +103,9 @@ func (rb *RoomBanner) GetRoomBanners(db *gorm.DB, vcAllow bool) ([]RoomBanner, e
}
res := make([]RoomBanner, 0, len(rows))
for _, v := range rows {
if !vcAllow && (v.ID == 241 || v.ID == 781 || v.ID == 771) {
// 版本控制
if !vcAllow && (v.ID == 241 || v.ID == 781 || v.ID == 771 || v.ID == 911 || v.ID == 841 ||
v.ID == 851 || v.ID == 1001 || v.ID == 981 || v.ID == 1451 || v.ID == 1621) {
continue
}
res = append(res, v)
......
package mic_m
import (
"git.hilo.cn/hilo-common/_const/enum/timezone_e"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/redis_key/mic_k"
"time"
)
......@@ -17,14 +19,15 @@ type UserOnMic struct {
LastCalTs int64
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
Tz timezone_e.Timezone
}
// 获取用户当日上麦
// 允许返回gorm.ErrRecordNotFound
func GetUserOnMic(model *domain.Model, userId mysql.ID) (*UserOnMic, error) {
func GetUserOnMic(model *domain.Model, userId mysql.ID, tz timezone_e.Timezone) (*UserOnMic, error) {
res := new(UserOnMic)
day := time.Now().Format("2006-01-02")
if err := model.DB().Where("date = ? AND user_id = ?", day, userId).First(res).Error; err != nil {
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
if err := model.DB().Where("date = ? AND user_id = ? AND tz = ?", day, userId, tz).First(res).Error; err != nil {
return nil, err
}
return res, nil
......@@ -34,48 +37,90 @@ func GetUserOnMic(model *domain.Model, userId mysql.ID) (*UserOnMic, error) {
// 事务操作
func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
omMic, err := GetUserOnMic(model, userId)
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
day0Ts := utils.GetZeroTime(time.Now()).Unix()
if omMic != nil && joinMicTimestamp < omMic.LastCalTs { // 加入的时间比上次计算时间小
curTs = omMic.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
day := time.Now().Format("2006-01-02")
onMicNew := &UserOnMic{
Date: day,
UserId: userId,
Seconds: mysql.Num(score),
LastCalTs: nowTs,
for _, tz := range timezone_e.Timezones {
omMic, err := GetUserOnMic(model, userId, tz)
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
day0Ts := utils.GetZeroTime(time.Now().In(timezone_e.TimezoneLocMap[tz])).Unix()
if omMic != nil && joinMicTimestamp < omMic.LastCalTs { // 加入的时间比上次计算时间小
curTs = omMic.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
onMicNew := &UserOnMic{
Date: day,
UserId: userId,
Seconds: mysql.Num(score),
LastCalTs: nowTs,
Tz: tz,
}
if err := model.DB().Model(UserOnMic{}).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}, {Name: "tz"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"seconds": gorm.Expr("seconds + ?", onMicNew.Seconds),
"last_cal_ts": nowTs,
}),
}).Create(onMicNew).Error; err != nil {
model.Log.Errorf("IncrUserOnMic fail:%v", err)
return err
}
}
return nil
})
}
// 增加用户上麦时长
// 事务操作
func IncrUserOnMicV2(model *domain.Model, userId mysql.ID) error {
for _, tz := range timezone_e.Timezones {
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
if err := model.DB().Model(UserOnMic{}).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}},
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}, {Name: "tz"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"seconds": gorm.Expr("seconds + ?", onMicNew.Seconds),
"last_cal_ts": nowTs,
"seconds": gorm.Expr("seconds + ?", 60),
}),
}).Create(onMicNew).Error; err != nil {
}).Create(&UserOnMic{
Date: day,
UserId: userId,
Seconds: 60,
Tz: tz,
}).Error; err != nil {
model.Log.Errorf("IncrUserOnMic fail:%v", err)
return err
}
return nil
})
}
return nil
}
// 增加用户上麦时长
// Redis
func IncrUserOnMicV3(model *domain.Model, userId mysql.ID) error {
for _, tz := range timezone_e.Timezones {
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
tzStr := "bj"
if tz == timezone_e.TimezoneKSA {
tzStr = "ksa"
}
tzKey := mic_k.GetUserOnMicKey(userId, tzStr, day)
model.RedisCluster.IncrBy(model, tzKey, 60)
model.RedisCluster.Expire(model, tzKey, time.Hour*24*30) // 30天上麦时长
}
return nil
}
// 批量获取用户上麦时长
// @return userId->seconds
func MGetUserOnMicSeconds(model *domain.Model, day string, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
func MGetUserOnMicSeconds(model *domain.Model, day string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
var rows []UserOnMic
res := make(map[mysql.ID]mysql.Num)
if err := model.DB().Model(UserOnMic{}).Where("`date`= ? AND user_id in ?", day, userIds).Find(&rows).Error; err != nil {
if err := model.DB().Model(UserOnMic{}).Where("`date`= ? AND tz = ? AND user_id in ?", day, tz, userIds).Find(&rows).Error; err != nil {
model.Log.Errorf("MGetUserOnMic fail:%v", err)
return res, err
}
......@@ -84,3 +129,18 @@ func MGetUserOnMicSeconds(model *domain.Model, day string, userIds []uint64) (ma
}
return res, nil
}
// 批量获取用户上麦时长
// @return userId->seconds
func MGetUserOnMicSecondsRange(model *domain.Model, beginDate, endDate string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
var rows []UserOnMic
res := make(map[mysql.ID]mysql.Num)
if err := model.DB().Model(UserOnMic{}).Where("`date` >= ? AND `date` <= ? AND tz = ? AND user_id in ?", beginDate, endDate, tz, userIds).Find(&rows).Error; err != nil {
model.Log.Errorf("MGetUserOnMic fail:%v", err)
return res, err
}
for _, r := range rows {
res[r.UserId] += r.Seconds
}
return res, nil
}
......@@ -144,7 +144,7 @@ func BatchGetActiveNoble(db *gorm.DB, userIds []uint64) (map[uint64]UserNoble, e
start += NUM
end += NUM
}
mylogrus.MyLog.Infof("BatchGetActiveNoble expected:%v,actual:%v,notEndUids:%v", len(userIds), len(result), notEndUids)
//mylogrus.MyLog.Infof("BatchGetActiveNoble expected:%v,actual:%v,notEndUids:%v", len(userIds), len(result), notEndUids)
if len(userIds) != len(result) {
mylogrus.MyLog.Warnf("BatchGetActiveNoble expected:%v", userIds)
}
......@@ -177,4 +177,4 @@ func BatchGetNobleLevel(db *gorm.DB, userIds []uint64) (map[uint64]uint16, error
result[i] = m[i].Level
}
return result, nil
}
\ No newline at end of file
}
......@@ -23,6 +23,7 @@ type ResCountry struct {
StandardShortName mysql.Str
AreaCode mysql.Str
AreaCodeName mysql.Str
Area mysql.Str
}
type ResLanguage struct {
......@@ -81,6 +82,22 @@ func GetAllCountries(model *domain.Model) (map[string]string, error) {
return result, nil
}
// 获取所有国家的Area信息
func GetAllCountriesArea(model *domain.Model) (map[string]string, error) {
var countrys []ResCountry
if err := model.Db.Model(&ResCountry{}).Where(&ResCountry{
Status: mysql.USER,
}).Find(&countrys).Error; err != nil {
return nil, myerr.WrapErr(err)
}
result := make(map[string]string, 0)
for _, i := range countrys {
result[i.Name] = i.Area
}
return result, nil
}
func GetAllCountryByFilter(model *domain.Model, shortNames []string) ([]ResCountry, error) {
var countrys []ResCountry
if err := model.Db.Model(&ResCountry{}).Where(&ResCountry{
......@@ -197,3 +214,9 @@ func GetLangeByCountry(db *gorm.DB, country mysql.Str) (string, error) {
}
}
//获取所有国家名字列表
func GetCountryNameList(model *domain.Model) ([]string, error) {
res := make([]string, 0)
err := model.DB().Table("res_country").Select("distinct(name) name").Pluck("name", &res).Error
return res, myerr.WrapErr(err)
}
......@@ -10,10 +10,11 @@ import (
type ResHeadwear struct {
mysql.Entity
*domain.Model `gorm:"-"`
Name mysql.Str
PicUrl mysql.Str
EffectUrl mysql.Str
*domain.Model `gorm:"-"`
Name mysql.Str
PicUrl mysql.Str
EffectUrl mysql.Str
ReverseEffectUrl mysql.Str
}
func GetResHeadwearById(model *domain.Model, id mysql.ID) (*ResHeadwear, error) {
......
......@@ -325,7 +325,7 @@ func GetOnlineStatus(model *domain.Model, extIds []string) (map[string]uint, err
model.Log.Warnf("getOnlineStatus redis failed")
left = extIds
} else {
model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r)
//model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r)
if len(r) >= len(extIds) {
for i, e := range extIds {
......@@ -387,10 +387,10 @@ func getOnlineStatus(extIds []string) ([]interface{}, error) {
for _, e := range extIds {
keys = append(keys, redis_key.GetOnLineStatusKey(e))
}
return redisCli.RedisClient.MGet(context.Background(), keys...).Result()
return redisCli.RedisClusterClient.MGet(context.Background(), keys...).Result()
}
func setOnlineStatus(extId string, status uint, ttl time.Duration) error {
key := redis_key.GetOnLineStatusKey(extId)
return redisCli.RedisClient.Set(context.Background(), key, status, ttl).Err()
return redisCli.RedisClusterClient.Set(context.Background(), key, status, ttl).Err()
}
......@@ -3,10 +3,12 @@ package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr"
)
//获取用户的国家,和所属的区域(是否阿语区)
// 获取用户的国家,和所属的区域(是否阿语区)
// 默认国家给沙特
func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
type info struct {
Name string
......@@ -14,7 +16,11 @@ func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
}
res := new(info)
if err := model.DB().Raw("select name, area from res_country where name = (select country from user where id = ?)", id).First(&res).Error; err != nil {
return "", 0, myerr.WrapErr(err)
if err != gorm.ErrRecordNotFound {
return "", 0, myerr.WrapErr(err)
}
// gorm.ErrRecordNotFound
return "KSA", 1, nil
}
return res.Name, res.Area, nil
}
......@@ -48,8 +48,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
if err != nil {
return nil, err
}
logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes)
logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList)
//logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes)
//logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList)
maxGrades := make(map[uint8]int, 0)
maxMedalIds := make(map[uint8]uint32, 0)
......@@ -70,8 +70,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)
......
......@@ -3,13 +3,17 @@ package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr"
"strings"
)
type SuperManager struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId mysql.ID
IsAll bool
Countries string
}
func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) {
......@@ -22,6 +26,33 @@ func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) {
return n > 0, nil
}
// 对某人是否有超管权限
func IsSuperManagerV2(model *domain.Model, userId, targetUserId mysql.ID) (bool, error) {
var man SuperManager
if err := model.Db.Model(&SuperManager{}).Where(&SuperManager{
UserId: userId,
}).First(&man).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("IsSuperManagerV2 fail:%v", err)
}
return false, nil
}
if man.IsAll {
return true, nil
}
targetUser, err := GetUser(model, targetUserId)
if err != nil {
return false, err
}
countries := strings.Split(man.Countries, ",")
for _, c := range countries {
if c == targetUser.Country {
return true, nil
}
}
return false, nil
}
func GetSuperManagerAll(model *domain.Model) ([]uint64, error) {
superManagers := []SuperManager{}
if err := model.Db.Model(&SuperManager{}).Find(&superManagers).Error; err != nil {
......@@ -51,4 +82,4 @@ func GetSuperManagerMap(userIds []uint64) (map[uint64]bool, error) {
rs[superManagers[i].UserId] = true
}
return rs, nil
}
\ No newline at end of file
}
......@@ -85,12 +85,29 @@ func GetUsersByIds(model *domain.Model, userIds []mysql.ID) ([]User, error) {
return users, nil
}
// 分批获取userIds
func GetUserMapByIds(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]User, error) {
rows, err := GetUsersByIds(model, userIds)
if err != nil {
return nil, err
}
result := make(map[mysql.ID]User, 0)
end := 500
if end > len(userIds) {
end = len(userIds)
}
var rows []User
start := 0
for start < len(userIds) {
tmp, err := GetUsersByIds(model, userIds[start:end])
if err != nil {
return result, err
} else {
rows = append(rows, tmp...)
}
start += 500
end += 500
if end > len(userIds) {
end = len(userIds)
}
//model.Log.Infof("GetUserMapByIds start:%v-end:%v", start, end)
}
for _, i := range rows {
result[i.ID] = i
}
......@@ -127,3 +144,39 @@ func GetUsers(model *domain.Model, ids []mysql.ID) ([]*User, error) {
}
return res, nil
}
// 获取用户externalIds
// return []externalIds map[userId]extId map[userId]code
func GetUserExternalIds(model *domain.Model, userIds []mysql.ID) ([]string, map[uint64]string, map[uint64]string) {
var res []string
var m = make(map[uint64]string)
var c = make(map[uint64]string)
if len(userIds) <= 0 {
return res, m, c
}
var users []User
total := len(userIds)
const NUM = 500
start, end := 0, NUM
for start < total {
if end > total {
end = total
}
var tmp []User
tmpUserId := userIds[start:end]
if err := model.DB().Model(User{}).Where("id in (?)", tmpUserId).Select("id,external_id,code").Find(&tmp).Error; err != nil {
model.Log.Errorf("GetUserExternalIds fail:%v", err)
} else if len(tmp) > 0 {
users = append(users, tmp...)
}
start += NUM
end += NUM
}
for _, user := range users {
res = append(res, user.ExternalId)
m[user.ID] = user.ExternalId
c[user.ID] = user.Code
}
return res, m, c
}
......@@ -59,14 +59,34 @@ func GetVip(db *gorm.DB, userId uint64) (*UserVip, error) {
return nil, nil
}
// 分批获取
func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) {
result := make(map[uint64]*int64, 0)
rows := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&rows).Error
if err != nil {
return nil, err
end := 500
if end > len(userIds) {
end = len(userIds)
}
start := 0
for start < len(userIds) {
tmp := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds[start:end]).Find(&tmp).Error
if err != nil {
return nil, err
}
if err != nil {
return result, err
} else {
rows = append(rows, tmp...)
}
start += 500
end += 500
if end > len(userIds) {
end = len(userIds)
}
//mylogrus.MyLog.Infof("BatchGetVips start:%v-end:%v", start, end)
}
result := make(map[uint64]*int64, 0)
for _, i := range userIds {
result[i] = nil
}
......
......@@ -8,6 +8,7 @@ import (
"hilo-group/domain/model/diamond_m"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/res_m"
"hilo-group/domain/model/user_m"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
)
......@@ -24,6 +25,22 @@ func NewDiamondService(myContext *mycontext.MyContext) *DiamondService {
// 币商转账钻石-家族限制检查
func (this *DiamondService) CheckDealerTransferFamilyLimit(dealerId, userId uint64, lang string) error {
model := domain.CreateModelContext(this.svc.MyContext)
//获取国家信息
_, dealerArea, err := user_m.GetUserCountryArea(model, dealerId)
if err != nil {
model.Log.Errorf("CheckDealerTransferFamilyLimit 获取国家资源错误 dealerId:%d, err:%v", dealerId, err)
return err
}
_, area, err := user_m.GetUserCountryArea(model, userId)
if err != nil {
model.Log.Errorf("CheckDealerTransferFamilyLimit 获取国家资源错误 userId:%d, err:%v", userId, err)
return err
}
if dealerArea != area {
return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_CHARGE_NO_AREA, lang, bizerr.DealerCannotSaleToOtherArea))
}
// 代理、用户是否加入了家族
dealerFamily, err := groupPower_m.GetGroupPowerUserOrNil(model, dealerId)
if err != nil {
......@@ -40,25 +57,25 @@ func (this *DiamondService) CheckDealerTransferFamilyLimit(dealerId, userId uint
return err
}
// 用户的家族是否有家族代理
var userHasFamilyAgent bool
if userFamily != nil {
userHasFamilyAgent, err = groupPower_m.IsGroupPowerHasFamilyAgent(model, userFamily.GroupPowerId)
if err != nil {
return err
}
}
//var userHasFamilyAgent bool
//if userFamily != nil {
// userHasFamilyAgent, err = groupPower_m.IsGroupPowerHasFamilyAgent(model, userFamily.GroupPowerId)
// if err != nil {
// return err
// }
//}
if dealerFamily != nil && dealerFamily.GroupPowerId > 0 { // 代理加入了家族
if isFamilyAgent && (userFamily == nil || userFamily.GroupPowerId != dealerFamily.GroupPowerId) { // 是家族代理:只能向本家族成员转移钻石,如果向非家族成员转移钻石,则提示“非家族成员”
return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_NOT_FAMILY_MEMBER, lang, bizerr.GroupPowerDealerNotMember))
}
if !isFamilyAgent && userHasFamilyAgent { // 不是家族代理:如果用户加入了家族,且家族中有家族代理,那么也不能,“此用户已有家族代理,不能出售钻石”
return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_DEALER_CAN_NOT_SOLE, lang, bizerr.GroupPowerDealerCanNotSole))
}
//if !isFamilyAgent && userHasFamilyAgent { // 不是家族代理:如果用户加入了家族,且家族中有家族代理,那么也不能,“此用户已有家族代理,不能出售钻石”
// return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_DEALER_CAN_NOT_SOLE, lang, bizerr.GroupPowerDealerCanNotSole))
//}
} else { // 代理没有加入家族的
// 普通代理:不能向已经加入家族的成员(并且家族有家族代理)转移钻石,如果转移则提示“此用户已有家族代理,不能出售钻石”
if userHasFamilyAgent {
return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_DEALER_CAN_NOT_SOLE, lang, bizerr.GroupPowerDealerCanNotSole))
}
//if userHasFamilyAgent {
// return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_DEALER_CAN_NOT_SOLE, lang, bizerr.GroupPowerDealerCanNotSole))
//}
}
return nil
}
This diff is collapsed.
package event_s
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"golang.org/x/sync/errgroup"
"hilo-group/domain/event/group_ev"
"hilo-group/domain/model/event_m"
"runtime/debug"
)
type GroupInEventService struct {
svc *domain.Service
}
func NewGroupInEventService(myContext *mycontext.MyContext) *GroupInEventService {
svc := domain.CreateService(myContext)
return &GroupInEventService{svc}
}
//
func (s *GroupInEventService) Consume() error {
defer func() {
if err := recover(); err != nil {
s.svc.Log.Errorf("ExceptionHandle GroupInEventService Consume SYSTEM ACTION PANIC: %v, stack: %v", err, string(debug.Stack()))
}
}()
var model = domain.CreateModel(s.svc.CtxAndDb)
events, offset, err := event_m.FetchEventGroupIn(model, BatchCount)
if err != nil {
return err
}
var wg errgroup.Group
for k := range events {
cpEvent := &event_m.EventGroupIn{
Entity: mysql.Entity{
ID: events[k].ID,
CreatedTime: events[k].CreatedTime,
UpdatedTime: events[k].UpdatedTime,
},
Proto: events[k].Proto,
Payload: events[k].Payload,
Mark: events[k].Mark,
MarkHiloGroup: events[k].MarkHiloGroup,
}
wg.Go(func() error {
if cpEvent.MarkHiloGroup == mysql.YES {
model.Log.Warnf("already consume msg :%v", cpEvent)
return nil
}
groupInEvent := new(group_ev.TxGroupInEvent)
if err := json.Unmarshal(cpEvent.Payload, groupInEvent); err != nil {
model.Log.Errorf("json msg fail,event:%v,err:%v", cpEvent, err)
return nil
}
// 发布事件
if err := group_ev.PublishTxGroupInEvent(model, groupInEvent); err != nil {
model.Log.Errorf("PublishTxGroupInEvent,event:%v,err:%v", cpEvent, err)
return err
}
// 标记已经处理
cpEvent.Model = model
err = cpEvent.MarkDone()
if err != nil {
model.Log.Errorf("consume msg fail,event:%v,err:%v", cpEvent, err)
}
return err
})
}
err = wg.Wait()
if err != nil {
model.Log.Errorf("batch consume msg has fail,event,err:%v", err)
// 暂时先允许丢数据,继续mark offset
}
// 最后一次提交offset
if len(events) > 0 {
offset.MarkOffset = events[len(events)-1].ID
return offset.Persistence()
}
return nil
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -93,6 +93,7 @@ require (
github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e // indirect
......
......@@ -401,6 +401,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.