...
 
Commits (284)
package groupPower_e
import "git.hilo.cn/hilo-common/resource/mysql"
//国家势力状态
type GroupPowerStatus = mysql.Type
type GroupPowerStatus = uint8
const (
//上架
......@@ -15,7 +13,7 @@ const (
)
//国家势力用户角色
type GroupPowerUserRole = mysql.Type
type GroupPowerUserRole = uint8
const (
//普通用户
......@@ -27,7 +25,7 @@ const (
)
//国家势力排行榜类型
type GroupPowerRankType = mysql.Type
type GroupPowerRankType = uint8
const (
GroupPowerRankTypeFamous GroupPowerRankType = 1
......@@ -36,7 +34,7 @@ const (
)
//国家势力日志操作类型
type GroupPowerUserLogType = mysql.Type
type GroupPowerUserLogType = uint8
const (
//加入
......@@ -51,7 +49,7 @@ const (
GroupPowerUserLogDissolve GroupPowerUserLogType = 5
)
type GroupPowerDiamondLogType = mysql.Type
type GroupPowerDiamondLogType = uint8
const (
//群组原因加入
......@@ -67,3 +65,7 @@ const (
PowerSuppportAwarded PowerSupportAwardState = 1 // 已经领取
PowerSuppportWaiting PowerSupportAwardState = 2 // 待领取
)
const (
LongestNameplate = 15
)
......@@ -156,3 +156,11 @@ var GROUP_NOBLE4_JOIN_LIMIT uint = 1000
var GROUP_ROLE_PERSONAL_VIEW_LIMIT = 5
var GROUP_MANAGER_LIMIT uint = 30
var GROUP_ADMIN_LIMIT uint = 50
type GroupProvider = uint8
const (
// 群组声音供应商
GroupProvider_SW GroupProvider = 0 // 声网
GroupProvider_TRTC GroupProvider = 1 // 腾讯trtc
)
package groupPower_k
import (
"fmt"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key"
)
// 家族之星榜单
// type: 1:送礼 2:活跃 3:收礼
// date:天/周/月的开始时间
const GroupPowerStarPrefix = "groupPowerStar:${type}:${period}:${groupPowerId}:${date}" // zset member:userId score:分数
func GetGroupPowerStarRankKey(_type groupPower_e.GroupPowerStarType, period string, groupPowerId uint64, date string) string {
return redis_key.ReplaceKey(GroupPowerStarPrefix,
fmt.Sprintf("%d", _type), period, fmt.Sprintf("%d", groupPowerId), date)
}
package group_k
import (
"fmt"
"hilo-group/_const/redis_key"
)
// 用户进房的key
const (
UserEnterRoomPrefix = "uer:"
UserEnterRoomUserKey = UserEnterRoomPrefix + "u:${user_id}"
UserEnterRoomGroupKey = UserEnterRoomPrefix + "g:${group_id}"
)
func GetUserEnterRoomUserKey(userId uint64) string {
return redis_key.ReplaceKey(UserEnterRoomUserKey, fmt.Sprintf("%d", userId))
}
func GetUserEnterRoomGroupKey(groupId string) string {
return redis_key.ReplaceKey(UserEnterRoomGroupKey, groupId)
}
......@@ -10,9 +10,33 @@ import (
const (
MicPrefix = "mic:"
MicDayInvite = MicPrefix + "day:invite:${userId}:${date}" // string 自动被邀请上麦,1天一次,TTL:24H
MicGroupPowerOnMic = MicPrefix + "groupPower:${userId}:${date}" // 家族内群上麦分钟数
MicUserOnMic = MicPrefix + "user:onMic:${tz}:${userId}:${date}"
MicGroupOnMic = MicPrefix + "group:onMic:${groupId}" // 在群组麦位上的人 hset field:micIndex member:userId
)
func GetUserMicDayInvite(userId mysql.ID) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicDayInvite, fmt.Sprintf("%d", userId), date)
}
// 家族内群上麦分钟数
func GetMicGroupPowerOnMic(userId uint64) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicGroupPowerOnMic, fmt.Sprintf("%d", userId), date)
}
// 获取用户上麦时间
// 北京、沙特时间
func GetUserOnMicKey(userId uint64, tz, date string) string {
return redis_key.ReplaceKey(MicUserOnMic, tz, fmt.Sprintf("%d", userId), date)
}
// 获取群组麦位上的人
// 可能会有数据不一致,已原来麦位的key为准
// 这里用户快速获取群上麦位的人用,代替大量mget命令慢查询
func GetGroupOnMicUser(groupId string) string {
return redis_key.ReplaceKey(MicGroupOnMic, groupId)
}
package mic_k
// onMic异步入库
const (
OnMicQueue = "onMic:hilo_group"
)
func GetOnMicQueue() string {
return OnMicQueue
}
......@@ -249,6 +249,9 @@ const groupInUserDuration = "group_in_user_duration_{groupUuid}"
// 15天内进入房间的人数
const roomVisitCount = "room_visit_count"
// 15天内进入房间的人数 member groupId score 麦位有人的数量
const roomVisitCountZSet = "room_visit_count_zset"
// 用户进入过的房间及时间
const userEnterRoom = "enter_room_{userId}"
......@@ -261,6 +264,9 @@ const groupPowerDiamond = "group_diamond_{period}"
// 国家Icon
const countryIcon = "contry_icon"
// 国家Area
const countryArea = "contry:area"
// 群贡献前三
const groupTop3Consume = "group_top3_consume_{period}_{groupId}"
......@@ -754,18 +760,27 @@ func GetPrefixGroupMicNumType(groupUuid string) string {
return strings.Replace(groupMicNumType, "{groupUuid}", groupUuid, -1)
}
// Deprecated: 用户进房时间
// 用 uer:g:${group_id}代替
func GetPrefixGroupInUserDuration(groupUuid string) string {
return strings.Replace(groupInUserDuration, "{groupUuid}", groupUuid, -1)
}
// Deprecated: 用户进房时间
// 可用 uer:u:${user_id}代替
func GetUserEnterRoomKey(userId uint64) string {
return strings.Replace(userEnterRoom, "{userId}", strconv.FormatUint(userId, 10), -1)
}
// Deprecated: 用redis集群中的zset代替
func GetPrefixRoomVisitCount() string {
return roomVisitCount
}
func GetPrefixRoomVisitCountZset() string {
return roomVisitCountZSet
}
func GetPrefixSupportLevel(date string) string {
return strings.Replace(supportLevel, "{date}", date, -1)
}
......@@ -778,6 +793,10 @@ func GetCountryIconKey() string {
return countryIcon
}
func GetCountryAreaKey() string {
return countryArea
}
func GetGroupTop3ConsumeKey(period string, groupId string) string {
return strings.Replace(strings.Replace(groupTop3Consume, "{period}", period, -1), "groupId", groupId, -1)
}
......
......@@ -107,6 +107,9 @@ const (
MSG_ID_BUY_FROM_FAMILY MsgIdType = 167 // 请向本家族代理购买钻石
MSG_ID_NEED_JOIN_FAMILY MsgIdType = 168 // 请加入代理的家族后进行购买
MSG_ID_SET_FAMILY_NAMEPL MsgIdType = 169 // 等级不够不能修改家族铭牌
MSG_ID_CHARGE_NO_AREA MsgIdType = 181 // 充值(代理转账,用户给代理充值),失败,不是本区域用户
MSG_ID_BAN_MIC_NOBLE_5 MsgIdType = 188 //无法禁言VIP5和vip6
MSG_ID_KICK_NOBLE_5 MsgIdType = 189 //无法踢出VIP5和vip6
ADD_GROUP_FAILED AddGroupResultType = 0
ADD_GROUP_DONE AddGroupResultType = 1
......
......@@ -5,14 +5,24 @@ import (
"hilo-group/cron/gift_cron"
"hilo-group/cron/group_cron"
"hilo-group/cron/mic_cron"
"hilo-group/cron/user_cron"
)
func Init() {
user_cron.LoadSvipVipNoble() // 加载用户特权
if !config.IsMaster() {
return
}
gift_cron.SendGiftEventInit() // 礼物消息
gift_cron.GiftRemark() // 礼物消息补偿
//gift_cron.SendGiftEventInit() // 礼物消息
//gift_cron.GiftRemark() // 礼物消息补偿
gift_cron.SendGiftEvent() // 礼物事件
mic_cron.OnMicCheck() // 检查上麦
mic_cron.OnMicQueue() // 检查上麦-队列操作
group_cron.GroupPowerExpClear() // 清理家族经验/等级
group_cron.GroupPowerMonthRankAct()
//group_cron.GroupInEventInit() // 进房事件
//group_cron.CreateGroup() //
group_cron.CalcGroupSupport() // 群组扶持计算
//group_cron.CalcGroupSupport_OldData()
group_cron.GroupCountryListSort()
}
......@@ -30,6 +30,7 @@ func GiftRemark() {
Payload: unmark.Payload,
MarkHiloGroup: unmark.MarkHiloGroup,
Mark: unmark.Mark, // 不能影响别的服务的mark状态
MarkHiloUser: unmark.MarkHiloUser,
}); err != nil {
model.Log.Errorf("FetchUnMarkEvent add unmark fail:%v", err)
continue
......
package gift_cron
import (
"context"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/domain/cache/gift_c"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/event/gift_ev"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m"
"time"
)
// 送礼事件
func SendGiftEvent() {
//if !config.IsMaster() {
// return
//}
go func() {
for true {
model := domain.CreateModelNil()
if sendGiftEvent := gift_c.BLPopQueueSendGift(model); sendGiftEvent != nil {
groupPowerGrade(model, sendGiftEvent) // 家族经验
groupPowerStar(model, sendGiftEvent) // 家族之星
groupSupportAddConsume(model, sendGiftEvent) // 群组扶持
}
}
}()
}
// 群组势力经验
func groupPowerGrade(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent)
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return
}
exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId)
if err != nil {
model.Log.Infof("CheckGroupPowerUser fail %+v", err)
return
}
if exist {
exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum
//return model.Transaction(func(model *domain.Model) error {
// return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
//})
//return groupPower_c.QueueGroupPowerGradeExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
if err := model.Transaction(func(model *domain.Model) error {
return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
}); err != nil {
model.Log.Errorf("IncrGroupPowerExp fail,data:%v-err:%v", *sendGiftEvent, err)
} else {
model.Log.Infof("IncrGroupPowerExp success,data:%v", *sendGiftEvent)
}
}
}
// 家族之星
func groupPowerStar(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return
}
var userIds = []mysql.ID{sendGiftEvent.SendUserId}
userIds = append(userIds, sendGiftEvent.ReceiveUserIds...)
groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds)
if err != nil {
model.Log.Errorf("AddSendGiftEventAsync fail:%v", err)
return
}
// 送礼加分
if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
if err := groupPower_c.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId,
groupPower_e.GroupPowerStarTypeFamous, diamonds); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore famous fail:%v", err)
}
}
// 收礼加分
for _, userId := range sendGiftEvent.ReceiveUserIds {
if data, ok := groupPowers[userId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum
if err := groupPower_c.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId,
groupPower_e.GroupPowerStarTypeCharm, diamonds); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore charm fail:%v", err)
}
}
}
return
}
// 群组扶持增加流水数据
func groupSupportAddConsume(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
if time.Now().Unix() <= 1693275900 {
return
}
model.Log.Infof("groupSupportAddConsume UserId:%d, sendGiftEvent:%+v", sendGiftEvent.SendUserId, sendGiftEvent)
if sendGiftEvent.SceneType != gift_e.GroupSceneType || sendGiftEvent.SceneUid == "" {
model.Log.Infof("groupSupportAddConsume UserId:%d, sendGiftEvent:%+v", sendGiftEvent.SendUserId, sendGiftEvent)
return
}
_, _, period := group_m.GetSupportLevelTime(time.Now())
// 钻石数
diamond := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
_, err := model.RedisCluster.ZIncrBy(context.Background(), keyDiamond, float64(diamond), sendGiftEvent.SceneUid).Result()
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, val:%d, member:%s, err:%v",
keyDiamond, diamond, sendGiftEvent.SceneUid, err)
}
err = redisCli.SetExpire(model.RedisCluster, keyDiamond, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, val:%d, member:%s, err:%v",
keyDiamond, diamond, sendGiftEvent.SceneUid, err)
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, sendGiftEvent.SceneUid)
err = model.RedisCluster.SAdd(context.Background(), keySupportNum, sendGiftEvent.SendUserId).Err()
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, UserId:%d, err:%v", keySupportNum, sendGiftEvent.SendUserId, err)
}
err = redisCli.SetExpire(model.RedisCluster, keySupportNum, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, UserId:%d, err:%v", keySupportNum, sendGiftEvent.SendUserId, err)
}
return
}
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/_const/enum/group_e"
"hilo-group/domain/service/group_s"
)
func CreateGroup() {
if !config.IsMaster() {
return
}
c := cron.New()
spec := "0 15 15 16 8 ?"
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
userId := uint64(7687)
num := 20
if config.AppIsRelease() {
userId = 8350311
num = 1000
}
err := group_s.NewGroupService(model.MyContext).CreateGroupMulByUid(userId, num, group_e.TwoMicNumType)
if err != nil {
model.Log.Errorf("CreateGroupMulByUid fail:%v", err)
}
})
c.Start()
}
package group_cron
import (
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"hilo-group/domain/service/event_s"
"time"
)
// 进房事件
func GroupInEventInit() {
if !config.IsMaster() {
return
}
mylogrus.MyLog.Infof("GroupInEventInit")
go func() {
ticker := time.NewTicker(time.Millisecond * 500)
defer ticker.Stop()
for {
select {
case <-ticker.C:
//start := time.Now()
myCtx := mycontext.CreateMyContext(nil)
// 消费进房事件
if err := event_s.NewGroupInEventService(myCtx).Consume(); err != nil {
myCtx.Log.Errorf("groupInEvent consume fail:%v", err)
} else {
//myCtx.Log.Infof("groupInEvent consume success,cost:%v", time.Now().Sub(start))
}
}
}
}()
}
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/domain/service/group_s"
)
// 清理家族经验和等级
func GroupCountryListSort() {
// 常用国家-每15分钟计算国家房间列表排序 /v1/imGroup/country [get] 接口
spec := "0 */15 * * * ?"
c := cron.New()
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
model.Log.Infof("GroupCountryListSort Common start")
group_s.SortGroupCommonCountryList(model)
model.Log.Infof("GroupCountryListSort Common end")
})
// 非常用国家-每60分钟计算国家房间列表排序 /v1/imGroup/country [get] 接口
spec2 := "0 59 * * * ?"
_ = c.AddFunc(spec2, func() {
var model = domain.CreateModelNil()
model.Log.Infof("GroupCountryListSort not Common start")
group_s.SortGroupNotCommonCountryList(model)
model.Log.Infof("GroupCountryListSort not Common end")
})
c.Start()
}
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/domain/service/group_power_s"
)
// 家族贡献月度排行榜发奖
func GroupPowerMonthRankAct() {
if !config.IsMaster() {
return
}
c := cron.New()
// 每月1号0:01结算发奖
spec := "0 1 0 1 * ?"
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
if err := group_power_s.CalcGroupPowerMonthRankAct(model); err != nil {
model.Log.Errorf("GroupPowerMonthRankAct fail:%v", err)
}
})
c.Start()
}
//func BufaGroupPowerMonthRankAct() {
// c := cron.New()
// spec := "0 50 15 1 * ?"
// _ = c.AddFunc(spec, func() {
// var model = domain.CreateModelNil()
// if err := group_power_s.BufaCalcGroupPowerMonthRankAct(model); err != nil {
// model.Log.Errorf("BufaGroupPowerMonthRankAct fail:%v", err)
// }
// })
//
// c.Start()
//}
package group_cron
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/sdk/tencentyun"
"git.hilo.cn/hilo-common/utils"
"github.com/robfig/cron"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/group_e"
"hilo-group/domain/model/gift_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/service/group_s"
"time"
)
// 群组扶持计算
func CalcGroupSupport() {
if !config.IsMaster() {
return
}
c := cron.New()
//北京时间周一0点,过了一秒后,
spec := "1 0 0 * * 1"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("cron CalcGroupSupport start")
calcTime := time.Now().AddDate(0, 0, -1)
if err := group_s.NewGroupService(model.MyContext).GroupSupportResult(calcTime); err != nil {
model.Log.Errorf("cron CalcGroupSupport faild calcTime:%v, err:%v", calcTime, err)
return
}
model.Log.Infof("cron CalcGroupSupport after GroupSupportResult")
//全服发送H5
if err := sendGroupSupportH5(domain.CreateModelContext(model.MyContext)); err != nil {
model.Log.Errorf("cron CalcGroupSupport err:%v", err)
} else {
model.Log.Infof("cron CalcGroupSupport success")
}
})
c.Start()
}
func sendGroupSupportH5(model *domain.Model) error {
groupIds, err := group_m.GetAllGroupsSorted(model)
if err != nil {
return err
}
model.Log.Infof("SendGroupSupportH5 groupIds:%v", groupIds)
groupSupportH5 := group_m.GroupSupportH5{
CommonPublicMsg: group_m.CommonPublicMsg{
Type: group_e.GroupSupportH5,
},
H5: config.GetH5Config().GROUP_SUPPORT,
}
buffer, err := json.Marshal(groupSupportH5)
if err != nil {
model.Log.Errorf("publicScreenMsg AddSendGiftAsync json.Marshal(giftContent) err:%v", err)
return err
}
content := string(buffer)
//策略1:for循环,没有开启协程,100个停一下
for i, _ := range groupIds {
func(groupId string, content string) {
defer utils.CheckGoPanic()
model.Log.Infof("SendGroupSupportH5 groupId:%v", groupId)
txGroupId, err := group_m.ToTxGroupId(model, groupId)
// 公屏消息
if err == nil {
tencentyun.SendCustomMsg(model.Log, txGroupId, nil, content, "")
}
}(groupIds[i], content)
if i != 0 && i%100 == 0 {
//躺平1秒
time.Sleep(1 * time.Second)
}
}
return nil
}
// 群组扶持计算-旧数据
func CalcGroupSupport_OldData() {
if !config.IsMaster() {
return
}
c := cron.New()
spec := "0 27 10 29 8 ?"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("CalcGroupSupport_OldData start")
//beginTime, endTime, period := group_m.GetSupportLevelTime(time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
beginTime, _, period := group_m.GetSupportLevelTime(time.Now())
endTime := time.Unix(1693275900, 0)
g := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, Model: model}
records, err := g.BatchGetConsumeByRange(beginTime, endTime)
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData beginTime:%v, endTime:%v, err:%v", beginTime, endTime, err)
return
}
// 流水写入redis
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
for _, r := range records {
if r.SceneUid == "" || r.Consume <= 0 {
continue
}
_, err = model.RedisCluster.ZIncrBy(context.Background(), keyDiamond, float64(r.Consume), r.SceneUid).Result()
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, val:%d, member:%s, err:%v",
keyDiamond, r.Consume, r.SceneUid, err)
}
}
err = redisCli.SetExpire(model.RedisCluster, keyDiamond, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, err:%v", keyDiamond, err)
return
}
// 支持者写入redis
for _, r := range records {
if r.SceneUid == "" || r.C <= 0 {
continue
}
// 支持者列表
support := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, SceneUid: r.SceneUid, Model: model}
uids, err := support.BatchGetSupportList(model, beginTime, endTime)
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData beginTime:%v, endTime:%v, imGroupId:%v, err:%v", beginTime, endTime, r.SceneUid, err)
continue
}
if len(uids) <= 0 {
continue
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, r.SceneUid)
for _, uid := range uids {
err = model.RedisCluster.SAdd(context.Background(), keySupportNum, uid).Err()
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, UserId:%d, err:%v", keySupportNum, uid, err)
}
}
err = redisCli.SetExpire(model.RedisCluster, keySupportNum, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("AddSendGiftEventAsync groupSupport key:%s, err:%v", keySupportNum, err)
}
}
model.Log.Infof("CalcGroupSupport_OldData end")
})
c.Start()
}
package mic_cron
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/cache/mic_c"
"hilo-group/domain/event/mic_ev"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/mic_m"
"hilo-group/domain/service/group_mic_s"
"time"
)
func OnMicCheck() {
c := cron.New()
//一分钟执行一次
spec := "0 */1 * * * ?"
spec := "30 */1 * * * ?"
_ = c.AddFunc(spec, func() {
//获取麦上的所有人
var model = domain.CreateModelNil()
......@@ -20,14 +26,15 @@ func OnMicCheck() {
return
}
for _, groupId := range groupIds {
onGroupMicKey := mic_k.GetGroupOnMicUser(groupId) // 同步在mic上的人
//遍历每个麦位
for i := 1; i <= 30; i++ {
for i := 1; i <= group_m.MaxMicNum; i++ {
micUser, err := group_m.GetMicUser(model, groupId, i)
if err != nil {
model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err)
}
if micUser != nil {
if err := mic_ev.PublishOnMicEvent(model, &mic_ev.OnMicEvent{
if err := mic_c.QueueOnMic(model, &mic_ev.OnMicEvent{
GroupUuid: micUser.GroupUuid,
I: micUser.I,
ExternalId: micUser.ExternalId,
......@@ -35,11 +42,43 @@ func OnMicCheck() {
Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp,
}); err != nil {
model.Log.Errorf("PublishOnMicEvent fail:%v", err)
model.Log.Errorf("QueueOnMic fail:%v", err)
}
// 设置mic上的人
model.Redis.HSet(model, onGroupMicKey, i, micUser.UserId)
} else {
// 删除mic上的人
model.Redis.HDel(model, onGroupMicKey, fmt.Sprintf("%d", i))
}
}
}
})
c.Start()
}
func OnMicQueue() {
for i := 0; i < 4; i++ {
go func() {
for true {
model := domain.CreateModelNil()
if onMic := mic_c.BLPopQueueOnMic(model); onMic != nil {
start := time.Now()
// 群组上麦经验
if err := group_mic_s.NewGroupPowerService(model.MyContext).IncrGroupPowerOnMicExpAndTime(onMic.GroupUuid, onMic.UserId, onMic.Timestamp); err != nil {
model.Log.Errorf("cron micIn GroupPowerOnMicExp err:%v", err)
} else {
model.Log.Infof("cron micIn GroupPowerOnMicExp success, groupId:%v, userId:%v,cost:%vs", onMic.GroupUuid, onMic.UserId, time.Now().Sub(start).Seconds())
}
// 用户上麦
//if err := mic_m.IncrUserOnMic(model, onMic.UserId, onMic.Timestamp); err != nil {
//if err := mic_m.IncrUserOnMicV2(model, onMic.UserId); err != nil {
if err := mic_m.IncrUserOnMicV3(model, onMic.UserId); err != nil {
model.Log.Errorf("cron micIn IncrUserOnMic err:%v", err)
} else {
}
}
}
}()
}
}
package user_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/domain/cache/user_c"
)
// 加载数据到lru
func LoadSvipVipNoble() {
go user_c.LoadAllSvipVipNoble(domain.CreateModelNil()) // 启动先执行一次
c := cron.New()
spec := "0 */30 * * * ?"
_ = c.AddFunc(spec, func() {
model := domain.CreateModelNil()
user_c.LoadAllSvipVipNoble(model)
})
c.Start()
}
......@@ -22,7 +22,15 @@ type BillboardUserInfo struct {
Num uint64 `json:"num"`
}
func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]BillboardUserInfo, error) {
//榜单中用户信息
type GroupTop3ConsumeUser struct {
//用户基本信息
UserBase user_cv.TopConsumersUser `json:"userBase"`
//数值
Num uint64 `json:"num"`
}
func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]GroupTop3ConsumeUser, error) {
now := time.Now()
period := now.Format(utils.COMPACT_MONTH_FORMAT)
data, err := getGroupTop3Consume(period, groupId)
......@@ -59,7 +67,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
ret, err := saveGroupTop3Consume(period, groupId, diamonds)
model.Log.Infof("GetGroupTop3Consume SAVE ret = %d, err: %v", ret, err)
return result, nil
list := make([]GroupTop3ConsumeUser, 0, len(result))
for _, v := range result {
list = append(list, GroupTop3ConsumeUser{
UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick},
})
}
return list, nil
}
userIds := make([]uint64, 0)
......@@ -86,7 +102,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
})
}
}
return result, nil
list := make([]GroupTop3ConsumeUser, 0, len(result))
for _, v := range result {
list = append(list, GroupTop3ConsumeUser{
UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick},
})
}
return list, nil
}
func getGroupTop3Consume(period string, groupId string) (map[string]string, error) {
......
package diamond_cv
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
. "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model/bean_m"
"hilo-group/domain/model/diamond_m"
"hilo-group/myerr"
"strconv"
)
type CvDiamond struct {
......@@ -26,33 +20,6 @@ type CvDiamondBean struct {
BeanNum string `json:"beanNum"`
}
func GetDiamondBean(userId mysql.ID) (*CvDiamondBean, error) {
var diamondAccount diamond_m.DiamondAccount
err := mysql.Db.Where(&diamond_m.DiamondAccount{
UserId: userId,
}).First(&diamondAccount).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
diamondAccount = diamond_m.DiamondAccount{
DiamondNum: 0,
}
}
return nil, err
}
var beanAccount bean_m.BeanAccount
err = mysql.Db.Where(&bean_m.BeanAccount{
UserId: userId,
}).First(&beanAccount).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
beanAccount = bean_m.BeanAccount{
BeanNum: 0,
}
}
}
return &CvDiamondBean{DiamondNum: diamondAccount.DiamondNum, BeanNum: strconv.FormatFloat(float64(beanAccount.BeanNum)/100, 'f', 2, 64)}, nil
}
type CvDiamondDetail struct {
//1:增加 2:减少
......@@ -75,112 +42,3 @@ func GetDiamond(userId mysql.ID) (*CvDiamond, error) {
}
return &CvDiamond{DiamondNum: NumToUint32(&diamondAccount.DiamondNum), PinkDiamondNum: NumToUint32(&diamondAccount.PinkDiamondNum)}, nil
}
\ No newline at end of file
func GetDiamondBalances(userIds []mysql.ID) (map[mysql.ID]mysql.Num, error) {
result := make(map[mysql.ID]mysql.Num, len(userIds))
data := make([]diamond_m.DiamondAccount, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&data).Error
if err != nil {
return nil, err
}
for _, i := range data {
result[i.UserId] = i.DiamondNum
}
return result, nil
}
//充值记录
func GetDiamondBuyList(userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
var diamondAccountDetails []diamond_m.DiamondAccountDetail
if err := mysql.Db.Model(&diamond_m.DiamondAccountDetail{}).
Where("user_id = ? AND operate_type in (?)", userId, []uint8{diamond_e.BuyDiamond, diamond_e.DealerTransfer, diamond_e.Checkout, diamond_e.PayerMax, diamond_e.Paypal}).
Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
return nil, err
}
var cvDiamondDetails []*CvDiamondDetail
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
//钻石明细,不包括充值
func GetDiamondDetailList(model *domain.Model, userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
diamondAccountDetails := make([]*diamond_m.DiamondAccountDetail, 0)
offset := (pageIndex - 1) * pageSize
optList := []int{int(diamond_e.BuyDiamond), int(diamond_e.DealerTransfer), int(diamond_e.Checkout), int(diamond_e.PayerMax)}
details := make([]*diamond_m.DiamondAccountDetail, 0)
if offset == 0 { // 首页请求数据,获取 pageSize*3 条过滤返回
sql := "select * from diamond_account_detail where user_id = ? order by id desc limit ?"
if err := mysql.Db.WithContext(model).Raw(sql, userId, pageSize*3).Find(&details).Error; err != nil {
return nil, myerr.WrapErr(err)
}
notInMap := make(map[int]bool)
for _, v := range optList {
notInMap[v] = true
}
for _, v := range details {
if _, ok := notInMap[int(v.OperateType)]; !ok {
diamondAccountDetails = append(diamondAccountDetails, v)
}
}
if len(diamondAccountDetails) > pageSize {
diamondAccountDetails = diamondAccountDetails[:pageSize]
}
}
// 非首页,或者首页没取满 pageSize 条
if offset > 0 || (len(details) == pageSize*3 && len(diamondAccountDetails) < pageSize) {
diamondAccountDetails = make([]*diamond_m.DiamondAccountDetail, 0)
sql := "select * from diamond_account_detail where user_id = ? and operate_type not in (?) order by id desc limit ?,?"
if err := mysql.Db.WithContext(model).Raw(sql, userId, optList, offset, pageSize).
Find(&diamondAccountDetails).Error; err != nil {
return nil, myerr.WrapErr(err)
}
}
//if err := mysql.Db.Table("diamond_account_detail FORCE INDEX(Index_1)").
// Where("user_id = ? AND operate_type not in (?)", userId,
// []int{int(diamond_m2.BuyDiamond), int(diamond_m2.DealerTransfer), int(diamond_m2.Checkout), int(diamond_m2.PayerMax)}).
// Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
// return nil, myerr.WrapErr(err)
//}
cvDiamondDetails := []*CvDiamondDetail{}
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
//粉钻流水,包含充值
func GetPinkDiamondDetailList(userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
var diamondAccountDetails []diamond_m.DiamondPinkAccountDetail
if err := mysql.Db.Model(&diamond_m.DiamondPinkAccountDetail{}).
Where("user_id = ?", userId).
Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var cvDiamondDetails []*CvDiamondDetail
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
......@@ -123,6 +123,13 @@ type MemberDetail struct {
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
......@@ -138,7 +145,7 @@ type GroupDetail struct {
MsgStatus uint8 `json:"msgStatus"` // 消息提醒状态
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
TotalConsume uint64 `json:"totalConsume"` // 群内消费总额
TopConsumers []billboard_cv.BillboardUserInfo `json:"topConsumers"` // 月最高消费三甲
TopConsumers []billboard_cv.GroupTop3ConsumeUser `json:"topConsumers"` // 月最高消费三甲
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏的数字点数
// "AppDefinedData": 群组维度的自定义字段 【暂时不用】
......@@ -154,6 +161,7 @@ type SimpleRoleInfo struct {
type BannerElement struct {
H5Url string `json:"h5Url"` // h5链接
BannerUrl string `json:"bannerUrl"` // 图片地址
ActionUrl string `json:"actionUrl"` // 统跳地址
}
type RoomInfo struct {
......@@ -175,7 +183,10 @@ type RoomInfo struct {
LuckyWheel LuckyWheelState `json:"luckyWheel"`
TotalConsume uint64 `json:"totalConsume"`
GameConfig *game_m.GameConfig `json:"gameConfig"`
Owner *user_cv.CvUserDetail `json:"owner"`
Owner *user_cv.RoomInfoOwner `json:"owner"`
EntryEffectType int `json:"entryEffectType"` // 进场特效类型 1: CP 2:神秘人 3:贵族 4:vip
CpUserAvatar string `json:"cpUserAvatar"` // cp对象头像
CpLevel int `json:"cpLevel"` // cp等级
}
type SupportPageDetail struct {
......@@ -221,6 +232,7 @@ type GroupChannelId struct {
Token string `json:"token"`
AgoraId uint32 `json:"agoraId"`
MicNumType uint8 `json:"micNumType"`
Provider uint8 `json:"provider"` // 供应商 1.声网 2.腾讯trtc
}
//国籍视图
......@@ -239,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)
......@@ -298,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 {
......@@ -356,6 +379,15 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [
}
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)
......@@ -366,14 +398,6 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [
}
}
}
// 补上房间流水勋章
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})
}
var password *string = nil
if len(g.Password) > 0 && g.Owner != myUserId {
......@@ -421,40 +445,220 @@ 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
}
......@@ -522,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 {
......@@ -574,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],
......@@ -585,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],
......
......@@ -40,10 +40,20 @@ type CvGroupPowerRank struct {
Items []CvGroupPowerRankData `json:"items"` // 列表
}
// 家族月度排行活动榜单
type CvGroupPowerRankMontAct struct {
MyGroupPower *CvGroupPowerRankData `json:"myGroupPower"` // 我的家族排名
Items []CvGroupPowerRankData `json:"items"` // 列表
MyGroupPowerLast *CvGroupPowerRankData `json:"myGroupPowerLast"` // 我的家族排名(上月)
ItemsLast []CvGroupPowerRankData `json:"itemsLast"` // 列表(上月)
LeftSecond int64 `json:"leftSecond"` // 活动倒计时
}
type CvGroupPowerRankData struct {
CvGroupPowerBase `json:",inline"`
CvGroupPowerGrade `json:",inline"`
Rank int `json:"rank"` // 排名
StarList []*CvGroupPowerStarData `json:"starList"` // 家族贡献top10
}
// 家族之星
......@@ -108,6 +118,6 @@ var GroupPowerGradePrivilegeNum = map[groupPower_e.GroupPowerGrade][]CvPrivilege
{groupPower_e.GroupPowerPrivilegeNameplate, 1, "https://image.whoisamy.shop/hilo/resource/family/nameplate_yellow.png"},
{groupPower_e.GroupPowerPrivilegeMedal, 1, "https://image.whoisamy.shop/hilo/resource/family/privilege_yellow.png"},
{groupPower_e.GroupPowerPrivilegeNameplateEdit, 1, "https://image.whoisamy.shop/hilo/resource/family/edit_yellow.png"},
{groupPower_e.GroupPowerPrivilegeNameplateHeadwear, 1,"https://image.whoisamy.shop/hilo/resource/family/headwear_yellow.png"},
{groupPower_e.GroupPowerPrivilegeNameplateHeadwear, 1, "https://image.whoisamy.shop/hilo/resource/family/headwear_yellow.png"},
},
}
package user_cv
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
......@@ -69,6 +70,25 @@ type CvUserDetail struct {
CountryManager *country_cv.CVCountryManager `json:"countryManager,omitempty"` // 国家管理员
}
type RoomInfoOwner struct {
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号
//是否VIP用户
IsVip bool `json:"isVip"`
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
Medals []uint32 `json:"medals"` // 勋章列表
Noble noble_cv.CvNoble `json:"noble"` // 当前的
WealthUserGrade uint32 `json:"wealthUserGrade"` //财富等级
CharmUserGrade uint32 `json:"charmUserGrade"` //魅力等级
MyGroupPowerName string `json:"myGroupPowerName"` // 当前用户所在势力绑定群组的名称
GroupPower GroupPower `json:"groupPower"` // 当前用户势力信息
}
type GroupPower struct {
Id uint64 `json:"id"` // 群主所在的势力ID
Icon string `json:"icon"` // 家族头像
......@@ -150,6 +170,45 @@ type CvUserExtend struct {
ActiveGrade uint32 `json:"activityUserGrade"`
}
type CvGroupMember struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//是否默认头像 true:是 false:不是
DefaultAvatar *bool `json:"defaultAvatar"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
//签名,不存在为nil
Description *string `json:"description"`
Birthday *uint64 `json:"birthday"`
//邀请码
Code *string `json:"code"`
//国家,不存在为nil
Country *string `json:"country"`
//国旗图标,不存在为nil
CountryIcon *string `json:"countryIcon"`
Sex *uint8 `json:"sex"`
//是否代理管理员, 只有自己查自己的时候才有值,其他情况为nil
IsAgentMgr *bool `json:"isAgentMgr"`
//是否展示年龄, 是本人才有数据,看其他用户均为nil
IsShowAge *uint8 `json:"isShowAge"`
//是否工会成员, 只有是自己查自己,这个才有值,其它全为nil, 20220329 数据开放:原因:产品1对1视频聊天中,公会用户视频需要送礼物。改为: 全部人可以知道是否是公会用户。
IsTradeUnion *bool `json:"isTradeUnion"`
//工会成员,是否开启了,匹配通知,只有 isTradeUnion值为true,这里才有值,
IsTradeUnionMatchNotification *bool `json:"isTradeUnionMatchNotification"`
//是否VIP用户
IsVip bool `json:"isVip"`
Ride property_cv.CvProperty `json:"ride"` // 当前使用的座驾
Noble noble_cv.CvNoble `json:"noble"` // 当前的
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
WealthGrade uint32 `json:"wealthUserGrade"`
CharmGrade uint32 `json:"charmUserGrade"`
ActiveGrade uint32 `json:"activityUserGrade"`
}
// 批量获取用户tiny信息
func GetUserTinyMap(userIds []mysql.ID) (map[mysql.ID]CvUserTiny, error) {
userTinys, _, err := GetUserTinys(userIds)
......@@ -849,17 +908,123 @@ 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 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{
CvUserBase: CvUserBase{
......@@ -1288,3 +1453,38 @@ func getMedalInfo(db *gorm.DB, medals []uint32) ([]uint32, []medal_cv.CvMedal, e
}
return validMedals, medalInfo, nil
}
func UserDetailToRoomInfoOwner(user *CvUserDetail) *RoomInfoOwner {
return &RoomInfoOwner{
Avatar: user.Avatar,
ExternalId: user.ExternalId,
Nick: user.Nick,
IsPrettyCode: user.IsPrettyCode,
IsVip: user.IsVip,
Svip: user.Svip,
Medals: user.Medals,
Noble: user.Noble,
WealthUserGrade: user.WealthUserGrade,
CharmUserGrade: user.CharmUserGrade,
MyGroupPowerName: user.MyGroupPowerName,
GroupPower: user.GroupPower,
}
}
type TopConsumersUser struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
}
func CvUserExtendToCvGroupMember(detail CvUserExtend) CvGroupMember {
jData, _ := json.Marshal(detail)
res := CvGroupMember{}
_ = json.Unmarshal(jData, &res)
return res
}
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT]
SECRET=hilo1632
ISSUER_API=hiloApi
......@@ -72,6 +74,9 @@ APP_CERTIFICATE=ff29c100a613433db82324e8411eabc8
CUSTOMER_KEY=6b132c0ff7164560a2bc53fda06ea85a
CUSTOMER_SECRET=eedad2cd16d24834990d5450ace9f1ce
CALLBACK_SECRET=n_ZizS_N8
[TRTC]
APP_ID=1400548270
APP_CERTIFICATE=321bd60f73096b059c7350f1cd97d51028850b34fa58c5c0d26bb4a19e783de8
[CHECKOUT]
AUTHORIZATION=sk_test_9b5e771c-5a3f-4a8d-a4da-31b19bd43d83
URL=https://api.sandbox.checkout.com/hosted-payments
......@@ -114,6 +119,8 @@ NOBLE_BUY_IOS=https://h5.whoisamy.shop/action/hiloHtml/22_05_26_buy_nobility/pag
GUILD_DATA_URL=https://test.chathot.me/action/hiloHtml/22_10_18_app_data_coins/index.html
MGR_GUILD_DATA_URL=https://test.chathot.me/action/hiloHtml/22_10_18_app_data_coins/union.html
RANKING_PINK_DIAMOND_URL=https://test.chathot.me/action/activitiesPage/2022_10_17HiloLiveH5/index.html
AGENT_SHARE_URL=https://test.chathot.me/action/hiloHtml/22_05_30_recharge/topup.html?external_id=
AGENT_SHARE_ICON=https://image.whoisamy.shop/hilo/resource/user_transfer1.png
[GROUPIM]
MSG_SORT_EXPIRE=21600
MSG_SORT_SNAP=300
......
......@@ -13,11 +13,14 @@ type gameAutoJoinMsg struct {
Token string
EnterType string
GameCode string
Is1V1 string
GameMode string
Is1V1Robot string
}
func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode string) error {
func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode, is1V1, gameMode, is1V1Robot string) error {
key := game_e.GetAutoMathEnterRoom(userId, imGroupId)
info := gameAutoJoinMsg{traceId, token, enterType, gameCode}
info := gameAutoJoinMsg{traceId, token, enterType, gameCode, is1V1, gameMode, is1V1Robot}
data, err := json.Marshal(info)
if err != nil {
return err
......@@ -26,7 +29,7 @@ func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, g
if err != nil {
return err
}
redisCli.GetRedis().Expire(context.Background(), key, time.Second*3)
redisCli.GetRedis().Expire(context.Background(), key, time.Second*10)
return nil
}
......
package gift_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/domain/event/gift_ev"
"time"
)
const EventSendGiftHiloGroupQueue = "send:gift:queue:hilo_group"
// redis pop event sendGift
func BLPopQueueSendGift(model *domain.Model) *gift_ev.SendGiftEvent {
var res *gift_ev.SendGiftEvent
queue := EventSendGiftHiloGroupQueue
strs, err := model.RedisCluster.BLPop(model, time.Second, queue).Result()
if err != nil {
if err != redis.Nil {
model.Log.Errorf("BLPopQueueSendGift fail:%v", err)
}
return nil
}
if len(strs) >= 2 {
content := strs[1]
res = new(gift_ev.SendGiftEvent)
if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopQueueSendGift json fail:%v", err)
return nil
}
return res
}
return nil
}
package groupPower_c
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/go-redis/redis/v8"
"github.com/jinzhu/now"
"github.com/pkg/errors"
"github.com/spf13/cast"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/groupPower_k"
"time"
)
// 家族之星-排名
type GroupPowerStarRank struct {
Period string
GroupPowerId mysql.ID
UserId mysql.ID
Type groupPower_e.GroupPowerStarType
Score mysql.Num
}
// 增加家族之星分数
func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num) error {
ttl := map[string]time.Duration{
"day": time.Hour * 24 * 7,
"week": time.Hour * 24 * 7 * 30,
"month": time.Hour * 24 * 7 * 30 * 2,
}
for _, period := range []string{"day", "week", "month"} {
date := ""
switch period {
case "day":
date = time.Now().Format("2006-01-02")
case "week":
date = now.BeginningOfWeek().Format("2006-01-02")
case "month":
date = now.BeginningOfMonth().Format("2006-01-02")
}
key := groupPower_k.GetGroupPowerStarRankKey(_type, period, groupPowerId, date)
model.RedisCluster.ZIncrBy(model, key, float64(score), fmt.Sprintf("%d", userId))
model.RedisCluster.Expire(model, key, ttl[period])
}
return nil
}
// 获取家族之星排行
// param period: day|week|month
func GetGroupPowerStarRankPeriod(model *domain.Model, period string, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, targetDate ...string) ([]*GroupPowerStarRank, error) {
var res []*GroupPowerStarRank
date := ""
switch period {
case "day":
date = time.Now().Format("2006-01-02")
case "week":
date = now.BeginningOfWeek().Format("2006-01-02")
case "month":
date = now.BeginningOfMonth().Format("2006-01-02")
}
if len(date) <= 0 {
return res, errors.New("illegal date")
}
if len(targetDate) > 0 {
date = targetDate[0]
}
key := groupPower_k.GetGroupPowerStarRankKey(_type, period, groupPowerId, date)
rows, err := model.RedisCluster.ZRevRangeByScoreWithScores(model, key, &redis.ZRangeBy{
Min: "-inf",
Max: "+inf",
Offset: int64(offset),
Count: int64(limit),
}).Result()
if err != nil {
model.Log.Errorf("GetGroupPowerStarRankPeriod fail:%v", err)
return res, err
}
for _, v := range rows {
res = append(res, &GroupPowerStarRank{
Period: period,
GroupPowerId: groupPowerId,
UserId: cast.ToUint64(v.Member),
Type: _type,
Score: mysql.Num(v.Score),
})
}
return res, nil
}
// 获取家族之星三个排行榜的各自第一名
func GetGroupPowerMonthStartTop1(model *domain.Model, groupPowerId mysql.ID) ([]*GroupPowerStarRank, error) {
var res []*GroupPowerStarRank
r1, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeFamous, 0, 1)
if err != nil {
return res, err
}
r2, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeActive, 0, 1)
if err != nil {
return res, err
}
r3, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeCharm, 0, 1)
if err != nil {
return res, err
}
res = append(res, r1...)
res = append(res, r2...)
res = append(res, r3...)
return res, nil
}
package group_c
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key/group_k"
"strconv"
"time"
)
// 用户进房
func ZAddUserEnterRoom(model *domain.Model, userId uint64, imGroupId string) {
userKey := group_k.GetUserEnterRoomUserKey(userId)
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
if err := model.Redis.ZAdd(model, userKey, &redis.Z{
Score: float64(time.Now().Unix()),
Member: imGroupId,
}).Err(); err != nil {
model.Log.Errorf("ZAddUserEnterRoom user fail:%v", err)
}
if err := model.Redis.ZAdd(model, groupKey, &redis.Z{
Score: float64(time.Now().Unix()),
Member: userId,
}).Err(); err != nil {
model.Log.Errorf("ZAddUserEnterRoom room fail:%v", err)
}
}
// 获取最近房间访客
// 15天
func GetLastRoomVisitors(model *domain.Model, imGroupId string) (userIds []uint64) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
res, err := model.Redis.ZRangeByScore(model, groupKey, &redis.ZRangeBy{
Min: fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix()),
Max: "+inf",
}).Result()
if err != nil {
return
}
for _, u := range res {
uid, _ := strconv.ParseUint(u, 10, 64)
if uid > 0 {
userIds = append(userIds, uid)
}
}
return
}
// 获取最近进入的房间
// 3个月
func GetUserRecentRooms(model *domain.Model, userId uint64, offset, limit int64) (imGroupIds []string, roomEnterTime map[string]int64) {
roomEnterTime = make(map[string]int64)
userKey := group_k.GetUserEnterRoomUserKey(userId)
res, err := model.Redis.ZRevRangeByScoreWithScores(model, userKey, &redis.ZRangeBy{
Min: fmt.Sprintf("%d", time.Now().AddDate(0, -3, 0).Unix()),
Max: "+inf",
Offset: offset,
Count: limit,
}).Result()
if err != nil {
return
}
for _, v := range res {
imGroupId := cast.ToString(v.Member)
imGroupIds = append(imGroupIds, imGroupId)
roomEnterTime[imGroupId] = int64(v.Score)
}
return
}
// 清理房间访客
// 15天前访问的
func RemoveRoomVisitors(model *domain.Model, imGroupId string) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
n, err := model.Redis.ZRemRangeByScore(model, groupKey, "-inf", fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix())).Result()
if err != nil {
model.Log.Errorf("RemoveRoomVisitors fail:%v", err)
} else {
model.Log.Infof("RemoveRoomVisitors key:%v,n:%v", groupKey, n)
}
}
......@@ -14,6 +14,10 @@ import (
"time"
)
func init() {
group_m.FuncAddEditGroupCd = AddEditGroupCd
}
func GetGroupMemberCount(groupId string) (int, error) {
key := redis_key.GetGroupMemCountKey(groupId)
return redisCli.RedisClient.Get(context.Background(), key).Int()
......@@ -79,17 +83,17 @@ func SetGroupMemberTTL(groupId string, ttl time.Duration) (bool, error) {
func GetGroupConsume(groupId string) (uint64, error) {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Get(context.Background(), key).Uint64()
return redisCli.RedisClusterClient.Get(context.Background(), key).Uint64()
}
func SetGroupConsume(groupId string, consume uint64, ttl time.Duration) error {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Set(context.Background(), key, consume, ttl).Err()
return redisCli.RedisClusterClient.Set(context.Background(), key, consume, ttl).Err()
}
func ClearGroupConsume(groupId string) error {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Del(context.Background(), key).Err()
return redisCli.RedisClusterClient.Del(context.Background(), key).Err()
}
// 增加编辑用户cd
......
package mic_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/mic_ev"
"time"
)
// redis queue on mic
func QueueOnMic(model *domain.Model, onMic *mic_ev.OnMicEvent) error {
queue := mic_k.GetOnMicQueue()
onMic.Ts = time.Now().UnixNano() // 给一个时间戳
body, _ := json.Marshal(onMic)
return model.RedisCluster.RPush(model, queue, string(body)).Err()
}
// redis pop on mic
func BLPopQueueOnMic(model *domain.Model) *mic_ev.OnMicEvent {
var res *mic_ev.OnMicEvent
queue := mic_k.GetOnMicQueue()
strs, err := model.RedisCluster.BLPop(model, time.Second, queue).Result()
if err != nil {
if err != redis.Nil {
model.Log.Errorf("BLPopQueueOnMic fail:%v", err)
}
return nil
}
if len(strs) >= 2 {
content := strs[1]
res = new(mic_ev.OnMicEvent)
if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopQueueOnMic json fail:%v", err)
return nil
}
return res
}
return nil
}
......@@ -27,17 +27,17 @@ func SetJSON(model *domain.Model, key string, obj interface{}) (err error) {
if err != nil {
return err
}
return model.Redis.Set(model.Context, key, value, DEFAULT_TTL).Err()
return model.RedisCluster.Set(model.Context, key, value, DEFAULT_TTL).Err()
}
// 获取redis中json结构体
// return err: may redisV8.Nil
func GetJSON(model *domain.Model, key string, obj interface{}) (err error) {
var value []byte
defer func() {
model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err)
}()
value, err = model.Redis.Get(model.Context, key).Bytes()
//defer func() {
// model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err)
//}()
value, err = model.RedisCluster.Get(model.Context, key).Bytes()
if err != nil {
// may redisV2.Nil
return
......@@ -59,7 +59,7 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
if time.Now().After(deadline) {
return false
}
flag, err := model.Redis.SetNX(model, key, "1", expireTimeout).Result()
flag, err := model.RedisCluster.SetNX(model, key, "1", expireTimeout).Result()
if err != nil || !flag {
time.Sleep(time.Millisecond * 10)
} else {
......@@ -70,5 +70,5 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
// 解锁
func UnLock(model *domain.Model, key string) {
model.Redis.Del(model, key)
model.RedisCluster.Del(model, key)
}
package res_c
import (
"context"
"git.hilo.cn/hilo-common/domain"
"hilo-group/_const/redis_key"
"github.com/bluele/gcache"
"hilo-group/domain/model/res_m"
"time"
)
// 统一改成lru
var countryIconLru = gcache.New(1000).LRU().Build()
var countryIconKey = "country:icon"
var countryAreaLru = gcache.New(1000).LRU().Build()
var countryAreaKey = "country:area"
func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
m, err := GetAllCountryIcon(model)
if err != nil || len(m) <= 0 {
......@@ -24,15 +30,54 @@ func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
}
func GetAllCountryIcon(model *domain.Model) (map[string]string, error) {
key := redis_key.GetCountryIconKey()
return model.Redis.HGetAll(context.Background(), key).Result()
//key := redis_key.GetCountryIconKey()
if data, err := countryIconLru.Get(countryIconKey); err == nil {
return data.(map[string]string), nil
}
//return model.Redis.HGetAll(context.Background(), key).Result()
return map[string]string{}, nil
}
func SaveAllCountryIcon(model *domain.Model, icons map[string]string) {
//key := redis_key.GetCountryIconKey()
//ret, err := model.Redis.HSet(context.Background(), key, icons).Result()
//if err == nil {
// model.Redis.Expire(context.Background(), key, time.Minute*10)
//}
//return ret, err
_ = countryIconLru.SetWithExpire(countryIconKey, icons, time.Minute*10)
}
func GetCountryAreaMap(model *domain.Model) (map[string]string, error) {
m, err := GetAllCountryArea(model)
if err != nil || len(m) <= 0 {
m, err = res_m.GetAllCountriesArea(model)
if err != nil {
return nil, err
}
if len(m) <= 0 {
return map[string]string{}, nil
}
SaveAllCountryArea(model, m)
}
return m, nil
}
func SaveAllCountryIcon(model *domain.Model, icons map[string]string) (int64, error) {
key := redis_key.GetCountryIconKey()
ret, err := model.Redis.HSet(context.Background(), key, icons).Result()
if err == nil {
model.Redis.Expire(context.Background(), key, time.Minute*10)
func GetAllCountryArea(model *domain.Model) (map[string]string, error) {
//key := redis_key.GetCountryAreaKey()
//return model.Redis.HGetAll(context.Background(), key).Result()
if data, err := countryAreaLru.Get(countryAreaKey); err == nil {
return data.(map[string]string), nil
}
return ret, err
return map[string]string{}, nil
}
func SaveAllCountryArea(model *domain.Model, data map[string]string) {
//key := redis_key.GetCountryAreaKey()
//ret, err := model.Redis.HSet(context.Background(), key, data).Result()
//if err == nil {
// model.Redis.Expire(context.Background(), key, time.Minute*10)
//}
//return ret, err
_ = countryAreaLru.SetWithExpire(countryAreaKey, data, time.Minute*10)
}
......@@ -2,42 +2,44 @@ package room_c
import (
"context"
"errors"
"fmt"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli"
"github.com/bluele/gcache"
redis2 "github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key"
"strconv"
"hilo-group/_const/redis_key/group_k"
"time"
)
// 处理访问房间的相关缓存
func ProcessRoomVisit(groupId string, userId uint64) error {
key := redis_key.GetPrefixGroupInUserDuration(groupId)
now := time.Now()
ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
Score: float64(now.Unix()),
Member: userId,
}).Result()
if err != nil {
return err
}
mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret)
// 每群定时清一次数据可以了
if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL))
if err == nil {
mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc)
} else {
mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error())
}
}
//key := redis_key.GetPrefixGroupInUserDuration(groupId)
//now := time.Now()
//ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
// Score: float64(now.Unix()),
// Member: userId,
//}).Result()
//if err != nil {
// return err
//}
//mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret)
//
//// 每群定时清一次数据可以了
//if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
// rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL))
// if err == nil {
// mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc)
// } else {
// mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error())
// }
//}
// 马上更新roomVisitCount
if _, err := GetSetRoomVisitCount(groupId); err != nil {
mylogrus.MyLog.Warnf("ProcessRoomVisit, failed for key %s, err: %s", key, err.Error())
mylogrus.MyLog.Errorf("ProcessRoomVisit, failed for groupId %s, err: %s", groupId, err.Error())
}
return nil
......@@ -59,15 +61,17 @@ func ProcessUserRoomVisit(userId uint64, groupId string) error {
}
// 查询用户访问过的房间及其时间
// todo 去掉查询,redis性能
func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
result := make(map[string]int64, 0)
return result, nil
key := redis_key.GetUserEnterRoomKey(userId)
ret, err := redisCli.GetRedis().ZRangeWithScores(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, err
}
mylogrus.MyLog.Infof("GetUserRoomVisit, ZRangeWithScores %s, return %v", key, ret)
//mylogrus.MyLog.Infof("GetUserRoomVisit, ZRangeWithScores %s, return %v", key, ret)
result := make(map[string]int64, 0)
for _, i := range ret {
result[i.Member.(string)] = int64(i.Score)
}
......@@ -75,53 +79,63 @@ func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
}
// 批量获取房间访问人数
// 带上lru
var roomVisitCountLru = gcache.New(100).LRU().Build()
func MGetRoomVisitCount(groupIds []string) (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
visit := make(map[string]string)
if len(groupIds) <= 0 {
return visit, nil
}
res, err := redisCli.GetRedis().HMGet(context.Background(), key, groupIds...).Result()
if err != nil {
return visit, err
lKey := "room:visit:count"
if data, err := roomVisitCountLru.Get(lKey); err == nil {
return data.(map[string]string), nil
}
if len(res) != len(groupIds) {
return visit, errors.New(fmt.Sprintf("MGetRoomVisitCount fail,miss match len,%v-%v", len(res), len(groupIds)))
// 用redisCluster中的zset代替,只是取出大于10的
zKey := redis_key.GetPrefixRoomVisitCountZset()
cnt := 10
if !config.AppIsRelease() {
cnt = 0
}
for i, groupId := range groupIds {
if cnt, ok := res[i].(string); ok {
visit[groupId] = cnt
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
}
for _, v := range zRes {
visit[cast.ToString(v.Member)] = cast.ToString(v.Score)
}
_ = roomVisitCountLru.SetWithExpire(lKey, visit, time.Minute*15)
return visit, nil
}
func GetSetRoomVisitCount(groupId string) (int64, error) {
key := redis_key.GetPrefixGroupInUserDuration(groupId)
//key := redis_key.GetPrefixGroupInUserDuration(groupId)
key := group_k.GetUserEnterRoomGroupKey(groupId)
vc, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
// 查到合法值后,更新二级缓存
if err == nil && vc >= 0 {
ret, err := saveRoomVisitCount(groupId, vc)
mylogrus.MyLog.Infof("saveRoomVisitCount %s, ret = %d, err: %v", groupId, ret, err)
if err := saveRoomVisitCount(groupId, vc); err != nil {
mylogrus.MyLog.Errorf("saveRoomVisitCount %s, err: %v", groupId, err)
}
}
return vc, err
}
func saveRoomVisitCount(groupId string, count int64) (int64, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result()
}
func clearRoomVisit(groupId string, t time.Time) (int64, error) {
value := strconv.FormatInt(t.Unix(), 10)
ret, err := redisCli.GetRedis().ZRemRangeByScore(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId), "0", value).Result()
if err != nil {
return 0, err
func saveRoomVisitCount(groupId string, count int64) error {
//key := redis_key.GetPrefixRoomVisitCount()
zKey := redis_key.GetPrefixRoomVisitCountZset()
// zset同步存一份到redis集群
if err := redisCli.GetClusterRedis().ZAdd(context.Background(), zKey, &redis2.Z{
Score: float64(count),
Member: groupId,
}).Err(); err != nil {
mylogrus.MyLog.Errorf("GetPrefixRoomVisitCountZset fail %s", err.Error())
return err
}
return ret, nil
}
func GetAllRoomVisitCount() (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HGetAll(context.Background(), key).Result()
return nil
//return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result()
}
package user_c
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"sync"
"time"
)
type UserLevel struct {
UserId mysql.ID
Level int
}
var svipVipNobleLock sync.RWMutex
var svipLevel = make(map[mysql.ID]int) // userId->svipLevel
var nobleLevel = make(map[mysql.ID]uint16) // userId->nobleLevel
var userVips = make(map[mysql.ID]bool) // userId->isVip
// 加载数据到lru
func LoadAllSvipVipNoble(model *domain.Model) {
start := time.Now()
var svips []UserLevel
svipMap := make(map[mysql.ID]int)
if err := model.DB().Table("user_svip").Select("user_id,level").Where("level > 0").Find(&svips).Error; err != nil {
model.Log.Errorf("LoadAllSvip fail:%v", err)
} else {
for _, v := range svips {
svipMap[v.UserId] = v.Level
}
}
var nobles []UserLevel
nobleMap := make(map[mysql.ID]uint16)
if err := model.DB().Table("user_noble").Select("user_id,MAX(level) level").
Where("level > 0 AND end_time > ?", time.Now()).Group("user_id").Find(&nobles).Error; err != nil {
model.Log.Errorf("LoadAllNoble fail:%v", err)
} else {
for _, v := range nobles {
nobleMap[v.UserId] = uint16(v.Level)
}
}
var vips []UserLevel
vipMap := make(map[mysql.ID]bool)
if err := model.DB().Table("user_vip").Select("user_id").
Where("expire_at > ?", time.Now()).Find(&vips).Error; err != nil {
model.Log.Errorf("LoadAllVip fail:%v", err)
} else {
for _, v := range vips {
vipMap[v.UserId] = true
}
}
// 上锁赋值
svipVipNobleLock.Lock()
svipLevel = svipMap
nobleLevel = nobleMap
userVips = vipMap
svipVipNobleLock.Unlock()
model.Log.Infof("LoadAllSvipVipNoble svip:%v,vip:%v,noble:%v,cost:%vs", len(svipMap), len(vipMap), len(nobleMap), time.Now().Sub(start).Seconds())
}
func BatchGetNobleLevel(model *domain.Model, userIds []uint64) map[uint64]uint16 {
res := make(map[uint64]uint16)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
res[userId] = nobleLevel[userId]
}
return res
}
func MGetUserSvipLevel(model *domain.Model, userIds []uint64) map[uint64]int {
res := make(map[uint64]int)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
res[userId] = svipLevel[userId]
}
return res
}
func BatchGetVips(model *domain.Model, userIds []uint64) map[uint64]*int64 {
res := make(map[uint64]*int64)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
vip := int64(1)
if userVips[userId] {
res[userId] = &vip
}
}
return res
}
......@@ -38,6 +38,36 @@ func GetUserTinyById(model *domain.Model, userId mysql.ID) (*user_m.UserTiny, er
return userTiny, nil
}
// 获取用户简要信息
// param userId 用户id
func MGetUserTinyById(model *domain.Model, userIds []mysql.ID) []*user_m.UserTiny {
var users []*user_m.UserTiny
for _, userId := range userIds {
if user, _ := GetUserTinyById(model, userId); user != nil {
users = append(users, user)
}
}
return users
}
// 获取用户externalIds
// return []externalIds map[userId]extId map[userId]code
func GetUserExternalIds(model *domain.Model, userIds []mysql.ID) ([]string, map[uint64]string, map[uint64]string) {
var res []string
var m = make(map[uint64]string)
var c = make(map[uint64]string)
if len(userIds) <= 0 {
return res, m, c
}
users := MGetUserTinyById(model, userIds)
for _, u := range users {
res = append(res, u.ExternalId)
m[u.ID] = u.ExternalId
c[u.ID] = u.Code
}
return res, m, c
}
// 获取用户简要信息By ExternalId
func GetUserByExternalId(model *domain.Model, externalId mysql.Str) (*user_m.UserTiny, error) {
userId, err := ToUserId(model, externalId)
......@@ -52,7 +82,7 @@ func ToUserId(model *domain.Model, externalId mysql.Str) (mysql.ID, error) {
if externalId == "" {
return 0, myerr.NewSysError("externalId 不能为空")
}
userId, err := model.Redis.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64()
userId, err := model.RedisCluster.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64()
if err != nil && err != redisV8.Nil {
return 0, err
}
......@@ -75,7 +105,7 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) {
if code == "" {
return 0, myerr.NewSysError("code 不能为空")
}
userId, err := model.Redis.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64()
userId, err := model.RedisCluster.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64()
if err != nil && err != redisV8.Nil {
return 0, err
}
......@@ -104,11 +134,11 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error {
// return err
//}
// cache externalId->userId
if err := model.Redis.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
if err := model.RedisCluster.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err
}
// cache code->userId
if err := model.Redis.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
if err := model.RedisCluster.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err
}
if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil {
......
package group_ev
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
)
var txGroupInListen = new(domain.EventBase)
// 进房事件
type TxGroupInEvent struct {
GroupId string // imGroupId
UserId mysql.ID
ExternalId string
Nick string
Avatar string
IsMember bool //是否永久成员
IsVip bool
NobleLevel uint16
}
func AddTxGroupInEventSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(txGroupInListen, callback)
}
func AddTxGroupInEventAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(txGroupInListen, callback)
}
func PublishTxGroupInEvent(model *domain.Model, event interface{}) error {
return domain.PublishEvent(txGroupInListen, model, event)
}
......@@ -14,6 +14,8 @@ type OnMicEvent struct {
UserId uint64 // 麦中的人
Forbid bool // 静音 true:静音,false:没有静音
Timestamp int64 // 上麦的的时间戳
Ts int64
}
func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) {
......
package common
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/utils"
"hilo-group/_const/redis_key"
"hilo-group/myerr"
"github.com/bluele/gcache"
"time"
)
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
bData, err := GetCache(redis_key.GetUserMedalMerge(userId))
if err != nil {
return nil, myerr.WrapErr(err)
}
// 改成lru
var userMedalMergeLru = gcache.New(10000).LRU().Build()
res := make([]uint32, 0)
err = json.Unmarshal(bData, &res)
if err != nil {
return nil, myerr.WrapErr(err)
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
if data, err := userMedalMergeLru.Get(userId); err == nil {
return data.([]uint32), nil
}
return res, nil
return nil, nil
}
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) error {
err := SetCache(redis_key.GetUserMedalMerge(userId), data, time.Hour*2)
if err != nil {
mylogrus.MyLog.Errorf("SetUserMedalMerge err:%s", err)
return myerr.WrapErr(err)
}
return nil
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) {
_ = userMedalMergeLru.SetWithExpire(userId, data, time.Minute*15)
}
// 删除勋章缓存, 延迟删除
......@@ -44,41 +30,6 @@ func DelUserMedalMergeCacheDelay(userId mysql.ID) {
}()
}
func DelUserMedalMergeCache(userId mysql.ID) error {
err := DelCache(redis_key.GetUserMedalMerge(userId))
if err != nil {
mylogrus.MyLog.Errorf("DetUserMedalMerge err:%s, userId:%v", err, userId)
return myerr.WrapErr(err)
}
return nil
}
func DelCache(key string) error {
err := redisCli.GetRedis().Del(context.Background(), key).Err()
if err != nil {
mylogrus.MyLog.Errorf("DelCache key:%s, err:%s", key, err)
return err
}
return nil
}
func GetCache(key string) ([]byte, error) {
data, err := redisCli.GetRedis().Get(context.Background(), key).Bytes()
if err != nil {
return nil, err
}
return data, nil
}
func SetCache(key string, data interface{}, expire time.Duration) error {
jData, err := json.Marshal(data)
if err != nil {
return err
}
err = redisCli.GetRedis().Set(context.Background(), key, jData, expire).Err()
if err != nil {
mylogrus.MyLog.Errorf("SetCache key:%s, data:%v, err:%s", key, data, err)
return err
}
return nil
func DelUserMedalMergeCache(userId mysql.ID) {
userMedalMergeLru.Remove(userId)
}
package diamond_m
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
"strconv"
......@@ -40,6 +40,11 @@ type DiamondAccountDetail struct {
diamondAccount *DiamondAccount `gorm:"-"`
}
func (DiamondAccountDetail) TableName() string {
month := time.Now().Format("200601")
return fmt.Sprintf("diamond_account_detail_%s", month)
}
// 粉钻详情
type DiamondPinkAccountDetail struct {
mysql.Entity
......@@ -110,7 +115,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
var count int64
if diamondOperateSet.FrequencyDay == -1 {
if diamondOperateSet.FrequencyNum != -1 {
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{
diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId,
OperateType: operateType,
}).Count(&count)
......@@ -125,7 +130,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, myerr.WrapErr(err)
}
//一天的次数
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{
diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId,
OperateType: operateType,
}).Where("created_time >= ? ", beginTime).Count(&count)
......@@ -133,7 +138,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, bizerr.DiamondFrequency
}
//终极拦截,利用
diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from diamond_account_detail d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )")
diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from " + DiamondAccountDetail{}.TableName() + " d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )")
}
//-1,代表值无效,由参数给与
......@@ -197,7 +202,10 @@ func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional()
}
//持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
//if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err)
}
//改变diamondAccount值
......@@ -245,7 +253,10 @@ func (diamondAccountDetail *DiamondAccountDetail) Persistent() error {
}
//持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
//if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err)
}
//改变diamondAccount值
......
package event_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
)
// 进房事件消息
type EventGroupIn struct {
mysql.Entity
*domain.Model `gorm:"-"`
Proto mysql.Type
Payload []byte
Mark mysql.YesNo
MarkHiloGroup mysql.YesNo
}
func (EventGroupIn) TableName() string {
return "event_group_in"
}
// 偏移值
type EventGroupInOffsetHiloGroup struct {
mysql.Entity
*domain.Model `gorm:"-"`
MarkOffset mysql.ID
}
// 获取当前偏移值
func GroupOffset(model *domain.Model) (*EventGroupInOffsetHiloGroup, error) {
offset := new(EventGroupInOffsetHiloGroup)
if err := model.Db.WithContext(model).First(offset).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("Offset fail:%v", err)
return nil, err
}
// gorm.ErrRecordNotFound
}
offset.Model = model
return offset, nil
}
// 批量获取进房事件
func FetchEventGroupIn(model *domain.Model, limit int) ([]*EventGroupIn, *EventGroupInOffsetHiloGroup, error) {
offset, err := GroupOffset(model)
if err != nil {
return nil, nil, err
}
var events []*EventGroupIn
if err := model.Db.WithContext(model).Model(EventGroupIn{}).
Where("id > ?", offset.MarkOffset).
Order("id asc").Limit(limit).Find(&events).Error; err != nil {
model.Log.Errorf("FetchEventGroupIn fail:%v", err)
return nil, nil, err
}
return events, offset, nil
}
// 标记已完成
func (p *EventGroupIn) MarkDone() error {
p.MarkHiloGroup = mysql.YES
return p.Db.WithContext(p.Model).Model(EventGroupIn{}).Where("id = ?", p.ID).Update("mark_hilo_group", p.MarkHiloGroup).Limit(1).Error
}
......@@ -9,3 +9,7 @@ func (p *EventGiftSendOffsetHiloGroup) Persistence() error {
func (p *EventGiftSend) Persistence() error {
return model.Persistent(p.Db, p)
}
func (p *EventGroupInOffsetHiloGroup) Persistence() error {
return model.Persistent(p.Db, p)
}
\ No newline at end of file
......@@ -16,10 +16,11 @@ type EventGiftSend struct {
Payload []byte
Mark mysql.YesNo
MarkHiloGroup mysql.YesNo
MarkHiloUser mysql.YesNo
}
func (EventGiftSend) TableName() string {
return "event_gift_send2"
return "event_gift_send"
}
// 偏移值
......
......@@ -31,6 +31,7 @@ type GameInfo struct {
type GameConfig struct {
Ludo *GameConfigDiamond `json:"ludo"`
Uno *GameConfigDiamond `json:"uno"`
Domino *GameConfigDiamond `json:"domino"`
}
type GameConfigDiamond struct {
......
......@@ -127,6 +127,40 @@ func (g *GiftOperate) GetConsumeByRange(beginTime, endTime time.Time) (uint32, u
if len(rows) <= 0 {
return 0, 0, nil
}
//if beginTime.Unix() >= 1691337600 && beginTime.Unix() < 1691942400 { // 因为这周水果机被部分人刷币,所以这里做了特殊的处理
// reduceMap := map[string]uint64{
// "HTGS#a63226380": 20000000,
// //"HTGS#a42641278": 10000000,
// "@TGS#3ZZ5GZLHA": 27141539,
// "HTGS#a81630128": 8955410,
// "HTGS#a42300598": 50211301,
// "HTGS#a40088696": 10000000,
// "HTGS#a21700997": 14352310,
// "HTGS#a83608384": 49644203,
// "@TGS#33GDXTSIH": 50000000,
// "HTGS#a50538513": 15000000,
// "HTGS#a77282385": 15000000,
// "HTGS#a59437326": 10000000,
// "HTGS#a16909405": 10000000,
// "HTGS#a44104431": 16861206,
// "HTGS#a56794634": 59591313,
// "HTGS#a11286025": 31232311,
// "HTGS#a17238550": 52309338,
// "HTGS#a83592361": 79545067,
// "HTGS#a39882521": 10255093,
// }
// if reduceNum, ok := reduceMap[g.SceneUid]; ok {
// if g.Log != nil {
// g.Log.Infof("fruit diamond reduceMap,groupId:%v,reduceNum:%v", g.SceneUid, reduceNum)
// }
// if rows[0].Consume >= reduceNum {
// rows[0].Consume -= reduceNum
// } else {
// rows[0].Consume = 0
// }
// }
//}
return rows[0].C, rows[0].Consume, nil
}
......@@ -148,6 +182,17 @@ func (g *GiftOperate) BatchGetConsumeByRange(beginTime, endTime time.Time) ([]Sc
return rows, nil
}
func (g *GiftOperate) BatchGetSupportList(model *domain.Model, beginTime, endTime time.Time) ([]uint64, error) {
userIds := make([]uint64, 0)
err := model.DB().Model(g).
Select("DISTINCT(send_user_id) AS user_id").
Where(g).Where("created_time BETWEEN ? AND ?", beginTime, endTime).Pluck("user_id", &userIds).Error
if err != nil {
return nil, err
}
return userIds, nil
}
func SumSendGift(model *domain.Model, sendUserId mysql.ID, giftId mysql.ID) (uint32, error) {
type Result struct {
N uint32
......
......@@ -140,8 +140,8 @@ func UpdateFamily(model *domain.Model, familyId uint64, name, nameplate, declara
if groupPower.ModifyNameplate != mysql.YES {
// 同步修改铭牌
n := len([]rune(name))
if n > 6 {
n = 6
if n > groupPower_e.LongestNameplate {
n = groupPower_e.LongestNameplate
}
updateMap["nameplate"] = string([]rune(name[0:n]))
}
......
......@@ -43,6 +43,17 @@ type GroupPowerUser struct {
Role groupPower_e.GroupPowerUserRole
}
type ActFamilyMonthRankLog struct {
Id uint64 `json:"id"`
Period string `json:"period"`
FamilyId uint64 `json:"family_id"`
RankFamily int `json:"rank_family"`
RankUser int `json:"rank_user"`
UserId uint64 `json:"user_id"`
Award string `json:"award"`
Area int `json:"area"`
}
func (gpu *GroupPowerUser) Get(db *gorm.DB) ([]GroupPowerUser, error) {
rows := make([]GroupPowerUser, 0)
err := db.Where(gpu).Find(&rows).Error
......@@ -64,6 +75,22 @@ func GetPowerOwner(db *gorm.DB, powerId uint64) (uint64, error) {
return records[0].UserId, nil
}
func GetPowerOwnerMap(model *domain.Model, powerIds []uint64) (map[uint64]uint64, error) {
rows := make([]GroupPowerUser, 0)
if len(powerIds) > 0 {
if err := model.DB().Model(&GroupPowerUser{}).
Where("group_power_id IN ? and role = ?", powerIds, groupPower_e.GroupPowerUserRoleMgr).
Find(&rows).Error; err != nil {
return nil, err
}
}
result := make(map[uint64]uint64, 0)
for _, i := range rows {
result[i.GroupPowerId] = i.UserId
}
return result, nil
}
func GetMyPowerId(db *gorm.DB, userId uint64) (uint64, error) {
gpu := GroupPowerUser{UserId: userId, Role: groupPower_e.GroupPowerUserRoleMgr}
records, err := gpu.Get(db)
......@@ -707,3 +734,7 @@ func BatchGetGroupPowerUser(model *domain.Model, userIds []mysql.ID) (map[mysql.
}
return res, nil
}
func CreateActFamilyMonthRankLog(model *domain.Model, list []*ActFamilyMonthRankLog) error {
return model.DB().CreateInBatches(&list, 50).Error
}
......@@ -8,6 +8,7 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/group_power_ev"
"time"
)
......@@ -40,25 +41,6 @@ type GroupPowerExpDetail struct {
Remark string
}
type GroupPowerOnMic struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Seconds int64
LastCalTs int64
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
type GroupPowerOnMicDetail struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Minute int
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
// 增加家族经验
// 达到经验值之后升级
// 单进程同步执行,不考虑并发
......@@ -82,17 +64,34 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return err
}
// 增加家族经验-总
gpg := &GroupPowerGrade{
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().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 {
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)
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
}
numDetails := len(onMicDetails)
if numDetails >= MaxMinuteTimes {
// 上麦经验贡献值最多1800,1分钟100
model.Redis.Expire(model, key, time.Hour*24) // ttl 一天
// 每日最多1800经验 = 18个10分钟 = 180分钟
if minutes > 180 {
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
}
if minutes%10 == 0 {
return IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟")
}
return nil
})
}
// 增加势力上麦时长-家族之星
// 事务操作
func IncrGroupPowerStarOnMicMonth(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 月统计
star, err := GetGroupPowerMonthStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
month0Ts := now.BeginningOfMonth().Unix()
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨月
if curTs < month0Ts {
curTs = month0Ts
}
score := nowTs - curTs
err = IncrGroupPowerMonthStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
return err
})
}
// 增加势力上麦时长-家族之星
// 事务操作
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
})
}
// 清理所有家族的经验
......
......@@ -2,6 +2,7 @@ package groupPower_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/common"
"hilo-group/myerr"
......@@ -88,3 +89,16 @@ func DelGroupPowerApplyJoinNoDeal(model *domain.Model, userId uint64) error {
}
return nil
}
// 获取家族申请人数
// param: isAccept 0:未审核 1:通过 2:拒绝
func CountGroupPowerApply(model *domain.Model, groupPowerId mysql.ID, isAccept int) (int64, error) {
var cnt int64
if err := model.DB().Model(GroupPowerApplyJoin{}).
Where("group_power_id = ?", groupPowerId).
Where("is_accept = ?", isAccept).Count(&cnt).Error; err != nil {
model.Log.Errorf("CountGroupPowerApply fail:%v", err)
return cnt, err
}
return cnt, nil
}
......@@ -4,6 +4,7 @@ import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/_const/enum/groupPower_e"
)
type GroupPowerExpRank struct {
......@@ -14,10 +15,20 @@ type GroupPowerExpRank struct {
// 获取家族经验排行榜
// param limit: 排行榜人数
func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int) ([]GroupPowerExpRank, error) {
// 10166 线上员工,对应的势力不上榜,groupPowerId=8951
func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int, gpStatus groupPower_e.GroupPowerStatus, area int) ([]GroupPowerExpRank, error) {
var res []GroupPowerExpRank
if err := model.DB().Table("group_power_day_exp").Select("group_power_id,SUM(exp) as exp").
Where("date BETWEEN ? AND ?", beginDate, endDate).Group("group_power_id").Order("exp DESC").Limit(limit).Find(&res).Error; err != nil {
db := model.DB().Table("group_power_day_exp gpd").Select("gpd.group_power_id,SUM(gpd.exp) as exp").
Where("gpd.group_power_id <> 8951").
Where("gpd.date BETWEEN ? AND ?", beginDate, endDate)
if gpStatus > 0 {
db = db.Joins("left join group_power gp on gpd.group_power_id = gp.id").Where("gp.status = ?", gpStatus)
if area > 0 {
db = db.Joins("left join group_info gi on gp.group_uid = gi.im_group_id left join res_country rs on gi.country = rs.name").
Where("rs.area = ?", area)
}
}
if err := db.Group("gpd.group_power_id").Order("exp DESC").Limit(limit).Find(&res).Error; err != nil {
model.Log.Errorf("GetGroupPowerExpRank fail:%v", err)
return res, err
}
......
......@@ -35,6 +35,7 @@ type GroupPowerDayStar struct {
}
// 增加家族之星分数
// Deprecated: 用redis
func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
month := time.Now().Format("200601")
star := &GroupPowerMonthStar{
......@@ -59,6 +60,7 @@ func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysq
}
// 增加家族之星分数
// Deprecated: 用redis代替
func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
star := &GroupPowerDayStar{
Date: time.Now(),
......@@ -81,32 +83,11 @@ func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.
return nil
}
// 获取家族之星分数
// 允许返回gorm.ErrRecordNotFound
func GetGroupPowerDayStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerDayStar, error) {
res := new(GroupPowerDayStar)
date := time.Now()
if err := model.DB().Where("date = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", date.Format("2006-01-02"), groupPowerId, userId, _type).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 获取家族之星分数
// 允许返回gorm.ErrRecordNotFound
func GetGroupPowerMonthStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerMonthStar, error) {
res := new(GroupPowerMonthStar)
month := time.Now().Format("200601")
if err := model.DB().Where("month = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", month, groupPowerId, userId, _type).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 获取家族之星排行
func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int) ([]*GroupPowerMonthStar, error) {
// Deprecated: 用redis
func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*GroupPowerMonthStar, error) {
var res []*GroupPowerMonthStar
month := time.Now().Format("200601")
//month := time.Now().Format("200601")
if err := model.DB().Model(GroupPowerMonthStar{}).Where("month = ? AND group_power_id = ? AND `type` = ?", month, groupPowerId, _type).
Order("score desc").Offset(offset).Limit(limit).Find(&res).Error; err != nil {
model.Log.Errorf("GetGroupPowerMonthStarRank fail:%v", err)
......
......@@ -13,6 +13,7 @@ import (
"gorm.io/gorm"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/myerr"
"strconv"
"strings"
......@@ -242,6 +243,20 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if len(groupIds) <= 0 {
return result, nil
}
// 获取群组中上麦用户
for _, groupId := range groupIds {
groupMicUserKey := mic_k.GetGroupOnMicUser(groupId)
userIds, err := model.Redis.HVals(model, groupMicUserKey).Result()
if err != nil {
model.Log.Errorf("BatchGetAllMicUser fail:%v", err)
}
for _, userIdStr := range userIds {
if userId, _ := strconv.ParseUint(userIdStr, 10, 64); userId > 0 {
result[groupId] = append(result[groupId], userId)
}
}
}
return result, nil
keys := make([]string, 0)
for _, g := range groupIds {
......@@ -253,7 +268,7 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if err != nil {
return nil, err
}
model.Log.Infof("BatchGetAllMicUser redis return size = %d, mics: %v", len(mics), mics)
//model.Log.Infof("BatchGetAllMicUser redis return size = %d, mics: %v", len(mics), mics)
if len(mics) >= len(groupIds) {
for i, g := range groupIds {
......@@ -432,7 +447,7 @@ func GetMicUserByExternalId(model *domain.Model, externalId string) (*MicUser, e
//麦位上没人,返回nil
func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error) {
if i < 1 || i > 30 {
if i < 1 || i > MaxMicNum {
return nil, myerr.NewSysErrorF("麦序不对,不在范围值内 i:%v", i)
}
str, err := redisCli.GetRedis().Get(context.Background(), redis_key.GetPrefixGroupMicUser(groupUuid, i)).Result()
......@@ -455,6 +470,7 @@ func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error)
I: i,
ExternalId: micUser.ExternalId,
UserId: micUser.UserId,
CpUserId: micUser.CpUserId,
Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp,
}, nil
......
......@@ -3,6 +3,8 @@ package group_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"time"
)
type GroupBanned struct {
......@@ -24,12 +26,19 @@ func (banned *GroupBanned) Delete(model *domain.Model) error {
return model.Db.Where(banned).Delete(&GroupBanned{}).Error
}
var bannedGroupCache = gcache.New(100).LRU().Build()
func GetBannedGroups(model *domain.Model) ([]GroupBanned, error) {
key := "banned"
if data, err := bannedGroupCache.Get(key); err == nil {
return data.([]GroupBanned), nil
}
result := make([]GroupBanned, 0)
err := model.Db.Find(&result).Error
err := model.DB().Find(&result).Error
if err != nil {
return nil, err
}
bannedGroupCache.SetWithExpire(key, result, time.Minute*5)
return result, nil
}
......
package group_m
import "git.hilo.cn/hilo-common/domain"
// 获取游戏房
func GetGameGroupsMap(model *domain.Model) map[string]bool {
res := make(map[string]bool)
var rows []GroupInfo
if err := model.DB().Model(GroupInfo{}).Where("is_game_room = 1").Find(&rows).Error; err != nil {
model.Log.Errorf("GetGameGroupsMap fail:%v", err)
return res
}
for _, v := range rows {
res[v.ImGroupId] = true
}
return res
}
......@@ -7,6 +7,7 @@ import (
"git.hilo.cn/hilo-common/utils"
"github.com/bluele/gcache"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/enum/group_e"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
......@@ -46,6 +47,7 @@ type GroupInfo struct {
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
VisitCount int64 `gorm:"-"` // 热度
IsGameRoom uint8 // 是否1v1游戏房
}
func GenerateGroupCode(n uint16) string {
......@@ -566,3 +568,45 @@ func GetFamilyRooms(model *domain.Model, familyId uint64, pageSize, pageIndex in
return res, nextIdx, hasNext, nil
}
func IsUseTRTC(model *domain.Model, imGroupId string) bool {
var count int64
if err := model.DB().Table("group_trtc").Where("im_group_id=?", imGroupId).Count(&count).Error; err != nil {
model.Log.Errorf("IsUseTRTC err:%v, groupId:%s", err, imGroupId)
return false
}
return count > 0
}
type GroupTrtc struct {
mysql.Entity
ImGroupId mysql.Str
}
// 初始化trtc房间
func InitTRTC(model *domain.Model, imGroupId string) error {
if err := model.DB().Model(GroupTrtc{}).Clauses(clause.OnConflict{DoNothing: true}).Create(&GroupTrtc{ImGroupId: imGroupId}).Error; err != nil {
model.Log.Errorf("InitTRTC err:%v, groupId:%s", err, imGroupId)
return err
}
return nil
}
// 初始化trtc房间
func DeleteTRTC(model *domain.Model, imGroupId string) error {
model.Log.Infof("DeleteTRTC , groupId:%s", imGroupId)
if err := model.DB().Model(GroupTrtc{}).Where("im_group_id = ?", imGroupId).Delete(&GroupTrtc{}).Error; err != nil {
model.Log.Errorf("DeleteTRTC err:%v, groupId:%s", err, imGroupId)
return err
}
return nil
}
func CountTRTC(model *domain.Model) int64 {
var total int64
if err := model.DB().Model(GroupTrtc{}).Count(&total).Error; err != nil {
model.Log.Errorf("CountTRTC fail:%v", err)
}
model.Log.Infof("CountTRTC , total:%v", total)
return total
}
......@@ -3,9 +3,11 @@ package group_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/myerr"
"time"
)
//群组勋章
......@@ -30,7 +32,6 @@ func (groupInfo *GroupInfo) GroupMedalMgrAdd(model *domain.Model, resMedalId uin
}
}
func GetGroupMedalOrErr(model *domain.Model, id mysql.ID) (*GroupMedal, error) {
groupMedal := GroupMedal{}
if err := model.Db.Model(&GroupMedal{}).First(&groupMedal, id).Error; err != nil {
......@@ -65,7 +66,11 @@ func BatchGetMedals(db *gorm.DB, groupIds []string) (map[string][]uint64, error)
return nil, nil
}
rows := make([]GroupMedal, 0)
if err := db.Model(&GroupMedal{}).Where("im_group_id IN ?", groupIds).Find(&rows).Error; err != nil {
if err := db.Model(GroupMedal{}).Joins("left join res_medal rm on group_medal.res_medal_id = rm.id").
Where("group_medal.im_group_id IN ?", groupIds).
Where("(group_medal.expire_at is null or group_medal.expire_at > ?)", time.Now().Format(utils.DATETIME_FORMAT)).
Order("rm.sort").
Find(&rows).Error; err != nil {
return nil, err
}
result := make(map[string][]uint64, 0)
......
......@@ -64,6 +64,20 @@ func IsHiddenGroup(db *gorm.DB, groupId string) (bool, error) {
}
}
func IsHiddenGroupBy(model *domain.Model, imGroupId string) bool {
info := new(GroupSetting)
if err := model.DB().Model(GroupSetting{}).Where("group_id = ? and is_hidden = 1", imGroupId).First(&info).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return false
}
return false
}
if info != nil && info.ID > 0 {
return true
}
return false
}
func (gs *GroupSetting) Get(db *gorm.DB) error {
return db.Where(gs).First(gs).Error
}
......
......@@ -23,9 +23,13 @@ func (g *GroupTop) Delete(model *domain.Model) error {
return model.Db.Where(g).Delete(&GroupTop{}).Error
}
func GroupTopGetAll(model *domain.Model) ([]string, error) {
func GroupTopGetAll(model *domain.Model, area int) ([]string, error) {
rows := make([]GroupTop, 0)
err := model.Db.Order("id").Find(&rows).Error
err := model.DB().Table("group_top").
Joins("left join group_info gi on group_top.im_group_id = gi.im_group_id "+
"left join res_country rc on gi.country = rc.name").
Where("rc.area = ?", area).
Order("group_top.id").Find(&rows).Error
if err != nil {
return nil, err
}
......
package group_m
import (
"git.hilo.cn/hilo-common/domain"
"hilo-group/_const/enum/group_e"
"hilo-group/myerr"
"math/rand"
"time"
)
type GroupIm struct {
Id uint64
Provider group_e.GroupProvider
Prob int
StartIdx int `gorm:"-"'`
EndIdx int `gorm:"-"`
}
type GroupImLog struct {
ImGroupId string
Provider group_e.GroupProvider
}
func GetGroupImConf(model *domain.Model) ([]*GroupIm, error) {
rows := make([]*GroupIm, 0)
if err := model.Db.Table("group_im").Find(&rows).Error; err != nil {
return nil, myerr.WrapErr(err)
}
return rows, nil
}
func GetRandomImProvider(model *domain.Model) group_e.GroupProvider {
var res group_e.GroupProvider
confList, err := GetGroupImConf(model)
if err != nil {
model.Log.Errorf("GetRandomImProvider err:%v", err)
return res
}
conf := GetRandomGroupImConf(confList)
return conf.Provider
}
func GetRandomGroupImConf(confList []*GroupIm) *GroupIm {
var res *GroupIm
var max int
for i, v := range confList {
if v.Prob > 0 {
confList[i].StartIdx = max
max += v.Prob
confList[i].EndIdx = max
}
}
rand.Seed(time.Now().UnixNano())
randNum := rand.Intn(max)
for _, v := range confList {
if v.StartIdx <= randNum && randNum < v.EndIdx {
res = v
}
}
return res
}
func CreateGroupImLog(model *domain.Model, imGroupId string, provider group_e.GroupProvider) error {
if err := model.Db.Model(GroupImLog{}).Create(GroupImLog{ImGroupId: imGroupId, Provider: provider}).Error; err != nil {
return myerr.WrapErr(err)
}
return nil
}
......@@ -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,7 +15,10 @@ 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"
"hilo-group/domain/model/user_m"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
......@@ -96,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
//麦位基本信息。
......@@ -122,8 +126,10 @@ type MicUser struct {
I int
//麦中的人
ExternalId string
//
//用户id
UserId uint64
//用户cpId
CpUserId uint64
//静音 true:静音,false:没有静音
Forbid bool
//上麦的的时间戳
......@@ -182,11 +188,13 @@ func UpdateMicExpire(model *domain.Model, groupUuid string, externalId string) e
//2022-07-20 升级,判断是自己是否已经在别的麦上了
//const micInScript = "local flag = redis.call('SET', '{prefixGroupMicUser}', '{micUserStr}', 'ex', '{micExpire}', 'nx') if flag ~= false then redis.call('SETEX', '{prefixGroupUserMic}', '{micExpire}', '{groupUserStr}') return 1 end return 2 "
const micInScript = "local flag = redis.call('EXISTS', '{prefixGroupUserMic}') if flag == 0 then local flag1 = redis.call('SET', '{prefixGroupMicUser}', '{micUserStr}', 'ex', '{micExpire}', 'nx') if flag1 ~= false then redis.call('SETEX', '{prefixGroupUserMic}', '{micExpire}', '{groupUserStr}') return 1 end return 2 end return 3"
const micUpdateScript = "local flag = redis.call('EXISTS', '{prefixGroupUserMic}') if flag == 1 then local flag1 = redis.call('SET', '{prefixGroupMicUser}', '{micUserStr}', 'ex', '{micExpire}', 'xx') if flag1 ~= false then redis.call('SETEX', '{prefixGroupUserMic}', '{micExpire}', '{groupUserStr}') return 1 end return 2 end return 3"
//
//上麦(自己),
//规则:1:加锁了不能上麦 2:麦上有人,不能上麦
//cpUserId如果有
func (mic *Mic) In(userId uint64, externalId string) error {
// 群是否被封禁, 呃,,,呃,,,呃,,,
banned := GroupBanned{ImGroupId: mic.GroupUuid}
......@@ -218,27 +226,92 @@ func (mic *Mic) In(userId uint64, externalId string) error {
if err != nil {
return err
}
//让自己踢出去。
/* if str, err := redisCli.GetRedis().Get(context.Background(), redis_key.GetPrefixGroupUserInMic(externalId)).Result(); err != nil {
if err != redis2.Nil {
//加入到麦上可能有人的集合中。
groupMicHasIn(mic.model, mic.GroupUuid, userId)
//lua上麦,让麦上的人同人在麦上,保持原子性操作
//清理脚本,不然redis占用内存越来越高,并且不会释放
groupUserStr, err := userInMicToStr(mic.GroupUuid, mic.I, userId)
if err != nil {
return err
}
script := strings.Replace(strings.Replace(
strings.Replace(
strings.Replace(
strings.Replace(micInScript,
"{micExpire}", strconv.Itoa(expireMinute), -1),
"{prefixGroupMicUser}", redis_key.GetPrefixGroupMicUser(mic.GroupUuid, mic.I), -1),
"{micUserStr}", micUserStr, -1),
"{prefixGroupUserMic}", redis_key.GetPrefixGroupUserInMic(externalId), -1),
"{groupUserStr}", groupUserStr, -1)
r, err := redis2.NewScript(script).Run(context.Background(), redisCli.GetRedis(), []string{}).Result()
mic.model.Log.Infof("micUser In micInScript:%v, result:%v", script, r)
d := r.(int64)
if err != nil {
return myerr.WrapErr(err)
}
} else {
if userInMic, err := strToUserInMic(str); err != nil {
return err
} else {
if micUser, err := GetMicUser(mic.model, userInMic.GroupUuid, userInMic.I); err != nil {
return err
} else {
if micUser != nil {
if err := micUser.LeaveByUser(userId, externalId); err != nil {
return err
if d == int64(2) {
return bizerr.GroupMicHasUser
}
if d == int64(3) {
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)
// 发信令,让前端重新拉取,接受容错,
sendSignalMsg(mic.model, mic.GroupUuid, GroupSystemMsg{
MsgId: group_e.GroupMicInSignal,
Source: externalId,
}, false)
return nil
}
//上麦(自己),
//规则:1:加锁了不能上麦 2:麦上有人,不能上麦
//cpUserId如果有
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)
}
}()
// 群是否被封禁, 呃,,,呃,,,呃,,,
banned := GroupBanned{ImGroupId: mic.GroupUuid}
if err := banned.Get(mic.model); err != gorm.ErrRecordNotFound {
return bizerr.GroupIsBanned
}
//判断群组设置上的麦 是否被关闭
groupInfo, err := GetGroupInfo(mic.model, mic.GroupUuid)
if err != nil {
return err
}
if groupInfo.MicOn == false {
return bizerr.GroupInfoMicClosed
}
}*/
//麦被加锁了
if mic.Lock {
return bizerr.GroupMicLock
}
//设置值到redis
micUserStr, err := micUserToStr(MicUser{
GroupUuid: mic.GroupUuid,
I: mic.I,
ExternalId: externalId,
UserId: userId,
CpUserId: cpUserId,
Forbid: forbid,
Timestamp: time.Now().Unix(),
})
if err != nil {
return err
}
//加入到麦上可能有人的集合中。
groupMicHasIn(mic.model, mic.GroupUuid, userId)
......@@ -248,12 +321,15 @@ func (mic *Mic) In(userId uint64, externalId string) error {
if err != nil {
return err
}
//r, err := redis2.NewScript(micInScript).Run(context.Background(), redisCli.GetRedis(), []string{redis.GetPrefixGroupMicUser(mic.groupUuid), strconv.Itoa(mic.i), redis.GetPrefixGroupUserMic(), externalId}, micUserStr, groupUserStr).Result()
script := strings.Replace(strings.Replace(
strings.Replace(
strings.Replace(
strings.Replace(micInScript, "{micExpire}", strconv.Itoa(expireMinute), -1), "{prefixGroupMicUser}", redis_key.GetPrefixGroupMicUser(mic.GroupUuid, mic.I), -1), "{micUserStr}", micUserStr, -1), "{prefixGroupUserMic}", redis_key.GetPrefixGroupUserInMic(externalId), -1), "{groupUserStr}", groupUserStr, -1)
//redisCli.GetRedis().ScriptFlush(context.Background())
strings.Replace(micUpdateScript,
"{micExpire}", strconv.Itoa(expireMinute), -1),
"{prefixGroupMicUser}", redis_key.GetPrefixGroupMicUser(mic.GroupUuid, mic.I), -1),
"{micUserStr}", micUserStr, -1),
"{prefixGroupUserMic}", redis_key.GetPrefixGroupUserInMic(externalId), -1),
"{groupUserStr}", groupUserStr, -1)
r, err := redis2.NewScript(script).Run(context.Background(), redisCli.GetRedis(), []string{}).Result()
mic.model.Log.Infof("micUser In micInScript:%v, result:%v", script, r)
d := r.(int64)
......@@ -289,12 +365,17 @@ func (micUser *MicUser) leave(operateUserId uint64, operateExternalId string) er
}
//
externalId := micUser.ExternalId
// 超管处理
if flag, err := user_m.IsSuperManagerV2(micUser.model, operateUserId, micUser.UserId); err != nil {
return err
} else if !flag {
if micUser.ExternalId != operateExternalId {
//检查权限,管理人权限, 不过不拥有管理人权限,则抛出错误
if err := MgrPermission(micUser.model, micUser.GroupUuid, operateUserId, micUser.UserId); err != nil {
return err
}
}
}
//设置值到redis
//redisCli.GetRedis().ScriptFlush(context.Background())
script := strings.Replace(strings.Replace(
......@@ -310,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)
......@@ -562,7 +647,7 @@ func (micUser *MicUser) SpeechOpen(userId uint64, externalId string) error {
//禁麦, 管理人 同 自己能禁麦(特别注意:产品说,无论是否式管理人开启禁麦,自己同管理人都能关闭禁麦)
//规则:1:自己禁麦 2:管理人禁麦
func (micUser *MicUser) SpeechClose(userId uint64, externalId string) error {
func (micUser *MicUser) SpeechClose(userId uint64, externalId, lang string) error {
if micUser == nil {
return bizerr.GroupMicNoUser
} else {
......@@ -574,7 +659,7 @@ func (micUser *MicUser) SpeechClose(userId uint64, externalId string) error {
} else if flag {
//不能让超级管理人移除
return bizerr.OfficialStaffLimit
} else if flag, err := user_m.IsSuperManager(micUser.model, userId); err != nil {
} else if flag, err := user_m.IsSuperManagerV2(micUser.model, userId, micUser.UserId); err != nil {
return err
} else if flag {
//超级管理人,无敌状态
......@@ -588,7 +673,8 @@ func (micUser *MicUser) SpeechClose(userId uint64, externalId string) error {
if flag, err := noble_m.CheckNobleLevel(micUser.model.Db, micUser.UserId, 5); err != nil {
return err
} else if flag {
return bizerr.NobleNoMicSpeechCloseLevel5
return myerr.WrapErr(res_m.GetErrByLanguage(micUser.model.Db, common.MSG_ID_BAN_MIC_NOBLE_5, lang, bizerr.NobleNoMicSpeechCloseOverLevel5))
//return bizerr.NobleNoMicSpeechCloseLevel5
}
micUser.Forbid = true
}
......@@ -748,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 "
......@@ -767,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判断是否, 最后的保证,(猜想:真正麦上有人的群没有很多)
......@@ -799,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
......@@ -836,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
}
......
......@@ -55,8 +55,11 @@ type MicUserData struct {
NobleLeave uint16 `json:"noble"` // 当前的贵族等级
HeadwearPicUrl string `json:"headwearPicUrl"`
HeadwearEffectUrl string `json:"headwearEffectUrl"`
HeadwearReverseEffectUrl string `json:"headwearReverseEffectUrl"` // 反转svga效果
SvipLevel int `json:"svipLevel"`
Svip rpc.CvSvip `json:"svip"`
MicEffect string `json:"micEffect"` //mic位置特效svga
HeadwearIcon string `json:"headwearIcon"` //头饰里面的小头像
}
type MicNumChangeContent struct {
......@@ -65,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)
......@@ -91,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 {
......@@ -125,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 {
......@@ -160,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 {
......@@ -201,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 {
......@@ -238,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 {
......@@ -256,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 {
......@@ -283,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 {
......@@ -307,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
}
......@@ -316,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 {
......@@ -337,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)
......@@ -347,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,
......@@ -356,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
......@@ -394,6 +409,11 @@ func getMicIContent(model *domain.Model, groupId string, i int) (MicContent, err
if err != nil {
return MicContent{}, err
}
var micEffect string
if micUser.CpUserId > 0 {
micEffect = "https://image.whoisamy.shop/hilo/resource/svga/mic_effect_cp.svga"
micUserData.MicEffect = micEffect
}
return MicContent{
GroupId: txGroupId,
I: mic.I,
......@@ -440,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 {
......@@ -453,9 +474,11 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
}
var headwearPicUrl string
var headwearEffectUrl string
var headwearReverseEffectUrl string
if headwearUser, flag := headwearMap[id]; flag {
headwearPicUrl = resHeadwearMap[headwearUser.HeadwearId].PicUrl
headwearEffectUrl = resHeadwearMap[headwearUser.HeadwearId].EffectUrl
headwearReverseEffectUrl = resHeadwearMap[headwearUser.HeadwearId].ReverseEffectUrl
}
micUserDataMap[id] = &MicUserData{
Id: user.ID,
......@@ -468,8 +491,10 @@ func getMicUserDatas(model *domain.Model, userIds []uint64) (map[uint64]*MicUser
NobleLeave: nobleMap[id],
HeadwearPicUrl: headwearPicUrl,
HeadwearEffectUrl: headwearEffectUrl,
HeadwearReverseEffectUrl: headwearReverseEffectUrl,
SvipLevel: svips[id].SvipLevel,
Svip: rpc.CopySimpleSvip(svips[id]),
HeadwearIcon: cpRelations[user.ID].CpUserAvatar,
}
}
return micUserDataMap, nil
......@@ -495,6 +520,7 @@ func getMicUserData(model *domain.Model, userId uint64) (*MicUserData, error) {
var headwearPicUrl string
var headwearEffectUrl string
var headwearReverseEffectUrl string
headwear, err := user_m.GetUserHeadwearUsing(model, userId)
if err != nil {
......@@ -507,7 +533,13 @@ func getMicUserData(model *domain.Model, userId uint64) (*MicUserData, error) {
}
headwearPicUrl = resHeadwear.PicUrl
headwearEffectUrl = resHeadwear.EffectUrl
headwearReverseEffectUrl = resHeadwear.ReverseEffectUrl
}
var headwearIcon string
if cpRelation, _ := rpc.GetUserCpRelation(model, userId); len(cpRelation.CpUserAvatar) > 0 {
headwearIcon = cpRelation.CpUserAvatar
}
return &MicUserData{
Id: user.ID,
ExternalId: user.ExternalId,
......@@ -519,7 +551,9 @@ func getMicUserData(model *domain.Model, userId uint64) (*MicUserData, error) {
NobleLeave: nobleLeave,
HeadwearPicUrl: headwearPicUrl,
HeadwearEffectUrl: headwearEffectUrl,
HeadwearReverseEffectUrl: headwearReverseEffectUrl,
SvipLevel: svip.SvipLevel,
Svip: rpc.CopySimpleSvip(svip),
HeadwearIcon: headwearIcon,
}, 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,
})
}
......
......@@ -103,7 +103,9 @@ func (rb *RoomBanner) GetRoomBanners(db *gorm.DB, vcAllow bool) ([]RoomBanner, e
}
res := make([]RoomBanner, 0, len(rows))
for _, v := range rows {
if !vcAllow && (v.ID == 241 || v.ID == 781 || v.ID == 771) {
// 版本控制
if !vcAllow && (v.ID == 241 || v.ID == 781 || v.ID == 771 || v.ID == 911 || v.ID == 841 ||
v.ID == 851 || v.ID == 1001 || v.ID == 981 || v.ID == 1451 || v.ID == 1621) {
continue
}
res = append(res, v)
......
package mic_m
import (
"git.hilo.cn/hilo-common/_const/enum/timezone_e"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/redis_key/mic_k"
"time"
)
......@@ -17,14 +19,15 @@ type UserOnMic struct {
LastCalTs int64
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
Tz timezone_e.Timezone
}
// 获取用户当日上麦
// 允许返回gorm.ErrRecordNotFound
func GetUserOnMic(model *domain.Model, userId mysql.ID) (*UserOnMic, error) {
func GetUserOnMic(model *domain.Model, userId mysql.ID, tz timezone_e.Timezone) (*UserOnMic, error) {
res := new(UserOnMic)
day := time.Now().Format("2006-01-02")
if err := model.DB().Where("date = ? AND user_id = ?", day, userId).First(res).Error; err != nil {
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
if err := model.DB().Where("date = ? AND user_id = ? AND tz = ?", day, userId, tz).First(res).Error; err != nil {
return nil, err
}
return res, nil
......@@ -34,13 +37,14 @@ func GetUserOnMic(model *domain.Model, userId mysql.ID) (*UserOnMic, error) {
// 事务操作
func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
omMic, err := GetUserOnMic(model, userId)
for _, tz := range timezone_e.Timezones {
omMic, err := GetUserOnMic(model, userId, tz)
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
day0Ts := utils.GetZeroTime(time.Now()).Unix()
day0Ts := utils.GetZeroTime(time.Now().In(timezone_e.TimezoneLocMap[tz])).Unix()
if omMic != nil && joinMicTimestamp < omMic.LastCalTs { // 加入的时间比上次计算时间小
curTs = omMic.LastCalTs
}
......@@ -49,15 +53,16 @@ func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64)
curTs = day0Ts
}
score := nowTs - curTs
day := time.Now().Format("2006-01-02")
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
onMicNew := &UserOnMic{
Date: day,
UserId: userId,
Seconds: mysql.Num(score),
LastCalTs: nowTs,
Tz: tz,
}
if err := model.DB().Model(UserOnMic{}).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}},
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}, {Name: "tz"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"seconds": gorm.Expr("seconds + ?", onMicNew.Seconds),
"last_cal_ts": nowTs,
......@@ -66,16 +71,56 @@ func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64)
model.Log.Errorf("IncrUserOnMic fail:%v", err)
return err
}
}
return nil
})
}
// 增加用户上麦时长
// 事务操作
func IncrUserOnMicV2(model *domain.Model, userId mysql.ID) error {
for _, tz := range timezone_e.Timezones {
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
if err := model.DB().Model(UserOnMic{}).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}, {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, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
func MGetUserOnMicSeconds(model *domain.Model, day string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
var rows []UserOnMic
res := make(map[mysql.ID]mysql.Num)
if err := model.DB().Model(UserOnMic{}).Where("`date`= ? AND user_id in ?", day, userIds).Find(&rows).Error; err != nil {
if err := model.DB().Model(UserOnMic{}).Where("`date`= ? AND tz = ? AND user_id in ?", day, tz, userIds).Find(&rows).Error; err != nil {
model.Log.Errorf("MGetUserOnMic fail:%v", err)
return res, err
}
......@@ -84,3 +129,18 @@ func MGetUserOnMicSeconds(model *domain.Model, day string, userIds []uint64) (ma
}
return res, nil
}
// 批量获取用户上麦时长
// @return userId->seconds
func MGetUserOnMicSecondsRange(model *domain.Model, beginDate, endDate string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
var rows []UserOnMic
res := make(map[mysql.ID]mysql.Num)
if err := model.DB().Model(UserOnMic{}).Where("`date` >= ? AND `date` <= ? AND tz = ? AND user_id in ?", beginDate, endDate, tz, userIds).Find(&rows).Error; err != nil {
model.Log.Errorf("MGetUserOnMic fail:%v", err)
return res, err
}
for _, r := range rows {
res[r.UserId] += r.Seconds
}
return res, nil
}
......@@ -144,7 +144,7 @@ func BatchGetActiveNoble(db *gorm.DB, userIds []uint64) (map[uint64]UserNoble, e
start += NUM
end += NUM
}
mylogrus.MyLog.Infof("BatchGetActiveNoble expected:%v,actual:%v,notEndUids:%v", len(userIds), len(result), notEndUids)
//mylogrus.MyLog.Infof("BatchGetActiveNoble expected:%v,actual:%v,notEndUids:%v", len(userIds), len(result), notEndUids)
if len(userIds) != len(result) {
mylogrus.MyLog.Warnf("BatchGetActiveNoble expected:%v", userIds)
}
......
......@@ -23,6 +23,7 @@ type ResCountry struct {
StandardShortName mysql.Str
AreaCode mysql.Str
AreaCodeName mysql.Str
Area mysql.Str
}
type ResLanguage struct {
......@@ -81,6 +82,22 @@ func GetAllCountries(model *domain.Model) (map[string]string, error) {
return result, nil
}
// 获取所有国家的Area信息
func GetAllCountriesArea(model *domain.Model) (map[string]string, error) {
var countrys []ResCountry
if err := model.Db.Model(&ResCountry{}).Where(&ResCountry{
Status: mysql.USER,
}).Find(&countrys).Error; err != nil {
return nil, myerr.WrapErr(err)
}
result := make(map[string]string, 0)
for _, i := range countrys {
result[i.Name] = i.Area
}
return result, nil
}
func GetAllCountryByFilter(model *domain.Model, shortNames []string) ([]ResCountry, error) {
var countrys []ResCountry
if err := model.Db.Model(&ResCountry{}).Where(&ResCountry{
......@@ -197,3 +214,9 @@ func GetLangeByCountry(db *gorm.DB, country mysql.Str) (string, error) {
}
}
//获取所有国家名字列表
func GetCountryNameList(model *domain.Model) ([]string, error) {
res := make([]string, 0)
err := model.DB().Table("res_country").Select("distinct(name) name").Pluck("name", &res).Error
return res, myerr.WrapErr(err)
}
......@@ -14,6 +14,7 @@ type ResHeadwear struct {
Name mysql.Str
PicUrl mysql.Str
EffectUrl mysql.Str
ReverseEffectUrl mysql.Str
}
func GetResHeadwearById(model *domain.Model, id mysql.ID) (*ResHeadwear, error) {
......
......@@ -325,7 +325,7 @@ func GetOnlineStatus(model *domain.Model, extIds []string) (map[string]uint, err
model.Log.Warnf("getOnlineStatus redis failed")
left = extIds
} else {
model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r)
//model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r)
if len(r) >= len(extIds) {
for i, e := range extIds {
......@@ -387,10 +387,10 @@ func getOnlineStatus(extIds []string) ([]interface{}, error) {
for _, e := range extIds {
keys = append(keys, redis_key.GetOnLineStatusKey(e))
}
return redisCli.RedisClient.MGet(context.Background(), keys...).Result()
return redisCli.RedisClusterClient.MGet(context.Background(), keys...).Result()
}
func setOnlineStatus(extId string, status uint, ttl time.Duration) error {
key := redis_key.GetOnLineStatusKey(extId)
return redisCli.RedisClient.Set(context.Background(), key, status, ttl).Err()
return redisCli.RedisClusterClient.Set(context.Background(), key, status, ttl).Err()
}
......@@ -3,10 +3,12 @@ package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr"
)
//获取用户的国家,和所属的区域(是否阿语区)
// 获取用户的国家,和所属的区域(是否阿语区)
// 默认国家给沙特
func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
type info struct {
Name string
......@@ -14,7 +16,11 @@ func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
}
res := new(info)
if err := model.DB().Raw("select name, area from res_country where name = (select country from user where id = ?)", id).First(&res).Error; err != nil {
if err != gorm.ErrRecordNotFound {
return "", 0, myerr.WrapErr(err)
}
// gorm.ErrRecordNotFound
return "KSA", 1, nil
}
return res.Name, res.Area, nil
}
......@@ -48,8 +48,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
if err != nil {
return nil, err
}
logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes)
logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList)
//logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes)
//logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList)
maxGrades := make(map[uint8]int, 0)
maxMedalIds := make(map[uint8]uint32, 0)
......@@ -70,8 +70,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
}
}
}
logger.Infof("maxGrade %+v", maxGrades)
logger.Infof("maxMedalIds %+v", maxMedalIds)
//logger.Infof("maxGrade %+v", maxGrades)
//logger.Infof("maxMedalIds %+v", maxMedalIds)
mIds := result
result = make([]uint32, 0)
......
......@@ -3,13 +3,17 @@ package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr"
"strings"
)
type SuperManager struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId mysql.ID
IsAll bool
Countries string
}
func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) {
......@@ -22,6 +26,33 @@ func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) {
return n > 0, nil
}
// 对某人是否有超管权限
func IsSuperManagerV2(model *domain.Model, userId, targetUserId mysql.ID) (bool, error) {
var man SuperManager
if err := model.Db.Model(&SuperManager{}).Where(&SuperManager{
UserId: userId,
}).First(&man).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("IsSuperManagerV2 fail:%v", err)
}
return false, nil
}
if man.IsAll {
return true, nil
}
targetUser, err := GetUser(model, targetUserId)
if err != nil {
return false, err
}
countries := strings.Split(man.Countries, ",")
for _, c := range countries {
if c == targetUser.Country {
return true, nil
}
}
return false, nil
}
func GetSuperManagerAll(model *domain.Model) ([]uint64, error) {
superManagers := []SuperManager{}
if err := model.Db.Model(&SuperManager{}).Find(&superManagers).Error; err != nil {
......
......@@ -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)
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 nil, err
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)
}
result := make(map[mysql.ID]User, 0)
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
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
}
......
......@@ -38,7 +38,7 @@ func (this *DiamondService) CheckDealerTransferFamilyLimit(dealerId, userId uint
return err
}
if dealerArea != area {
return bizerr.DealerCannotSaleToOtherArea
return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_CHARGE_NO_AREA, lang, bizerr.DealerCannotSaleToOtherArea))
}
// 代理、用户是否加入了家族
......
......@@ -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,91 +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)
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
}
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)
}
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
}
......@@ -30,13 +30,12 @@ func (s *GiftSendEventService) Consume() error {
}
}()
var model = domain.CreateModel(s.svc.CtxAndDb)
return model.Transaction(func(model *domain.Model) error {
events, offset, err := event_m.FetchEventGiftSend(model, BatchCount)
if err != nil {
return err
}
for k := range events {
// 一个事件一个事务
err = model.Transaction(func(model *domain.Model) error {
cpEvent := &event_m.EventGiftSend{
Entity: mysql.Entity{
ID: events[k].ID,
......@@ -49,26 +48,24 @@ func (s *GiftSendEventService) Consume() error {
}
if cpEvent.MarkHiloGroup == mysql.YES {
model.Log.Warnf("already consume msg :%v", cpEvent)
return nil
continue
}
sendGiftEvent := new(gift_ev.SendGiftEvent)
if err := json.Unmarshal(cpEvent.Payload, sendGiftEvent); err != nil {
model.Log.Errorf("json msg fail,event:%v,err:%v", cpEvent, err)
return nil
continue
}
if err := gift_ev.PublishSendGiftEvent(model, sendGiftEvent); err != nil {
model.Log.Errorf("PublishSendGiftEvent fail,event:%v,err:%v", string(cpEvent.Payload), err)
return err
}
// 标记已经处理
// 标记已经处理,mark比publish事件提前,尽量避免异步事件重复执行
cpEvent.Model = model
err = cpEvent.MarkDone()
if err != nil {
model.Log.Errorf("consume msg fail,event:%v,err:%v", cpEvent, err)
return err
}
return nil
})
if err := gift_ev.PublishSendGiftEvent(model, sendGiftEvent); err != nil {
model.Log.Errorf("PublishSendGiftEvent fail,event:%v,err:%v", string(cpEvent.Payload), err)
return err
}
}
// 最后一次提交offset
if len(events) > 0 {
......@@ -76,4 +73,5 @@ func (s *GiftSendEventService) Consume() error {
return offset.Persistence()
}
return nil
})
}
......@@ -6,12 +6,16 @@ import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"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"
"hilo-group/domain/model/user_m"
"hilo-group/domain/service/signal_s"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
......@@ -214,13 +218,13 @@ func (s *GroupMicService) GroupMicSpeechOpen(userId uint64, externalId string, g
}
//关闭麦
func (s *GroupMicService) GroupMicSpeechClose(userId uint64, externalId string, groupUuid string, i int) error {
func (s *GroupMicService) GroupMicSpeechClose(userId uint64, externalId string, groupUuid, lang string, i int) error {
model := domain.CreateModelContext(s.svc.MyContext)
micUser, err := group_m.GetMicUser(model, groupUuid, i)
if err != nil {
return err
}
return micUser.SpeechClose(userId, externalId)
return micUser.SpeechClose(userId, externalId, lang)
}
//麦上的人群发消息
......@@ -315,16 +319,115 @@ 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
}
// 检查cp上麦
func (s *GroupMicService) CheckCpOnMic(groupUuid string) {
model := domain.CreateModelContext(s.svc.MyContext)
// 填充cp麦位
micNumType, err := group_m.GetMicNumType(model, groupUuid)
if err != nil {
return
}
_, micUsers, err := group_m.GetAllMic(groupUuid, micNumType)
if err != nil {
return
}
// 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的信息
if err != nil {
model.Log.Errorf("MGetUserCpPairs fail:%v", err)
return
}
users, err := user_m.GetUserMapByIds(model, userIds)
if err != nil {
model.Log.Errorf("GetUserMapByIds fail:%v", err)
return
}
for _, pairs := range cpPairs {
level := pairs[2]
if level < 5 { // cpLevel < 5 级别没有麦位特效
continue
}
userId := pairs[0]
cpUserId := pairs[1]
redisLock(redis_key.GetPrefixGroupMicUserInLock(userId), uuid.NewV4().String(), time.Second*2, func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
mic, err := group_m.GetMic(model, groupUuid, userMicIndex[userId])
if err != nil {
return err
}
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)
mic, err := group_m.GetMic(model, groupUuid, userMicIndex[cpUserId])
if err != nil {
return err
}
return mic.Update(cpUserId, users[cpUserId].ExternalId, userId, forbidMap[cpUserId])
})
}
return
}
// 检查cp下麦
func (s *GroupMicService) CheckCpLeaveMic(groupUuid string, leaveUid uint64) {
model := domain.CreateModelContext(s.svc.MyContext)
// 填充cp麦位
micNumType, err := group_m.GetMicNumType(model, groupUuid)
if err != nil {
return
}
_, micUsers, err := group_m.GetAllMic(groupUuid, micNumType)
if err != nil {
return
}
// 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
}
user, err := user_m.GetUser(model, cpUserId)
if err != nil {
model.Log.Errorf("GetUser fail:%v", err)
return
}
redisLock(redis_key.GetPrefixGroupMicUserInLock(cpUserId), uuid.NewV4().String(), time.Second*2, func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
mic, err := group_m.GetMic(model, groupUuid, userMicIndex[cpUserId])
if err != nil {
return err
}
return mic.Update(cpUserId, user.ExternalId, 0, forbidMap[cpUserId])
})
return
}
package group_power_s
import (
"encoding/json"
"git.hilo.cn/hilo-common/_const/enum/diamond_e"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/txop/award_tx"
"git.hilo.cn/hilo-common/utils"
"github.com/jinzhu/now"
"hilo-group/_const/enum/groupPower_e"
"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"
"hilo-group/domain/model/msg_m"
"hilo-group/domain/model/noble_m"
"hilo-group/domain/model/user_m"
"hilo-group/myerr/bizerr"
"time"
)
type GroupPowerService struct {
......@@ -66,3 +82,505 @@ func (s *GroupPowerService) GroupPowerUserLeave(groupPowerId mysql.ID, userId my
})
return remainSeconds, err
}
func GetGroupPowerRankResp(model *domain.Model, beginDate, endDate string, userId uint64, gpStatus groupPower_e.GroupPowerStatus,
area int) (response group_power_cv.CvGroupPowerRank, err error) {
rank, err := groupPower_m.GetGroupPowerExpRank(model, beginDate, endDate, 30, gpStatus, area)
if err != nil {
return
}
var ids []mysql.ID
for _, g := range rank {
ids = append(ids, g.GroupPowerId)
}
var myGroupPower *groupPower_m.GroupPowerUser
if userId > 0 {
myGroupPower, err = groupPower_m.GetGroupPowerUserOrNil(model, userId)
if err != nil {
return
}
}
if myGroupPower != nil {
ids = append(ids, myGroupPower.GroupPowerId)
}
grades, err := groupPower_m.MGetGroupPowerGrade(model, ids)
if err != nil {
return
}
groupPowers, err := groupPower_m.MGetGroupPowerInfoMap(model, ids)
if err != nil {
return
}
if myGroupPower != nil {
myGroupPowerRank, err := groupPower_m.GetMyGroupPowerExpRank(model, beginDate, endDate, myGroupPower.GroupPowerId)
if err != nil {
return response, err
}
response.MyGroupPower = &group_power_cv.CvGroupPowerRankData{
CvGroupPowerBase: group_power_cv.CvGroupPowerBase{
Id: myGroupPower.GroupPowerId,
Icon: groupPowers[myGroupPower.GroupPowerId].Icon,
Name: groupPowers[myGroupPower.GroupPowerId].Name,
Nameplate: groupPowers[myGroupPower.GroupPowerId].Nameplate,
},
CvGroupPowerGrade: group_power_cv.CvGroupPowerGrade{
Grade: grades[myGroupPower.GroupPowerId].Grade,
Exp: myGroupPowerRank.Exp,
},
Rank: 0,
}
}
for _, v := range rank {
if response.MyGroupPower != nil && v.GroupPowerId == response.MyGroupPower.Id {
response.MyGroupPower.Rank = v.Rank
}
response.Items = append(response.Items, group_power_cv.CvGroupPowerRankData{
CvGroupPowerBase: group_power_cv.CvGroupPowerBase{
Id: v.GroupPowerId,
Icon: groupPowers[v.GroupPowerId].Icon,
Name: groupPowers[v.GroupPowerId].Name,
Nameplate: groupPowers[v.GroupPowerId].Nameplate,
},
CvGroupPowerGrade: group_power_cv.CvGroupPowerGrade{
Grade: grades[v.GroupPowerId].Grade,
Exp: v.Exp,
},
Rank: v.Rank,
})
}
if response.MyGroupPower != nil && response.MyGroupPower.Rank == 0 {
response.MyGroupPower.Rank = 31 // 客户端统一显示30+
}
return response, nil
}
func GetGroupPowerStar(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*group_power_cv.CvGroupPowerStarData, error) {
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
}
//var response []group_power_cv.CvGroupPowerStarData
response := make([]*group_power_cv.CvGroupPowerStarData, 0)
var userIds []mysql.ID
for _, row := range rank {
userIds = append(userIds, row.UserId)
}
users, err := user_c.GetUserTinyMap(model, userIds, true)
//users, err := user_m.GetUserMapByIds(model, userIds)
for _, row := range rank {
user := users[row.UserId]
score := row.Score
if _type == groupPower_e.GroupPowerStarTypeActive {
score = score / 60
}
if score <= 0 {
continue
}
response = append(response, &group_power_cv.CvGroupPowerStarData{
User: user_cv.CvUserTiny{
Id: user.ID,
ExternalId: user.ExternalId,
Code: user.Code,
Nick: user.Nick,
Avatar: user.Avatar,
},
Score: score,
})
}
return response, nil
}
func CalcGroupPowerMonthRankAct(model *domain.Model) error {
lastDayTime := time.Now().AddDate(0, 0, -1)
_now := now.New(lastDayTime)
calcMonth := _now.BeginningOfMonth().Format(utils.MONTH_FORMAT)
starDate := _now.BeginningOfMonth().Format(utils.COMPACT_MONTH_FORMAT)
beginDate, endDate := _now.BeginningOfMonth().Format("2006-01-02"), _now.EndOfMonth().Format("2006-01-02")
return DoCalcGroupPowerMonthRankAct(model, calcMonth, beginDate, endDate, starDate)
}
func BufaCalcGroupPowerMonthRankAct(model *domain.Model) error {
lastDayTime := time.Now().AddDate(0, 0, -1)
_now := now.New(lastDayTime)
calcMonth := _now.BeginningOfMonth().Format(utils.MONTH_FORMAT)
starDate := _now.BeginningOfMonth().Format(utils.COMPACT_MONTH_FORMAT)
beginDate, endDate := _now.BeginningOfMonth().Format("2006-01-02"), _now.EndOfMonth().Format("2006-01-02")
return BufaDoCalcGroupPowerMonthRankAct(model, calcMonth, beginDate, endDate, starDate)
}
func DoCalcGroupPowerMonthRankAct(model *domain.Model, calcMonth, beginDate, endDate, starDate string) error {
areaList := []int{1, 2}
for _, area := range areaList { // 计算获奖
model := domain.CreateModelContext(model.MyContext)
response, err := GetGroupPowerRankResp(model, beginDate, endDate, 0, groupPower_e.GroupPowerUserHas, area)
if err != nil {
return err
}
powerIds := make([]uint64, 0, len(response.Items))
for i, v := range response.Items {
powerIds = append(powerIds, v.Id)
response.Items[i].StarList, err = GetGroupPowerStar(model, v.Id, groupPower_e.GroupPowerStarTypeFamous, 0, 10, starDate)
if err != nil {
return err
}
}
// 奖励、日志
awardList, logList, err := getAwardAndLogList(model, powerIds, response.Items, calcMonth, area)
if err != nil {
return err
}
err = model.Transaction(func(model *domain.Model) error {
// log
err = groupPower_m.CreateActFamilyMonthRankLog(model, logList)
if err != nil {
model.Log.Errorf("CalcGroupPowerMonthRankAct area:%d, err:%+v", area, err)
return err
}
// award
for _, v := range awardList {
err = award_tx.SendUserAward(model, v, diamond_e.GeneralActivity, msg_e.MgrSendDiamondProperty)
if err != nil {
model.Log.Errorf("CalcGroupPowerMonthRankAct award:%+v, err:%+v", v, err)
return err
}
}
return nil
})
if err != nil {
model.Log.Errorf("CalcGroupPowerMonthRankAct area:%d, err:%+v", area, err)
return err
}
}
return nil
}
func BufaDoCalcGroupPowerMonthRankAct(model *domain.Model, calcMonth, beginDate, endDate, starDate string) error {
areaList := []int{2}
for _, area := range areaList { // 计算获奖
model := domain.CreateModelContext(model.MyContext)
response, err := GetGroupPowerRankResp(model, beginDate, endDate, 0, groupPower_e.GroupPowerUserHas, area)
if err != nil {
return err
}
powerIds := make([]uint64, 0, len(response.Items))
for i, v := range response.Items {
powerIds = append(powerIds, v.Id)
response.Items[i].StarList, err = GetGroupPowerStar(model, v.Id, groupPower_e.GroupPowerStarTypeFamous, 0, 10, starDate)
if err != nil {
return err
}
}
// 奖励、日志
awardList, logList, err := bufaGetAwardAndLogList(model, powerIds, response.Items, calcMonth, area)
//_, _, err = bufaGetAwardAndLogList(model, powerIds, response.Items, calcMonth, area)
if err != nil {
return err
}
err = model.Transaction(func(model *domain.Model) error {
// log
err = groupPower_m.CreateActFamilyMonthRankLog(model, logList)
if err != nil {
model.Log.Errorf("CalcGroupPowerMonthRankAct area:%d, err:%+v", area, err)
return err
}
// award
for _, v := range awardList {
err = award_tx.SendUserAward(model, v, diamond_e.GeneralActivity, msg_e.MgrSendDiamondProperty)
if err != nil {
model.Log.Errorf("CalcGroupPowerMonthRankAct award:%+v, err:%+v", v, err)
return err
}
}
return nil
})
if err != nil {
model.Log.Errorf("CalcGroupPowerMonthRankAct area:%d, err:%+v", area, err)
return err
}
}
return nil
}
func getAwardAndLogList(model *domain.Model, powerIds []uint64, items []group_power_cv.CvGroupPowerRankData, calcMonth string, area int) ([]*award_tx.UserAward, []*groupPower_m.ActFamilyMonthRankLog, error) {
// 读奖励配置
confMap := CalcGroupPowerMonthRankActConf()
awardList := make([]*award_tx.UserAward, 0, 120) // 奖励
ownerMap, err := groupPower_m.GetPowerOwnerMap(model, powerIds)
if err != nil {
return nil, nil, err
}
// log list
logList := make([]*groupPower_m.ActFamilyMonthRankLog, 0, 50)
for _, v := range items {
teamRank := 0
if v.Rank >= 1 && v.Rank <= 3 {
teamRank = v.Rank
} else if v.Rank >= 4 && v.Rank <= 10 {
teamRank = 4
} else {
break
}
ownerId, ok := ownerMap[v.Id]
if !ok || ownerId <= 0 {
model.Log.Errorf("CalcGroupPowerMonthRankAct 获取势力主错误 familyId:%d", v.Id)
return nil, nil, bizerr.InvalidParameter
}
uRankConfMap, tCOk := confMap[teamRank]
if !tCOk {
break
}
// 家族长奖励
oAward, aOk := uRankConfMap[0]
if !aOk {
model.Log.Errorf("CalcGroupPowerMonthRankAct 配置错误:%v", confMap)
return nil, nil, bizerr.InvalidParameter
}
oAwardJ, _ := json.Marshal(oAward)
logList = append(logList, &groupPower_m.ActFamilyMonthRankLog{
Period: calcMonth,
FamilyId: v.Id,
RankFamily: v.Rank,
RankUser: 0,
UserId: ownerId,
Award: string(oAwardJ),
Area: area,
})
awardList = append(awardList, &award_tx.UserAward{
UserId: ownerId,
MedalId: oAward.MedalId,
MedalDuration: oAward.MedalDay,
Diamond: oAward.Diamond,
NobleLevel: oAward.Noble,
NobleDuration: oAward.NobleDay,
HeaddressId: oAward.HeaddressId,
HeaddressDuration: oAward.HeaddressDay})
// 家族成员奖励
for i, m := range v.StarList {
uRank := i + 1
confIdx := 9
if uRank >= 1 && uRank <= 3 {
confIdx = 1
} else if uRank >= 4 && uRank <= 10 {
confIdx = 4
}
mAward, aOk := uRankConfMap[confIdx]
if !aOk {
break
}
mAwardJ, _ := json.Marshal(mAward)
logList = append(logList, &groupPower_m.ActFamilyMonthRankLog{
Period: calcMonth,
FamilyId: v.Id,
RankFamily: v.Rank,
RankUser: uRank,
UserId: m.User.Id,
Award: string(mAwardJ),
Area: area,
})
awardList = append(awardList, &award_tx.UserAward{
UserId: m.User.Id,
MedalId: mAward.MedalId,
MedalDuration: mAward.MedalDay,
Diamond: mAward.Diamond,
NobleLevel: mAward.Noble,
NobleDuration: mAward.NobleDay,
HeaddressId: mAward.HeaddressId,
HeaddressDuration: mAward.HeaddressDay})
}
}
return awardList, logList, nil
}
func bufaGetAwardAndLogList(model *domain.Model, powerIds []uint64, items []group_power_cv.CvGroupPowerRankData, calcMonth string, area int) ([]*award_tx.UserAward, []*groupPower_m.ActFamilyMonthRankLog, error) {
// 读奖励配置
confMap := CalcGroupPowerMonthRankActConf()
awardList := make([]*award_tx.UserAward, 0, 120) // 奖励
ownerMap, err := groupPower_m.GetPowerOwnerMap(model, powerIds)
if err != nil {
return nil, nil, err
}
// log list
logList := make([]*groupPower_m.ActFamilyMonthRankLog, 0, 50)
for _, v := range items {
teamRank := 0
if v.Rank >= 1 && v.Rank <= 3 {
teamRank = v.Rank
} else if v.Rank >= 4 && v.Rank <= 10 {
teamRank = 4
} else {
break
}
ownerId, ok := ownerMap[v.Id]
if !ok || ownerId <= 0 {
model.Log.Errorf("CalcGroupPowerMonthRankAct 获取势力主错误 familyId:%d", v.Id)
return nil, nil, bizerr.InvalidParameter
}
uRankConfMap, tCOk := confMap[teamRank]
if !tCOk {
break
}
//// 家族长奖励
//oAward, aOk := uRankConfMap[0]
//if !aOk {
// model.Log.Errorf("CalcGroupPowerMonthRankAct 配置错误:%v", confMap)
// return nil, nil, bizerr.InvalidParameter
//}
//oAwardJ, _ := json.Marshal(oAward)
//logList = append(logList, &groupPower_m.ActFamilyMonthRankLog{
// Period: calcMonth,
// FamilyId: v.Id,
// RankFamily: v.Rank,
// RankUser: 0,
// UserId: ownerId,
// Award: string(oAwardJ),
// Area: area,
//})
//awardList = append(awardList, &award_tx.UserAward{
// UserId: ownerId,
// MedalId: oAward.MedalId,
// MedalDuration: oAward.MedalDay,
// Diamond: oAward.Diamond,
// NobleLevel: oAward.Noble,
// NobleDuration: oAward.NobleDay,
// HeaddressId: oAward.HeaddressId,
// HeaddressDuration: oAward.HeaddressDay})
// 家族成员奖励
for i, m := range v.StarList {
uRank := i + 1
confIdx := 9
if uRank >= 1 && uRank <= 3 {
confIdx = 1
} else if uRank >= 4 && uRank <= 10 {
confIdx = 4
}
if v.Id == 2481 && uRank == 1 {
continue
}
mAward, aOk := uRankConfMap[confIdx]
if !aOk {
break
}
mAwardJ, _ := json.Marshal(mAward)
logList = append(logList, &groupPower_m.ActFamilyMonthRankLog{
Period: calcMonth,
FamilyId: v.Id,
RankFamily: v.Rank,
RankUser: uRank,
UserId: m.User.Id,
Award: string(mAwardJ),
Area: area,
})
awardList = append(awardList, &award_tx.UserAward{
UserId: m.User.Id,
MedalId: mAward.MedalId,
MedalDuration: mAward.MedalDay,
Diamond: mAward.Diamond,
NobleLevel: mAward.Noble,
NobleDuration: mAward.NobleDay,
HeaddressId: mAward.HeaddressId,
HeaddressDuration: mAward.HeaddressDay})
}
}
return awardList, logList, nil
}
// 奖励配置
type awardConf struct {
MedalId uint64
MedalDay uint32
Diamond uint32
Noble uint32
NobleDay uint32
HeaddressId uint64
HeaddressDay int
}
func CalcGroupPowerMonthRankActConf() map[int]map[int]*awardConf {
return map[int]map[int]*awardConf{
1: {
0: {MedalId: 5211, MedalDay: 30, Diamond: 320000, Noble: 5, NobleDay: 15},
1: {MedalId: 5251, MedalDay: 30, Diamond: 120000, Noble: 5, NobleDay: 7, HeaddressId: 2121, HeaddressDay: 30},
4: {HeaddressId: 2121, HeaddressDay: 30},
},
2: {
0: {MedalId: 5221, MedalDay: 30, Diamond: 220000, Noble: 5, NobleDay: 15},
1: {MedalId: 5261, MedalDay: 30, Diamond: 100000, Noble: 5, NobleDay: 7, HeaddressId: 2131, HeaddressDay: 30},
4: {HeaddressId: 2131, HeaddressDay: 30},
},
3: {
0: {MedalId: 5231, MedalDay: 30, Diamond: 120000, Noble: 5, NobleDay: 5},
1: {MedalId: 5271, MedalDay: 30, Diamond: 70000, HeaddressId: 2141, HeaddressDay: 30},
4: {HeaddressId: 2141, HeaddressDay: 30},
},
4: {
0: {MedalId: 5241, MedalDay: 30},
1: {MedalId: 5281, MedalDay: 30, HeaddressId: 2151, HeaddressDay: 30},
},
}
}
func GetGroupPowerMaxMemberNum(model *domain.Model, familyId uint64, groupPowerGrade groupPower_e.GroupPowerGrade) (maxNum int) {
maxNum = group_power_cv.GroupPowerGradePrivilegeNum[groupPowerGrade][0].Num
ownerId, err := groupPower_m.GetPowerOwner(model.Db, familyId)
if err == nil {
//检查是否是贵族
if flag, err := noble_m.CheckNobleLevel(model.Db, ownerId, 6); err != nil {
} else if flag {
newNumMap := map[groupPower_e.GroupPowerGrade]int{
groupPower_e.GroupPowerGrade0: 400,
groupPower_e.GroupPowerGrade1: 600,
groupPower_e.GroupPowerGrade2: 1000,
groupPower_e.GroupPowerGrade3: 1400}
if newNum, ok := newNumMap[groupPowerGrade]; ok {
maxNum = newNum
}
}
}
users, err := groupPower_m.GetGroupPowerUser(model, familyId)
if err != nil {
return
}
memberNum := len(users)
if memberNum > maxNum {
maxNum = memberNum
}
return
}
// 检查需不需要通知用户拉取家族小助手消息
func CheckoutSendMsgToMgr(myContext *mycontext.MyContext, groupPowerId uint64) {
defer utils.CheckGoPanic()
model := domain.CreateModelContext(myContext)
//// 申请人数
//cnt, err := groupPower_m.CountGroupPowerApply(model, groupPowerId, 0)
//if err != nil {
// model.Log.Errorf("CheckoutSendMsgToMgr err:%v, id:%v", err, groupPowerId)
// return
//}
//if cnt <= 0 {
// return
//}
// 找到家族管理员们
mgrList, err := groupPower_m.GetGroupPowerMgrList(model, groupPowerId)
if err != nil {
model.Log.Errorf("CheckoutSendMsgToMgr err:%v, id:%v", err, groupPowerId)
return
}
userMap, err := user_m.GetUserMapByIds(model, mgrList)
if err != nil {
model.Log.Errorf("CheckoutSendMsgToMgr err:%v, id:%v", err, groupPowerId)
return
}
for _, v := range mgrList {
if user, ok := userMap[v]; ok {
msg_m.SendEmasMsgAssistant(model, user.ExternalId, user.DeviceType)
}
}
}
......@@ -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
}
model.Log.Debugf("GetSupportLevelMap, GET %s: %v", period, levels)
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)
return levels, nil
}
}
} else {
result, err = group_m.GetAllGroupSupportResult(model.Db, period)
// cache miss
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)
}
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
}
......@@ -5,27 +5,36 @@ import (
"encoding/json"
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/rpc"
"git.hilo.cn/hilo-common/sdk/agora"
"git.hilo.cn/hilo-common/sdk/tencentyun"
"git.hilo.cn/hilo-common/sdk/trtc"
"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"
"hilo-group/domain/cache/tim_c"
"hilo-group/domain/event/group_ev"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/noble_m"
"hilo-group/domain/model/res_m"
"hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_mic_s"
"hilo-group/domain/service/signal_s"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
"strconv"
"strings"
"time"
)
......@@ -39,6 +48,10 @@ func (s *GroupService) CreateGroup(userId uint64, g *group_m.GroupInfo) error {
if err := group_m.CreateGroupRole(model, g.ImGroupId, userId, group_e.GROUP_OWNER); err != nil {
return err
}
//// 新房间标记成trtc房间
//if err := group_m.InitTRTC(model, g.ImGroupId); err != nil {
// model.Log.Errorf("CreateGroup g:%+v, err:%v", g, err)
//}
return nil
})
}
......@@ -115,9 +128,10 @@ func (s *GroupService) LeaveGroupMember(model *domain.Model, groupId string, use
}
//进入房间, 返回channelId, err
func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid string, password, imei, ip string) (string, string, error) {
func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid string, password, imei, ip string, provider group_e.GroupProvider, roomId int64) (string, string, error) {
var channelId string
var token string
var rideId uint64
err := s.svc.Transactional(func() error {
//检查群组是否存在, 没有真正的domel,直接service上怼
model := domain.CreateModel(s.svc.CtxAndDb)
......@@ -158,6 +172,11 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin
}
// 不是超管 且 用户是否在群的黑名单中
if !isM && group_m.InGroupBlackList(model, groupUuid, imei, ip, userId) {
// 特殊处理的拉黑列表
blackMap := map[string]uint64{"HTGS#a17058241": 3058361}
if bUid, ok := blackMap[groupUuid]; ok && bUid == userId {
return bizerr.InBlacklist
}
if svip.SvipLevel < 6 { // svip6暂时不判断GroupBlackList
return bizerr.InBlacklist
}
......@@ -171,7 +190,13 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin
if err != nil {
return err
}
if provider == group_e.GroupProvider_TRTC {
channelId = groupInfo.ChannelId
token = trtc.CreateGroupTRTCUserSig(userId, config.GetTRTCConfig())
model.Log.Infof("enter trtc group userId:%v, groupId:%v", userId, groupUuid)
} else {
channelId, token, err = agora.CreateGroupAgora(groupInfo.ChannelId, uint32(userId))
}
if err != nil {
return err
} else {
......@@ -211,6 +236,9 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin
NobleLevel uint16 `json:"nobleLevel"`
SvipLevel int `json:"svipLevel"`
Svip rpc.CvSvip `json:"svip"`
CpLevel int `json:"cpLevel"` // cp等级
CpUserAvatar string `json:"cpUserAvatar"` // cp用户头像
EntryEffectType int `json:"entryEffectType"` // 进场特效类型 1: CP 2:神秘人 3:贵族 4:vip
}
up := user_m.UserProperty{}
......@@ -225,6 +253,14 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin
if err != nil {
return err
}
var cpLevel int
var cpUserAvatar string
var cpEntryEffect bool
if cp, _ := rpc.GetUserCpEntryEffect(model, userId); cp != nil {
cpLevel = cp.CpLevel
cpUserAvatar = cp.CpUserAvatar
cpEntryEffect = cp.CpEntryEffect
}
r := UserParam{
Nick: user.Nick,
UserAvatar: user.Avatar,
......@@ -236,7 +272,27 @@ func (s *GroupService) GroupIn(userId uint64, externalId string, groupUuid strin
RidReceiverAvatar: properties[rides[userId]].ReceiverAvatar,
NobleLevel: nobleLevel,
Svip: rpc.CopySimpleSvip(svip),
CpLevel: cpLevel,
CpUserAvatar: cpUserAvatar,
}
rideId = r.RideId
// 进场特效类型
var entryEffectType int // 进场特效类型 1: CP 2:神秘人 3:贵族 4:vip ,顺序从小到大
if r.IsVip {
entryEffectType = 4
}
if r.NobleLevel > 0 {
entryEffectType = 3
}
for _, v := range r.Svip.Privileges {
if len(v.MysteryCode) > 0 {
entryEffectType = 2
}
}
if cpEntryEffect {
entryEffectType = 1
}
r.EntryEffectType = entryEffectType
buf, err := json.Marshal(r)
if err == nil {
......@@ -268,6 +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)
return channelId, token, nil
}
}
......@@ -359,13 +416,14 @@ func (s *GroupService) RemoveZombie(model *domain.Model, groupId string) (string
//离开房间
func (s *GroupService) GroupLeave(userId uint64, externalId string, groupId string) error {
model := domain.CreateModelContext(s.svc.MyContext)
// check cp麦位置
group_mic_s.NewGroupPowerService(s.svc.MyContext).CheckCpLeaveMic(groupId, userId)
_, err := group_m.RoomLivingLeave(model, userId, externalId, groupId)
return err
}
//踢人
func (s *GroupService) GroupKick(groupUuid string, userId uint64, userExternalId string, userNick string, avatar string, beKickUserId uint64, beKickExternalId string, beKickUserNick string, beKickUserAvatar string) error {
func (s *GroupService) GroupKick(groupUuid string, userId uint64, userExternalId string, userNick string, avatar string, beKickUserId uint64, beKickExternalId string, beKickUserNick string, beKickUserAvatar, lang string) error {
return s.svc.Transactional(func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
//木有model层给我,直接server怼了
......@@ -378,7 +436,7 @@ func (s *GroupService) GroupKick(groupUuid string, userId uint64, userExternalId
}
//超级管理人,无敌状态
if flag, err := user_m.IsSuperManager(model, userId); err != nil {
if flag, err := user_m.IsSuperManagerV2(model, userId, beKickUserId); err != nil {
return err
} else if !flag {
//判断权限
......@@ -389,7 +447,8 @@ func (s *GroupService) GroupKick(groupUuid string, userId uint64, userExternalId
if flag, err := noble_m.CheckNobleLevel(model.Db, beKickUserId, 5); err != nil {
return err
} else if flag {
return bizerr.NobleNoKickLevel5
return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_KICK_NOBLE_5, lang, bizerr.NobleNoKickOverLevel5))
//return bizerr.NobleNoKickLevel5
}
}
//踢人10分钟
......@@ -445,3 +504,126 @@ func (s *GroupService) GroupClearScreenByMgr(groupId string, userId uint64) erro
signal_s.SendSignalMsg(model, groupId, systemMsg, false)
return nil
}
func dealActDataAfterEnterRoom(myContext *mycontext.MyContext, userId, rideId uint64, roomId int64) {
defer utils.CheckGoPanic()
if rideId == 1261 {
// 处理活动数据
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,13 +28,13 @@ 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)
// 1. 去掉非群管理者
roles, _, err := group_m.GetRolesInGroup(model, groupId)
if err != nil {
return err
model.Log.Errorf("GroupSupportList groupId:%v, uids:%v, err:%v", groupId, uids, err)
return nil, nil, err
}
userIds := make([]uint64, 0)
for _, i := range uids {
......@@ -40,13 +47,13 @@ func (s *GroupService) GroupSupportList(groupId string, uids []uint64) ([]uint64
}
// 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
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 {
......@@ -59,7 +66,8 @@ func (s *GroupService) GroupSupportList(groupId string, uids []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
}
passed := true
......@@ -82,25 +90,95 @@ func (s *GroupService) GroupSupportList(groupId string, uids []uint64) ([]uint64
}
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
}
//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
......@@ -72,6 +74,9 @@ APP_CERTIFICATE=ff29c100a613433db82324e8411eabc8
CUSTOMER_KEY=6b132c0ff7164560a2bc53fda06ea85a
CUSTOMER_SECRET=eedad2cd16d24834990d5450ace9f1ce
CALLBACK_SECRET=n_ZizS_N8
[TRTC]
APP_ID=1400548270
APP_CERTIFICATE=321bd60f73096b059c7350f1cd97d51028850b34fa58c5c0d26bb4a19e783de8
[CHECKOUT]
AUTHORIZATION=sk_test_9b5e771c-5a3f-4a8d-a4da-31b19bd43d83
URL=https://api.sandbox.checkout.com/hosted-payments
......@@ -107,6 +112,8 @@ USER_LEVEL=http://test.chathot.me/action/activityhtml/hiloUserLevel/index.html
GROUP_SUPPORT=http://test.chathot.me/action/activityhtml/21_12_06/page.html
LUCKY_WHEEL=https://h5.whoisamy.shop/action/activityhtml/21_12_30/page.html
NOBLE_BUY_IOS=https://h5.whoisamy.shop/action/hiloHtml/lxt_h5/page.html
AGENT_SHARE_URL=
AGENT_SHARE_ICON=
[GROUPIM]
MSG_SORT_EXPIRE=43200
MSG_SORT_SNAP=300
......
......@@ -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,6 +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使用此权限
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{}) // 已经加入了其它国家势力
......@@ -101,6 +102,8 @@ var (
//贵族
NobleNoMicSpeechCloseLevel5 = myerr.NewBusinessCode(21001, "Can't mute the King", myerr.BusinessData{}) //无法禁言贵族5
NobleNoKickLevel5 = myerr.NewBusinessCode(21002, "Can't kick the King", myerr.BusinessData{}) //无法禁言贵族5
NobleNoMicSpeechCloseOverLevel5 = myerr.NewBusinessCode(21003, "Unable to mute VIP5 and VIP6", myerr.BusinessData{}) //无法禁言贵族5、6
NobleNoKickOverLevel5 = myerr.NewBusinessCode(21004, "Unable to kick out VIP5 and VIP6", myerr.BusinessData{}) //无法踢出贵族5、6
// 超级管理人
OfficialStaffLimit = myerr.NewBusinessCode(22001, "Operation failed", myerr.BusinessData{})
......
ALTER TABLE hilo.group_medal ADD expire_at DATETIME DEFAULT null NULL COMMENT '过期时间';
CREATE INDEX expire_at USING BTREE ON hilo.group_medal (expire_at);
ALTER TABLE hilo.res_medal ADD attr_type TINYINT UNSIGNED DEFAULT 1 NOT NULL COMMENT '勋章类型1.个人2.房间';
update res_medal set attr_type = 2 where name like '%房间%';
update res_medal set attr_type = 2 where id in (select res_medal_id from group_medal);
\ No newline at end of file
CREATE TABLE `act_family_month_rank_log` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`period` varchar(20) NOT NULL DEFAULT '' COMMENT '月份',
`family_id` bigint unsigned NOT NULL COMMENT '家族id',
`rank_family` int unsigned NOT NULL DEFAULT '0' COMMENT '家族排名',
`rank_user` int unsigned NOT NULL DEFAULT '0' COMMENT '用户在家族中的家族排名',
`user_id` bigint unsigned NOT NULL COMMENT 'id',
`award` varchar(500) NOT NULL DEFAULT '' COMMENT '获得的奖励',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `period` (`period`,`family_id`,`rank_user`),
KEY `user_idx` (`user_id`) USING BTREE,
KEY `created_time` (`created_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='家族月度排行发奖日志';
ALTER TABLE hilo.act_family_month_rank_log ADD area TINYINT DEFAULT 0 NOT NULL COMMENT '区域1.阿语区2.非阿语区';
-CREATE TABLE `group_trtc` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`im_group_id` char(32) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `im_group_id` (`im_group_id`),
KEY `created_time` (`created_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='使用trtc的群组';
CREATE TABLE `group_im` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`provider` int NOT NULL COMMENT '厂商类型0.声网1.腾讯trtc',
`prob` bigint unsigned NOT NULL COMMENT '概率',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `created_time` (`created_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='房间im厂商选用概率配置';
INSERT INTO hilo.group_im (`provider`, `prob`)
VALUES (0, 1000),
(1, 1000);
CREATE TABLE `group_im_log` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`im_group_id` char(32) COLLATE utf8mb4_unicode_ci NOT NULL,
`provider` int NOT NULL COMMENT '厂商类型0.声网1.腾讯trtc',
`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `im_group_id_idx` (`im_group_id`) USING BTREE,
KEY `created_time_idx` (`created_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='房间im提供商切换log';
\ No newline at end of file
[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
......@@ -72,6 +74,9 @@ APP_ID=6291d069123642d9929a49c734c50719
APP_CERTIFICATE=d5de40350aa54e60bcdce90c71e9598a
CUSTOMER_KEY=6b132c0ff7164560a2bc53fda06ea85a
CUSTOMER_SECRET=eedad2cd16d24834990d5450ace9f1ce
[TRTC]
APP_ID=40000066
APP_CERTIFICATE=3ab68ea5bddc8774d90b8c764ae71188914bd5fd06f30b28790c51e44ca7885c
[CHECKOUT]
AUTHORIZATION=sk_fca6e213-b7df-4bd7-99f4-7c0a9f7c778c
URL=https://api.checkout.com/hosted-payments
......@@ -115,6 +120,8 @@ NOBLE_BUY_IOS=https://h5.whoisamy.shop/action/hiloHtml/lxt_h5/page.html
GUILD_DATA_URL=https://h5.whoisamy.shop/action/hiloHtml/22_10_18_app_data_coins/index.html
MGR_GUILD_DATA_URL=https://h5.whoisamy.shop/action/hiloHtml/22_10_18_app_data_coins/union.html
RANKING_PINK_DIAMOND_URL=https://h5.whoisamy.shop/action/activitiesPage/2022_10_17HiloLiveH5/index.html
AGENT_SHARE_URL=https://h5.chathot.me/action/hiloHtml/22_05_30_recharge/topup.html?external_id=
AGENT_SHARE_ICON=https://image.whoisamy.shop/hilo/resource/user_transfer1.png
[GROUPIM]
MSG_SORT_EXPIRE=1209600
MSG_SORT_SNAP=300
......
......@@ -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)
}
......@@ -3,9 +3,12 @@ package charge_r
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/config"
"github.com/gin-gonic/gin"
"hilo-group/domain/cache/user_c"
"hilo-group/domain/model/diamond_m"
"hilo-group/domain/service/diamond_s"
"hilo-group/myerr/bizerr"
"hilo-group/req"
"hilo-group/resp"
)
......@@ -30,12 +33,42 @@ func CanShareChargeLink(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
isDealer, err := diamond_m.IsDiamondDealer(model.DB(), userId)
if err != nil {
return myContext, err
}
if !isDealer {
return myContext, bizerr.InvalidParameter
}
// 家族限制检查
if err = diamond_s.NewDiamondService(myContext).CheckDealerTransferFamilyLimit(userId, toUser.ID, lang); err != nil {
myContext.Log.Errorf("CanShareChargeLink err:%v", err)
return myContext, err
}
type res struct {
ShareUrl string `json:"shareUrl"`
ShareIcon string `json:"shareIcon"`
RechargeUrl string `json:"rechargeUrl"`
}
// 安卓3.8.0版本有bug,这里暂时兼容
shareUrl := config.GetH5Config().AGENT_SHARE_URL
deviceType, major, minor, _, err := req.GetAppVersion(c)
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) {
shareUrl = shareUrl + myUser.ExternalId
}
}
rechargeUrl := config.GetH5Config().AGENT_SHARE_URL + myUser.ExternalId
resp.ResponseOk(c, nil)
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"
......@@ -774,10 +775,11 @@ func GroupPowerInfo(c *gin.Context) (*mycontext.MyContext, error) {
if grade.Grade != groupPower_e.GroupPowerGradeMax {
nextExp = groupPower_e.GroupPowerGradeExp[grade.Grade+1]
}
maxNum := group_power_s.GetGroupPowerMaxMemberNum(model, gpInfo.ID, grade.Grade)
info := &group_power_cv.GroupPower{
Id: gpInfo.ID, Name: gpInfo.Name, Nameplate: gpInfo.Nameplate, Declaration: gpInfo.Declaration, Icon: gpInfo.Icon,
Grade: grade.Grade, Exp: grade.Exp, NextExp: nextExp, GradeName: gpInfo.GradeName, GradeMedal: gpInfo.GradeMedal,
MemberNum: mysql.Num(total), MemberMax: mysql.Num(group_power_cv.GroupPowerGradePrivilegeNum[grade.Grade][0].Num),
MemberNum: mysql.Num(total), MemberMax: mysql.Num(maxNum),
}
if info.Icon != "" {
info.Icon = common.MakeFullUrl(info.Icon)
......@@ -819,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)
}
......@@ -977,8 +979,11 @@ func GroupPowerApplyJoin(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, myerr.WrapErr(err)
}
// Aoxi要求不能让这些人加入家族
banUserMap := map[uint64]bool{251: true, 1384611: true, 4223511: true, 4338751: true, 4339471: true, 4339541: true,
4354581: true, 6541: true, 23971: true}
var banUserIds = []uint64{251, 1384611, 4223511, 4338751, 4339471, 4339541, 4354581, 6541, 23971, 5191971, 5192161, 5192201, 5429011, 5429121, 5429191, 5687371, 6160461, 6185321, 6194741, 6315381}
var banUserMap = make(map[uint64]bool)
for _, id := range banUserIds {
banUserMap[id] = true
}
if _, ok := banUserMap[userId]; ok {
return myContext, bizerr.GroupPowerCannotJoin
}
......@@ -1007,7 +1012,8 @@ func GroupPowerApplyJoin(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil {
return myContext, myerr.WrapErr(err)
}
maxNum := group_power_cv.GroupPowerGradePrivilegeNum[gpInfo.Grade][0].Num
maxNum := group_power_s.GetGroupPowerMaxMemberNum(model, familyId, gpInfo.Grade)
//maxNum := group_power_cv.GroupPowerGradePrivilegeNum[gpInfo.Grade][0].Num
if nowNum+1 > int64(maxNum) {
return myContext, bizerr.GroupPowerMemberMax
}
......@@ -1025,7 +1031,8 @@ func GroupPowerApplyJoin(c *gin.Context) (*mycontext.MyContext, error) {
} else {
for _, v := range mgrList {
// 发小助手通知用户
msg.SendLittleAssistantMsg(model, v, msg_e.GroupPowerApplyJoinMsg, "", "", "", "", "")
msg.SendLittleAssistantMsg(model, v, 0, "", "", "", "", "")
//msg.SendLittleAssistantMsg(model, v, msg_e.GroupPowerApplyJoinMsg, "", "", "", "", "")
}
}
......@@ -1097,6 +1104,8 @@ func GroupPowerApplyPass(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
resp.ResponseOk(c, nil)
// 家族小助手通知
go group_power_s.CheckoutSendMsgToMgr(myContext, myGroupPUser.GroupPowerId)
return myContext, nil
}
// 判断家族是否满人了
......@@ -1109,7 +1118,8 @@ func GroupPowerApplyPass(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
grade := gradeM[apply.GroupPowerId]
maxNum := group_power_cv.GroupPowerGradePrivilegeNum[grade.Grade][0].Num
//maxNum := group_power_cv.GroupPowerGradePrivilegeNum[grade.Grade][0].Num
maxNum := group_power_s.GetGroupPowerMaxMemberNum(model, apply.GroupPowerId, grade.Grade)
if int(nowNum+1) > maxNum {
return myContext, bizerr.GroupPowerMemberMax
}
......@@ -1149,10 +1159,12 @@ func GroupPowerApplyPass(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
// 发小助手通知用户
err = msg.SendLittleAssistantMsg(model, apply.UserId, msg_e.GroupPowerWelcomeJoin, "", "", "", "", "")
if err != nil {
model.Log.Errorf("GroupPowerApplyPass msg err:%v", err)
}
//err = msg.SendLittleAssistantMsg(model, apply.UserId, msg_e.GroupPowerWelcomeJoin, "", "", "", "", "")
//if err != nil {
// model.Log.Errorf("GroupPowerApplyPass msg err:%v", err)
//}
// 家族小助手通知
go group_power_s.CheckoutSendMsgToMgr(myContext, myGroupPUser.GroupPowerId)
resp.ResponseOk(c, nil)
return myContext, nil
......@@ -1223,6 +1235,41 @@ func GroupPowerApplyList(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, nil
}
// @Tags 家族
// @Summary 申请人数
// @Success 200 {object} int
// @Router /v1/groupPower/apply/count [get]
func GroupPowerApplyCount(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, err := req.GetUserId(c)
if err != nil {
return myContext, err
}
model := domain.CreateModelContext(myContext)
// 判断是否加入了家族
gpU := groupPower_m.GroupPowerUser{UserId: userId}
myGroupPUser, err := gpU.GetGroupPowerUser(model)
if err != nil {
return myContext, err
}
// 操作者是否加入了家族,是否有操作权限
if myGroupPUser == nil || myGroupPUser.ID == 0 {
return myContext, bizerr.GroupPowerHaveNoJoin
}
if myGroupPUser.Role == 0 || myGroupPUser.Role == groupPower_e.GroupPowerUserRoleUser {
return myContext, bizerr.GroupPowerHaveNoPower
}
// 申请人数
cnt, err := groupPower_m.CountGroupPowerApply(model, myGroupPUser.GroupPowerId, 0)
if err != nil {
return myContext, err
}
resp.ResponseOk(c, cnt)
return myContext, nil
}
// @Tags 家族
// @Summary 退出/踢出家族
// @Param type formData int true "1.自己退出,2.踢人"
......@@ -1510,7 +1557,7 @@ func GroupPowerSetInfo(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, res_m.GetErrByLanguage(model.Db, common.MSG_ID_SET_FAMILY_NAMEPL, lang, bizerr.GroupPowerChangeNameplate)
}
// 检查铭牌长度和唯一性
if len(para.Nameplate) > 6 {
if len(para.Nameplate) > groupPower_e.LongestNameplate {
return myContext, bizerr.GroupPowerHaveTooLong
}
if groupPower_m.IsExistsNameplate(model, para.Nameplate) {
......@@ -1552,7 +1599,6 @@ func GroupPowerSetInfo(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil {
return myContext, myerr.WrapErr(err)
}
groupPowerGrade, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{gp.ID})
gradeM, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{gp.ID})
if err != nil {
return myContext, err
......@@ -1562,10 +1608,11 @@ func GroupPowerSetInfo(c *gin.Context) (*mycontext.MyContext, error) {
if grade.Grade != groupPower_e.GroupPowerGradeMax {
nextExp = groupPower_e.GroupPowerGradeExp[grade.Grade+1]
}
maxNum := group_power_s.GetGroupPowerMaxMemberNum(model, gpInfo.ID, grade.Grade)
info := &group_power_cv.GroupPower{
Id: gpInfo.ID, Name: gpInfo.Name, Nameplate: gpInfo.Nameplate, Declaration: gpInfo.Declaration, Icon: gpInfo.Icon,
Grade: grade.Grade, Exp: grade.Exp, NextExp: nextExp, GradeName: gpInfo.GradeName, GradeMedal: gpInfo.GradeMedal,
MemberNum: mysql.Num(total), MemberMax: mysql.Num(group_power_cv.GroupPowerGradePrivilegeNum[groupPowerGrade[gp.ID].Grade][0].Num),
MemberNum: mysql.Num(total), MemberMax: mysql.Num(maxNum),
}
if info.Icon != "" {
info.Icon = common.MakeFullUrl(info.Icon)
......
......@@ -10,8 +10,10 @@ 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"
"hilo-group/myerr/bizerr"
"hilo-group/req"
"hilo-group/resp"
......@@ -46,72 +48,95 @@ func GroupPowerRank(c *gin.Context) (*mycontext.MyContext, error) {
beginDate, endDate = now.BeginningOfMonth().Format("2006-01-02"), now.EndOfMonth().Format("2006-01-02")
}
var model = domain.CreateModelContext(myContext)
rank, err := groupPower_m.GetGroupPowerExpRank(model, beginDate, endDate, 30)
response, err := group_power_s.GetGroupPowerRankResp(model, beginDate, endDate, userId, 0, 0)
if err != nil {
return myContext, err
}
var ids []mysql.ID
for _, g := range rank {
ids = append(ids, g.GroupPowerId)
resp.ResponseOk(c, response)
return myContext, nil
}
// @Tags 国家势力
// @Summary 家族榜单-活动
// @Success 200 {object} group_power_cv.CvGroupPowerRankMontAct
// @Router /v1/h5/groupPower/rank/month [get]
func GroupPowerMonthRankAct(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, err := req.GetUserId(c)
if err != nil {
return myContext, err
}
response := group_power_cv.CvGroupPowerRank{}
var model = domain.CreateModelContext(myContext)
// 国家区域
var area int
// 我的家族
myGroupPower, err := groupPower_m.GetGroupPowerUserOrNil(model, userId)
if err != nil {
return myContext, err
}
if myGroupPower != nil {
ids = append(ids, myGroupPower.GroupPowerId)
if myGroupPower != nil && myGroupPower.GroupPowerId > 0 {
//获取势力主
mgrUserId, err := groupPower_m.GetGroupPowerMgr(model, myGroupPower.GroupPowerId)
if err != nil {
return myContext, err
}
grades, err := groupPower_m.MGetGroupPowerGrade(model, ids)
_, area, err = user_m.GetUserCountryArea(model, mgrUserId)
if err != nil {
model.Log.Errorf("GroupPowerMonthRankAct 获取国家资源错误 userId:%d, err:%v", userId, err)
return myContext, err
}
groupPowers, err := groupPower_m.MGetGroupPowerInfoMap(model, ids)
}
if area == 0 {
_, area, err = user_m.GetUserCountryArea(model, userId)
if err != nil {
model.Log.Errorf("GroupPowerMonthRankAct 获取国家资源错误 userId:%d, err:%v", userId, err)
return myContext, err
}
if myGroupPower != nil {
myGroupPowerRank, err := groupPower_m.GetMyGroupPowerExpRank(model, beginDate, endDate, myGroupPower.GroupPowerId)
}
// 这个月
beginDate, endDate := now.BeginningOfMonth().Format(utils.DATE_FORMAT), now.EndOfMonth().Format(utils.DATE_FORMAT)
response, err := GroupPowerMonthRankActByMonth(model, userId, beginDate, endDate, time.Now().Format(utils.COMPACT_MONTH_FORMAT), area)
if err != nil {
return myContext, err
}
response.MyGroupPower = &group_power_cv.CvGroupPowerRankData{
CvGroupPowerBase: group_power_cv.CvGroupPowerBase{
Id: myGroupPower.GroupPowerId,
Icon: groupPowers[myGroupPower.GroupPowerId].Icon,
Name: groupPowers[myGroupPower.GroupPowerId].Name,
Nameplate: groupPowers[myGroupPower.GroupPowerId].Nameplate,
},
CvGroupPowerGrade: group_power_cv.CvGroupPowerGrade{
Grade: grades[myGroupPower.GroupPowerId].Grade,
Exp: myGroupPowerRank.Exp,
},
Rank: 0,
// 上月
lastMonthStart := utils.GetLastMonthStart(time.Now())
lastTime := now.New(lastMonthStart)
beginDateLast, endDateLast := lastTime.BeginningOfMonth().Format(utils.DATE_FORMAT), lastTime.EndOfMonth().Format(utils.DATE_FORMAT)
responseLast, err := GroupPowerMonthRankActByMonth(model, userId, beginDateLast, endDateLast, lastMonthStart.Format(utils.COMPACT_MONTH_FORMAT), area)
if err != nil {
return myContext, err
}
res := &group_power_cv.CvGroupPowerRankMontAct{
MyGroupPower: response.MyGroupPower,
Items: response.Items,
MyGroupPowerLast: responseLast.MyGroupPower,
ItemsLast: responseLast.Items,
LeftSecond: now.EndOfMonth().Unix() - time.Now().Unix(),
}
resp.ResponseOk(c, res)
return myContext, nil
}
func GroupPowerMonthRankActByMonth(model *domain.Model, userId uint64, beginDate, endDate, month string, area int) (response group_power_cv.CvGroupPowerRank, err error) {
response, err = group_power_s.GetGroupPowerRankResp(model, beginDate, endDate, userId, groupPower_e.GroupPowerUserHas, area)
if err != nil {
return response, err
}
for _, v := range rank {
if response.MyGroupPower != nil && v.GroupPowerId == response.MyGroupPower.Id {
response.MyGroupPower.Rank = v.Rank
if response.MyGroupPower != nil {
response.MyGroupPower.StarList, err = group_power_s.GetGroupPowerStar(model, response.MyGroupPower.Id, groupPower_e.GroupPowerStarTypeFamous, 0, 10, month)
}
response.Items = append(response.Items, group_power_cv.CvGroupPowerRankData{
CvGroupPowerBase: group_power_cv.CvGroupPowerBase{
Id: v.GroupPowerId,
Icon: groupPowers[v.GroupPowerId].Icon,
Name: groupPowers[v.GroupPowerId].Name,
Nameplate: groupPowers[v.GroupPowerId].Nameplate,
},
CvGroupPowerGrade: group_power_cv.CvGroupPowerGrade{
Grade: grades[v.GroupPowerId].Grade,
Exp: v.Exp,
},
Rank: v.Rank,
})
if err != nil {
return response, err
}
if response.MyGroupPower != nil && response.MyGroupPower.Rank == 0 {
response.MyGroupPower.Rank = 31 // 客户端统一显示30+
for i, v := range response.Items {
response.Items[i].StarList, err = group_power_s.GetGroupPowerStar(model, v.Id, groupPower_e.GroupPowerStarTypeFamous, 0, 10, month)
if err != nil {
return response, err
}
resp.ResponseOk(c, response)
return myContext, nil
}
return response, nil
}
// @Tags 国家势力
......@@ -135,7 +160,7 @@ func GroupPowerRankTop(c *gin.Context) (*mycontext.MyContext, error) {
beginDate, endDate = now.BeginningOfMonth().Format("2006-01-02"), now.EndOfMonth().Format("2006-01-02")
}
var model = domain.CreateModelContext(myContext)
rank, err := groupPower_m.GetGroupPowerExpRank(model, beginDate, endDate, 3)
rank, err := groupPower_m.GetGroupPowerExpRank(model, beginDate, endDate, 3, 0, 0)
if err != nil {
return myContext, err
}
......@@ -201,38 +226,12 @@ func GroupPowerStar(c *gin.Context) (*mycontext.MyContext, error) {
if param.PageSize <= 0 {
param.PageSize = 30
}
var model = domain.CreateModelContext(myContext)
offset, limit := (param.PageIndex-1)*param.PageSize, param.PageSize
rank, err := groupPower_m.GetGroupPowerMonthStarRank(model, param.GroupPowerId, param.Type, offset, limit)
var model = domain.CreateModelContext(myContext)
response, err := group_power_s.GetGroupPowerStar(model, param.GroupPowerId, param.Type, offset, limit, time.Now().Format(utils.COMPACT_MONTH_FORMAT))
if err != nil {
return myContext, err
}
var response []group_power_cv.CvGroupPowerStarData
var userIds []mysql.ID
for _, row := range rank {
userIds = append(userIds, row.UserId)
}
users, err := user_m.GetUserMapByIds(model, userIds)
for _, row := range rank {
user := users[row.UserId]
score := row.Score
if param.Type == groupPower_e.GroupPowerStarTypeActive {
score = score / 60
}
if score <= 0 {
continue
}
response = append(response, group_power_cv.CvGroupPowerStarData{
User: user_cv.CvUserTiny{
Id: user.ID,
ExternalId: user.ExternalId,
Code: user.Code,
Nick: user.Nick,
Avatar: user.Avatar,
},
Score: score,
})
}
resp.ResponsePageBaseOk(c, response, 0, false)
return myContext, nil
}
......@@ -266,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 {
......@@ -48,7 +54,8 @@ func MGetGroupPowers(c *gin.Context) (*mycontext.MyContext, error) {
var memberMax mysql.Num
grade := groupPowerGrade[groupPowerId].Grade
if grade >= groupPower_e.GroupPowerGrade0 && grade <= groupPower_e.GroupPowerGradeMax {
memberMax = mysql.Num(group_power_cv.GroupPowerGradePrivilegeNum[groupPowerGrade[groupPowerId].Grade][0].Num)
//memberMax = mysql.Num(group_power_cv.GroupPowerGradePrivilegeNum[groupPowerGrade[groupPowerId].Grade][0].Num)
memberMax = mysql.Num(group_power_s.GetGroupPowerMaxMemberNum(model, groupPowerId, grade))
}
memberNum := mysql.Num(len(groupPowerUsers[groupPowerId]))
if memberNum > memberMax {
......@@ -91,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
}
......@@ -38,6 +38,7 @@ import (
"hilo-group/myerr/bizerr"
"hilo-group/req"
"hilo-group/resp"
"net/url"
"sort"
"strconv"
"strings"
......@@ -210,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)
......@@ -373,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 为必填项")
......@@ -406,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
......@@ -456,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
}
......@@ -502,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
......@@ -544,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)
......@@ -553,11 +557,12 @@ 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).
Order("m.id desc").
Where("(expire_at is null or expire_at > ?)", time.Now().Format(utils.DATETIME_FORMAT)).
Order("res_medal.sort").
Find(&resMedals).Error
if err == nil {
for _, r := range resMedals {
......@@ -567,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 {
......@@ -591,20 +597,52 @@ func GetRoomInfo(c *gin.Context) (*mycontext.MyContext, error) {
result.Banners = append(result.Banners, group_cv.BannerElement{
H5Url: i.Url,
BannerUrl: i.Image,
ActionUrl: i.Url, // 支持direction=1横屏
})
}
} 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.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 {
entryEffectType = 4
}
if user.Noble.Level > 0 {
entryEffectType = 3
}
for _, v := range user.Svip.Privileges {
if len(v.MysteryCode) > 0 {
entryEffectType = 2
}
}
}
if cpEntryEffect {
entryEffectType = 1
}
result.EntryEffectType = entryEffectType
model.Log.Infof("GetRoomInfo cost 8:%v", time.Now().Sub(start).Seconds())
resp.ResponseOk(c, result)
return myContext, nil
......@@ -750,6 +788,8 @@ type GroupBanner struct {
BannerUrl string `json:"bannerUrl"`
//群主Id
GroupId string `json:"groupId"`
//统跳地址 http开头:web页面,query参数direction(0:竖屏 1:横屏); hilo开头:原生页面
ActionUrl string `json:"actionUrl"`
}
// @Tags 群组
......@@ -810,7 +850,9 @@ func GroupBannerList(c *gin.Context) (*mycontext.MyContext, error) {
model.Log.Infof("CompareVersion appVersion:%v,auditVersion:%v,allow:%v,err:%v,skip top recharge", appVersion, vc.AuditVersion, allow, err)
continue
}
if !allow && (v.ID == 2301 || v.ID == 4711 || v.ID == 2321 || v.ID == 5341 || v.ID == 5331) {
// 版本控制
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
}
......@@ -825,11 +867,27 @@ func GroupBannerList(c *gin.Context) (*mycontext.MyContext, error) {
if v.Area == 3 && !utils.IsInStringList(country, v.CountryList) {
continue
}
actionUrl := v.Url
if uri, err := url.Parse(actionUrl); err == nil {
query := uri.RawQuery
queryArr := strings.Split(query, "&")
v := url.Values{}
if len(queryArr) > 0 {
for _, q := range queryArr {
if arr := strings.Split(q, "="); len(arr) == 2 {
v.Add(arr[0], arr[1])
}
}
}
//v.Add("direction", "1") // 横屏的需要这样
uri.RawQuery = v.Encode()
actionUrl = uri.String()
}
groupBanners = append(groupBanners, GroupBanner{
H5Url: v.Url,
BannerUrl: v.Image,
GroupId: groupMap[v.GroupCode],
ActionUrl: actionUrl,
})
}
resp.ResponseOk(c, groupBanners)
......@@ -839,6 +897,7 @@ func GroupBannerList(c *gin.Context) (*mycontext.MyContext, error) {
type RoomBanner struct {
H5Url string `json:"h5Url"` // h5链接
BannerUrl string `json:"bannerUrl"` // 图片地址
ActionUrl string `json:"actionUrl"` // 统跳地址 http开头:web页面,query参数direction(0:竖屏 1:横屏); hilo开头:原生页面
}
// @Tags 群组
......@@ -891,6 +950,7 @@ func RoomBannerList(c *gin.Context) (*mycontext.MyContext, error) {
result = append(result, RoomBanner{
H5Url: i.Url,
BannerUrl: i.Image,
ActionUrl: i.Url,
})
}
resp.ResponseOk(c, result)
......@@ -1170,7 +1230,10 @@ func GroupMedalAll(c *gin.Context) (*mycontext.MyContext, error) {
}
resMedals := []res_m.ResMedal{}
if 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).Order("m.id desc").Find(&resMedals).Error; err != nil {
if 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).
Where("(expire_at is null or expire_at > ?)", time.Now().Format(utils.DATETIME_FORMAT)).
Order("res_medal.sort").Find(&resMedals).Error; err != nil {
return myContext, err
}
......
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"
......@@ -15,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"
......@@ -47,6 +51,15 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
start := time.Now()
myContext := mycontext.CreateMyContext(c.Keys)
// ios 贵族6不兼容需要强更
deviceType := c.GetHeader(mycontext.DEVICETYPE)
appVersion := c.GetHeader(mycontext.APP_VERSION)
if deviceType == "iOS" {
if low, _ := utils.CompareVersion(appVersion, "< 3.7.0"); low {
return myContext, bizerr.UpgradeRequired
}
}
pageSize, err := strconv.Atoi(c.Query("pageSize"))
if err != nil || pageSize <= 0 {
pageSize = 10
......@@ -62,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
......@@ -80,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)
......@@ -89,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
......@@ -105,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
}
......@@ -137,23 +151,17 @@ 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 += " |"
myArea := fmt.Sprintf("%d", area)
// 国家区域信息
resAreaMap, err := res_c.GetCountryAreaMap(model)
if err != nil {
return myContext, err
}
areaScore := make(map[string]int)
countryScore := make(map[string]int)
if len(myCountry) > 0 {
......@@ -163,18 +171,23 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
} else {
countryScore[i] = 0
}
if cArea, ok := resAreaMap[groups[i].Country]; ok {
if myArea == cArea {
areaScore[i] = 1
} else {
areaScore[i] = 0
}
}
}
}
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 {
......@@ -192,6 +205,15 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
} else if countryScore[gi] < countryScore[gj] {
return false
}
// 不是我的国家,按区域排序
if countryScore[gi] == 0 {
if areaScore[gi] > areaScore[gj] {
return true
} else if areaScore[gi] < areaScore[gj] {
return false
}
}
// 2、按麦上人数多少排序
if micGroupNum[gi] > micGroupNum[gj] {
return true
......@@ -221,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)
......@@ -263,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 {
......@@ -296,6 +312,16 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
}
medals := make([]medal_cv.PicElement, 0)
// 补上房间流水勋章
var pe *medal_cv.PicElement
_, pe, err = medal_cv.GetGroupConsumeMedal(model, i.ImGroupId)
if err != nil {
model.Log.Infof("GetPopularGroups: GetGroupConsumeMedal: %s", err.Error())
} else if pe != nil {
medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl})
}
if m, ok := groupMedals[i.ImGroupId]; ok {
for _, j := range m {
mId := uint32(j)
......@@ -307,15 +333,6 @@ func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
}
}
// 补上房间流水勋章
var pe *medal_cv.PicElement
_, pe, err = medal_cv.GetGroupConsumeMedal(model, i.ImGroupId)
if err != nil {
model.Log.Infof("GetPopularGroups: 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 := ""
......@@ -361,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
}
......@@ -429,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)
}
// 获取最新群组列表
......@@ -662,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 {
......@@ -675,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
}
......@@ -755,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)
......@@ -786,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 {
......@@ -826,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 {
......@@ -847,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 {
......@@ -902,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) {
......@@ -920,8 +943,8 @@ 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],
result.Members = append(result.Members, group_cv.GroupVisitorsDetail{
CvGroupMember: user_cv.CvUserExtendToCvGroupMember(userExtends[u]),
Role: roles[u],
OnlineStatus: statusMap[users[u].ExternalId],
InRoom: inRoom,
......@@ -929,6 +952,165 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
}
}
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
}
......@@ -1193,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)
......@@ -1406,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
}
roomVisitCount, err := room_c.GetAllRoomVisitCount()
model := domain.CreateModelContext(myContext)
// 从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)
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
}
groups[v.ImGroupId] = &noPwdGroups[i]
visitCount[v.ImGroupId] = vc
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
}
} 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
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
}
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})
}
return groups, banCount, visitCount, nil
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],
})
}
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
}
}
......@@ -600,6 +601,8 @@ func GroupMicIn(c *gin.Context) (*mycontext.MyContext, error) {
} else {
resp.ResponseOk(c, nil)
}
// check cp 麦位置
go group_mic_s.NewGroupPowerService(myContext).CheckCpOnMic(groupUuid)
return myContext, nil
}
......@@ -699,6 +702,8 @@ func GroupMicLeave(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
}
// check cp麦位置
group_mic_s.NewGroupPowerService(myContext).CheckCpLeaveMic(groupId, userId)
if err := group_mic_s.NewGroupPowerService(myContext).GroupMicLeave(groupId, i, userId, externalId); err != nil {
return myContext, err
......@@ -832,13 +837,18 @@ func GroupMicSpeechClose(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
_, lang, err := req.GetUserIdLang(c, myContext)
if err != nil {
return myContext, err
}
model := domain.CreateModelContext(myContext)
groupUuid, err = group_m.ToImGroupId(model, groupUuid)
if err != nil {
return myContext, err
}
if err := group_mic_s.NewGroupPowerService(myContext).GroupMicSpeechClose(userId, externalId, groupUuid, i); err != nil {
if err := group_mic_s.NewGroupPowerService(myContext).GroupMicSpeechClose(userId, externalId, groupUuid, lang, i); err != nil {
return myContext, err
}
resp.ResponseOk(c, nil)
......
......@@ -14,6 +14,7 @@ import (
"git.hilo.cn/hilo-common/utils"
"github.com/gin-gonic/gin"
uuid "github.com/satori/go.uuid"
"github.com/spf13/cast"
"gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/_const/enum/group_e"
......@@ -447,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
......@@ -876,12 +877,19 @@ func SearchGroup(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
if owner.Status == user_e.UserStatusFrozen {
if flag, _ := user_m.IsSuperManager(model, myUserId); !flag {
if flag, _ := user_m.IsSuperManagerV2(model, myUserId, owner.ID); !flag {
// 被封锁的用户,除了超管账户,其它用户搜索他的群组和个人ID,搜索结果为空
resp.ResponsePageOk(c, result, uint(total), 1)
return myContext, nil
}
}
if group_m.IsHiddenGroupBy(model, g.ImGroupId) {
if flag, _ := user_m.IsSuperManagerV2(model, myUserId, g.Owner); !flag {
// 被隐藏的用户,除了超管账户,其它用户搜索他的群组和个人ID,搜索结果为空
resp.ResponsePageOk(c, result, uint(total), 1)
return myContext, nil
}
}
supportLevels, err := group_s.NewGroupService(myContext).GetWeekMaxSupportLevelMap()
if err != nil {
return myContext, err
......@@ -1230,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
......@@ -1716,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) {
......@@ -1730,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)
......@@ -1751,7 +1785,85 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
}
model.Log.Infof("GroupIn ip userId:%v,imGroupId:%v,ip:%v,imei:%v", userId, groupId, ip, imei)
if channelId, token, err := group_s.NewGroupService(myContext).GroupIn(userId, externalId, groupId, password, imei, ip); err != nil {
provider := group_e.GroupProvider_SW
if group_m.IsUseTRTC(model, groupId) {
provider = group_e.GroupProvider_TRTC
//total := int64(11000)
//if !config.AppIsRelease() {
// total = 30
//}
//if group_m.CountTRTC(model) > total {
// roomUser, err := group_m.GetRoomOnlineUser(myContext, groupId)
// if err == nil && roomUser.Total == 0 {
// if err := group_m.DeleteTRTC(model, groupId); err == nil {
// provider = group_e.GroupProvider_SW
// }
// }
//}
} else {
// 增加trtc房间
//dayMaxCovertNum := int64(600)
//numKey := rediskey.GetConvertToTRTCNum()
//covertNum, err := redisCli.GetCacheInt64(numKey)
//if time.Now().Unix() > 1684810309 && time.Now().Unix() < 1684857600 && err == nil && covertNum <= dayMaxCovertNum {
// roomUser, err := group_m.GetRoomOnlineUser(myContext, groupId)
// if err == nil && roomUser.Total == 0 {
// newNum, err := redisCli.IncrNumExpire(numKey, 1, time.Hour*24)
// if err == nil && newNum <= dayMaxCovertNum {
// if err := group_m.InitTRTC(model, groupId); err != nil {
// return myContext, err
// }
// provider = group_e.GroupProvider_TRTC
// model.Log.Infof("auto shift trtc room groupId:%v,%+v-%v", groupId, roomUser, err)
// }
// }
//}
}
// 进房时判断要用哪个im
targetProvider := group_m.GetRandomImProvider(model)
if provider != targetProvider {
roomUser, err := group_m.GetRoomOnlineUser(myContext, groupId)
if err == nil && roomUser.Total == 0 { // 房间没人才做切换
switch provider {
case group_e.GroupProvider_SW: // 旧的是声网,切换成trtc
if err := group_m.InitTRTC(model, groupId); err != nil {
return myContext, err
}
case group_e.GroupProvider_TRTC: // 旧的是trtc,切换成声网
if err := group_m.DeleteTRTC(model, groupId); err != nil {
return myContext, err
}
}
// 切换
provider = targetProvider
// log
err = group_m.CreateGroupImLog(model, groupId, provider)
if err != nil {
model.Log.Errorf("CreateGroupImLog err:%v, imGroupId:%s, provider:%v", err, groupId, provider)
}
}
}
if provider == group_e.GroupProvider_TRTC {
// 版本升级提示,旧版本(3.6.0以下),提示升级
_, major, minor, _, err := req.GetAppVersion(c)
if err != nil {
return myContext, err
}
if (major < 3) || (major == 3 && minor < 6) {
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
} else {
// 加入房间缓存
......@@ -1759,14 +1871,15 @@ 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,
AgoraId: uint32(userId),
MicNumType: gi.MicNumType,
Provider: provider,
})
// v2.26及以后,客户端自己加TIM群,不再由服务器代加
......@@ -1784,10 +1897,10 @@ func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
}()
}
// 判断是否需要执行游戏逻辑
if enterType != "" && gameCode != "" {
traceId := c.Writer.Header().Get(mycontext.TRACEID)
if enterType != "" && (gameCode != "" || is1V1Robot == "1") {
traceId, _ := c.Get(mycontext.TRACEID)
token := c.Writer.Header().Get(mycontext.TOKEN)
err := game_c.SetAutoMathEnterRoom(userId, gi.ImGroupId, 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)
}
......@@ -1917,7 +2030,7 @@ func GroupKick(c *gin.Context) (*mycontext.MyContext, error) {
}
//beKickUserId, err := toUserId(beKickExternalId)
if err := group_s.NewGroupService(myContext).GroupKick(groupId, userId, externalId, nick, avatar, beKickUser.ID, beKickUser.ExternalId, beKickUser.Nick, beKickUser.Avatar); err != nil {
if err := group_s.NewGroupService(myContext).GroupKick(groupId, userId, externalId, nick, avatar, beKickUser.ID, beKickUser.ExternalId, beKickUser.Nick, beKickUser.Avatar, lang); err != nil {
return myContext, err
}
resp.ResponseOk(c, nil)
......
......@@ -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
......@@ -543,7 +545,7 @@ func AddGroupBlacklist(c *gin.Context) (*mycontext.MyContext, error) {
// 检查是否可以对svip6进行操作 optUserId:被操作的用户id
func CheckOptToSvip6(model *domain.Model, userId, optUserId uint64, lang string, privilegeId int) error {
// 是否超管
isM, err := user_m.IsSuperManager(model, userId)
isM, err := user_m.IsSuperManagerV2(model, userId, optUserId)
if err != nil {
return 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 {
......@@ -179,7 +187,7 @@ func GetSupportDetail(c *gin.Context) (*mycontext.MyContext, error) {
func TryAddSupporter(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
myUserId, err := req.GetUserId(c)
myUserId, lang, err := req.GetUserIdLang(c, myContext)
if err != nil {
return myContext, err
}
......@@ -222,7 +230,17 @@ func TryAddSupporter(c *gin.Context) (*mycontext.MyContext, error) {
if role != group_e.GROUP_MANAGER && role != group_e.GROUP_ADMIN {
return myContext, bizerr.NotManagerOrAdmin
}
// 判断财富等级必须要大于等于3级
wealthGrade, _, err := user_m.GetWealthGrade(model, userId)
if err != nil {
return myContext, err
}
if wealthGrade < 3 {
if msg, _ := res_m.GetResMultiTextBy(model.DB(), 187, lang); msg != nil { // 187:res_multi_text 财富等级为到8级
return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupSupportWealthLevel3.GetCode(), msg.Content, myerr.BusinessData{})
}
return myContext, bizerr.GroupSupportWealthLevel3
}
// 判断用户是否作为助手领取过奖励
sameImeiUsers, err := user_m.GetSameImeiMap(model, userId)
if err != nil {
......@@ -325,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 {
......@@ -356,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
}
......
package mic_r
import (
"git.hilo.cn/hilo-common/_const/enum/timezone_e"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/mysql"
......@@ -12,12 +13,14 @@ import (
type MGetUserOnMicSecondsReq struct {
Day string `form:"day" binding:"required"`
Ids []mysql.ID `form:"ids" binding:"required"`
Tz timezone_e.Timezone `form:"tz"`
}
// @Tags 麦位-内部
// @Summary 批量获取用户天上麦时长
// @Param day query string true "天 格式2006-001-02"
// @Param ids query string true "用户id,如:ids=1&ids=2&ids=3"
// @Param tz query string false "时区 0:北京时间(默认) 1:沙特时间"
// @Success 200 {object} map[uint64]uint32
// @Router /inner/mic/onMicSeconds [get]
func MGetUserOnMicSeconds(c *gin.Context) (*mycontext.MyContext, error) {
......@@ -27,7 +30,38 @@ func MGetUserOnMicSeconds(c *gin.Context) (*mycontext.MyContext, error) {
if err := c.ShouldBindQuery(&req); err != nil {
return myCtx, err
}
onMic, err := mic_m.MGetUserOnMicSeconds(model, req.Day, req.Ids)
onMic, err := mic_m.MGetUserOnMicSeconds(model, req.Day, req.Tz, req.Ids)
if err != nil {
return myCtx, err
}
response := onMic
resp.ResponseOk(c, response)
return myCtx, nil
}
type MGetUserOnMicSecondsRangeReq struct {
BeginDate string `form:"beginDate" binding:"required"`
EndDate string `form:"endDate" binding:"required"`
Ids []mysql.ID `form:"ids" binding:"required"`
Tz timezone_e.Timezone `form:"tz"`
}
// @Tags 麦位-内部
// @Summary 批量获取用户范围上麦时长
// @Param beginDate query string true "天 格式2006-001-02"
// @Param endDate query string true "天 格式2006-001-02"
// @Param ids query string true "用户id,如:ids=1&ids=2&ids=3"
// @Param tz query string false "时区 0:北京时间(默认) 1:沙特时间"
// @Success 200 {object} map[uint64]uint32
// @Router /inner/mic/onMicSeconds/range [get]
func MGetUserOnMicSecondsRange(c *gin.Context) (*mycontext.MyContext, error) {
myCtx := mycontext.CreateMyContext(c.Keys)
var model = domain.CreateModelContext(myCtx)
var req MGetUserOnMicSecondsRangeReq
if err := c.ShouldBindQuery(&req); err != nil {
return myCtx, err
}
onMic, err := mic_m.MGetUserOnMicSecondsRange(model, req.BeginDate, req.EndDate, req.Tz, req.Ids)
if err != nil {
return myCtx, 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"
......@@ -102,6 +103,12 @@ func LoggerHandle(c *gin.Context) {
c.Set(mycontext.APP_VERSION, appVersion)
c.Set(mycontext.URL, reqUri)
c.Set(mycontext.METHOD, method)
lang := header.Get(mycontext.LANGUAGE)
c.Set(mycontext.LANGUAGE, lang)
carrier := header.Get(mycontext.CARRIER)
c.Set(mycontext.CARRIER, carrier)
timezone := header.Get(mycontext.TIMEZONE)
c.Set(mycontext.TIMEZONE, timezone)
userId, _ := req.GetUserId(c)
......@@ -127,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))
......@@ -133,6 +134,7 @@ func InitRouter() *gin.Engine {
groupPower.POST("/apply", wrapper(group_power_r.GroupPowerApplyJoin))
groupPower.POST("/apply/pass", wrapper(group_power_r.GroupPowerApplyPass))
groupPower.GET("/apply/list", wrapper(group_power_r.GroupPowerApplyList))
groupPower.GET("/apply/count", wrapper(group_power_r.GroupPowerApplyCount))
groupPower.POST("/quit", wrapper(group_power_r.GroupPowerQuit))
groupPower.GET("/quit/list", wrapper(group_power_r.GroupPowerQuitList))
groupPower.POST("/admin", wrapper(group_power_r.GroupPowerSetAdmin))
......@@ -145,6 +147,7 @@ func InitRouter() *gin.Engine {
h5GroupPower := v1.Group("/h5/groupPower")
{
h5GroupPower.GET("/grade/detail", wrapper(group_power_r.GroupPowerGradeDetail))
h5GroupPower.GET("/rank/month", wrapper(group_power_r.GroupPowerMonthRankAct))
}
charge := v1.Group("/charge")
......@@ -161,6 +164,7 @@ func InitRouter() *gin.Engine {
innerMic := inner.Group("/mic")
{
innerMic.GET("/onMicSeconds", wrapper(mic_r.MGetUserOnMicSeconds))
innerMic.GET("/onMicSeconds/range", wrapper(mic_r.MGetUserOnMicSecondsRange))
}
r.GET("/test", wrapper(group_power_r.Test))
return r
......
package test
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/rpc"
"testing"
)
func TestGetCpRelation(t *testing.T) {
cpRelation, err := rpc.GetUserCpRelation(domain.CreateModelNil(), 7642)
t.Logf("%v-%v", cpRelation, err)
}
func TestGetCpPairs(t *testing.T) {
cpPairs, err := rpc.MGetUserCpPairs(domain.CreateModelNil(), []uint64{7642, 4549})
t.Logf("%v-%v", cpPairs, err)
}
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"
"testing"
"time"
)
func TestGetAllGroupPowerOwner(t *testing.T) {
owners, err := groupPower_m.BatchGetAllGroupPowerUsers(domain.CreateModelNil())
owners, _, err := groupPower_m.BatchGetAllGroupPowerUsers(domain.CreateModelNil(), 1, 1)
println(owners, err)
}
func TestGetGroupPowerMonthStartTop1(t *testing.T) {
res, err := groupPower_m.GetGroupPowerMonthStartTop1(domain.CreateModelNil(), 250)
println(res,err)
println(res, err)
}
func TestIsUseTRTC(t *testing.T) {
if group_m.IsUseTRTC(domain.CreateModelNil(), "@TGS#3I57DMRIB") {
fmt.Println("true--------------")
}
}
func TestIsMaxMember(t *testing.T) {
//maxNum := group_power_s.GetGroupPowerMaxMemberNum(domain.CreateModelNil(), 263, grade.Grade)
fmt.Println("true--------------")
}
func TestDoCalcGroupPowerMonthRankAct(t *testing.T) {
lastDayTime := time.Now().AddDate(0, 0, -1)
_now := now.New(lastDayTime)
calcMonth := _now.BeginningOfMonth().Format(utils.MONTH_FORMAT)
beginDate, endDate := _now.BeginningOfMonth().Format("2006-01-02"), _now.EndOfMonth().Format("2006-01-02")
_ = group_power_s.DoCalcGroupPowerMonthRankAct(domain.CreateModelNil(), calcMonth, beginDate, endDate, "")
}
func TestDoCalcGroupPowerMonthRankActbufa(t *testing.T) {
lastDayTime := time.Now().AddDate(0, 0, -1)
_now := now.New(lastDayTime)
calcMonth := _now.BeginningOfMonth().Format(utils.MONTH_FORMAT)
starDate := _now.BeginningOfMonth().Format(utils.COMPACT_MONTH_FORMAT)
beginDate, endDate := _now.BeginningOfMonth().Format("2006-01-02"), _now.EndOfMonth().Format("2006-01-02")
_ = group_power_s.BufaDoCalcGroupPowerMonthRankAct(domain.CreateModelNil(), calcMonth, beginDate, endDate, starDate)
}
func TestGetRandomImProvider(t *testing.T) {
var times0, times1 int
model := domain.CreateModelNil()
confList, err := group_m.GetGroupImConf(model)
if err != nil {
model.Log.Errorf("GetRandomImProvider err:%v", err)
return
}
for i := 0; i < 1000000; i++ {
conf := group_m.GetRandomGroupImConf(confList)
if conf.Provider == 0 {
times0 += 1
} else if conf.Provider == 1 {
times1 += 1
}
}
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
......
local flag = redis.call('EXISTS', 'group_user_in_mic_88913f81dc704b9e8e0a8b38956ee8b3')
if flag == 0
then local flag1 = redis.call('SET', 'group_mic_user_HTGS#a91394382_1', '{"GroupUuid":"HTGS#a91394382","I":1,"ExternalId":"88913f81dc704b9e8e0a8b38956ee8b3","UserId":7642,"CpUserId":4549,"Forbid":false,"Timestamp":1686305425}', 'ex', '43200', 'nx')
if flag1 ~= false then redis.call('SETEX', 'group_user_in_mic_88913f81dc704b9e8e0a8b38956ee8b3', '43200', '{"GroupUuid":"HTGS#a91394382","I":1,"UserId":7642}')
return 1 end
return 2 end
return 3
\ No newline at end of file
package test
import (
"fmt"
"net/url"
"path"
"strings"
"testing"
)
func TestUrlParse(t *testing.T) {
//rawUrl := "https://pkg.go.dev/net/url?a=b&c=d#example-ParseQuery"
rawUrl := "https://pkg.go.dev/net/url"
uri, err := url.Parse(rawUrl)
if err != nil {
return
}
query := uri.RawQuery
queryArr := strings.Split(query, "&")
v := url.Values{}
if len(queryArr) > 0 {
for _, q := range queryArr {
if arr := strings.Split(q, "="); len(arr) == 2 {
v.Add(arr[0], arr[1])
}
}
}
v.Add("v1", "v1")
v.Add("v2", "v2")
uri.RawQuery = v.Encode()
uri.Path = path.Join(uri.Path, "/ccc/ddd")
fmt.Println(fmt.Sprintf("修改后的URL是:%s", uri.String()))
}
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")
}