...
 
Commits (178)
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 ( ...@@ -10,9 +10,33 @@ import (
const ( const (
MicPrefix = "mic:" MicPrefix = "mic:"
MicDayInvite = MicPrefix + "day:invite:${userId}:${date}" // string 自动被邀请上麦,1天一次,TTL:24H 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 { func GetUserMicDayInvite(userId mysql.ID) string {
date := time.Now().Format("2006-01-02") date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicDayInvite, fmt.Sprintf("%d", userId), date) 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}" ...@@ -249,6 +249,9 @@ const groupInUserDuration = "group_in_user_duration_{groupUuid}"
// 15天内进入房间的人数 // 15天内进入房间的人数
const roomVisitCount = "room_visit_count" const roomVisitCount = "room_visit_count"
// 15天内进入房间的人数 member groupId score 麦位有人的数量
const roomVisitCountZSet = "room_visit_count_zset"
// 用户进入过的房间及时间 // 用户进入过的房间及时间
const userEnterRoom = "enter_room_{userId}" const userEnterRoom = "enter_room_{userId}"
...@@ -757,18 +760,27 @@ func GetPrefixGroupMicNumType(groupUuid string) string { ...@@ -757,18 +760,27 @@ func GetPrefixGroupMicNumType(groupUuid string) string {
return strings.Replace(groupMicNumType, "{groupUuid}", groupUuid, -1) return strings.Replace(groupMicNumType, "{groupUuid}", groupUuid, -1)
} }
// Deprecated: 用户进房时间
// 用 uer:g:${group_id}代替
func GetPrefixGroupInUserDuration(groupUuid string) string { func GetPrefixGroupInUserDuration(groupUuid string) string {
return strings.Replace(groupInUserDuration, "{groupUuid}", groupUuid, -1) return strings.Replace(groupInUserDuration, "{groupUuid}", groupUuid, -1)
} }
// Deprecated: 用户进房时间
// 可用 uer:u:${user_id}代替
func GetUserEnterRoomKey(userId uint64) string { func GetUserEnterRoomKey(userId uint64) string {
return strings.Replace(userEnterRoom, "{userId}", strconv.FormatUint(userId, 10), -1) return strings.Replace(userEnterRoom, "{userId}", strconv.FormatUint(userId, 10), -1)
} }
// Deprecated: 用redis集群中的zset代替
func GetPrefixRoomVisitCount() string { func GetPrefixRoomVisitCount() string {
return roomVisitCount return roomVisitCount
} }
func GetPrefixRoomVisitCountZset() string {
return roomVisitCountZSet
}
func GetPrefixSupportLevel(date string) string { func GetPrefixSupportLevel(date string) string {
return strings.Replace(supportLevel, "{date}", date, -1) return strings.Replace(supportLevel, "{date}", date, -1)
} }
......
...@@ -5,15 +5,24 @@ import ( ...@@ -5,15 +5,24 @@ import (
"hilo-group/cron/gift_cron" "hilo-group/cron/gift_cron"
"hilo-group/cron/group_cron" "hilo-group/cron/group_cron"
"hilo-group/cron/mic_cron" "hilo-group/cron/mic_cron"
"hilo-group/cron/user_cron"
) )
func Init() { func Init() {
user_cron.LoadSvipVipNoble() // 加载用户特权
if !config.IsMaster() { if !config.IsMaster() {
return return
} }
gift_cron.SendGiftEventInit() // 礼物消息 //gift_cron.SendGiftEventInit() // 礼物消息
gift_cron.GiftRemark() // 礼物消息补偿 //gift_cron.GiftRemark() // 礼物消息补偿
gift_cron.SendGiftEvent() // 礼物事件
mic_cron.OnMicCheck() // 检查上麦 mic_cron.OnMicCheck() // 检查上麦
mic_cron.OnMicQueue() // 检查上麦-队列操作
group_cron.GroupPowerExpClear() // 清理家族经验/等级 group_cron.GroupPowerExpClear() // 清理家族经验/等级
group_cron.GroupPowerMonthRankAct() group_cron.GroupPowerMonthRankAct()
//group_cron.GroupInEventInit() // 进房事件
//group_cron.CreateGroup() //
group_cron.CalcGroupSupport() // 群组扶持计算
//group_cron.CalcGroupSupport_OldData()
group_cron.GroupCountryListSort()
} }
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,12 +2,16 @@ package group_cron ...@@ -2,12 +2,16 @@ package group_cron
import ( import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron" "github.com/robfig/cron"
"hilo-group/domain/service/group_power_s" "hilo-group/domain/service/group_power_s"
) )
// 家族贡献月度排行榜发奖 // 家族贡献月度排行榜发奖
func GroupPowerMonthRankAct() { func GroupPowerMonthRankAct() {
if !config.IsMaster() {
return
}
c := cron.New() c := cron.New()
// 每月1号0:01结算发奖 // 每月1号0:01结算发奖
spec := "0 1 0 1 * ?" spec := "0 1 0 1 * ?"
......
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 package mic_cron
import ( import (
"fmt"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron" "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/event/mic_ev"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/mic_m"
"hilo-group/domain/service/group_mic_s"
"time"
) )
func OnMicCheck() { func OnMicCheck() {
c := cron.New() c := cron.New()
//一分钟执行一次 //一分钟执行一次
spec := "0 */1 * * * ?" spec := "30 */1 * * * ?"
_ = c.AddFunc(spec, func() { _ = c.AddFunc(spec, func() {
//获取麦上的所有人 //获取麦上的所有人
var model = domain.CreateModelNil() var model = domain.CreateModelNil()
...@@ -20,14 +26,15 @@ func OnMicCheck() { ...@@ -20,14 +26,15 @@ func OnMicCheck() {
return return
} }
for _, groupId := range groupIds { 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) micUser, err := group_m.GetMicUser(model, groupId, i)
if err != nil { if err != nil {
model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err) model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err)
} }
if micUser != nil { if micUser != nil {
if err := mic_ev.PublishOnMicEvent(model, &mic_ev.OnMicEvent{ if err := mic_c.QueueOnMic(model, &mic_ev.OnMicEvent{
GroupUuid: micUser.GroupUuid, GroupUuid: micUser.GroupUuid,
I: micUser.I, I: micUser.I,
ExternalId: micUser.ExternalId, ExternalId: micUser.ExternalId,
...@@ -35,11 +42,43 @@ func OnMicCheck() { ...@@ -35,11 +42,43 @@ func OnMicCheck() {
Forbid: micUser.Forbid, Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp, Timestamp: micUser.Timestamp,
}); err != nil { }); 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() 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 { ...@@ -22,7 +22,15 @@ type BillboardUserInfo struct {
Num uint64 `json:"num"` 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() now := time.Now()
period := now.Format(utils.COMPACT_MONTH_FORMAT) period := now.Format(utils.COMPACT_MONTH_FORMAT)
data, err := getGroupTop3Consume(period, groupId) data, err := getGroupTop3Consume(period, groupId)
...@@ -59,7 +67,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ( ...@@ -59,7 +67,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
ret, err := saveGroupTop3Consume(period, groupId, diamonds) ret, err := saveGroupTop3Consume(period, groupId, diamonds)
model.Log.Infof("GetGroupTop3Consume SAVE ret = %d, err: %v", ret, err) 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) userIds := make([]uint64, 0)
...@@ -86,7 +102,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ( ...@@ -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) { func getGroupTop3Consume(period string, groupId string) (map[string]string, error) {
......
package diamond_cv package diamond_cv
import ( import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
. "git.hilo.cn/hilo-common/utils" . "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/domain/model/diamond_m"
"hilo-group/myerr"
"strconv"
) )
type CvDiamond struct { type CvDiamond struct {
...@@ -26,33 +20,6 @@ type CvDiamondBean struct { ...@@ -26,33 +20,6 @@ type CvDiamondBean struct {
BeanNum string `json:"beanNum"` 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 { type CvDiamondDetail struct {
//1:增加 2:减少 //1:增加 2:减少
...@@ -74,113 +41,4 @@ func GetDiamond(userId mysql.ID) (*CvDiamond, error) { ...@@ -74,113 +41,4 @@ func GetDiamond(userId mysql.ID) (*CvDiamond, error) {
return nil, err return nil, err
} }
return &CvDiamond{DiamondNum: NumToUint32(&diamondAccount.DiamondNum), PinkDiamondNum: NumToUint32(&diamondAccount.PinkDiamondNum)}, nil return &CvDiamond{DiamondNum: NumToUint32(&diamondAccount.DiamondNum), PinkDiamondNum: NumToUint32(&diamondAccount.PinkDiamondNum)}, nil
} }
\ No newline at end of file
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
}
...@@ -123,6 +123,13 @@ type MemberDetail struct { ...@@ -123,6 +123,13 @@ type MemberDetail struct {
InRoom bool `json:"inRoom"` // 是否在房间内 InRoom bool `json:"inRoom"` // 是否在房间内
} }
type GroupVisitorsDetail struct {
user_cv.CvGroupMember
Role group_e.GroupRoleType `json:"role"`
OnlineStatus online_e.OnlineStatusType `json:"onlineStatus"` // IM在线状态
InRoom bool `json:"inRoom"` // 是否在房间内
}
type GroupDetail struct { type GroupDetail struct {
GroupBasicInfo GroupBasicInfo
...@@ -133,14 +140,14 @@ type GroupDetail struct { ...@@ -133,14 +140,14 @@ type GroupDetail struct {
ThemeId uint64 `json:"themeId"` ThemeId uint64 `json:"themeId"`
ThemeUrl string `json:"themeUrl"` ThemeUrl string `json:"themeUrl"`
// 1:官方 2:自定义 // 1:官方 2:自定义
ThemeType uint8 `json:"themeType"` ThemeType uint8 `json:"themeType"`
Role group_e.GroupRoleType `json:"role"` Role group_e.GroupRoleType `json:"role"`
MsgStatus uint8 `json:"msgStatus"` // 消息提醒状态 MsgStatus uint8 `json:"msgStatus"` // 消息提醒状态
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语 WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
TotalConsume uint64 `json:"totalConsume"` // 群内消费总额 TotalConsume uint64 `json:"totalConsume"` // 群内消费总额
TopConsumers []billboard_cv.BillboardUserInfo `json:"topConsumers"` // 月最高消费三甲 TopConsumers []billboard_cv.GroupTop3ConsumeUser `json:"topConsumers"` // 月最高消费三甲
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量 DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏的数字点数 DiceType uint16 `json:"diceType"` // 骰子游戏的数字点数
// "AppDefinedData": 群组维度的自定义字段 【暂时不用】 // "AppDefinedData": 群组维度的自定义字段 【暂时不用】
RoleMembers []RoleMemberInfo `json:"role_members"` RoleMembers []RoleMemberInfo `json:"role_members"`
Owner *user_cv.CvUserDetail `json:"owner"` // 群主信息 Owner *user_cv.CvUserDetail `json:"owner"` // 群主信息
...@@ -166,20 +173,20 @@ type RoomInfo struct { ...@@ -166,20 +173,20 @@ type RoomInfo struct {
ThemeId uint64 `json:"themeId"` ThemeId uint64 `json:"themeId"`
ThemeUrl string `json:"themeUrl"` ThemeUrl string `json:"themeUrl"`
// 1:官方 2:自定义 // 1:官方 2:自定义
ThemeType uint8 `json:"themeType"` ThemeType uint8 `json:"themeType"`
Role group_e.GroupRoleType `json:"role"` Role group_e.GroupRoleType `json:"role"`
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量 DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏类型 DiceType uint16 `json:"diceType"` // 骰子游戏类型
RoleMembers []SimpleRoleInfo `json:"roleMembers"` RoleMembers []SimpleRoleInfo `json:"roleMembers"`
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语 WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
Banners []BannerElement `json:"banners"` Banners []BannerElement `json:"banners"`
LuckyWheel LuckyWheelState `json:"luckyWheel"` LuckyWheel LuckyWheelState `json:"luckyWheel"`
TotalConsume uint64 `json:"totalConsume"` TotalConsume uint64 `json:"totalConsume"`
GameConfig *game_m.GameConfig `json:"gameConfig"` GameConfig *game_m.GameConfig `json:"gameConfig"`
Owner *user_cv.CvUserDetail `json:"owner"` Owner *user_cv.RoomInfoOwner `json:"owner"`
EntryEffectType int `json:"entryEffectType"` // 进场特效类型 1: CP 2:神秘人 3:贵族 4:vip EntryEffectType int `json:"entryEffectType"` // 进场特效类型 1: CP 2:神秘人 3:贵族 4:vip
CpUserAvatar string `json:"cpUserAvatar"` // cp对象头像 CpUserAvatar string `json:"cpUserAvatar"` // cp对象头像
CpLevel int `json:"cpLevel"` // cp等级 CpLevel int `json:"cpLevel"` // cp等级
} }
type SupportPageDetail struct { type SupportPageDetail struct {
...@@ -244,13 +251,24 @@ type CvCountry struct { ...@@ -244,13 +251,24 @@ type CvCountry struct {
AreaCodeName *string `json:"areaShortName"` AreaCodeName *string `json:"areaShortName"`
} }
func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds []string, pageSize, pageIndex int) ([]JoinedGroupInfo, int, error) { func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, originGroupIds []string, pageSize, pageIndex int) ([]JoinedGroupInfo, int, error) {
model := domain.CreateModel(myService.CtxAndDb) model := domain.CreateModel(myService.CtxAndDb)
groupInfo, err := group_m.BatchGetGroupInfo(model, groupIds) groupInfo, err := group_m.BatchGetGroupInfo(model, originGroupIds)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
var groupIds []string
for _, groupId := range originGroupIds {
if group, ok := groupInfo[groupId]; ok {
if group.IsGameRoom == 0 {
groupIds = append(groupIds, groupId)
}
}
}
if len(groupIds) <= 0 {
return nil, 0, nil
}
// todo: 可以移到后面,减小查询范围,因为roomMicUserMap不影响排序 // todo: 可以移到后面,减小查询范围,因为roomMicUserMap不影响排序
roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds) roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds)
...@@ -303,7 +321,7 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [ ...@@ -303,7 +321,7 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
model.Log.Infof("BuildJoinedGroupInfo, roomEnterTime: %v", roomEnterTime) //model.Log.Infof("BuildJoinedGroupInfo, roomEnterTime: %v", roomEnterTime)
// 排序优先级V8.0版本 // 排序优先级V8.0版本
sort.Slice(groupIds, func(i, j int) bool { sort.Slice(groupIds, func(i, j int) bool {
...@@ -427,39 +445,219 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [ ...@@ -427,39 +445,219 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [
return result, len(groupInfo), nil return result, len(groupInfo), nil
} }
func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*group_m.GroupInfo) ([]*PopularGroupInfo, error) { // 填充用户最近进房
groupIds := make([]string, 0, len(groupInfo)) func BuildRecentGroupInfo(myService *domain.Service, myUserId uint64, originGroupIds []string, roomEnterTime map[string]int64) ([]JoinedGroupInfo, int, error) {
for _, v := range groupInfo { model := domain.CreateModel(myService.CtxAndDb)
groupIds = append(groupIds, v.ImGroupId)
groupInfo, err := group_m.BatchGetGroupInfo(model, originGroupIds)
if err != nil {
return nil, 0, err
}
var groupIds []string
for _, groupId := range originGroupIds {
if group, ok := groupInfo[groupId]; ok {
if group.IsGameRoom == 0 {
groupIds = append(groupIds, groupId)
}
}
}
if len(groupIds) <= 0 {
return nil, 0, nil
} }
// roomMicUserMap不影响排序 // 获取群组中上麦用户
roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds) roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds)
if err != nil { if err != nil {
return nil, err return nil, 0, err
} }
uids := make([]uint64, 0) uids := make([]uint64, 0)
micUsersMap := make(map[string][]uint64, 0) micUsersMap := make(map[string][]uint64, 0)
for _, v := range groupInfo { for _, i := range groupInfo {
micUsersMap[v.ImGroupId] = make([]uint64, 0) micUsersMap[i.ImGroupId] = make([]uint64, 0)
if len(v.Password) <= 0 { if len(i.Password) <= 0 {
// 密码群不显示麦上头像 // 密码群不显示麦上头像
u := roomMicUserMap[v.ImGroupId] u := roomMicUserMap[i.ImGroupId]
if len(u) >= 4 { if len(u) >= 4 {
micUsersMap[v.ImGroupId] = u[0:4] micUsersMap[i.ImGroupId] = u[0:4]
} else if len(u) > 0 { } else if len(u) > 0 {
micUsersMap[v.ImGroupId] = u micUsersMap[i.ImGroupId] = u
} }
uids = append(uids, micUsersMap[v.ImGroupId]...) uids = append(uids, micUsersMap[i.ImGroupId]...)
} }
} }
uids = utils.UniqueSliceUInt64(uids) uids = utils.UniqueSliceUInt64(uids)
userTiny, err := user_cv.GetUserTinyMap(uids) userTiny, err := user_cv.GetUserTinyMap(uids)
if err != nil { if err != nil {
return nil, err return nil, 0, err
}
roomCount, err := group_m.BatchGetRoomCount(model, groupIds)
if err != nil {
return nil, 0, err
}
countryInfo, err := res_c.GetCountryIconMap(model)
if err != nil {
return nil, 0, err
}
supportLevels, err := group_s.NewGroupService(model.MyContext).GetWeekMaxSupportLevelMap()
if err != nil {
return nil, 0, err
}
visitCount, err := group_m.BatchGetRoomVisitCount(model.Log, groupIds)
if err != nil {
return nil, 0, err
}
// 排序优先级V8.0版本
sort.Slice(groupIds, func(i, j int) bool {
gi := groupIds[i]
gj := groupIds[j]
return roomEnterTime[gi] > roomEnterTime[gj] ||
roomEnterTime[gi] == roomEnterTime[gj] && visitCount[gj] > visitCount[gj] ||
roomEnterTime[gi] == roomEnterTime[gj] && visitCount[gj] == visitCount[gj] && i >= j
})
result := make([]JoinedGroupInfo, 0)
owners := make([]uint64, 0)
for _, i := range groupIds {
owners = append(owners, groupInfo[i].Owner)
}
powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners)
if err != nil {
return nil, 0, err
}
groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds)
if err != nil {
return nil, 0, err
}
resMedal, err := res_m.MedalGetAllMap(model.Db)
if err != nil {
return nil, 0, err
}
rr := rocket_m.RocketResult{}
maxStageMap, err := rr.GetMaxStage(model.Db, groupIds)
if err != nil {
return nil, 0, err
} }
// 正在进行的游戏
games := game_m.GetNotEndGamesMap(model)
for _, i := range groupIds {
g := groupInfo[i]
micUsers := make([]user_cv.CvUserTiny, 0)
for _, j := range micUsersMap[i] {
micUsers = append(micUsers, userTiny[j])
}
var maxStage *uint16 = nil
if s, ok := maxStageMap[i]; ok {
maxStage = &s
}
medals := make([]medal_cv.PicElement, 0)
// 补上房间流水勋章
var pe *medal_cv.PicElement
_, pe, err = medal_cv.GetGroupConsumeMedal(model, i)
if err != nil {
model.Log.Infof("BuildJoinedGroupInfo: GetGroupConsumeMedal: %s", err.Error())
} else if pe != nil {
medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl})
}
// res_medal
if m, ok := groupMedals[i]; ok {
for _, j := range m {
mId := uint32(j)
if e, ok := resMedal[mId]; ok {
medals = append(medals, medal_cv.PicElement{
PicUrl: e.PicUrl,
})
}
}
}
var password *string = nil
if len(g.Password) > 0 && g.Owner != myUserId {
emptyStr := ""
password = &emptyStr
}
result = append(result, JoinedGroupInfo{
PopularGroupInfo: PopularGroupInfo{
GroupInfo: GroupInfo{
GroupBasicInfo: GroupBasicInfo{
GroupId: g.TxGroupId,
Name: g.Name,
Notification: g.Notification,
Introduction: g.Introduction,
FaceUrl: g.FaceUrl,
Code: g.Code,
CountryIcon: countryInfo[g.Country],
Password: password,
SupportLevel: supportLevels[i],
GroupInUserDuration: visitCount[i],
MicNumType: int(g.MicNumType),
GroupMedals: medals,
},
HasOnMic: len(micUsers) > 0,
GroupPowerId: powerIds[g.Owner],
GroupPowerName: powerNames[g.Owner],
GroupPowerNameplate: powerNameplates[g.Owner],
GroupPower: GroupPower{
Id: powerIds[g.Owner],
Name: powerNames[g.Owner],
Nameplate: powerNameplates[g.Owner],
Grade: powerGrades[g.Owner],
},
},
MicUsers: micUsers,
RoomUserCount: uint(roomCount[i]),
MaxStage: maxStage,
GameTypes: games[g.TxGroupId],
},
LastEnterTime: roomEnterTime[i],
})
}
return result, len(groupInfo), nil
}
func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*group_m.GroupInfo) ([]*PopularGroupInfo, error) {
groupIds := make([]string, 0, len(groupInfo))
for _, v := range groupInfo {
groupIds = append(groupIds, v.ImGroupId)
}
// roomMicUserMap不影响排序
//roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds)
//if err != nil {
// return nil, err
//}
//uids := make([]uint64, 0)
//micUsersMap := make(map[string][]uint64, 0)
//for _, v := range groupInfo {
// micUsersMap[v.ImGroupId] = make([]uint64, 0)
//
// if len(v.Password) <= 0 {
// // 密码群不显示麦上头像
// u := roomMicUserMap[v.ImGroupId]
// if len(u) >= 4 {
// micUsersMap[v.ImGroupId] = u[0:4]
// } else if len(u) > 0 {
// micUsersMap[v.ImGroupId] = u
// }
// uids = append(uids, micUsersMap[v.ImGroupId]...)
// }
//}
//uids = utils.UniqueSliceUInt64(uids)
//userTiny, err := user_cv.GetUserTinyMap(uids)
//if err != nil {
// return nil, err
//}
roomCount, err := group_m.BatchGetRoomCount(model, groupIds) roomCount, err := group_m.BatchGetRoomCount(model, groupIds)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -528,10 +726,10 @@ func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*gr ...@@ -528,10 +726,10 @@ func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*gr
for _, v := range groupInfo { for _, v := range groupInfo {
g := v g := v
i := v.ImGroupId i := v.ImGroupId
micUsers := make([]user_cv.CvUserTiny, 0) //micUsers := make([]user_cv.CvUserTiny, 0)
for _, j := range micUsersMap[i] { //for _, j := range micUsersMap[i] {
micUsers = append(micUsers, userTiny[j]) // micUsers = append(micUsers, userTiny[j])
} //}
var maxStage *uint16 = nil var maxStage *uint16 = nil
if s, ok := maxStageMap[i]; ok { if s, ok := maxStageMap[i]; ok {
...@@ -580,7 +778,7 @@ func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*gr ...@@ -580,7 +778,7 @@ func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*gr
MicNumType: int(g.MicNumType), MicNumType: int(g.MicNumType),
GroupMedals: medals, GroupMedals: medals,
}, },
HasOnMic: len(micUsers) > 0, //HasOnMic: len(micUsers) > 0,
GroupPowerId: powerIds[g.Owner], GroupPowerId: powerIds[g.Owner],
GroupPowerName: powerNames[g.Owner], GroupPowerName: powerNames[g.Owner],
GroupPowerNameplate: powerNameplates[g.Owner], GroupPowerNameplate: powerNameplates[g.Owner],
...@@ -591,7 +789,7 @@ func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*gr ...@@ -591,7 +789,7 @@ func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*gr
Grade: powerGrades[g.Owner], Grade: powerGrades[g.Owner],
}, },
}, },
MicUsers: micUsers, //MicUsers: micUsers,
RoomUserCount: uint(roomCount[i]), RoomUserCount: uint(roomCount[i]),
MaxStage: maxStage, MaxStage: maxStage,
GameTypes: games[g.TxGroupId], GameTypes: games[g.TxGroupId],
......
package user_cv package user_cv
import ( import (
"encoding/json"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
...@@ -69,6 +70,25 @@ type CvUserDetail struct { ...@@ -69,6 +70,25 @@ type CvUserDetail struct {
CountryManager *country_cv.CVCountryManager `json:"countryManager,omitempty"` // 国家管理员 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 { type GroupPower struct {
Id uint64 `json:"id"` // 群主所在的势力ID Id uint64 `json:"id"` // 群主所在的势力ID
Icon string `json:"icon"` // 家族头像 Icon string `json:"icon"` // 家族头像
...@@ -150,6 +170,45 @@ type CvUserExtend struct { ...@@ -150,6 +170,45 @@ type CvUserExtend struct {
ActiveGrade uint32 `json:"activityUserGrade"` 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信息 // 批量获取用户tiny信息
func GetUserTinyMap(userIds []mysql.ID) (map[mysql.ID]CvUserTiny, error) { func GetUserTinyMap(userIds []mysql.ID) (map[mysql.ID]CvUserTiny, error) {
userTinys, _, err := GetUserTinys(userIds) userTinys, _, err := GetUserTinys(userIds)
...@@ -849,16 +908,122 @@ func GetUserDetail(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*Cv ...@@ -849,16 +908,122 @@ func GetUserDetail(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*Cv
noble, superManagerMap[userId], myGroups, phoneInfo, thirdList, cvCountryManager) 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, 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, 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, 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) { myGroups []group_m.GroupInfo, phoneInfo *user_m.UserPhoneInfo, thirdList []int8, countryManager *country_cv.CVCountryManager) (*CvUserDetail, error) {
room, err := group_m.ToTxGroupId(model, room) if len(room) > 0 {
if err != nil { var err error
model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err) room, err = group_m.ToTxGroupId(model, room)
room = "" if err != nil {
model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err)
room = ""
}
} }
cvUserDetail := &CvUserDetail{ cvUserDetail := &CvUserDetail{
...@@ -1288,3 +1453,38 @@ func getMedalInfo(db *gorm.DB, medals []uint32) ([]uint32, []medal_cv.CvMedal, e ...@@ -1288,3 +1453,38 @@ func getMedalInfo(db *gorm.DB, medals []uint32) ([]uint32, []medal_cv.CvMedal, e
} }
return validMedals, medalInfo, nil 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 ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=47.244.34.27:6379 REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT] [JWT]
SECRET=hilo1632 SECRET=hilo1632
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
...@@ -9,15 +9,18 @@ import ( ...@@ -9,15 +9,18 @@ import (
) )
type gameAutoJoinMsg struct { type gameAutoJoinMsg struct {
TraceId string TraceId string
Token string Token string
EnterType string EnterType string
GameCode 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) 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) data, err := json.Marshal(info)
if err != nil { if err != nil {
return err return err
...@@ -26,7 +29,7 @@ func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, g ...@@ -26,7 +29,7 @@ func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, g
if err != nil { if err != nil {
return err return err
} }
redisCli.GetRedis().Expire(context.Background(), key, time.Second*3) redisCli.GetRedis().Expire(context.Background(), key, time.Second*10)
return nil 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)
}
}
...@@ -83,17 +83,17 @@ func SetGroupMemberTTL(groupId string, ttl time.Duration) (bool, error) { ...@@ -83,17 +83,17 @@ func SetGroupMemberTTL(groupId string, ttl time.Duration) (bool, error) {
func GetGroupConsume(groupId string) (uint64, error) { func GetGroupConsume(groupId string) (uint64, error) {
key := getGroupConsumeKey(groupId) 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 { func SetGroupConsume(groupId string, consume uint64, ttl time.Duration) error {
key := getGroupConsumeKey(groupId) 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 { func ClearGroupConsume(groupId string) error {
key := getGroupConsumeKey(groupId) key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Del(context.Background(), key).Err() return redisCli.RedisClusterClient.Del(context.Background(), key).Err()
} }
// 增加编辑用户cd // 增加编辑用户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) { ...@@ -27,17 +27,17 @@ func SetJSON(model *domain.Model, key string, obj interface{}) (err error) {
if err != nil { if err != nil {
return err return err
} }
return model.Redis.Set(model.Context, key, value, DEFAULT_TTL).Err() return model.RedisCluster.Set(model.Context, key, value, DEFAULT_TTL).Err()
} }
// 获取redis中json结构体 // 获取redis中json结构体
// return err: may redisV8.Nil // return err: may redisV8.Nil
func GetJSON(model *domain.Model, key string, obj interface{}) (err error) { func GetJSON(model *domain.Model, key string, obj interface{}) (err error) {
var value []byte var value []byte
defer func() { //defer func() {
model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err) // model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err)
}() //}()
value, err = model.Redis.Get(model.Context, key).Bytes() value, err = model.RedisCluster.Get(model.Context, key).Bytes()
if err != nil { if err != nil {
// may redisV2.Nil // may redisV2.Nil
return return
...@@ -59,7 +59,7 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time ...@@ -59,7 +59,7 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
if time.Now().After(deadline) { if time.Now().After(deadline) {
return false return false
} }
flag, err := model.Redis.SetNX(model, key, "1", expireTimeout).Result() flag, err := model.RedisCluster.SetNX(model, key, "1", expireTimeout).Result()
if err != nil || !flag { if err != nil || !flag {
time.Sleep(time.Millisecond * 10) time.Sleep(time.Millisecond * 10)
} else { } else {
...@@ -70,5 +70,5 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time ...@@ -70,5 +70,5 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
// 解锁 // 解锁
func UnLock(model *domain.Model, key string) { func UnLock(model *domain.Model, key string) {
model.Redis.Del(model, key) model.RedisCluster.Del(model, key)
} }
package res_c package res_c
import ( import (
"context"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"hilo-group/_const/redis_key" "github.com/bluele/gcache"
"hilo-group/domain/model/res_m" "hilo-group/domain/model/res_m"
"time" "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) { func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
m, err := GetAllCountryIcon(model) m, err := GetAllCountryIcon(model)
if err != nil || len(m) <= 0 { if err != nil || len(m) <= 0 {
...@@ -24,17 +30,22 @@ func GetCountryIconMap(model *domain.Model) (map[string]string, error) { ...@@ -24,17 +30,22 @@ func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
} }
func GetAllCountryIcon(model *domain.Model) (map[string]string, error) { func GetAllCountryIcon(model *domain.Model) (map[string]string, error) {
key := redis_key.GetCountryIconKey() //key := redis_key.GetCountryIconKey()
return model.Redis.HGetAll(context.Background(), key).Result() 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) (int64, error) { func SaveAllCountryIcon(model *domain.Model, icons map[string]string) {
key := redis_key.GetCountryIconKey() //key := redis_key.GetCountryIconKey()
ret, err := model.Redis.HSet(context.Background(), key, icons).Result() //ret, err := model.Redis.HSet(context.Background(), key, icons).Result()
if err == nil { //if err == nil {
model.Redis.Expire(context.Background(), key, time.Minute*10) // model.Redis.Expire(context.Background(), key, time.Minute*10)
} //}
return ret, err //return ret, err
_ = countryIconLru.SetWithExpire(countryIconKey, icons, time.Minute*10)
} }
func GetCountryAreaMap(model *domain.Model) (map[string]string, error) { func GetCountryAreaMap(model *domain.Model) (map[string]string, error) {
...@@ -53,15 +64,20 @@ func GetCountryAreaMap(model *domain.Model) (map[string]string, error) { ...@@ -53,15 +64,20 @@ func GetCountryAreaMap(model *domain.Model) (map[string]string, error) {
} }
func GetAllCountryArea(model *domain.Model) (map[string]string, error) { func GetAllCountryArea(model *domain.Model) (map[string]string, error) {
key := redis_key.GetCountryAreaKey() //key := redis_key.GetCountryAreaKey()
return model.Redis.HGetAll(context.Background(), key).Result() //return model.Redis.HGetAll(context.Background(), key).Result()
if data, err := countryAreaLru.Get(countryAreaKey); err == nil {
return data.(map[string]string), nil
}
return map[string]string{}, nil
} }
func SaveAllCountryArea(model *domain.Model, data map[string]string) (int64, error) { func SaveAllCountryArea(model *domain.Model, data map[string]string) {
key := redis_key.GetCountryAreaKey() //key := redis_key.GetCountryAreaKey()
ret, err := model.Redis.HSet(context.Background(), key, data).Result() //ret, err := model.Redis.HSet(context.Background(), key, data).Result()
if err == nil { //if err == nil {
model.Redis.Expire(context.Background(), key, time.Minute*10) // model.Redis.Expire(context.Background(), key, time.Minute*10)
} //}
return ret, err //return ret, err
_ = countryAreaLru.SetWithExpire(countryAreaKey, data, time.Minute*10)
} }
...@@ -2,42 +2,44 @@ package room_c ...@@ -2,42 +2,44 @@ package room_c
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli" "git.hilo.cn/hilo-common/resource/redisCli"
"github.com/bluele/gcache"
redis2 "github.com/go-redis/redis/v8" redis2 "github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"strconv" "hilo-group/_const/redis_key/group_k"
"time" "time"
) )
// 处理访问房间的相关缓存 // 处理访问房间的相关缓存
func ProcessRoomVisit(groupId string, userId uint64) error { func ProcessRoomVisit(groupId string, userId uint64) error {
key := redis_key.GetPrefixGroupInUserDuration(groupId) //key := redis_key.GetPrefixGroupInUserDuration(groupId)
now := time.Now() //now := time.Now()
ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{ //ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
Score: float64(now.Unix()), // Score: float64(now.Unix()),
Member: userId, // Member: userId,
}).Result() //}).Result()
if err != nil { //if err != nil {
return err // return err
} //}
mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret) //mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret)
//
// 每群定时清一次数据可以了 //// 每群定时清一次数据可以了
if now.Second()%redis_key.GroupInDurationClearPeriod == 0 { //if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL)) // rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL))
if err == nil { // if err == nil {
mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc) // mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc)
} else { // } else {
mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error()) // mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error())
} // }
} //}
// 马上更新roomVisitCount // 马上更新roomVisitCount
if _, err := GetSetRoomVisitCount(groupId); err != nil { 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 return nil
...@@ -59,15 +61,17 @@ func ProcessUserRoomVisit(userId uint64, groupId string) error { ...@@ -59,15 +61,17 @@ func ProcessUserRoomVisit(userId uint64, groupId string) error {
} }
// 查询用户访问过的房间及其时间 // 查询用户访问过的房间及其时间
// todo 去掉查询,redis性能
func GetUserRoomVisit(userId uint64) (map[string]int64, error) { func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
result := make(map[string]int64, 0)
return result, nil
key := redis_key.GetUserEnterRoomKey(userId) key := redis_key.GetUserEnterRoomKey(userId)
ret, err := redisCli.GetRedis().ZRangeWithScores(context.Background(), key, 0, -1).Result() ret, err := redisCli.GetRedis().ZRangeWithScores(context.Background(), key, 0, -1).Result()
if err != nil { if err != nil {
return nil, err 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 { for _, i := range ret {
result[i.Member.(string)] = int64(i.Score) result[i.Member.(string)] = int64(i.Score)
} }
...@@ -75,53 +79,63 @@ func GetUserRoomVisit(userId uint64) (map[string]int64, error) { ...@@ -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) { func MGetRoomVisitCount(groupIds []string) (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
visit := make(map[string]string) visit := make(map[string]string)
if len(groupIds) <= 0 { if len(groupIds) <= 0 {
return visit, nil 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 { if err != nil {
mylogrus.MyLog.Errorf("MGetRoomVisitCount zset fail:%v", err)
return visit, err return visit, err
} }
if len(res) != len(groupIds) { for _, v := range zRes {
return visit, errors.New(fmt.Sprintf("MGetRoomVisitCount fail,miss match len,%v-%v", len(res), len(groupIds))) visit[cast.ToString(v.Member)] = cast.ToString(v.Score)
}
for i, groupId := range groupIds {
if cnt, ok := res[i].(string); ok {
visit[groupId] = cnt
}
} }
_ = roomVisitCountLru.SetWithExpire(lKey, visit, time.Minute*15)
return visit, nil return visit, nil
} }
func GetSetRoomVisitCount(groupId string) (int64, error) { 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() vc, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
// 查到合法值后,更新二级缓存 // 查到合法值后,更新二级缓存
if err == nil && vc >= 0 { if err == nil && vc >= 0 {
ret, err := saveRoomVisitCount(groupId, vc) if err := saveRoomVisitCount(groupId, vc); err != nil {
mylogrus.MyLog.Infof("saveRoomVisitCount %s, ret = %d, err: %v", groupId, ret, err) mylogrus.MyLog.Errorf("saveRoomVisitCount %s, err: %v", groupId, err)
}
} }
return vc, err return vc, err
} }
func saveRoomVisitCount(groupId string, count int64) (int64, error) { func saveRoomVisitCount(groupId string, count int64) error {
key := redis_key.GetPrefixRoomVisitCount() //key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result() zKey := redis_key.GetPrefixRoomVisitCountZset()
} // zset同步存一份到redis集群
if err := redisCli.GetClusterRedis().ZAdd(context.Background(), zKey, &redis2.Z{
func clearRoomVisit(groupId string, t time.Time) (int64, error) { Score: float64(count),
value := strconv.FormatInt(t.Unix(), 10) Member: groupId,
ret, err := redisCli.GetRedis().ZRemRangeByScore(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId), "0", value).Result() }).Err(); err != nil {
if err != nil { mylogrus.MyLog.Errorf("GetPrefixRoomVisitCountZset fail %s", err.Error())
return 0, err return err
} }
return ret, nil return nil
} //return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result()
func GetAllRoomVisitCount() (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HGetAll(context.Background(), key).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 ...@@ -38,6 +38,36 @@ func GetUserTinyById(model *domain.Model, userId mysql.ID) (*user_m.UserTiny, er
return userTiny, nil 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 // 获取用户简要信息By ExternalId
func GetUserByExternalId(model *domain.Model, externalId mysql.Str) (*user_m.UserTiny, error) { func GetUserByExternalId(model *domain.Model, externalId mysql.Str) (*user_m.UserTiny, error) {
userId, err := ToUserId(model, externalId) userId, err := ToUserId(model, externalId)
...@@ -52,7 +82,7 @@ func ToUserId(model *domain.Model, externalId mysql.Str) (mysql.ID, error) { ...@@ -52,7 +82,7 @@ func ToUserId(model *domain.Model, externalId mysql.Str) (mysql.ID, error) {
if externalId == "" { if externalId == "" {
return 0, myerr.NewSysError("externalId 不能为空") return 0, myerr.NewSysError("externalId 不能为空")
} }
userId, err := model.Redis.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64() userId, err := model.RedisCluster.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64()
if err != nil && err != redisV8.Nil { if err != nil && err != redisV8.Nil {
return 0, err return 0, err
} }
...@@ -75,7 +105,7 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) { ...@@ -75,7 +105,7 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) {
if code == "" { if code == "" {
return 0, myerr.NewSysError("code 不能为空") return 0, myerr.NewSysError("code 不能为空")
} }
userId, err := model.Redis.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64() userId, err := model.RedisCluster.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64()
if err != nil && err != redisV8.Nil { if err != nil && err != redisV8.Nil {
return 0, err return 0, err
} }
...@@ -104,11 +134,11 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error { ...@@ -104,11 +134,11 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error {
// return err // return err
//} //}
// cache externalId->userId // cache externalId->userId
if err := model.Redis.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil { if err := model.RedisCluster.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err return err
} }
// cache code->userId // cache code->userId
if err := model.Redis.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil { if err := model.RedisCluster.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err return err
} }
if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil { if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil {
......
package 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 { ...@@ -14,6 +14,8 @@ type OnMicEvent struct {
UserId uint64 // 麦中的人 UserId uint64 // 麦中的人
Forbid bool // 静音 true:静音,false:没有静音 Forbid bool // 静音 true:静音,false:没有静音
Timestamp int64 // 上麦的的时间戳 Timestamp int64 // 上麦的的时间戳
Ts int64
} }
func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) { func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) {
......
package common package common
import ( import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/utils" "git.hilo.cn/hilo-common/utils"
"hilo-group/_const/redis_key" "github.com/bluele/gcache"
"hilo-group/myerr"
"time" "time"
) )
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) { // 改成lru
bData, err := GetCache(redis_key.GetUserMedalMerge(userId)) var userMedalMergeLru = gcache.New(10000).LRU().Build()
if err != nil {
return nil, myerr.WrapErr(err)
}
res := make([]uint32, 0) func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
err = json.Unmarshal(bData, &res) if data, err := userMedalMergeLru.Get(userId); err == nil {
if err != nil { return data.([]uint32), nil
return nil, myerr.WrapErr(err)
} }
return res, nil return nil, nil
} }
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) error { func SetUserMedalMergeCache(userId mysql.ID, data []uint32) {
err := SetCache(redis_key.GetUserMedalMerge(userId), data, time.Hour*2) _ = userMedalMergeLru.SetWithExpire(userId, data, time.Minute*15)
if err != nil {
mylogrus.MyLog.Errorf("SetUserMedalMerge err:%s", err)
return myerr.WrapErr(err)
}
return nil
} }
// 删除勋章缓存, 延迟删除 // 删除勋章缓存, 延迟删除
...@@ -44,41 +30,6 @@ func DelUserMedalMergeCacheDelay(userId mysql.ID) { ...@@ -44,41 +30,6 @@ func DelUserMedalMergeCacheDelay(userId mysql.ID) {
}() }()
} }
func DelUserMedalMergeCache(userId mysql.ID) error { func DelUserMedalMergeCache(userId mysql.ID) {
err := DelCache(redis_key.GetUserMedalMerge(userId)) userMedalMergeLru.Remove(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
} }
package diamond_m package diamond_m
import ( import (
"fmt"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils" "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/diamond_e" "hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model"
"hilo-group/myerr" "hilo-group/myerr"
"hilo-group/myerr/bizerr" "hilo-group/myerr/bizerr"
"strconv" "strconv"
...@@ -40,6 +40,11 @@ type DiamondAccountDetail struct { ...@@ -40,6 +40,11 @@ type DiamondAccountDetail struct {
diamondAccount *DiamondAccount `gorm:"-"` diamondAccount *DiamondAccount `gorm:"-"`
} }
func (DiamondAccountDetail) TableName() string {
month := time.Now().Format("200601")
return fmt.Sprintf("diamond_account_detail_%s", month)
}
// 粉钻详情 // 粉钻详情
type DiamondPinkAccountDetail struct { type DiamondPinkAccountDetail struct {
mysql.Entity mysql.Entity
...@@ -110,7 +115,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon ...@@ -110,7 +115,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
var count int64 var count int64
if diamondOperateSet.FrequencyDay == -1 { if diamondOperateSet.FrequencyDay == -1 {
if diamondOperateSet.FrequencyNum != -1 { if diamondOperateSet.FrequencyNum != -1 {
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{ diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId, UserId: diamondAccount.UserId,
OperateType: operateType, OperateType: operateType,
}).Count(&count) }).Count(&count)
...@@ -125,7 +130,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon ...@@ -125,7 +130,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
//一天的次数 //一天的次数
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{ diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId, UserId: diamondAccount.UserId,
OperateType: operateType, OperateType: operateType,
}).Where("created_time >= ? ", beginTime).Count(&count) }).Where("created_time >= ? ", beginTime).Count(&count)
...@@ -133,7 +138,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon ...@@ -133,7 +138,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, bizerr.DiamondFrequency return nil, bizerr.DiamondFrequency
} }
//终极拦截,利用 //终极拦截,利用
diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from diamond_account_detail d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )") diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from " + DiamondAccountDetail{}.TableName() + " d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )")
} }
//-1,代表值无效,由参数给与 //-1,代表值无效,由参数给与
...@@ -197,7 +202,10 @@ func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional() ...@@ -197,7 +202,10 @@ func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional()
} }
//持久化diamondAccountDetail //持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil { //if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err) return myerr.WrapErr(err)
} }
//改变diamondAccount值 //改变diamondAccount值
...@@ -245,7 +253,10 @@ func (diamondAccountDetail *DiamondAccountDetail) Persistent() error { ...@@ -245,7 +253,10 @@ func (diamondAccountDetail *DiamondAccountDetail) Persistent() error {
} }
//持久化diamondAccountDetail //持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil { //if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err) return myerr.WrapErr(err)
} }
//改变diamondAccount值 //改变diamondAccount值
......
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 { ...@@ -9,3 +9,7 @@ func (p *EventGiftSendOffsetHiloGroup) Persistence() error {
func (p *EventGiftSend) Persistence() error { func (p *EventGiftSend) Persistence() error {
return model.Persistent(p.Db, p) return model.Persistent(p.Db, p)
} }
func (p *EventGroupInOffsetHiloGroup) Persistence() error {
return model.Persistent(p.Db, p)
}
\ No newline at end of file
...@@ -29,8 +29,9 @@ type GameInfo struct { ...@@ -29,8 +29,9 @@ type GameInfo struct {
} }
type GameConfig struct { type GameConfig struct {
Ludo *GameConfigDiamond `json:"ludo"` Ludo *GameConfigDiamond `json:"ludo"`
Uno *GameConfigDiamond `json:"uno"` Uno *GameConfigDiamond `json:"uno"`
Domino *GameConfigDiamond `json:"domino"`
} }
type GameConfigDiamond struct { type GameConfigDiamond struct {
......
...@@ -127,6 +127,40 @@ func (g *GiftOperate) GetConsumeByRange(beginTime, endTime time.Time) (uint32, u ...@@ -127,6 +127,40 @@ func (g *GiftOperate) GetConsumeByRange(beginTime, endTime time.Time) (uint32, u
if len(rows) <= 0 { if len(rows) <= 0 {
return 0, 0, nil 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 return rows[0].C, rows[0].Consume, nil
} }
...@@ -148,6 +182,17 @@ func (g *GiftOperate) BatchGetConsumeByRange(beginTime, endTime time.Time) ([]Sc ...@@ -148,6 +182,17 @@ func (g *GiftOperate) BatchGetConsumeByRange(beginTime, endTime time.Time) ([]Sc
return rows, nil 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) { func SumSendGift(model *domain.Model, sendUserId mysql.ID, giftId mysql.ID) (uint32, error) {
type Result struct { type Result struct {
N uint32 N uint32
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
"hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/group_power_ev" "hilo-group/domain/event/group_power_ev"
"time" "time"
) )
...@@ -40,25 +41,6 @@ type GroupPowerExpDetail struct { ...@@ -40,25 +41,6 @@ type GroupPowerExpDetail struct {
Remark string 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 ...@@ -82,17 +64,34 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return err return err
} }
// 增加家族经验-总 // 增加家族经验-总
gpg := &GroupPowerGrade{ gpg := new(GroupPowerGrade)
GroupPowerId: groupPowerId, // insert
Exp: exp, if err := txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(gpg).Error; err != nil {
Grade: 0, if err != gorm.ErrRecordNotFound {
ExpireAt: time.Time{}, return err
} }
if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}}, // gorm.ErrRecordNotFound
DoUpdates: clause.Assignments(map[string]interface{}{ gpg = &GroupPowerGrade{
"exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil { GroupPowerId: groupPowerId,
return err 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) latestGrade := new(GroupPowerGrade)
if err = txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(latestGrade).Error; err != nil { 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 ...@@ -135,154 +134,24 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return nil 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 { func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID) error {
return model.Transaction(func(model *domain.Model) error { key := mic_k.GetMicGroupPowerOnMic(userId)
// 获取用户上麦奖励历史 minutes, err := model.Redis.IncrBy(model, key, 1).Result()
onMicDetails, err := GetGroupPowerUserOnMicDetails(model, groupPowerId, userId) if err != nil {
if err != nil { model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err)
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)
return err return err
}) }
} model.Redis.Expire(model, key, time.Hour*24) // ttl 一天
// 每日最多1800经验 = 18个10分钟 = 180分钟
// 增加势力上麦时长-家族之星 if minutes > 180 {
// 事务操作 return nil
func IncrGroupPowerStarOnMicDay(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error { }
return model.Transaction(func(model *domain.Model) error { if minutes%10 == 0 {
// 日统计 return IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟")
star, err := GetGroupPowerDayStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive) }
curTs := joinMicTimestamp return nil
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
})
} }
// 清理所有家族的经验 // 清理所有家族的经验
......
...@@ -15,9 +15,11 @@ type GroupPowerExpRank struct { ...@@ -15,9 +15,11 @@ type GroupPowerExpRank struct {
// 获取家族经验排行榜 // 获取家族经验排行榜
// param limit: 排行榜人数 // param limit: 排行榜人数
// 10166 线上员工,对应的势力不上榜,groupPowerId=8951
func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int, gpStatus groupPower_e.GroupPowerStatus, area int) ([]GroupPowerExpRank, error) { func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int, gpStatus groupPower_e.GroupPowerStatus, area int) ([]GroupPowerExpRank, error) {
var res []GroupPowerExpRank var res []GroupPowerExpRank
db := model.DB().Table("group_power_day_exp gpd").Select("gpd.group_power_id,SUM(gpd.exp) as exp"). 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) Where("gpd.date BETWEEN ? AND ?", beginDate, endDate)
if gpStatus > 0 { if gpStatus > 0 {
db = db.Joins("left join group_power gp on gpd.group_power_id = gp.id").Where("gp.status = ?", gpStatus) db = db.Joins("left join group_power gp on gpd.group_power_id = gp.id").Where("gp.status = ?", gpStatus)
......
...@@ -35,6 +35,7 @@ type GroupPowerDayStar struct { ...@@ -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 { func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
month := time.Now().Format("200601") month := time.Now().Format("200601")
star := &GroupPowerMonthStar{ star := &GroupPowerMonthStar{
...@@ -59,6 +60,7 @@ func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysq ...@@ -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 { func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
star := &GroupPowerDayStar{ star := &GroupPowerDayStar{
Date: time.Now(), Date: time.Now(),
...@@ -81,29 +83,8 @@ func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql. ...@@ -81,29 +83,8 @@ func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.
return nil 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
}
// 获取家族之星排行 // 获取家族之星排行
// Deprecated: 用redis
func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*GroupPowerMonthStar, error) { func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*GroupPowerMonthStar, error) {
var res []*GroupPowerMonthStar var res []*GroupPowerMonthStar
//month := time.Now().Format("200601") //month := time.Now().Format("200601")
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/myerr" "hilo-group/myerr"
"strconv" "strconv"
"strings" "strings"
...@@ -242,6 +243,20 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my ...@@ -242,6 +243,20 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if len(groupIds) <= 0 { if len(groupIds) <= 0 {
return result, nil 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) keys := make([]string, 0)
for _, g := range groupIds { for _, g := range groupIds {
...@@ -253,7 +268,7 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my ...@@ -253,7 +268,7 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if err != nil { if err != nil {
return nil, err 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) { if len(mics) >= len(groupIds) {
for i, g := range groupIds { for i, g := range groupIds {
...@@ -432,7 +447,7 @@ func GetMicUserByExternalId(model *domain.Model, externalId string) (*MicUser, e ...@@ -432,7 +447,7 @@ func GetMicUserByExternalId(model *domain.Model, externalId string) (*MicUser, e
//麦位上没人,返回nil //麦位上没人,返回nil
func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error) { 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) return nil, myerr.NewSysErrorF("麦序不对,不在范围值内 i:%v", i)
} }
str, err := redisCli.GetRedis().Get(context.Background(), redis_key.GetPrefixGroupMicUser(groupUuid, i)).Result() str, err := redisCli.GetRedis().Get(context.Background(), redis_key.GetPrefixGroupMicUser(groupUuid, i)).Result()
......
...@@ -3,6 +3,8 @@ package group_m ...@@ -3,6 +3,8 @@ package group_m
import ( import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"time"
) )
type GroupBanned struct { type GroupBanned struct {
...@@ -24,12 +26,19 @@ func (banned *GroupBanned) Delete(model *domain.Model) error { ...@@ -24,12 +26,19 @@ func (banned *GroupBanned) Delete(model *domain.Model) error {
return model.Db.Where(banned).Delete(&GroupBanned{}).Error return model.Db.Where(banned).Delete(&GroupBanned{}).Error
} }
var bannedGroupCache = gcache.New(100).LRU().Build()
func GetBannedGroups(model *domain.Model) ([]GroupBanned, error) { 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) result := make([]GroupBanned, 0)
err := model.Db.Find(&result).Error err := model.DB().Find(&result).Error
if err != nil { if err != nil {
return nil, err return nil, err
} }
bannedGroupCache.SetWithExpire(key, result, time.Minute*5)
return result, nil 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
}
...@@ -47,6 +47,7 @@ type GroupInfo struct { ...@@ -47,6 +47,7 @@ type GroupInfo struct {
CreatedTime time.Time `gorm:"->"` CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"` UpdatedTime time.Time `gorm:"->"`
VisitCount int64 `gorm:"-"` // 热度 VisitCount int64 `gorm:"-"` // 热度
IsGameRoom uint8 // 是否1v1游戏房
} }
func GenerateGroupCode(n uint16) string { func GenerateGroupCode(n uint16) string {
......
...@@ -23,9 +23,13 @@ func (g *GroupTop) Delete(model *domain.Model) error { ...@@ -23,9 +23,13 @@ func (g *GroupTop) Delete(model *domain.Model) error {
return model.Db.Where(g).Delete(&GroupTop{}).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) 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 { if err != nil {
return nil, err return nil, err
} }
......
...@@ -3,6 +3,7 @@ package group_m ...@@ -3,6 +3,7 @@ package group_m
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config" "git.hilo.cn/hilo-common/resource/config"
...@@ -14,6 +15,7 @@ import ( ...@@ -14,6 +15,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/common" "hilo-group/common"
"hilo-group/domain/model/noble_m" "hilo-group/domain/model/noble_m"
"hilo-group/domain/model/res_m" "hilo-group/domain/model/res_m"
...@@ -98,8 +100,8 @@ func GetMicNumType(model *domain.Model, groupUuid string) (group_e.GroupMicNumTy ...@@ -98,8 +100,8 @@ func GetMicNumType(model *domain.Model, groupUuid string) (group_e.GroupMicNumTy
} }
} }
//6个小时 // 3天
const expireMinute = 60 * 60 * 12 const expireMinute = 60 * 60 * 24 * 3
const micExpire = expireMinute * time.Second const micExpire = expireMinute * time.Second
//麦位基本信息。 //麦位基本信息。
...@@ -255,6 +257,10 @@ func (mic *Mic) In(userId uint64, externalId string) error { ...@@ -255,6 +257,10 @@ func (mic *Mic) In(userId uint64, externalId string) error {
return bizerr.GroupMicUserHasIn return bizerr.GroupMicUserHasIn
} }
// 增加群组中上麦用户
groupMicUserKey := mic_k.GetGroupOnMicUser(mic.GroupUuid)
mic.model.Redis.HSet(mic.model, groupMicUserKey, mic.I, userId)
//离开动作已结束,增加到队列中 //离开动作已结束,增加到队列中
MicChangeRPush(mic.model, mic.GroupUuid, mic.I) MicChangeRPush(mic.model, mic.GroupUuid, mic.I)
...@@ -269,7 +275,7 @@ func (mic *Mic) In(userId uint64, externalId string) error { ...@@ -269,7 +275,7 @@ func (mic *Mic) In(userId uint64, externalId string) error {
//上麦(自己), //上麦(自己),
//规则:1:加锁了不能上麦 2:麦上有人,不能上麦 //规则:1:加锁了不能上麦 2:麦上有人,不能上麦
//cpUserId如果有 //cpUserId如果有
func (mic *Mic) Update(userId uint64, externalId string, cpUserId uint64) (err error) { func (mic *Mic) Update(userId uint64, externalId string, cpUserId uint64, forbid bool) (err error) {
defer func() { defer func() {
if err != nil { if err != nil {
mic.model.Log.Errorf("MicUpdate fail,userId:%v,cpUserId:%v,err:%v", userId, cpUserId, err) mic.model.Log.Errorf("MicUpdate fail,userId:%v,cpUserId:%v,err:%v", userId, cpUserId, err)
...@@ -300,7 +306,7 @@ func (mic *Mic) Update(userId uint64, externalId string, cpUserId uint64) (err e ...@@ -300,7 +306,7 @@ func (mic *Mic) Update(userId uint64, externalId string, cpUserId uint64) (err e
ExternalId: externalId, ExternalId: externalId,
UserId: userId, UserId: userId,
CpUserId: cpUserId, CpUserId: cpUserId,
Forbid: false, Forbid: forbid,
Timestamp: time.Now().Unix(), Timestamp: time.Now().Unix(),
}) })
if err != nil { if err != nil {
...@@ -385,6 +391,10 @@ func (micUser *MicUser) leave(operateUserId uint64, operateExternalId string) er ...@@ -385,6 +391,10 @@ func (micUser *MicUser) leave(operateUserId uint64, operateExternalId string) er
//return bizerr.GroupMicErr //return bizerr.GroupMicErr
} }
// 减少群组中上麦用户
groupMicUserKey := mic_k.GetGroupOnMicUser(micUser.GroupUuid)
micUser.model.Redis.HDel(micUser.model, groupMicUserKey, fmt.Sprintf("%d", micUser.I))
//离开动作已结束,增加到队列中 //离开动作已结束,增加到队列中
MicChangeRPush(micUser.model, micUser.GroupUuid, micUser.I) MicChangeRPush(micUser.model, micUser.GroupUuid, micUser.I)
...@@ -824,12 +834,14 @@ func groupMicHasIn(model *domain.Model, groupId string, userId mysql.ID) { ...@@ -824,12 +834,14 @@ func groupMicHasIn(model *domain.Model, groupId string, userId mysql.ID) {
} else { } else {
println(n) println(n)
} }
if _, err := redisCli.GetRedis().ZAdd(context.Background(), redis_key.GetPrefixGroupMicHasInUserTime(), &redis2.Z{ // 下面的是只写,不查的。 todo 直接干掉???
Score: float64(time.Now().Unix()), // 只是知道用户在哪个时间点上了哪个群的麦,但是不知道上了哪个麦位置, 而且micUser已经有统计这些信息了
Member: getMemberStr(groupId, userId), //if _, err := redisCli.GetRedis().ZAdd(context.Background(), redis_key.GetPrefixGroupMicHasInUserTime(), &redis2.Z{
}).Result(); err != nil { // Score: float64(time.Now().Unix()),
model.Log.Errorf("groupMicHasIn redis:GetPrefixGroupMicHasInTime groupId:%v err:%v", groupId, err) // Member: getMemberStr(groupId, userId),
} //}).Result(); err != nil {
// model.Log.Errorf("groupMicHasIn redis:GetPrefixGroupMicHasInTime groupId:%v err:%v", groupId, err)
//}
} }
const micHasInScript = "local flag = redis.call('EXISTS', '{key1}', '{key2}', '{key3}', '{key4}', '{key5}', '{key6}', '{key7}', '{key8}', '{key9}', '{key10}', '{key11}', '{key12}', '{key13}', '{key14}', '{key15}', '{key16}', '{key17}', '{key18}', '{key19}', '{key20}') if flag == 0 then redis.call('Srem', '{key}', '{remKey}') end return flag " const micHasInScript = "local flag = redis.call('EXISTS', '{key1}', '{key2}', '{key3}', '{key4}', '{key5}', '{key6}', '{key7}', '{key8}', '{key9}', '{key10}', '{key11}', '{key12}', '{key13}', '{key14}', '{key15}', '{key16}', '{key17}', '{key18}', '{key19}', '{key20}') if flag == 0 then redis.call('Srem', '{key}', '{remKey}') end return flag "
...@@ -843,6 +855,7 @@ func GetMicHasInGroups() ([]string, error) { ...@@ -843,6 +855,7 @@ func GetMicHasInGroups() ([]string, error) {
if err != nil { if err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
return groupUuids, nil // 不需要下面的逐个麦位的判断了
// //
resultGroupUuids := make([]string, 0, len(groupUuids)) resultGroupUuids := make([]string, 0, len(groupUuids))
//循环lua判断是否, 最后的保证,(猜想:真正麦上有人的群没有很多) //循环lua判断是否, 最后的保证,(猜想:真正麦上有人的群没有很多)
...@@ -875,7 +888,7 @@ var micGroupNumCache = gcache.New(10000).LRU().Build() ...@@ -875,7 +888,7 @@ var micGroupNumCache = gcache.New(10000).LRU().Build()
func GetMicHasInGroupNum(model *domain.Model) (map[string]int64, error) { func GetMicHasInGroupNum(model *domain.Model) (map[string]int64, error) {
// get from cache // get from cache
if data, err := micGroupNumCache.Get(micGroupNumKey); err == nil { if data, err := micGroupNumCache.Get(micGroupNumKey); err == nil {
model.Log.Infof("GetMicHasInGroupNum cache hit:%v", data) //model.Log.Infof("GetMicHasInGroupNum cache hit:%v", data)
// 正服才缓存 // 正服才缓存
if config.AppIsRelease() { if config.AppIsRelease() {
return data.(map[string]int64), nil return data.(map[string]int64), nil
...@@ -912,8 +925,41 @@ func GetMicHasInGroupNum(model *domain.Model) (map[string]int64, error) { ...@@ -912,8 +925,41 @@ func GetMicHasInGroupNum(model *domain.Model) (map[string]int64, error) {
} }
} }
// cache 1min // cache 1min
_ = micGroupNumCache.SetWithExpire(micGroupNumKey, resultGroupUuids, time.Minute) _ = micGroupNumCache.SetWithExpire(micGroupNumKey, resultGroupUuids, time.Minute*15)
model.Log.Infof("GetMicHasInGroupNum cache miss:%v", resultGroupUuids) return resultGroupUuids, nil
}
// 获取麦上人数
func GetMicHasInGroupNumByList(model *domain.Model, groupIds []string) (map[string]int64, error) {
resultGroupUuids := make(map[string]int64, len(groupIds))
micHasInKey := redis_key.GetPrefixGroupMicHasIn()
for _, group := range groupIds {
isMem, err := redisCli.GetRedis().SIsMember(context.Background(), micHasInKey, group).Result()
if err != nil {
model.Log.Errorf("GetMicHasInGroupNumByList err:%v", err)
return nil, myerr.WrapErr(err)
}
if isMem {
s := strings.Replace(micHasInScript, "{key}", micHasInKey, -1)
s = strings.Replace(s, "{remKey}", group, -1)
for i := 1; i <= MaxMicNum; i++ {
s = strings.Replace(s, "{key"+strconv.Itoa(i)+"}", redis_key.GetPrefixGroupMicUser(group, i), -1)
}
//r, err := redis2.NewScript(s).Run(context.Background(), redisCli.GetRedis(), []string{}).Result()
sha1, err := model.Redis.ScriptLoad(model, s).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
micNum, err := model.Redis.EvalSha(model, sha1, nil, nil).Int64()
if err != nil {
return nil, myerr.WrapErr(err)
}
//d := r.(int64)
if micNum > 0 {
resultGroupUuids[group] = micNum
}
}
}
return resultGroupUuids, nil return resultGroupUuids, nil
} }
......
...@@ -68,7 +68,7 @@ type MicNumChangeContent struct { ...@@ -68,7 +68,7 @@ type MicNumChangeContent struct {
Timestamp int64 `json:"timestamp"` Timestamp int64 `json:"timestamp"`
} }
func MicGroupKickOutRPush(model *domain.Model, groupUid string, userExternalId string, beKickExternalId string) { func MicGroupKickOutRPush(model *domain.Model, groupUid string, userExternalId string, beKickExternalId string, beKickuserId uint64) {
model.Log.Infof("MicChangeRPush MicGroupKickOutRPush begin groupUuid:%v", groupUid) model.Log.Infof("MicChangeRPush MicGroupKickOutRPush begin groupUuid:%v", groupUid)
txGroupId, err := ToTxGroupId(model, groupUid) txGroupId, err := ToTxGroupId(model, groupUid)
...@@ -94,7 +94,9 @@ func MicGroupKickOutRPush(model *domain.Model, groupUid string, userExternalId s ...@@ -94,7 +94,9 @@ func MicGroupKickOutRPush(model *domain.Model, groupUid string, userExternalId s
model.Log.Errorf("MicChangeRPush MicGroupKickOutRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicGroupKickOutRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { // socket通知被拉黑者退房
rpc.SendQuitRoom(beKickuserId, 2, txGroupId)
if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicGroupKickOutRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicGroupKickOutRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} else { } else {
...@@ -128,7 +130,7 @@ func MicSocketMicOutRPush(model *domain.Model, groupUid string, userExternalId s ...@@ -128,7 +130,7 @@ func MicSocketMicOutRPush(model *domain.Model, groupUid string, userExternalId s
model.Log.Errorf("MicChangeRPush MicSocketMicOutRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicSocketMicOutRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicSocketMicOutRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicSocketMicOutRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} else { } else {
...@@ -163,7 +165,7 @@ func MicNumChangeRPush(model *domain.Model, groupUid string, micNumType group_e. ...@@ -163,7 +165,7 @@ func MicNumChangeRPush(model *domain.Model, groupUid string, micNumType group_e.
model.Log.Errorf("MicChangeRPush MicNumChangeRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicNumChangeRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicNumChangeRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str)) model.Log.Errorf("MicChangeRPush MicNumChangeRPush err:%+v, groupUuid:%v, micContent:%+v", err, groupUid, string(str))
return return
} else { } else {
...@@ -204,7 +206,7 @@ func MicEmptyRPush(model *domain.Model, groupUid string, i int) { ...@@ -204,7 +206,7 @@ func MicEmptyRPush(model *domain.Model, groupUid string, i int) {
model.Log.Errorf("MicChangeRPush MicEmptyRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContent)) model.Log.Errorf("MicChangeRPush MicEmptyRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContent))
return return
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicEmptyRPush err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContent)) model.Log.Errorf("MicChangeRPush MicEmptyRPush err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContent))
return return
} else { } else {
...@@ -241,7 +243,7 @@ func MicChangeRPush(model *domain.Model, groupUid string, i int) { ...@@ -241,7 +243,7 @@ func MicChangeRPush(model *domain.Model, groupUid string, i int) {
model.Log.Errorf("MicChangeRPush MicChangeRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContentStr)) model.Log.Errorf("MicChangeRPush MicChangeRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContentStr))
return return
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicChangeRPush err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContentStr)) model.Log.Errorf("MicChangeRPush MicChangeRPush err:%+v, groupUuid:%v, i:%v, micContent:%+v", err, groupUid, i, string(micContentStr))
return return
} else { } else {
...@@ -259,9 +261,9 @@ func MicAllRPush(model *domain.Model, groupUid string, externalId string) error ...@@ -259,9 +261,9 @@ func MicAllRPush(model *domain.Model, groupUid string, externalId string) error
} }
// //
micContents, err := getMicAllContent(model, groupUid) micContents, err := GetMicAllContent(model, groupUid)
if err != nil { if err != nil {
model.Log.Errorf("MicChangeRPush MicAllRPush getMicAllContent err:%+v, micContents:%v groupUuid:%v, externalId:%v", err, micContents, groupUid, externalId) model.Log.Errorf("MicChangeRPush MicAllRPush GetMicAllContent err:%+v, micContents:%v groupUuid:%v, externalId:%v", err, micContents, groupUid, externalId)
return err return err
} }
for _, micContent := range micContents { for _, micContent := range micContents {
...@@ -286,7 +288,7 @@ func MicAllRPush(model *domain.Model, groupUid string, externalId string) error ...@@ -286,7 +288,7 @@ func MicAllRPush(model *domain.Model, groupUid string, externalId string) error
model.Log.Errorf("MicChangeRPush MicAllRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, externalId:%v, micContent:%+v", err, groupUid, externalId, string(micContentStr)) model.Log.Errorf("MicChangeRPush MicAllRPush Marshal MicSystemMsg err:%+v, groupUuid:%v, externalId:%v, micContent:%+v", err, groupUid, externalId, string(micContentStr))
continue continue
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicChangeRPush MicAllRPush err:%+v, groupUuid:%v, externalId:%v, micContent:%+v", err, groupUid, externalId, string(micContentStr)) model.Log.Errorf("MicChangeRPush MicAllRPush err:%+v, groupUuid:%v, externalId:%v, micContent:%+v", err, groupUid, externalId, string(micContentStr))
continue continue
} else { } else {
...@@ -310,7 +312,7 @@ func MicRPush(model *domain.Model, txGroupId string, msg GroupSystemMsg) error { ...@@ -310,7 +312,7 @@ func MicRPush(model *domain.Model, txGroupId string, msg GroupSystemMsg) error {
model.Log.Errorf("MicRPush Marshal MicSystemMsg err:%+v, txGroupId:%v, micContent:%+v", err, txGroupId, string(str)) model.Log.Errorf("MicRPush Marshal MicSystemMsg err:%+v, txGroupId:%v, micContent:%+v", err, txGroupId, string(str))
return err return err
} }
if n, err := redisCli.GetRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 { if n, err := redisCli.GetClusterRedis().RPush(context.Background(), redis_key.GetMicInfoChange(), string(str)).Result(); err != nil || n == 0 {
model.Log.Errorf("MicRPush err:%+v, txGroupId:%v, micContent:%+v", err, txGroupId, string(str)) model.Log.Errorf("MicRPush err:%+v, txGroupId:%v, micContent:%+v", err, txGroupId, string(str))
return err return err
} }
...@@ -319,7 +321,7 @@ func MicRPush(model *domain.Model, txGroupId string, msg GroupSystemMsg) error { ...@@ -319,7 +321,7 @@ func MicRPush(model *domain.Model, txGroupId string, msg GroupSystemMsg) error {
} }
//得使用旧的imGroupId //得使用旧的imGroupId
func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error) { func GetMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error) {
txGroupId, err := ToTxGroupId(model, groupUid) txGroupId, err := ToTxGroupId(model, groupUid)
if err != nil { if err != nil {
...@@ -340,6 +342,9 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error ...@@ -340,6 +342,9 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error
userIds := make([]uint64, 0, len(micUsers)) userIds := make([]uint64, 0, len(micUsers))
for _, r := range micUsers { for _, r := range micUsers {
userIds = append(userIds, r.UserId) userIds = append(userIds, r.UserId)
if r.CpUserId > 0 {
userIds = append(userIds, r.CpUserId)
}
} }
model.Log.Infof("MicChangeRPush getMicAllContent groupUid:%v, userIds:%+v", groupUid, userIds) model.Log.Infof("MicChangeRPush getMicAllContent groupUid:%v, userIds:%+v", groupUid, userIds)
...@@ -350,6 +355,13 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error ...@@ -350,6 +355,13 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error
micContents := make([]MicContent, 0, len(mics)) micContents := make([]MicContent, 0, len(mics))
for _, r := range mics { for _, r := range mics {
var micEffect string
cpUserId := micUserMap[r.I].CpUserId
micUserData := micUserDataMap[micUserMap[r.I].UserId]
if cpUserId > 0 {
micEffect = "https://image.whoisamy.shop/hilo/resource/svga/mic_effect_cp.svga"
micUserData.MicEffect = micEffect
}
micContents = append(micContents, MicContent{ micContents = append(micContents, MicContent{
GroupId: txGroupId, GroupId: txGroupId,
I: r.I, I: r.I,
...@@ -359,7 +371,7 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error ...@@ -359,7 +371,7 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error
ExternalId: micUserMap[r.I].ExternalId, ExternalId: micUserMap[r.I].ExternalId,
AgoraId: uint32(micUserMap[r.I].UserId), AgoraId: uint32(micUserMap[r.I].UserId),
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().UnixNano(),
User: micUserDataMap[micUserMap[r.I].UserId], User: micUserData,
}) })
} }
return micContents, nil return micContents, nil
...@@ -448,6 +460,7 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser ...@@ -448,6 +460,7 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
return nil, err return nil, err
} }
svips, _ := rpc.MGetUserSvip(model, userIds) svips, _ := rpc.MGetUserSvip(model, userIds)
cpRelations, _ := rpc.MGetUserCpRelations(model, userIds)
micUserDataMap := map[uint64]*MicUserData{} micUserDataMap := map[uint64]*MicUserData{}
for _, id := range userIds { for _, id := range userIds {
...@@ -461,11 +474,11 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser ...@@ -461,11 +474,11 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
} }
var headwearPicUrl string var headwearPicUrl string
var headwearEffectUrl string var headwearEffectUrl string
var reverseHeadwearEffectUrl string var headwearReverseEffectUrl string
if headwearUser, flag := headwearMap[id]; flag { if headwearUser, flag := headwearMap[id]; flag {
headwearPicUrl = resHeadwearMap[headwearUser.HeadwearId].PicUrl headwearPicUrl = resHeadwearMap[headwearUser.HeadwearId].PicUrl
headwearEffectUrl = resHeadwearMap[headwearUser.HeadwearId].EffectUrl headwearEffectUrl = resHeadwearMap[headwearUser.HeadwearId].EffectUrl
reverseHeadwearEffectUrl = resHeadwearMap[headwearUser.HeadwearId].ReverseEffectUrl headwearReverseEffectUrl = resHeadwearMap[headwearUser.HeadwearId].ReverseEffectUrl
} }
micUserDataMap[id] = &MicUserData{ micUserDataMap[id] = &MicUserData{
Id: user.ID, Id: user.ID,
...@@ -478,9 +491,10 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser ...@@ -478,9 +491,10 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
NobleLeave: nobleMap[id], NobleLeave: nobleMap[id],
HeadwearPicUrl: headwearPicUrl, HeadwearPicUrl: headwearPicUrl,
HeadwearEffectUrl: headwearEffectUrl, HeadwearEffectUrl: headwearEffectUrl,
HeadwearReverseEffectUrl: reverseHeadwearEffectUrl, HeadwearReverseEffectUrl: headwearReverseEffectUrl,
SvipLevel: svips[id].SvipLevel, SvipLevel: svips[id].SvipLevel,
Svip: rpc.CopySimpleSvip(svips[id]), Svip: rpc.CopySimpleSvip(svips[id]),
HeadwearIcon: cpRelations[user.ID].CpUserAvatar,
} }
} }
return micUserDataMap, nil return micUserDataMap, nil
......
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/group_k"
"hilo-group/domain/cache/room_c" "hilo-group/domain/cache/room_c"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/myerr" "hilo-group/myerr"
...@@ -49,14 +50,14 @@ func RoomLivingExpire(model *domain.Model, groupUid string, userId uint64) { ...@@ -49,14 +50,14 @@ func RoomLivingExpire(model *domain.Model, groupUid string, userId uint64) {
model.Log.Infof("room RoomLivingExpire userId:%v, groupUid:%v", userId, groupUid) model.Log.Infof("room RoomLivingExpire userId:%v, groupUid:%v", userId, groupUid)
// //
key := redis_key.GetPrefixGroupRoomLiving() 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()), Score: float64(time.Now().Unix()),
Member: getMemberStr(groupUid, userId), Member: getMemberStr(groupUid, userId),
}).Result() }).Result()
if err != nil { if err != nil {
model.Log.Errorf("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err) model.Log.Errorf("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err)
} else { } 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,14 +70,14 @@ func RoomLivingIn(model *domain.Model, groupUid string, userId uint64, externalI ...@@ -69,14 +70,14 @@ func RoomLivingIn(model *domain.Model, groupUid string, userId uint64, externalI
} }
// //
key := redis_key.GetPrefixGroupRoomLiving() 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()), Score: float64(time.Now().Unix()),
Member: getMemberStr(groupUid, userId), Member: getMemberStr(groupUid, userId),
}).Result() }).Result()
if err != nil { if err != nil {
model.Log.Errorf("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err) model.Log.Errorf("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err)
} else { } 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) { go func(myContext *mycontext.MyContext, groupId string) {
...@@ -111,11 +112,11 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri ...@@ -111,11 +112,11 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri
key := redis_key.GetPrefixGroupRoomLiving() key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil { //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) 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 { if err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
...@@ -124,12 +125,12 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri ...@@ -124,12 +125,12 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri
for i, _ := range data { for i, _ := range data {
gid, uid := analysisMemberStr(data[i]) gid, uid := analysisMemberStr(data[i])
if uid == userId && (groupId == "" || gid == groupId) { 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) model.Log.Errorf("RoomLivingLeave ZRem key:%s, groupId:%s, userId:%d, err:%v", key, gid, uid, err)
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} else { } else {
groupIds = append(groupIds, gid) 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)
} }
// 发信令,让前端重新拉取,接受容错, // 发信令,让前端重新拉取,接受容错,
...@@ -208,7 +209,7 @@ func RoomLivingLeaveByKick(model *domain.Model, groupUuid string, beKickuserId u ...@@ -208,7 +209,7 @@ func RoomLivingLeaveByKick(model *domain.Model, groupUuid string, beKickuserId u
Target: beKickExternalId, Target: beKickExternalId,
}, false)*/ }, false)*/
MicGroupKickOutRPush(model, groupUuid, userExternalId, beKickExternalId) MicGroupKickOutRPush(model, groupUuid, userExternalId, beKickExternalId, beKickuserId)
return roomLivingLeave(model, beKickuserId, groupUuid) return roomLivingLeave(model, beKickuserId, groupUuid)
} }
...@@ -271,15 +272,15 @@ func RoomLivingExistsUserId(groupUid string) ([]uint64, error) { ...@@ -271,15 +272,15 @@ func RoomLivingExistsUserId(groupUid string) ([]uint64, error) {
key := redis_key.GetPrefixGroupRoomLiving() key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil { //if err := redisCli.ClearExpired(key, expireMinute); err != nil {
var model = domain.CreateModelNil() 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) 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 { if err != nil {
return nil, myerr.WrapErr(err) 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)) userIds := make([]uint64, 0, len(groupUserIdstrs))
for i, _ := range groupUserIdstrs { for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i]) tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
...@@ -299,11 +300,11 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) { ...@@ -299,11 +300,11 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) {
key := redis_key.GetPrefixGroupRoomLiving() key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil { //if err := redisCli.ClearExpired(key, expireMinute); err != nil {
model := domain.CreateModelNil() 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) 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 { if err != nil {
return nil, myerr.WrapErr(err) return nil, myerr.WrapErr(err)
} }
...@@ -324,16 +325,16 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) { ...@@ -324,16 +325,16 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) {
func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{}, error) { func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{}, error) {
key := redis_key.GetPrefixGroupRoomLiving() key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil { //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) model.Log.Infof("RoomLivingExistsGroup: err:%v", err)
return nil, myerr.WrapErr(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 { if err != nil {
return nil, myerr.WrapErr(err) 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{}{} groupGroup := map[string]map[uint64]struct{}{}
for i, _ := range groupUserIdstrs { for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i]) tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
...@@ -343,7 +344,7 @@ func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{}, ...@@ -343,7 +344,7 @@ func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{},
groupGroup[tempGroupUid] = map[uint64]struct{}{userId: {}} 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 return groupGroup, nil
} }
...@@ -389,18 +390,8 @@ func GetAllGroupsSorted(model *domain.Model) ([]string, error) { ...@@ -389,18 +390,8 @@ func GetAllGroupsSorted(model *domain.Model) ([]string, error) {
// 取房间最近N天的访问人数 // 取房间最近N天的访问人数
func GetRoomVisitCount(groupId string) (int64, error) { func GetRoomVisitCount(groupId string) (int64, error) {
// 每群定时请一次数据可以了 key := group_k.GetUserEnterRoomGroupKey(groupId)
now := time.Now() visitCount, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
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()
if err != nil { if err != nil {
return 0, err return 0, err
} }
...@@ -429,15 +420,12 @@ func BatchGetRoomVisitCount(logE *logrus.Entry, groupIds []string) (map[string]i ...@@ -429,15 +420,12 @@ func BatchGetRoomVisitCount(logE *logrus.Entry, groupIds []string) (map[string]i
if err != nil { if err != nil {
return nil, err return nil, err
} }
logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
visitCount := make(map[string]int64) visitCount := make(map[string]int64)
for _, groupId := range groupIds { for _, groupId := range groupIds {
// 先从二级缓存中找 // 先从二级缓存中找
if c, ok := roomVisitCount[groupId]; ok { if c, ok := roomVisitCount[groupId]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 { if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
logE.Debugf("GetRoomVisitCount, from roomVisitCount %s - %d", groupId, vc)
visitCount[groupId] = vc visitCount[groupId] = vc
} }
} else { } else {
...@@ -464,7 +452,7 @@ func BatchGetRoomVisitCountList(logE *logrus.Entry, groupIds []string) (map[stri ...@@ -464,7 +452,7 @@ func BatchGetRoomVisitCountList(logE *logrus.Entry, groupIds []string) (map[stri
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
logE.Infof("MGetRoomVisitCount:%v", roomVisitCount) //logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
res := make([]*RoomVisit, 0, len(groupIds)) res := make([]*RoomVisit, 0, len(groupIds))
visitCount := make(map[string]int64) visitCount := make(map[string]int64)
...@@ -505,7 +493,8 @@ func (uer *UserEnterRoom) Save(db *gorm.DB) error { ...@@ -505,7 +493,8 @@ func (uer *UserEnterRoom) Save(db *gorm.DB) error {
func (uer *UserEnterRoom) Find(db *gorm.DB) ([]UserEnterRoom, error) { func (uer *UserEnterRoom) Find(db *gorm.DB) ([]UserEnterRoom, error) {
rows := make([]UserEnterRoom, 0) 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 nil, err
} }
return rows, nil return rows, nil
......
...@@ -57,6 +57,24 @@ func GetAllGroupSupportResult(db *gorm.DB, period string) (map[string]uint8, err ...@@ -57,6 +57,24 @@ func GetAllGroupSupportResult(db *gorm.DB, period string) (map[string]uint8, err
return result, nil 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 { type GroupSupportAwardAdmin struct {
mysql.Entity mysql.Entity
...@@ -102,14 +120,14 @@ func (gsa *GroupSupportAwardMgr) Get(db *gorm.DB) ([]GroupSupportAwardMgr, error ...@@ -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) { 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) //resGroupSupport, err := res_m.GetResGroupSupportById(model, resGroupSupportId)
if err != nil { //if err != nil {
return nil, nil, err // return nil, nil, err
} //}
if int(resGroupSupport.MgrNum) < len(userIds) { if int(resSupport.MgrNum) < len(userIds) {
return nil, nil, myerr.NewSysErrorF("AddGroupSupportAward mgrNum:%v 同 len(userIds)=%v 不一致", resGroupSupport.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 ...@@ -118,9 +136,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys
GroupUid: groupUid, GroupUid: groupUid,
IssuerUserId: issuerUserId, IssuerUserId: issuerUserId,
UserId: issuerUserId, UserId: issuerUserId,
DiamondNum: resGroupSupport.AdminAward, DiamondNum: resSupport.AdminAward,
Grade: resGroupSupport.Grade, Grade: resSupport.Grade,
ResGroupSupportId: resGroupSupport.ID, ResGroupSupportId: resSupport.ID,
Period: period, Period: period,
} }
...@@ -133,9 +151,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys ...@@ -133,9 +151,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys
GroupUid: groupUid, GroupUid: groupUid,
IssuerUserId: issuerUserId, IssuerUserId: issuerUserId,
UserId: userIds[i], UserId: userIds[i],
DiamondNum: resGroupSupport.MgrAward, DiamondNum: resSupport.MgrAward,
Grade: resGroupSupport.Grade, Grade: resSupport.Grade,
ResGroupSupportId: resGroupSupport.ID, ResGroupSupportId: resSupport.ID,
Period: period, Period: period,
}) })
} }
......
...@@ -104,7 +104,8 @@ func (rb *RoomBanner) GetRoomBanners(db *gorm.DB, vcAllow bool) ([]RoomBanner, e ...@@ -104,7 +104,8 @@ func (rb *RoomBanner) GetRoomBanners(db *gorm.DB, vcAllow bool) ([]RoomBanner, e
res := make([]RoomBanner, 0, len(rows)) res := make([]RoomBanner, 0, len(rows))
for _, v := range rows { for _, v := range rows {
// 版本控制 // 版本控制
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) { 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 continue
} }
res = append(res, v) res = append(res, v)
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"git.hilo.cn/hilo-common/utils" "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
"hilo-group/_const/redis_key/mic_k"
"time" "time"
) )
...@@ -75,6 +76,45 @@ func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64) ...@@ -75,6 +76,45 @@ func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64)
}) })
} }
// 增加用户上麦时长
// 事务操作
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"}, {Name: "tz"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"seconds": gorm.Expr("seconds + ?", 60),
}),
}).Create(&UserOnMic{
Date: day,
UserId: userId,
Seconds: 60,
Tz: tz,
}).Error; err != nil {
model.Log.Errorf("IncrUserOnMic fail:%v", err)
return err
}
}
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 // @return userId->seconds
func MGetUserOnMicSeconds(model *domain.Model, day string, tz timezone_e.Timezone, 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) {
......
...@@ -144,7 +144,7 @@ func BatchGetActiveNoble(db *gorm.DB, userIds []uint64) (map[uint64]UserNoble, e ...@@ -144,7 +144,7 @@ func BatchGetActiveNoble(db *gorm.DB, userIds []uint64) (map[uint64]UserNoble, e
start += NUM start += NUM
end += 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) { if len(userIds) != len(result) {
mylogrus.MyLog.Warnf("BatchGetActiveNoble expected:%v", userIds) mylogrus.MyLog.Warnf("BatchGetActiveNoble expected:%v", userIds)
} }
...@@ -177,4 +177,4 @@ func BatchGetNobleLevel(db *gorm.DB, userIds []uint64) (map[uint64]uint16, error ...@@ -177,4 +177,4 @@ func BatchGetNobleLevel(db *gorm.DB, userIds []uint64) (map[uint64]uint16, error
result[i] = m[i].Level result[i] = m[i].Level
} }
return result, nil return result, nil
} }
\ No newline at end of file
...@@ -213,3 +213,10 @@ func GetLangeByCountry(db *gorm.DB, country mysql.Str) (string, error) { ...@@ -213,3 +213,10 @@ func GetLangeByCountry(db *gorm.DB, country mysql.Str) (string, error) {
return "", myerr.WrapErr(err) return "", myerr.WrapErr(err)
} }
} }
//获取所有国家名字列表
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)
}
...@@ -325,7 +325,7 @@ func GetOnlineStatus(model *domain.Model, extIds []string) (map[string]uint, err ...@@ -325,7 +325,7 @@ func GetOnlineStatus(model *domain.Model, extIds []string) (map[string]uint, err
model.Log.Warnf("getOnlineStatus redis failed") model.Log.Warnf("getOnlineStatus redis failed")
left = extIds left = extIds
} else { } 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) { if len(r) >= len(extIds) {
for i, e := range extIds { for i, e := range extIds {
...@@ -387,10 +387,10 @@ func getOnlineStatus(extIds []string) ([]interface{}, error) { ...@@ -387,10 +387,10 @@ func getOnlineStatus(extIds []string) ([]interface{}, error) {
for _, e := range extIds { for _, e := range extIds {
keys = append(keys, redis_key.GetOnLineStatusKey(e)) 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 { func setOnlineStatus(extId string, status uint, ttl time.Duration) error {
key := redis_key.GetOnLineStatusKey(extId) 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 ...@@ -3,10 +3,12 @@ package user_m
import ( import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr" "hilo-group/myerr"
) )
//获取用户的国家,和所属的区域(是否阿语区) // 获取用户的国家,和所属的区域(是否阿语区)
// 默认国家给沙特
func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) { func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
type info struct { type info struct {
Name string Name string
...@@ -14,7 +16,11 @@ func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) { ...@@ -14,7 +16,11 @@ func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
} }
res := new(info) 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 { 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 return res.Name, res.Area, nil
} }
...@@ -48,8 +48,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui ...@@ -48,8 +48,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
if err != nil { if err != nil {
return nil, err return nil, err
} }
logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes) //logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes)
logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList) //logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList)
maxGrades := make(map[uint8]int, 0) maxGrades := make(map[uint8]int, 0)
maxMedalIds := make(map[uint8]uint32, 0) maxMedalIds := make(map[uint8]uint32, 0)
...@@ -70,8 +70,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui ...@@ -70,8 +70,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
} }
} }
} }
logger.Infof("maxGrade %+v", maxGrades) //logger.Infof("maxGrade %+v", maxGrades)
logger.Infof("maxMedalIds %+v", maxMedalIds) //logger.Infof("maxMedalIds %+v", maxMedalIds)
mIds := result mIds := result
result = make([]uint32, 0) result = make([]uint32, 0)
......
...@@ -85,12 +85,29 @@ func GetUsersByIds(model *domain.Model, userIds []mysql.ID) ([]User, error) { ...@@ -85,12 +85,29 @@ func GetUsersByIds(model *domain.Model, userIds []mysql.ID) ([]User, error) {
return users, nil return users, nil
} }
// 分批获取userIds
func GetUserMapByIds(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]User, error) { 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) 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 { for _, i := range rows {
result[i.ID] = i result[i.ID] = i
} }
...@@ -127,3 +144,39 @@ func GetUsers(model *domain.Model, ids []mysql.ID) ([]*User, error) { ...@@ -127,3 +144,39 @@ func GetUsers(model *domain.Model, ids []mysql.ID) ([]*User, error) {
} }
return res, nil 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) { ...@@ -59,14 +59,34 @@ func GetVip(db *gorm.DB, userId uint64) (*UserVip, error) {
return nil, nil return nil, nil
} }
// 分批获取
func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) { func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) {
result := make(map[uint64]*int64, 0)
rows := make([]UserVip, 0) rows := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&rows).Error end := 500
if err != nil { if end > len(userIds) {
return nil, err 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 { for _, i := range userIds {
result[i] = nil result[i] = nil
} }
......
...@@ -6,22 +6,18 @@ import ( ...@@ -6,22 +6,18 @@ import (
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/rpc" "git.hilo.cn/hilo-common/rpc"
"git.hilo.cn/hilo-common/sdk/tencentyun" "git.hilo.cn/hilo-common/sdk/tencentyun"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/msg_e" "hilo-group/_const/enum/msg_e"
"hilo-group/_const/enum/task_e" "hilo-group/_const/enum/task_e"
"hilo-group/domain/event/gift_ev" "hilo-group/domain/cache/group_c"
"hilo-group/domain/event/group_ev" "hilo-group/domain/event/group_ev"
"hilo-group/domain/event/group_power_ev" "hilo-group/domain/event/group_power_ev"
"hilo-group/domain/event/mic_ev"
"hilo-group/domain/model/diamond_m" "hilo-group/domain/model/diamond_m"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/mic_m"
"hilo-group/domain/model/msg_m" "hilo-group/domain/model/msg_m"
"hilo-group/domain/model/task_m" "hilo-group/domain/model/task_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_mic_s"
"hilo-group/myerr" "hilo-group/myerr"
"strconv" "strconv"
"time" "time"
...@@ -33,8 +29,8 @@ func EventInit() { ...@@ -33,8 +29,8 @@ func EventInit() {
GroupEvents() GroupEvents()
GroupImMass() GroupImMass()
GroupTheme() GroupTheme()
SendGift() // 送礼事件 //SendGift() // 送礼事件
OnMic() // 在麦上事件 GroupInMicChangeEvent() // 用户进房推送mic位置信息
} }
func GroupSupportEvents() { func GroupSupportEvents() {
...@@ -246,6 +242,7 @@ func GroupEvents() { ...@@ -246,6 +242,7 @@ func GroupEvents() {
} }
err := uer.Save(model.Db) err := uer.Save(model.Db)
model.Log.Infof("AddGroupInAsync, UserEnterRoom err: %v", err) model.Log.Infof("AddGroupInAsync, UserEnterRoom err: %v", err)
group_c.ZAddUserEnterRoom(model, event.UserId, event.GroupId) // redis存储
return err return err
}) })
...@@ -468,99 +465,69 @@ func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32, ...@@ -468,99 +465,69 @@ func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32,
func SendGift() { func SendGift() {
// 送礼事件-势力经验 // 送礼事件-势力经验
gift_ev.AddSendGiftEventSync(func(model *domain.Model, event interface{}) error { //gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error {
sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent) // sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
if !ok { // if !ok {
model.Log.Errorf("AddSendGiftEventAsync event type err") // model.Log.Errorf("AddSendGiftEventAsync event type err")
return nil // return nil
} // }
model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent) // model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent)
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow { // if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return nil // return nil
} // }
exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId) // exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId)
if err != nil { // if err != nil {
model.Log.Infof("CheckGroupPowerUser fail %+v", err) // model.Log.Infof("CheckGroupPowerUser fail %+v", err)
return err // return err
} // }
if exist { // if exist {
exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum // exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum
return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼") // //return model.Transaction(func(model *domain.Model) error {
} // // return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
return nil // //})
}) // return groupPower_c.QueueGroupPowerGradeExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
// }
// return nil
//})
// 家族之星-送礼/收礼 // 家族之星-送礼/收礼
gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error { //gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error {
sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent) // sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
if !ok { // if !ok {
model.Log.Errorf("AddSendGiftEventAsync event type err") // model.Log.Errorf("AddSendGiftEventAsync event type err")
return nil // return nil
} // }
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow { // if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return nil // return nil
} // }
var userIds = []mysql.ID{sendGiftEvent.SendUserId} // var userIds = []mysql.ID{sendGiftEvent.SendUserId}
userIds = append(userIds, sendGiftEvent.ReceiveUserIds...) // userIds = append(userIds, sendGiftEvent.ReceiveUserIds...)
groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds) // groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds)
if err != nil { // if err != nil {
model.Log.Errorf("AddSendGiftEventAsync fail:%v", err) // model.Log.Errorf("AddSendGiftEventAsync fail:%v", err)
return err // return err
} // }
// 送礼加分 // // 送礼加分
if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok { // if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) // diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
if err := groupPower_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeFamous, diamonds, 0); err != nil { // if err := groupPower_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeFamous, diamonds, 0); err != nil {
model.Log.Errorf("IncrGroupPowerMonthStarScore famous fail:%v", err) // model.Log.Errorf("IncrGroupPowerMonthStarScore famous fail:%v", err)
} // }
if err := groupPower_m.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeFamous, diamonds, 0); err != nil { // if err := groupPower_m.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeFamous, diamonds, 0); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore famous fail:%v", err) // model.Log.Errorf("IncrGroupPowerDayStarScore famous fail:%v", err)
} // }
} // }
// 收礼加分 // // 收礼加分
for _, userId := range sendGiftEvent.ReceiveUserIds { // for _, userId := range sendGiftEvent.ReceiveUserIds {
if data, ok := groupPowers[userId]; ok { // if data, ok := groupPowers[userId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum // diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum
if err := groupPower_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil { // if err := groupPower_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil {
model.Log.Errorf("IncrGroupPowerMonthStarScore charm fail:%v", err) // model.Log.Errorf("IncrGroupPowerMonthStarScore charm fail:%v", err)
} // }
if err := groupPower_m.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil { // if err := groupPower_m.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore charm fail:%v", err) // model.Log.Errorf("IncrGroupPowerDayStarScore charm fail:%v", err)
} // }
} // }
} // }
return nil // return nil
}) //})
}
func OnMic() {
// 上麦经验/上麦时长
mic_ev.AddOnMicEventAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*mic_ev.OnMicEvent)
if !ok {
model.Log.Errorf("AddOnMicEventSync event type err")
return nil
}
if err := group_mic_s.NewGroupPowerService(model.MyContext).IncrGroupPowerOnMicExpAndTime(event.GroupUuid, event.UserId, event.Timestamp); err != nil {
model.Log.Errorf("cron micIn GroupPowerOnMicExp err:%v", err)
} else {
model.Log.Infof("cron micIn GroupPowerOnMicExp success, groupId:%v, userId:%v", event.GroupUuid, event.UserId)
}
return nil
})
// 用户上麦时长
mic_ev.AddOnMicEventAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*mic_ev.OnMicEvent)
if !ok {
model.Log.Errorf("AddOnMicEventSync event type err")
return nil
}
if err := mic_m.IncrUserOnMic(model, event.UserId, event.Timestamp); err != nil {
model.Log.Errorf("cron micIn IncrUserOnMic err:%v", err)
} else {
model.Log.Infof("cron micIn IncrUserOnMic success,userId:%v", event.UserId)
}
// 处理活动数据
go rpc.AddActPoint(model, event.UserId, 1, 0)
return nil
})
} }
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
}
package event_s
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/protocol/userProxy"
"git.hilo.cn/hilo-common/rpc"
uuid "github.com/satori/go.uuid"
"hilo-group/domain/event/group_ev"
"hilo-group/domain/model/group_m"
"hilo-group/myerr/bizerr"
)
// 用户进房后推送mic信息
func GroupInMicChangeEvent() {
group_ev.AddTxGroupInEventAsync(func(model *domain.Model, event interface{}) error {
e, ok := event.(*group_ev.TxGroupInEvent)
if !ok {
return bizerr.InvalidParameter
}
return MicAllRPush(model, e.GroupId, e.UserId, e.ExternalId)
})
}
func MicAllRPush(model *domain.Model, imGroupId string, userId uint64, externalId string) error {
model.Log.Infof("MicChangeRPush MicAllRPush begin groupUuid:%v, externalId:%v", imGroupId, externalId)
txGroupId, err := group_m.ToTxGroupId(model, imGroupId)
if err != nil {
model.Log.Errorf("ToImGroupId fail:%v", err)
return err
}
//
micContents, err := group_m.GetMicAllContent(model, imGroupId)
if err != nil {
model.Log.Errorf("MicChangeRPush MicAllRPush getMicAllContent err:%+v, micContents:%v groupUuid:%v, externalId:%v", err, micContents, txGroupId, externalId)
return err
}
for _, micContent := range micContents {
//麦上是默认值,就不用推
if micContent.Forbid == false && micContent.User == nil && micContent.AgoraId == 0 && micContent.Lock == false && micContent.ExternalId == "" && micContent.MicForbid == false {
model.Log.Infof("MicChangeRPush MicAllRPush default micContent:%v, groupUuid:%v, externalId:%v, micContent:%+v", micContent, txGroupId, externalId, micContent)
continue
}
micContentStr, err := json.Marshal(micContent)
if err != nil {
continue
}
var micExternalId string
var micUserData *userProxy.MicUserData
if micContent.User != nil {
micExternalId = micContent.ExternalId
micUserData = &userProxy.MicUserData{
Id: micContent.User.Id,
ExternalId: micContent.User.ExternalId,
Avatar: micContent.User.Avatar,
Nick: micContent.User.Nick,
Sex: uint32(micContent.User.Sex),
Code: micContent.User.Code,
IsVip: micContent.User.IsVip,
Noble: uint32(micContent.User.NobleLeave),
HeadwearPicUrl: micContent.User.HeadwearPicUrl,
HeadwearEffectUrl: micContent.User.HeadwearEffectUrl,
HeadwearReverseEffectUrl: micContent.User.HeadwearReverseEffectUrl,
SvipLevel: uint32(micContent.User.SvipLevel),
MicEffect: micContent.User.MicEffect,
HeadwearIcon: micContent.User.HeadwearIcon,
Svip: nil,
}
if micContent.User.Svip.SvipLevel > 0 || len(micContent.User.Svip.Privileges) > 0 {
micUserData.Svip = &userProxy.Svip{
SvipLevel: uint64(micContent.User.SvipLevel),
}
for _, v := range micContent.User.Svip.Privileges {
micUserData.Svip.Privileges = append(micUserData.Svip.Privileges, &userProxy.SvipPrivilege{
Type: int32(v.Type),
CanSwitch: v.CanSwitch,
UserSwitch: v.UserSwitch,
MysteryCode: v.MysteryCode,
})
}
}
}
seqId := uuid.NewV4().String()
if err := rpc.SendSocketMicChange(seqId, userId, micExternalId, txGroupId, uint32(micContent.I), micContent.Lock, micContent.Forbid, micContent.MicForbid, micContent.AgoraId, micUserData); err != nil {
model.Log.Errorf("MicAllRPush err:%+v, groupUuid:%v, externalId:%v, micContent:%+v", err, txGroupId, externalId, string(micContentStr))
} else {
model.Log.Infof("MicChangeRPush MicAllRPush Marshal micContent, groupUuid:%v, externalId:%v, micContent:%+v", txGroupId, externalId, string(micContentStr))
}
}
model.Log.Infof("MicAllRPush end groupUuid:%v, externalId:%v", txGroupId, externalId)
return nil
}
...@@ -8,8 +8,10 @@ import ( ...@@ -8,8 +8,10 @@ import (
"git.hilo.cn/hilo-common/resource/redisCli" "git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/rpc" "git.hilo.cn/hilo-common/rpc"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/event/group_ev" "hilo-group/domain/event/group_ev"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
...@@ -317,15 +319,13 @@ func (s *GroupMicService) IncrGroupPowerOnMicExpAndTime(groupId string, userId u ...@@ -317,15 +319,13 @@ func (s *GroupMicService) IncrGroupPowerOnMicExpAndTime(groupId string, userId u
return nil return nil
} }
// 增加势力上麦经验 // 增加势力上麦经验
if err := groupPower_m.IncrGroupPowerExpOnMic(model, groupPowerId, userId, joinMicTimestamp); err != nil { if err := groupPower_m.IncrGroupPowerExpOnMic(model, groupPowerId, userId); err != nil {
model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err) model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err)
} }
// 增加势力上麦时长-月 // 增加势力上麦时长-天/周/月
if err := groupPower_m.IncrGroupPowerStarOnMicMonth(model, groupPowerId, userId, joinMicTimestamp); err != nil { //if err := groupPower_m.IncrGroupPowerStarOnMicDay(model, groupPowerId, userId, joinMicTimestamp); err != nil {
model.Log.Errorf("IncrGroupPowerStarOnMicMonth fail:%v", err) if err := groupPower_c.IncrGroupPowerDayStarScore(model, groupPowerId, userId,
} groupPower_e.GroupPowerStarTypeActive, 60); err != nil {
// 增加势力上麦时长-天
if err := groupPower_m.IncrGroupPowerStarOnMicDay(model, groupPowerId, userId, joinMicTimestamp); err != nil {
model.Log.Errorf("IncrGroupPowerStarOnMicDay fail:%v", err) model.Log.Errorf("IncrGroupPowerStarOnMicDay fail:%v", err)
} }
return nil return nil
...@@ -346,9 +346,11 @@ func (s *GroupMicService) CheckCpOnMic(groupUuid string) { ...@@ -346,9 +346,11 @@ func (s *GroupMicService) CheckCpOnMic(groupUuid string) {
// userId->micIndex // userId->micIndex
var userMicIndex = make(map[uint64]int) var userMicIndex = make(map[uint64]int)
var userIds []uint64 var userIds []uint64
forbidMap := make(map[uint64]bool)
for _, u := range micUsers { for _, u := range micUsers {
userMicIndex[u.UserId] = u.I userMicIndex[u.UserId] = u.I
userIds = append(userIds, u.UserId) userIds = append(userIds, u.UserId)
forbidMap[u.UserId] = u.Forbid
} }
cpPairs, err := rpc.MGetUserCpPairs(model, userIds) cpPairs, err := rpc.MGetUserCpPairs(model, userIds)
// 更新麦上cp的信息 // 更新麦上cp的信息
...@@ -374,7 +376,7 @@ func (s *GroupMicService) CheckCpOnMic(groupUuid string) { ...@@ -374,7 +376,7 @@ func (s *GroupMicService) CheckCpOnMic(groupUuid string) {
if err != nil { if err != nil {
return err return err
} }
return mic.Update(userId, users[userId].ExternalId, cpUserId) return mic.Update(userId, users[userId].ExternalId, cpUserId, forbidMap[userId])
}) })
redisLock(redis_key.GetPrefixGroupMicUserInLock(cpUserId), uuid.NewV4().String(), time.Second*2, func() error { redisLock(redis_key.GetPrefixGroupMicUserInLock(cpUserId), uuid.NewV4().String(), time.Second*2, func() error {
model := domain.CreateModel(s.svc.CtxAndDb) model := domain.CreateModel(s.svc.CtxAndDb)
...@@ -382,7 +384,7 @@ func (s *GroupMicService) CheckCpOnMic(groupUuid string) { ...@@ -382,7 +384,7 @@ func (s *GroupMicService) CheckCpOnMic(groupUuid string) {
if err != nil { if err != nil {
return err return err
} }
return mic.Update(cpUserId, users[cpUserId].ExternalId, userId) return mic.Update(cpUserId, users[cpUserId].ExternalId, userId, forbidMap[cpUserId])
}) })
} }
return return
...@@ -403,11 +405,13 @@ func (s *GroupMicService) CheckCpLeaveMic(groupUuid string, leaveUid uint64) { ...@@ -403,11 +405,13 @@ func (s *GroupMicService) CheckCpLeaveMic(groupUuid string, leaveUid uint64) {
// userId->micIndex // userId->micIndex
var userMicIndex = make(map[uint64]int) var userMicIndex = make(map[uint64]int)
var cpUserId uint64 var cpUserId uint64
forbidMap := make(map[uint64]bool)
for _, u := range micUsers { for _, u := range micUsers {
if u.UserId == leaveUid { if u.UserId == leaveUid {
cpUserId = u.CpUserId cpUserId = u.CpUserId
} }
userMicIndex[u.UserId] = u.I userMicIndex[u.UserId] = u.I
forbidMap[u.UserId] = u.Forbid
} }
if cpUserId <= 0 { if cpUserId <= 0 {
return return
...@@ -423,7 +427,7 @@ func (s *GroupMicService) CheckCpLeaveMic(groupUuid string, leaveUid uint64) { ...@@ -423,7 +427,7 @@ func (s *GroupMicService) CheckCpLeaveMic(groupUuid string, leaveUid uint64) {
if err != nil { if err != nil {
return err return err
} }
return mic.Update(cpUserId, user.ExternalId, 0) return mic.Update(cpUserId, user.ExternalId, 0, forbidMap[cpUserId])
}) })
return return
} }
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"hilo-group/_const/enum/msg_e" "hilo-group/_const/enum/msg_e"
"hilo-group/cv/group_power_cv" "hilo-group/cv/group_power_cv"
"hilo-group/cv/user_cv" "hilo-group/cv/user_cv"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/cache/user_c" "hilo-group/domain/cache/user_c"
"hilo-group/domain/event/group_power_ev" "hilo-group/domain/event/group_power_ev"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
...@@ -154,7 +155,12 @@ func GetGroupPowerRankResp(model *domain.Model, beginDate, endDate string, userI ...@@ -154,7 +155,12 @@ func GetGroupPowerRankResp(model *domain.Model, beginDate, endDate string, userI
} }
func GetGroupPowerStar(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*group_power_cv.CvGroupPowerStarData, error) { func GetGroupPowerStar(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*group_power_cv.CvGroupPowerStarData, error) {
rank, err := groupPower_m.GetGroupPowerMonthStarRank(model, groupPowerId, _type, offset, limit, month) monthTime, err := time.Parse("200601", month)
if err != nil {
return nil, err
}
//rank, err := groupPower_m.GetGroupPowerMonthStarRank(model, groupPowerId, _type, offset, limit, month)
rank, err := groupPower_c.GetGroupPowerStarRankPeriod(model, "month", groupPowerId, _type, offset, limit, monthTime.Format("2006-01-02"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -4,8 +4,8 @@ import ( ...@@ -4,8 +4,8 @@ import (
"encoding/json" "encoding/json"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/mgr_e" "hilo-group/_const/enum/mgr_e"
...@@ -18,7 +18,6 @@ import ( ...@@ -18,7 +18,6 @@ import (
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/domain/service/signal_s" "hilo-group/domain/service/signal_s"
"hilo-group/myerr" "hilo-group/myerr"
"strconv"
"time" "time"
) )
...@@ -31,7 +30,7 @@ func NewGroupService(myContext *mycontext.MyContext) *GroupService { ...@@ -31,7 +30,7 @@ func NewGroupService(myContext *mycontext.MyContext) *GroupService {
return &GroupService{svc} return &GroupService{svc}
} }
// 取本周最高的扶持等级 fixme:删除这个过渡函数 // 取本周最高的扶持等级
func (s *GroupService) GetWeekMaxSupportLevelMap() (map[string]uint8, error) { func (s *GroupService) GetWeekMaxSupportLevelMap() (map[string]uint8, error) {
return s.GetSupportLevelMap(time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY)) return s.GetSupportLevelMap(time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
} }
...@@ -42,56 +41,57 @@ func (s *GroupService) GetSupportLevelMap(now time.Time) (map[string]uint8, erro ...@@ -42,56 +41,57 @@ func (s *GroupService) GetSupportLevelMap(now time.Time) (map[string]uint8, erro
_, _, period := group_m.GetSupportLevelTime(now) _, _, period := group_m.GetSupportLevelTime(now)
levels, err := GetAllSupportLevel(model, period) levels, err := GetAllSupportLevel(model, period)
if err != nil { if err == nil {
return nil, err return levels, nil
} }
model.Log.Debugf("GetSupportLevelMap, GET %s: %v", period, levels) // cache miss
result := make(map[string]uint8, 0) result, err := group_m.GetAllGroupSupportResult(model.Db, period)
if len(levels) > 0 { if err == nil {
for g, l := range levels { SaveAllSupportLevel(model, period, result)
le, err := strconv.ParseUint(l, 10, 8)
if err == nil {
result[g] = uint8(le)
}
}
} else {
result, err = group_m.GetAllGroupSupportResult(model.Db, period)
if err == nil {
ret, err := SaveAllSupportLevel(model, period, result)
model.Log.Infof("GetSupportLevelMap SAVE ret = %d, err: %v", ret, err)
}
} }
return result, nil return result, nil
} }
func SaveAllSupportLevel(model *domain.Model, date string, levels map[string]uint8) (int64, error) { //// 取本周最高的扶持等级
values := make(map[string]interface{}, 0) //func (s *GroupService) GetWeekMaxSupportLevelMapByIds(groupIds []string) (map[string]uint8, error) {
for g, l := range levels { // return s.GetSupportLevelMapByIds(groupIds, time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
if l > 0 { //}
values[g] = l //
} //func (s *GroupService) GetSupportLevelMapByIds(groupIds []string, now time.Time) (map[string]uint8, error) {
} // model := domain.CreateModel(s.svc.CtxAndDb)
if len(values) <= 0 { //
return 0, nil // _, _, period := group_m.GetSupportLevelTime(now)
} //
key := redis_key.GetPrefixSupportLevel(date) // levels, err := GetAllSupportLevel(model, period)
ret, err := model.Redis.HSet(model, key, values).Result() // if err == nil {
// return levels, nil
// }
// // cache miss
//
// result, err := group_m.GetGroupSupportResult(model.DB(), period, groupIds)
// if err == nil {
// SaveAllSupportLevel(model, period, result)
// }
// return result, nil
//}
if err == nil { // supportLevelLru Cache
// 设置一个TTL保险一些 TODO: 可以优化,保证数据总是有的 var supportLevelCache = gcache.New(100).LRU().Build()
ttl := time.Hour
if !config.AppIsRelease() { func SaveAllSupportLevel(model *domain.Model, date string, levels map[string]uint8) {
ttl = time.Minute key := redis_key.GetPrefixSupportLevel(date)
} _ = supportLevelCache.SetWithExpire(key, levels, time.Hour)
model.Redis.Expire(model, key, ttl) return
}
return ret, err
} }
func GetAllSupportLevel(model *domain.Model, date string) (map[string]string, error) { func GetAllSupportLevel(model *domain.Model, date string) (map[string]uint8, error) {
key := redis_key.GetPrefixSupportLevel(date) key := redis_key.GetPrefixSupportLevel(date)
return model.Redis.HGetAll(model, key).Result() if data, err := supportLevelCache.Get(key); err == nil {
return data.(map[string]uint8), nil
} else {
return map[string]uint8{}, err
}
} }
func (s *GroupService) GetJoinGroupLimit(userId mysql.ID) (uint, error) { func (s *GroupService) GetJoinGroupLimit(userId mysql.ID) (uint, error) {
......
package group_s
import (
"context"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/_const/enum/gift_e"
"hilo-group/cv/gift_cv"
"hilo-group/domain/cache/room_c"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/res_m"
"sort"
"strconv"
"time"
)
func SortGroupCommonCountryList(model *domain.Model) {
// 常用的国家
countryMap := map[string]struct{}{"India": {}, "Indonesia": {}, "Iraq": {}, "KSA": {}, "Kuwait": {}, "Pakistan": {}, "Turkey": {}}
for country, _ := range countryMap {
sortGroupList, err := GetGroupSortList(model, country)
if err != nil {
model.Log.Errorf("SortGroupCommonCountryList err:%v", err)
return
}
// 写入redis
err = setToRedis(model, country, sortGroupList)
if err != nil {
model.Log.Errorf("SortGroupCommonCountryList country:%v, len(sortGroupList):%v, err:%v", country, len(sortGroupList), err)
return
}
time.Sleep(time.Second * 3)
}
}
func SortGroupNotCommonCountryList(model *domain.Model) {
// 常用的国家
countryMap := map[string]struct{}{"India": {}, "Indonesia": {}, "Iraq": {}, "KSA": {}, "Kuwait": {}, "Pakistan": {}, "Turkey": {}}
// 取所有的国家名字
allCountryList, err := res_m.GetCountryNameList(model)
if err != nil {
model.Log.Errorf("SortGroupNotCommonCountryList err:%v", err)
return
}
for _, country := range allCountryList {
if _, ok := countryMap[country]; ok {
continue
}
// 计算非常用国家
sortGroupList, err := GetGroupSortList(model, country)
if err != nil {
model.Log.Errorf("SortGroupNotCommonCountryList err:%v", err)
return
}
// 写入redis
err = setToRedis(model, country, sortGroupList)
if err != nil {
model.Log.Errorf("SortGroupNotCommonCountryList country:%v, len(sortGroupList):%v, err:%v", country, len(sortGroupList), err)
return
}
time.Sleep(time.Second * 5)
}
}
func setToRedis(model *domain.Model, country string, groupList []string) error {
// 写入redis
key := rediskey.GetGroupCountrySortList(country)
for idx, group := range groupList {
err := model.RedisCluster.ZRemRangeByRank(context.Background(), key, int64(idx), int64(idx)).Err() // 先删除旧的
if err != nil {
model.Log.Errorf("setToRedis SortGroup key:%v, idx:%v, err:%v", key, idx, err)
return err
}
// 插入
err = model.RedisCluster.ZAdd(context.Background(), key, &redis.Z{Score: float64(idx), Member: group}).Err()
if err != nil {
model.Log.Errorf("setToRedis SortGroup key:%v, idx:%v, group:%s, err:%v", key, idx, group, err)
return err
}
if idx%1000 == 0 {
time.Sleep(time.Millisecond * 50)
}
}
return nil
}
// 计算国家群组列表排序
func GetGroupSortList(model *domain.Model, country string) ([]string, error) {
bannedGroups, err := group_m.GetBannedGroupsMap(model)
if err != nil {
return nil, err
}
beginTime := time.Now()
groups, banCount, visitCount, err := GetCandidatesByCountry(model, bannedGroups, country)
if err != nil {
return nil, err
}
endTime := time.Now()
model.Log.Infof("GroupCountryListSort: candidates size = %d, takes %d ms banned = %d, visitCount size = %d",
len(groups), endTime.Sub(beginTime).Milliseconds(), banCount, len(visitCount))
// 获取麦上有人的所有群组及麦上人数
micGroupNum, err := group_m.GetMicHasInGroupNum(model)
if err != nil {
return nil, err
}
model.Log.Infof("GroupCountryListSort, micGroupNum : %v", micGroupNum)
model.Log.Infof("GroupCountryListSort cost2:%v", time.Now().Sub(beginTime))
sortedGroupIds := make([]string, 0)
diamondGroupIds := make([]string, 0)
for i, _ := range groups {
// 麦上没人也放出来
sortedGroupIds = append(sortedGroupIds, i)
// 麦上有人才计算流水
if micGroupNum[i] > 0 {
diamondGroupIds = append(diamondGroupIds, i)
}
}
now := time.Now()
bTime := now.Add(-time.Minute * 30)
g := gift_cv.GiftOperate{SceneType: gift_e.GroupSceneType}
diamonds, err := g.GetRangeConsumeSummaryV2(bTime, now, diamondGroupIds)
if err != nil {
return nil, err
}
model.Log.Infof("GroupCountryListSort, diamonds in 30 mins: %v", diamonds)
model.Log.Infof("GroupCountryListSort cost3:%v", time.Now().Sub(beginTime))
//supportLevels, err := NewGroupService(model.MyContext).GetWeekMaxSupportLevelMap()
//if err != nil {
// return nil, err
//}
//model.Log.Infof("GroupCountryListSort, supportLevels : %v", supportLevels)
model.Log.Infof("GroupCountryListSort cost4:%v", time.Now().Sub(beginTime))
// 排序优先级2022-07-25
sort.Slice(sortedGroupIds, func(i, j int) bool {
gi := sortedGroupIds[i]
gj := sortedGroupIds[j]
// 1、按麦上人数多少排序
if micGroupNum[gi] > micGroupNum[gj] {
return true
} else if micGroupNum[gi] < micGroupNum[gj] {
return false
}
// 2、麦上人数相同,按30分钟内送礼钻石数排序
if diamonds[gi] > diamonds[gj] {
return true
} else if diamonds[gi] < diamonds[gj] {
return false
}
// 3. 根据热度排序groupInUserDuration
if visitCount[gi] > visitCount[gj] {
return true
} else if visitCount[gi] < visitCount[gj] {
return false
}
// * Final resort: 群组CODE,短号优先,然后按字母序
return len(groups[gi].Code) < len(groups[gj].Code) || len(groups[gi].Code) == len(groups[gj].Code) && groups[gi].Code < groups[gj].Code
})
model.Log.Infof("GroupCountryListSort cost5:%v", time.Now().Sub(beginTime))
return sortedGroupIds, nil
}
// 国家群候选:没有密码且没被封禁的群, 有国家
func GetCandidatesByCountry(model *domain.Model, bannedGroups map[string]uint64, country string) (map[string]*group_m.GroupInfo, int, map[string]int64, error) {
noPwdGroups, err := group_m.FindOwnerCountryGroups(model, country)
if err != nil {
return nil, 0, nil, err
}
var groupIds []string
for _, v := range noPwdGroups {
groupIds = append(groupIds, v.ImGroupId) // imGroupId
}
//roomVisitCount, err := room_c.GetAllRoomVisitCount()
roomVisitCount, err := room_c.MGetRoomVisitCount(groupIds)
if err != nil {
return nil, 0, nil, err
}
gameRoom := group_m.GetGameGroupsMap(model)
banCount := 0
groups := make(map[string]*group_m.GroupInfo, 0)
visitCount := make(map[string]int64)
for i, v := range noPwdGroups {
// 过滤掉被封禁的群
if bannedGroups[v.ImGroupId] != 0 {
banCount++
continue
}
// 过滤游戏房
if gameRoom[v.ImGroupId] {
continue
}
// 先从二级缓存中找
if c, ok := roomVisitCount[v.ImGroupId]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
//model.Log.Debugf("getPopularCandidates, from roomVisitCount %s(%s) - %d", v.ImGroupId, v.Code, vc)
groups[v.ImGroupId] = &noPwdGroups[i]
visitCount[v.ImGroupId] = vc
}
} else {
// 如果没有,就从roomVisit中取
if vc, err := room_c.GetSetRoomVisitCount(v.ImGroupId); err == nil && vc > 0 {
model.Log.Infof("getPopularCandidates, from roomVisit %s(%s) - %d", v.ImGroupId, v.Code, vc)
groups[v.ImGroupId] = &noPwdGroups[i]
visitCount[v.ImGroupId] = vc
}
}
}
return groups, banCount, visitCount, nil
}
func GetVisitCount(groupIds []string) (map[string]int64, error) {
roomVisitCount, err := room_c.MGetRoomVisitCount(groupIds)
if err != nil {
return nil, err
}
visitCount := make(map[string]int64)
for _, v := range groupIds {
// 先从二级缓存中找
if c, ok := roomVisitCount[v]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
visitCount[v] = vc
}
} else {
// 如果没有,就从roomVisit中取
if vc, err := room_c.GetSetRoomVisitCount(v); err == nil && vc > 0 {
visitCount[v] = vc
}
}
}
return visitCount, nil
}
...@@ -17,7 +17,9 @@ import ( ...@@ -17,7 +17,9 @@ import (
"git.hilo.cn/hilo-common/utils" "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/msg_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/group_k"
"hilo-group/common" "hilo-group/common"
"hilo-group/cv/property_cv" "hilo-group/cv/property_cv"
"hilo-group/domain/cache/group_c" "hilo-group/domain/cache/group_c"
...@@ -32,6 +34,7 @@ import ( ...@@ -32,6 +34,7 @@ import (
"hilo-group/myerr" "hilo-group/myerr"
"hilo-group/myerr/bizerr" "hilo-group/myerr/bizerr"
"strconv" "strconv"
"strings"
"time" "time"
) )
...@@ -253,16 +256,10 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin ...@@ -253,16 +256,10 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin
var cpLevel int var cpLevel int
var cpUserAvatar string var cpUserAvatar string
var cpEntryEffect bool var cpEntryEffect bool
if cp, _ := rpc.GetUserCp(model, userId); cp != nil { if cp, _ := rpc.GetUserCpEntryEffect(model, userId); cp != nil {
cpLevel = cp.CpLevel.Level cpLevel = cp.CpLevel
if cp.CpUserInfo.Avatar != nil { cpUserAvatar = cp.CpUserAvatar
cpUserAvatar = *cp.CpUserInfo.Avatar cpEntryEffect = cp.CpEntryEffect
}
for _, v := range cp.MyPrivilegeList {
if v.Type == 5 {
cpEntryEffect = true
}
}
} }
r := UserParam{ r := UserParam{
Nick: user.Nick, Nick: user.Nick,
...@@ -327,7 +324,7 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin ...@@ -327,7 +324,7 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin
if err != nil { if err != nil {
return "", "", err return "", "", err
} else { } else {
go dealActDataAfterEnterRoom(s.svc.MyContext, userId, rideId, roomId) //go dealActDataAfterEnterRoom(s.svc.MyContext, userId, rideId, roomId)
return channelId, token, nil return channelId, token, nil
} }
} }
...@@ -515,3 +512,118 @@ func dealActDataAfterEnterRoom(myContext *mycontext.MyContext, userId, rideId ui ...@@ -515,3 +512,118 @@ func dealActDataAfterEnterRoom(myContext *mycontext.MyContext, userId, rideId ui
go rpc.AddActPoint(domain.CreateModelContext(myContext), userId, 5, roomId) go rpc.AddActPoint(domain.CreateModelContext(myContext), userId, 5, roomId)
} }
} }
// 创建房间,慎用
func (s *GroupService) CreateGroupMulByUid(userId uint64, num int, micNumType group_e.GroupMicNumType) error {
model := domain.CreateModel(s.svc.CtxAndDb)
if lock := redisCli.Lock(group_k.GetGroupLockKey(userId), time.Second*5); !lock {
return bizerr.ReqTooFrequent
}
user, err := user_m.GetUser(model, userId)
if err != nil {
model.Log.Errorf("CreateGroupMulByUid err:%v", err)
return err
}
// 强行修正为英语,以保证建群成功
user.Language = utils.DEFAULT_LANG
// 群组的头像默认为用户头像,群组的名称默认为用户昵称,群简介默认为“s%的群组”,群公告默认为“欢迎来到Hilo”
name := ""
text := res_m.ResMultiText{MsgId: msg_e.MSG_ID_GROUP_NAME, Language: user.Language}
if text.Get(model.Db) == nil {
name = strings.ReplaceAll(text.Content, "{nick}", user.Nick)
}
introduction := ""
text2 := res_m.ResMultiText{MsgId: msg_e.MSG_ID_GROUP_INTRODUCTION, Language: user.Language}
if text2.Get(model.Db) == nil {
introduction = strings.ReplaceAll(text2.Content, "{nick}", user.Nick)
}
notification := ""
text3 := res_m.ResMultiText{MsgId: msg_e.MSG_ID_GROUP_NOTIFICATION, Language: user.Language}
if text3.Get(model.Db) == nil {
notification = strings.ReplaceAll(text3.Content, "{nick}", user.Nick)
}
faceUrl := user.Avatar
for idx := 0; idx < num; idx++ {
code := group_m.GenerateGroupCode(group_e.GROUP_DEFAULT_CODE_LENGTH)
i := 0
for ; i < group_e.CREATE_GROUP_MAX_ATTEMPT; i++ {
success, err := res_m.CheckCode(model, code)
if err != nil || !success {
break
}
r, err := group_m.FindGroupByCode(model, code)
if err == nil && r == nil {
break
}
code = group_m.GenerateGroupCode(group_e.GROUP_DEFAULT_CODE_LENGTH)
}
if i >= group_e.CREATE_GROUP_MAX_ATTEMPT {
return myerr.NewSysError("Failed in generating groupId")
}
groupId := group_e.OverseaGroupNamePrefix + code
groupId, err = tencentyun.CreateGroup(name, groupId)
if err != nil {
model.Log.Errorf("CreateGroupMulByUid err:%v", err)
return err
}
channelId := utils.GetUUID()
_, _, err = agora.CreateGroupAgora(channelId, uint32(userId))
if err != nil {
// 回滚,删除刚刚建立的TX群组
tencentyun.DestroyGroup(groupId, false)
model.Log.Errorf("CreateGroupMulByUid err:%v", err)
return err
}
roomType := group_e.OverseaRoom
g := group_m.GroupInfo{
ImGroupId: groupId,
TxGroupId: groupId,
Type: uint16(roomType),
Code: code,
OriginCode: code,
Owner: userId,
Name: name,
Introduction: introduction,
Notification: notification,
FaceUrl: faceUrl,
Country: user.Country,
ChannelId: channelId,
MicOn: true,
LoadHistory: false,
MicNumType: micNumType,
TouristMic: 1,
TouristSendMsg: 1,
TouristSendPic: 1,
IsGameRoom: 1,
}
if err := s.CreateGroup(userId, &g); err != nil {
// 回滚,删除刚刚建立的TX群组
tencentyun.DestroyGroup(groupId, false)
model.Log.Errorf("CreateGroupMulByUid err:%v", err)
return err
}
gm := group_m.GroupMember{
GroupId: groupId,
UserId: userId,
}
if err = gm.Create(model.Db); err != nil {
model.Log.Warnf("Failed to set GroupMember +%v", gm)
}
time.Sleep(time.Millisecond * 30)
}
return nil
}
package group_s package group_s
import ( import (
"context"
"git.hilo.cn/hilo-common/_const/enum/msg_e"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"github.com/go-redis/redis/v8"
"hilo-group/_const/enum/gift_e" "hilo-group/_const/enum/gift_e"
"hilo-group/domain/event/group_ev" "hilo-group/domain/event/group_ev"
"hilo-group/domain/model/gift_m" "hilo-group/domain/model/gift_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/msg_m"
"hilo-group/domain/model/res_m" "hilo-group/domain/model/res_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/myerr/bizerr" "strconv"
"time" "time"
) )
// 群组支持名单过滤 // 群组支持名单过滤
func (s *GroupService) GroupSupportList(groupId string, uids []uint64) ([]uint64, []uint64, error) { func (s *GroupService) GroupSupportList(groupId string, uids []uint64, supportLevel uint32) ([]uint64, []uint64, error) {
if len(uids) <= 0 { if len(uids) <= 0 {
return uids, nil, nil return uids, nil, nil
} }
...@@ -21,86 +28,157 @@ func (s *GroupService) GroupSupportList(groupId string, uids []uint64) ([]uint64 ...@@ -21,86 +28,157 @@ func (s *GroupService) GroupSupportList(groupId string, uids []uint64) ([]uint64
result := make([]uint64, 0) result := make([]uint64, 0)
out := make([]uint64, 0) out := make([]uint64, 0)
err := s.svc.Transactional(func() error { model := domain.CreateModel(s.svc.CtxAndDb)
model := domain.CreateModel(s.svc.CtxAndDb)
// 1. 去掉非群管理者 // 1. 去掉非群管理者
roles, _, err := group_m.GetRolesInGroup(model, groupId) roles, _, err := group_m.GetRolesInGroup(model, groupId)
if err != nil { if err != nil {
return err model.Log.Errorf("GroupSupportList groupId:%v, uids:%v, err:%v", groupId, uids, err)
} return nil, nil, err
userIds := make([]uint64, 0) }
for _, i := range uids { userIds := make([]uint64, 0)
if _, ok := roles[i]; ok { for _, i := range uids {
userIds = append(userIds, i) if _, ok := roles[i]; ok {
} else { userIds = append(userIds, i)
out = append(out, i) } else {
model.Log.Infof("GroupSupportList: rule out %d, no role", i) out = append(out, i)
} model.Log.Infof("GroupSupportList: rule out %d, no role", i)
} }
}
// TODO: 去掉非群成员 // TODO: 去掉非群成员
//(4)1个账户只能做1个群组的管理员(5)1个设备下只允许领取1个管理奖励
_, _, period := group_m.GetLastSupportPeriod(time.Now())
gsa := group_m.GroupSupportAwardMgr{Period: period}
rows, err := gsa.Get(model.Db)
if err != nil {
model.Log.Errorf("GroupSupportList groupId:%v, uids:%v, err:%v", groupId, uids, err)
return nil, nil, err
}
awards := make(map[uint64]struct{}, 0)
for _, i := range rows {
awards[i.UserId] = struct{}{}
}
//(4)1个账户只能做1个群组的管理员(5)1个设备下只允许领取1个管理奖励 uids = userIds
_, _, period := group_m.GetLastSupportPeriod(time.Now()) userIds = make([]uint64, 0)
gsa := group_m.GroupSupportAwardMgr{Period: period} m := make(map[uint64]uint64)
rows, err := gsa.Get(model.Db) for _, u := range uids {
m, err := user_m.GetSameImeiMap(model, u)
if err != nil { if err != nil {
return err model.Log.Errorf("GroupSupportList groupId:%v, uids:%v, err:%v", groupId, uids, err)
return nil, nil, err
} }
awards := make(map[uint64]struct{}, 0)
for _, i := range rows {
awards[i.UserId] = struct{}{}
}
uids = userIds
userIds = make([]uint64, 0)
m := make(map[uint64]uint64)
for _, u := range uids {
m, err := user_m.GetSameImeiMap(model, u)
if err != nil {
return err
}
passed := true passed := true
for _, i := range m { for _, i := range m {
if _, ok := awards[i]; ok { if _, ok := awards[i]; ok {
if i == u { if i == u {
passed = false passed = false
model.Log.Infof("GroupSupportList: rule out %d, already awarded", i) model.Log.Infof("GroupSupportList: rule out %d, already awarded", i)
} else { } else {
passed = false passed = false
model.Log.Infof("GroupSupportList: rule out %d, imei awarded", i) model.Log.Infof("GroupSupportList: rule out %d, imei awarded", i)
}
} }
} }
if passed == true {
userIds = append(userIds, u)
} else {
out = append(out, u)
}
} }
model.Log.Infof("GroupSupportList: uids %v, map %v", uids, m) if passed == true {
userIds = append(userIds, u)
_, supportLevel, err := s.GetSupportLevel(groupId) } else {
if err != nil { out = append(out, u)
return err
} }
}
model.Log.Infof("GroupSupportList: uids %v, map %v", uids, m)
if uint32(len(userIds)) > supportLevel { if uint32(len(userIds)) > supportLevel {
model.Log.Infof("GroupSupportList: rule out %v, limit exeeded", userIds[supportLevel:]) model.Log.Infof("GroupSupportList: rule out %v, limit exeeded", userIds[supportLevel:])
out = append(out, userIds[supportLevel:]...) out = append(out, userIds[supportLevel:]...)
userIds = userIds[0:supportLevel] userIds = userIds[0:supportLevel]
}
result = userIds
return nil
})
if err == nil {
return result, out, nil
} else {
return nil, nil, err
} }
result = userIds
return result, out, nil
//err := s.svc.Transactional(func() error {
// model := domain.CreateModel(s.svc.CtxAndDb)
//
// // 1. 去掉非群管理者
// roles, _, err := group_m.GetRolesInGroup(model, groupId)
// if err != nil {
// return err
// }
// userIds := make([]uint64, 0)
// for _, i := range uids {
// if _, ok := roles[i]; ok {
// userIds = append(userIds, i)
// } else {
// out = append(out, i)
// model.Log.Infof("GroupSupportList: rule out %d, no role", i)
// }
// }
//
// // TODO: 去掉非群成员
//
// //(4)1个账户只能做1个群组的管理员(5)1个设备下只允许领取1个管理奖励
// _, _, period := group_m.GetLastSupportPeriod(time.Now())
// gsa := group_m.GroupSupportAwardMgr{Period: period}
// rows, err := gsa.Get(model.Db)
// if err != nil {
// return err
// }
// awards := make(map[uint64]struct{}, 0)
// for _, i := range rows {
// awards[i.UserId] = struct{}{}
// }
//
// uids = userIds
// userIds = make([]uint64, 0)
// m := make(map[uint64]uint64)
// for _, u := range uids {
// m, err := user_m.GetSameImeiMap(model, u)
// if err != nil {
// return err
// }
//
// passed := true
// for _, i := range m {
// if _, ok := awards[i]; ok {
// if i == u {
// passed = false
// model.Log.Infof("GroupSupportList: rule out %d, already awarded", i)
// } else {
// passed = false
// model.Log.Infof("GroupSupportList: rule out %d, imei awarded", i)
// }
// }
// }
// if passed == true {
// userIds = append(userIds, u)
// } else {
// out = append(out, u)
// }
// }
// model.Log.Infof("GroupSupportList: uids %v, map %v", uids, m)
//
// _, supportLevel, err := s.GetSupportLevel(groupId)
// if err != nil {
// return err
// }
//
// if uint32(len(userIds)) > supportLevel {
// model.Log.Infof("GroupSupportList: rule out %v, limit exeeded", userIds[supportLevel:])
// out = append(out, userIds[supportLevel:]...)
// userIds = userIds[0:supportLevel]
// }
// result = userIds
// return nil
//})
//
//if err == nil {
// return result, out, nil
//} else {
// return nil, nil, err
//}
} }
func (s *GroupService) GetSupportLevel(groupId string) (uint64, uint32, error) { func (s *GroupService) GetSupportLevel(groupId string) (uint64, uint32, error) {
...@@ -124,17 +202,50 @@ func (s *GroupService) GetSupportLevel(groupId string) (uint64, uint32, error) { ...@@ -124,17 +202,50 @@ func (s *GroupService) GetSupportLevel(groupId string) (uint64, uint32, error) {
return 0, 0, nil return 0, 0, nil
} }
func (s *GroupService) GetSupportLevelByRedis(groupId string) (*res_m.ResGroupSupport, uint32, error) {
model := domain.CreateModel(s.svc.CtxAndDb)
_, _, period := group_m.GetLastSupportPeriod(time.Now())
consume, count, err := GetGroupConsumeCount(model, groupId, period)
if err != nil {
return nil, 0, err
}
rec, err := res_m.GetResGroupSupportBy(model, count, consume)
if err != nil {
return nil, 0, err
}
if rec != nil {
return rec, rec.MgrNum, nil
}
return rec, 0, nil
}
func GetGroupConsumeCount(model *domain.Model, imGroupId, period string) (uint64, uint32, error) {
// 流水
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
consume, err := model.RedisCluster.ZScore(context.Background(), keyDiamond, imGroupId).Result()
if err != nil && err != redis.Nil {
model.Log.Errorf("GetSupportLevelByRedis key:%v, groupId:%v, err:%v", keyDiamond, imGroupId, err)
return 0, 0, err
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, imGroupId)
count, err := model.RedisCluster.SCard(context.Background(), keySupportNum).Result()
if err != nil && err != redis.Nil {
model.Log.Errorf("GetSupportLevelByRedis key:%v, groupId:%v, err:%v", keySupportNum, imGroupId, err)
return 0, 0, err
}
return uint64(consume), uint32(count), nil
}
//群组支持奖励 //群组支持奖励
func (s *GroupService) GroupSupportAward(groupId string, profitAllocator uint64, userIds []uint64, resId uint64, period string) error { func (s *GroupService) GroupSupportAward(groupId string, profitAllocator uint64, userIds []uint64, resSupport *res_m.ResGroupSupport,
period string, groupInfo *group_m.GroupInfo) error {
return s.svc.Transactional(func() error { return s.svc.Transactional(func() error {
model := domain.CreateModel(s.svc.CtxAndDb) model := domain.CreateModel(s.svc.CtxAndDb)
//
groupInfo, err := group_m.GetGroupInfo(model, groupId)
if groupInfo == nil {
return bizerr.GroupNotFound
}
//发放奖励 //发放奖励
groupSupportAwardAdmin, groupSupportAwardMgrs, err := group_m.AddGroupSupportAward(model, groupId, profitAllocator, resId, userIds, period) groupSupportAwardAdmin, groupSupportAwardMgrs, err := group_m.AddGroupSupportAward(model, groupId, profitAllocator, resSupport, userIds, period)
if err != nil { if err != nil {
return err return err
} }
...@@ -173,3 +284,128 @@ func (s *GroupService) RenewGroupSupporter(groupId string, userIds []uint64) err ...@@ -173,3 +284,128 @@ func (s *GroupService) RenewGroupSupporter(groupId string, userIds []uint64) err
return nil return nil
}) })
} }
func (s *GroupService) GroupSupportResult(time time.Time) error {
model := domain.CreateModelContext(s.svc.MyContext)
_, _, period := group_m.GetSupportLevelTime(time)
// 群组扶持数值
groupGradeMap, err := getGroupGradeMap(model, period)
if err != nil {
model.Log.Errorf("GroupSupportResult time:%v, err:%v", time, err)
return err
}
model.Log.Infof("GroupSupportResult period:%s, len:%d, groupUidGadeMap:%v", period, len(groupGradeMap), groupGradeMap)
// 房间访问人数
roomVisitCount, err := GetAllRoomNonZeroVisitCount()
if err != nil {
model.Log.Errorf("GroupSupportResult err:%v", err)
return err
}
// 入库群组扶持结果
for g, grade := range groupGradeMap {
r := group_m.InitGroupSupportResult(model, g, grade, period, roomVisitCount[g])
r.SetOnDuplicateKeyIGNORE()
if err = r.Persistent(); err != nil {
model.Log.Errorf("GroupSupportResult InitGroupSupportResult r:%+v, err:%v", r, err)
}
}
// 小助手通知
AssistantNotification(model, groupGradeMap)
return nil
}
func getGroupGradeMap(model *domain.Model, period string) (map[string]uint8, error) {
// 配置
gsConfig, err := res_m.GetResGroupSupportByValid(model)
if err != nil {
model.Log.Errorf("GroupSupportResult err:%v", err)
return nil, err
}
// 群组扶持数值
groupGradeMap := make(map[string]uint8, 0)
//userNum := make(map[string]uint32, 0)
// 流水
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
var start int64
count := int64(999)
var zList []redis.Z
// 一次取1000个处理
for start == 0 || len(zList) > 0 {
stop := start + count
zList, err = model.RedisCluster.ZRangeWithScores(context.Background(), keyDiamond, start, stop).Result()
if err != nil {
model.Log.Errorf("GroupSupportResult err:%v", err)
return nil, err
}
if len(zList) == 0 {
break
}
for _, v := range zList {
imGroupId := v.Member.(string)
consume := mysql.Num(v.Score)
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, imGroupId)
supportNum, err := model.RedisCluster.SCard(context.Background(), keySupportNum).Result()
if err != nil {
model.Log.Errorf("GroupSupportResult key:%s, err:%v", keySupportNum, err)
return nil, err
}
for j := len(gsConfig) - 1; j >= 0; j-- {
if mysql.Num(supportNum) >= gsConfig[j].ContributeUserNum && consume >= gsConfig[j].ContributeDiamondNum {
groupGradeMap[imGroupId] = gsConfig[j].Grade
//userNum[imGroupId] = uint32(supportNum)
break
}
}
}
start = stop + 1
}
return groupGradeMap, nil
}
func AssistantNotification(model *domain.Model, groupGradeMap map[string]uint8) {
// 小助手通知
for g, _ := range groupGradeMap {
userId, err := group_m.GetProfitAllocator(model, g)
if err != nil {
model.Log.Errorf("GroupSupportResult msg GetProfitAllocator err:%v, groupUid:%v", err, g)
continue
}
//推送
user, err := user_m.GetUser(model, userId)
if err != nil {
model.Log.Infof("GroupSupportResult msg GetUser userId:=%v, err:=%v", userId, err)
continue
}
record := msg_m.NewUserRecord(model, user.ID, msg_e.GroupSupportResult, "", 0, "", "", "", "", "")
if err := record.Persistent(); err != nil {
model.Log.Infof("GroupSupportResult msg record.Persistent() err:%v", err)
continue
}
msg_m.SendEmasMsgAssistant(model, user.ExternalId, user.DeviceType)
}
}
func GetAllRoomNonZeroVisitCount() (map[string]uint, error) {
m, err := GetAllRoomVisitCount()
if err != nil {
return nil, err
}
result := make(map[string]uint, 0)
for g, s := range m {
if c, err := strconv.Atoi(s); err == nil && c > 0 {
result[g] = uint(c)
}
}
return result, nil
}
func GetAllRoomVisitCount() (map[string]string, error) {
key := rediskey.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HGetAll(context.Background(), key).Result()
}
...@@ -93,6 +93,7 @@ require ( ...@@ -93,6 +93,7 @@ require (
github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 // indirect github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // 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/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.6 // indirect golang.org/x/text v0.3.6 // indirect
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e // 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 ...@@ -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-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-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.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-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-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
......
...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=47.244.34.27:6379 REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT] [JWT]
SECRET=hilo1632 SECRET=hilo1632
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
...@@ -3,6 +3,7 @@ package main ...@@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"git.hilo.cn/hilo-common/resource/consul" "git.hilo.cn/hilo-common/resource/consul"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-group/cron" "hilo-group/cron"
"hilo-group/domain/service/event_s" "hilo-group/domain/service/event_s"
"hilo-group/route" "hilo-group/route"
...@@ -17,6 +18,7 @@ const ( ...@@ -17,6 +18,7 @@ const (
func main() { func main() {
cron.Init() // 开启定时任务 cron.Init() // 开启定时任务
event_s.EventInit() // 注册事件(内部事件+mysql拟kafka) event_s.EventInit() // 注册事件(内部事件+mysql拟kafka)
redisCli.InitCluster() // redis集群
r := route.InitRouter() // 注册路由 r := route.InitRouter() // 注册路由
consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册 consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册
r.Run(fmt.Sprintf(":%d", PORT)) // 启动服务 r.Run(fmt.Sprintf(":%d", PORT)) // 启动服务
......
...@@ -69,7 +69,7 @@ var ( ...@@ -69,7 +69,7 @@ var (
GroupCustomThemeLimit = myerr.NewBusinessCode(14020, "Group Custom Theme Limit", myerr.BusinessData{}) //群主题定制数量只能是5个 GroupCustomThemeLimit = myerr.NewBusinessCode(14020, "Group Custom Theme Limit", myerr.BusinessData{}) //群主题定制数量只能是5个
GroupSupportIpLimit = myerr.NewBusinessCode(14024, "ID:%v is a duplicate account, please select another user to receive the reward", myerr.BusinessData{}) // 群组扶持ip限制 GroupSupportIpLimit = myerr.NewBusinessCode(14024, "ID:%v is a duplicate account, please select another user to receive the reward", myerr.BusinessData{}) // 群组扶持ip限制
GroupNoPowerToSvip6 = myerr.NewBusinessCode(14026, "Cannot use this permission for SVIP6", myerr.BusinessData{}) // 踢出,无法对SVIP6使用此权限 GroupNoPowerToSvip6 = myerr.NewBusinessCode(14026, "Cannot use this permission for SVIP6", myerr.BusinessData{}) // 踢出,无法对SVIP6使用此权限
GroupSupportWealthLevel8 = myerr.NewBusinessCode(14027, "Wealth level not reach 8", myerr.BusinessData{}) // 财富等级8 GroupSupportWealthLevel3 = myerr.NewBusinessCode(14027, "Wealth level not reach 3", myerr.BusinessData{}) // 财富等级3
// 家族 // 家族
GroupPowerHasJoinOther = myerr.NewBusinessCode(15001, "You already have joined power, please exit first", myerr.BusinessData{}) // 已经加入了其它国家势力 GroupPowerHasJoinOther = myerr.NewBusinessCode(15001, "You already have joined power, please exit first", myerr.BusinessData{}) // 已经加入了其它国家势力
......
[DATABASE] [DATABASE]
MYSQL_HOST=ua4papc3hmgqf351pbej-rw4rm.rwlb.dubai.rds.aliyuncs.com MYSQL_HOST=ua4papc3hmgqf351pbej-rw4rm.rwlb.dubai.rds.aliyuncs.com
MYSQL_USERNAME=nextvideo MYSQL_USERNAME=hilo_group
MYSQL_PASSWORD=ihlUwI4nhi9W88MI MYSQL_PASSWORD=ihlUwI4nhi9W88MI
MYSQL_DB=hilo MYSQL_DB=hilo
[DATABASECODE] [DATABASECODE]
...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=r-eb3btxn8vfdsuwdbuf.redis.dubai.rds.aliyuncs.com:6379 REDIS_HOST=r-eb3btxn8vfdsuwdbuf.redis.dubai.rds.aliyuncs.com:6379
REDIS_PASSWORD= REDIS_PASSWORD=
REDIS_CLUSTER_HOST=r-eb3yt6k8zgxs62kjjs.redis.dubai.rds.aliyuncs.com:6379
REDIS_CLUSTER_PASSWORD=
[JWT] [JWT]
SECRET=hilo1504 SECRET=hilo1504
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"hilo-group/myerr" "hilo-group/myerr"
"net/http" "net/http"
...@@ -16,6 +17,7 @@ type Response struct { ...@@ -16,6 +17,7 @@ type Response struct {
MessageData interface{} `json:"messageData"` // 消息详情 MessageData interface{} `json:"messageData"` // 消息详情
OperationMessage interface{} `json:"operationMessage"` // 操作消息 OperationMessage interface{} `json:"operationMessage"` // 操作消息
Data interface{} `json:"data"` // 数据 Data interface{} `json:"data"` // 数据
Edata interface{} `json:"edata"` // 数据
} }
/** /**
...@@ -30,7 +32,12 @@ func ResponseOk(c *gin.Context, data interface{}) { ...@@ -30,7 +32,12 @@ func ResponseOk(c *gin.Context, data interface{}) {
Code: myerr.GetSuccessCode(), Code: myerr.GetSuccessCode(),
Message: myerr.GetSuccessMsg(), Message: myerr.GetSuccessMsg(),
OperationMessage: myerr.GetSuccessMsg(), OperationMessage: myerr.GetSuccessMsg(),
Data: data, }
if _, ok := c.Get(mycontext.InnerEncrypt); ok {
//response.Edata = utils.EncryptionData(data, []byte("484194d4d0f968a7"))
response.Edata = utils.EncryptionData(data, []byte("hilo!@#$%^&*()_+"))
} else {
response.Data = data
} }
printResponseBody(c, &response) printResponseBody(c, &response)
...@@ -116,15 +123,21 @@ type Page struct { ...@@ -116,15 +123,21 @@ type Page struct {
func ResponsePageOk(c *gin.Context, data interface{}, total uint, index int) { func ResponsePageOk(c *gin.Context, data interface{}, total uint, index int) {
// always return http.StatusOK // always return http.StatusOK
pageData := Page{
Total: total,
Index: index,
Data: data,
}
response := Response{ response := Response{
Code: myerr.GetSuccessCode(), Code: myerr.GetSuccessCode(),
Message: myerr.GetSuccessMsg(), Message: myerr.GetSuccessMsg(),
OperationMessage: myerr.GetSuccessMsg(), OperationMessage: myerr.GetSuccessMsg(),
Data: Page{ }
Total: total, if _, ok := c.Get(mycontext.InnerEncrypt); ok {
Index: index, //response.Edata = utils.EncryptionData(data, []byte("484194d4d0f968a7"))
Data: data, response.Edata = utils.EncryptionData(pageData, []byte("hilo!@#$%^&*()_+"))
}, } else {
response.Data = pageData
} }
printResponseBody(c, &response) printResponseBody(c, &response)
...@@ -149,15 +162,21 @@ func ResponsePageBaseOk(c *gin.Context, data interface{}, nextPageIndex int, has ...@@ -149,15 +162,21 @@ func ResponsePageBaseOk(c *gin.Context, data interface{}, nextPageIndex int, has
if data == nil { if data == nil {
data = make([]interface{}, 0) data = make([]interface{}, 0)
} }
pageData := PageRespBase{
NextPageIndex: nextPageIndex,
HasNextPage: hasNextPage,
Data: data,
}
response := Response{ response := Response{
Code: myerr.GetSuccessCode(), Code: myerr.GetSuccessCode(),
Message: myerr.GetSuccessMsg(), Message: myerr.GetSuccessMsg(),
OperationMessage: myerr.GetSuccessMsg(), OperationMessage: myerr.GetSuccessMsg(),
Data: PageRespBase{ }
NextPageIndex: nextPageIndex, if _, ok := c.Get(mycontext.InnerEncrypt); ok {
HasNextPage: hasNextPage, //response.Edata = utils.EncryptionData(data, []byte("484194d4d0f968a7"))
Data: data, response.Edata = utils.EncryptionData(pageData, []byte("hilo!@#$%^&*()_+"))
}, } else {
response.Data = pageData
} }
c.JSON(http.StatusOK, response) c.JSON(http.StatusOK, response)
} }
...@@ -47,8 +47,9 @@ func CanShareChargeLink(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -47,8 +47,9 @@ func CanShareChargeLink(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err return myContext, err
} }
type res struct { type res struct {
ShareUrl string `json:"shareUrl"` ShareUrl string `json:"shareUrl"`
ShareIcon string `json:"shareIcon"` ShareIcon string `json:"shareIcon"`
RechargeUrl string `json:"rechargeUrl"`
} }
// 安卓3.8.0版本有bug,这里暂时兼容 // 安卓3.8.0版本有bug,这里暂时兼容
...@@ -57,16 +58,17 @@ func CanShareChargeLink(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -57,16 +58,17 @@ func CanShareChargeLink(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
myUser, err := user_c.GetUserTinyById(model, userId)
if err != nil {
return myContext, err
}
if deviceType == "android" { if deviceType == "android" {
if (major > 3) || (major == 3 && minor >= 8) { if (major > 3) || (major == 3 && minor >= 8) {
myUser, err := user_c.GetUserTinyById(model, userId)
if err != nil {
return myContext, err
}
shareUrl = shareUrl + myUser.ExternalId shareUrl = shareUrl + myUser.ExternalId
} }
} }
rechargeUrl := config.GetH5Config().AGENT_SHARE_URL + myUser.ExternalId
resp.ResponseOk(c, res{shareUrl, config.GetH5Config().AGENT_SHARE_ICON}) resp.ResponseOk(c, res{shareUrl, config.GetH5Config().AGENT_SHARE_ICON, rechargeUrl})
return myContext, nil return myContext, nil
} }
...@@ -23,6 +23,7 @@ import ( ...@@ -23,6 +23,7 @@ import (
"hilo-group/cv/group_power_cv" "hilo-group/cv/group_power_cv"
"hilo-group/cv/medal_cv" "hilo-group/cv/medal_cv"
"hilo-group/cv/user_cv" "hilo-group/cv/user_cv"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/cache/res_c" "hilo-group/domain/cache/res_c"
"hilo-group/domain/cache/user_c" "hilo-group/domain/cache/user_c"
"hilo-group/domain/model/game_m" "hilo-group/domain/model/game_m"
...@@ -820,7 +821,7 @@ func GroupPowerInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -820,7 +821,7 @@ func GroupPowerInfo(c *gin.Context) (*mycontext.MyContext, error) {
} }
} }
// 补上家族之星三个榜一 // 补上家族之星三个榜一
stars, err := groupPower_m.GetGroupPowerMonthStartTop1(model, gp.ID) stars, err := groupPower_c.GetGroupPowerMonthStartTop1(model, gp.ID)
if err != nil { if err != nil {
return myContext, myerr.WrapErr(err) return myContext, myerr.WrapErr(err)
} }
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/groupPower_e"
"hilo-group/cv/group_power_cv" "hilo-group/cv/group_power_cv"
"hilo-group/cv/user_cv" "hilo-group/cv/user_cv"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_power_s" "hilo-group/domain/service/group_power_s"
...@@ -264,7 +265,7 @@ func GroupPowerStarPeriod(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -264,7 +265,7 @@ func GroupPowerStarPeriod(c *gin.Context) (*mycontext.MyContext, error) {
} }
var model = domain.CreateModelContext(myContext) var model = domain.CreateModelContext(myContext)
offset, limit := (param.PageIndex-1)*param.PageSize, param.PageSize offset, limit := (param.PageIndex-1)*param.PageSize, param.PageSize
rank, err := groupPower_m.GetGroupPowerStarRankPeriod(model, period, param.GroupPowerId, param.Type, offset, limit) rank, err := groupPower_c.GetGroupPowerStarRankPeriod(model, period, param.GroupPowerId, param.Type, offset, limit)
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
......
package group_power_r package group_power_r
import ( import (
"fmt"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/jinzhu/now"
"hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/enum/msg_e" "hilo-group/_const/enum/msg_e"
"hilo-group/_const/redis_key/groupPower_k"
"hilo-group/cv/group_power_cv" "hilo-group/cv/group_power_cv"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/msg_m" "hilo-group/domain/model/msg_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_power_s" "hilo-group/domain/service/group_power_s"
"hilo-group/myerr/bizerr"
"hilo-group/resp" "hilo-group/resp"
"time"
) )
type MGetGroupPowerReq struct { type MGetGroupPowerReq struct {
...@@ -93,3 +98,66 @@ func Test(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -93,3 +98,66 @@ func Test(c *gin.Context) (*mycontext.MyContext, error) {
//} //}
return nil, nil return nil, nil
} }
type GroupPowerDayStar struct {
Date time.Time
GroupPowerId uint64
Type groupPower_e.GroupPowerStarType
UserId uint64
Score uint64
}
// @Tags 国家势力-内部
// @Summary 同步家族之星到redis
// @Success 200
// @Router /inner/groupPower/sync/star [get]
func SyncStar(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
t := time.Now()
start := c.Query("start")
end := c.Query("end")
if len(start) <= 0 || len(end) <= 0 {
return myCtx, bizerr.InvalidParameter
}
var model = domain.CreateModelContext(myCtx)
var stars []GroupPowerDayStar
if err := model.DB().Table("group_power_day_star").
Select("`date`,group_power_id,type,user_id,SUM(score) score").
Where("`date` BETWEEN ? AND ?", start, end).
Group("`date`,group_power_id,type,user_id").Find(&stars).Error; err != nil {
model.Log.Errorf("SyncStar fail:%v", err)
return myCtx, err
}
ttl := map[string]time.Duration{
"day": time.Hour * 24 * 7,
"week": time.Hour * 24 * 7 * 30,
"month": time.Hour * 24 * 7 * 30 * 2,
}
num := len(stars)
for i, star := range stars {
for _, period := range []string{"day", "week", "month"} {
var dateStr string
switch period {
case "day":
dateStr = star.Date.Format("2006-01-02")
case "week":
dateStr = now.With(star.Date).BeginningOfWeek().Format("2006-01-02")
case "month":
dateStr = now.With(star.Date).BeginningOfMonth().Format("2006-01-02")
}
key := groupPower_k.GetGroupPowerStarRankKey(star.Type, period, star.GroupPowerId, dateStr)
model.RedisCluster.ZIncrBy(model, key, float64(star.Score), fmt.Sprintf("%d", star.UserId))
model.RedisCluster.Expire(model, key, ttl[period])
model.Log.Infof("SyncStar i:%v,star:%v", i, star)
}
}
type res struct {
Num int
Cost float64
}
resp.ResponseOk(c, res{
Num: num,
Cost: time.Now().Sub(t).Seconds(),
})
return myCtx, nil
}
...@@ -211,7 +211,7 @@ func GetTheirGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -211,7 +211,7 @@ func GetTheirGroups(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
model.Log.Infof("BuildJoinedGroupInfo, roomEnterTime: %v", roomEnterTime) //model.Log.Infof("BuildJoinedGroupInfo, roomEnterTime: %v", roomEnterTime)
// 正在进行的游戏 // 正在进行的游戏
games := game_m.GetNotEndGamesMap(model) games := game_m.GetNotEndGamesMap(model)
...@@ -374,7 +374,7 @@ func PluginReady(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -374,7 +374,7 @@ func PluginReady(c *gin.Context) (*mycontext.MyContext, error) {
// @Router /v1/imGroup/roomInfo/{groupId} [get] // @Router /v1/imGroup/roomInfo/{groupId} [get]
func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) { func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys) myContext := mycontext.CreateMyContext(c.Keys)
start := time.Now()
groupId := c.Param("groupId") groupId := c.Param("groupId")
if len(groupId) <= 0 { if len(groupId) <= 0 {
return myContext, myerr.NewSysError("groupId 为必填项") return myContext, myerr.NewSysError("groupId 为必填项")
...@@ -407,7 +407,8 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -407,7 +407,8 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
deviceType, appVersion := cast.ToString(_deviceType), cast.ToString(_appVersion) deviceType, appVersion := cast.ToString(_deviceType), cast.ToString(_appVersion)
vc := version_m.GetVersionControlByPlatform(model, deviceType) vc := version_m.GetVersionControlByPlatform(model, deviceType)
allow, err := utils.CompareVersion(appVersion, fmt.Sprintf("<= %s", vc.AuditVersion)) allow, err := utils.CompareVersion(appVersion, fmt.Sprintf("<= %s", vc.AuditVersion))
model.Log.Infof("GetRoomInfo CompareVersion appVersion:%v,auditVersion:%v,allow:%v,err:%v", appVersion, vc.AuditVersion, allow, err)
model.Log.Infof("GetRoomInfo cost 0:%v", time.Now().Sub(start).Seconds())
themeUrl := "" themeUrl := ""
var themeId uint64 = 0 var themeId uint64 = 0
...@@ -457,10 +458,15 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -457,10 +458,15 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
ThemeUrl: themeUrl, ThemeUrl: themeUrl,
ThemeType: themeType, ThemeType: themeType,
Role: group_e.GROUP_VISITOR, Role: group_e.GROUP_VISITOR,
GameConfig: &game_m.GameConfig{Ludo: &game_m.GameConfigDiamond{Diamond: game_e.GameLudoDiamondList}, Uno: &game_m.GameConfigDiamond{Diamond: game_e.GameLudoDiamondList}}, GameConfig: &game_m.GameConfig{
Ludo: &game_m.GameConfigDiamond{Diamond: game_e.GameLudoDiamondList},
Uno: &game_m.GameConfigDiamond{Diamond: game_e.GameLudoDiamondList},
Domino: &game_m.GameConfigDiamond{Diamond: game_e.GameLudoDiamondList},
},
} }
roles, _, err := group_m.GetRolesInGroup(model, groupInfo.ImGroupId) model.Log.Infof("GetRoomInfo cost 1:%v", time.Now().Sub(start).Seconds())
roles, orderList, err := group_m.GetRolesInGroup(model, groupId)
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
...@@ -503,11 +509,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -503,11 +509,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
} }
} }
roles, orderList, err := group_m.GetRolesInGroup(model, groupId) model.Log.Infof("GetRoomInfo cost 2:%v", time.Now().Sub(start).Seconds())
if err != nil {
return myContext, err
}
users, err := user_cv.GetUserTinyMap(orderList) users, err := user_cv.GetUserTinyMap(orderList)
if err != nil { if err != nil {
return myContext, err return myContext, err
...@@ -545,6 +547,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -545,6 +547,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
} }
result.WelcomeText = strings.ReplaceAll(result.WelcomeText, "@%s", "") result.WelcomeText = strings.ReplaceAll(result.WelcomeText, "@%s", "")
model.Log.Infof("GetRoomInfo cost 3:%v", time.Now().Sub(start).Seconds())
// 补上房间流水勋章 // 补上房间流水勋章
var pe *medal_cv.PicElement var pe *medal_cv.PicElement
result.TotalConsume, pe, err = medal_cv.GetGroupConsumeMedal(model, groupId) result.TotalConsume, pe, err = medal_cv.GetGroupConsumeMedal(model, groupId)
...@@ -554,7 +557,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -554,7 +557,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
result.GroupMedals = append(result.GroupMedals, medal_cv.PicElement{PicUrl: pe.PicUrl}) result.GroupMedals = append(result.GroupMedals, medal_cv.PicElement{PicUrl: pe.PicUrl})
} }
resMedals := []res_m.ResMedal{} var resMedals []res_m.ResMedal
err = mysql.Db.Model(&res_m.ResMedal{}). err = mysql.Db.Model(&res_m.ResMedal{}).
Joins("INNER JOIN group_medal m ON m.res_medal_id = res_medal.id"). Joins("INNER JOIN group_medal m ON m.res_medal_id = res_medal.id").
Where("m.im_group_id = ?", groupId). Where("m.im_group_id = ?", groupId).
...@@ -569,8 +572,9 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -569,8 +572,9 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
}) })
} }
} else { } else {
model.Log.Infof("GetRoomInfo: group_medal: %s", err.Error()) model.Log.Errorf("GetRoomInfo: group_medal: %s", err.Error())
} }
model.Log.Infof("GetRoomInfo cost 4:%v", time.Now().Sub(start).Seconds())
// 获取国家信息 // 获取国家信息
country, area, err := user_m.GetUserCountryArea(model, userId) country, area, err := user_m.GetUserCountryArea(model, userId)
if err != nil { if err != nil {
...@@ -597,31 +601,29 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -597,31 +601,29 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
}) })
} }
} else { } else {
model.Log.Infof("GetRoomInfo: GetRoomBanners: %s", err.Error()) model.Log.Errorf("GetRoomInfo: GetRoomBanners: %s", err.Error())
} }
result.LuckyWheel, err = group_cv.GetLuckWheelState(model, groupId) model.Log.Infof("GetRoomInfo cost 5:%v", time.Now().Sub(start).Seconds())
result.LuckyWheel, err = group_cv.GetLuckWheelState(model, groupId) // todo check 耗时
if err != nil { if err != nil {
model.Log.Infof("GetRoomInfo: GetLuckWheelState: %s", err.Error()) model.Log.Errorf("GetRoomInfo: GetLuckWheelState: %s", err.Error())
} }
model.Log.Infof("GetRoomInfo cost 6:%v", time.Now().Sub(start).Seconds())
// 群主的详情 // 群主的详情
result.Owner, err = user_cv.GetUserDetail(model, groupInfo.Owner, userId) owner, err := user_cv.GetRoomInfoOwner(model, groupInfo.Owner, userId)
result.Owner = user_cv.UserDetailToRoomInfoOwner(owner)
if err != nil { if err != nil {
model.Log.Errorf("GetRoomInfo: GetUserBase: %s", err.Error()) model.Log.Errorf("GetRoomInfo: GetUserBase: %s", err.Error())
} }
model.Log.Infof("GetRoomInfo cost 7:%v", time.Now().Sub(start).Seconds())
// 进场特效类型 // 进场特效类型
var entryEffectType int // 进场特效类型 1: CP 2:神秘人 3:贵族 4:vip ,顺序从小到大 var entryEffectType int // 进场特效类型 1: CP 2:神秘人 3:贵族 4:vip ,顺序从小到大
var cpEntryEffect bool var cpEntryEffect bool
if cp, _ := rpc.GetUserCp(model, userId); cp != nil { if cp, _ := rpc.GetUserCpEntryEffect(model, userId); cp != nil {
for _, v := range cp.MyPrivilegeList { cpEntryEffect = cp.CpEntryEffect
if v.Type == 5 { result.CpLevel = cp.CpLevel
cpEntryEffect = true result.CpUserAvatar = cp.CpUserAvatar
}
}
result.CpLevel = cp.CpLevel.Level
if cp.CpUserInfo != nil && cp.CpUserInfo.Avatar != nil {
result.CpUserAvatar = *cp.CpUserInfo.Avatar
}
} }
if user, _ := user_cv.GetUserDetail(model, userId, userId); user != nil { if user, _ := user_cv.GetUserDetail(model, userId, userId); user != nil {
if user.IsVip { if user.IsVip {
...@@ -640,6 +642,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -640,6 +642,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
entryEffectType = 1 entryEffectType = 1
} }
result.EntryEffectType = entryEffectType result.EntryEffectType = entryEffectType
model.Log.Infof("GetRoomInfo cost 8:%v", time.Now().Sub(start).Seconds())
resp.ResponseOk(c, result) resp.ResponseOk(c, result)
return myContext, nil return myContext, nil
...@@ -848,7 +851,8 @@ func GroupBannerList(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -848,7 +851,8 @@ func GroupBannerList(c *gin.Context) (*mycontext.MyContext, error) {
continue continue
} }
// 版本控制 // 版本控制
if !allow && (v.ID == 2301 || v.ID == 4711 || v.ID == 2321 || v.ID == 5341 || v.ID == 5331 || v.ID == 5631 || v.ID == 5471 || v.ID == 5461 || v.ID == 5771 || v.ID == 5811 || v.ID == 5881) { if !allow && (v.ID == 2301 || v.ID == 4711 || v.ID == 2321 || v.ID == 5341 || v.ID == 5331 || v.ID == 5631 || v.ID == 5471 ||
v.ID == 5461 || v.ID == 5771 || v.ID == 5811 || v.ID == 5881 || v.ID == 8781 || v.ID == 10351) {
model.Log.Infof("CompareVersion appVersion:%v,auditVersion:%v,allow:%v,err:%v,skip top recharge", appVersion, vc.AuditVersion, allow, err) model.Log.Infof("CompareVersion appVersion:%v,auditVersion:%v,allow:%v,err:%v,skip top recharge", appVersion, vc.AuditVersion, allow, err)
continue continue
} }
......
package group_r package group_r
import ( import (
"context"
"fmt" "fmt"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
...@@ -16,8 +18,9 @@ import ( ...@@ -16,8 +18,9 @@ import (
"hilo-group/cv/group_power_cv" "hilo-group/cv/group_power_cv"
"hilo-group/cv/medal_cv" "hilo-group/cv/medal_cv"
"hilo-group/cv/user_cv" "hilo-group/cv/user_cv"
"hilo-group/domain/cache/group_c"
"hilo-group/domain/cache/res_c" "hilo-group/domain/cache/res_c"
"hilo-group/domain/cache/room_c" "hilo-group/domain/cache/user_c"
"hilo-group/domain/model/game_m" "hilo-group/domain/model/game_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/noble_m" "hilo-group/domain/model/noble_m"
...@@ -72,14 +75,12 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -72,14 +75,12 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
} }
model := domain.CreateModelContext(myContext) model := domain.CreateModelContext(myContext)
/* 2022-06-30 老板说先不分区 // 获取国家信息
regions, err := res_m.GetAllLangRegion(model) _, area, err := user_m.GetUserCountryArea(model, myUserId)
if err != nil { if err != nil {
model.Log.Errorf("GetUserCountryArea 获取国家资源错误 userId:%d, err:%v", myUserId, err)
return myContext, err return myContext, err
} }
myRegion := regions[myCountry]
model.Log.Infof("GetPopularGroups: user %d, name = %s, country = %s, region = %s", myUserId, myNick, myCountry, myRegion)
*/
bannedGroups, err := group_m.GetBannedGroupsMap(model) bannedGroups, err := group_m.GetBannedGroupsMap(model)
if err != nil { if err != nil {
return myContext, err return myContext, err
...@@ -90,7 +91,7 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -90,7 +91,7 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
model.Log.Infof("GetPopularGroups: page size = %d, page index = %d, banMap %v, hidenMap %v,cost:%v", pageSize, pageIndex, bannedGroups, hiddenGroups, time.Now().Sub(start)) gameGroups := group_m.GetGameGroupsMap(model)
hotGroupList := make([]group_m.GroupInfo, 0) hotGroupList := make([]group_m.GroupInfo, 0)
...@@ -99,7 +100,7 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -99,7 +100,7 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
model.Log.Infof("GetMicHasInGroupNum: cost %v", time.Now().Sub(start)) model.Log.Infof("GetMicHasInGroupNum: cost %v", time.Now().Sub(start)) // 正服高峰期耗时也很短的。
banCount := 0 banCount := 0
hiddenCount := 0 hiddenCount := 0
...@@ -115,12 +116,15 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -115,12 +116,15 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
hiddenCount++ hiddenCount++
continue continue
} }
// 过滤掉游戏房
if gameGroups[i] {
continue
}
groupIds = append(groupIds, i) groupIds = append(groupIds, i)
} }
model.Log.Infof("GetPopularGroups, micGroupNum: %v, banned %d, hidden %d,cost:%v", micGroupNum, banCount, hiddenCount, time.Now().Sub(start))
// 3. 处理置顶群 // 3. 处理置顶群
topGroupIds, err := getTopGroups(model, bannedGroups, hiddenGroups) topGroupIds, err := getTopGroups(model, bannedGroups, hiddenGroups, area)
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
...@@ -147,30 +151,10 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -147,30 +151,10 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
} }
for _, i := range topGroupIds { for _, i := range topGroupIds {
/* 2022-06-30 老板说先不分区 // 置顶只对同语言区的生效
if myRegion != regions[topGroupInfo[i].Country] {
continue
}
*/
// 已经置顶的,直接进队列,不再参与排序 // 已经置顶的,直接进队列,不再参与排序
hotGroupList = append(hotGroupList, groups[i]) hotGroupList = append(hotGroupList, groups[i])
//delete(groupIds, i)
} }
// for pretty log
//logstr := ""
//for _, i := range hotGroupList {
//logstr += " " + i.ImGroupId
//}
//logstr += " |"
// 获取国家信息
_, area, err := user_m.GetUserCountryArea(model, myUserId)
if err != nil {
model.Log.Errorf("GetUserCountryArea 获取国家资源错误 userId:%d, err:%v", myUserId, err)
return myContext, err
}
myArea := fmt.Sprintf("%d", area) myArea := fmt.Sprintf("%d", area)
// 国家区域信息 // 国家区域信息
resAreaMap, err := res_c.GetCountryAreaMap(model) resAreaMap, err := res_c.GetCountryAreaMap(model)
...@@ -196,16 +180,14 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -196,16 +180,14 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
} }
} }
} }
model.Log.Infof("GetPopularGroups, countryScore[*]: %v,cost:%v", countryScore, time.Now().Sub(start))
now := time.Now() now := time.Now()
bTime := now.Add(-time.Minute * 30) bTime := now.Add(-time.Minute * 30)
g := gift_cv.GiftOperate{SceneType: gift_e.GroupSceneType} g := gift_cv.GiftOperate{SceneType: gift_e.GroupSceneType}
diamonds, err := g.GetRangeConsumeSummaryV2(bTime, now, groupIds) diamonds, err := g.GetRangeConsumeSummaryV2(bTime, now, groupIds) // 获取1小时内的送礼榜
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
model.Log.Infof("GetPopularGroups, diamonds in 30 mins: %v,cost:%v", diamonds, time.Now().Sub(start))
visitCount, err := group_m.BatchGetRoomVisitCount(model.Log, groupIds) visitCount, err := group_m.BatchGetRoomVisitCount(model.Log, groupIds)
if err != nil { if err != nil {
...@@ -261,15 +243,9 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -261,15 +243,9 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
// * 同国家 ^ 麦上有人 + 开放群 - 需要等级的群 // * 同国家 ^ 麦上有人 + 开放群 - 需要等级的群
for _, g := range sortedGroupIds { for _, g := range sortedGroupIds {
hotGroupList = append(hotGroupList, groups[g]) hotGroupList = append(hotGroupList, groups[g])
//prefix := " "
//if countryScore[g] == 0 {
//prefix += "*"
//}
//logstr += prefix + g + ":" + groups[g].Code + ":" + strconv.Itoa(int(micGroupNum[g])) +
// ":" + strconv.FormatUint(diamonds[g], 10) + ":" + strconv.Itoa(int(visitCount[g]))
} }
total := len(hotGroupList) total := len(hotGroupList)
model.Log.Infof("GetPopularGroups: hotGroupList size = %d,cost:%v", total, time.Now().Sub(start)) //model.Log.Infof("GetPopularGroups: hotGroupList size = %d,cost:%v", total, time.Now().Sub(start))
result := make([]group_cv.PopularGroupInfo, 0) result := make([]group_cv.PopularGroupInfo, 0)
...@@ -303,7 +279,7 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -303,7 +279,7 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
//if err != nil { //if err != nil {
// return myContext, err // return myContext, err
//} //}
model.Log.Infof("GetPopularGroups: final start = %d, end = %d, groupIds %v,cost:%v", beginPos, endPos, groupIds, time.Now().Sub(start)) //model.Log.Infof("GetPopularGroups: final start = %d, end = %d, groupIds %v,cost:%v", beginPos, endPos, groupIds, time.Now().Sub(start))
roomCount, err := group_m.BatchGetRoomCount(model, groupIds) roomCount, err := group_m.BatchGetRoomCount(model, groupIds)
if err != nil { if err != nil {
...@@ -402,8 +378,8 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -402,8 +378,8 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, nil return myContext, nil
} }
func getTopGroups(model *domain.Model, bannedGroups map[string]uint64, hiddenGroups map[string]struct{}) ([]string, error) { func getTopGroups(model *domain.Model, bannedGroups map[string]uint64, hiddenGroups map[string]struct{}, area int) ([]string, error) {
topGroups, err := group_m.GroupTopGetAll(model) topGroups, err := group_m.GroupTopGetAll(model, area)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -470,9 +446,13 @@ func GetLatestGroups(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -470,9 +446,13 @@ func GetLatestGroups(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
gameGroups := group_m.GetGameGroupsMap(model)
gids := make([]string, 0) gids := make([]string, 0)
for i, _ := range micGroupNum { for i, _ := range micGroupNum {
// 过滤游戏房
if gameGroups[i] {
continue
}
gids = append(gids, i) gids = append(gids, i)
} }
// 获取最新群组列表 // 获取最新群组列表
...@@ -703,11 +683,12 @@ func GetRecentGroup(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -703,11 +683,12 @@ func GetRecentGroup(c *gin.Context) (*mycontext.MyContext, error) {
model := domain.CreateModelContext(myContext) model := domain.CreateModelContext(myContext)
uer := group_m.UserEnterRoom{UserId: userId} //uer := group_m.UserEnterRoom{UserId: userId}
rec, err := uer.Find(model.Db) //rec, err := uer.Find(model.Db)
if err != nil { //if err != nil {
return myContext, err // return myContext, err
} //}
rec, roomEnterTime := group_c.GetUserRecentRooms(model, userId, 0, 50)
myGroups, err := group_m.FindGroupMapByOwner(model, userId) myGroups, err := group_m.FindGroupMapByOwner(model, userId)
if err != nil { if err != nil {
...@@ -716,14 +697,14 @@ func GetRecentGroup(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -716,14 +697,14 @@ func GetRecentGroup(c *gin.Context) (*mycontext.MyContext, error) {
// 剔除自己创建的群 // 剔除自己创建的群
groupIds := make([]string, 0) groupIds := make([]string, 0)
for _, i := range rec { for _, groupId := range rec {
if _, ok := myGroups[i.GroupId]; !ok { if _, ok := myGroups[groupId]; !ok {
groupIds = append(groupIds, i.GroupId) groupIds = append(groupIds, groupId)
} }
} }
myService := domain.CreateService(myContext) myService := domain.CreateService(myContext)
result, _, err := group_cv.BuildJoinedGroupInfo(myService, userId, groupIds, 30, 1) result, _, err := group_cv.BuildRecentGroupInfo(myService, userId, groupIds, roomEnterTime)
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
...@@ -796,7 +777,7 @@ func GetMyGroup(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -796,7 +777,7 @@ func GetMyGroup(c *gin.Context) (*mycontext.MyContext, error) {
// @Param groupId path string true "群ID" // @Param groupId path string true "群ID"
// @Param pageSize query int false "分页大小 默认:10" default(10) // @Param pageSize query int false "分页大小 默认:10" default(10)
// @Param pageIndex query int false "第几个分页,从1开始 默认:1" default(1) // @Param pageIndex query int false "第几个分页,从1开始 默认:1" default(1)
// @Success 200 {object} GroupMembersRsp // @Success 200 {object} GetGroupVisitorsRsp
// @Router /v1/imGroup/visitors/{groupId} [get] // @Router /v1/imGroup/visitors/{groupId} [get]
func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) { func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys) myContext := mycontext.CreateMyContext(c.Keys)
...@@ -827,27 +808,28 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -827,27 +808,28 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err return myContext, err
} }
uer := group_m.UserEnterRoom{GroupId: groupId} //uer := group_m.UserEnterRoom{GroupId: groupId}
rows, err := uer.Find(model.Db) //rows, err := uer.Find(model.Db)
if err != nil { //if err != nil {
return myContext, err // return myContext, err
} //}
rows := group_c.GetLastRoomVisitors(model, groupId)
now := time.Now() //now := time.Now()
t := now.AddDate(0, 0, -15) // 只要15天内进入房间的人 //t := now.AddDate(0, 0, -15) // 只要15天内进入房间的人
userIds := make([]uint64, 0) userIds := make([]uint64, 0)
for _, i := range rows { for _, u := range rows {
if i.EnterTime.After(t) { //if i.EnterTime.After(t) {
userIds = append(userIds, i.UserId) userIds = append(userIds, u)
} //}
} }
users, err := user_m.GetUserMapByIds(model, userIds) users, err := user_m.GetUserMapByIds(model, userIds)
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
model.Log.Infof("GetGroupVisitors %s: memberNum = %d, user size = %d", groupId, len(rows), len(userIds)) //model.Log.Infof("GetGroupVisitors %s: memberNum = %d, user size = %d", groupId, len(rows), len(userIds))
result := GroupMembersRsp{Total: uint(len(userIds))} result := GetGroupVisitorsRsp{Total: uint(len(userIds))}
beginPos := pageSize * (pageIndex - 1) beginPos := pageSize * (pageIndex - 1)
if uint(beginPos) < result.Total { if uint(beginPos) < result.Total {
...@@ -867,7 +849,7 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -867,7 +849,7 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
result.Online++ result.Online++
} }
} }
model.Log.Infof("GetGroupVisitors %s: statusMap size = %d, onLine = %d", groupId, len(statusMap), result.Online) //model.Log.Infof("GetGroupVisitors %s: statusMap size = %d, onLine = %d", groupId, len(statusMap), result.Online)
roles, _, err := group_m.GetRolesInGroup(model, groupId) roles, _, err := group_m.GetRolesInGroup(model, groupId)
if err != nil { if err != nil {
...@@ -888,7 +870,7 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -888,7 +870,7 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err return myContext, err
} }
model.Log.Infof("GetGroupVisitors %s, users %v, roles: %v, nobles: %v, vips: %v", groupId, userIds, roles, nobleLevels, vips) //model.Log.Infof("GetGroupVisitors %s, users %v, roles: %v, nobles: %v, vips: %v", groupId, userIds, roles, nobleLevels, vips)
roomUsers, err := group_m.RoomLivingExistsUserId(groupId) roomUsers, err := group_m.RoomLivingExistsUserId(groupId)
if err != nil { if err != nil {
...@@ -943,7 +925,7 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -943,7 +925,7 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
return false return false
}) })
model.Log.Infof("GetGroupVisitors %s, sorted users: %v", groupId, userIds) //model.Log.Infof("GetGroupVisitors %s, sorted users: %v", groupId, userIds)
endPos := pageSize * pageIndex endPos := pageSize * pageIndex
if endPos > len(userIds) { if endPos > len(userIds) {
...@@ -961,15 +943,174 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -961,15 +943,174 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
if _, ok := roomUserMap[u]; ok { if _, ok := roomUserMap[u]; ok {
inRoom = true inRoom = true
} }
result.Members = append(result.Members, group_cv.MemberDetail{ result.Members = append(result.Members, group_cv.GroupVisitorsDetail{
CvUserExtend: userExtends[u], CvGroupMember: user_cv.CvUserExtendToCvGroupMember(userExtends[u]),
Role: roles[u], Role: roles[u],
OnlineStatus: statusMap[users[u].ExternalId], OnlineStatus: statusMap[users[u].ExternalId],
InRoom: inRoom, InRoom: inRoom,
})
}
}
resp.ResponseOk(c, result)
// 清理15天之前的访客
group_c.RemoveRoomVisitors(model, groupId)
return myContext, nil
}
// @Tags 群组
// @Summary 最近访问列表
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupId path string true "群ID"
// @Param pageSize query int false "分页大小 默认:10" default(10)
// @Param pageIndex query int false "第几个分页,从1开始 默认:1" default(1)
// @Success 200 {object} GetGroupVisitorsRsp
// @Router /v1/imGroup/visitors/{groupId} [get]
func GetGroupVisitorsV2(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
groupId := c.Param("groupId")
if len(groupId) <= 0 {
return myContext, bizerr.ParaMissing
}
pageSize, err := strconv.Atoi(c.Query("pageSize"))
if err != nil || pageSize <= 0 {
pageSize = 10
}
pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
if err != nil || pageIndex <= 0 {
pageIndex = 1
}
userId, _, err := req.GetUserIdAndExtId(c, myContext)
if err != nil {
return myContext, err
}
model := domain.CreateModelContext(myContext)
groupId, err = group_m.ToImGroupId(model, groupId)
if err != nil {
return myContext, err
}
// 获取最近进房用户
rows := group_c.GetLastRoomVisitors(model, groupId)
userIds := make([]uint64, 0)
for _, u := range rows {
userIds = append(userIds, u)
}
result := GetGroupVisitorsRsp{Total: uint(len(userIds))}
beginPos := pageSize * (pageIndex - 1)
if uint(beginPos) < result.Total {
// 取在线状态
extIds, userExtIdMap, userCodeMap := user_m.GetUserExternalIds(model, userIds)
statusMap, err := tim_m.GetOnlineStatus(model, extIds)
if err != nil {
return myContext, err
}
result.Online = 0
for _, v := range statusMap {
if v == online_e.IM_STATUS_ON_LINE {
result.Online++
}
}
// 获取群组角色
roles, _, err := group_m.GetRolesInGroup(model, groupId)
if err != nil {
return myContext, err
}
// 获取贵族
nobleLevels := user_c.BatchGetNobleLevel(model, userIds)
// 获取svip
svipLevels := user_c.MGetUserSvipLevel(model, userIds)
// 获取svip
vips := user_c.BatchGetVips(model, userIds)
roomUsers, err := group_m.RoomLivingExistsUserId(groupId)
if err != nil {
return myContext, err
}
roomUserMap := utils.SliceToMapUInt64(roomUsers)
// 排序规则 :在房间的优先,其次是在线,再次看角色,最后看贵族
sort.Slice(userIds, func(i, j int) bool {
ui := userIds[i]
uj := userIds[j]
_, ok1 := roomUserMap[ui]
_, ok2 := roomUserMap[uj]
if ok1 && !ok2 {
return true
} else if ok1 == ok2 {
ei := userExtIdMap[ui]
ej := userExtIdMap[uj]
if statusMap[ei] > statusMap[ej] {
return true
}
if statusMap[ei] == statusMap[ej] {
if roles[ui] > roles[uj] {
return true
}
if roles[ui] == roles[uj] {
// SVIP>贵族5>贵族4>贵族3>贵族2>VIP
if svipLevels[ui] > svipLevels[uj] {
return true
} else if svipLevels[ui] == svipLevels[uj] {
if nobleLevels[ui] > nobleLevels[uj] && nobleLevels[ui] >= 2 {
return true
}
if nobleLevels[ui] == nobleLevels[uj] || nobleLevels[ui] < 2 && nobleLevels[uj] < 2 {
if vips[ui] != nil {
if vips[uj] == nil {
return true
} else {
return userCodeMap[ui] < userCodeMap[uj]
}
} else if vips[uj] == nil {
return userCodeMap[ui] < userCodeMap[uj]
}
}
}
}
}
}
return false
})
endPos := pageSize * pageIndex
if endPos > len(userIds) {
endPos = len(userIds)
}
userIds = userIds[beginPos:endPos]
userExtends, err := user_cv.BatchGetUserExtend(model, userIds, userId) // 这里只是取出pageSize=10条数据
if err != nil {
return myContext, err
}
for _, u := range userIds {
inRoom := false
if _, ok := roomUserMap[u]; ok {
inRoom = true
}
result.Members = append(result.Members, group_cv.GroupVisitorsDetail{
CvGroupMember: user_cv.CvUserExtendToCvGroupMember(userExtends[u]),
Role: roles[u],
OnlineStatus: statusMap[userExtIdMap[u]],
InRoom: inRoom,
}) })
} }
} }
resp.ResponseOk(c, result) resp.ResponseOk(c, result)
// 清理15天之前的访客,定期
if time.Now().Second() == 0 {
group_c.RemoveRoomVisitors(model, groupId)
}
return myContext, nil return myContext, nil
} }
...@@ -1234,17 +1375,17 @@ func GetGroupByCountry(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -1234,17 +1375,17 @@ func GetGroupByCountry(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err return myContext, err
} }
model.Log.Infof("GetGroupByCountry: page size = %d, page index = %d, banMap %v", pageSize, pageIndex, bannedGroups) //model.Log.Infof("GetGroupByCountry: page size = %d, page index = %d, banMap %v", pageSize, pageIndex, bannedGroups)
beginTime := time.Now() beginTime := time.Now()
groups, banCount, visitCount, err := getCandidatesByCountry(model, bannedGroups, countryShortName) groups, banCount, visitCount, err := group_s.GetCandidatesByCountry(model, bannedGroups, countryShortName)
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
endTime := time.Now() endTime := time.Now()
model.Log.Infof("GetGroupByCountry: candidates size = %d, takes %d ms banned = %d, visitCount size = %d", model.Log.Infof("GetGroupByCountry: candidates size = %d, takes %d ms banned = %d, visitCount size = %d",
len(groups), endTime.Sub(beginTime).Milliseconds(), banCount, len(visitCount)) len(groups), endTime.Sub(beginTime).Milliseconds(), banCount, len(visitCount))
model.Log.Infof("GetGroupByCountry cost1:%v", time.Now().Sub(beginTime)) //model.Log.Infof("GetGroupByCountry cost1:%v", time.Now().Sub(beginTime))
hotGroupList := make([]*group_m.GroupInfo, 0) hotGroupList := make([]*group_m.GroupInfo, 0)
...@@ -1447,47 +1588,180 @@ func GetGroupByCountry(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -1447,47 +1588,180 @@ func GetGroupByCountry(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, nil return myContext, nil
} }
// 国家群候选:没有密码且没被封禁的群, 有国家 func GetGroupByCountryV2(c *gin.Context) (*mycontext.MyContext, error) {
func getCandidatesByCountry(model *domain.Model, bannedGroups map[string]uint64, country string) (map[string]*group_m.GroupInfo, int, map[string]int64, error) { myContext := mycontext.CreateMyContext(c.Keys)
noPwdGroups, err := group_m.FindOwnerCountryGroups(model, country) myUserId, err := req.GetUserId(c)
if err != nil { if err != nil {
return nil, 0, nil, err return myContext, err
}
countryShortName := c.Query("countryShortName")
if countryShortName == "" {
return myContext, myerr.NewSysError("countryShortName 为必填项")
} }
pageSize, err := strconv.Atoi(c.Query("pageSize"))
if err != nil || pageSize <= 0 {
pageSize = 10
}
pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
if err != nil || pageIndex <= 0 {
pageIndex = 1
}
model := domain.CreateModelContext(myContext)
roomVisitCount, err := room_c.GetAllRoomVisitCount() // 从redis分页取群组id
sortedGroupIds := make([]string, 0, pageSize)
beginPos := int64(pageSize * (pageIndex - 1))
endPos := int64(pageSize*pageIndex - 1)
key := rediskey.GetGroupCountrySortList(countryShortName)
zList, err := model.RedisCluster.ZRangeWithScores(context.Background(), key, beginPos, endPos).Result()
if err != nil { if err != nil {
return nil, 0, nil, err model.Log.Errorf("GetGroupByCountry err:%v", err)
return myContext, err
}
for _, v := range zList {
sortedGroupIds = append(sortedGroupIds, v.Member.(string))
} }
banCount := 0 hotGroupList := make([]*group_m.GroupInfo, 0)
groups := make(map[string]*group_m.GroupInfo, 0) // * 同语言区 ^ 麦上有人 + 开放群 - 需要等级的群
visitCount := make(map[string]int64) for _, i := range sortedGroupIds {
for i, v := range noPwdGroups { gInfo, err := group_m.GetGroupInfo(model, i)
// 过滤掉被封禁的群 if err != nil {
if bannedGroups[v.ImGroupId] != 0 { model.Log.Errorf("GetGroupByCountry err:%v", err)
banCount++ return myContext, err
continue
} }
hotGroupList = append(hotGroupList, gInfo)
}
total, err := model.RedisCluster.ZCard(context.Background(), key).Uint64()
if err != nil {
model.Log.Errorf("GetGroupByCountry err:%v", err)
return myContext, err
}
// 先从二级缓存中找 // 返回结果
if c, ok := roomVisitCount[v.ImGroupId]; ok { result := make([]group_cv.PopularGroupInfo, 0)
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
//model.Log.Debugf("getPopularCandidates, from roomVisitCount %s(%s) - %d", v.ImGroupId, v.Code, vc)
groups[v.ImGroupId] = &noPwdGroups[i] groupIds := make([]string, 0)
visitCount[v.ImGroupId] = vc owners := make([]uint64, 0)
} for _, i := range hotGroupList {
} else { groupIds = append(groupIds, i.ImGroupId)
// 如果没有,就从roomVisit中取 owners = append(owners, i.Owner)
if vc, err := room_c.GetSetRoomVisitCount(v.ImGroupId); err == nil && vc > 0 { }
model.Log.Infof("getPopularCandidates, from roomVisit %s(%s) - %d", v.ImGroupId, v.Code, vc) powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners)
if err != nil {
return myContext, err
}
groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds)
if err != nil {
return myContext, err
}
resMedal, err := res_m.MedalGetAllMap(model.Db)
if err != nil {
return myContext, err
}
countryInfo, err := res_c.GetCountryIconMap(model)
if err != nil {
return myContext, err
}
rr := rocket_m.RocketResult{}
maxStageMap, err := rr.GetMaxStage(model.DB(), groupIds)
if err != nil {
return myContext, err
}
roomCount, err := group_m.BatchGetRoomCount(model, groupIds)
if err != nil {
return nil, err
}
// 正在进行的游戏
games := game_m.GetNotEndGamesMap(model)
// 扶持等级
supportLevels, err := group_s.NewGroupService(myContext).GetWeekMaxSupportLevelMap()
if err != nil {
return myContext, err
}
visitCount, err := group_s.GetVisitCount(groupIds)
if err != nil {
model.Log.Errorf("GetGroupByCountry err:%v", err)
return myContext, err
}
// 获取麦上人数
micGroupNum, err := group_m.GetMicHasInGroupNum(model)
if err != nil {
return myContext, err
}
groups[v.ImGroupId] = &noPwdGroups[i] for _, i := range hotGroupList {
visitCount[v.ImGroupId] = vc var maxStage *uint16 = nil
if s, ok := maxStageMap[i.ImGroupId]; ok {
maxStage = &s
}
medals := make([]medal_cv.PicElement, 0)
if m, ok := groupMedals[i.ImGroupId]; ok {
for _, j := range m {
mId := uint32(j)
if e, ok := resMedal[mId]; ok {
medals = append(medals, medal_cv.PicElement{
PicUrl: e.PicUrl,
})
}
} }
} }
// 补上房间流水勋章
var pe *medal_cv.PicElement
_, pe, err = medal_cv.GetGroupConsumeMedal(model, i.ImGroupId)
if err != nil {
model.Log.Infof("GetGroupByCountry: GetGroupConsumeMedal: %s", err.Error())
} else if pe != nil {
medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl})
}
var password *string = nil
if len(i.Password) > 0 && i.Owner != myUserId {
emptyStr := ""
password = &emptyStr
}
result = append(result, group_cv.PopularGroupInfo{
GroupInfo: group_cv.GroupInfo{
GroupBasicInfo: group_cv.GroupBasicInfo{
GroupId: i.TxGroupId,
Name: i.Name,
Introduction: i.Introduction,
Notification: i.Notification,
FaceUrl: i.FaceUrl,
Code: i.Code,
CountryIcon: countryInfo[i.Country],
Password: password,
SupportLevel: supportLevels[i.ImGroupId],
GroupInUserDuration: visitCount[i.ImGroupId],
MicNumType: int(i.MicNumType),
GroupMedals: medals,
},
HasOnMic: micGroupNum[i.ImGroupId] > 0,
GroupPowerId: powerIds[i.Owner],
GroupPowerName: powerNames[i.Owner],
GroupPowerNameplate: powerNameplates[i.Owner],
GroupPower: group_cv.GroupPower{
Id: powerIds[i.Owner],
Name: powerNames[i.Owner],
Nameplate: powerNameplates[i.Owner],
Grade: powerGrades[i.Owner],
},
},
MicUsers: []user_cv.CvUserTiny{},
RoomUserCount: uint(roomCount[i.ImGroupId]),
MaxStage: maxStage,
GameTypes: games[i.TxGroupId],
})
} }
return groups, banCount, visitCount, nil
resp.ResponsePageOk(c, result, uint(total), pageIndex)
return myContext, nil
} }
// @Tags 资源 // @Tags 资源
......
...@@ -439,7 +439,7 @@ func GroupMicTaskInviteDialog(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -439,7 +439,7 @@ func GroupMicTaskInviteDialog(c *gin.Context) (*mycontext.MyContext, error) {
endTime := beginTime.AddDate(0, 0, 1) endTime := beginTime.AddDate(0, 0, 1)
var n int64 var n int64
if err := mysql.Db.Model(&diamond_m.DiamondAccountDetail{}).Where(&diamond_m.DiamondAccountDetail{ if err := mysql.Db.Table(diamond_m.DiamondAccountDetail{}.TableName()).Where(&diamond_m.DiamondAccountDetail{
UserId: userId, UserId: userId,
AddReduce: mysql.ADD, AddReduce: mysql.ADD,
}).Where("Created_Time <= ? and Created_Time >= ?", endTime, beginTime).Where("(Operate_Type = ? or Operate_Type = ?)", diamond_e.DailyInAppVip, diamond_e.DailyInAppCommon).Count(&n).Error; err != nil { }).Where("Created_Time <= ? and Created_Time >= ?", endTime, beginTime).Where("(Operate_Type = ? or Operate_Type = ?)", diamond_e.DailyInAppVip, diamond_e.DailyInAppCommon).Count(&n).Error; err != nil {
...@@ -550,12 +550,13 @@ func GroupMicIn(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -550,12 +550,13 @@ func GroupMicIn(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err return myContext, err
} }
if micUser != nil { if micUser != nil {
if iStr == "" { // 同房间且上麦序列为空
if iStr == "" && micUser.GroupUuid == groupUuid {
// 非切麦操作 // 非切麦操作
return myContext, bizerr.GroupMicUserHasIn return myContext, bizerr.GroupMicUserHasIn
} }
// 切换麦位,先下麦 // 切换麦位,先下麦
if err := group_mic_s.NewGroupPowerService(myContext).GroupMicLeave(groupUuid, micUser.I, userId, externalId); err != nil { if err := group_mic_s.NewGroupPowerService(myContext).GroupMicLeave(micUser.GroupUuid, micUser.I, userId, externalId); err != nil {
return myContext, err return myContext, err
} }
} }
......
...@@ -448,7 +448,7 @@ func GetGroupDetail(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -448,7 +448,7 @@ func GetGroupDetail(c *gin.Context) (*mycontext.MyContext, error) {
result.Role = group_e.GROUP_MEMBER result.Role = group_e.GROUP_MEMBER
} }
groupUser := group_m.GroupUser{Model: model, UserId: userId} groupUser := group_m.GroupUser{Model: model, UserId: userId, GroupId: groupId}
msgStatus, err := groupUser.Get() msgStatus, err := groupUser.Get()
if err != nil { if err != nil {
return myContext, err return myContext, err
...@@ -1238,6 +1238,12 @@ type GroupMembersRsp struct { ...@@ -1238,6 +1238,12 @@ type GroupMembersRsp struct {
Total uint `json:"total"` Total uint `json:"total"`
} }
type GetGroupVisitorsRsp struct {
Members []group_cv.GroupVisitorsDetail `json:"members"`
Online uint `json:"online"` // 在线人数
Total uint `json:"total"`
}
// @Tags 群组 // @Tags 群组
// @Summary 获取永久成员列表 // @Summary 获取永久成员列表
// @Accept application/x-www-form-urlencoded // @Accept application/x-www-form-urlencoded
...@@ -1724,8 +1730,11 @@ func downgradeRoom(myContext *mycontext.MyContext, gi *group_m.GroupInfo) error ...@@ -1724,8 +1730,11 @@ func downgradeRoom(myContext *mycontext.MyContext, gi *group_m.GroupInfo) error
// @Param nonce header string true "随机数字" // @Param nonce header string true "随机数字"
// @Param groupId formData string true "群ID" // @Param groupId formData string true "群ID"
// @Param password formData string false "房间密码" // @Param password formData string false "房间密码"
// @Param enterType formData int false "进房类型:1.ludo游戏快速匹配进房 2:uno" // @Param enterType formData int false "进房类型:1.ludo游戏快速匹配进房 2:uno 10.domino"
// @Param gameCode formData string false "gameCode" // @Param gameCode formData string false "gameCode"
// @Param is1V1 formData int false "是否1v1,0否1是"
// @Param gameMode formData int false "游戏模式0.快速1.经典"
// @Param is1V1Robot formData int false "是否游戏机器人,0否1是"
// @Success 200 {object} group_cv.GroupChannelId // @Success 200 {object} group_cv.GroupChannelId
// @Router /v1/imGroup/in [put] // @Router /v1/imGroup/in [put]
func GroupIn(c *gin.Context) (*mycontext.MyContext, error) { func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
...@@ -1738,6 +1747,23 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -1738,6 +1747,23 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
password := c.PostForm("password") password := c.PostForm("password")
enterType := c.PostForm("enterType") enterType := c.PostForm("enterType")
gameCode := c.PostForm("gameCode") gameCode := c.PostForm("gameCode")
is1V1 := c.PostForm("is1V1")
gameMode := c.PostForm("gameMode")
is1V1Robot := c.PostForm("is1V1Robot")
// 把id:9 添加进房间:5030的黑名单
if (userId == 2087771 || userId == 1763211) && groupId == "HTGS#a46766257" {
return myContext, bizerr.NoPrivileges
}
// 把Cartier和1980加入到房间id:VIP、房间id:305、房间id:7的房间黑名单
if (userId == 2129451 || userId == 2809891) && groupId == "HTGS#a25015185" {
return myContext, bizerr.NoPrivileges
}
if (userId == 2129451 || userId == 2809891) && groupId == "HTGS#a48723458" {
return myContext, bizerr.NoPrivileges
}
if (userId == 2129451 || userId == 2809891) && groupId == "HTGS#a69660046" {
return myContext, bizerr.NoPrivileges
}
model := domain.CreateModelContext(myContext) model := domain.CreateModelContext(myContext)
gi, err := group_m.GetInfoByTxGroupId(model, groupId) gi, err := group_m.GetInfoByTxGroupId(model, groupId)
...@@ -1828,6 +1854,14 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -1828,6 +1854,14 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, bizerr.UpgradeRequired return myContext, bizerr.UpgradeRequired
} }
} }
// 指定房间号写死trtc
if groupId == "HTGS#a93989299" {
provider = group_e.GroupProvider_TRTC
}
// 指定房间号写死sw
if groupId == "HTGS#a25015185" {
provider = group_e.GroupProvider_SW
}
if channelId, token, err := group_s.NewGroupService(myContext).GroupIn(userId, externalId, groupId, password, imei, ip, provider, gi.Id); err != nil { if channelId, token, err := group_s.NewGroupService(myContext).GroupIn(userId, externalId, groupId, password, imei, ip, provider, gi.Id); err != nil {
return myContext, err return myContext, err
...@@ -1837,9 +1871,9 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -1837,9 +1871,9 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
myContext.Log.Infof("GroupIn, ProcessRoomVisit err: %s", err.Error()) myContext.Log.Infof("GroupIn, ProcessRoomVisit err: %s", err.Error())
} }
// 更新用户进入房间缓存记录 // 更新用户进入房间缓存记录
if err = room_c.ProcessUserRoomVisit(userId, groupId); err != nil { //if err = room_c.ProcessUserRoomVisit(userId, groupId); err != nil {
myContext.Log.Infof("GroupIn, ProcessUserRoomVisit err: %s", err.Error()) // myContext.Log.Infof("GroupIn, ProcessUserRoomVisit err: %s", err.Error())
} //}
resp.ResponseOk(c, group_cv.GroupChannelId{ resp.ResponseOk(c, group_cv.GroupChannelId{
ChannelId: channelId, ChannelId: channelId,
Token: token, Token: token,
...@@ -1863,10 +1897,10 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -1863,10 +1897,10 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
}() }()
} }
// 判断是否需要执行游戏逻辑 // 判断是否需要执行游戏逻辑
if enterType != "" && gameCode != "" { if enterType != "" && (gameCode != "" || is1V1Robot == "1") {
traceId, _ := c.Get(mycontext.TRACEID) traceId, _ := c.Get(mycontext.TRACEID)
token := c.Writer.Header().Get(mycontext.TOKEN) token := c.Writer.Header().Get(mycontext.TOKEN)
err := game_c.SetAutoMathEnterRoom(userId, gi.ImGroupId, cast.ToString(traceId), token, enterType, gameCode) err := game_c.SetAutoMathEnterRoom(userId, gi.ImGroupId, cast.ToString(traceId), token, enterType, gameCode, is1V1, gameMode, is1V1Robot)
if err != nil { if err != nil {
model.Log.Errorf("GroupIn cache.SetAutoMathEnterRoom userId:%v, imGroupId:%v, err:%v", userId, gi.ImGroupId, err) model.Log.Errorf("GroupIn cache.SetAutoMathEnterRoom userId:%v, imGroupId:%v, err:%v", userId, gi.ImGroupId, err)
} }
......
...@@ -522,6 +522,8 @@ func AddGroupBlacklist(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -522,6 +522,8 @@ func AddGroupBlacklist(c *gin.Context) (*mycontext.MyContext, error) {
if err == nil { if err == nil {
signal_s.SendCustomMsg(model, groupId, nil, string(buf)) signal_s.SendCustomMsg(model, groupId, nil, string(buf))
} }
// socket通知被拉黑者退房
rpc.SendQuitRoom(user.ID, 1, txGroupId)
if err = group_s.NewGroupService(myContext).LeaveGroup(model, groupId, user.ID, externalId); err != nil { if err = group_s.NewGroupService(myContext).LeaveGroup(model, groupId, user.ID, externalId); err != nil {
return myContext, err return myContext, err
...@@ -719,6 +721,7 @@ func KickGroupMembers(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -719,6 +721,7 @@ func KickGroupMembers(c *gin.Context) (*mycontext.MyContext, error) {
model := domain.CreateModelContext(myContext) model := domain.CreateModelContext(myContext)
txGroupId := groupId
groupId, err = group_m.ToImGroupId(model, groupId) groupId, err = group_m.ToImGroupId(model, groupId)
if err != nil { if err != nil {
return myContext, err return myContext, err
...@@ -750,6 +753,8 @@ func KickGroupMembers(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -750,6 +753,8 @@ func KickGroupMembers(c *gin.Context) (*mycontext.MyContext, error) {
Source: myExtId, Target: externalId, Content: string(buf)} Source: myExtId, Target: externalId, Content: string(buf)}
signal_s.SendSignalMsg(model, groupId, systemMsg, false) signal_s.SendSignalMsg(model, groupId, systemMsg, false)
} }
// socket通知退房
rpc.SendQuitRoom(user.ID, 2, txGroupId)
if err = group_s.NewGroupService(myContext).LeaveGroup(model, groupId, user.ID, externalId); err != nil { if err = group_s.NewGroupService(myContext).LeaveGroup(model, groupId, user.ID, externalId); err != nil {
return myContext, err return myContext, err
......
...@@ -6,13 +6,11 @@ import ( ...@@ -6,13 +6,11 @@ import (
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/msg_e" "hilo-group/_const/enum/msg_e"
"hilo-group/cv/group_cv" "hilo-group/cv/group_cv"
"hilo-group/cv/user_cv" "hilo-group/cv/user_cv"
"hilo-group/domain/cache/group_c" "hilo-group/domain/cache/group_c"
"hilo-group/domain/model/gift_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/res_m" "hilo-group/domain/model/res_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
...@@ -111,18 +109,28 @@ func GetSupportDetail(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -111,18 +109,28 @@ func GetSupportDetail(c *gin.Context) (*mycontext.MyContext, error) {
result := group_cv.SupportPageDetail{GroupId: txGroupId} result := group_cv.SupportPageDetail{GroupId: txGroupId}
now := time.Now() now := time.Now()
beginTime, endTime, _ := group_m.GetSupportLevelTime(now) _, endTime, period := group_m.GetSupportLevelTime(now)
result.RemainSecond = endTime.Unix() - now.Unix() result.RemainSecond = endTime.Unix() - now.Unix()
g := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, SceneUid: groupId, Model: model} //g := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, SceneUid: groupId, Model: model}
result.CurrentCount, result.CurrentConsume, err = g.GetConsumeByRange(beginTime, endTime) //result.CurrentCount, result.CurrentConsume, err = g.GetConsumeByRange(beginTime, endTime)
//if err != nil {
// return myContext, err
//}
result.CurrentConsume, result.CurrentCount, err = group_s.GetGroupConsumeCount(model, groupId, period)
if err != nil { if err != nil {
model.Log.Errorf("GetSupportDetail groupId:%s, err:%v", groupId, err)
return myContext, err return myContext, err
} }
beginTime, endTime, _ = group_m.GetSupportLevelTime(now.AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY)) _, _, periodLast := group_m.GetSupportLevelTime(now.AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
result.LastCount, result.LastConsume, err = g.GetConsumeByRange(beginTime, endTime) //result.LastCount, result.LastConsume, err = g.GetConsumeByRange(beginTimeLast, endTimeLast)
//if err != nil {
// return myContext, err
//}
result.LastConsume, result.LastCount, err = group_s.GetGroupConsumeCount(model, groupId, periodLast)
if err != nil { if err != nil {
model.Log.Errorf("GetSupportDetail groupId:%s, err:%v", groupId, err)
return myContext, err return myContext, err
} }
...@@ -152,7 +160,7 @@ func GetSupportDetail(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -152,7 +160,7 @@ func GetSupportDetail(c *gin.Context) (*mycontext.MyContext, error) {
} }
// 判断这个周期这个群的奖金是否已经发过 // 判断这个周期这个群的奖金是否已经发过
_, _, period := group_m.GetLastSupportPeriod(now) _, _, period = group_m.GetLastSupportPeriod(now)
gsaa := group_m.GroupSupportAwardAdmin{Period: period, GroupUid: groupId} gsaa := group_m.GroupSupportAwardAdmin{Period: period, GroupUid: groupId}
rows, err := gsaa.Get(model.Db) rows, err := gsaa.Get(model.Db)
if err != nil { if err != nil {
...@@ -222,16 +230,16 @@ func TryAddSupporter(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -222,16 +230,16 @@ func TryAddSupporter(c *gin.Context) (*mycontext.MyContext, error) {
if role != group_e.GROUP_MANAGER && role != group_e.GROUP_ADMIN { if role != group_e.GROUP_MANAGER && role != group_e.GROUP_ADMIN {
return myContext, bizerr.NotManagerOrAdmin return myContext, bizerr.NotManagerOrAdmin
} }
// 判断财富等级必须要大于等于8 // 判断财富等级必须要大于等于3
wealthGrade, _, err := user_m.GetWealthGrade(model, userId) wealthGrade, _, err := user_m.GetWealthGrade(model, userId)
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
if wealthGrade < 8 { if wealthGrade < 3 {
if msg, _ := res_m.GetResMultiTextBy(model.DB(), 187, lang); msg != nil { // 187:res_multi_text 财富等级为到8级 if msg, _ := res_m.GetResMultiTextBy(model.DB(), 187, lang); msg != nil { // 187:res_multi_text 财富等级为到8级
return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupSupportWealthLevel8.GetCode(), msg.Content, myerr.BusinessData{}) return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupSupportWealthLevel3.GetCode(), msg.Content, myerr.BusinessData{})
} }
return myContext, bizerr.GroupSupportWealthLevel8 return myContext, bizerr.GroupSupportWealthLevel3
} }
// 判断用户是否作为助手领取过奖励 // 判断用户是否作为助手领取过奖励
sameImeiUsers, err := user_m.GetSameImeiMap(model, userId) sameImeiUsers, err := user_m.GetSameImeiMap(model, userId)
...@@ -335,20 +343,24 @@ func TakeSupportAward(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -335,20 +343,24 @@ func TakeSupportAward(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, bizerr.GroupAlreadyAwarded return myContext, bizerr.GroupAlreadyAwarded
} }
userIds, outUserIds, err := group_s.NewGroupService(myContext).GroupSupportList(groupId, userIds)
model.Log.Infof("TakeSupportAward: %v, %v", userIds, outUserIds)
model = domain.CreateModelContext(myContext) model = domain.CreateModelContext(myContext)
resSupportId, _, err := group_s.NewGroupService(myContext).GetSupportLevel(groupId) resSupport, supportLevel, err := group_s.NewGroupService(myContext).GetSupportLevelByRedis(groupId)
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
if resSupportId <= 0 { if resSupport.ID <= 0 {
return myContext, bizerr.NotQualified return myContext, bizerr.NotQualified
} }
userIds, outUserIds, err := group_s.NewGroupService(myContext).GroupSupportList(groupId, userIds, supportLevel)
model.Log.Infof("TakeSupportAward: %v, %v", userIds, outUserIds)
if err != nil {
model.Log.Errorf("TakeSupportAward groupId:%v, userId:%v err:%v", groupId, userId, err)
return myContext, err
}
// 检查userIds的ip限制 // 检查userIds的ip限制
userIp, err := user_m.GetUserIpMap(model.Db, userIds) userIp, err := user_m.GetUserIpMap(model.Db, userIds)
if err != nil { if err != nil {
...@@ -366,22 +378,28 @@ func TakeSupportAward(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -366,22 +378,28 @@ func TakeSupportAward(c *gin.Context) (*mycontext.MyContext, error) {
msg = fmt.Sprintf(resMul.Content, codeMap[uid]) msg = fmt.Sprintf(resMul.Content, codeMap[uid])
} }
if times, err := group_c.GetGroupSupportAwardIpTimes(model, ip); err != nil || times >= 6 { if times, err := group_c.GetGroupSupportAwardIpTimes(model, ip); err != nil || times >= 6 {
myContext.Log.Infof("ip more 6:%v-%v-%v", times, ip, uid)
return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupSupportIpLimit.GetCode(), msg, myerr.BusinessData{}) return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupSupportIpLimit.GetCode(), msg, myerr.BusinessData{})
} }
} }
} }
for ip, cnt := range sameIp { for ip, cnt := range sameIp {
if cnt >= 6 { if cnt >= 6 {
var msg = fmt.Sprintf(bizerr.GroupSupportIpLimit.GetMsg(), ipUser[ip]) var msg = fmt.Sprintf(bizerr.GroupSupportIpLimit.GetMsg(), codeMap[ipUser[ip]])
if resMul, _ := res_m.GetResMultiTextBy(model.Db, msg_e.MSG_ID_REPEAT_ACCOUNT, lang); resMul != nil { if resMul, _ := res_m.GetResMultiTextBy(model.Db, msg_e.MSG_ID_REPEAT_ACCOUNT, lang); resMul != nil {
msg = fmt.Sprintf(resMul.Content, ipUser[ip]) msg = fmt.Sprintf(resMul.Content, codeMap[ipUser[ip]])
} }
myContext.Log.Infof("ip more 6 two:%v-%v-%v", cnt, ip, ipUser[ip])
return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupSupportIpLimit.GetCode(), msg, myerr.BusinessData{}) return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupSupportIpLimit.GetCode(), msg, myerr.BusinessData{})
} }
} }
groupInfo, err := group_m.GetGroupInfo(model, groupId)
if groupInfo == nil || groupInfo.Id <= 0 {
return myContext, bizerr.GroupNotFound
}
// 真正地放奖励 // 真正地放奖励
err = group_s.NewGroupService(myContext).GroupSupportAward(groupId, pa, userIds, resSupportId, period) err = group_s.NewGroupService(myContext).GroupSupportAward(groupId, pa, userIds, resSupport, period, groupInfo)
if err != nil { if err != nil {
return myContext, err return myContext, err
} }
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus" "git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config" "git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"hilo-group/myerr/bizerr" "hilo-group/myerr/bizerr"
"hilo-group/req" "hilo-group/req"
...@@ -133,3 +134,15 @@ func LoggerHandle(c *gin.Context) { ...@@ -133,3 +134,15 @@ func LoggerHandle(c *gin.Context) {
latency := end.Sub(start) latency := end.Sub(start)
mycontext.CreateMyContext(c.Keys).Log.Infof("request end fullPath:%v,url:%v, method: %v, traceId:%v, latency:%v userId:%v", c.FullPath(), reqUri, method, traceId, latency, userId) mycontext.CreateMyContext(c.Keys).Log.Infof("request end fullPath:%v,url:%v, method: %v, traceId:%v, latency:%v userId:%v", c.FullPath(), reqUri, method, traceId, latency, userId)
} }
// 加密Handle
func EncryptHandle(c *gin.Context) {
header := c.Request.Header
appVersion := header.Get("Appversion")
if len(appVersion) > 0 {
if high, _ := utils.CompareVersion(appVersion, "> 3.9.0"); high {
c.Set(mycontext.InnerEncrypt, true)
}
}
c.Next()
}
...@@ -31,8 +31,8 @@ func InitRouter() *gin.Engine { ...@@ -31,8 +31,8 @@ func InitRouter() *gin.Engine {
// //
imGroup.POST("/group", wrapper(group_r.CreateGroup)) imGroup.POST("/group", wrapper(group_r.CreateGroup))
imGroup.DELETE("/group/:groupId", wrapper(group_r.DestroyGroup)) imGroup.DELETE("/group/:groupId", wrapper(group_r.DestroyGroup))
imGroup.GET("/group/:code", wrapper(group_r.GetGroupInfo)) imGroup.GET("/group/:code", EncryptHandle, wrapper(group_r.GetGroupInfo))
imGroup.GET("/detail/:groupId", wrapper(group_r.GetGroupDetail)) imGroup.GET("/detail/:groupId", EncryptHandle, wrapper(group_r.GetGroupDetail))
imGroup.PUT("/group/:groupId", wrapper(group_r.ModifyGroupInfo)) imGroup.PUT("/group/:groupId", wrapper(group_r.ModifyGroupInfo))
imGroup.GET("/search/:code", wrapper(group_r.SearchGroup)) imGroup.GET("/search/:code", wrapper(group_r.SearchGroup))
imGroup.DELETE("/member/:groupId", wrapper(group_r.LeaveGroup)) imGroup.DELETE("/member/:groupId", wrapper(group_r.LeaveGroup))
...@@ -42,13 +42,14 @@ func InitRouter() *gin.Engine { ...@@ -42,13 +42,14 @@ func InitRouter() *gin.Engine {
imGroup.GET("/myRecent", wrapper(group_r.GetRecentGroup)) imGroup.GET("/myRecent", wrapper(group_r.GetRecentGroup))
imGroup.GET("/myPermanent", wrapper(group_r.GetMyGroup)) imGroup.GET("/myPermanent", wrapper(group_r.GetMyGroup))
// //
imGroup.GET("/visitors/:groupId", wrapper(group_r.GetGroupVisitors)) imGroup.GET("/visitors/:groupId", wrapper(group_r.GetGroupVisitorsV2))
imGroup.GET("/visitors2/:groupId", wrapper(group_r.GetGroupVisitors)) // 自测用,跟上面的反过来
imGroup.GET("/ownPublicGroup/:userExternalId", wrapper(group_r.GetOwnPublicGroup)) imGroup.GET("/ownPublicGroup/:userExternalId", wrapper(group_r.GetOwnPublicGroup))
//// 2.19的新接口 //// 2.19的新接口
imGroup.GET("/ownGroup", wrapper(group_r.GetOwnGroup)) imGroup.GET("/ownGroup", wrapper(group_r.GetOwnGroup))
imGroup.GET("/theirGroup/:userExternalId", wrapper(group_r.GetTheirGroups)) imGroup.GET("/theirGroup/:userExternalId", wrapper(group_r.GetTheirGroups))
imGroup.PUT("/pluginReady/:groupId", wrapper(group_r.PluginReady)) imGroup.PUT("/pluginReady/:groupId", wrapper(group_r.PluginReady))
imGroup.GET("/roomInfo/:groupId", wrapper(group_r.GetRoomInfo)) imGroup.GET("/roomInfo/:groupId", EncryptHandle, wrapper(group_r.GetRoomInfo)) // 进房
// //
imGroup.GET("/password/:groupId", wrapper(group_r.GetGroupPassword)) imGroup.GET("/password/:groupId", wrapper(group_r.GetGroupPassword))
imGroup.GET("/role/:groupId", wrapper(group_r.GetGroupRole)) imGroup.GET("/role/:groupId", wrapper(group_r.GetGroupRole))
...@@ -92,7 +93,7 @@ func InitRouter() *gin.Engine { ...@@ -92,7 +93,7 @@ func InitRouter() *gin.Engine {
imGroup.POST("/mic/speech/close", wrapper(group_r.GroupMicSpeechClose)) imGroup.POST("/mic/speech/close", wrapper(group_r.GroupMicSpeechClose))
imGroup.POST("/mic/mute", wrapper(group_r.GroupMicMute)) imGroup.POST("/mic/mute", wrapper(group_r.GroupMicMute))
imGroup.POST("/mic/unmute", wrapper(group_r.GroupMicUnmute)) imGroup.POST("/mic/unmute", wrapper(group_r.GroupMicUnmute))
imGroup.PUT("/in", wrapper(group_r.GroupIn)) imGroup.PUT("/in", wrapper(group_r.GroupIn)) // 进房
imGroup.POST("/leave", wrapper(group_r.GroupLeave)) imGroup.POST("/leave", wrapper(group_r.GroupLeave))
imGroup.POST("/kick", wrapper(group_r.GroupKick)) imGroup.POST("/kick", wrapper(group_r.GroupKick))
imGroup.PUT("/user/msg/status", wrapper(group_r.GroupUserMsg)) imGroup.PUT("/user/msg/status", wrapper(group_r.GroupUserMsg))
...@@ -106,7 +107,7 @@ func InitRouter() *gin.Engine { ...@@ -106,7 +107,7 @@ func InitRouter() *gin.Engine {
imGroup.POST("/mgr/clearScreen", wrapper(group_r.GroupMgrClearScreen)) imGroup.POST("/mgr/clearScreen", wrapper(group_r.GroupMgrClearScreen))
imGroup.GET("/online/users", wrapper(group_r.GroupInUsers)) imGroup.GET("/online/users", wrapper(group_r.GroupInUsers))
imGroup.GET("/online/users/new", wrapper(group_r.GroupInUserNew)) imGroup.GET("/online/users/new", wrapper(group_r.GroupInUserNew))
imGroup.GET("/country", wrapper(group_r.GetGroupByCountry)) imGroup.GET("/country", wrapper(group_r.GetGroupByCountryV2))
imGroup.GET("/country/prior", wrapper(group_r.GroupountryPrior)) imGroup.GET("/country/prior", wrapper(group_r.GroupountryPrior))
// //
imGroup.POST("/theme/custom", wrapper(group_r.GroupThemeAdd)) imGroup.POST("/theme/custom", wrapper(group_r.GroupThemeAdd))
......
...@@ -3,8 +3,10 @@ package test ...@@ -3,8 +3,10 @@ package test
import ( import (
"fmt" "fmt"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/utils" "git.hilo.cn/hilo-common/utils"
"github.com/jinzhu/now" "github.com/jinzhu/now"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/service/group_power_s" "hilo-group/domain/service/group_power_s"
...@@ -69,3 +71,14 @@ func TestGetRandomImProvider(t *testing.T) { ...@@ -69,3 +71,14 @@ func TestGetRandomImProvider(t *testing.T) {
fmt.Printf("true--------------times0:%v\n", times0) fmt.Printf("true--------------times0:%v\n", times0)
fmt.Printf("true--------------times1:%v\n", times1) fmt.Printf("true--------------times1:%v\n", times1)
} }
func TestMonthStar(t *testing.T) {
monthTime, err := time.Parse("200601", "202307")
if err != nil {
panic(err)
}
redisCli.InitCluster()
res, err := groupPower_c.GetGroupPowerStarRankPeriod(domain.CreateModelNil(), "month", 242, 1, 0, 10, monthTime.Format("2006-01-02"))
println(res)
println(err)
}
...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code ...@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS] [REDIS]
REDIS_HOST=47.244.34.27:6379 REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT] [JWT]
SECRET=hilo1632 SECRET=hilo1632
ISSUER_API=hiloApi ISSUER_API=hiloApi
......
package test
import (
"git.hilo.cn/hilo-common/domain"
"hilo-group/domain/cache/group_c"
"hilo-group/domain/model/user_m"
"testing"
)
func TestGetUserMap(t *testing.T) {
var userIds []uint64
for i := 0; i < 10502; i++ {
userIds = append(userIds, 7642)
}
res, err := user_m.GetUserMapByIds(domain.CreateModelNil(), userIds)
t.Logf("%v-%v", res, err)
}
func TestGetUserVipMap(t *testing.T) {
var userIds []uint64
for i := 0; i < 10502; i++ {
userIds = append(userIds, 7642)
}
res, err := user_m.BatchGetVips(userIds)
t.Logf("%v-%v", res, err)
}
func TestRemoveRoomVisit(t *testing.T) {
group_c.RemoveRoomVisitors(domain.CreateModelNil(), "HTGS#a47478749")
}