...
 
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 (
const (
MicPrefix = "mic:"
MicDayInvite = MicPrefix + "day:invite:${userId}:${date}" // string 自动被邀请上麦,1天一次,TTL:24H
MicGroupPowerOnMic = MicPrefix + "groupPower:${userId}:${date}" // 家族内群上麦分钟数
MicUserOnMic = MicPrefix + "user:onMic:${tz}:${userId}:${date}"
MicGroupOnMic = MicPrefix + "group:onMic:${groupId}" // 在群组麦位上的人 hset field:micIndex member:userId
)
func GetUserMicDayInvite(userId mysql.ID) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicDayInvite, fmt.Sprintf("%d", userId), date)
}
// 家族内群上麦分钟数
func GetMicGroupPowerOnMic(userId uint64) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicGroupPowerOnMic, fmt.Sprintf("%d", userId), date)
}
// 获取用户上麦时间
// 北京、沙特时间
func GetUserOnMicKey(userId uint64, tz, date string) string {
return redis_key.ReplaceKey(MicUserOnMic, tz, fmt.Sprintf("%d", userId), date)
}
// 获取群组麦位上的人
// 可能会有数据不一致,已原来麦位的key为准
// 这里用户快速获取群上麦位的人用,代替大量mget命令慢查询
func GetGroupOnMicUser(groupId string) string {
return redis_key.ReplaceKey(MicGroupOnMic, groupId)
}
package mic_k
// onMic异步入库
const (
OnMicQueue = "onMic:hilo_group"
)
func GetOnMicQueue() string {
return OnMicQueue
}
......@@ -249,6 +249,9 @@ const groupInUserDuration = "group_in_user_duration_{groupUuid}"
// 15天内进入房间的人数
const roomVisitCount = "room_visit_count"
// 15天内进入房间的人数 member groupId score 麦位有人的数量
const roomVisitCountZSet = "room_visit_count_zset"
// 用户进入过的房间及时间
const userEnterRoom = "enter_room_{userId}"
......@@ -757,18 +760,27 @@ func GetPrefixGroupMicNumType(groupUuid string) string {
return strings.Replace(groupMicNumType, "{groupUuid}", groupUuid, -1)
}
// Deprecated: 用户进房时间
// 用 uer:g:${group_id}代替
func GetPrefixGroupInUserDuration(groupUuid string) string {
return strings.Replace(groupInUserDuration, "{groupUuid}", groupUuid, -1)
}
// Deprecated: 用户进房时间
// 可用 uer:u:${user_id}代替
func GetUserEnterRoomKey(userId uint64) string {
return strings.Replace(userEnterRoom, "{userId}", strconv.FormatUint(userId, 10), -1)
}
// Deprecated: 用redis集群中的zset代替
func GetPrefixRoomVisitCount() string {
return roomVisitCount
}
func GetPrefixRoomVisitCountZset() string {
return roomVisitCountZSet
}
func GetPrefixSupportLevel(date string) string {
return strings.Replace(supportLevel, "{date}", date, -1)
}
......
......@@ -5,15 +5,24 @@ import (
"hilo-group/cron/gift_cron"
"hilo-group/cron/group_cron"
"hilo-group/cron/mic_cron"
"hilo-group/cron/user_cron"
)
func Init() {
user_cron.LoadSvipVipNoble() // 加载用户特权
if !config.IsMaster() {
return
}
gift_cron.SendGiftEventInit() // 礼物消息
gift_cron.GiftRemark() // 礼物消息补偿
//gift_cron.SendGiftEventInit() // 礼物消息
//gift_cron.GiftRemark() // 礼物消息补偿
gift_cron.SendGiftEvent() // 礼物事件
mic_cron.OnMicCheck() // 检查上麦
mic_cron.OnMicQueue() // 检查上麦-队列操作
group_cron.GroupPowerExpClear() // 清理家族经验/等级
group_cron.GroupPowerMonthRankAct()
//group_cron.GroupInEventInit() // 进房事件
//group_cron.CreateGroup() //
group_cron.CalcGroupSupport() // 群组扶持计算
//group_cron.CalcGroupSupport_OldData()
group_cron.GroupCountryListSort()
}
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
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/domain/service/group_power_s"
)
// 家族贡献月度排行榜发奖
func GroupPowerMonthRankAct() {
if !config.IsMaster() {
return
}
c := cron.New()
// 每月1号0:01结算发奖
spec := "0 1 0 1 * ?"
......
package group_cron
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/sdk/tencentyun"
"git.hilo.cn/hilo-common/utils"
"github.com/robfig/cron"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/group_e"
"hilo-group/domain/model/gift_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/service/group_s"
"time"
)
// 群组扶持计算
func CalcGroupSupport() {
if !config.IsMaster() {
return
}
c := cron.New()
//北京时间周一0点,过了一秒后,
spec := "1 0 0 * * 1"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("cron CalcGroupSupport start")
calcTime := time.Now().AddDate(0, 0, -1)
if err := group_s.NewGroupService(model.MyContext).GroupSupportResult(calcTime); err != nil {
model.Log.Errorf("cron CalcGroupSupport faild calcTime:%v, err:%v", calcTime, err)
return
}
model.Log.Infof("cron CalcGroupSupport after GroupSupportResult")
//全服发送H5
if err := sendGroupSupportH5(domain.CreateModelContext(model.MyContext)); err != nil {
model.Log.Errorf("cron CalcGroupSupport err:%v", err)
} else {
model.Log.Infof("cron CalcGroupSupport success")
}
})
c.Start()
}
func sendGroupSupportH5(model *domain.Model) error {
groupIds, err := group_m.GetAllGroupsSorted(model)
if err != nil {
return err
}
model.Log.Infof("SendGroupSupportH5 groupIds:%v", groupIds)
groupSupportH5 := group_m.GroupSupportH5{
CommonPublicMsg: group_m.CommonPublicMsg{
Type: group_e.GroupSupportH5,
},
H5: config.GetH5Config().GROUP_SUPPORT,
}
buffer, err := json.Marshal(groupSupportH5)
if err != nil {
model.Log.Errorf("publicScreenMsg AddSendGiftAsync json.Marshal(giftContent) err:%v", err)
return err
}
content := string(buffer)
//策略1:for循环,没有开启协程,100个停一下
for i, _ := range groupIds {
func(groupId string, content string) {
defer utils.CheckGoPanic()
model.Log.Infof("SendGroupSupportH5 groupId:%v", groupId)
txGroupId, err := group_m.ToTxGroupId(model, groupId)
// 公屏消息
if err == nil {
tencentyun.SendCustomMsg(model.Log, txGroupId, nil, content, "")
}
}(groupIds[i], content)
if i != 0 && i%100 == 0 {
//躺平1秒
time.Sleep(1 * time.Second)
}
}
return nil
}
// 群组扶持计算-旧数据
func CalcGroupSupport_OldData() {
if !config.IsMaster() {
return
}
c := cron.New()
spec := "0 27 10 29 8 ?"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("CalcGroupSupport_OldData start")
//beginTime, endTime, period := group_m.GetSupportLevelTime(time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
beginTime, _, period := group_m.GetSupportLevelTime(time.Now())
endTime := time.Unix(1693275900, 0)
g := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, Model: model}
records, err := g.BatchGetConsumeByRange(beginTime, endTime)
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData beginTime:%v, endTime:%v, err:%v", beginTime, endTime, err)
return
}
// 流水写入redis
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
for _, r := range records {
if r.SceneUid == "" || r.Consume <= 0 {
continue
}
_, err = model.RedisCluster.ZIncrBy(context.Background(), keyDiamond, float64(r.Consume), r.SceneUid).Result()
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, val:%d, member:%s, err:%v",
keyDiamond, r.Consume, r.SceneUid, err)
}
}
err = redisCli.SetExpire(model.RedisCluster, keyDiamond, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, err:%v", keyDiamond, err)
return
}
// 支持者写入redis
for _, r := range records {
if r.SceneUid == "" || r.C <= 0 {
continue
}
// 支持者列表
support := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, SceneUid: r.SceneUid, Model: model}
uids, err := support.BatchGetSupportList(model, beginTime, endTime)
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData beginTime:%v, endTime:%v, imGroupId:%v, err:%v", beginTime, endTime, r.SceneUid, err)
continue
}
if len(uids) <= 0 {
continue
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, r.SceneUid)
for _, uid := range uids {
err = model.RedisCluster.SAdd(context.Background(), keySupportNum, uid).Err()
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, UserId:%d, err:%v", keySupportNum, uid, err)
}
}
err = redisCli.SetExpire(model.RedisCluster, keySupportNum, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("AddSendGiftEventAsync groupSupport key:%s, err:%v", keySupportNum, err)
}
}
model.Log.Infof("CalcGroupSupport_OldData end")
})
c.Start()
}
package mic_cron
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/cache/mic_c"
"hilo-group/domain/event/mic_ev"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/mic_m"
"hilo-group/domain/service/group_mic_s"
"time"
)
func OnMicCheck() {
c := cron.New()
//一分钟执行一次
spec := "0 */1 * * * ?"
spec := "30 */1 * * * ?"
_ = c.AddFunc(spec, func() {
//获取麦上的所有人
var model = domain.CreateModelNil()
......@@ -20,14 +26,15 @@ func OnMicCheck() {
return
}
for _, groupId := range groupIds {
onGroupMicKey := mic_k.GetGroupOnMicUser(groupId) // 同步在mic上的人
//遍历每个麦位
for i := 1; i <= 30; i++ {
for i := 1; i <= group_m.MaxMicNum; i++ {
micUser, err := group_m.GetMicUser(model, groupId, i)
if err != nil {
model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err)
}
if micUser != nil {
if err := mic_ev.PublishOnMicEvent(model, &mic_ev.OnMicEvent{
if err := mic_c.QueueOnMic(model, &mic_ev.OnMicEvent{
GroupUuid: micUser.GroupUuid,
I: micUser.I,
ExternalId: micUser.ExternalId,
......@@ -35,11 +42,43 @@ func OnMicCheck() {
Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp,
}); err != nil {
model.Log.Errorf("PublishOnMicEvent fail:%v", err)
model.Log.Errorf("QueueOnMic fail:%v", err)
}
// 设置mic上的人
model.Redis.HSet(model, onGroupMicKey, i, micUser.UserId)
} else {
// 删除mic上的人
model.Redis.HDel(model, onGroupMicKey, fmt.Sprintf("%d", i))
}
}
}
})
c.Start()
}
func OnMicQueue() {
for i := 0; i < 4; i++ {
go func() {
for true {
model := domain.CreateModelNil()
if onMic := mic_c.BLPopQueueOnMic(model); onMic != nil {
start := time.Now()
// 群组上麦经验
if err := group_mic_s.NewGroupPowerService(model.MyContext).IncrGroupPowerOnMicExpAndTime(onMic.GroupUuid, onMic.UserId, onMic.Timestamp); err != nil {
model.Log.Errorf("cron micIn GroupPowerOnMicExp err:%v", err)
} else {
model.Log.Infof("cron micIn GroupPowerOnMicExp success, groupId:%v, userId:%v,cost:%vs", onMic.GroupUuid, onMic.UserId, time.Now().Sub(start).Seconds())
}
// 用户上麦
//if err := mic_m.IncrUserOnMic(model, onMic.UserId, onMic.Timestamp); err != nil {
//if err := mic_m.IncrUserOnMicV2(model, onMic.UserId); err != nil {
if err := mic_m.IncrUserOnMicV3(model, onMic.UserId); err != nil {
model.Log.Errorf("cron micIn IncrUserOnMic err:%v", err)
} else {
}
}
}
}()
}
}
package user_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/domain/cache/user_c"
)
// 加载数据到lru
func LoadSvipVipNoble() {
go user_c.LoadAllSvipVipNoble(domain.CreateModelNil()) // 启动先执行一次
c := cron.New()
spec := "0 */30 * * * ?"
_ = c.AddFunc(spec, func() {
model := domain.CreateModelNil()
user_c.LoadAllSvipVipNoble(model)
})
c.Start()
}
......@@ -22,7 +22,15 @@ type BillboardUserInfo struct {
Num uint64 `json:"num"`
}
func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]BillboardUserInfo, error) {
//榜单中用户信息
type GroupTop3ConsumeUser struct {
//用户基本信息
UserBase user_cv.TopConsumersUser `json:"userBase"`
//数值
Num uint64 `json:"num"`
}
func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]GroupTop3ConsumeUser, error) {
now := time.Now()
period := now.Format(utils.COMPACT_MONTH_FORMAT)
data, err := getGroupTop3Consume(period, groupId)
......@@ -59,7 +67,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
ret, err := saveGroupTop3Consume(period, groupId, diamonds)
model.Log.Infof("GetGroupTop3Consume SAVE ret = %d, err: %v", ret, err)
return result, nil
list := make([]GroupTop3ConsumeUser, 0, len(result))
for _, v := range result {
list = append(list, GroupTop3ConsumeUser{
UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick},
})
}
return list, nil
}
userIds := make([]uint64, 0)
......@@ -86,7 +102,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
})
}
}
return result, nil
list := make([]GroupTop3ConsumeUser, 0, len(result))
for _, v := range result {
list = append(list, GroupTop3ConsumeUser{
UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick},
})
}
return list, nil
}
func getGroupTop3Consume(period string, groupId string) (map[string]string, error) {
......
package diamond_cv
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
. "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model/bean_m"
"hilo-group/domain/model/diamond_m"
"hilo-group/myerr"
"strconv"
)
type CvDiamond struct {
......@@ -26,33 +20,6 @@ type CvDiamondBean struct {
BeanNum string `json:"beanNum"`
}
func GetDiamondBean(userId mysql.ID) (*CvDiamondBean, error) {
var diamondAccount diamond_m.DiamondAccount
err := mysql.Db.Where(&diamond_m.DiamondAccount{
UserId: userId,
}).First(&diamondAccount).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
diamondAccount = diamond_m.DiamondAccount{
DiamondNum: 0,
}
}
return nil, err
}
var beanAccount bean_m.BeanAccount
err = mysql.Db.Where(&bean_m.BeanAccount{
UserId: userId,
}).First(&beanAccount).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
beanAccount = bean_m.BeanAccount{
BeanNum: 0,
}
}
}
return &CvDiamondBean{DiamondNum: diamondAccount.DiamondNum, BeanNum: strconv.FormatFloat(float64(beanAccount.BeanNum)/100, 'f', 2, 64)}, nil
}
type CvDiamondDetail struct {
//1:增加 2:减少
......@@ -74,113 +41,4 @@ func GetDiamond(userId mysql.ID) (*CvDiamond, error) {
return nil, err
}
return &CvDiamond{DiamondNum: NumToUint32(&diamondAccount.DiamondNum), PinkDiamondNum: NumToUint32(&diamondAccount.PinkDiamondNum)}, nil
}
func GetDiamondBalances(userIds []mysql.ID) (map[mysql.ID]mysql.Num, error) {
result := make(map[mysql.ID]mysql.Num, len(userIds))
data := make([]diamond_m.DiamondAccount, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&data).Error
if err != nil {
return nil, err
}
for _, i := range data {
result[i.UserId] = i.DiamondNum
}
return result, nil
}
//充值记录
func GetDiamondBuyList(userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
var diamondAccountDetails []diamond_m.DiamondAccountDetail
if err := mysql.Db.Model(&diamond_m.DiamondAccountDetail{}).
Where("user_id = ? AND operate_type in (?)", userId, []uint8{diamond_e.BuyDiamond, diamond_e.DealerTransfer, diamond_e.Checkout, diamond_e.PayerMax, diamond_e.Paypal}).
Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
return nil, err
}
var cvDiamondDetails []*CvDiamondDetail
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
//钻石明细,不包括充值
func GetDiamondDetailList(model *domain.Model, userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
diamondAccountDetails := make([]*diamond_m.DiamondAccountDetail, 0)
offset := (pageIndex - 1) * pageSize
optList := []int{int(diamond_e.BuyDiamond), int(diamond_e.DealerTransfer), int(diamond_e.Checkout), int(diamond_e.PayerMax)}
details := make([]*diamond_m.DiamondAccountDetail, 0)
if offset == 0 { // 首页请求数据,获取 pageSize*3 条过滤返回
sql := "select * from diamond_account_detail where user_id = ? order by id desc limit ?"
if err := mysql.Db.WithContext(model).Raw(sql, userId, pageSize*3).Find(&details).Error; err != nil {
return nil, myerr.WrapErr(err)
}
notInMap := make(map[int]bool)
for _, v := range optList {
notInMap[v] = true
}
for _, v := range details {
if _, ok := notInMap[int(v.OperateType)]; !ok {
diamondAccountDetails = append(diamondAccountDetails, v)
}
}
if len(diamondAccountDetails) > pageSize {
diamondAccountDetails = diamondAccountDetails[:pageSize]
}
}
// 非首页,或者首页没取满 pageSize 条
if offset > 0 || (len(details) == pageSize*3 && len(diamondAccountDetails) < pageSize) {
diamondAccountDetails = make([]*diamond_m.DiamondAccountDetail, 0)
sql := "select * from diamond_account_detail where user_id = ? and operate_type not in (?) order by id desc limit ?,?"
if err := mysql.Db.WithContext(model).Raw(sql, userId, optList, offset, pageSize).
Find(&diamondAccountDetails).Error; err != nil {
return nil, myerr.WrapErr(err)
}
}
//if err := mysql.Db.Table("diamond_account_detail FORCE INDEX(Index_1)").
// Where("user_id = ? AND operate_type not in (?)", userId,
// []int{int(diamond_m2.BuyDiamond), int(diamond_m2.DealerTransfer), int(diamond_m2.Checkout), int(diamond_m2.PayerMax)}).
// Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
// return nil, myerr.WrapErr(err)
//}
cvDiamondDetails := []*CvDiamondDetail{}
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
//粉钻流水,包含充值
func GetPinkDiamondDetailList(userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
var diamondAccountDetails []diamond_m.DiamondPinkAccountDetail
if err := mysql.Db.Model(&diamond_m.DiamondPinkAccountDetail{}).
Where("user_id = ?", userId).
Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var cvDiamondDetails []*CvDiamondDetail
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
}
\ No newline at end of file
......@@ -123,6 +123,13 @@ type MemberDetail struct {
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 {
GroupBasicInfo
......@@ -133,14 +140,14 @@ type GroupDetail struct {
ThemeId uint64 `json:"themeId"`
ThemeUrl string `json:"themeUrl"`
// 1:官方 2:自定义
ThemeType uint8 `json:"themeType"`
Role group_e.GroupRoleType `json:"role"`
MsgStatus uint8 `json:"msgStatus"` // 消息提醒状态
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
TotalConsume uint64 `json:"totalConsume"` // 群内消费总额
TopConsumers []billboard_cv.BillboardUserInfo `json:"topConsumers"` // 月最高消费三甲
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏的数字点数
ThemeType uint8 `json:"themeType"`
Role group_e.GroupRoleType `json:"role"`
MsgStatus uint8 `json:"msgStatus"` // 消息提醒状态
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
TotalConsume uint64 `json:"totalConsume"` // 群内消费总额
TopConsumers []billboard_cv.GroupTop3ConsumeUser `json:"topConsumers"` // 月最高消费三甲
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏的数字点数
// "AppDefinedData": 群组维度的自定义字段 【暂时不用】
RoleMembers []RoleMemberInfo `json:"role_members"`
Owner *user_cv.CvUserDetail `json:"owner"` // 群主信息
......@@ -166,20 +173,20 @@ type RoomInfo struct {
ThemeId uint64 `json:"themeId"`
ThemeUrl string `json:"themeUrl"`
// 1:官方 2:自定义
ThemeType uint8 `json:"themeType"`
Role group_e.GroupRoleType `json:"role"`
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏类型
RoleMembers []SimpleRoleInfo `json:"roleMembers"`
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
Banners []BannerElement `json:"banners"`
LuckyWheel LuckyWheelState `json:"luckyWheel"`
TotalConsume uint64 `json:"totalConsume"`
GameConfig *game_m.GameConfig `json:"gameConfig"`
Owner *user_cv.CvUserDetail `json:"owner"`
EntryEffectType int `json:"entryEffectType"` // 进场特效类型 1: CP 2:神秘人 3:贵族 4:vip
CpUserAvatar string `json:"cpUserAvatar"` // cp对象头像
CpLevel int `json:"cpLevel"` // cp等级
ThemeType uint8 `json:"themeType"`
Role group_e.GroupRoleType `json:"role"`
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏类型
RoleMembers []SimpleRoleInfo `json:"roleMembers"`
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
Banners []BannerElement `json:"banners"`
LuckyWheel LuckyWheelState `json:"luckyWheel"`
TotalConsume uint64 `json:"totalConsume"`
GameConfig *game_m.GameConfig `json:"gameConfig"`
Owner *user_cv.RoomInfoOwner `json:"owner"`
EntryEffectType int `json:"entryEffectType"` // 进场特效类型 1: CP 2:神秘人 3:贵族 4:vip
CpUserAvatar string `json:"cpUserAvatar"` // cp对象头像
CpLevel int `json:"cpLevel"` // cp等级
}
type SupportPageDetail struct {
......@@ -244,13 +251,24 @@ type CvCountry struct {
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)
groupInfo, err := group_m.BatchGetGroupInfo(model, groupIds)
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
}
// todo: 可以移到后面,减小查询范围,因为roomMicUserMap不影响排序
roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds)
......@@ -303,7 +321,7 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [
if err != nil {
return nil, 0, err
}
model.Log.Infof("BuildJoinedGroupInfo, roomEnterTime: %v", roomEnterTime)
//model.Log.Infof("BuildJoinedGroupInfo, roomEnterTime: %v", roomEnterTime)
// 排序优先级V8.0版本
sort.Slice(groupIds, func(i, j int) bool {
......@@ -427,39 +445,219 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [
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)
// 填充用户最近进房
func BuildRecentGroupInfo(myService *domain.Service, myUserId uint64, originGroupIds []string, roomEnterTime map[string]int64) ([]JoinedGroupInfo, int, error) {
model := domain.CreateModel(myService.CtxAndDb)
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)
if err != nil {
return nil, err
return nil, 0, err
}
uids := make([]uint64, 0)
micUsersMap := make(map[string][]uint64, 0)
for _, v := range groupInfo {
micUsersMap[v.ImGroupId] = make([]uint64, 0)
for _, i := range groupInfo {
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 {
micUsersMap[v.ImGroupId] = u[0:4]
micUsersMap[i.ImGroupId] = u[0:4]
} 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)
userTiny, err := user_cv.GetUserTinyMap(uids)
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)
if err != nil {
return nil, err
......@@ -528,10 +726,10 @@ func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*gr
for _, v := range groupInfo {
g := v
i := v.ImGroupId
micUsers := make([]user_cv.CvUserTiny, 0)
for _, j := range micUsersMap[i] {
micUsers = append(micUsers, userTiny[j])
}
//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 {
......@@ -580,7 +778,7 @@ func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*gr
MicNumType: int(g.MicNumType),
GroupMedals: medals,
},
HasOnMic: len(micUsers) > 0,
//HasOnMic: len(micUsers) > 0,
GroupPowerId: powerIds[g.Owner],
GroupPowerName: powerNames[g.Owner],
GroupPowerNameplate: powerNameplates[g.Owner],
......@@ -591,7 +789,7 @@ func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*gr
Grade: powerGrades[g.Owner],
},
},
MicUsers: micUsers,
//MicUsers: micUsers,
RoomUserCount: uint(roomCount[i]),
MaxStage: maxStage,
GameTypes: games[g.TxGroupId],
......
package user_cv
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
......@@ -69,6 +70,25 @@ type CvUserDetail struct {
CountryManager *country_cv.CVCountryManager `json:"countryManager,omitempty"` // 国家管理员
}
type RoomInfoOwner struct {
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号
//是否VIP用户
IsVip bool `json:"isVip"`
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
Medals []uint32 `json:"medals"` // 勋章列表
Noble noble_cv.CvNoble `json:"noble"` // 当前的
WealthUserGrade uint32 `json:"wealthUserGrade"` //财富等级
CharmUserGrade uint32 `json:"charmUserGrade"` //魅力等级
MyGroupPowerName string `json:"myGroupPowerName"` // 当前用户所在势力绑定群组的名称
GroupPower GroupPower `json:"groupPower"` // 当前用户势力信息
}
type GroupPower struct {
Id uint64 `json:"id"` // 群主所在的势力ID
Icon string `json:"icon"` // 家族头像
......@@ -150,6 +170,45 @@ type CvUserExtend struct {
ActiveGrade uint32 `json:"activityUserGrade"`
}
type CvGroupMember struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//是否默认头像 true:是 false:不是
DefaultAvatar *bool `json:"defaultAvatar"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
//签名,不存在为nil
Description *string `json:"description"`
Birthday *uint64 `json:"birthday"`
//邀请码
Code *string `json:"code"`
//国家,不存在为nil
Country *string `json:"country"`
//国旗图标,不存在为nil
CountryIcon *string `json:"countryIcon"`
Sex *uint8 `json:"sex"`
//是否代理管理员, 只有自己查自己的时候才有值,其他情况为nil
IsAgentMgr *bool `json:"isAgentMgr"`
//是否展示年龄, 是本人才有数据,看其他用户均为nil
IsShowAge *uint8 `json:"isShowAge"`
//是否工会成员, 只有是自己查自己,这个才有值,其它全为nil, 20220329 数据开放:原因:产品1对1视频聊天中,公会用户视频需要送礼物。改为: 全部人可以知道是否是公会用户。
IsTradeUnion *bool `json:"isTradeUnion"`
//工会成员,是否开启了,匹配通知,只有 isTradeUnion值为true,这里才有值,
IsTradeUnionMatchNotification *bool `json:"isTradeUnionMatchNotification"`
//是否VIP用户
IsVip bool `json:"isVip"`
Ride property_cv.CvProperty `json:"ride"` // 当前使用的座驾
Noble noble_cv.CvNoble `json:"noble"` // 当前的
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
WealthGrade uint32 `json:"wealthUserGrade"`
CharmGrade uint32 `json:"charmUserGrade"`
ActiveGrade uint32 `json:"activityUserGrade"`
}
// 批量获取用户tiny信息
func GetUserTinyMap(userIds []mysql.ID) (map[mysql.ID]CvUserTiny, error) {
userTinys, _, err := GetUserTinys(userIds)
......@@ -849,16 +908,122 @@ func GetUserDetail(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*Cv
noble, superManagerMap[userId], myGroups, phoneInfo, thirdList, cvCountryManager)
}
//群主信息
func GetRoomInfoOwner(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*CvUserDetail, error) {
model.Log.Infof("GetUserDetail %d begin", userId)
var user user_m.User
var err error
if err = mysql.Db.First(&user, userId).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var wealthUserScore user_m.MatchWealthUserScore
if err := mysql.Db.Model(&user_m.MatchWealthUserScore{}).Where(&user_m.MatchWealthUserScore{UserId: userId}).First(&wealthUserScore).Error; err != nil {
if err != nil {
if err == gorm.ErrRecordNotFound {
wealthUserScore = user_m.MatchWealthUserScore{
UserId: userId,
Score: 0,
Grade: 0,
}
} else {
return nil, myerr.WrapErr(err)
}
}
}
var charmUserScore user_m.MatchCharmUserScore
if err := mysql.Db.Model(&user_m.MatchCharmUserScore{}).Where(&user_m.MatchCharmUserScore{
UserId: userId,
}).First(&charmUserScore).Error; err != nil {
if err != nil {
if err == gorm.ErrRecordNotFound {
charmUserScore = user_m.MatchCharmUserScore{
UserId: userId,
Score: 0,
Grade: 0,
}
} else {
return nil, myerr.WrapErr(err)
}
}
}
isVip, expireTime, err := user_m.IsVip(userId)
if err != nil {
return nil, myerr.WrapErr(err)
}
svip, err := rpc.GetUserSvip(model, userId)
if err != nil {
return nil, myerr.WrapErr(err)
}
medals := make(map[uint64][]uint32, 0)
medals[userId], err = user_m.GetUserMedalMerge(model.Log, mysql.Db, userId)
if err != nil {
return nil, err
}
medals, medalInfo, err := medal_cv.GetMedalInfoMap(mysql.Db, medals)
if err != nil {
return nil, err
}
groupPowerId, groupPowerName, err := groupPower_m.GetUserGroupPower(model, userId)
if err != nil {
return nil, err
}
powers := map[mysql.ID]uint64{userId: groupPowerId}
powerNames := map[mysql.ID]string{userId: groupPowerName}
groupPowerInfos, err := groupPower_m.MGetGroupPowerInfoMap(model, []mysql.ID{groupPowerId})
groupPowerGrades, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{groupPowerId})
groupPowerUsers, err := groupPower_m.MGetGroupPowerUsers(model, []mysql.ID{groupPowerId})
var memberMax int
grade := groupPowerGrades[groupPowerId].Grade
if grade >= groupPower_e.GroupPowerGrade0 && grade <= groupPower_e.GroupPowerGradeMax {
if grade == groupPower_e.GroupPowerGrade0 {
memberMax = 300
}
if grade == groupPower_e.GroupPowerGrade1 {
memberMax = 500
}
if grade == groupPower_e.GroupPowerGrade2 {
memberMax = 800
}
if grade == groupPower_e.GroupPowerGrade3 {
memberMax = 1200
}
}
memberNum := len(groupPowerUsers[groupPowerId])
if memberNum > memberMax {
memberMax = memberNum
}
groupPowerMembers := [2]int{memberNum, memberMax} // 0->memberNum 1->memberLimit
noble, err := noble_m.FindActiveNoble(mysql.Db, userId)
if err != nil {
return nil, err
}
return userToDetailOne(model, &user, myUserId, nil, false, false,
map[mysql.ID]Relation{}, isVip, expireTime, svip, nil, property_cv.CvProperty{}, wealthUserScore.Grade, charmUserScore.Grade,
0, medals[userId], medalInfo[userId], "", powers[userId], powerNames[userId], groupPowerInfos[groupPowerId], groupPowerGrades[groupPowerId], groupPowerMembers,
noble, false, nil, nil, nil, nil)
}
// 单用户版,简化参数
func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.UserTradeUnion, isLike bool, likeMe bool, hvMap map[mysql.ID]Relation,
isVip bool, vipExpireTime *int64, svip rpc.CvSvip, headwear *headwear_cv.CvHeadwear, ride property_cv.CvProperty, wealthGrade uint32, charmGrade uint32, activityGrade uint32,
medals []uint32, medalInfo []medal_cv.CvMedal, room string, power uint64, powerName string, powerInfo groupPower_m.GroupPowerInfo, grade groupPower_m.GroupPowerGrade, members [2]int, noble *noble_m.UserNoble, isOfficialStaff bool,
myGroups []group_m.GroupInfo, phoneInfo *user_m.UserPhoneInfo, thirdList []int8, countryManager *country_cv.CVCountryManager) (*CvUserDetail, error) {
room, err := group_m.ToTxGroupId(model, room)
if err != nil {
model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err)
room = ""
if len(room) > 0 {
var err error
room, err = group_m.ToTxGroupId(model, room)
if err != nil {
model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err)
room = ""
}
}
cvUserDetail := &CvUserDetail{
......@@ -1288,3 +1453,38 @@ func getMedalInfo(db *gorm.DB, medals []uint32) ([]uint32, []medal_cv.CvMedal, e
}
return validMedals, medalInfo, nil
}
func UserDetailToRoomInfoOwner(user *CvUserDetail) *RoomInfoOwner {
return &RoomInfoOwner{
Avatar: user.Avatar,
ExternalId: user.ExternalId,
Nick: user.Nick,
IsPrettyCode: user.IsPrettyCode,
IsVip: user.IsVip,
Svip: user.Svip,
Medals: user.Medals,
Noble: user.Noble,
WealthUserGrade: user.WealthUserGrade,
CharmUserGrade: user.CharmUserGrade,
MyGroupPowerName: user.MyGroupPowerName,
GroupPower: user.GroupPower,
}
}
type TopConsumersUser struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
}
func CvUserExtendToCvGroupMember(detail CvUserExtend) CvGroupMember {
jData, _ := json.Marshal(detail)
res := CvGroupMember{}
_ = json.Unmarshal(jData, &res)
return res
}
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT]
SECRET=hilo1632
ISSUER_API=hiloApi
......
......@@ -9,15 +9,18 @@ import (
)
type gameAutoJoinMsg struct {
TraceId string
Token string
EnterType string
GameCode string
TraceId string
Token string
EnterType string
GameCode string
Is1V1 string
GameMode string
Is1V1Robot string
}
func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode string) error {
func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode, is1V1, gameMode, is1V1Robot string) error {
key := game_e.GetAutoMathEnterRoom(userId, imGroupId)
info := gameAutoJoinMsg{traceId, token, enterType, gameCode}
info := gameAutoJoinMsg{traceId, token, enterType, gameCode, is1V1, gameMode, is1V1Robot}
data, err := json.Marshal(info)
if err != nil {
return err
......@@ -26,7 +29,7 @@ func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, g
if err != nil {
return err
}
redisCli.GetRedis().Expire(context.Background(), key, time.Second*3)
redisCli.GetRedis().Expire(context.Background(), key, time.Second*10)
return nil
}
......
package gift_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/domain/event/gift_ev"
"time"
)
const EventSendGiftHiloGroupQueue = "send:gift:queue:hilo_group"
// redis pop event sendGift
func BLPopQueueSendGift(model *domain.Model) *gift_ev.SendGiftEvent {
var res *gift_ev.SendGiftEvent
queue := EventSendGiftHiloGroupQueue
strs, err := model.RedisCluster.BLPop(model, time.Second, queue).Result()
if err != nil {
if err != redis.Nil {
model.Log.Errorf("BLPopQueueSendGift fail:%v", err)
}
return nil
}
if len(strs) >= 2 {
content := strs[1]
res = new(gift_ev.SendGiftEvent)
if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopQueueSendGift json fail:%v", err)
return nil
}
return res
}
return nil
}
package groupPower_c
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/go-redis/redis/v8"
"github.com/jinzhu/now"
"github.com/pkg/errors"
"github.com/spf13/cast"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/groupPower_k"
"time"
)
// 家族之星-排名
type GroupPowerStarRank struct {
Period string
GroupPowerId mysql.ID
UserId mysql.ID
Type groupPower_e.GroupPowerStarType
Score mysql.Num
}
// 增加家族之星分数
func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num) error {
ttl := map[string]time.Duration{
"day": time.Hour * 24 * 7,
"week": time.Hour * 24 * 7 * 30,
"month": time.Hour * 24 * 7 * 30 * 2,
}
for _, period := range []string{"day", "week", "month"} {
date := ""
switch period {
case "day":
date = time.Now().Format("2006-01-02")
case "week":
date = now.BeginningOfWeek().Format("2006-01-02")
case "month":
date = now.BeginningOfMonth().Format("2006-01-02")
}
key := groupPower_k.GetGroupPowerStarRankKey(_type, period, groupPowerId, date)
model.RedisCluster.ZIncrBy(model, key, float64(score), fmt.Sprintf("%d", userId))
model.RedisCluster.Expire(model, key, ttl[period])
}
return nil
}
// 获取家族之星排行
// param period: day|week|month
func GetGroupPowerStarRankPeriod(model *domain.Model, period string, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, targetDate ...string) ([]*GroupPowerStarRank, error) {
var res []*GroupPowerStarRank
date := ""
switch period {
case "day":
date = time.Now().Format("2006-01-02")
case "week":
date = now.BeginningOfWeek().Format("2006-01-02")
case "month":
date = now.BeginningOfMonth().Format("2006-01-02")
}
if len(date) <= 0 {
return res, errors.New("illegal date")
}
if len(targetDate) > 0 {
date = targetDate[0]
}
key := groupPower_k.GetGroupPowerStarRankKey(_type, period, groupPowerId, date)
rows, err := model.RedisCluster.ZRevRangeByScoreWithScores(model, key, &redis.ZRangeBy{
Min: "-inf",
Max: "+inf",
Offset: int64(offset),
Count: int64(limit),
}).Result()
if err != nil {
model.Log.Errorf("GetGroupPowerStarRankPeriod fail:%v", err)
return res, err
}
for _, v := range rows {
res = append(res, &GroupPowerStarRank{
Period: period,
GroupPowerId: groupPowerId,
UserId: cast.ToUint64(v.Member),
Type: _type,
Score: mysql.Num(v.Score),
})
}
return res, nil
}
// 获取家族之星三个排行榜的各自第一名
func GetGroupPowerMonthStartTop1(model *domain.Model, groupPowerId mysql.ID) ([]*GroupPowerStarRank, error) {
var res []*GroupPowerStarRank
r1, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeFamous, 0, 1)
if err != nil {
return res, err
}
r2, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeActive, 0, 1)
if err != nil {
return res, err
}
r3, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeCharm, 0, 1)
if err != nil {
return res, err
}
res = append(res, r1...)
res = append(res, r2...)
res = append(res, r3...)
return res, nil
}
package group_c
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key/group_k"
"strconv"
"time"
)
// 用户进房
func ZAddUserEnterRoom(model *domain.Model, userId uint64, imGroupId string) {
userKey := group_k.GetUserEnterRoomUserKey(userId)
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
if err := model.Redis.ZAdd(model, userKey, &redis.Z{
Score: float64(time.Now().Unix()),
Member: imGroupId,
}).Err(); err != nil {
model.Log.Errorf("ZAddUserEnterRoom user fail:%v", err)
}
if err := model.Redis.ZAdd(model, groupKey, &redis.Z{
Score: float64(time.Now().Unix()),
Member: userId,
}).Err(); err != nil {
model.Log.Errorf("ZAddUserEnterRoom room fail:%v", err)
}
}
// 获取最近房间访客
// 15天
func GetLastRoomVisitors(model *domain.Model, imGroupId string) (userIds []uint64) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
res, err := model.Redis.ZRangeByScore(model, groupKey, &redis.ZRangeBy{
Min: fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix()),
Max: "+inf",
}).Result()
if err != nil {
return
}
for _, u := range res {
uid, _ := strconv.ParseUint(u, 10, 64)
if uid > 0 {
userIds = append(userIds, uid)
}
}
return
}
// 获取最近进入的房间
// 3个月
func GetUserRecentRooms(model *domain.Model, userId uint64, offset, limit int64) (imGroupIds []string, roomEnterTime map[string]int64) {
roomEnterTime = make(map[string]int64)
userKey := group_k.GetUserEnterRoomUserKey(userId)
res, err := model.Redis.ZRevRangeByScoreWithScores(model, userKey, &redis.ZRangeBy{
Min: fmt.Sprintf("%d", time.Now().AddDate(0, -3, 0).Unix()),
Max: "+inf",
Offset: offset,
Count: limit,
}).Result()
if err != nil {
return
}
for _, v := range res {
imGroupId := cast.ToString(v.Member)
imGroupIds = append(imGroupIds, imGroupId)
roomEnterTime[imGroupId] = int64(v.Score)
}
return
}
// 清理房间访客
// 15天前访问的
func RemoveRoomVisitors(model *domain.Model, imGroupId string) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
n, err := model.Redis.ZRemRangeByScore(model, groupKey, "-inf", fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix())).Result()
if err != nil {
model.Log.Errorf("RemoveRoomVisitors fail:%v", err)
} else {
model.Log.Infof("RemoveRoomVisitors key:%v,n:%v", groupKey, n)
}
}
......@@ -83,17 +83,17 @@ func SetGroupMemberTTL(groupId string, ttl time.Duration) (bool, error) {
func GetGroupConsume(groupId string) (uint64, error) {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Get(context.Background(), key).Uint64()
return redisCli.RedisClusterClient.Get(context.Background(), key).Uint64()
}
func SetGroupConsume(groupId string, consume uint64, ttl time.Duration) error {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Set(context.Background(), key, consume, ttl).Err()
return redisCli.RedisClusterClient.Set(context.Background(), key, consume, ttl).Err()
}
func ClearGroupConsume(groupId string) error {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Del(context.Background(), key).Err()
return redisCli.RedisClusterClient.Del(context.Background(), key).Err()
}
// 增加编辑用户cd
......
package mic_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/mic_ev"
"time"
)
// redis queue on mic
func QueueOnMic(model *domain.Model, onMic *mic_ev.OnMicEvent) error {
queue := mic_k.GetOnMicQueue()
onMic.Ts = time.Now().UnixNano() // 给一个时间戳
body, _ := json.Marshal(onMic)
return model.RedisCluster.RPush(model, queue, string(body)).Err()
}
// redis pop on mic
func BLPopQueueOnMic(model *domain.Model) *mic_ev.OnMicEvent {
var res *mic_ev.OnMicEvent
queue := mic_k.GetOnMicQueue()
strs, err := model.RedisCluster.BLPop(model, time.Second, queue).Result()
if err != nil {
if err != redis.Nil {
model.Log.Errorf("BLPopQueueOnMic fail:%v", err)
}
return nil
}
if len(strs) >= 2 {
content := strs[1]
res = new(mic_ev.OnMicEvent)
if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopQueueOnMic json fail:%v", err)
return nil
}
return res
}
return nil
}
......@@ -27,17 +27,17 @@ func SetJSON(model *domain.Model, key string, obj interface{}) (err error) {
if err != nil {
return err
}
return model.Redis.Set(model.Context, key, value, DEFAULT_TTL).Err()
return model.RedisCluster.Set(model.Context, key, value, DEFAULT_TTL).Err()
}
// 获取redis中json结构体
// return err: may redisV8.Nil
func GetJSON(model *domain.Model, key string, obj interface{}) (err error) {
var value []byte
defer func() {
model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err)
}()
value, err = model.Redis.Get(model.Context, key).Bytes()
//defer func() {
// model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err)
//}()
value, err = model.RedisCluster.Get(model.Context, key).Bytes()
if err != nil {
// may redisV2.Nil
return
......@@ -59,7 +59,7 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
if time.Now().After(deadline) {
return false
}
flag, err := model.Redis.SetNX(model, key, "1", expireTimeout).Result()
flag, err := model.RedisCluster.SetNX(model, key, "1", expireTimeout).Result()
if err != nil || !flag {
time.Sleep(time.Millisecond * 10)
} else {
......@@ -70,5 +70,5 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
// 解锁
func UnLock(model *domain.Model, key string) {
model.Redis.Del(model, key)
model.RedisCluster.Del(model, key)
}
package res_c
import (
"context"
"git.hilo.cn/hilo-common/domain"
"hilo-group/_const/redis_key"
"github.com/bluele/gcache"
"hilo-group/domain/model/res_m"
"time"
)
// 统一改成lru
var countryIconLru = gcache.New(1000).LRU().Build()
var countryIconKey = "country:icon"
var countryAreaLru = gcache.New(1000).LRU().Build()
var countryAreaKey = "country:area"
func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
m, err := GetAllCountryIcon(model)
if err != nil || len(m) <= 0 {
......@@ -24,17 +30,22 @@ func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
}
func GetAllCountryIcon(model *domain.Model) (map[string]string, error) {
key := redis_key.GetCountryIconKey()
return model.Redis.HGetAll(context.Background(), key).Result()
//key := redis_key.GetCountryIconKey()
if data, err := countryIconLru.Get(countryIconKey); err == nil {
return data.(map[string]string), nil
}
//return model.Redis.HGetAll(context.Background(), key).Result()
return map[string]string{}, nil
}
func SaveAllCountryIcon(model *domain.Model, icons map[string]string) (int64, error) {
key := redis_key.GetCountryIconKey()
ret, err := model.Redis.HSet(context.Background(), key, icons).Result()
if err == nil {
model.Redis.Expire(context.Background(), key, time.Minute*10)
}
return ret, err
func SaveAllCountryIcon(model *domain.Model, icons map[string]string) {
//key := redis_key.GetCountryIconKey()
//ret, err := model.Redis.HSet(context.Background(), key, icons).Result()
//if err == nil {
// model.Redis.Expire(context.Background(), key, time.Minute*10)
//}
//return ret, err
_ = countryIconLru.SetWithExpire(countryIconKey, icons, time.Minute*10)
}
func GetCountryAreaMap(model *domain.Model) (map[string]string, error) {
......@@ -53,15 +64,20 @@ func GetCountryAreaMap(model *domain.Model) (map[string]string, error) {
}
func GetAllCountryArea(model *domain.Model) (map[string]string, error) {
key := redis_key.GetCountryAreaKey()
return model.Redis.HGetAll(context.Background(), key).Result()
//key := redis_key.GetCountryAreaKey()
//return model.Redis.HGetAll(context.Background(), key).Result()
if data, err := countryAreaLru.Get(countryAreaKey); err == nil {
return data.(map[string]string), nil
}
return map[string]string{}, nil
}
func SaveAllCountryArea(model *domain.Model, data map[string]string) (int64, error) {
key := redis_key.GetCountryAreaKey()
ret, err := model.Redis.HSet(context.Background(), key, data).Result()
if err == nil {
model.Redis.Expire(context.Background(), key, time.Minute*10)
}
return ret, err
func SaveAllCountryArea(model *domain.Model, data map[string]string) {
//key := redis_key.GetCountryAreaKey()
//ret, err := model.Redis.HSet(context.Background(), key, data).Result()
//if err == nil {
// model.Redis.Expire(context.Background(), key, time.Minute*10)
//}
//return ret, err
_ = countryAreaLru.SetWithExpire(countryAreaKey, data, time.Minute*10)
}
......@@ -2,42 +2,44 @@ package room_c
import (
"context"
"errors"
"fmt"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli"
"github.com/bluele/gcache"
redis2 "github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key"
"strconv"
"hilo-group/_const/redis_key/group_k"
"time"
)
// 处理访问房间的相关缓存
func ProcessRoomVisit(groupId string, userId uint64) error {
key := redis_key.GetPrefixGroupInUserDuration(groupId)
now := time.Now()
ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
Score: float64(now.Unix()),
Member: userId,
}).Result()
if err != nil {
return err
}
mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret)
// 每群定时清一次数据可以了
if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL))
if err == nil {
mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc)
} else {
mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error())
}
}
//key := redis_key.GetPrefixGroupInUserDuration(groupId)
//now := time.Now()
//ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
// Score: float64(now.Unix()),
// Member: userId,
//}).Result()
//if err != nil {
// return err
//}
//mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret)
//
//// 每群定时清一次数据可以了
//if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
// rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL))
// if err == nil {
// mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc)
// } else {
// mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error())
// }
//}
// 马上更新roomVisitCount
if _, err := GetSetRoomVisitCount(groupId); err != nil {
mylogrus.MyLog.Warnf("ProcessRoomVisit, failed for key %s, err: %s", key, err.Error())
mylogrus.MyLog.Errorf("ProcessRoomVisit, failed for groupId %s, err: %s", groupId, err.Error())
}
return nil
......@@ -59,15 +61,17 @@ func ProcessUserRoomVisit(userId uint64, groupId string) error {
}
// 查询用户访问过的房间及其时间
// todo 去掉查询,redis性能
func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
result := make(map[string]int64, 0)
return result, nil
key := redis_key.GetUserEnterRoomKey(userId)
ret, err := redisCli.GetRedis().ZRangeWithScores(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, err
}
mylogrus.MyLog.Infof("GetUserRoomVisit, ZRangeWithScores %s, return %v", key, ret)
//mylogrus.MyLog.Infof("GetUserRoomVisit, ZRangeWithScores %s, return %v", key, ret)
result := make(map[string]int64, 0)
for _, i := range ret {
result[i.Member.(string)] = int64(i.Score)
}
......@@ -75,53 +79,63 @@ func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
}
// 批量获取房间访问人数
// 带上lru
var roomVisitCountLru = gcache.New(100).LRU().Build()
func MGetRoomVisitCount(groupIds []string) (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
visit := make(map[string]string)
if len(groupIds) <= 0 {
return visit, nil
}
res, err := redisCli.GetRedis().HMGet(context.Background(), key, groupIds...).Result()
lKey := "room:visit:count"
if data, err := roomVisitCountLru.Get(lKey); err == nil {
return data.(map[string]string), nil
}
// 用redisCluster中的zset代替,只是取出大于10的
zKey := redis_key.GetPrefixRoomVisitCountZset()
cnt := 10
if !config.AppIsRelease() {
cnt = 0
}
zRes, err := redisCli.GetClusterRedis().ZRevRangeByScoreWithScores(context.Background(), zKey, &redis2.ZRangeBy{
Min: fmt.Sprintf("%d", cnt),
Max: "+inf",
}).Result()
if err != nil {
mylogrus.MyLog.Errorf("MGetRoomVisitCount zset fail:%v", err)
return visit, err
}
if len(res) != len(groupIds) {
return visit, errors.New(fmt.Sprintf("MGetRoomVisitCount fail,miss match len,%v-%v", len(res), len(groupIds)))
}
for i, groupId := range groupIds {
if cnt, ok := res[i].(string); ok {
visit[groupId] = cnt
}
for _, v := range zRes {
visit[cast.ToString(v.Member)] = cast.ToString(v.Score)
}
_ = roomVisitCountLru.SetWithExpire(lKey, visit, time.Minute*15)
return visit, nil
}
func GetSetRoomVisitCount(groupId string) (int64, error) {
key := redis_key.GetPrefixGroupInUserDuration(groupId)
//key := redis_key.GetPrefixGroupInUserDuration(groupId)
key := group_k.GetUserEnterRoomGroupKey(groupId)
vc, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
// 查到合法值后,更新二级缓存
if err == nil && vc >= 0 {
ret, err := saveRoomVisitCount(groupId, vc)
mylogrus.MyLog.Infof("saveRoomVisitCount %s, ret = %d, err: %v", groupId, ret, err)
if err := saveRoomVisitCount(groupId, vc); err != nil {
mylogrus.MyLog.Errorf("saveRoomVisitCount %s, err: %v", groupId, err)
}
}
return vc, err
}
func saveRoomVisitCount(groupId string, count int64) (int64, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result()
}
func clearRoomVisit(groupId string, t time.Time) (int64, error) {
value := strconv.FormatInt(t.Unix(), 10)
ret, err := redisCli.GetRedis().ZRemRangeByScore(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId), "0", value).Result()
if err != nil {
return 0, err
func saveRoomVisitCount(groupId string, count int64) error {
//key := redis_key.GetPrefixRoomVisitCount()
zKey := redis_key.GetPrefixRoomVisitCountZset()
// zset同步存一份到redis集群
if err := redisCli.GetClusterRedis().ZAdd(context.Background(), zKey, &redis2.Z{
Score: float64(count),
Member: groupId,
}).Err(); err != nil {
mylogrus.MyLog.Errorf("GetPrefixRoomVisitCountZset fail %s", err.Error())
return err
}
return ret, nil
}
func GetAllRoomVisitCount() (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HGetAll(context.Background(), key).Result()
return nil
//return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result()
}
package user_c
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"sync"
"time"
)
type UserLevel struct {
UserId mysql.ID
Level int
}
var svipVipNobleLock sync.RWMutex
var svipLevel = make(map[mysql.ID]int) // userId->svipLevel
var nobleLevel = make(map[mysql.ID]uint16) // userId->nobleLevel
var userVips = make(map[mysql.ID]bool) // userId->isVip
// 加载数据到lru
func LoadAllSvipVipNoble(model *domain.Model) {
start := time.Now()
var svips []UserLevel
svipMap := make(map[mysql.ID]int)
if err := model.DB().Table("user_svip").Select("user_id,level").Where("level > 0").Find(&svips).Error; err != nil {
model.Log.Errorf("LoadAllSvip fail:%v", err)
} else {
for _, v := range svips {
svipMap[v.UserId] = v.Level
}
}
var nobles []UserLevel
nobleMap := make(map[mysql.ID]uint16)
if err := model.DB().Table("user_noble").Select("user_id,MAX(level) level").
Where("level > 0 AND end_time > ?", time.Now()).Group("user_id").Find(&nobles).Error; err != nil {
model.Log.Errorf("LoadAllNoble fail:%v", err)
} else {
for _, v := range nobles {
nobleMap[v.UserId] = uint16(v.Level)
}
}
var vips []UserLevel
vipMap := make(map[mysql.ID]bool)
if err := model.DB().Table("user_vip").Select("user_id").
Where("expire_at > ?", time.Now()).Find(&vips).Error; err != nil {
model.Log.Errorf("LoadAllVip fail:%v", err)
} else {
for _, v := range vips {
vipMap[v.UserId] = true
}
}
// 上锁赋值
svipVipNobleLock.Lock()
svipLevel = svipMap
nobleLevel = nobleMap
userVips = vipMap
svipVipNobleLock.Unlock()
model.Log.Infof("LoadAllSvipVipNoble svip:%v,vip:%v,noble:%v,cost:%vs", len(svipMap), len(vipMap), len(nobleMap), time.Now().Sub(start).Seconds())
}
func BatchGetNobleLevel(model *domain.Model, userIds []uint64) map[uint64]uint16 {
res := make(map[uint64]uint16)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
res[userId] = nobleLevel[userId]
}
return res
}
func MGetUserSvipLevel(model *domain.Model, userIds []uint64) map[uint64]int {
res := make(map[uint64]int)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
res[userId] = svipLevel[userId]
}
return res
}
func BatchGetVips(model *domain.Model, userIds []uint64) map[uint64]*int64 {
res := make(map[uint64]*int64)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
vip := int64(1)
if userVips[userId] {
res[userId] = &vip
}
}
return res
}
......@@ -38,6 +38,36 @@ func GetUserTinyById(model *domain.Model, userId mysql.ID) (*user_m.UserTiny, er
return userTiny, nil
}
// 获取用户简要信息
// param userId 用户id
func MGetUserTinyById(model *domain.Model, userIds []mysql.ID) []*user_m.UserTiny {
var users []*user_m.UserTiny
for _, userId := range userIds {
if user, _ := GetUserTinyById(model, userId); user != nil {
users = append(users, user)
}
}
return users
}
// 获取用户externalIds
// return []externalIds map[userId]extId map[userId]code
func GetUserExternalIds(model *domain.Model, userIds []mysql.ID) ([]string, map[uint64]string, map[uint64]string) {
var res []string
var m = make(map[uint64]string)
var c = make(map[uint64]string)
if len(userIds) <= 0 {
return res, m, c
}
users := MGetUserTinyById(model, userIds)
for _, u := range users {
res = append(res, u.ExternalId)
m[u.ID] = u.ExternalId
c[u.ID] = u.Code
}
return res, m, c
}
// 获取用户简要信息By ExternalId
func GetUserByExternalId(model *domain.Model, externalId mysql.Str) (*user_m.UserTiny, error) {
userId, err := ToUserId(model, externalId)
......@@ -52,7 +82,7 @@ func ToUserId(model *domain.Model, externalId mysql.Str) (mysql.ID, error) {
if externalId == "" {
return 0, myerr.NewSysError("externalId 不能为空")
}
userId, err := model.Redis.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64()
userId, err := model.RedisCluster.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64()
if err != nil && err != redisV8.Nil {
return 0, err
}
......@@ -75,7 +105,7 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) {
if code == "" {
return 0, myerr.NewSysError("code 不能为空")
}
userId, err := model.Redis.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64()
userId, err := model.RedisCluster.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64()
if err != nil && err != redisV8.Nil {
return 0, err
}
......@@ -104,11 +134,11 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error {
// return err
//}
// cache externalId->userId
if err := model.Redis.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
if err := model.RedisCluster.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err
}
// cache code->userId
if err := model.Redis.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
if err := model.RedisCluster.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err
}
if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil {
......
package group_ev
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
)
var txGroupInListen = new(domain.EventBase)
// 进房事件
type TxGroupInEvent struct {
GroupId string // imGroupId
UserId mysql.ID
ExternalId string
Nick string
Avatar string
IsMember bool //是否永久成员
IsVip bool
NobleLevel uint16
}
func AddTxGroupInEventSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(txGroupInListen, callback)
}
func AddTxGroupInEventAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(txGroupInListen, callback)
}
func PublishTxGroupInEvent(model *domain.Model, event interface{}) error {
return domain.PublishEvent(txGroupInListen, model, event)
}
......@@ -14,6 +14,8 @@ type OnMicEvent struct {
UserId uint64 // 麦中的人
Forbid bool // 静音 true:静音,false:没有静音
Timestamp int64 // 上麦的的时间戳
Ts int64
}
func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) {
......
package common
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/utils"
"hilo-group/_const/redis_key"
"hilo-group/myerr"
"github.com/bluele/gcache"
"time"
)
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
bData, err := GetCache(redis_key.GetUserMedalMerge(userId))
if err != nil {
return nil, myerr.WrapErr(err)
}
// 改成lru
var userMedalMergeLru = gcache.New(10000).LRU().Build()
res := make([]uint32, 0)
err = json.Unmarshal(bData, &res)
if err != nil {
return nil, myerr.WrapErr(err)
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
if data, err := userMedalMergeLru.Get(userId); err == nil {
return data.([]uint32), nil
}
return res, nil
return nil, nil
}
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) error {
err := SetCache(redis_key.GetUserMedalMerge(userId), data, time.Hour*2)
if err != nil {
mylogrus.MyLog.Errorf("SetUserMedalMerge err:%s", err)
return myerr.WrapErr(err)
}
return nil
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) {
_ = userMedalMergeLru.SetWithExpire(userId, data, time.Minute*15)
}
// 删除勋章缓存, 延迟删除
......@@ -44,41 +30,6 @@ func DelUserMedalMergeCacheDelay(userId mysql.ID) {
}()
}
func DelUserMedalMergeCache(userId mysql.ID) error {
err := DelCache(redis_key.GetUserMedalMerge(userId))
if err != nil {
mylogrus.MyLog.Errorf("DetUserMedalMerge err:%s, userId:%v", err, userId)
return myerr.WrapErr(err)
}
return nil
}
func DelCache(key string) error {
err := redisCli.GetRedis().Del(context.Background(), key).Err()
if err != nil {
mylogrus.MyLog.Errorf("DelCache key:%s, err:%s", key, err)
return err
}
return nil
}
func GetCache(key string) ([]byte, error) {
data, err := redisCli.GetRedis().Get(context.Background(), key).Bytes()
if err != nil {
return nil, err
}
return data, nil
}
func SetCache(key string, data interface{}, expire time.Duration) error {
jData, err := json.Marshal(data)
if err != nil {
return err
}
err = redisCli.GetRedis().Set(context.Background(), key, jData, expire).Err()
if err != nil {
mylogrus.MyLog.Errorf("SetCache key:%s, data:%v, err:%s", key, data, err)
return err
}
return nil
func DelUserMedalMergeCache(userId mysql.ID) {
userMedalMergeLru.Remove(userId)
}
package diamond_m
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
"strconv"
......@@ -40,6 +40,11 @@ type DiamondAccountDetail struct {
diamondAccount *DiamondAccount `gorm:"-"`
}
func (DiamondAccountDetail) TableName() string {
month := time.Now().Format("200601")
return fmt.Sprintf("diamond_account_detail_%s", month)
}
// 粉钻详情
type DiamondPinkAccountDetail struct {
mysql.Entity
......@@ -110,7 +115,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
var count int64
if diamondOperateSet.FrequencyDay == -1 {
if diamondOperateSet.FrequencyNum != -1 {
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{
diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId,
OperateType: operateType,
}).Count(&count)
......@@ -125,7 +130,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, myerr.WrapErr(err)
}
//一天的次数
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{
diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId,
OperateType: operateType,
}).Where("created_time >= ? ", beginTime).Count(&count)
......@@ -133,7 +138,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, bizerr.DiamondFrequency
}
//终极拦截,利用
diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from diamond_account_detail d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )")
diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from " + DiamondAccountDetail{}.TableName() + " d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )")
}
//-1,代表值无效,由参数给与
......@@ -197,7 +202,10 @@ func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional()
}
//持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
//if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err)
}
//改变diamondAccount值
......@@ -245,7 +253,10 @@ func (diamondAccountDetail *DiamondAccountDetail) Persistent() error {
}
//持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
//if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err)
}
//改变diamondAccount值
......
package event_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
)
// 进房事件消息
type EventGroupIn struct {
mysql.Entity
*domain.Model `gorm:"-"`
Proto mysql.Type
Payload []byte
Mark mysql.YesNo
MarkHiloGroup mysql.YesNo
}
func (EventGroupIn) TableName() string {
return "event_group_in"
}
// 偏移值
type EventGroupInOffsetHiloGroup struct {
mysql.Entity
*domain.Model `gorm:"-"`
MarkOffset mysql.ID
}
// 获取当前偏移值
func GroupOffset(model *domain.Model) (*EventGroupInOffsetHiloGroup, error) {
offset := new(EventGroupInOffsetHiloGroup)
if err := model.Db.WithContext(model).First(offset).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("Offset fail:%v", err)
return nil, err
}
// gorm.ErrRecordNotFound
}
offset.Model = model
return offset, nil
}
// 批量获取进房事件
func FetchEventGroupIn(model *domain.Model, limit int) ([]*EventGroupIn, *EventGroupInOffsetHiloGroup, error) {
offset, err := GroupOffset(model)
if err != nil {
return nil, nil, err
}
var events []*EventGroupIn
if err := model.Db.WithContext(model).Model(EventGroupIn{}).
Where("id > ?", offset.MarkOffset).
Order("id asc").Limit(limit).Find(&events).Error; err != nil {
model.Log.Errorf("FetchEventGroupIn fail:%v", err)
return nil, nil, err
}
return events, offset, nil
}
// 标记已完成
func (p *EventGroupIn) MarkDone() error {
p.MarkHiloGroup = mysql.YES
return p.Db.WithContext(p.Model).Model(EventGroupIn{}).Where("id = ?", p.ID).Update("mark_hilo_group", p.MarkHiloGroup).Limit(1).Error
}
......@@ -9,3 +9,7 @@ func (p *EventGiftSendOffsetHiloGroup) Persistence() error {
func (p *EventGiftSend) Persistence() error {
return model.Persistent(p.Db, p)
}
func (p *EventGroupInOffsetHiloGroup) Persistence() error {
return model.Persistent(p.Db, p)
}
\ No newline at end of file
......@@ -29,8 +29,9 @@ type GameInfo struct {
}
type GameConfig struct {
Ludo *GameConfigDiamond `json:"ludo"`
Uno *GameConfigDiamond `json:"uno"`
Ludo *GameConfigDiamond `json:"ludo"`
Uno *GameConfigDiamond `json:"uno"`
Domino *GameConfigDiamond `json:"domino"`
}
type GameConfigDiamond struct {
......
......@@ -127,6 +127,40 @@ func (g *GiftOperate) GetConsumeByRange(beginTime, endTime time.Time) (uint32, u
if len(rows) <= 0 {
return 0, 0, nil
}
//if beginTime.Unix() >= 1691337600 && beginTime.Unix() < 1691942400 { // 因为这周水果机被部分人刷币,所以这里做了特殊的处理
// reduceMap := map[string]uint64{
// "HTGS#a63226380": 20000000,
// //"HTGS#a42641278": 10000000,
// "@TGS#3ZZ5GZLHA": 27141539,
// "HTGS#a81630128": 8955410,
// "HTGS#a42300598": 50211301,
// "HTGS#a40088696": 10000000,
// "HTGS#a21700997": 14352310,
// "HTGS#a83608384": 49644203,
// "@TGS#33GDXTSIH": 50000000,
// "HTGS#a50538513": 15000000,
// "HTGS#a77282385": 15000000,
// "HTGS#a59437326": 10000000,
// "HTGS#a16909405": 10000000,
// "HTGS#a44104431": 16861206,
// "HTGS#a56794634": 59591313,
// "HTGS#a11286025": 31232311,
// "HTGS#a17238550": 52309338,
// "HTGS#a83592361": 79545067,
// "HTGS#a39882521": 10255093,
// }
// if reduceNum, ok := reduceMap[g.SceneUid]; ok {
// if g.Log != nil {
// g.Log.Infof("fruit diamond reduceMap,groupId:%v,reduceNum:%v", g.SceneUid, reduceNum)
// }
// if rows[0].Consume >= reduceNum {
// rows[0].Consume -= reduceNum
// } else {
// rows[0].Consume = 0
// }
// }
//}
return rows[0].C, rows[0].Consume, nil
}
......@@ -148,6 +182,17 @@ func (g *GiftOperate) BatchGetConsumeByRange(beginTime, endTime time.Time) ([]Sc
return rows, nil
}
func (g *GiftOperate) BatchGetSupportList(model *domain.Model, beginTime, endTime time.Time) ([]uint64, error) {
userIds := make([]uint64, 0)
err := model.DB().Model(g).
Select("DISTINCT(send_user_id) AS user_id").
Where(g).Where("created_time BETWEEN ? AND ?", beginTime, endTime).Pluck("user_id", &userIds).Error
if err != nil {
return nil, err
}
return userIds, nil
}
func SumSendGift(model *domain.Model, sendUserId mysql.ID, giftId mysql.ID) (uint32, error) {
type Result struct {
N uint32
......
......@@ -8,6 +8,7 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/group_power_ev"
"time"
)
......@@ -40,25 +41,6 @@ type GroupPowerExpDetail struct {
Remark string
}
type GroupPowerOnMic struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Seconds int64
LastCalTs int64
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
type GroupPowerOnMicDetail struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Minute int
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
// 增加家族经验
// 达到经验值之后升级
// 单进程同步执行,不考虑并发
......@@ -82,17 +64,34 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return err
}
// 增加家族经验-总
gpg := &GroupPowerGrade{
GroupPowerId: groupPowerId,
Exp: exp,
Grade: 0,
ExpireAt: time.Time{},
}
if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil {
return err
gpg := new(GroupPowerGrade)
// insert
if err := txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(gpg).Error; err != nil {
if err != gorm.ErrRecordNotFound {
return err
}
// gorm.ErrRecordNotFound
gpg = &GroupPowerGrade{
GroupPowerId: groupPowerId,
Exp: exp,
Grade: 0,
ExpireAt: time.Time{},
}
if err = txModel.DB().Create(gpg).Error; err != nil {
return err
}
} else {
// or update
if err := txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).
UpdateColumn("exp", gorm.Expr("exp + ?", exp)).Error; err != nil {
return err
}
}
//if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}},
// DoUpdates: clause.Assignments(map[string]interface{}{
// "exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil {
// return err
//}
// 当前写后读
latestGrade := new(GroupPowerGrade)
if err = txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(latestGrade).Error; err != nil {
......@@ -135,154 +134,24 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return nil
}
// 获取势力用户上麦加经验记录
func GetGroupPowerUserOnMicDetails(model *domain.Model, groupPowerId, userId mysql.ID) ([]*GroupPowerOnMicDetail, error) {
var res []*GroupPowerOnMicDetail
date := time.Now().Format("2006-01-02")
if err := model.DB().Model(GroupPowerOnMicDetail{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).Find(&res).Error; err != nil {
return res, err
}
return res, nil
}
// 获取势力用户上麦记录
func GetGroupPowerOnMic(model *domain.Model, groupPowerId, userId mysql.ID) (*GroupPowerOnMic, error) {
gpom := new(GroupPowerOnMic)
date := time.Now().Format("2006-01-02")
if err := model.DB().Model(GroupPowerOnMic{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).First(gpom).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return &GroupPowerOnMic{Date: date, GroupPowerId: groupPowerId, UserId: userId}, nil
}
return nil, err
}
return gpom, nil
}
const MaxMinuteTimes = 18
// 增加势力上麦经验
// 事务操作
func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 获取用户上麦奖励历史
onMicDetails, err := GetGroupPowerUserOnMicDetails(model, groupPowerId, userId)
if err != nil {
return err
}
numDetails := len(onMicDetails)
if numDetails >= MaxMinuteTimes {
// 上麦经验贡献值最多1800,1分钟100
return nil
}
onMic, err := GetGroupPowerOnMic(model, groupPowerId, userId)
if err != nil {
return err
}
nowTs := time.Now().Unix()
curTs := joinMicTimestamp
day0Ts := utils.GetZeroTime(time.Now()).Unix()
if joinMicTimestamp < onMic.LastCalTs {
curTs = onMic.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
onMicSeconds := nowTs - curTs
var moreDetails []*GroupPowerOnMicDetail
totalMinuteTimes := int((onMic.Seconds + onMicSeconds) / 600) // 今天实际能加经验次数
if totalMinuteTimes >= MaxMinuteTimes {
totalMinuteTimes = MaxMinuteTimes
}
if totalMinuteTimes > numDetails {
// 续上上一次的时间,从numDetails开始
for mt := numDetails + 1; mt <= totalMinuteTimes; mt++ {
moreDetails = append(moreDetails, &GroupPowerOnMicDetail{
Date: time.Now().Format("2006-01-02"),
GroupPowerId: groupPowerId,
UserId: userId,
Minute: mt * 10, // 转换分钟
})
}
}
// 有更多麦上10分钟,可以加经验
if len(moreDetails) > 0 {
for _, detail := range moreDetails {
// 添加明细,避免重复计算
if err := model.DB().Model(GroupPowerOnMicDetail{}).Create(detail).Error; err != nil {
return err
}
// 每10分钟增加100点经验
if err := IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟"); err != nil {
return err
}
}
// 更新micExp信息
onMic.Seconds = onMic.Seconds + onMicSeconds
onMic.LastCalTs = nowTs
if err := model.DB().Model(GroupPowerOnMic{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "date"}, {Name: "group_power_id"}},
DoUpdates: clause.Assignments(
map[string]interface{}{
"seconds": onMic.Seconds,
"last_cal_ts": nowTs,
},
)}).
Create(onMic).Error; err != nil {
return err
}
}
return nil
})
}
// 增加势力上麦时长-家族之星
// 事务操作
func IncrGroupPowerStarOnMicMonth(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 月统计
star, err := GetGroupPowerMonthStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
month0Ts := now.BeginningOfMonth().Unix()
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨月
if curTs < month0Ts {
curTs = month0Ts
}
score := nowTs - curTs
err = IncrGroupPowerMonthStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID) error {
key := mic_k.GetMicGroupPowerOnMic(userId)
minutes, err := model.Redis.IncrBy(model, key, 1).Result()
if err != nil {
model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err)
return err
})
}
// 增加势力上麦时长-家族之星
// 事务操作
func IncrGroupPowerStarOnMicDay(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 日统计
star, err := GetGroupPowerDayStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
day0Ts := now.BeginningOfDay().Unix()
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
err = IncrGroupPowerDayStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
return err
})
}
model.Redis.Expire(model, key, time.Hour*24) // ttl 一天
// 每日最多1800经验 = 18个10分钟 = 180分钟
if minutes > 180 {
return nil
}
if minutes%10 == 0 {
return IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟")
}
return nil
}
// 清理所有家族的经验
......
......@@ -15,9 +15,11 @@ type GroupPowerExpRank struct {
// 获取家族经验排行榜
// param limit: 排行榜人数
// 10166 线上员工,对应的势力不上榜,groupPowerId=8951
func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int, gpStatus groupPower_e.GroupPowerStatus, area int) ([]GroupPowerExpRank, error) {
var res []GroupPowerExpRank
db := model.DB().Table("group_power_day_exp gpd").Select("gpd.group_power_id,SUM(gpd.exp) as exp").
Where("gpd.group_power_id <> 8951").
Where("gpd.date BETWEEN ? AND ?", beginDate, endDate)
if gpStatus > 0 {
db = db.Joins("left join group_power gp on gpd.group_power_id = gp.id").Where("gp.status = ?", gpStatus)
......
......@@ -35,6 +35,7 @@ type GroupPowerDayStar struct {
}
// 增加家族之星分数
// Deprecated: 用redis
func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
month := time.Now().Format("200601")
star := &GroupPowerMonthStar{
......@@ -59,6 +60,7 @@ func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysq
}
// 增加家族之星分数
// Deprecated: 用redis代替
func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
star := &GroupPowerDayStar{
Date: time.Now(),
......@@ -81,29 +83,8 @@ func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.
return nil
}
// 获取家族之星分数
// 允许返回gorm.ErrRecordNotFound
func GetGroupPowerDayStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerDayStar, error) {
res := new(GroupPowerDayStar)
date := time.Now()
if err := model.DB().Where("date = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", date.Format("2006-01-02"), groupPowerId, userId, _type).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 获取家族之星分数
// 允许返回gorm.ErrRecordNotFound
func GetGroupPowerMonthStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerMonthStar, error) {
res := new(GroupPowerMonthStar)
month := time.Now().Format("200601")
if err := model.DB().Where("month = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", month, groupPowerId, userId, _type).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 获取家族之星排行
// Deprecated: 用redis
func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*GroupPowerMonthStar, error) {
var res []*GroupPowerMonthStar
//month := time.Now().Format("200601")
......
......@@ -13,6 +13,7 @@ import (
"gorm.io/gorm"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/myerr"
"strconv"
"strings"
......@@ -242,6 +243,20 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if len(groupIds) <= 0 {
return result, nil
}
// 获取群组中上麦用户
for _, groupId := range groupIds {
groupMicUserKey := mic_k.GetGroupOnMicUser(groupId)
userIds, err := model.Redis.HVals(model, groupMicUserKey).Result()
if err != nil {
model.Log.Errorf("BatchGetAllMicUser fail:%v", err)
}
for _, userIdStr := range userIds {
if userId, _ := strconv.ParseUint(userIdStr, 10, 64); userId > 0 {
result[groupId] = append(result[groupId], userId)
}
}
}
return result, nil
keys := make([]string, 0)
for _, g := range groupIds {
......@@ -253,7 +268,7 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if err != nil {
return nil, err
}
model.Log.Infof("BatchGetAllMicUser redis return size = %d, mics: %v", len(mics), mics)
//model.Log.Infof("BatchGetAllMicUser redis return size = %d, mics: %v", len(mics), mics)
if len(mics) >= len(groupIds) {
for i, g := range groupIds {
......@@ -432,7 +447,7 @@ func GetMicUserByExternalId(model *domain.Model, externalId string) (*MicUser, e
//麦位上没人,返回nil
func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error) {
if i < 1 || i > 30 {
if i < 1 || i > MaxMicNum {
return nil, myerr.NewSysErrorF("麦序不对,不在范围值内 i:%v", i)
}
str, err := redisCli.GetRedis().Get(context.Background(), redis_key.GetPrefixGroupMicUser(groupUuid, i)).Result()
......
......@@ -3,6 +3,8 @@ package group_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"time"
)
type GroupBanned struct {
......@@ -24,12 +26,19 @@ func (banned *GroupBanned) Delete(model *domain.Model) error {
return model.Db.Where(banned).Delete(&GroupBanned{}).Error
}
var bannedGroupCache = gcache.New(100).LRU().Build()
func GetBannedGroups(model *domain.Model) ([]GroupBanned, error) {
key := "banned"
if data, err := bannedGroupCache.Get(key); err == nil {
return data.([]GroupBanned), nil
}
result := make([]GroupBanned, 0)
err := model.Db.Find(&result).Error
err := model.DB().Find(&result).Error
if err != nil {
return nil, err
}
bannedGroupCache.SetWithExpire(key, result, time.Minute*5)
return result, nil
}
......
package group_m
import "git.hilo.cn/hilo-common/domain"
// 获取游戏房
func GetGameGroupsMap(model *domain.Model) map[string]bool {
res := make(map[string]bool)
var rows []GroupInfo
if err := model.DB().Model(GroupInfo{}).Where("is_game_room = 1").Find(&rows).Error; err != nil {
model.Log.Errorf("GetGameGroupsMap fail:%v", err)
return res
}
for _, v := range rows {
res[v.ImGroupId] = true
}
return res
}
......@@ -47,6 +47,7 @@ type GroupInfo struct {
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
VisitCount int64 `gorm:"-"` // 热度
IsGameRoom uint8 // 是否1v1游戏房
}
func GenerateGroupCode(n uint16) string {
......
......@@ -23,9 +23,13 @@ func (g *GroupTop) Delete(model *domain.Model) error {
return model.Db.Where(g).Delete(&GroupTop{}).Error
}
func GroupTopGetAll(model *domain.Model) ([]string, error) {
func GroupTopGetAll(model *domain.Model, area int) ([]string, error) {
rows := make([]GroupTop, 0)
err := model.Db.Order("id").Find(&rows).Error
err := model.DB().Table("group_top").
Joins("left join group_info gi on group_top.im_group_id = gi.im_group_id "+
"left join res_country rc on gi.country = rc.name").
Where("rc.area = ?", area).
Order("group_top.id").Find(&rows).Error
if err != nil {
return nil, err
}
......
......@@ -3,6 +3,7 @@ package group_m
import (
"context"
"encoding/json"
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
......@@ -14,6 +15,7 @@ import (
"gorm.io/gorm"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/common"
"hilo-group/domain/model/noble_m"
"hilo-group/domain/model/res_m"
......@@ -98,8 +100,8 @@ func GetMicNumType(model *domain.Model, groupUuid string) (group_e.GroupMicNumTy
}
}
//6个小时
const expireMinute = 60 * 60 * 12
// 3天
const expireMinute = 60 * 60 * 24 * 3
const micExpire = expireMinute * time.Second
//麦位基本信息。
......@@ -255,6 +257,10 @@ func (mic *Mic) In(userId uint64, externalId string) error {
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)
......@@ -269,7 +275,7 @@ func (mic *Mic) In(userId uint64, externalId string) error {
//上麦(自己),
//规则:1:加锁了不能上麦 2:麦上有人,不能上麦
//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() {
if err != nil {
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
ExternalId: externalId,
UserId: userId,
CpUserId: cpUserId,
Forbid: false,
Forbid: forbid,
Timestamp: time.Now().Unix(),
})
if err != nil {
......@@ -385,6 +391,10 @@ func (micUser *MicUser) leave(operateUserId uint64, operateExternalId string) er
//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)
......@@ -824,12 +834,14 @@ func groupMicHasIn(model *domain.Model, groupId string, userId mysql.ID) {
} else {
println(n)
}
if _, err := redisCli.GetRedis().ZAdd(context.Background(), redis_key.GetPrefixGroupMicHasInUserTime(), &redis2.Z{
Score: float64(time.Now().Unix()),
Member: getMemberStr(groupId, userId),
}).Result(); err != nil {
model.Log.Errorf("groupMicHasIn redis:GetPrefixGroupMicHasInTime groupId:%v err:%v", groupId, err)
}
// 下面的是只写,不查的。 todo 直接干掉???
// 只是知道用户在哪个时间点上了哪个群的麦,但是不知道上了哪个麦位置, 而且micUser已经有统计这些信息了
//if _, err := redisCli.GetRedis().ZAdd(context.Background(), redis_key.GetPrefixGroupMicHasInUserTime(), &redis2.Z{
// Score: float64(time.Now().Unix()),
// 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 "
......@@ -843,6 +855,7 @@ func GetMicHasInGroups() ([]string, error) {
if err != nil {
return nil, myerr.WrapErr(err)
}
return groupUuids, nil // 不需要下面的逐个麦位的判断了
//
resultGroupUuids := make([]string, 0, len(groupUuids))
//循环lua判断是否, 最后的保证,(猜想:真正麦上有人的群没有很多)
......@@ -875,7 +888,7 @@ var micGroupNumCache = gcache.New(10000).LRU().Build()
func GetMicHasInGroupNum(model *domain.Model) (map[string]int64, error) {
// get from cache
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() {
return data.(map[string]int64), nil
......@@ -912,8 +925,41 @@ func GetMicHasInGroupNum(model *domain.Model) (map[string]int64, error) {
}
}
// cache 1min
_ = micGroupNumCache.SetWithExpire(micGroupNumKey, resultGroupUuids, time.Minute)
model.Log.Infof("GetMicHasInGroupNum cache miss:%v", resultGroupUuids)
_ = micGroupNumCache.SetWithExpire(micGroupNumKey, resultGroupUuids, time.Minute*15)
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
}
......
......@@ -68,7 +68,7 @@ type MicNumChangeContent struct {
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)
txGroupId, err := ToTxGroupId(model, groupUid)
......@@ -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))
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))
return
} else {
......@@ -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))
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))
return
} else {
......@@ -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))
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))
return
} else {
......@@ -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))
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))
return
} else {
......@@ -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))
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))
return
} else {
......@@ -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 {
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
}
for _, micContent := range micContents {
......@@ -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))
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))
continue
} else {
......@@ -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))
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))
return err
}
......@@ -319,7 +321,7 @@ func MicRPush(model *domain.Model, txGroupId string, msg GroupSystemMsg) error {
}
//得使用旧的imGroupId
func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error) {
func GetMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error) {
txGroupId, err := ToTxGroupId(model, groupUid)
if err != nil {
......@@ -340,6 +342,9 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error
userIds := make([]uint64, 0, len(micUsers))
for _, r := range micUsers {
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)
......@@ -350,6 +355,13 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error
micContents := make([]MicContent, 0, len(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{
GroupId: txGroupId,
I: r.I,
......@@ -359,7 +371,7 @@ func getMicAllContent(model *domain.Model, groupUid string) ([]MicContent, error
ExternalId: micUserMap[r.I].ExternalId,
AgoraId: uint32(micUserMap[r.I].UserId),
Timestamp: time.Now().UnixNano(),
User: micUserDataMap[micUserMap[r.I].UserId],
User: micUserData,
})
}
return micContents, nil
......@@ -448,6 +460,7 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
return nil, err
}
svips, _ := rpc.MGetUserSvip(model, userIds)
cpRelations, _ := rpc.MGetUserCpRelations(model, userIds)
micUserDataMap := map[uint64]*MicUserData{}
for _, id := range userIds {
......@@ -461,11 +474,11 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
}
var headwearPicUrl string
var headwearEffectUrl string
var reverseHeadwearEffectUrl string
var headwearReverseEffectUrl string
if headwearUser, flag := headwearMap[id]; flag {
headwearPicUrl = resHeadwearMap[headwearUser.HeadwearId].PicUrl
headwearEffectUrl = resHeadwearMap[headwearUser.HeadwearId].EffectUrl
reverseHeadwearEffectUrl = resHeadwearMap[headwearUser.HeadwearId].ReverseEffectUrl
headwearReverseEffectUrl = resHeadwearMap[headwearUser.HeadwearId].ReverseEffectUrl
}
micUserDataMap[id] = &MicUserData{
Id: user.ID,
......@@ -478,9 +491,10 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
NobleLeave: nobleMap[id],
HeadwearPicUrl: headwearPicUrl,
HeadwearEffectUrl: headwearEffectUrl,
HeadwearReverseEffectUrl: reverseHeadwearEffectUrl,
HeadwearReverseEffectUrl: headwearReverseEffectUrl,
SvipLevel: svips[id].SvipLevel,
Svip: rpc.CopySimpleSvip(svips[id]),
HeadwearIcon: cpRelations[user.ID].CpUserAvatar,
}
}
return micUserDataMap, nil
......
......@@ -14,6 +14,7 @@ import (
"gorm.io/gorm/clause"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/group_k"
"hilo-group/domain/cache/room_c"
"hilo-group/domain/model/user_m"
"hilo-group/myerr"
......@@ -49,14 +50,14 @@ func RoomLivingExpire(model *domain.Model, groupUid string, userId uint64) {
model.Log.Infof("room RoomLivingExpire userId:%v, groupUid:%v", userId, groupUid)
//
key := redis_key.GetPrefixGroupRoomLiving()
i, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
_, err := model.RedisCluster.ZAdd(context.Background(), key, &redis2.Z{
Score: float64(time.Now().Unix()),
Member: getMemberStr(groupUid, userId),
}).Result()
if err != nil {
model.Log.Errorf("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err)
} else {
model.Log.Infof("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
//model.Log.Infof("RoomLivingExpire ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
}
}
......@@ -69,14 +70,14 @@ func RoomLivingIn(model *domain.Model, groupUid string, userId uint64, externalI
}
//
key := redis_key.GetPrefixGroupRoomLiving()
i, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
_, err := model.RedisCluster.ZAdd(context.Background(), key, &redis2.Z{
Score: float64(time.Now().Unix()),
Member: getMemberStr(groupUid, userId),
}).Result()
if err != nil {
model.Log.Errorf("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err)
} else {
model.Log.Infof("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
//model.Log.Infof("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
}
go func(myContext *mycontext.MyContext, groupId string) {
......@@ -111,11 +112,11 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err)
}
data, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result()
data, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
......@@ -124,12 +125,12 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri
for i, _ := range data {
gid, uid := analysisMemberStr(data[i])
if uid == userId && (groupId == "" || gid == groupId) {
if _, err := redisCli.GetRedis().ZRem(context.Background(), key, getMemberStr(gid, uid)).Result(); err != nil {
if _, err := model.RedisCluster.ZRem(context.Background(), key, getMemberStr(gid, uid)).Result(); err != nil {
model.Log.Errorf("RoomLivingLeave ZRem key:%s, groupId:%s, userId:%d, err:%v", key, gid, uid, err)
return nil, myerr.WrapErr(err)
} else {
groupIds = append(groupIds, gid)
model.Log.Infof("RoomLivingLeave ZRem success key:%s, groupId:%s, userId:%d", key, gid, uid)
//model.Log.Infof("RoomLivingLeave ZRem success key:%s, groupId:%s, userId:%d", key, gid, uid)
}
// 发信令,让前端重新拉取,接受容错,
......@@ -208,7 +209,7 @@ func RoomLivingLeaveByKick(model *domain.Model, groupUuid string, beKickuserId u
Target: beKickExternalId,
}, false)*/
MicGroupKickOutRPush(model, groupUuid, userExternalId, beKickExternalId)
MicGroupKickOutRPush(model, groupUuid, userExternalId, beKickExternalId, beKickuserId)
return roomLivingLeave(model, beKickuserId, groupUuid)
}
......@@ -271,15 +272,15 @@ func RoomLivingExistsUserId(groupUid string) ([]uint64, error) {
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
var model = domain.CreateModelNil()
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err)
}
groupUserIdstrs, err := redisCli.GetRedis().ZRevRange(context.Background(), key, 0, -1).Result()
groupUserIdstrs, err := model.RedisCluster.ZRevRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
mylogrus.MyLog.Infof("group_room_living RoomLivingExistsUserId groupUserIdstrs:%v", groupUserIdstrs)
//mylogrus.MyLog.Infof("group_room_living RoomLivingExistsUserId groupUserIdstrs:%v", groupUserIdstrs)
userIds := make([]uint64, 0, len(groupUserIdstrs))
for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
......@@ -299,11 +300,11 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) {
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
model := domain.CreateModelNil()
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err)
}
groupUserIdstrs, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result()
groupUserIdstrs, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
......@@ -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) {
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
model.Log.Infof("RoomLivingExistsGroup: err:%v", err)
return nil, myerr.WrapErr(err)
}
groupUserIdstrs, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result()
groupUserIdstrs, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
model.Log.Infof("group_room_living RoomLivingExistsGroup groupUserIdstrs:%v", groupUserIdstrs)
//model.Log.Infof("group_room_living RoomLivingExistsGroup groupUserIdstrs:%v", groupUserIdstrs)
groupGroup := map[string]map[uint64]struct{}{}
for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
......@@ -343,7 +344,7 @@ func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{},
groupGroup[tempGroupUid] = map[uint64]struct{}{userId: {}}
}
}
model.Log.Infof("RoomLivingExistsGroup size = %d", len(groupGroup))
//model.Log.Infof("RoomLivingExistsGroup size = %d", len(groupGroup))
return groupGroup, nil
}
......@@ -389,18 +390,8 @@ func GetAllGroupsSorted(model *domain.Model) ([]string, error) {
// 取房间最近N天的访问人数
func GetRoomVisitCount(groupId string) (int64, error) {
// 每群定时请一次数据可以了
now := time.Now()
if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
// 先移除(N天之前的),后统计
if _, err := redisCli.GetRedis().ZRemRangeByScore(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId),
"0", strconv.FormatInt(time.Now().AddDate(0, 0, -redis_key.GroupInDurationTTL).Unix(), 10)).
Result(); err != nil {
return 0, err
}
}
visitCount, err := redisCli.GetRedis().ZCard(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId)).Result()
key := group_k.GetUserEnterRoomGroupKey(groupId)
visitCount, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
if err != nil {
return 0, err
}
......@@ -429,15 +420,12 @@ func BatchGetRoomVisitCount(logE *logrus.Entry, groupIds []string) (map[string]i
if err != nil {
return nil, err
}
logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
visitCount := make(map[string]int64)
for _, groupId := range groupIds {
// 先从二级缓存中找
if c, ok := roomVisitCount[groupId]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
logE.Debugf("GetRoomVisitCount, from roomVisitCount %s - %d", groupId, vc)
visitCount[groupId] = vc
}
} else {
......@@ -464,7 +452,7 @@ func BatchGetRoomVisitCountList(logE *logrus.Entry, groupIds []string) (map[stri
if err != nil {
return nil, nil, err
}
logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
//logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
res := make([]*RoomVisit, 0, len(groupIds))
visitCount := make(map[string]int64)
......@@ -505,7 +493,8 @@ func (uer *UserEnterRoom) Save(db *gorm.DB) error {
func (uer *UserEnterRoom) Find(db *gorm.DB) ([]UserEnterRoom, error) {
rows := make([]UserEnterRoom, 0)
if err := db.Where(uer).Order("enter_time DESC").Find(&rows).Error; err != nil {
t := time.Now().AddDate(0, 0, -15)
if err := db.Where(uer).Where("enter_time >= ?", t).Order("enter_time DESC").Find(&rows).Error; err != nil {
return nil, err
}
return rows, nil
......
......@@ -57,6 +57,24 @@ func GetAllGroupSupportResult(db *gorm.DB, period string) (map[string]uint8, err
return result, nil
}
func GetGroupSupportResult(db *gorm.DB, period string, groupIds []string) (map[string]uint8, error) {
if len(period) <= 0 {
return nil, nil
}
gsr := GroupSupportResult{
Period: period,
}
rows := make([]GroupSupportResult, 0)
if err := db.Where(gsr).Where("group_uid in (?)", groupIds).Find(&rows).Error; err != nil {
return nil, err
}
result := make(map[string]uint8)
for _, i := range rows {
result[i.GroupUid] = i.Grade
}
return result, nil
}
//群组扶持奖励,利益分配者
type GroupSupportAwardAdmin struct {
mysql.Entity
......@@ -102,14 +120,14 @@ func (gsa *GroupSupportAwardMgr) Get(db *gorm.DB) ([]GroupSupportAwardMgr, error
}
//添加记录
func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mysql.ID, resGroupSupportId mysql.ID, userIds []mysql.ID, period string) (*GroupSupportAwardAdmin, []GroupSupportAwardMgr, error) {
//资源获取
resGroupSupport, err := res_m.GetResGroupSupportById(model, resGroupSupportId)
if err != nil {
return nil, nil, err
}
if int(resGroupSupport.MgrNum) < len(userIds) {
return nil, nil, myerr.NewSysErrorF("AddGroupSupportAward mgrNum:%v 同 len(userIds)=%v 不一致", resGroupSupport.MgrNum, len(userIds))
func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mysql.ID, resSupport *res_m.ResGroupSupport, userIds []mysql.ID, period string) (*GroupSupportAwardAdmin, []GroupSupportAwardMgr, error) {
////资源获取
//resGroupSupport, err := res_m.GetResGroupSupportById(model, resGroupSupportId)
//if err != nil {
// return nil, nil, err
//}
if int(resSupport.MgrNum) < len(userIds) {
return nil, nil, myerr.NewSysErrorF("AddGroupSupportAward mgrNum:%v 同 len(userIds)=%v 不一致", resSupport.MgrNum, len(userIds))
}
//增加群主奖励
......@@ -118,9 +136,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys
GroupUid: groupUid,
IssuerUserId: issuerUserId,
UserId: issuerUserId,
DiamondNum: resGroupSupport.AdminAward,
Grade: resGroupSupport.Grade,
ResGroupSupportId: resGroupSupport.ID,
DiamondNum: resSupport.AdminAward,
Grade: resSupport.Grade,
ResGroupSupportId: resSupport.ID,
Period: period,
}
......@@ -133,9 +151,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys
GroupUid: groupUid,
IssuerUserId: issuerUserId,
UserId: userIds[i],
DiamondNum: resGroupSupport.MgrAward,
Grade: resGroupSupport.Grade,
ResGroupSupportId: resGroupSupport.ID,
DiamondNum: resSupport.MgrAward,
Grade: resSupport.Grade,
ResGroupSupportId: resSupport.ID,
Period: period,
})
}
......
......@@ -104,7 +104,8 @@ func (rb *RoomBanner) GetRoomBanners(db *gorm.DB, vcAllow bool) ([]RoomBanner, e
res := make([]RoomBanner, 0, len(rows))
for _, v := range rows {
// 版本控制
if !vcAllow && (v.ID == 241 || v.ID == 781 || v.ID == 771 || 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
}
res = append(res, v)
......
......@@ -7,6 +7,7 @@ import (
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/redis_key/mic_k"
"time"
)
......@@ -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
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
start += NUM
end += NUM
}
mylogrus.MyLog.Infof("BatchGetActiveNoble expected:%v,actual:%v,notEndUids:%v", len(userIds), len(result), notEndUids)
//mylogrus.MyLog.Infof("BatchGetActiveNoble expected:%v,actual:%v,notEndUids:%v", len(userIds), len(result), notEndUids)
if len(userIds) != len(result) {
mylogrus.MyLog.Warnf("BatchGetActiveNoble expected:%v", userIds)
}
......@@ -177,4 +177,4 @@ func BatchGetNobleLevel(db *gorm.DB, userIds []uint64) (map[uint64]uint16, error
result[i] = m[i].Level
}
return result, nil
}
\ No newline at end of file
}
......@@ -213,3 +213,10 @@ func GetLangeByCountry(db *gorm.DB, country mysql.Str) (string, error) {
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
model.Log.Warnf("getOnlineStatus redis failed")
left = extIds
} else {
model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r)
//model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r)
if len(r) >= len(extIds) {
for i, e := range extIds {
......@@ -387,10 +387,10 @@ func getOnlineStatus(extIds []string) ([]interface{}, error) {
for _, e := range extIds {
keys = append(keys, redis_key.GetOnLineStatusKey(e))
}
return redisCli.RedisClient.MGet(context.Background(), keys...).Result()
return redisCli.RedisClusterClient.MGet(context.Background(), keys...).Result()
}
func setOnlineStatus(extId string, status uint, ttl time.Duration) error {
key := redis_key.GetOnLineStatusKey(extId)
return redisCli.RedisClient.Set(context.Background(), key, status, ttl).Err()
return redisCli.RedisClusterClient.Set(context.Background(), key, status, ttl).Err()
}
......@@ -3,10 +3,12 @@ package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr"
)
//获取用户的国家,和所属的区域(是否阿语区)
// 获取用户的国家,和所属的区域(是否阿语区)
// 默认国家给沙特
func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
type info struct {
Name string
......@@ -14,7 +16,11 @@ func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
}
res := new(info)
if err := model.DB().Raw("select name, area from res_country where name = (select country from user where id = ?)", id).First(&res).Error; err != nil {
return "", 0, myerr.WrapErr(err)
if err != gorm.ErrRecordNotFound {
return "", 0, myerr.WrapErr(err)
}
// gorm.ErrRecordNotFound
return "KSA", 1, nil
}
return res.Name, res.Area, nil
}
......@@ -48,8 +48,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
if err != nil {
return nil, err
}
logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes)
logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList)
//logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes)
//logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList)
maxGrades := make(map[uint8]int, 0)
maxMedalIds := make(map[uint8]uint32, 0)
......@@ -70,8 +70,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
}
}
}
logger.Infof("maxGrade %+v", maxGrades)
logger.Infof("maxMedalIds %+v", maxMedalIds)
//logger.Infof("maxGrade %+v", maxGrades)
//logger.Infof("maxMedalIds %+v", maxMedalIds)
mIds := result
result = make([]uint32, 0)
......
......@@ -85,12 +85,29 @@ func GetUsersByIds(model *domain.Model, userIds []mysql.ID) ([]User, error) {
return users, nil
}
// 分批获取userIds
func GetUserMapByIds(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]User, error) {
rows, err := GetUsersByIds(model, userIds)
if err != nil {
return nil, err
}
result := make(map[mysql.ID]User, 0)
end := 500
if end > len(userIds) {
end = len(userIds)
}
var rows []User
start := 0
for start < len(userIds) {
tmp, err := GetUsersByIds(model, userIds[start:end])
if err != nil {
return result, err
} else {
rows = append(rows, tmp...)
}
start += 500
end += 500
if end > len(userIds) {
end = len(userIds)
}
//model.Log.Infof("GetUserMapByIds start:%v-end:%v", start, end)
}
for _, i := range rows {
result[i.ID] = i
}
......@@ -127,3 +144,39 @@ func GetUsers(model *domain.Model, ids []mysql.ID) ([]*User, error) {
}
return res, nil
}
// 获取用户externalIds
// return []externalIds map[userId]extId map[userId]code
func GetUserExternalIds(model *domain.Model, userIds []mysql.ID) ([]string, map[uint64]string, map[uint64]string) {
var res []string
var m = make(map[uint64]string)
var c = make(map[uint64]string)
if len(userIds) <= 0 {
return res, m, c
}
var users []User
total := len(userIds)
const NUM = 500
start, end := 0, NUM
for start < total {
if end > total {
end = total
}
var tmp []User
tmpUserId := userIds[start:end]
if err := model.DB().Model(User{}).Where("id in (?)", tmpUserId).Select("id,external_id,code").Find(&tmp).Error; err != nil {
model.Log.Errorf("GetUserExternalIds fail:%v", err)
} else if len(tmp) > 0 {
users = append(users, tmp...)
}
start += NUM
end += NUM
}
for _, user := range users {
res = append(res, user.ExternalId)
m[user.ID] = user.ExternalId
c[user.ID] = user.Code
}
return res, m, c
}
......@@ -59,14 +59,34 @@ func GetVip(db *gorm.DB, userId uint64) (*UserVip, error) {
return nil, nil
}
// 分批获取
func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) {
result := make(map[uint64]*int64, 0)
rows := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&rows).Error
if err != nil {
return nil, err
end := 500
if end > len(userIds) {
end = len(userIds)
}
start := 0
for start < len(userIds) {
tmp := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds[start:end]).Find(&tmp).Error
if err != nil {
return nil, err
}
if err != nil {
return result, err
} else {
rows = append(rows, tmp...)
}
start += 500
end += 500
if end > len(userIds) {
end = len(userIds)
}
//mylogrus.MyLog.Infof("BatchGetVips start:%v-end:%v", start, end)
}
result := make(map[uint64]*int64, 0)
for _, i := range userIds {
result[i] = nil
}
......
......@@ -6,22 +6,18 @@ import (
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/rpc"
"git.hilo.cn/hilo-common/sdk/tencentyun"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/msg_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_power_ev"
"hilo-group/domain/event/mic_ev"
"hilo-group/domain/model/diamond_m"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/mic_m"
"hilo-group/domain/model/msg_m"
"hilo-group/domain/model/task_m"
"hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_mic_s"
"hilo-group/myerr"
"strconv"
"time"
......@@ -33,8 +29,8 @@ func EventInit() {
GroupEvents()
GroupImMass()
GroupTheme()
SendGift() // 送礼事件
OnMic() // 在麦上事件
//SendGift() // 送礼事件
GroupInMicChangeEvent() // 用户进房推送mic位置信息
}
func GroupSupportEvents() {
......@@ -246,6 +242,7 @@ func GroupEvents() {
}
err := uer.Save(model.Db)
model.Log.Infof("AddGroupInAsync, UserEnterRoom err: %v", err)
group_c.ZAddUserEnterRoom(model, event.UserId, event.GroupId) // redis存储
return err
})
......@@ -468,99 +465,69 @@ func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32,
func SendGift() {
// 送礼事件-势力经验
gift_ev.AddSendGiftEventSync(func(model *domain.Model, event interface{}) error {
sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
if !ok {
model.Log.Errorf("AddSendGiftEventAsync event type err")
return nil
}
model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent)
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return nil
}
exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId)
if err != nil {
model.Log.Infof("CheckGroupPowerUser fail %+v", err)
return err
}
if exist {
exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum
return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
}
return nil
})
//gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error {
// sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
// if !ok {
// model.Log.Errorf("AddSendGiftEventAsync event type err")
// return nil
// }
// model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent)
// if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
// return nil
// }
// exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId)
// if err != nil {
// model.Log.Infof("CheckGroupPowerUser fail %+v", err)
// return err
// }
// 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, "送礼")
// }
// return nil
//})
// 家族之星-送礼/收礼
gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error {
sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
if !ok {
model.Log.Errorf("AddSendGiftEventAsync event type err")
return nil
}
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return nil
}
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 err
}
// 送礼加分
if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok {
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 {
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 {
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_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil {
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 {
model.Log.Errorf("IncrGroupPowerDayStarScore charm fail:%v", err)
}
}
}
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
})
//gift_ev.AddSendGiftEventAsync(func(model *domain.Model, event interface{}) error {
// sendGiftEvent, ok := event.(*gift_ev.SendGiftEvent)
// if !ok {
// model.Log.Errorf("AddSendGiftEventAsync event type err")
// return nil
// }
// if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
// return nil
// }
// 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 err
// }
// // 送礼加分
// if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok {
// 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 {
// 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 {
// 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_m.IncrGroupPowerMonthStarScore(model, data.GroupPowerId, data.UserId, groupPower_e.GroupPowerStarTypeCharm, diamonds, 0); err != nil {
// 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 {
// model.Log.Errorf("IncrGroupPowerDayStarScore charm fail:%v", err)
// }
// }
// }
// 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 (
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/rpc"
uuid "github.com/satori/go.uuid"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/event/group_ev"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m"
......@@ -317,15 +319,13 @@ func (s *GroupMicService) IncrGroupPowerOnMicExpAndTime(groupId string, userId u
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)
}
// 增加势力上麦时长-月
if err := groupPower_m.IncrGroupPowerStarOnMicMonth(model, groupPowerId, userId, joinMicTimestamp); err != nil {
model.Log.Errorf("IncrGroupPowerStarOnMicMonth fail:%v", err)
}
// 增加势力上麦时长-天
if err := groupPower_m.IncrGroupPowerStarOnMicDay(model, groupPowerId, userId, joinMicTimestamp); err != nil {
// 增加势力上麦时长-天/周/月
//if err := groupPower_m.IncrGroupPowerStarOnMicDay(model, groupPowerId, userId, joinMicTimestamp); err != nil {
if err := groupPower_c.IncrGroupPowerDayStarScore(model, groupPowerId, userId,
groupPower_e.GroupPowerStarTypeActive, 60); err != nil {
model.Log.Errorf("IncrGroupPowerStarOnMicDay fail:%v", err)
}
return nil
......@@ -346,9 +346,11 @@ func (s *GroupMicService) CheckCpOnMic(groupUuid string) {
// userId->micIndex
var userMicIndex = make(map[uint64]int)
var userIds []uint64
forbidMap := make(map[uint64]bool)
for _, u := range micUsers {
userMicIndex[u.UserId] = u.I
userIds = append(userIds, u.UserId)
forbidMap[u.UserId] = u.Forbid
}
cpPairs, err := rpc.MGetUserCpPairs(model, userIds)
// 更新麦上cp的信息
......@@ -374,7 +376,7 @@ func (s *GroupMicService) CheckCpOnMic(groupUuid string) {
if err != nil {
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 {
model := domain.CreateModel(s.svc.CtxAndDb)
......@@ -382,7 +384,7 @@ func (s *GroupMicService) CheckCpOnMic(groupUuid string) {
if err != nil {
return err
}
return mic.Update(cpUserId, users[cpUserId].ExternalId, userId)
return mic.Update(cpUserId, users[cpUserId].ExternalId, userId, forbidMap[cpUserId])
})
}
return
......@@ -403,11 +405,13 @@ func (s *GroupMicService) CheckCpLeaveMic(groupUuid string, leaveUid uint64) {
// userId->micIndex
var userMicIndex = make(map[uint64]int)
var cpUserId uint64
forbidMap := make(map[uint64]bool)
for _, u := range micUsers {
if u.UserId == leaveUid {
cpUserId = u.CpUserId
}
userMicIndex[u.UserId] = u.I
forbidMap[u.UserId] = u.Forbid
}
if cpUserId <= 0 {
return
......@@ -423,7 +427,7 @@ func (s *GroupMicService) CheckCpLeaveMic(groupUuid string, leaveUid uint64) {
if err != nil {
return err
}
return mic.Update(cpUserId, user.ExternalId, 0)
return mic.Update(cpUserId, user.ExternalId, 0, forbidMap[cpUserId])
})
return
}
......@@ -13,6 +13,7 @@ import (
"hilo-group/_const/enum/msg_e"
"hilo-group/cv/group_power_cv"
"hilo-group/cv/user_cv"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/cache/user_c"
"hilo-group/domain/event/group_power_ev"
"hilo-group/domain/model/groupPower_m"
......@@ -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) {
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 {
return nil, err
}
......
......@@ -4,8 +4,8 @@ import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"gorm.io/gorm"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/mgr_e"
......@@ -18,7 +18,6 @@ import (
"hilo-group/domain/model/user_m"
"hilo-group/domain/service/signal_s"
"hilo-group/myerr"
"strconv"
"time"
)
......@@ -31,7 +30,7 @@ func NewGroupService(myContext *mycontext.MyContext) *GroupService {
return &GroupService{svc}
}
// 取本周最高的扶持等级 fixme:删除这个过渡函数
// 取本周最高的扶持等级
func (s *GroupService) GetWeekMaxSupportLevelMap() (map[string]uint8, error) {
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
_, _, period := group_m.GetSupportLevelTime(now)
levels, err := GetAllSupportLevel(model, period)
if err != nil {
return nil, err
if err == nil {
return levels, nil
}
model.Log.Debugf("GetSupportLevelMap, GET %s: %v", period, levels)
// cache miss
result := make(map[string]uint8, 0)
if len(levels) > 0 {
for g, l := range levels {
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)
}
result, err := group_m.GetAllGroupSupportResult(model.Db, period)
if err == nil {
SaveAllSupportLevel(model, period, result)
}
return result, nil
}
func SaveAllSupportLevel(model *domain.Model, date string, levels map[string]uint8) (int64, error) {
values := make(map[string]interface{}, 0)
for g, l := range levels {
if l > 0 {
values[g] = l
}
}
if len(values) <= 0 {
return 0, nil
}
key := redis_key.GetPrefixSupportLevel(date)
ret, err := model.Redis.HSet(model, key, values).Result()
//// 取本周最高的扶持等级
//func (s *GroupService) GetWeekMaxSupportLevelMapByIds(groupIds []string) (map[string]uint8, error) {
// return s.GetSupportLevelMapByIds(groupIds, time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
//}
//
//func (s *GroupService) GetSupportLevelMapByIds(groupIds []string, now time.Time) (map[string]uint8, error) {
// model := domain.CreateModel(s.svc.CtxAndDb)
//
// _, _, period := group_m.GetSupportLevelTime(now)
//
// levels, err := GetAllSupportLevel(model, period)
// 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 {
// 设置一个TTL保险一些 TODO: 可以优化,保证数据总是有的
ttl := time.Hour
if !config.AppIsRelease() {
ttl = time.Minute
}
model.Redis.Expire(model, key, ttl)
}
return ret, err
// supportLevelLru Cache
var supportLevelCache = gcache.New(100).LRU().Build()
func SaveAllSupportLevel(model *domain.Model, date string, levels map[string]uint8) {
key := redis_key.GetPrefixSupportLevel(date)
_ = supportLevelCache.SetWithExpire(key, levels, time.Hour)
return
}
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)
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) {
......
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 (
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/msg_e"
"hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/group_k"
"hilo-group/common"
"hilo-group/cv/property_cv"
"hilo-group/domain/cache/group_c"
......@@ -32,6 +34,7 @@ import (
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
"strconv"
"strings"
"time"
)
......@@ -253,16 +256,10 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin
var cpLevel int
var cpUserAvatar string
var cpEntryEffect bool
if cp, _ := rpc.GetUserCp(model, userId); cp != nil {
cpLevel = cp.CpLevel.Level
if cp.CpUserInfo.Avatar != nil {
cpUserAvatar = *cp.CpUserInfo.Avatar
}
for _, v := range cp.MyPrivilegeList {
if v.Type == 5 {
cpEntryEffect = true
}
}
if cp, _ := rpc.GetUserCpEntryEffect(model, userId); cp != nil {
cpLevel = cp.CpLevel
cpUserAvatar = cp.CpUserAvatar
cpEntryEffect = cp.CpEntryEffect
}
r := UserParam{
Nick: user.Nick,
......@@ -327,7 +324,7 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin
if err != nil {
return "", "", err
} else {
go dealActDataAfterEnterRoom(s.svc.MyContext, userId, rideId, roomId)
//go dealActDataAfterEnterRoom(s.svc.MyContext, userId, rideId, roomId)
return channelId, token, nil
}
}
......@@ -515,3 +512,118 @@ func dealActDataAfterEnterRoom(myContext *mycontext.MyContext, userId, rideId ui
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
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/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"github.com/go-redis/redis/v8"
"hilo-group/_const/enum/gift_e"
"hilo-group/domain/event/group_ev"
"hilo-group/domain/model/gift_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/msg_m"
"hilo-group/domain/model/res_m"
"hilo-group/domain/model/user_m"
"hilo-group/myerr/bizerr"
"strconv"
"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 {
return uids, nil, nil
}
......@@ -21,86 +28,157 @@ func (s *GroupService) GroupSupportList(groupId string, uids []uint64) ([]uint64
result := 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. 去掉非群管理者
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)
}
// 1. 去掉非群管理者
roles, _, err := group_m.GetRolesInGroup(model, groupId)
if err != nil {
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 {
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: 去掉非群成员
// 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个管理奖励
_, _, period := group_m.GetLastSupportPeriod(time.Now())
gsa := group_m.GroupSupportAwardMgr{Period: period}
rows, err := gsa.Get(model.Db)
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
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
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)
}
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 passed == true {
userIds = append(userIds, u)
} else {
out = append(out, u)
}
}
model.Log.Infof("GroupSupportList: uids %v, map %v", uids, m)
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
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 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) {
......@@ -124,17 +202,50 @@ func (s *GroupService) GetSupportLevel(groupId string) (uint64, uint32, error) {
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 {
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 {
return err
}
......@@ -173,3 +284,128 @@ func (s *GroupService) RenewGroupSupporter(groupId string, userIds []uint64) err
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 (
github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e // indirect
......
......@@ -401,6 +401,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
......
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT]
SECRET=hilo1632
ISSUER_API=hiloApi
......
......@@ -3,6 +3,7 @@ package main
import (
"fmt"
"git.hilo.cn/hilo-common/resource/consul"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-group/cron"
"hilo-group/domain/service/event_s"
"hilo-group/route"
......@@ -17,6 +18,7 @@ const (
func main() {
cron.Init() // 开启定时任务
event_s.EventInit() // 注册事件(内部事件+mysql拟kafka)
redisCli.InitCluster() // redis集群
r := route.InitRouter() // 注册路由
consul.RegisterToConsul(PORT, RegisterName, RegisterTag) // 服务注册
r.Run(fmt.Sprintf(":%d", PORT)) // 启动服务
......
......@@ -69,7 +69,7 @@ var (
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限制
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{}) // 已经加入了其它国家势力
......
[DATABASE]
MYSQL_HOST=ua4papc3hmgqf351pbej-rw4rm.rwlb.dubai.rds.aliyuncs.com
MYSQL_USERNAME=nextvideo
MYSQL_USERNAME=hilo_group
MYSQL_PASSWORD=ihlUwI4nhi9W88MI
MYSQL_DB=hilo
[DATABASECODE]
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=r-eb3btxn8vfdsuwdbuf.redis.dubai.rds.aliyuncs.com:6379
REDIS_PASSWORD=
REDIS_CLUSTER_HOST=r-eb3yt6k8zgxs62kjjs.redis.dubai.rds.aliyuncs.com:6379
REDIS_CLUSTER_PASSWORD=
[JWT]
SECRET=hilo1504
ISSUER_API=hiloApi
......
......@@ -4,6 +4,7 @@ import (
"encoding/json"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/utils"
"github.com/gin-gonic/gin"
"hilo-group/myerr"
"net/http"
......@@ -16,6 +17,7 @@ type Response struct {
MessageData interface{} `json:"messageData"` // 消息详情
OperationMessage interface{} `json:"operationMessage"` // 操作消息
Data interface{} `json:"data"` // 数据
Edata interface{} `json:"edata"` // 数据
}
/**
......@@ -30,7 +32,12 @@ func ResponseOk(c *gin.Context, data interface{}) {
Code: myerr.GetSuccessCode(),
Message: myerr.GetSuccessMsg(),
OperationMessage: myerr.GetSuccessMsg(),
Data: data,
}
if _, ok := c.Get(mycontext.InnerEncrypt); ok {
//response.Edata = utils.EncryptionData(data, []byte("484194d4d0f968a7"))
response.Edata = utils.EncryptionData(data, []byte("hilo!@#$%^&*()_+"))
} else {
response.Data = data
}
printResponseBody(c, &response)
......@@ -116,15 +123,21 @@ type Page struct {
func ResponsePageOk(c *gin.Context, data interface{}, total uint, index int) {
// always return http.StatusOK
pageData := Page{
Total: total,
Index: index,
Data: data,
}
response := Response{
Code: myerr.GetSuccessCode(),
Message: myerr.GetSuccessMsg(),
OperationMessage: myerr.GetSuccessMsg(),
Data: Page{
Total: total,
Index: index,
Data: data,
},
}
if _, ok := c.Get(mycontext.InnerEncrypt); ok {
//response.Edata = utils.EncryptionData(data, []byte("484194d4d0f968a7"))
response.Edata = utils.EncryptionData(pageData, []byte("hilo!@#$%^&*()_+"))
} else {
response.Data = pageData
}
printResponseBody(c, &response)
......@@ -149,15 +162,21 @@ func ResponsePageBaseOk(c *gin.Context, data interface{}, nextPageIndex int, has
if data == nil {
data = make([]interface{}, 0)
}
pageData := PageRespBase{
NextPageIndex: nextPageIndex,
HasNextPage: hasNextPage,
Data: data,
}
response := Response{
Code: myerr.GetSuccessCode(),
Message: myerr.GetSuccessMsg(),
OperationMessage: myerr.GetSuccessMsg(),
Data: PageRespBase{
NextPageIndex: nextPageIndex,
HasNextPage: hasNextPage,
Data: data,
},
}
if _, ok := c.Get(mycontext.InnerEncrypt); ok {
//response.Edata = utils.EncryptionData(data, []byte("484194d4d0f968a7"))
response.Edata = utils.EncryptionData(pageData, []byte("hilo!@#$%^&*()_+"))
} else {
response.Data = pageData
}
c.JSON(http.StatusOK, response)
}
......@@ -47,8 +47,9 @@ func CanShareChargeLink(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
type res struct {
ShareUrl string `json:"shareUrl"`
ShareIcon string `json:"shareIcon"`
ShareUrl string `json:"shareUrl"`
ShareIcon string `json:"shareIcon"`
RechargeUrl string `json:"rechargeUrl"`
}
// 安卓3.8.0版本有bug,这里暂时兼容
......@@ -57,16 +58,17 @@ func CanShareChargeLink(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil {
return myContext, err
}
myUser, err := user_c.GetUserTinyById(model, userId)
if err != nil {
return myContext, err
}
if deviceType == "android" {
if (major > 3) || (major == 3 && minor >= 8) {
myUser, err := user_c.GetUserTinyById(model, userId)
if err != nil {
return myContext, err
}
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
}
......@@ -23,6 +23,7 @@ import (
"hilo-group/cv/group_power_cv"
"hilo-group/cv/medal_cv"
"hilo-group/cv/user_cv"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/cache/res_c"
"hilo-group/domain/cache/user_c"
"hilo-group/domain/model/game_m"
......@@ -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 {
return myContext, myerr.WrapErr(err)
}
......
......@@ -10,6 +10,7 @@ import (
"hilo-group/_const/enum/groupPower_e"
"hilo-group/cv/group_power_cv"
"hilo-group/cv/user_cv"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_power_s"
......@@ -264,7 +265,7 @@ func GroupPowerStarPeriod(c *gin.Context) (*mycontext.MyContext, error) {
}
var model = domain.CreateModelContext(myContext)
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 {
return myContext, err
}
......
package group_power_r
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/gin-gonic/gin"
"github.com/jinzhu/now"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/enum/msg_e"
"hilo-group/_const/redis_key/groupPower_k"
"hilo-group/cv/group_power_cv"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/msg_m"
"hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_power_s"
"hilo-group/myerr/bizerr"
"hilo-group/resp"
"time"
)
type MGetGroupPowerReq struct {
......@@ -93,3 +98,66 @@ func Test(c *gin.Context) (*mycontext.MyContext, error) {
//}
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) {
if err != nil {
return myContext, err
}
model.Log.Infof("BuildJoinedGroupInfo, roomEnterTime: %v", roomEnterTime)
//model.Log.Infof("BuildJoinedGroupInfo, roomEnterTime: %v", roomEnterTime)
// 正在进行的游戏
games := game_m.GetNotEndGamesMap(model)
......@@ -374,7 +374,7 @@ func PluginReady(c *gin.Context) (*mycontext.MyContext, error) {
// @Router /v1/imGroup/roomInfo/{groupId} [get]
func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
start := time.Now()
groupId := c.Param("groupId")
if len(groupId) <= 0 {
return myContext, myerr.NewSysError("groupId 为必填项")
......@@ -407,7 +407,8 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
deviceType, appVersion := cast.ToString(_deviceType), cast.ToString(_appVersion)
vc := version_m.GetVersionControlByPlatform(model, deviceType)
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 := ""
var themeId uint64 = 0
......@@ -457,10 +458,15 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
ThemeUrl: themeUrl,
ThemeType: themeType,
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 {
return myContext, err
}
......@@ -503,11 +509,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
}
}
roles, orderList, err := group_m.GetRolesInGroup(model, groupId)
if err != nil {
return myContext, err
}
model.Log.Infof("GetRoomInfo cost 2:%v", time.Now().Sub(start).Seconds())
users, err := user_cv.GetUserTinyMap(orderList)
if err != nil {
return myContext, err
......@@ -545,6 +547,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
}
result.WelcomeText = strings.ReplaceAll(result.WelcomeText, "@%s", "")
model.Log.Infof("GetRoomInfo cost 3:%v", time.Now().Sub(start).Seconds())
// 补上房间流水勋章
var pe *medal_cv.PicElement
result.TotalConsume, pe, err = medal_cv.GetGroupConsumeMedal(model, groupId)
......@@ -554,7 +557,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
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{}).
Joins("INNER JOIN group_medal m ON m.res_medal_id = res_medal.id").
Where("m.im_group_id = ?", groupId).
......@@ -569,8 +572,9 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
})
}
} 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)
if err != nil {
......@@ -597,31 +601,29 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
})
}
} 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 {
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 {
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 cpEntryEffect bool
if cp, _ := rpc.GetUserCp(model, userId); cp != nil {
for _, v := range cp.MyPrivilegeList {
if v.Type == 5 {
cpEntryEffect = true
}
}
result.CpLevel = cp.CpLevel.Level
if cp.CpUserInfo != nil && cp.CpUserInfo.Avatar != nil {
result.CpUserAvatar = *cp.CpUserInfo.Avatar
}
if cp, _ := rpc.GetUserCpEntryEffect(model, userId); cp != nil {
cpEntryEffect = cp.CpEntryEffect
result.CpLevel = cp.CpLevel
result.CpUserAvatar = cp.CpUserAvatar
}
if user, _ := user_cv.GetUserDetail(model, userId, userId); user != nil {
if user.IsVip {
......@@ -640,6 +642,7 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
entryEffectType = 1
}
result.EntryEffectType = entryEffectType
model.Log.Infof("GetRoomInfo cost 8:%v", time.Now().Sub(start).Seconds())
resp.ResponseOk(c, result)
return myContext, nil
......@@ -848,7 +851,8 @@ func GroupBannerList(c *gin.Context) (*mycontext.MyContext, error) {
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)
continue
}
......
package group_r
import (
"context"
"fmt"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
......@@ -16,8 +18,9 @@ import (
"hilo-group/cv/group_power_cv"
"hilo-group/cv/medal_cv"
"hilo-group/cv/user_cv"
"hilo-group/domain/cache/group_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/group_m"
"hilo-group/domain/model/noble_m"
......@@ -72,14 +75,12 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
}
model := domain.CreateModelContext(myContext)
/* 2022-06-30 老板说先不分区
regions, err := res_m.GetAllLangRegion(model)
// 获取国家信息
_, area, err := user_m.GetUserCountryArea(model, myUserId)
if err != nil {
model.Log.Errorf("GetUserCountryArea 获取国家资源错误 userId:%d, err:%v", myUserId, 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)
if err != nil {
return myContext, err
......@@ -90,7 +91,7 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil {
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)
......@@ -99,7 +100,7 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil {
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
hiddenCount := 0
......@@ -115,12 +116,15 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
hiddenCount++
continue
}
// 过滤掉游戏房
if gameGroups[i] {
continue
}
groupIds = append(groupIds, i)
}
model.Log.Infof("GetPopularGroups, micGroupNum: %v, banned %d, hidden %d,cost:%v", micGroupNum, banCount, hiddenCount, time.Now().Sub(start))
// 3. 处理置顶群
topGroupIds, err := getTopGroups(model, bannedGroups, hiddenGroups)
topGroupIds, err := getTopGroups(model, bannedGroups, hiddenGroups, area)
if err != nil {
return myContext, err
}
......@@ -147,30 +151,10 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
}
for _, i := range topGroupIds {
/* 2022-06-30 老板说先不分区 // 置顶只对同语言区的生效
if myRegion != regions[topGroupInfo[i].Country] {
continue
}
*/
// 已经置顶的,直接进队列,不再参与排序
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)
// 国家区域信息
resAreaMap, err := res_c.GetCountryAreaMap(model)
......@@ -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()
bTime := now.Add(-time.Minute * 30)
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 {
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)
if err != nil {
......@@ -261,15 +243,9 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
// * 同国家 ^ 麦上有人 + 开放群 - 需要等级的群
for _, g := range sortedGroupIds {
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)
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)
......@@ -303,7 +279,7 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
//if err != nil {
// 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)
if err != nil {
......@@ -402,8 +378,8 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, nil
}
func getTopGroups(model *domain.Model, bannedGroups map[string]uint64, hiddenGroups map[string]struct{}) ([]string, error) {
topGroups, err := group_m.GroupTopGetAll(model)
func getTopGroups(model *domain.Model, bannedGroups map[string]uint64, hiddenGroups map[string]struct{}, area int) ([]string, error) {
topGroups, err := group_m.GroupTopGetAll(model, area)
if err != nil {
return nil, err
}
......@@ -470,9 +446,13 @@ func GetLatestGroups(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil {
return myContext, err
}
gameGroups := group_m.GetGameGroupsMap(model)
gids := make([]string, 0)
for i, _ := range micGroupNum {
// 过滤游戏房
if gameGroups[i] {
continue
}
gids = append(gids, i)
}
// 获取最新群组列表
......@@ -703,11 +683,12 @@ func GetRecentGroup(c *gin.Context) (*mycontext.MyContext, error) {
model := domain.CreateModelContext(myContext)
uer := group_m.UserEnterRoom{UserId: userId}
rec, err := uer.Find(model.Db)
if err != nil {
return myContext, err
}
//uer := group_m.UserEnterRoom{UserId: userId}
//rec, err := uer.Find(model.Db)
//if err != nil {
// return myContext, err
//}
rec, roomEnterTime := group_c.GetUserRecentRooms(model, userId, 0, 50)
myGroups, err := group_m.FindGroupMapByOwner(model, userId)
if err != nil {
......@@ -716,14 +697,14 @@ func GetRecentGroup(c *gin.Context) (*mycontext.MyContext, error) {
// 剔除自己创建的群
groupIds := make([]string, 0)
for _, i := range rec {
if _, ok := myGroups[i.GroupId]; !ok {
groupIds = append(groupIds, i.GroupId)
for _, groupId := range rec {
if _, ok := myGroups[groupId]; !ok {
groupIds = append(groupIds, groupId)
}
}
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 {
return myContext, err
}
......@@ -796,7 +777,7 @@ func GetMyGroup(c *gin.Context) (*mycontext.MyContext, error) {
// @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} GroupMembersRsp
// @Success 200 {object} GetGroupVisitorsRsp
// @Router /v1/imGroup/visitors/{groupId} [get]
func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
......@@ -827,27 +808,28 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
uer := group_m.UserEnterRoom{GroupId: groupId}
rows, err := uer.Find(model.Db)
if err != nil {
return myContext, err
}
//uer := group_m.UserEnterRoom{GroupId: groupId}
//rows, err := uer.Find(model.Db)
//if err != nil {
// return myContext, err
//}
rows := group_c.GetLastRoomVisitors(model, groupId)
now := time.Now()
t := now.AddDate(0, 0, -15) // 只要15天内进入房间的人
//now := time.Now()
//t := now.AddDate(0, 0, -15) // 只要15天内进入房间的人
userIds := make([]uint64, 0)
for _, i := range rows {
if i.EnterTime.After(t) {
userIds = append(userIds, i.UserId)
}
for _, u := range rows {
//if i.EnterTime.After(t) {
userIds = append(userIds, u)
//}
}
users, err := user_m.GetUserMapByIds(model, userIds)
if err != nil {
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)
if uint(beginPos) < result.Total {
......@@ -867,7 +849,7 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
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)
if err != nil {
......@@ -888,7 +870,7 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
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)
if err != nil {
......@@ -943,7 +925,7 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
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
if endPos > len(userIds) {
......@@ -961,15 +943,174 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
if _, ok := roomUserMap[u]; ok {
inRoom = true
}
result.Members = append(result.Members, group_cv.MemberDetail{
CvUserExtend: userExtends[u],
Role: roles[u],
OnlineStatus: statusMap[users[u].ExternalId],
InRoom: inRoom,
result.Members = append(result.Members, group_cv.GroupVisitorsDetail{
CvGroupMember: user_cv.CvUserExtendToCvGroupMember(userExtends[u]),
Role: roles[u],
OnlineStatus: statusMap[users[u].ExternalId],
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)
// 清理15天之前的访客,定期
if time.Now().Second() == 0 {
group_c.RemoveRoomVisitors(model, groupId)
}
return myContext, nil
}
......@@ -1234,17 +1375,17 @@ func GetGroupByCountry(c *gin.Context) (*mycontext.MyContext, error) {
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()
groups, banCount, visitCount, err := getCandidatesByCountry(model, bannedGroups, countryShortName)
groups, banCount, visitCount, err := group_s.GetCandidatesByCountry(model, bannedGroups, countryShortName)
if err != nil {
return myContext, err
}
endTime := time.Now()
model.Log.Infof("GetGroupByCountry: candidates size = %d, takes %d ms banned = %d, visitCount size = %d",
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)
......@@ -1447,47 +1588,180 @@ func GetGroupByCountry(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, 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)
func GetGroupByCountryV2(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
myUserId, err := req.GetUserId(c)
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 {
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
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
hotGroupList := make([]*group_m.GroupInfo, 0)
// * 同语言区 ^ 麦上有人 + 开放群 - 需要等级的群
for _, i := range sortedGroupIds {
gInfo, err := group_m.GetGroupInfo(model, i)
if err != nil {
model.Log.Errorf("GetGroupByCountry err:%v", err)
return myContext, err
}
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 {
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)
// 返回结果
result := make([]group_cv.PopularGroupInfo, 0)
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)
groupIds := make([]string, 0)
owners := make([]uint64, 0)
for _, i := range hotGroupList {
groupIds = append(groupIds, i.ImGroupId)
owners = append(owners, i.Owner)
}
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]
visitCount[v.ImGroupId] = vc
for _, i := range hotGroupList {
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 资源
......
......@@ -439,7 +439,7 @@ func GroupMicTaskInviteDialog(c *gin.Context) (*mycontext.MyContext, error) {
endTime := beginTime.AddDate(0, 0, 1)
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,
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 {
......@@ -550,12 +550,13 @@ func GroupMicIn(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
if micUser != nil {
if iStr == "" {
// 同房间且上麦序列为空
if iStr == "" && micUser.GroupUuid == groupUuid {
// 非切麦操作
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
}
}
......
......@@ -448,7 +448,7 @@ func GetGroupDetail(c *gin.Context) (*mycontext.MyContext, error) {
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()
if err != nil {
return myContext, err
......@@ -1238,6 +1238,12 @@ type GroupMembersRsp struct {
Total uint `json:"total"`
}
type GetGroupVisitorsRsp struct {
Members []group_cv.GroupVisitorsDetail `json:"members"`
Online uint `json:"online"` // 在线人数
Total uint `json:"total"`
}
// @Tags 群组
// @Summary 获取永久成员列表
// @Accept application/x-www-form-urlencoded
......@@ -1724,8 +1730,11 @@ func downgradeRoom(myContext *mycontext.MyContext, gi *group_m.GroupInfo) error
// @Param nonce header string true "随机数字"
// @Param groupId formData string true "群ID"
// @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 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
// @Router /v1/imGroup/in [put]
func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
......@@ -1738,6 +1747,23 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
password := c.PostForm("password")
enterType := c.PostForm("enterType")
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)
gi, err := group_m.GetInfoByTxGroupId(model, groupId)
......@@ -1828,6 +1854,14 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
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 {
return myContext, err
......@@ -1837,9 +1871,9 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
myContext.Log.Infof("GroupIn, ProcessRoomVisit err: %s", err.Error())
}
// 更新用户进入房间缓存记录
if err = room_c.ProcessUserRoomVisit(userId, groupId); err != nil {
myContext.Log.Infof("GroupIn, ProcessUserRoomVisit err: %s", err.Error())
}
//if err = room_c.ProcessUserRoomVisit(userId, groupId); err != nil {
// myContext.Log.Infof("GroupIn, ProcessUserRoomVisit err: %s", err.Error())
//}
resp.ResponseOk(c, group_cv.GroupChannelId{
ChannelId: channelId,
Token: token,
......@@ -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)
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 {
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) {
if err == nil {
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 {
return myContext, err
......@@ -719,6 +721,7 @@ func KickGroupMembers(c *gin.Context) (*mycontext.MyContext, error) {
model := domain.CreateModelContext(myContext)
txGroupId := groupId
groupId, err = group_m.ToImGroupId(model, groupId)
if err != nil {
return myContext, err
......@@ -750,6 +753,8 @@ func KickGroupMembers(c *gin.Context) (*mycontext.MyContext, error) {
Source: myExtId, Target: externalId, Content: string(buf)}
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 {
return myContext, err
......
......@@ -6,13 +6,11 @@ import (
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/gin-gonic/gin"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/msg_e"
"hilo-group/cv/group_cv"
"hilo-group/cv/user_cv"
"hilo-group/domain/cache/group_c"
"hilo-group/domain/model/gift_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/res_m"
"hilo-group/domain/model/user_m"
......@@ -111,18 +109,28 @@ func GetSupportDetail(c *gin.Context) (*mycontext.MyContext, error) {
result := group_cv.SupportPageDetail{GroupId: txGroupId}
now := time.Now()
beginTime, endTime, _ := group_m.GetSupportLevelTime(now)
_, endTime, period := group_m.GetSupportLevelTime(now)
result.RemainSecond = endTime.Unix() - now.Unix()
g := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, SceneUid: groupId, Model: model}
result.CurrentCount, result.CurrentConsume, err = g.GetConsumeByRange(beginTime, endTime)
//g := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, SceneUid: groupId, Model: model}
//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 {
model.Log.Errorf("GetSupportDetail groupId:%s, err:%v", groupId, err)
return myContext, err
}
beginTime, endTime, _ = group_m.GetSupportLevelTime(now.AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
result.LastCount, result.LastConsume, err = g.GetConsumeByRange(beginTime, endTime)
_, _, periodLast := group_m.GetSupportLevelTime(now.AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
//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 {
model.Log.Errorf("GetSupportDetail groupId:%s, err:%v", groupId, err)
return myContext, err
}
......@@ -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}
rows, err := gsaa.Get(model.Db)
if err != nil {
......@@ -222,16 +230,16 @@ func TryAddSupporter(c *gin.Context) (*mycontext.MyContext, error) {
if role != group_e.GROUP_MANAGER && role != group_e.GROUP_ADMIN {
return myContext, bizerr.NotManagerOrAdmin
}
// 判断财富等级必须要大于等于8
// 判断财富等级必须要大于等于3
wealthGrade, _, err := user_m.GetWealthGrade(model, userId)
if err != nil {
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级
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)
......@@ -335,20 +343,24 @@ func TakeSupportAward(c *gin.Context) (*mycontext.MyContext, error) {
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)
resSupportId, _, err := group_s.NewGroupService(myContext).GetSupportLevel(groupId)
resSupport, supportLevel, err := group_s.NewGroupService(myContext).GetSupportLevelByRedis(groupId)
if err != nil {
return myContext, err
}
if resSupportId <= 0 {
if resSupport.ID <= 0 {
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限制
userIp, err := user_m.GetUserIpMap(model.Db, userIds)
if err != nil {
......@@ -366,22 +378,28 @@ func TakeSupportAward(c *gin.Context) (*mycontext.MyContext, error) {
msg = fmt.Sprintf(resMul.Content, codeMap[uid])
}
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{})
}
}
}
for ip, cnt := range sameIp {
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 {
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{})
}
}
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 {
return myContext, err
}
......
......@@ -5,6 +5,7 @@ import (
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/utils"
"github.com/gin-gonic/gin"
"hilo-group/myerr/bizerr"
"hilo-group/req"
......@@ -133,3 +134,15 @@ func LoggerHandle(c *gin.Context) {
latency := end.Sub(start)
mycontext.CreateMyContext(c.Keys).Log.Infof("request end fullPath:%v,url:%v, method: %v, traceId:%v, latency:%v userId:%v", c.FullPath(), reqUri, method, traceId, latency, userId)
}
// 加密Handle
func EncryptHandle(c *gin.Context) {
header := c.Request.Header
appVersion := header.Get("Appversion")
if len(appVersion) > 0 {
if high, _ := utils.CompareVersion(appVersion, "> 3.9.0"); high {
c.Set(mycontext.InnerEncrypt, true)
}
}
c.Next()
}
......@@ -31,8 +31,8 @@ func InitRouter() *gin.Engine {
//
imGroup.POST("/group", wrapper(group_r.CreateGroup))
imGroup.DELETE("/group/:groupId", wrapper(group_r.DestroyGroup))
imGroup.GET("/group/:code", wrapper(group_r.GetGroupInfo))
imGroup.GET("/detail/:groupId", wrapper(group_r.GetGroupDetail))
imGroup.GET("/group/:code", EncryptHandle, wrapper(group_r.GetGroupInfo))
imGroup.GET("/detail/:groupId", EncryptHandle, wrapper(group_r.GetGroupDetail))
imGroup.PUT("/group/:groupId", wrapper(group_r.ModifyGroupInfo))
imGroup.GET("/search/:code", wrapper(group_r.SearchGroup))
imGroup.DELETE("/member/:groupId", wrapper(group_r.LeaveGroup))
......@@ -42,13 +42,14 @@ func InitRouter() *gin.Engine {
imGroup.GET("/myRecent", wrapper(group_r.GetRecentGroup))
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))
//// 2.19的新接口
imGroup.GET("/ownGroup", wrapper(group_r.GetOwnGroup))
imGroup.GET("/theirGroup/:userExternalId", wrapper(group_r.GetTheirGroups))
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("/role/:groupId", wrapper(group_r.GetGroupRole))
......@@ -92,7 +93,7 @@ func InitRouter() *gin.Engine {
imGroup.POST("/mic/speech/close", wrapper(group_r.GroupMicSpeechClose))
imGroup.POST("/mic/mute", wrapper(group_r.GroupMicMute))
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("/kick", wrapper(group_r.GroupKick))
imGroup.PUT("/user/msg/status", wrapper(group_r.GroupUserMsg))
......@@ -106,7 +107,7 @@ func InitRouter() *gin.Engine {
imGroup.POST("/mgr/clearScreen", wrapper(group_r.GroupMgrClearScreen))
imGroup.GET("/online/users", wrapper(group_r.GroupInUsers))
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.POST("/theme/custom", wrapper(group_r.GroupThemeAdd))
......
......@@ -3,8 +3,10 @@ package test
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/utils"
"github.com/jinzhu/now"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/service/group_power_s"
......@@ -69,3 +71,14 @@ func TestGetRandomImProvider(t *testing.T) {
fmt.Printf("true--------------times0:%v\n", times0)
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
[REDIS]
REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT]
SECRET=hilo1632
ISSUER_API=hiloApi
......
package 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")
}