...
 
Commits (306)
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
)
......@@ -134,6 +134,7 @@ const (
GroupPowerUpgrade = 48 // 家族升级
GroupPowerExpireNotice = 49 // 家族等级即将过期(每月20日)
GroupPowerWelcomeJoin = 53 // 欢迎加入家族
GroupPowerApplyJoinMsg = 54 // 申请加入家族通知
)
type MsgSysUserType = mysql.Type
......
package groupPower_k
import (
"fmt"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key"
)
// 家族之星榜单
// type: 1:送礼 2:活跃 3:收礼
// date:天/周/月的开始时间
const GroupPowerStarPrefix = "groupPowerStar:${type}:${period}:${groupPowerId}:${date}" // zset member:userId score:分数
func GetGroupPowerStarRankKey(_type groupPower_e.GroupPowerStarType, period string, groupPowerId uint64, date string) string {
return redis_key.ReplaceKey(GroupPowerStarPrefix,
fmt.Sprintf("%d", _type), period, fmt.Sprintf("%d", groupPowerId), date)
}
package group_k
import (
"fmt"
"hilo-group/_const/redis_key"
)
// 用户进房的key
const (
UserEnterRoomPrefix = "uer:"
UserEnterRoomUserKey = UserEnterRoomPrefix + "u:${user_id}"
UserEnterRoomGroupKey = UserEnterRoomPrefix + "g:${group_id}"
)
func GetUserEnterRoomUserKey(userId uint64) string {
return redis_key.ReplaceKey(UserEnterRoomUserKey, fmt.Sprintf("%d", userId))
}
func GetUserEnterRoomGroupKey(groupId string) string {
return redis_key.ReplaceKey(UserEnterRoomGroupKey, groupId)
}
......@@ -10,9 +10,33 @@ import (
const (
MicPrefix = "mic:"
MicDayInvite = MicPrefix + "day:invite:${userId}:${date}" // string 自动被邀请上麦,1天一次,TTL:24H
MicGroupPowerOnMic = MicPrefix + "groupPower:${userId}:${date}" // 家族内群上麦分钟数
MicUserOnMic = MicPrefix + "user:onMic:${tz}:${userId}:${date}"
MicGroupOnMic = MicPrefix + "group:onMic:${groupId}" // 在群组麦位上的人 hset field:micIndex member:userId
)
func GetUserMicDayInvite(userId mysql.ID) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicDayInvite, fmt.Sprintf("%d", userId), date)
}
// 家族内群上麦分钟数
func GetMicGroupPowerOnMic(userId uint64) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicGroupPowerOnMic, fmt.Sprintf("%d", userId), date)
}
// 获取用户上麦时间
// 北京、沙特时间
func GetUserOnMicKey(userId uint64, tz, date string) string {
return redis_key.ReplaceKey(MicUserOnMic, tz, fmt.Sprintf("%d", userId), date)
}
// 获取群组麦位上的人
// 可能会有数据不一致,已原来麦位的key为准
// 这里用户快速获取群上麦位的人用,代替大量mget命令慢查询
func GetGroupOnMicUser(groupId string) string {
return redis_key.ReplaceKey(MicGroupOnMic, groupId)
}
package mic_k
// onMic异步入库
const (
OnMicQueue = "onMic:hilo_group"
)
func GetOnMicQueue() string {
return OnMicQueue
}
......@@ -249,6 +249,9 @@ const groupInUserDuration = "group_in_user_duration_{groupUuid}"
// 15天内进入房间的人数
const roomVisitCount = "room_visit_count"
// 15天内进入房间的人数 member groupId score 麦位有人的数量
const roomVisitCountZSet = "room_visit_count_zset"
// 用户进入过的房间及时间
const userEnterRoom = "enter_room_{userId}"
......@@ -261,6 +264,9 @@ const groupPowerDiamond = "group_diamond_{period}"
// 国家Icon
const countryIcon = "contry_icon"
// 国家Area
const countryArea = "contry:area"
// 群贡献前三
const groupTop3Consume = "group_top3_consume_{period}_{groupId}"
......@@ -754,18 +760,27 @@ func GetPrefixGroupMicNumType(groupUuid string) string {
return strings.Replace(groupMicNumType, "{groupUuid}", groupUuid, -1)
}
// Deprecated: 用户进房时间
// 用 uer:g:${group_id}代替
func GetPrefixGroupInUserDuration(groupUuid string) string {
return strings.Replace(groupInUserDuration, "{groupUuid}", groupUuid, -1)
}
// Deprecated: 用户进房时间
// 可用 uer:u:${user_id}代替
func GetUserEnterRoomKey(userId uint64) string {
return strings.Replace(userEnterRoom, "{userId}", strconv.FormatUint(userId, 10), -1)
}
// Deprecated: 用redis集群中的zset代替
func GetPrefixRoomVisitCount() string {
return roomVisitCount
}
func GetPrefixRoomVisitCountZset() string {
return roomVisitCountZSet
}
func GetPrefixSupportLevel(date string) string {
return strings.Replace(supportLevel, "{date}", date, -1)
}
......@@ -778,6 +793,10 @@ func GetCountryIconKey() string {
return countryIcon
}
func GetCountryAreaKey() string {
return countryArea
}
func GetGroupTop3ConsumeKey(period string, groupId string) string {
return strings.Replace(strings.Replace(groupTop3Consume, "{period}", period, -1), "groupId", groupId, -1)
}
......
......@@ -107,6 +107,9 @@ const (
MSG_ID_BUY_FROM_FAMILY MsgIdType = 167 // 请向本家族代理购买钻石
MSG_ID_NEED_JOIN_FAMILY MsgIdType = 168 // 请加入代理的家族后进行购买
MSG_ID_SET_FAMILY_NAMEPL MsgIdType = 169 // 等级不够不能修改家族铭牌
MSG_ID_CHARGE_NO_AREA MsgIdType = 181 // 充值(代理转账,用户给代理充值),失败,不是本区域用户
MSG_ID_BAN_MIC_NOBLE_5 MsgIdType = 188 //无法禁言VIP5和vip6
MSG_ID_KICK_NOBLE_5 MsgIdType = 189 //无法踢出VIP5和vip6
ADD_GROUP_FAILED AddGroupResultType = 0
ADD_GROUP_DONE AddGroupResultType = 1
......
......@@ -5,14 +5,24 @@ import (
"hilo-group/cron/gift_cron"
"hilo-group/cron/group_cron"
"hilo-group/cron/mic_cron"
"hilo-group/cron/user_cron"
)
func Init() {
user_cron.LoadSvipVipNoble() // 加载用户特权
if !config.IsMaster() {
return
}
gift_cron.SendGiftEventInit() // 礼物消息
gift_cron.GiftRemark() // 礼物消息补偿
//gift_cron.SendGiftEventInit() // 礼物消息
//gift_cron.GiftRemark() // 礼物消息补偿
gift_cron.SendGiftEvent() // 礼物事件
mic_cron.OnMicCheck() // 检查上麦
mic_cron.OnMicQueue() // 检查上麦-队列操作
group_cron.GroupPowerExpClear() // 清理家族经验/等级
group_cron.GroupPowerMonthRankAct()
//group_cron.GroupInEventInit() // 进房事件
//group_cron.CreateGroup() //
group_cron.CalcGroupSupport() // 群组扶持计算
//group_cron.CalcGroupSupport_OldData()
group_cron.GroupCountryListSort()
}
......@@ -30,6 +30,7 @@ func GiftRemark() {
Payload: unmark.Payload,
MarkHiloGroup: unmark.MarkHiloGroup,
Mark: unmark.Mark, // 不能影响别的服务的mark状态
MarkHiloUser: unmark.MarkHiloUser,
}); err != nil {
model.Log.Errorf("FetchUnMarkEvent add unmark fail:%v", err)
continue
......
package gift_cron
import (
"context"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/domain/cache/gift_c"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/event/gift_ev"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m"
"time"
)
// 送礼事件
func SendGiftEvent() {
//if !config.IsMaster() {
// return
//}
go func() {
for true {
model := domain.CreateModelNil()
if sendGiftEvent := gift_c.BLPopQueueSendGift(model); sendGiftEvent != nil {
groupPowerGrade(model, sendGiftEvent) // 家族经验
groupPowerStar(model, sendGiftEvent) // 家族之星
groupSupportAddConsume(model, sendGiftEvent) // 群组扶持
}
}
}()
}
// 群组势力经验
func groupPowerGrade(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
model.Log.Infof("AddSendGiftEventAsync %+v", sendGiftEvent)
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return
}
exist, groupPowerId, err := groupPower_m.CheckGroupPowerUser(model, sendGiftEvent.SendUserId)
if err != nil {
model.Log.Infof("CheckGroupPowerUser fail %+v", err)
return
}
if exist {
exp := sendGiftEvent.GiftN * mysql.Num(len(sendGiftEvent.ReceiveUserIds)) * sendGiftEvent.ResGift.DiamondNum
//return model.Transaction(func(model *domain.Model) error {
// return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
//})
//return groupPower_c.QueueGroupPowerGradeExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
if err := model.Transaction(func(model *domain.Model) error {
return groupPower_m.IncrGroupPowerExp(model, groupPowerId, exp, sendGiftEvent.SendUserId, "送礼")
}); err != nil {
model.Log.Errorf("IncrGroupPowerExp fail,data:%v-err:%v", *sendGiftEvent, err)
} else {
model.Log.Infof("IncrGroupPowerExp success,data:%v", *sendGiftEvent)
}
}
}
// 家族之星
func groupPowerStar(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
if sendGiftEvent.ResGift.GiftType != mysql.DiamondYellow {
return
}
var userIds = []mysql.ID{sendGiftEvent.SendUserId}
userIds = append(userIds, sendGiftEvent.ReceiveUserIds...)
groupPowers, err := groupPower_m.BatchGetGroupPowerUser(model, userIds)
if err != nil {
model.Log.Errorf("AddSendGiftEventAsync fail:%v", err)
return
}
// 送礼加分
if data, ok := groupPowers[sendGiftEvent.SendUserId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
if err := groupPower_c.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId,
groupPower_e.GroupPowerStarTypeFamous, diamonds); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore famous fail:%v", err)
}
}
// 收礼加分
for _, userId := range sendGiftEvent.ReceiveUserIds {
if data, ok := groupPowers[userId]; ok {
diamonds := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum
if err := groupPower_c.IncrGroupPowerDayStarScore(model, data.GroupPowerId, data.UserId,
groupPower_e.GroupPowerStarTypeCharm, diamonds); err != nil {
model.Log.Errorf("IncrGroupPowerDayStarScore charm fail:%v", err)
}
}
}
return
}
// 群组扶持增加流水数据
func groupSupportAddConsume(model *domain.Model, sendGiftEvent *gift_ev.SendGiftEvent) {
if time.Now().Unix() <= 1693275900 {
return
}
model.Log.Infof("groupSupportAddConsume UserId:%d, sendGiftEvent:%+v", sendGiftEvent.SendUserId, sendGiftEvent)
if sendGiftEvent.SceneType != gift_e.GroupSceneType || sendGiftEvent.SceneUid == "" {
model.Log.Infof("groupSupportAddConsume UserId:%d, sendGiftEvent:%+v", sendGiftEvent.SendUserId, sendGiftEvent)
return
}
_, _, period := group_m.GetSupportLevelTime(time.Now())
// 钻石数
diamond := sendGiftEvent.GiftN * sendGiftEvent.ResGift.DiamondNum * mysql.Num(len(sendGiftEvent.ReceiveUserIds))
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
_, err := model.RedisCluster.ZIncrBy(context.Background(), keyDiamond, float64(diamond), sendGiftEvent.SceneUid).Result()
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, val:%d, member:%s, err:%v",
keyDiamond, diamond, sendGiftEvent.SceneUid, err)
}
err = redisCli.SetExpire(model.RedisCluster, keyDiamond, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, val:%d, member:%s, err:%v",
keyDiamond, diamond, sendGiftEvent.SceneUid, err)
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, sendGiftEvent.SceneUid)
err = model.RedisCluster.SAdd(context.Background(), keySupportNum, sendGiftEvent.SendUserId).Err()
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, UserId:%d, err:%v", keySupportNum, sendGiftEvent.SendUserId, err)
}
err = redisCli.SetExpire(model.RedisCluster, keySupportNum, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("groupSupportAddConsume key:%s, UserId:%d, err:%v", keySupportNum, sendGiftEvent.SendUserId, err)
}
return
}
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/_const/enum/group_e"
"hilo-group/domain/service/group_s"
)
func CreateGroup() {
if !config.IsMaster() {
return
}
c := cron.New()
spec := "0 15 15 16 8 ?"
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
userId := uint64(7687)
num := 20
if config.AppIsRelease() {
userId = 8350311
num = 1000
}
err := group_s.NewGroupService(model.MyContext).CreateGroupMulByUid(userId, num, group_e.TwoMicNumType)
if err != nil {
model.Log.Errorf("CreateGroupMulByUid fail:%v", err)
}
})
c.Start()
}
package group_cron
import (
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"hilo-group/domain/service/event_s"
"time"
)
// 进房事件
func GroupInEventInit() {
if !config.IsMaster() {
return
}
mylogrus.MyLog.Infof("GroupInEventInit")
go func() {
ticker := time.NewTicker(time.Millisecond * 500)
defer ticker.Stop()
for {
select {
case <-ticker.C:
//start := time.Now()
myCtx := mycontext.CreateMyContext(nil)
// 消费进房事件
if err := event_s.NewGroupInEventService(myCtx).Consume(); err != nil {
myCtx.Log.Errorf("groupInEvent consume fail:%v", err)
} else {
//myCtx.Log.Infof("groupInEvent consume success,cost:%v", time.Now().Sub(start))
}
}
}
}()
}
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/domain/service/group_s"
)
// 清理家族经验和等级
func GroupCountryListSort() {
// 常用国家-每15分钟计算国家房间列表排序 /v1/imGroup/country [get] 接口
spec := "0 */15 * * * ?"
c := cron.New()
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
model.Log.Infof("GroupCountryListSort Common start")
group_s.SortGroupCommonCountryList(model)
model.Log.Infof("GroupCountryListSort Common end")
})
// 非常用国家-每60分钟计算国家房间列表排序 /v1/imGroup/country [get] 接口
spec2 := "0 59 * * * ?"
_ = c.AddFunc(spec2, func() {
var model = domain.CreateModelNil()
model.Log.Infof("GroupCountryListSort not Common start")
group_s.SortGroupNotCommonCountryList(model)
model.Log.Infof("GroupCountryListSort not Common end")
})
c.Start()
}
......@@ -2,7 +2,6 @@ package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/domain/event/group_power_ev"
"hilo-group/domain/model/groupPower_m"
......@@ -30,9 +29,6 @@ func GroupPowerExpClear() {
})
// 每月20号发家族即将过期通知
spec = "0 0 0 20 * ?"
if !config.AppIsRelease() {
spec = "0 0 */1 * * ?"
}
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
_ = group_power_ev.PublishGroupPowerExpireNotice(model, &group_power_ev.GroupPowerExpireNoticeEvent{})
......
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"github.com/robfig/cron"
"hilo-group/domain/service/group_power_s"
)
// 家族贡献月度排行榜发奖
func GroupPowerMonthRankAct() {
if !config.IsMaster() {
return
}
c := cron.New()
// 每月1号0:01结算发奖
spec := "0 1 0 1 * ?"
_ = c.AddFunc(spec, func() {
var model = domain.CreateModelNil()
if err := group_power_s.CalcGroupPowerMonthRankAct(model); err != nil {
model.Log.Errorf("GroupPowerMonthRankAct fail:%v", err)
}
})
c.Start()
}
//func BufaGroupPowerMonthRankAct() {
// c := cron.New()
// spec := "0 50 15 1 * ?"
// _ = c.AddFunc(spec, func() {
// var model = domain.CreateModelNil()
// if err := group_power_s.BufaCalcGroupPowerMonthRankAct(model); err != nil {
// model.Log.Errorf("BufaGroupPowerMonthRankAct fail:%v", err)
// }
// })
//
// c.Start()
//}
package group_cron
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/sdk/tencentyun"
"git.hilo.cn/hilo-common/utils"
"github.com/robfig/cron"
"hilo-group/_const/enum/gift_e"
"hilo-group/_const/enum/group_e"
"hilo-group/domain/model/gift_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/service/group_s"
"time"
)
// 群组扶持计算
func CalcGroupSupport() {
if !config.IsMaster() {
return
}
c := cron.New()
//北京时间周一0点,过了一秒后,
spec := "1 0 0 * * 1"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("cron CalcGroupSupport start")
calcTime := time.Now().AddDate(0, 0, -1)
if err := group_s.NewGroupService(model.MyContext).GroupSupportResult(calcTime); err != nil {
model.Log.Errorf("cron CalcGroupSupport faild calcTime:%v, err:%v", calcTime, err)
return
}
model.Log.Infof("cron CalcGroupSupport after GroupSupportResult")
//全服发送H5
if err := sendGroupSupportH5(domain.CreateModelContext(model.MyContext)); err != nil {
model.Log.Errorf("cron CalcGroupSupport err:%v", err)
} else {
model.Log.Infof("cron CalcGroupSupport success")
}
})
c.Start()
}
func sendGroupSupportH5(model *domain.Model) error {
groupIds, err := group_m.GetAllGroupsSorted(model)
if err != nil {
return err
}
model.Log.Infof("SendGroupSupportH5 groupIds:%v", groupIds)
groupSupportH5 := group_m.GroupSupportH5{
CommonPublicMsg: group_m.CommonPublicMsg{
Type: group_e.GroupSupportH5,
},
H5: config.GetH5Config().GROUP_SUPPORT,
}
buffer, err := json.Marshal(groupSupportH5)
if err != nil {
model.Log.Errorf("publicScreenMsg AddSendGiftAsync json.Marshal(giftContent) err:%v", err)
return err
}
content := string(buffer)
//策略1:for循环,没有开启协程,100个停一下
for i, _ := range groupIds {
func(groupId string, content string) {
defer utils.CheckGoPanic()
model.Log.Infof("SendGroupSupportH5 groupId:%v", groupId)
txGroupId, err := group_m.ToTxGroupId(model, groupId)
// 公屏消息
if err == nil {
tencentyun.SendCustomMsg(model.Log, txGroupId, nil, content, "")
}
}(groupIds[i], content)
if i != 0 && i%100 == 0 {
//躺平1秒
time.Sleep(1 * time.Second)
}
}
return nil
}
// 群组扶持计算-旧数据
func CalcGroupSupport_OldData() {
if !config.IsMaster() {
return
}
c := cron.New()
spec := "0 27 10 29 8 ?"
_ = c.AddFunc(spec, func() {
defer utils.CheckGoPanic()
var model = domain.CreateModelNil()
//开始
model.Log.Infof("CalcGroupSupport_OldData start")
//beginTime, endTime, period := group_m.GetSupportLevelTime(time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
beginTime, _, period := group_m.GetSupportLevelTime(time.Now())
endTime := time.Unix(1693275900, 0)
g := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, Model: model}
records, err := g.BatchGetConsumeByRange(beginTime, endTime)
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData beginTime:%v, endTime:%v, err:%v", beginTime, endTime, err)
return
}
// 流水写入redis
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
for _, r := range records {
if r.SceneUid == "" || r.Consume <= 0 {
continue
}
_, err = model.RedisCluster.ZIncrBy(context.Background(), keyDiamond, float64(r.Consume), r.SceneUid).Result()
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, val:%d, member:%s, err:%v",
keyDiamond, r.Consume, r.SceneUid, err)
}
}
err = redisCli.SetExpire(model.RedisCluster, keyDiamond, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, err:%v", keyDiamond, err)
return
}
// 支持者写入redis
for _, r := range records {
if r.SceneUid == "" || r.C <= 0 {
continue
}
// 支持者列表
support := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, SceneUid: r.SceneUid, Model: model}
uids, err := support.BatchGetSupportList(model, beginTime, endTime)
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData beginTime:%v, endTime:%v, imGroupId:%v, err:%v", beginTime, endTime, r.SceneUid, err)
continue
}
if len(uids) <= 0 {
continue
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, r.SceneUid)
for _, uid := range uids {
err = model.RedisCluster.SAdd(context.Background(), keySupportNum, uid).Err()
if err != nil {
model.Log.Errorf("CalcGroupSupport_OldData groupSupport key:%s, UserId:%d, err:%v", keySupportNum, uid, err)
}
}
err = redisCli.SetExpire(model.RedisCluster, keySupportNum, time.Hour*24*14) // 保留两周
if err != nil {
model.Log.Errorf("AddSendGiftEventAsync groupSupport key:%s, err:%v", keySupportNum, err)
}
}
model.Log.Infof("CalcGroupSupport_OldData end")
})
c.Start()
}
package mic_cron
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/cache/mic_c"
"hilo-group/domain/event/mic_ev"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/mic_m"
"hilo-group/domain/service/group_mic_s"
"time"
)
func OnMicCheck() {
c := cron.New()
//一分钟执行一次
spec := "0 */1 * * * ?"
spec := "30 */1 * * * ?"
_ = c.AddFunc(spec, func() {
//获取麦上的所有人
var model = domain.CreateModelNil()
......@@ -20,14 +26,15 @@ func OnMicCheck() {
return
}
for _, groupId := range groupIds {
onGroupMicKey := mic_k.GetGroupOnMicUser(groupId) // 同步在mic上的人
//遍历每个麦位
for i := 1; i <= 30; i++ {
for i := 1; i <= group_m.MaxMicNum; i++ {
micUser, err := group_m.GetMicUser(model, groupId, i)
if err != nil {
model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err)
}
if micUser != nil {
if err := mic_ev.PublishOnMicEvent(model, &mic_ev.OnMicEvent{
if err := mic_c.QueueOnMic(model, &mic_ev.OnMicEvent{
GroupUuid: micUser.GroupUuid,
I: micUser.I,
ExternalId: micUser.ExternalId,
......@@ -35,11 +42,43 @@ func OnMicCheck() {
Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp,
}); err != nil {
model.Log.Errorf("PublishOnMicEvent fail:%v", err)
model.Log.Errorf("QueueOnMic fail:%v", err)
}
// 设置mic上的人
model.Redis.HSet(model, onGroupMicKey, i, micUser.UserId)
} else {
// 删除mic上的人
model.Redis.HDel(model, onGroupMicKey, fmt.Sprintf("%d", i))
}
}
}
})
c.Start()
}
func OnMicQueue() {
for i := 0; i < 4; i++ {
go func() {
for true {
model := domain.CreateModelNil()
if onMic := mic_c.BLPopQueueOnMic(model); onMic != nil {
start := time.Now()
// 群组上麦经验
if err := group_mic_s.NewGroupPowerService(model.MyContext).IncrGroupPowerOnMicExpAndTime(onMic.GroupUuid, onMic.UserId, onMic.Timestamp); err != nil {
model.Log.Errorf("cron micIn GroupPowerOnMicExp err:%v", err)
} else {
model.Log.Infof("cron micIn GroupPowerOnMicExp success, groupId:%v, userId:%v,cost:%vs", onMic.GroupUuid, onMic.UserId, time.Now().Sub(start).Seconds())
}
// 用户上麦
//if err := mic_m.IncrUserOnMic(model, onMic.UserId, onMic.Timestamp); err != nil {
//if err := mic_m.IncrUserOnMicV2(model, onMic.UserId); err != nil {
if err := mic_m.IncrUserOnMicV3(model, onMic.UserId); err != nil {
model.Log.Errorf("cron micIn IncrUserOnMic err:%v", err)
} else {
}
}
}
}()
}
}
package user_cron
import (
"git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron"
"hilo-group/domain/cache/user_c"
)
// 加载数据到lru
func LoadSvipVipNoble() {
go user_c.LoadAllSvipVipNoble(domain.CreateModelNil()) // 启动先执行一次
c := cron.New()
spec := "0 */30 * * * ?"
_ = c.AddFunc(spec, func() {
model := domain.CreateModelNil()
user_c.LoadAllSvipVipNoble(model)
})
c.Start()
}
......@@ -22,7 +22,15 @@ type BillboardUserInfo struct {
Num uint64 `json:"num"`
}
func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]BillboardUserInfo, error) {
//榜单中用户信息
type GroupTop3ConsumeUser struct {
//用户基本信息
UserBase user_cv.TopConsumersUser `json:"userBase"`
//数值
Num uint64 `json:"num"`
}
func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) ([]GroupTop3ConsumeUser, error) {
now := time.Now()
period := now.Format(utils.COMPACT_MONTH_FORMAT)
data, err := getGroupTop3Consume(period, groupId)
......@@ -59,7 +67,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
ret, err := saveGroupTop3Consume(period, groupId, diamonds)
model.Log.Infof("GetGroupTop3Consume SAVE ret = %d, err: %v", ret, err)
return result, nil
list := make([]GroupTop3ConsumeUser, 0, len(result))
for _, v := range result {
list = append(list, GroupTop3ConsumeUser{
UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick},
})
}
return list, nil
}
userIds := make([]uint64, 0)
......@@ -86,7 +102,15 @@ func GetGroupTop3Consume(model *domain.Model, groupId string, myUserId uint64) (
})
}
}
return result, nil
list := make([]GroupTop3ConsumeUser, 0, len(result))
for _, v := range result {
list = append(list, GroupTop3ConsumeUser{
UserBase: user_cv.TopConsumersUser{Id: v.UserBase.Id, Avatar: v.UserBase.Avatar, ExternalId: v.UserBase.ExternalId, Nick: v.UserBase.Nick},
})
}
return list, nil
}
func getGroupTop3Consume(period string, groupId string) (map[string]string, error) {
......
package diamond_cv
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
. "git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model/bean_m"
"hilo-group/domain/model/diamond_m"
"hilo-group/myerr"
"strconv"
)
type CvDiamond struct {
......@@ -26,33 +20,6 @@ type CvDiamondBean struct {
BeanNum string `json:"beanNum"`
}
func GetDiamondBean(userId mysql.ID) (*CvDiamondBean, error) {
var diamondAccount diamond_m.DiamondAccount
err := mysql.Db.Where(&diamond_m.DiamondAccount{
UserId: userId,
}).First(&diamondAccount).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
diamondAccount = diamond_m.DiamondAccount{
DiamondNum: 0,
}
}
return nil, err
}
var beanAccount bean_m.BeanAccount
err = mysql.Db.Where(&bean_m.BeanAccount{
UserId: userId,
}).First(&beanAccount).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
beanAccount = bean_m.BeanAccount{
BeanNum: 0,
}
}
}
return &CvDiamondBean{DiamondNum: diamondAccount.DiamondNum, BeanNum: strconv.FormatFloat(float64(beanAccount.BeanNum)/100, 'f', 2, 64)}, nil
}
type CvDiamondDetail struct {
//1:增加 2:减少
......@@ -74,113 +41,4 @@ func GetDiamond(userId mysql.ID) (*CvDiamond, error) {
return nil, err
}
return &CvDiamond{DiamondNum: NumToUint32(&diamondAccount.DiamondNum), PinkDiamondNum: NumToUint32(&diamondAccount.PinkDiamondNum)}, nil
}
func GetDiamondBalances(userIds []mysql.ID) (map[mysql.ID]mysql.Num, error) {
result := make(map[mysql.ID]mysql.Num, len(userIds))
data := make([]diamond_m.DiamondAccount, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&data).Error
if err != nil {
return nil, err
}
for _, i := range data {
result[i.UserId] = i.DiamondNum
}
return result, nil
}
//充值记录
func GetDiamondBuyList(userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
var diamondAccountDetails []diamond_m.DiamondAccountDetail
if err := mysql.Db.Model(&diamond_m.DiamondAccountDetail{}).
Where("user_id = ? AND operate_type in (?)", userId, []uint8{diamond_e.BuyDiamond, diamond_e.DealerTransfer, diamond_e.Checkout, diamond_e.PayerMax, diamond_e.Paypal}).
Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
return nil, err
}
var cvDiamondDetails []*CvDiamondDetail
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
//钻石明细,不包括充值
func GetDiamondDetailList(model *domain.Model, userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
diamondAccountDetails := make([]*diamond_m.DiamondAccountDetail, 0)
offset := (pageIndex - 1) * pageSize
optList := []int{int(diamond_e.BuyDiamond), int(diamond_e.DealerTransfer), int(diamond_e.Checkout), int(diamond_e.PayerMax)}
details := make([]*diamond_m.DiamondAccountDetail, 0)
if offset == 0 { // 首页请求数据,获取 pageSize*3 条过滤返回
sql := "select * from diamond_account_detail where user_id = ? order by id desc limit ?"
if err := mysql.Db.WithContext(model).Raw(sql, userId, pageSize*3).Find(&details).Error; err != nil {
return nil, myerr.WrapErr(err)
}
notInMap := make(map[int]bool)
for _, v := range optList {
notInMap[v] = true
}
for _, v := range details {
if _, ok := notInMap[int(v.OperateType)]; !ok {
diamondAccountDetails = append(diamondAccountDetails, v)
}
}
if len(diamondAccountDetails) > pageSize {
diamondAccountDetails = diamondAccountDetails[:pageSize]
}
}
// 非首页,或者首页没取满 pageSize 条
if offset > 0 || (len(details) == pageSize*3 && len(diamondAccountDetails) < pageSize) {
diamondAccountDetails = make([]*diamond_m.DiamondAccountDetail, 0)
sql := "select * from diamond_account_detail where user_id = ? and operate_type not in (?) order by id desc limit ?,?"
if err := mysql.Db.WithContext(model).Raw(sql, userId, optList, offset, pageSize).
Find(&diamondAccountDetails).Error; err != nil {
return nil, myerr.WrapErr(err)
}
}
//if err := mysql.Db.Table("diamond_account_detail FORCE INDEX(Index_1)").
// Where("user_id = ? AND operate_type not in (?)", userId,
// []int{int(diamond_m2.BuyDiamond), int(diamond_m2.DealerTransfer), int(diamond_m2.Checkout), int(diamond_m2.PayerMax)}).
// Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
// return nil, myerr.WrapErr(err)
//}
cvDiamondDetails := []*CvDiamondDetail{}
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
//粉钻流水,包含充值
func GetPinkDiamondDetailList(userId mysql.ID, pageSize int, pageIndex int) ([]*CvDiamondDetail, error) {
var diamondAccountDetails []diamond_m.DiamondPinkAccountDetail
if err := mysql.Db.Model(&diamond_m.DiamondPinkAccountDetail{}).
Where("user_id = ?", userId).
Order("id desc").Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&diamondAccountDetails).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var cvDiamondDetails []*CvDiamondDetail
for i := 0; i < len(diamondAccountDetails); i++ {
unixTime := diamondAccountDetails[i].CreatedTime.Unix()
cvDiamondDetails = append(cvDiamondDetails, &CvDiamondDetail{
AddReduce: TypeToUint8(&diamondAccountDetails[i].AddReduce),
OperateType: TypeToUint8(&diamondAccountDetails[i].OperateType),
DiamondNum: NumToUint32(&diamondAccountDetails[i].Num),
CreatedTime: &unixTime,
})
}
return cvDiamondDetails, nil
}
}
\ No newline at end of file
......@@ -123,6 +123,13 @@ type MemberDetail struct {
InRoom bool `json:"inRoom"` // 是否在房间内
}
type GroupVisitorsDetail struct {
user_cv.CvGroupMember
Role group_e.GroupRoleType `json:"role"`
OnlineStatus online_e.OnlineStatusType `json:"onlineStatus"` // IM在线状态
InRoom bool `json:"inRoom"` // 是否在房间内
}
type GroupDetail struct {
GroupBasicInfo
......@@ -133,14 +140,14 @@ type GroupDetail struct {
ThemeId uint64 `json:"themeId"`
ThemeUrl string `json:"themeUrl"`
// 1:官方 2:自定义
ThemeType uint8 `json:"themeType"`
Role group_e.GroupRoleType `json:"role"`
MsgStatus uint8 `json:"msgStatus"` // 消息提醒状态
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
TotalConsume uint64 `json:"totalConsume"` // 群内消费总额
TopConsumers []billboard_cv.BillboardUserInfo `json:"topConsumers"` // 月最高消费三甲
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏的数字点数
ThemeType uint8 `json:"themeType"`
Role group_e.GroupRoleType `json:"role"`
MsgStatus uint8 `json:"msgStatus"` // 消息提醒状态
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
TotalConsume uint64 `json:"totalConsume"` // 群内消费总额
TopConsumers []billboard_cv.GroupTop3ConsumeUser `json:"topConsumers"` // 月最高消费三甲
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏的数字点数
// "AppDefinedData": 群组维度的自定义字段 【暂时不用】
RoleMembers []RoleMemberInfo `json:"role_members"`
Owner *user_cv.CvUserDetail `json:"owner"` // 群主信息
......@@ -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 {
......@@ -165,17 +173,20 @@ type RoomInfo struct {
ThemeId uint64 `json:"themeId"`
ThemeUrl string `json:"themeUrl"`
// 1:官方 2:自定义
ThemeType uint8 `json:"themeType"`
Role group_e.GroupRoleType `json:"role"`
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏类型
RoleMembers []SimpleRoleInfo `json:"roleMembers"`
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
Banners []BannerElement `json:"banners"`
LuckyWheel LuckyWheelState `json:"luckyWheel"`
TotalConsume uint64 `json:"totalConsume"`
GameConfig *game_m.GameConfig `json:"gameConfig"`
Owner *user_cv.CvUserDetail `json:"owner"`
ThemeType uint8 `json:"themeType"`
Role group_e.GroupRoleType `json:"role"`
DiceNum uint16 `json:"diceNum"` // 骰子游戏的数量
DiceType uint16 `json:"diceType"` // 骰子游戏类型
RoleMembers []SimpleRoleInfo `json:"roleMembers"`
WelcomeText string `json:"welcomeText"` // 新成员入群欢迎语
Banners []BannerElement `json:"banners"`
LuckyWheel LuckyWheelState `json:"luckyWheel"`
TotalConsume uint64 `json:"totalConsume"`
GameConfig *game_m.GameConfig `json:"gameConfig"`
Owner *user_cv.RoomInfoOwner `json:"owner"`
EntryEffectType int `json:"entryEffectType"` // 进场特效类型 1: CP 2:神秘人 3:贵族 4:vip
CpUserAvatar string `json:"cpUserAvatar"` // cp对象头像
CpLevel int `json:"cpLevel"` // cp等级
}
type SupportPageDetail struct {
......@@ -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,39 +445,219 @@ func BuildJoinedGroupInfo(myService *domain.Service, myUserId uint64, groupIds [
return result, len(groupInfo), nil
}
func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*group_m.GroupInfo) ([]*PopularGroupInfo, error) {
groupIds := make([]string, 0, len(groupInfo))
for _, v := range groupInfo {
groupIds = append(groupIds, v.ImGroupId)
// 填充用户最近进房
func BuildRecentGroupInfo(myService *domain.Service, myUserId uint64, originGroupIds []string, roomEnterTime map[string]int64) ([]JoinedGroupInfo, int, error) {
model := domain.CreateModel(myService.CtxAndDb)
groupInfo, err := group_m.BatchGetGroupInfo(model, originGroupIds)
if err != nil {
return nil, 0, err
}
var groupIds []string
for _, groupId := range originGroupIds {
if group, ok := groupInfo[groupId]; ok {
if group.IsGameRoom == 0 {
groupIds = append(groupIds, groupId)
}
}
}
if len(groupIds) <= 0 {
return nil, 0, nil
}
// roomMicUserMap不影响排序
// 获取群组中上麦用户
roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds)
if err != nil {
return nil, err
return nil, 0, err
}
uids := make([]uint64, 0)
micUsersMap := make(map[string][]uint64, 0)
for _, v := range groupInfo {
micUsersMap[v.ImGroupId] = make([]uint64, 0)
for _, i := range groupInfo {
micUsersMap[i.ImGroupId] = make([]uint64, 0)
if len(v.Password) <= 0 {
if len(i.Password) <= 0 {
// 密码群不显示麦上头像
u := roomMicUserMap[v.ImGroupId]
u := roomMicUserMap[i.ImGroupId]
if len(u) >= 4 {
micUsersMap[v.ImGroupId] = u[0:4]
micUsersMap[i.ImGroupId] = u[0:4]
} else if len(u) > 0 {
micUsersMap[v.ImGroupId] = u
micUsersMap[i.ImGroupId] = u
}
uids = append(uids, micUsersMap[v.ImGroupId]...)
uids = append(uids, micUsersMap[i.ImGroupId]...)
}
}
uids = utils.UniqueSliceUInt64(uids)
userTiny, err := user_cv.GetUserTinyMap(uids)
if err != nil {
return nil, err
return nil, 0, err
}
roomCount, err := group_m.BatchGetRoomCount(model, groupIds)
if err != nil {
return nil, 0, err
}
countryInfo, err := res_c.GetCountryIconMap(model)
if err != nil {
return nil, 0, err
}
supportLevels, err := group_s.NewGroupService(model.MyContext).GetWeekMaxSupportLevelMap()
if err != nil {
return nil, 0, err
}
visitCount, err := group_m.BatchGetRoomVisitCount(model.Log, groupIds)
if err != nil {
return nil, 0, err
}
// 排序优先级V8.0版本
sort.Slice(groupIds, func(i, j int) bool {
gi := groupIds[i]
gj := groupIds[j]
return roomEnterTime[gi] > roomEnterTime[gj] ||
roomEnterTime[gi] == roomEnterTime[gj] && visitCount[gj] > visitCount[gj] ||
roomEnterTime[gi] == roomEnterTime[gj] && visitCount[gj] == visitCount[gj] && i >= j
})
result := make([]JoinedGroupInfo, 0)
owners := make([]uint64, 0)
for _, i := range groupIds {
owners = append(owners, groupInfo[i].Owner)
}
powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners)
if err != nil {
return nil, 0, err
}
groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds)
if err != nil {
return nil, 0, err
}
resMedal, err := res_m.MedalGetAllMap(model.Db)
if err != nil {
return nil, 0, err
}
rr := rocket_m.RocketResult{}
maxStageMap, err := rr.GetMaxStage(model.Db, groupIds)
if err != nil {
return nil, 0, err
}
// 正在进行的游戏
games := game_m.GetNotEndGamesMap(model)
for _, i := range groupIds {
g := groupInfo[i]
micUsers := make([]user_cv.CvUserTiny, 0)
for _, j := range micUsersMap[i] {
micUsers = append(micUsers, userTiny[j])
}
var maxStage *uint16 = nil
if s, ok := maxStageMap[i]; ok {
maxStage = &s
}
medals := make([]medal_cv.PicElement, 0)
// 补上房间流水勋章
var pe *medal_cv.PicElement
_, pe, err = medal_cv.GetGroupConsumeMedal(model, i)
if err != nil {
model.Log.Infof("BuildJoinedGroupInfo: GetGroupConsumeMedal: %s", err.Error())
} else if pe != nil {
medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl})
}
// res_medal
if m, ok := groupMedals[i]; ok {
for _, j := range m {
mId := uint32(j)
if e, ok := resMedal[mId]; ok {
medals = append(medals, medal_cv.PicElement{
PicUrl: e.PicUrl,
})
}
}
}
var password *string = nil
if len(g.Password) > 0 && g.Owner != myUserId {
emptyStr := ""
password = &emptyStr
}
result = append(result, JoinedGroupInfo{
PopularGroupInfo: PopularGroupInfo{
GroupInfo: GroupInfo{
GroupBasicInfo: GroupBasicInfo{
GroupId: g.TxGroupId,
Name: g.Name,
Notification: g.Notification,
Introduction: g.Introduction,
FaceUrl: g.FaceUrl,
Code: g.Code,
CountryIcon: countryInfo[g.Country],
Password: password,
SupportLevel: supportLevels[i],
GroupInUserDuration: visitCount[i],
MicNumType: int(g.MicNumType),
GroupMedals: medals,
},
HasOnMic: len(micUsers) > 0,
GroupPowerId: powerIds[g.Owner],
GroupPowerName: powerNames[g.Owner],
GroupPowerNameplate: powerNameplates[g.Owner],
GroupPower: GroupPower{
Id: powerIds[g.Owner],
Name: powerNames[g.Owner],
Nameplate: powerNameplates[g.Owner],
Grade: powerGrades[g.Owner],
},
},
MicUsers: micUsers,
RoomUserCount: uint(roomCount[i]),
MaxStage: maxStage,
GameTypes: games[g.TxGroupId],
},
LastEnterTime: roomEnterTime[i],
})
}
return result, len(groupInfo), nil
}
func BuildPopularGroupInfo(model *domain.Model, myUserId uint64, groupInfo []*group_m.GroupInfo) ([]*PopularGroupInfo, error) {
groupIds := make([]string, 0, len(groupInfo))
for _, v := range groupInfo {
groupIds = append(groupIds, v.ImGroupId)
}
// roomMicUserMap不影响排序
//roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds)
//if err != nil {
// return nil, err
//}
//uids := make([]uint64, 0)
//micUsersMap := make(map[string][]uint64, 0)
//for _, v := range groupInfo {
// micUsersMap[v.ImGroupId] = make([]uint64, 0)
//
// if len(v.Password) <= 0 {
// // 密码群不显示麦上头像
// u := roomMicUserMap[v.ImGroupId]
// if len(u) >= 4 {
// micUsersMap[v.ImGroupId] = u[0:4]
// } else if len(u) > 0 {
// micUsersMap[v.ImGroupId] = u
// }
// uids = append(uids, micUsersMap[v.ImGroupId]...)
// }
//}
//uids = utils.UniqueSliceUInt64(uids)
//userTiny, err := user_cv.GetUserTinyMap(uids)
//if err != nil {
// return nil, err
//}
roomCount, err := group_m.BatchGetRoomCount(model, groupIds)
if err != nil {
return nil, err
......@@ -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"` // 排名
Rank int `json:"rank"` // 排名
StarList []*CvGroupPowerStarData `json:"starList"` // 家族贡献top10
}
// 家族之星
......@@ -108,6 +118,6 @@ var GroupPowerGradePrivilegeNum = map[groupPower_e.GroupPowerGrade][]CvPrivilege
{groupPower_e.GroupPowerPrivilegeNameplate, 1, "https://image.whoisamy.shop/hilo/resource/family/nameplate_yellow.png"},
{groupPower_e.GroupPowerPrivilegeMedal, 1, "https://image.whoisamy.shop/hilo/resource/family/privilege_yellow.png"},
{groupPower_e.GroupPowerPrivilegeNameplateEdit, 1, "https://image.whoisamy.shop/hilo/resource/family/edit_yellow.png"},
{groupPower_e.GroupPowerPrivilegeNameplateHeadwear, 1,"https://image.whoisamy.shop/hilo/resource/family/headwear_yellow.png"},
{groupPower_e.GroupPowerPrivilegeNameplateHeadwear, 1, "https://image.whoisamy.shop/hilo/resource/family/headwear_yellow.png"},
},
}
package user_cv
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
......@@ -69,6 +70,25 @@ type CvUserDetail struct {
CountryManager *country_cv.CVCountryManager `json:"countryManager,omitempty"` // 国家管理员
}
type RoomInfoOwner struct {
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
IsPrettyCode bool `json:"isPrettyCode"` // 是否靓号
//是否VIP用户
IsVip bool `json:"isVip"`
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
Medals []uint32 `json:"medals"` // 勋章列表
Noble noble_cv.CvNoble `json:"noble"` // 当前的
WealthUserGrade uint32 `json:"wealthUserGrade"` //财富等级
CharmUserGrade uint32 `json:"charmUserGrade"` //魅力等级
MyGroupPowerName string `json:"myGroupPowerName"` // 当前用户所在势力绑定群组的名称
GroupPower GroupPower `json:"groupPower"` // 当前用户势力信息
}
type GroupPower struct {
Id uint64 `json:"id"` // 群主所在的势力ID
Icon string `json:"icon"` // 家族头像
......@@ -150,6 +170,45 @@ type CvUserExtend struct {
ActiveGrade uint32 `json:"activityUserGrade"`
}
type CvGroupMember struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//是否默认头像 true:是 false:不是
DefaultAvatar *bool `json:"defaultAvatar"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
//签名,不存在为nil
Description *string `json:"description"`
Birthday *uint64 `json:"birthday"`
//邀请码
Code *string `json:"code"`
//国家,不存在为nil
Country *string `json:"country"`
//国旗图标,不存在为nil
CountryIcon *string `json:"countryIcon"`
Sex *uint8 `json:"sex"`
//是否代理管理员, 只有自己查自己的时候才有值,其他情况为nil
IsAgentMgr *bool `json:"isAgentMgr"`
//是否展示年龄, 是本人才有数据,看其他用户均为nil
IsShowAge *uint8 `json:"isShowAge"`
//是否工会成员, 只有是自己查自己,这个才有值,其它全为nil, 20220329 数据开放:原因:产品1对1视频聊天中,公会用户视频需要送礼物。改为: 全部人可以知道是否是公会用户。
IsTradeUnion *bool `json:"isTradeUnion"`
//工会成员,是否开启了,匹配通知,只有 isTradeUnion值为true,这里才有值,
IsTradeUnionMatchNotification *bool `json:"isTradeUnionMatchNotification"`
//是否VIP用户
IsVip bool `json:"isVip"`
Ride property_cv.CvProperty `json:"ride"` // 当前使用的座驾
Noble noble_cv.CvNoble `json:"noble"` // 当前的
Svip rpc.CvSvip `json:"svip"` // svip结构,等级+权限
WealthGrade uint32 `json:"wealthUserGrade"`
CharmGrade uint32 `json:"charmUserGrade"`
ActiveGrade uint32 `json:"activityUserGrade"`
}
// 批量获取用户tiny信息
func GetUserTinyMap(userIds []mysql.ID) (map[mysql.ID]CvUserTiny, error) {
userTinys, _, err := GetUserTinys(userIds)
......@@ -849,16 +908,122 @@ func GetUserDetail(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*Cv
noble, superManagerMap[userId], myGroups, phoneInfo, thirdList, cvCountryManager)
}
//群主信息
func GetRoomInfoOwner(model *domain.Model, userId mysql.ID, myUserId mysql.ID) (*CvUserDetail, error) {
model.Log.Infof("GetUserDetail %d begin", userId)
var user user_m.User
var err error
if err = mysql.Db.First(&user, userId).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var wealthUserScore user_m.MatchWealthUserScore
if err := mysql.Db.Model(&user_m.MatchWealthUserScore{}).Where(&user_m.MatchWealthUserScore{UserId: userId}).First(&wealthUserScore).Error; err != nil {
if err != nil {
if err == gorm.ErrRecordNotFound {
wealthUserScore = user_m.MatchWealthUserScore{
UserId: userId,
Score: 0,
Grade: 0,
}
} else {
return nil, myerr.WrapErr(err)
}
}
}
var charmUserScore user_m.MatchCharmUserScore
if err := mysql.Db.Model(&user_m.MatchCharmUserScore{}).Where(&user_m.MatchCharmUserScore{
UserId: userId,
}).First(&charmUserScore).Error; err != nil {
if err != nil {
if err == gorm.ErrRecordNotFound {
charmUserScore = user_m.MatchCharmUserScore{
UserId: userId,
Score: 0,
Grade: 0,
}
} else {
return nil, myerr.WrapErr(err)
}
}
}
isVip, expireTime, err := user_m.IsVip(userId)
if err != nil {
return nil, myerr.WrapErr(err)
}
svip, err := rpc.GetUserSvip(model, userId)
if err != nil {
return nil, myerr.WrapErr(err)
}
medals := make(map[uint64][]uint32, 0)
medals[userId], err = user_m.GetUserMedalMerge(model.Log, mysql.Db, userId)
if err != nil {
return nil, err
}
medals, medalInfo, err := medal_cv.GetMedalInfoMap(mysql.Db, medals)
if err != nil {
return nil, err
}
groupPowerId, groupPowerName, err := groupPower_m.GetUserGroupPower(model, userId)
if err != nil {
return nil, err
}
powers := map[mysql.ID]uint64{userId: groupPowerId}
powerNames := map[mysql.ID]string{userId: groupPowerName}
groupPowerInfos, err := groupPower_m.MGetGroupPowerInfoMap(model, []mysql.ID{groupPowerId})
groupPowerGrades, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{groupPowerId})
groupPowerUsers, err := groupPower_m.MGetGroupPowerUsers(model, []mysql.ID{groupPowerId})
var memberMax int
grade := groupPowerGrades[groupPowerId].Grade
if grade >= groupPower_e.GroupPowerGrade0 && grade <= groupPower_e.GroupPowerGradeMax {
if grade == groupPower_e.GroupPowerGrade0 {
memberMax = 300
}
if grade == groupPower_e.GroupPowerGrade1 {
memberMax = 500
}
if grade == groupPower_e.GroupPowerGrade2 {
memberMax = 800
}
if grade == groupPower_e.GroupPowerGrade3 {
memberMax = 1200
}
}
memberNum := len(groupPowerUsers[groupPowerId])
if memberNum > memberMax {
memberMax = memberNum
}
groupPowerMembers := [2]int{memberNum, memberMax} // 0->memberNum 1->memberLimit
noble, err := noble_m.FindActiveNoble(mysql.Db, userId)
if err != nil {
return nil, err
}
return userToDetailOne(model, &user, myUserId, nil, false, false,
map[mysql.ID]Relation{}, isVip, expireTime, svip, nil, property_cv.CvProperty{}, wealthUserScore.Grade, charmUserScore.Grade,
0, medals[userId], medalInfo[userId], "", powers[userId], powerNames[userId], groupPowerInfos[groupPowerId], groupPowerGrades[groupPowerId], groupPowerMembers,
noble, false, nil, nil, nil, nil)
}
// 单用户版,简化参数
func userToDetailOne(model *domain.Model, user *user_m.User, myUserId mysql.ID, userTradeUnion *user_m.UserTradeUnion, isLike bool, likeMe bool, hvMap map[mysql.ID]Relation,
isVip bool, vipExpireTime *int64, svip rpc.CvSvip, headwear *headwear_cv.CvHeadwear, ride property_cv.CvProperty, wealthGrade uint32, charmGrade uint32, activityGrade uint32,
medals []uint32, medalInfo []medal_cv.CvMedal, room string, power uint64, powerName string, powerInfo groupPower_m.GroupPowerInfo, grade groupPower_m.GroupPowerGrade, members [2]int, noble *noble_m.UserNoble, isOfficialStaff bool,
myGroups []group_m.GroupInfo, phoneInfo *user_m.UserPhoneInfo, thirdList []int8, countryManager *country_cv.CVCountryManager) (*CvUserDetail, error) {
room, err := group_m.ToTxGroupId(model, room)
if err != nil {
model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err)
room = ""
if len(room) > 0 {
var err error
room, err = group_m.ToTxGroupId(model, room)
if err != nil {
model.Log.Warnf("ToTxGroupId failed for %s, err:%v", room, err)
room = ""
}
}
cvUserDetail := &CvUserDetail{
......@@ -1288,3 +1453,38 @@ func getMedalInfo(db *gorm.DB, medals []uint32) ([]uint32, []medal_cv.CvMedal, e
}
return validMedals, medalInfo, nil
}
func UserDetailToRoomInfoOwner(user *CvUserDetail) *RoomInfoOwner {
return &RoomInfoOwner{
Avatar: user.Avatar,
ExternalId: user.ExternalId,
Nick: user.Nick,
IsPrettyCode: user.IsPrettyCode,
IsVip: user.IsVip,
Svip: user.Svip,
Medals: user.Medals,
Noble: user.Noble,
WealthUserGrade: user.WealthUserGrade,
CharmUserGrade: user.CharmUserGrade,
MyGroupPowerName: user.MyGroupPowerName,
GroupPower: user.GroupPower,
}
}
type TopConsumersUser struct {
//不会有返回值
Id *mysql.ID `json:"id,omitempty"`
//头像,不存在为nil
Avatar *string `json:"avatar"`
//用户对外ID
ExternalId *string `json:"externalId"`
//昵称,不存在为nil
Nick *string `json:"nick"`
}
func CvUserExtendToCvGroupMember(detail CvUserExtend) CvGroupMember {
jData, _ := json.Marshal(detail)
res := CvGroupMember{}
_ = json.Unmarshal(jData, &res)
return res
}
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT]
SECRET=hilo1632
ISSUER_API=hiloApi
......@@ -72,6 +74,9 @@ APP_CERTIFICATE=ff29c100a613433db82324e8411eabc8
CUSTOMER_KEY=6b132c0ff7164560a2bc53fda06ea85a
CUSTOMER_SECRET=eedad2cd16d24834990d5450ace9f1ce
CALLBACK_SECRET=n_ZizS_N8
[TRTC]
APP_ID=1400548270
APP_CERTIFICATE=321bd60f73096b059c7350f1cd97d51028850b34fa58c5c0d26bb4a19e783de8
[CHECKOUT]
AUTHORIZATION=sk_test_9b5e771c-5a3f-4a8d-a4da-31b19bd43d83
URL=https://api.sandbox.checkout.com/hosted-payments
......@@ -114,6 +119,8 @@ NOBLE_BUY_IOS=https://h5.whoisamy.shop/action/hiloHtml/22_05_26_buy_nobility/pag
GUILD_DATA_URL=https://test.chathot.me/action/hiloHtml/22_10_18_app_data_coins/index.html
MGR_GUILD_DATA_URL=https://test.chathot.me/action/hiloHtml/22_10_18_app_data_coins/union.html
RANKING_PINK_DIAMOND_URL=https://test.chathot.me/action/activitiesPage/2022_10_17HiloLiveH5/index.html
AGENT_SHARE_URL=https://test.chathot.me/action/hiloHtml/22_05_30_recharge/topup.html?external_id=
AGENT_SHARE_ICON=https://image.whoisamy.shop/hilo/resource/user_transfer1.png
[GROUPIM]
MSG_SORT_EXPIRE=21600
MSG_SORT_SNAP=300
......
......@@ -9,15 +9,18 @@ import (
)
type gameAutoJoinMsg struct {
TraceId string
Token string
EnterType string
GameCode string
TraceId string
Token string
EnterType string
GameCode string
Is1V1 string
GameMode string
Is1V1Robot string
}
func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode string) error {
func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode, is1V1, gameMode, is1V1Robot string) error {
key := game_e.GetAutoMathEnterRoom(userId, imGroupId)
info := gameAutoJoinMsg{traceId, token, enterType, gameCode}
info := gameAutoJoinMsg{traceId, token, enterType, gameCode, is1V1, gameMode, is1V1Robot}
data, err := json.Marshal(info)
if err != nil {
return err
......@@ -26,7 +29,7 @@ func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, g
if err != nil {
return err
}
redisCli.GetRedis().Expire(context.Background(), key, time.Second*3)
redisCli.GetRedis().Expire(context.Background(), key, time.Second*10)
return nil
}
......
package gift_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/domain/event/gift_ev"
"time"
)
const EventSendGiftHiloGroupQueue = "send:gift:queue:hilo_group"
// redis pop event sendGift
func BLPopQueueSendGift(model *domain.Model) *gift_ev.SendGiftEvent {
var res *gift_ev.SendGiftEvent
queue := EventSendGiftHiloGroupQueue
strs, err := model.RedisCluster.BLPop(model, time.Second, queue).Result()
if err != nil {
if err != redis.Nil {
model.Log.Errorf("BLPopQueueSendGift fail:%v", err)
}
return nil
}
if len(strs) >= 2 {
content := strs[1]
res = new(gift_ev.SendGiftEvent)
if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopQueueSendGift json fail:%v", err)
return nil
}
return res
}
return nil
}
package groupPower_c
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/go-redis/redis/v8"
"github.com/jinzhu/now"
"github.com/pkg/errors"
"github.com/spf13/cast"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/groupPower_k"
"time"
)
// 家族之星-排名
type GroupPowerStarRank struct {
Period string
GroupPowerId mysql.ID
UserId mysql.ID
Type groupPower_e.GroupPowerStarType
Score mysql.Num
}
// 增加家族之星分数
func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num) error {
ttl := map[string]time.Duration{
"day": time.Hour * 24 * 7,
"week": time.Hour * 24 * 7 * 30,
"month": time.Hour * 24 * 7 * 30 * 2,
}
for _, period := range []string{"day", "week", "month"} {
date := ""
switch period {
case "day":
date = time.Now().Format("2006-01-02")
case "week":
date = now.BeginningOfWeek().Format("2006-01-02")
case "month":
date = now.BeginningOfMonth().Format("2006-01-02")
}
key := groupPower_k.GetGroupPowerStarRankKey(_type, period, groupPowerId, date)
model.RedisCluster.ZIncrBy(model, key, float64(score), fmt.Sprintf("%d", userId))
model.RedisCluster.Expire(model, key, ttl[period])
}
return nil
}
// 获取家族之星排行
// param period: day|week|month
func GetGroupPowerStarRankPeriod(model *domain.Model, period string, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, targetDate ...string) ([]*GroupPowerStarRank, error) {
var res []*GroupPowerStarRank
date := ""
switch period {
case "day":
date = time.Now().Format("2006-01-02")
case "week":
date = now.BeginningOfWeek().Format("2006-01-02")
case "month":
date = now.BeginningOfMonth().Format("2006-01-02")
}
if len(date) <= 0 {
return res, errors.New("illegal date")
}
if len(targetDate) > 0 {
date = targetDate[0]
}
key := groupPower_k.GetGroupPowerStarRankKey(_type, period, groupPowerId, date)
rows, err := model.RedisCluster.ZRevRangeByScoreWithScores(model, key, &redis.ZRangeBy{
Min: "-inf",
Max: "+inf",
Offset: int64(offset),
Count: int64(limit),
}).Result()
if err != nil {
model.Log.Errorf("GetGroupPowerStarRankPeriod fail:%v", err)
return res, err
}
for _, v := range rows {
res = append(res, &GroupPowerStarRank{
Period: period,
GroupPowerId: groupPowerId,
UserId: cast.ToUint64(v.Member),
Type: _type,
Score: mysql.Num(v.Score),
})
}
return res, nil
}
// 获取家族之星三个排行榜的各自第一名
func GetGroupPowerMonthStartTop1(model *domain.Model, groupPowerId mysql.ID) ([]*GroupPowerStarRank, error) {
var res []*GroupPowerStarRank
r1, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeFamous, 0, 1)
if err != nil {
return res, err
}
r2, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeActive, 0, 1)
if err != nil {
return res, err
}
r3, err := GetGroupPowerStarRankPeriod(model, "month", groupPowerId, groupPower_e.GroupPowerStarTypeCharm, 0, 1)
if err != nil {
return res, err
}
res = append(res, r1...)
res = append(res, r2...)
res = append(res, r3...)
return res, nil
}
package group_c
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key/group_k"
"strconv"
"time"
)
// 用户进房
func ZAddUserEnterRoom(model *domain.Model, userId uint64, imGroupId string) {
userKey := group_k.GetUserEnterRoomUserKey(userId)
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
if err := model.Redis.ZAdd(model, userKey, &redis.Z{
Score: float64(time.Now().Unix()),
Member: imGroupId,
}).Err(); err != nil {
model.Log.Errorf("ZAddUserEnterRoom user fail:%v", err)
}
if err := model.Redis.ZAdd(model, groupKey, &redis.Z{
Score: float64(time.Now().Unix()),
Member: userId,
}).Err(); err != nil {
model.Log.Errorf("ZAddUserEnterRoom room fail:%v", err)
}
}
// 获取最近房间访客
// 15天
func GetLastRoomVisitors(model *domain.Model, imGroupId string) (userIds []uint64) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
res, err := model.Redis.ZRangeByScore(model, groupKey, &redis.ZRangeBy{
Min: fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix()),
Max: "+inf",
}).Result()
if err != nil {
return
}
for _, u := range res {
uid, _ := strconv.ParseUint(u, 10, 64)
if uid > 0 {
userIds = append(userIds, uid)
}
}
return
}
// 获取最近进入的房间
// 3个月
func GetUserRecentRooms(model *domain.Model, userId uint64, offset, limit int64) (imGroupIds []string, roomEnterTime map[string]int64) {
roomEnterTime = make(map[string]int64)
userKey := group_k.GetUserEnterRoomUserKey(userId)
res, err := model.Redis.ZRevRangeByScoreWithScores(model, userKey, &redis.ZRangeBy{
Min: fmt.Sprintf("%d", time.Now().AddDate(0, -3, 0).Unix()),
Max: "+inf",
Offset: offset,
Count: limit,
}).Result()
if err != nil {
return
}
for _, v := range res {
imGroupId := cast.ToString(v.Member)
imGroupIds = append(imGroupIds, imGroupId)
roomEnterTime[imGroupId] = int64(v.Score)
}
return
}
// 清理房间访客
// 15天前访问的
func RemoveRoomVisitors(model *domain.Model, imGroupId string) {
groupKey := group_k.GetUserEnterRoomGroupKey(imGroupId)
n, err := model.Redis.ZRemRangeByScore(model, groupKey, "-inf", fmt.Sprintf("%d", time.Now().AddDate(0, 0, -15).Unix())).Result()
if err != nil {
model.Log.Errorf("RemoveRoomVisitors fail:%v", err)
} else {
model.Log.Infof("RemoveRoomVisitors key:%v,n:%v", groupKey, n)
}
}
......@@ -14,6 +14,10 @@ import (
"time"
)
func init() {
group_m.FuncAddEditGroupCd = AddEditGroupCd
}
func GetGroupMemberCount(groupId string) (int, error) {
key := redis_key.GetGroupMemCountKey(groupId)
return redisCli.RedisClient.Get(context.Background(), key).Int()
......@@ -79,17 +83,17 @@ func SetGroupMemberTTL(groupId string, ttl time.Duration) (bool, error) {
func GetGroupConsume(groupId string) (uint64, error) {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Get(context.Background(), key).Uint64()
return redisCli.RedisClusterClient.Get(context.Background(), key).Uint64()
}
func SetGroupConsume(groupId string, consume uint64, ttl time.Duration) error {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Set(context.Background(), key, consume, ttl).Err()
return redisCli.RedisClusterClient.Set(context.Background(), key, consume, ttl).Err()
}
func ClearGroupConsume(groupId string) error {
key := getGroupConsumeKey(groupId)
return redisCli.RedisClient.Del(context.Background(), key).Err()
return redisCli.RedisClusterClient.Del(context.Background(), key).Err()
}
// 增加编辑用户cd
......
package mic_c
import (
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/mic_ev"
"time"
)
// redis queue on mic
func QueueOnMic(model *domain.Model, onMic *mic_ev.OnMicEvent) error {
queue := mic_k.GetOnMicQueue()
onMic.Ts = time.Now().UnixNano() // 给一个时间戳
body, _ := json.Marshal(onMic)
return model.RedisCluster.RPush(model, queue, string(body)).Err()
}
// redis pop on mic
func BLPopQueueOnMic(model *domain.Model) *mic_ev.OnMicEvent {
var res *mic_ev.OnMicEvent
queue := mic_k.GetOnMicQueue()
strs, err := model.RedisCluster.BLPop(model, time.Second, queue).Result()
if err != nil {
if err != redis.Nil {
model.Log.Errorf("BLPopQueueOnMic fail:%v", err)
}
return nil
}
if len(strs) >= 2 {
content := strs[1]
res = new(mic_ev.OnMicEvent)
if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopQueueOnMic json fail:%v", err)
return nil
}
return res
}
return nil
}
......@@ -27,17 +27,17 @@ func SetJSON(model *domain.Model, key string, obj interface{}) (err error) {
if err != nil {
return err
}
return model.Redis.Set(model.Context, key, value, DEFAULT_TTL).Err()
return model.RedisCluster.Set(model.Context, key, value, DEFAULT_TTL).Err()
}
// 获取redis中json结构体
// return err: may redisV8.Nil
func GetJSON(model *domain.Model, key string, obj interface{}) (err error) {
var value []byte
defer func() {
model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err)
}()
value, err = model.Redis.Get(model.Context, key).Bytes()
//defer func() {
// model.Log.Infof("GetJson key:%v,value:%s,obj:%v,err:%v", key, value, obj, err)
//}()
value, err = model.RedisCluster.Get(model.Context, key).Bytes()
if err != nil {
// may redisV2.Nil
return
......@@ -59,7 +59,7 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
if time.Now().After(deadline) {
return false
}
flag, err := model.Redis.SetNX(model, key, "1", expireTimeout).Result()
flag, err := model.RedisCluster.SetNX(model, key, "1", expireTimeout).Result()
if err != nil || !flag {
time.Sleep(time.Millisecond * 10)
} else {
......@@ -70,5 +70,5 @@ func TryLock(model *domain.Model, key string, acquireTimeout, expireTimeout time
// 解锁
func UnLock(model *domain.Model, key string) {
model.Redis.Del(model, key)
model.RedisCluster.Del(model, key)
}
package res_c
import (
"context"
"git.hilo.cn/hilo-common/domain"
"hilo-group/_const/redis_key"
"github.com/bluele/gcache"
"hilo-group/domain/model/res_m"
"time"
)
// 统一改成lru
var countryIconLru = gcache.New(1000).LRU().Build()
var countryIconKey = "country:icon"
var countryAreaLru = gcache.New(1000).LRU().Build()
var countryAreaKey = "country:area"
func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
m, err := GetAllCountryIcon(model)
if err != nil || len(m) <= 0 {
......@@ -24,15 +30,54 @@ func GetCountryIconMap(model *domain.Model) (map[string]string, error) {
}
func GetAllCountryIcon(model *domain.Model) (map[string]string, error) {
key := redis_key.GetCountryIconKey()
return model.Redis.HGetAll(context.Background(), key).Result()
//key := redis_key.GetCountryIconKey()
if data, err := countryIconLru.Get(countryIconKey); err == nil {
return data.(map[string]string), nil
}
//return model.Redis.HGetAll(context.Background(), key).Result()
return map[string]string{}, nil
}
func SaveAllCountryIcon(model *domain.Model, icons map[string]string) {
//key := redis_key.GetCountryIconKey()
//ret, err := model.Redis.HSet(context.Background(), key, icons).Result()
//if err == nil {
// model.Redis.Expire(context.Background(), key, time.Minute*10)
//}
//return ret, err
_ = countryIconLru.SetWithExpire(countryIconKey, icons, time.Minute*10)
}
func GetCountryAreaMap(model *domain.Model) (map[string]string, error) {
m, err := GetAllCountryArea(model)
if err != nil || len(m) <= 0 {
m, err = res_m.GetAllCountriesArea(model)
if err != nil {
return nil, err
}
if len(m) <= 0 {
return map[string]string{}, nil
}
SaveAllCountryArea(model, m)
}
return m, nil
}
func SaveAllCountryIcon(model *domain.Model, icons map[string]string) (int64, error) {
key := redis_key.GetCountryIconKey()
ret, err := model.Redis.HSet(context.Background(), key, icons).Result()
if err == nil {
model.Redis.Expire(context.Background(), key, time.Minute*10)
func GetAllCountryArea(model *domain.Model) (map[string]string, error) {
//key := redis_key.GetCountryAreaKey()
//return model.Redis.HGetAll(context.Background(), key).Result()
if data, err := countryAreaLru.Get(countryAreaKey); err == nil {
return data.(map[string]string), nil
}
return ret, err
return map[string]string{}, nil
}
func SaveAllCountryArea(model *domain.Model, data map[string]string) {
//key := redis_key.GetCountryAreaKey()
//ret, err := model.Redis.HSet(context.Background(), key, data).Result()
//if err == nil {
// model.Redis.Expire(context.Background(), key, time.Minute*10)
//}
//return ret, err
_ = countryAreaLru.SetWithExpire(countryAreaKey, data, time.Minute*10)
}
......@@ -2,42 +2,44 @@ package room_c
import (
"context"
"errors"
"fmt"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/redisCli"
"github.com/bluele/gcache"
redis2 "github.com/go-redis/redis/v8"
"github.com/spf13/cast"
"hilo-group/_const/redis_key"
"strconv"
"hilo-group/_const/redis_key/group_k"
"time"
)
// 处理访问房间的相关缓存
func ProcessRoomVisit(groupId string, userId uint64) error {
key := redis_key.GetPrefixGroupInUserDuration(groupId)
now := time.Now()
ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
Score: float64(now.Unix()),
Member: userId,
}).Result()
if err != nil {
return err
}
mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret)
// 每群定时清一次数据可以了
if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL))
if err == nil {
mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc)
} else {
mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error())
}
}
//key := redis_key.GetPrefixGroupInUserDuration(groupId)
//now := time.Now()
//ret, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
// Score: float64(now.Unix()),
// Member: userId,
//}).Result()
//if err != nil {
// return err
//}
//mylogrus.MyLog.Infof("ProcessRoomVisit, ZADD %s, return %d", key, ret)
//
//// 每群定时清一次数据可以了
//if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
// rc, err := clearRoomVisit(groupId, now.AddDate(0, 0, -redis_key.GroupInDurationTTL))
// if err == nil {
// mylogrus.MyLog.Infof("ProcessRoomVisit, clearRoomVisit %s, return %d", key, rc)
// } else {
// mylogrus.MyLog.Warnf("ProcessRoomVisit, clearRoomVisit %s, failed %s", key, err.Error())
// }
//}
// 马上更新roomVisitCount
if _, err := GetSetRoomVisitCount(groupId); err != nil {
mylogrus.MyLog.Warnf("ProcessRoomVisit, failed for key %s, err: %s", key, err.Error())
mylogrus.MyLog.Errorf("ProcessRoomVisit, failed for groupId %s, err: %s", groupId, err.Error())
}
return nil
......@@ -59,15 +61,17 @@ func ProcessUserRoomVisit(userId uint64, groupId string) error {
}
// 查询用户访问过的房间及其时间
// todo 去掉查询,redis性能
func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
result := make(map[string]int64, 0)
return result, nil
key := redis_key.GetUserEnterRoomKey(userId)
ret, err := redisCli.GetRedis().ZRangeWithScores(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, err
}
mylogrus.MyLog.Infof("GetUserRoomVisit, ZRangeWithScores %s, return %v", key, ret)
//mylogrus.MyLog.Infof("GetUserRoomVisit, ZRangeWithScores %s, return %v", key, ret)
result := make(map[string]int64, 0)
for _, i := range ret {
result[i.Member.(string)] = int64(i.Score)
}
......@@ -75,53 +79,63 @@ func GetUserRoomVisit(userId uint64) (map[string]int64, error) {
}
// 批量获取房间访问人数
// 带上lru
var roomVisitCountLru = gcache.New(100).LRU().Build()
func MGetRoomVisitCount(groupIds []string) (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
visit := make(map[string]string)
if len(groupIds) <= 0 {
return visit, nil
}
res, err := redisCli.GetRedis().HMGet(context.Background(), key, groupIds...).Result()
lKey := "room:visit:count"
if data, err := roomVisitCountLru.Get(lKey); err == nil {
return data.(map[string]string), nil
}
// 用redisCluster中的zset代替,只是取出大于10的
zKey := redis_key.GetPrefixRoomVisitCountZset()
cnt := 10
if !config.AppIsRelease() {
cnt = 0
}
zRes, err := redisCli.GetClusterRedis().ZRevRangeByScoreWithScores(context.Background(), zKey, &redis2.ZRangeBy{
Min: fmt.Sprintf("%d", cnt),
Max: "+inf",
}).Result()
if err != nil {
mylogrus.MyLog.Errorf("MGetRoomVisitCount zset fail:%v", err)
return visit, err
}
if len(res) != len(groupIds) {
return visit, errors.New(fmt.Sprintf("MGetRoomVisitCount fail,miss match len,%v-%v", len(res), len(groupIds)))
}
for i, groupId := range groupIds {
if cnt, ok := res[i].(string); ok {
visit[groupId] = cnt
}
for _, v := range zRes {
visit[cast.ToString(v.Member)] = cast.ToString(v.Score)
}
_ = roomVisitCountLru.SetWithExpire(lKey, visit, time.Minute*15)
return visit, nil
}
func GetSetRoomVisitCount(groupId string) (int64, error) {
key := redis_key.GetPrefixGroupInUserDuration(groupId)
//key := redis_key.GetPrefixGroupInUserDuration(groupId)
key := group_k.GetUserEnterRoomGroupKey(groupId)
vc, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
// 查到合法值后,更新二级缓存
if err == nil && vc >= 0 {
ret, err := saveRoomVisitCount(groupId, vc)
mylogrus.MyLog.Infof("saveRoomVisitCount %s, ret = %d, err: %v", groupId, ret, err)
if err := saveRoomVisitCount(groupId, vc); err != nil {
mylogrus.MyLog.Errorf("saveRoomVisitCount %s, err: %v", groupId, err)
}
}
return vc, err
}
func saveRoomVisitCount(groupId string, count int64) (int64, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result()
}
func clearRoomVisit(groupId string, t time.Time) (int64, error) {
value := strconv.FormatInt(t.Unix(), 10)
ret, err := redisCli.GetRedis().ZRemRangeByScore(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId), "0", value).Result()
if err != nil {
return 0, err
func saveRoomVisitCount(groupId string, count int64) error {
//key := redis_key.GetPrefixRoomVisitCount()
zKey := redis_key.GetPrefixRoomVisitCountZset()
// zset同步存一份到redis集群
if err := redisCli.GetClusterRedis().ZAdd(context.Background(), zKey, &redis2.Z{
Score: float64(count),
Member: groupId,
}).Err(); err != nil {
mylogrus.MyLog.Errorf("GetPrefixRoomVisitCountZset fail %s", err.Error())
return err
}
return ret, nil
}
func GetAllRoomVisitCount() (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HGetAll(context.Background(), key).Result()
return nil
//return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result()
}
package user_c
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"sync"
"time"
)
type UserLevel struct {
UserId mysql.ID
Level int
}
var svipVipNobleLock sync.RWMutex
var svipLevel = make(map[mysql.ID]int) // userId->svipLevel
var nobleLevel = make(map[mysql.ID]uint16) // userId->nobleLevel
var userVips = make(map[mysql.ID]bool) // userId->isVip
// 加载数据到lru
func LoadAllSvipVipNoble(model *domain.Model) {
start := time.Now()
var svips []UserLevel
svipMap := make(map[mysql.ID]int)
if err := model.DB().Table("user_svip").Select("user_id,level").Where("level > 0").Find(&svips).Error; err != nil {
model.Log.Errorf("LoadAllSvip fail:%v", err)
} else {
for _, v := range svips {
svipMap[v.UserId] = v.Level
}
}
var nobles []UserLevel
nobleMap := make(map[mysql.ID]uint16)
if err := model.DB().Table("user_noble").Select("user_id,MAX(level) level").
Where("level > 0 AND end_time > ?", time.Now()).Group("user_id").Find(&nobles).Error; err != nil {
model.Log.Errorf("LoadAllNoble fail:%v", err)
} else {
for _, v := range nobles {
nobleMap[v.UserId] = uint16(v.Level)
}
}
var vips []UserLevel
vipMap := make(map[mysql.ID]bool)
if err := model.DB().Table("user_vip").Select("user_id").
Where("expire_at > ?", time.Now()).Find(&vips).Error; err != nil {
model.Log.Errorf("LoadAllVip fail:%v", err)
} else {
for _, v := range vips {
vipMap[v.UserId] = true
}
}
// 上锁赋值
svipVipNobleLock.Lock()
svipLevel = svipMap
nobleLevel = nobleMap
userVips = vipMap
svipVipNobleLock.Unlock()
model.Log.Infof("LoadAllSvipVipNoble svip:%v,vip:%v,noble:%v,cost:%vs", len(svipMap), len(vipMap), len(nobleMap), time.Now().Sub(start).Seconds())
}
func BatchGetNobleLevel(model *domain.Model, userIds []uint64) map[uint64]uint16 {
res := make(map[uint64]uint16)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
res[userId] = nobleLevel[userId]
}
return res
}
func MGetUserSvipLevel(model *domain.Model, userIds []uint64) map[uint64]int {
res := make(map[uint64]int)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
res[userId] = svipLevel[userId]
}
return res
}
func BatchGetVips(model *domain.Model, userIds []uint64) map[uint64]*int64 {
res := make(map[uint64]*int64)
svipVipNobleLock.RLock()
defer svipVipNobleLock.RUnlock()
for _, userId := range userIds {
vip := int64(1)
if userVips[userId] {
res[userId] = &vip
}
}
return res
}
......@@ -38,6 +38,36 @@ func GetUserTinyById(model *domain.Model, userId mysql.ID) (*user_m.UserTiny, er
return userTiny, nil
}
// 获取用户简要信息
// param userId 用户id
func MGetUserTinyById(model *domain.Model, userIds []mysql.ID) []*user_m.UserTiny {
var users []*user_m.UserTiny
for _, userId := range userIds {
if user, _ := GetUserTinyById(model, userId); user != nil {
users = append(users, user)
}
}
return users
}
// 获取用户externalIds
// return []externalIds map[userId]extId map[userId]code
func GetUserExternalIds(model *domain.Model, userIds []mysql.ID) ([]string, map[uint64]string, map[uint64]string) {
var res []string
var m = make(map[uint64]string)
var c = make(map[uint64]string)
if len(userIds) <= 0 {
return res, m, c
}
users := MGetUserTinyById(model, userIds)
for _, u := range users {
res = append(res, u.ExternalId)
m[u.ID] = u.ExternalId
c[u.ID] = u.Code
}
return res, m, c
}
// 获取用户简要信息By ExternalId
func GetUserByExternalId(model *domain.Model, externalId mysql.Str) (*user_m.UserTiny, error) {
userId, err := ToUserId(model, externalId)
......@@ -52,7 +82,7 @@ func ToUserId(model *domain.Model, externalId mysql.Str) (mysql.ID, error) {
if externalId == "" {
return 0, myerr.NewSysError("externalId 不能为空")
}
userId, err := model.Redis.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64()
userId, err := model.RedisCluster.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64()
if err != nil && err != redisV8.Nil {
return 0, err
}
......@@ -75,7 +105,7 @@ func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) {
if code == "" {
return 0, myerr.NewSysError("code 不能为空")
}
userId, err := model.Redis.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64()
userId, err := model.RedisCluster.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64()
if err != nil && err != redisV8.Nil {
return 0, err
}
......@@ -104,11 +134,11 @@ func cacheUserTiny(model *domain.Model, user *user_m.User) error {
// return err
//}
// cache externalId->userId
if err := model.Redis.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
if err := model.RedisCluster.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err
}
// cache code->userId
if err := model.Redis.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
if err := model.RedisCluster.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
return err
}
if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil {
......
package group_ev
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
)
var txGroupInListen = new(domain.EventBase)
// 进房事件
type TxGroupInEvent struct {
GroupId string // imGroupId
UserId mysql.ID
ExternalId string
Nick string
Avatar string
IsMember bool //是否永久成员
IsVip bool
NobleLevel uint16
}
func AddTxGroupInEventSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(txGroupInListen, callback)
}
func AddTxGroupInEventAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(txGroupInListen, callback)
}
func PublishTxGroupInEvent(model *domain.Model, event interface{}) error {
return domain.PublishEvent(txGroupInListen, model, event)
}
......@@ -14,6 +14,8 @@ type OnMicEvent struct {
UserId uint64 // 麦中的人
Forbid bool // 静音 true:静音,false:没有静音
Timestamp int64 // 上麦的的时间戳
Ts int64
}
func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) {
......
package common
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/resource/redisCli"
"git.hilo.cn/hilo-common/utils"
"hilo-group/_const/redis_key"
"hilo-group/myerr"
"github.com/bluele/gcache"
"time"
)
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
bData, err := GetCache(redis_key.GetUserMedalMerge(userId))
if err != nil {
return nil, myerr.WrapErr(err)
}
// 改成lru
var userMedalMergeLru = gcache.New(10000).LRU().Build()
res := make([]uint32, 0)
err = json.Unmarshal(bData, &res)
if err != nil {
return nil, myerr.WrapErr(err)
func GetUserMedalMergeCache(userId mysql.ID) ([]uint32, error) {
if data, err := userMedalMergeLru.Get(userId); err == nil {
return data.([]uint32), nil
}
return res, nil
return nil, nil
}
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) error {
err := SetCache(redis_key.GetUserMedalMerge(userId), data, time.Hour*2)
if err != nil {
mylogrus.MyLog.Errorf("SetUserMedalMerge err:%s", err)
return myerr.WrapErr(err)
}
return nil
func SetUserMedalMergeCache(userId mysql.ID, data []uint32) {
_ = userMedalMergeLru.SetWithExpire(userId, data, time.Minute*15)
}
// 删除勋章缓存, 延迟删除
......@@ -44,41 +30,6 @@ func DelUserMedalMergeCacheDelay(userId mysql.ID) {
}()
}
func DelUserMedalMergeCache(userId mysql.ID) error {
err := DelCache(redis_key.GetUserMedalMerge(userId))
if err != nil {
mylogrus.MyLog.Errorf("DetUserMedalMerge err:%s, userId:%v", err, userId)
return myerr.WrapErr(err)
}
return nil
}
func DelCache(key string) error {
err := redisCli.GetRedis().Del(context.Background(), key).Err()
if err != nil {
mylogrus.MyLog.Errorf("DelCache key:%s, err:%s", key, err)
return err
}
return nil
}
func GetCache(key string) ([]byte, error) {
data, err := redisCli.GetRedis().Get(context.Background(), key).Bytes()
if err != nil {
return nil, err
}
return data, nil
}
func SetCache(key string, data interface{}, expire time.Duration) error {
jData, err := json.Marshal(data)
if err != nil {
return err
}
err = redisCli.GetRedis().Set(context.Background(), key, jData, expire).Err()
if err != nil {
mylogrus.MyLog.Errorf("SetCache key:%s, data:%v, err:%s", key, data, err)
return err
}
return nil
func DelUserMedalMergeCache(userId mysql.ID) {
userMedalMergeLru.Remove(userId)
}
package diamond_m
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mylogrus"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/domain/model"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
"strconv"
......@@ -40,6 +40,11 @@ type DiamondAccountDetail struct {
diamondAccount *DiamondAccount `gorm:"-"`
}
func (DiamondAccountDetail) TableName() string {
month := time.Now().Format("200601")
return fmt.Sprintf("diamond_account_detail_%s", month)
}
// 粉钻详情
type DiamondPinkAccountDetail struct {
mysql.Entity
......@@ -110,7 +115,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
var count int64
if diamondOperateSet.FrequencyDay == -1 {
if diamondOperateSet.FrequencyNum != -1 {
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{
diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId,
OperateType: operateType,
}).Count(&count)
......@@ -125,7 +130,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, myerr.WrapErr(err)
}
//一天的次数
diamondAccount.Db.Model(&DiamondAccountDetail{}).Where(&DiamondAccountDetail{
diamondAccount.DB().Table(DiamondAccountDetail{}.TableName()).Where(&DiamondAccountDetail{
UserId: diamondAccount.UserId,
OperateType: operateType,
}).Where("created_time >= ? ", beginTime).Count(&count)
......@@ -133,7 +138,7 @@ func (diamondAccount *DiamondAccount) addDiamondAccountDetail(operateType diamon
return nil, bizerr.DiamondFrequency
}
//终极拦截,利用
diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from diamond_account_detail d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )")
diamondAccount.SetCheckUpdateCondition(" EXISTS (SELECT * from (SELECT COUNT(1) as n from " + DiamondAccountDetail{}.TableName() + " d where d.user_id = " + strconv.FormatUint(diamondAccount.UserId, 10) + " and d.operate_type = " + strconv.FormatUint(uint64(operateType), 10) + " and d.created_time >= from_unixtime(" + strconv.FormatInt(utils.GetZeroTime(time.Now()).Unix(), 10) + ")) t where t.n < " + strconv.Itoa(diamondOperateSet.FrequencyNum) + " )")
}
//-1,代表值无效,由参数给与
......@@ -197,7 +202,10 @@ func (diamondAccountDetail *DiamondAccountDetail) PersistentNoInTransactional()
}
//持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
//if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err)
}
//改变diamondAccount值
......@@ -245,7 +253,10 @@ func (diamondAccountDetail *DiamondAccountDetail) Persistent() error {
}
//持久化diamondAccountDetail
if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
//if err := model.Persistent(diamondAccountDetail.Db, diamondAccountDetail); err != nil {
// return myerr.WrapErr(err)
//}
if err := diamondAccountDetail.DB().Table(diamondAccountDetail.TableName()).Save(diamondAccountDetail).Error; err != nil {
return myerr.WrapErr(err)
}
//改变diamondAccount值
......
package event_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
)
// 进房事件消息
type EventGroupIn struct {
mysql.Entity
*domain.Model `gorm:"-"`
Proto mysql.Type
Payload []byte
Mark mysql.YesNo
MarkHiloGroup mysql.YesNo
}
func (EventGroupIn) TableName() string {
return "event_group_in"
}
// 偏移值
type EventGroupInOffsetHiloGroup struct {
mysql.Entity
*domain.Model `gorm:"-"`
MarkOffset mysql.ID
}
// 获取当前偏移值
func GroupOffset(model *domain.Model) (*EventGroupInOffsetHiloGroup, error) {
offset := new(EventGroupInOffsetHiloGroup)
if err := model.Db.WithContext(model).First(offset).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("Offset fail:%v", err)
return nil, err
}
// gorm.ErrRecordNotFound
}
offset.Model = model
return offset, nil
}
// 批量获取进房事件
func FetchEventGroupIn(model *domain.Model, limit int) ([]*EventGroupIn, *EventGroupInOffsetHiloGroup, error) {
offset, err := GroupOffset(model)
if err != nil {
return nil, nil, err
}
var events []*EventGroupIn
if err := model.Db.WithContext(model).Model(EventGroupIn{}).
Where("id > ?", offset.MarkOffset).
Order("id asc").Limit(limit).Find(&events).Error; err != nil {
model.Log.Errorf("FetchEventGroupIn fail:%v", err)
return nil, nil, err
}
return events, offset, nil
}
// 标记已完成
func (p *EventGroupIn) MarkDone() error {
p.MarkHiloGroup = mysql.YES
return p.Db.WithContext(p.Model).Model(EventGroupIn{}).Where("id = ?", p.ID).Update("mark_hilo_group", p.MarkHiloGroup).Limit(1).Error
}
......@@ -9,3 +9,7 @@ func (p *EventGiftSendOffsetHiloGroup) Persistence() error {
func (p *EventGiftSend) Persistence() error {
return model.Persistent(p.Db, p)
}
func (p *EventGroupInOffsetHiloGroup) Persistence() error {
return model.Persistent(p.Db, p)
}
\ No newline at end of file
......@@ -16,10 +16,11 @@ type EventGiftSend struct {
Payload []byte
Mark mysql.YesNo
MarkHiloGroup mysql.YesNo
MarkHiloUser mysql.YesNo
}
func (EventGiftSend) TableName() string {
return "event_gift_send2"
return "event_gift_send"
}
// 偏移值
......
......@@ -29,8 +29,9 @@ type GameInfo struct {
}
type GameConfig struct {
Ludo *GameConfigDiamond `json:"ludo"`
Uno *GameConfigDiamond `json:"uno"`
Ludo *GameConfigDiamond `json:"ludo"`
Uno *GameConfigDiamond `json:"uno"`
Domino *GameConfigDiamond `json:"domino"`
}
type GameConfigDiamond struct {
......
......@@ -127,6 +127,40 @@ func (g *GiftOperate) GetConsumeByRange(beginTime, endTime time.Time) (uint32, u
if len(rows) <= 0 {
return 0, 0, nil
}
//if beginTime.Unix() >= 1691337600 && beginTime.Unix() < 1691942400 { // 因为这周水果机被部分人刷币,所以这里做了特殊的处理
// reduceMap := map[string]uint64{
// "HTGS#a63226380": 20000000,
// //"HTGS#a42641278": 10000000,
// "@TGS#3ZZ5GZLHA": 27141539,
// "HTGS#a81630128": 8955410,
// "HTGS#a42300598": 50211301,
// "HTGS#a40088696": 10000000,
// "HTGS#a21700997": 14352310,
// "HTGS#a83608384": 49644203,
// "@TGS#33GDXTSIH": 50000000,
// "HTGS#a50538513": 15000000,
// "HTGS#a77282385": 15000000,
// "HTGS#a59437326": 10000000,
// "HTGS#a16909405": 10000000,
// "HTGS#a44104431": 16861206,
// "HTGS#a56794634": 59591313,
// "HTGS#a11286025": 31232311,
// "HTGS#a17238550": 52309338,
// "HTGS#a83592361": 79545067,
// "HTGS#a39882521": 10255093,
// }
// if reduceNum, ok := reduceMap[g.SceneUid]; ok {
// if g.Log != nil {
// g.Log.Infof("fruit diamond reduceMap,groupId:%v,reduceNum:%v", g.SceneUid, reduceNum)
// }
// if rows[0].Consume >= reduceNum {
// rows[0].Consume -= reduceNum
// } else {
// rows[0].Consume = 0
// }
// }
//}
return rows[0].C, rows[0].Consume, nil
}
......@@ -148,6 +182,17 @@ func (g *GiftOperate) BatchGetConsumeByRange(beginTime, endTime time.Time) ([]Sc
return rows, nil
}
func (g *GiftOperate) BatchGetSupportList(model *domain.Model, beginTime, endTime time.Time) ([]uint64, error) {
userIds := make([]uint64, 0)
err := model.DB().Model(g).
Select("DISTINCT(send_user_id) AS user_id").
Where(g).Where("created_time BETWEEN ? AND ?", beginTime, endTime).Pluck("user_id", &userIds).Error
if err != nil {
return nil, err
}
return userIds, nil
}
func SumSendGift(model *domain.Model, sendUserId mysql.ID, giftId mysql.ID) (uint32, error) {
type Result struct {
N uint32
......
......@@ -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/_const/enum/groupPower_e"
"hilo-group/common"
......@@ -48,7 +49,7 @@ func (this *GroupPower) Get(model *domain.Model) (*GroupPower, error) {
func (gpu *GroupPowerUser) GetBy(model *domain.Model, pageSize, pageIndex int) ([]*GroupPowerUser, int64, int, bool, error) {
rows := make([]*GroupPowerUser, 0)
db := model.Db.Model(GroupPowerUser{}).Where(gpu).Order("field(`role`, 2, 3, 1)")
db := model.Db.Model(GroupPowerUser{}).Where(gpu).Order("field(`role`, 2, 3, 1),`id`")
var count int64
err := db.Count(&count).Error
if err != nil {
......@@ -116,9 +117,13 @@ func UpdateFamily(model *domain.Model, familyId uint64, name, nameplate, declara
if familyId == 0 || (name == "" && nameplate == "" && declaration == "" && icon == "") {
return nil
}
var groupPower GroupPower
if err := model.DB().Model(GroupPower{}).Where("id = ?", familyId).First(&groupPower).Error; err != nil {
return err
}
// 修改铭牌
if nameplate != "" {
sql := "UPDATE `group_power` a left join (SELECT ? `id` FROM group_power WHERE nameplate = ?) b on a.id = b.id SET a.`nameplate`=? where a.id=? and b.id is null;"
sql := "UPDATE `group_power` a left join (SELECT ? `id` FROM group_power WHERE nameplate = ?) b on a.id = b.id SET a.`nameplate`=?,modify_nameplate = 1 where a.id=? and b.id is null;"
result := model.Db.Exec(sql, familyId, nameplate, nameplate, familyId)
if result.Error != nil {
return myerr.WrapErr(result.Error)
......@@ -132,6 +137,14 @@ func UpdateFamily(model *domain.Model, familyId uint64, name, nameplate, declara
updateMap := make(map[string]interface{})
if name != "" {
updateMap["name"] = name
if groupPower.ModifyNameplate != mysql.YES {
// 同步修改铭牌
n := len([]rune(name))
if n > groupPower_e.LongestNameplate {
n = groupPower_e.LongestNameplate
}
updateMap["nameplate"] = string([]rune(name[0:n]))
}
}
if declaration != "" {
updateMap["declaration"] = declaration
......
......@@ -22,16 +22,17 @@ import (
type GroupPower struct {
mysql.Entity
*domain.Model `gorm:"-"`
GroupUid mysql.Str
Name mysql.Str
Status groupPower_e.GroupPowerStatus
Nameplate mysql.Str // 铭牌
Declaration mysql.Str // 宣言
Icon mysql.Str // 头像
GradeName mysql.Str // 等级称号
GradeMedal mysql.Str // 等级勋章图片
Grade groupPower_e.GroupPowerGrade `gorm:"-"`
*domain.Model `gorm:"-"`
GroupUid mysql.Str
Name mysql.Str
Status groupPower_e.GroupPowerStatus
Nameplate mysql.Str // 铭牌
Declaration mysql.Str // 宣言
Icon mysql.Str // 头像
GradeName mysql.Str // 等级称号
GradeMedal mysql.Str // 等级勋章图片
Grade groupPower_e.GroupPowerGrade `gorm:"-"`
ModifyNameplate mysql.YesNo
}
type GroupPowerUser struct {
......@@ -42,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
......@@ -63,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)
......@@ -470,6 +498,16 @@ func GetGroupPowerMgr(model *domain.Model, groupPowerId mysql.ID) (mysql.ID, err
return groupPowerUser.UserId, nil
}
//获取势力主和管理员
func GetGroupPowerMgrList(model *domain.Model, groupPowerId mysql.ID) ([]mysql.ID, error) {
res := make([]mysql.ID, 0)
err := model.Db.Model(GroupPowerUser{}).Select("user_id").Where("group_power_id = ? and role in (2,3)", groupPowerId).Scan(&res).Error
if err != nil {
return res, myerr.WrapErr(err)
}
return res, nil
}
//运营平台让用户离开
func (groupPower *GroupPower) MgrUserLeave(userId mysql.ID) (*GroupPowerUser, error) {
//
......@@ -696,3 +734,7 @@ func BatchGetGroupPowerUser(model *domain.Model, userIds []mysql.ID) (map[mysql.
}
return res, nil
}
func CreateActFamilyMonthRankLog(model *domain.Model, list []*ActFamilyMonthRankLog) error {
return model.DB().CreateInBatches(&list, 50).Error
}
......@@ -8,6 +8,7 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/enum/groupPower_e"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/group_power_ev"
"time"
)
......@@ -40,25 +41,6 @@ type GroupPowerExpDetail struct {
Remark string
}
type GroupPowerOnMic struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Seconds int64
LastCalTs int64
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
type GroupPowerOnMicDetail struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Minute int
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
// 增加家族经验
// 达到经验值之后升级
// 单进程同步执行,不考虑并发
......@@ -82,17 +64,34 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return err
}
// 增加家族经验-总
gpg := &GroupPowerGrade{
GroupPowerId: groupPowerId,
Exp: exp,
Grade: 0,
ExpireAt: time.Time{},
}
if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil {
return err
gpg := new(GroupPowerGrade)
// insert
if err := txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(gpg).Error; err != nil {
if err != gorm.ErrRecordNotFound {
return err
}
// gorm.ErrRecordNotFound
gpg = &GroupPowerGrade{
GroupPowerId: groupPowerId,
Exp: exp,
Grade: 0,
ExpireAt: time.Time{},
}
if err = txModel.DB().Create(gpg).Error; err != nil {
return err
}
} else {
// or update
if err := txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).
UpdateColumn("exp", gorm.Expr("exp + ?", exp)).Error; err != nil {
return err
}
}
//if err = txModel.DB().Model(GroupPowerGrade{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "group_power_id"}},
// DoUpdates: clause.Assignments(map[string]interface{}{
// "exp": gorm.Expr("exp + ?", gpg.Exp)})}).Create(gpg).Error; err != nil {
// return err
//}
// 当前写后读
latestGrade := new(GroupPowerGrade)
if err = txModel.DB().Model(GroupPowerGrade{}).Where("group_power_id = ?", groupPowerId).First(latestGrade).Error; err != nil {
......@@ -135,154 +134,24 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return nil
}
// 获取势力用户上麦加经验记录
func GetGroupPowerUserOnMicDetails(model *domain.Model, groupPowerId, userId mysql.ID) ([]*GroupPowerOnMicDetail, error) {
var res []*GroupPowerOnMicDetail
date := time.Now().Format("2006-01-02")
if err := model.DB().Model(GroupPowerOnMicDetail{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).Find(&res).Error; err != nil {
return res, err
}
return res, nil
}
// 获取势力用户上麦记录
func GetGroupPowerOnMic(model *domain.Model, groupPowerId, userId mysql.ID) (*GroupPowerOnMic, error) {
gpom := new(GroupPowerOnMic)
date := time.Now().Format("2006-01-02")
if err := model.DB().Model(GroupPowerOnMic{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).First(gpom).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return &GroupPowerOnMic{Date: date, GroupPowerId: groupPowerId, UserId: userId}, nil
}
return nil, err
}
return gpom, nil
}
const MaxMinuteTimes = 18
// 增加势力上麦经验
// 事务操作
func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 获取用户上麦奖励历史
onMicDetails, err := GetGroupPowerUserOnMicDetails(model, groupPowerId, userId)
if err != nil {
return err
}
numDetails := len(onMicDetails)
if numDetails >= MaxMinuteTimes {
// 上麦经验贡献值最多1800,1分钟100
return nil
}
onMic, err := GetGroupPowerOnMic(model, groupPowerId, userId)
if err != nil {
return err
}
nowTs := time.Now().Unix()
curTs := joinMicTimestamp
day0Ts := utils.GetZeroTime(time.Now()).Unix()
if joinMicTimestamp < onMic.LastCalTs {
curTs = onMic.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
onMicSeconds := nowTs - curTs
var moreDetails []*GroupPowerOnMicDetail
totalMinuteTimes := int((onMic.Seconds + onMicSeconds) / 600) // 今天实际能加经验次数
if totalMinuteTimes >= MaxMinuteTimes {
totalMinuteTimes = MaxMinuteTimes
}
if totalMinuteTimes > numDetails {
// 续上上一次的时间,从numDetails开始
for mt := numDetails + 1; mt <= totalMinuteTimes; mt++ {
moreDetails = append(moreDetails, &GroupPowerOnMicDetail{
Date: time.Now().Format("2006-01-02"),
GroupPowerId: groupPowerId,
UserId: userId,
Minute: mt * 10, // 转换分钟
})
}
}
// 有更多麦上10分钟,可以加经验
if len(moreDetails) > 0 {
for _, detail := range moreDetails {
// 添加明细,避免重复计算
if err := model.DB().Model(GroupPowerOnMicDetail{}).Create(detail).Error; err != nil {
return err
}
// 每10分钟增加100点经验
if err := IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟"); err != nil {
return err
}
}
// 更新micExp信息
onMic.Seconds = onMic.Seconds + onMicSeconds
onMic.LastCalTs = nowTs
if err := model.DB().Model(GroupPowerOnMic{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "date"}, {Name: "group_power_id"}},
DoUpdates: clause.Assignments(
map[string]interface{}{
"seconds": onMic.Seconds,
"last_cal_ts": nowTs,
},
)}).
Create(onMic).Error; err != nil {
return err
}
}
return nil
})
}
// 增加势力上麦时长-家族之星
// 事务操作
func IncrGroupPowerStarOnMicMonth(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 月统计
star, err := GetGroupPowerMonthStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
month0Ts := now.BeginningOfMonth().Unix()
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨月
if curTs < month0Ts {
curTs = month0Ts
}
score := nowTs - curTs
err = IncrGroupPowerMonthStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID) error {
key := mic_k.GetMicGroupPowerOnMic(userId)
minutes, err := model.Redis.IncrBy(model, key, 1).Result()
if err != nil {
model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err)
return err
})
}
// 增加势力上麦时长-家族之星
// 事务操作
func IncrGroupPowerStarOnMicDay(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
// 日统计
star, err := GetGroupPowerDayStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
day0Ts := now.BeginningOfDay().Unix()
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
err = IncrGroupPowerDayStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
return err
})
}
model.Redis.Expire(model, key, time.Hour*24) // ttl 一天
// 每日最多1800经验 = 18个10分钟 = 180分钟
if minutes > 180 {
return nil
}
if minutes%10 == 0 {
return IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟")
}
return nil
}
// 清理所有家族的经验
......
......@@ -2,6 +2,7 @@ package groupPower_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/common"
"hilo-group/myerr"
......@@ -88,3 +89,16 @@ func DelGroupPowerApplyJoinNoDeal(model *domain.Model, userId uint64) error {
}
return nil
}
// 获取家族申请人数
// param: isAccept 0:未审核 1:通过 2:拒绝
func CountGroupPowerApply(model *domain.Model, groupPowerId mysql.ID, isAccept int) (int64, error) {
var cnt int64
if err := model.DB().Model(GroupPowerApplyJoin{}).
Where("group_power_id = ?", groupPowerId).
Where("is_accept = ?", isAccept).Count(&cnt).Error; err != nil {
model.Log.Errorf("CountGroupPowerApply fail:%v", err)
return cnt, err
}
return cnt, nil
}
......@@ -4,6 +4,7 @@ import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/_const/enum/groupPower_e"
)
type GroupPowerExpRank struct {
......@@ -14,10 +15,20 @@ type GroupPowerExpRank struct {
// 获取家族经验排行榜
// param limit: 排行榜人数
func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int) ([]GroupPowerExpRank, error) {
// 10166 线上员工,对应的势力不上榜,groupPowerId=8951
func GetGroupPowerExpRank(model *domain.Model, beginDate, endDate string, limit int, gpStatus groupPower_e.GroupPowerStatus, area int) ([]GroupPowerExpRank, error) {
var res []GroupPowerExpRank
if err := model.DB().Table("group_power_day_exp").Select("group_power_id,SUM(exp) as exp").
Where("date BETWEEN ? AND ?", beginDate, endDate).Group("group_power_id").Order("exp DESC").Limit(limit).Find(&res).Error; err != nil {
db := model.DB().Table("group_power_day_exp gpd").Select("gpd.group_power_id,SUM(gpd.exp) as exp").
Where("gpd.group_power_id <> 8951").
Where("gpd.date BETWEEN ? AND ?", beginDate, endDate)
if gpStatus > 0 {
db = db.Joins("left join group_power gp on gpd.group_power_id = gp.id").Where("gp.status = ?", gpStatus)
if area > 0 {
db = db.Joins("left join group_info gi on gp.group_uid = gi.im_group_id left join res_country rs on gi.country = rs.name").
Where("rs.area = ?", area)
}
}
if err := db.Group("gpd.group_power_id").Order("exp DESC").Limit(limit).Find(&res).Error; err != nil {
model.Log.Errorf("GetGroupPowerExpRank fail:%v", err)
return res, err
}
......
......@@ -35,6 +35,7 @@ type GroupPowerDayStar struct {
}
// 增加家族之星分数
// Deprecated: 用redis
func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
month := time.Now().Format("200601")
star := &GroupPowerMonthStar{
......@@ -59,6 +60,7 @@ func IncrGroupPowerMonthStarScore(model *domain.Model, groupPowerId, userId mysq
}
// 增加家族之星分数
// Deprecated: 用redis代替
func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType, score mysql.Num, lastCalTs int64) error {
star := &GroupPowerDayStar{
Date: time.Now(),
......@@ -81,32 +83,11 @@ func IncrGroupPowerDayStarScore(model *domain.Model, groupPowerId, userId mysql.
return nil
}
// 获取家族之星分数
// 允许返回gorm.ErrRecordNotFound
func GetGroupPowerDayStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerDayStar, error) {
res := new(GroupPowerDayStar)
date := time.Now()
if err := model.DB().Where("date = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", date.Format("2006-01-02"), groupPowerId, userId, _type).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 获取家族之星分数
// 允许返回gorm.ErrRecordNotFound
func GetGroupPowerMonthStar(model *domain.Model, groupPowerId, userId mysql.ID, _type groupPower_e.GroupPowerStarType) (*GroupPowerMonthStar, error) {
res := new(GroupPowerMonthStar)
month := time.Now().Format("200601")
if err := model.DB().Where("month = ? AND group_power_id = ? AND user_id = ? AND `type` = ?", month, groupPowerId, userId, _type).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 获取家族之星排行
func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int) ([]*GroupPowerMonthStar, error) {
// Deprecated: 用redis
func GetGroupPowerMonthStarRank(model *domain.Model, groupPowerId mysql.ID, _type groupPower_e.GroupPowerStarType, offset, limit int, month string) ([]*GroupPowerMonthStar, error) {
var res []*GroupPowerMonthStar
month := time.Now().Format("200601")
//month := time.Now().Format("200601")
if err := model.DB().Model(GroupPowerMonthStar{}).Where("month = ? AND group_power_id = ? AND `type` = ?", month, groupPowerId, _type).
Order("score desc").Offset(offset).Limit(limit).Find(&res).Error; err != nil {
model.Log.Errorf("GetGroupPowerMonthStarRank fail:%v", err)
......
......@@ -13,6 +13,7 @@ import (
"gorm.io/gorm"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key"
"hilo-group/_const/redis_key/mic_k"
"hilo-group/myerr"
"strconv"
"strings"
......@@ -242,6 +243,20 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if len(groupIds) <= 0 {
return result, nil
}
// 获取群组中上麦用户
for _, groupId := range groupIds {
groupMicUserKey := mic_k.GetGroupOnMicUser(groupId)
userIds, err := model.Redis.HVals(model, groupMicUserKey).Result()
if err != nil {
model.Log.Errorf("BatchGetAllMicUser fail:%v", err)
}
for _, userIdStr := range userIds {
if userId, _ := strconv.ParseUint(userIdStr, 10, 64); userId > 0 {
result[groupId] = append(result[groupId], userId)
}
}
}
return result, nil
keys := make([]string, 0)
for _, g := range groupIds {
......@@ -253,7 +268,7 @@ func BatchGetAllMicUser(model *domain.Model, groupIds []string) (map[string][]my
if err != nil {
return nil, err
}
model.Log.Infof("BatchGetAllMicUser redis return size = %d, mics: %v", len(mics), mics)
//model.Log.Infof("BatchGetAllMicUser redis return size = %d, mics: %v", len(mics), mics)
if len(mics) >= len(groupIds) {
for i, g := range groupIds {
......@@ -432,7 +447,7 @@ func GetMicUserByExternalId(model *domain.Model, externalId string) (*MicUser, e
//麦位上没人,返回nil
func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error) {
if i < 1 || i > 30 {
if i < 1 || i > MaxMicNum {
return nil, myerr.NewSysErrorF("麦序不对,不在范围值内 i:%v", i)
}
str, err := redisCli.GetRedis().Get(context.Background(), redis_key.GetPrefixGroupMicUser(groupUuid, i)).Result()
......@@ -455,6 +470,7 @@ func GetMicUser(model *domain.Model, groupUuid string, i int) (*MicUser, error)
I: i,
ExternalId: micUser.ExternalId,
UserId: micUser.UserId,
CpUserId: micUser.CpUserId,
Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp,
}, nil
......
......@@ -3,6 +3,8 @@ package group_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/bluele/gcache"
"time"
)
type GroupBanned struct {
......@@ -24,12 +26,19 @@ func (banned *GroupBanned) Delete(model *domain.Model) error {
return model.Db.Where(banned).Delete(&GroupBanned{}).Error
}
var bannedGroupCache = gcache.New(100).LRU().Build()
func GetBannedGroups(model *domain.Model) ([]GroupBanned, error) {
key := "banned"
if data, err := bannedGroupCache.Get(key); err == nil {
return data.([]GroupBanned), nil
}
result := make([]GroupBanned, 0)
err := model.Db.Find(&result).Error
err := model.DB().Find(&result).Error
if err != nil {
return nil, err
}
bannedGroupCache.SetWithExpire(key, result, time.Minute*5)
return result, nil
}
......
package group_m
import "git.hilo.cn/hilo-common/domain"
// 获取游戏房
func GetGameGroupsMap(model *domain.Model) map[string]bool {
res := make(map[string]bool)
var rows []GroupInfo
if err := model.DB().Model(GroupInfo{}).Where("is_game_room = 1").Find(&rows).Error; err != nil {
model.Log.Errorf("GetGameGroupsMap fail:%v", err)
return res
}
for _, v := range rows {
res[v.ImGroupId] = true
}
return res
}
......@@ -7,6 +7,7 @@ import (
"git.hilo.cn/hilo-common/utils"
"github.com/bluele/gcache"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/enum/group_e"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
......@@ -46,6 +47,7 @@ type GroupInfo struct {
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
VisitCount int64 `gorm:"-"` // 热度
IsGameRoom uint8 // 是否1v1游戏房
}
func GenerateGroupCode(n uint16) string {
......@@ -566,3 +568,45 @@ func GetFamilyRooms(model *domain.Model, familyId uint64, pageSize, pageIndex in
return res, nextIdx, hasNext, nil
}
func IsUseTRTC(model *domain.Model, imGroupId string) bool {
var count int64
if err := model.DB().Table("group_trtc").Where("im_group_id=?", imGroupId).Count(&count).Error; err != nil {
model.Log.Errorf("IsUseTRTC err:%v, groupId:%s", err, imGroupId)
return false
}
return count > 0
}
type GroupTrtc struct {
mysql.Entity
ImGroupId mysql.Str
}
// 初始化trtc房间
func InitTRTC(model *domain.Model, imGroupId string) error {
if err := model.DB().Model(GroupTrtc{}).Clauses(clause.OnConflict{DoNothing: true}).Create(&GroupTrtc{ImGroupId: imGroupId}).Error; err != nil {
model.Log.Errorf("InitTRTC err:%v, groupId:%s", err, imGroupId)
return err
}
return nil
}
// 初始化trtc房间
func DeleteTRTC(model *domain.Model, imGroupId string) error {
model.Log.Infof("DeleteTRTC , groupId:%s", imGroupId)
if err := model.DB().Model(GroupTrtc{}).Where("im_group_id = ?", imGroupId).Delete(&GroupTrtc{}).Error; err != nil {
model.Log.Errorf("DeleteTRTC err:%v, groupId:%s", err, imGroupId)
return err
}
return nil
}
func CountTRTC(model *domain.Model) int64 {
var total int64
if err := model.DB().Model(GroupTrtc{}).Count(&total).Error; err != nil {
model.Log.Errorf("CountTRTC fail:%v", err)
}
model.Log.Infof("CountTRTC , total:%v", total)
return total
}
......@@ -3,9 +3,11 @@ package group_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/myerr"
"time"
)
//群组勋章
......@@ -30,7 +32,6 @@ func (groupInfo *GroupInfo) GroupMedalMgrAdd(model *domain.Model, resMedalId uin
}
}
func GetGroupMedalOrErr(model *domain.Model, id mysql.ID) (*GroupMedal, error) {
groupMedal := GroupMedal{}
if err := model.Db.Model(&GroupMedal{}).First(&groupMedal, id).Error; err != nil {
......@@ -65,7 +66,11 @@ func BatchGetMedals(db *gorm.DB, groupIds []string) (map[string][]uint64, error)
return nil, nil
}
rows := make([]GroupMedal, 0)
if err := db.Model(&GroupMedal{}).Where("im_group_id IN ?", groupIds).Find(&rows).Error; err != nil {
if err := db.Model(GroupMedal{}).Joins("left join res_medal rm on group_medal.res_medal_id = rm.id").
Where("group_medal.im_group_id IN ?", groupIds).
Where("(group_medal.expire_at is null or group_medal.expire_at > ?)", time.Now().Format(utils.DATETIME_FORMAT)).
Order("rm.sort").
Find(&rows).Error; err != nil {
return nil, err
}
result := make(map[string][]uint64, 0)
......
......@@ -64,6 +64,20 @@ func IsHiddenGroup(db *gorm.DB, groupId string) (bool, error) {
}
}
func IsHiddenGroupBy(model *domain.Model, imGroupId string) bool {
info := new(GroupSetting)
if err := model.DB().Model(GroupSetting{}).Where("group_id = ? and is_hidden = 1", imGroupId).First(&info).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return false
}
return false
}
if info != nil && info.ID > 0 {
return true
}
return false
}
func (gs *GroupSetting) Get(db *gorm.DB) error {
return db.Where(gs).First(gs).Error
}
......
......@@ -23,9 +23,13 @@ func (g *GroupTop) Delete(model *domain.Model) error {
return model.Db.Where(g).Delete(&GroupTop{}).Error
}
func GroupTopGetAll(model *domain.Model) ([]string, error) {
func GroupTopGetAll(model *domain.Model, area int) ([]string, error) {
rows := make([]GroupTop, 0)
err := model.Db.Order("id").Find(&rows).Error
err := model.DB().Table("group_top").
Joins("left join group_info gi on group_top.im_group_id = gi.im_group_id "+
"left join res_country rc on gi.country = rc.name").
Where("rc.area = ?", area).
Order("group_top.id").Find(&rows).Error
if err != nil {
return nil, err
}
......
package group_m
import (
"git.hilo.cn/hilo-common/domain"
"hilo-group/_const/enum/group_e"
"hilo-group/myerr"
"math/rand"
"time"
)
type GroupIm struct {
Id uint64
Provider group_e.GroupProvider
Prob int
StartIdx int `gorm:"-"'`
EndIdx int `gorm:"-"`
}
type GroupImLog struct {
ImGroupId string
Provider group_e.GroupProvider
}
func GetGroupImConf(model *domain.Model) ([]*GroupIm, error) {
rows := make([]*GroupIm, 0)
if err := model.Db.Table("group_im").Find(&rows).Error; err != nil {
return nil, myerr.WrapErr(err)
}
return rows, nil
}
func GetRandomImProvider(model *domain.Model) group_e.GroupProvider {
var res group_e.GroupProvider
confList, err := GetGroupImConf(model)
if err != nil {
model.Log.Errorf("GetRandomImProvider err:%v", err)
return res
}
conf := GetRandomGroupImConf(confList)
return conf.Provider
}
func GetRandomGroupImConf(confList []*GroupIm) *GroupIm {
var res *GroupIm
var max int
for i, v := range confList {
if v.Prob > 0 {
confList[i].StartIdx = max
max += v.Prob
confList[i].EndIdx = max
}
}
rand.Seed(time.Now().UnixNano())
randNum := rand.Intn(max)
for _, v := range confList {
if v.StartIdx <= randNum && randNum < v.EndIdx {
res = v
}
}
return res
}
func CreateGroupImLog(model *domain.Model, imGroupId string, provider group_e.GroupProvider) error {
if err := model.Db.Model(GroupImLog{}).Create(GroupImLog{ImGroupId: imGroupId, Provider: provider}).Error; err != nil {
return myerr.WrapErr(err)
}
return nil
}
......@@ -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 {
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
}
}
}
}
}*/
//加入到麦上可能有人的集合中。
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)
}
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,10 +365,15 @@ func (micUser *MicUser) leave(operateUserId uint64, operateExternalId string) er
}
//
externalId := micUser.ExternalId
if micUser.ExternalId != operateExternalId {
//检查权限,管理人权限, 不过不拥有管理人权限,则抛出错误
if err := MgrPermission(micUser.model, micUser.GroupUuid, operateUserId, micUser.UserId); err != nil {
return err
// 超管处理
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
......@@ -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
}
......
......@@ -45,18 +45,21 @@ type MicContent struct {
}
type MicUserData struct {
Id uint64 `json:"id,omitempty"`
ExternalId string `json:"externalId"`
Avatar string `json:"avatar"`
Nick string `json:"nick"`
Sex uint8 `json:"sex"`
Code string `json:"code"`
IsVip bool `json:"isVip"`
NobleLeave uint16 `json:"noble"` // 当前的贵族等级
HeadwearPicUrl string `json:"headwearPicUrl"`
HeadwearEffectUrl string `json:"headwearEffectUrl"`
SvipLevel int `json:"svipLevel"`
Svip rpc.CvSvip `json:"svip"`
Id uint64 `json:"id,omitempty"`
ExternalId string `json:"externalId"`
Avatar string `json:"avatar"`
Nick string `json:"nick"`
Sex uint8 `json:"sex"`
Code string `json:"code"`
IsVip bool `json:"isVip"`
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,23 +474,27 @@ 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,
ExternalId: user.ExternalId,
Avatar: user.Avatar,
Nick: user.Nick,
Sex: user.Sex,
Code: user.Code,
IsVip: vipFlag,
NobleLeave: nobleMap[id],
HeadwearPicUrl: headwearPicUrl,
HeadwearEffectUrl: headwearEffectUrl,
SvipLevel: svips[id].SvipLevel,
Svip: rpc.CopySimpleSvip(svips[id]),
Id: user.ID,
ExternalId: user.ExternalId,
Avatar: user.Avatar,
Nick: user.Nick,
Sex: user.Sex,
Code: user.Code,
IsVip: vipFlag,
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,19 +533,27 @@ 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,
Avatar: user.Avatar,
Nick: user.Nick,
Sex: user.Sex,
Code: user.Code,
IsVip: flag,
NobleLeave: nobleLeave,
HeadwearPicUrl: headwearPicUrl,
HeadwearEffectUrl: headwearEffectUrl,
SvipLevel: svip.SvipLevel,
Svip: rpc.CopySimpleSvip(svip),
Id: user.ID,
ExternalId: user.ExternalId,
Avatar: user.Avatar,
Nick: user.Nick,
Sex: user.Sex,
Code: user.Code,
IsVip: flag,
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,17 +70,18 @@ func RoomLivingIn(model *domain.Model, groupUid string, userId uint64, externalI
}
//
key := redis_key.GetPrefixGroupRoomLiving()
i, err := redisCli.GetRedis().ZAdd(context.Background(), key, &redis2.Z{
_, err := model.RedisCluster.ZAdd(context.Background(), key, &redis2.Z{
Score: float64(time.Now().Unix()),
Member: getMemberStr(groupUid, userId),
}).Result()
if err != nil {
model.Log.Errorf("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v, err:%v", key, groupUid, userId, err)
} else {
model.Log.Infof("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
//model.Log.Infof("UpdateRoomLiving ZAdd key:%v, groupUid:%v, userId:%v result:%v", key, groupUid, userId, i)
}
go func(myContext *mycontext.MyContext, groupId string) {
model := domain.CreateModelContext(myContext) // 野协程给新的model.Db
roomOnlineUser, err := GetRoomOnlineUser(myContext, groupId)
if err != nil {
myContext.Log.Errorf("room RoomLivingIn roomOnlineUser err:%+v, groupUid:%v", err, groupId)
......@@ -110,11 +112,11 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err)
}
data, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result()
data, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
......@@ -123,12 +125,12 @@ func roomLivingLeave(model *domain.Model, userId uint64, groupId string) ([]stri
for i, _ := range data {
gid, uid := analysisMemberStr(data[i])
if uid == userId && (groupId == "" || gid == groupId) {
if _, err := redisCli.GetRedis().ZRem(context.Background(), key, getMemberStr(gid, uid)).Result(); err != nil {
if _, err := model.RedisCluster.ZRem(context.Background(), key, getMemberStr(gid, uid)).Result(); err != nil {
model.Log.Errorf("RoomLivingLeave ZRem key:%s, groupId:%s, userId:%d, err:%v", key, gid, uid, err)
return nil, myerr.WrapErr(err)
} else {
groupIds = append(groupIds, gid)
model.Log.Infof("RoomLivingLeave ZRem success key:%s, groupId:%s, userId:%d", key, gid, uid)
//model.Log.Infof("RoomLivingLeave ZRem success key:%s, groupId:%s, userId:%d", key, gid, uid)
}
// 发信令,让前端重新拉取,接受容错,
......@@ -207,7 +209,7 @@ func RoomLivingLeaveByKick(model *domain.Model, groupUuid string, beKickuserId u
Target: beKickExternalId,
}, false)*/
MicGroupKickOutRPush(model, groupUuid, userExternalId, beKickExternalId)
MicGroupKickOutRPush(model, groupUuid, userExternalId, beKickExternalId, beKickuserId)
return roomLivingLeave(model, beKickuserId, groupUuid)
}
......@@ -270,15 +272,15 @@ func RoomLivingExistsUserId(groupUid string) ([]uint64, error) {
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
var model = domain.CreateModelNil()
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err)
}
groupUserIdstrs, err := redisCli.GetRedis().ZRevRange(context.Background(), key, 0, -1).Result()
groupUserIdstrs, err := model.RedisCluster.ZRevRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
mylogrus.MyLog.Infof("group_room_living RoomLivingExistsUserId groupUserIdstrs:%v", groupUserIdstrs)
//mylogrus.MyLog.Infof("group_room_living RoomLivingExistsUserId groupUserIdstrs:%v", groupUserIdstrs)
userIds := make([]uint64, 0, len(groupUserIdstrs))
for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
......@@ -298,11 +300,11 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) {
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
model := domain.CreateModelNil()
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
return nil, myerr.WrapErr(err)
}
groupUserIdstrs, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result()
groupUserIdstrs, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
......@@ -323,16 +325,16 @@ func RoomLivingUserIdFilter(userIds []mysql.ID) (map[mysql.ID]string, error) {
func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{}, error) {
key := redis_key.GetPrefixGroupRoomLiving()
//if err := redisCli.ClearExpired(key, expireMinute); err != nil {
if err := model.Redis.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
if err := model.RedisCluster.ZRemRangeByScore(model, key, "0", strconv.FormatInt(time.Now().Unix()-expireMinute, 10)).Err(); err != nil {
model.Log.Infof("RoomLivingExistsGroup: err:%v", err)
return nil, myerr.WrapErr(err)
}
groupUserIdstrs, err := redisCli.GetRedis().ZRange(context.Background(), key, 0, -1).Result()
groupUserIdstrs, err := model.RedisCluster.ZRange(context.Background(), key, 0, -1).Result()
if err != nil {
return nil, myerr.WrapErr(err)
}
model.Log.Infof("group_room_living RoomLivingExistsGroup groupUserIdstrs:%v", groupUserIdstrs)
//model.Log.Infof("group_room_living RoomLivingExistsGroup groupUserIdstrs:%v", groupUserIdstrs)
groupGroup := map[string]map[uint64]struct{}{}
for i, _ := range groupUserIdstrs {
tempGroupUid, userId := analysisMemberStr(groupUserIdstrs[i])
......@@ -342,7 +344,7 @@ func RoomLivingExistsGroup(model *domain.Model) (map[string]map[uint64]struct{},
groupGroup[tempGroupUid] = map[uint64]struct{}{userId: {}}
}
}
model.Log.Infof("RoomLivingExistsGroup size = %d", len(groupGroup))
//model.Log.Infof("RoomLivingExistsGroup size = %d", len(groupGroup))
return groupGroup, nil
}
......@@ -388,18 +390,8 @@ func GetAllGroupsSorted(model *domain.Model) ([]string, error) {
// 取房间最近N天的访问人数
func GetRoomVisitCount(groupId string) (int64, error) {
// 每群定时请一次数据可以了
now := time.Now()
if now.Second()%redis_key.GroupInDurationClearPeriod == 0 {
// 先移除(N天之前的),后统计
if _, err := redisCli.GetRedis().ZRemRangeByScore(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId),
"0", strconv.FormatInt(time.Now().AddDate(0, 0, -redis_key.GroupInDurationTTL).Unix(), 10)).
Result(); err != nil {
return 0, err
}
}
visitCount, err := redisCli.GetRedis().ZCard(context.Background(), redis_key.GetPrefixGroupInUserDuration(groupId)).Result()
key := group_k.GetUserEnterRoomGroupKey(groupId)
visitCount, err := redisCli.GetRedis().ZCard(context.Background(), key).Result()
if err != nil {
return 0, err
}
......@@ -428,15 +420,12 @@ func BatchGetRoomVisitCount(logE *logrus.Entry, groupIds []string) (map[string]i
if err != nil {
return nil, err
}
logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
visitCount := make(map[string]int64)
for _, groupId := range groupIds {
// 先从二级缓存中找
if c, ok := roomVisitCount[groupId]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
logE.Debugf("GetRoomVisitCount, from roomVisitCount %s - %d", groupId, vc)
visitCount[groupId] = vc
}
} else {
......@@ -463,7 +452,7 @@ func BatchGetRoomVisitCountList(logE *logrus.Entry, groupIds []string) (map[stri
if err != nil {
return nil, nil, err
}
logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
//logE.Infof("MGetRoomVisitCount:%v", roomVisitCount)
res := make([]*RoomVisit, 0, len(groupIds))
visitCount := make(map[string]int64)
......@@ -504,7 +493,8 @@ func (uer *UserEnterRoom) Save(db *gorm.DB) error {
func (uer *UserEnterRoom) Find(db *gorm.DB) ([]UserEnterRoom, error) {
rows := make([]UserEnterRoom, 0)
if err := db.Where(uer).Order("enter_time DESC").Find(&rows).Error; err != nil {
t := time.Now().AddDate(0, 0, -15)
if err := db.Where(uer).Where("enter_time >= ?", t).Order("enter_time DESC").Find(&rows).Error; err != nil {
return nil, err
}
return rows, nil
......
......@@ -57,6 +57,24 @@ func GetAllGroupSupportResult(db *gorm.DB, period string) (map[string]uint8, err
return result, nil
}
func GetGroupSupportResult(db *gorm.DB, period string, groupIds []string) (map[string]uint8, error) {
if len(period) <= 0 {
return nil, nil
}
gsr := GroupSupportResult{
Period: period,
}
rows := make([]GroupSupportResult, 0)
if err := db.Where(gsr).Where("group_uid in (?)", groupIds).Find(&rows).Error; err != nil {
return nil, err
}
result := make(map[string]uint8)
for _, i := range rows {
result[i.GroupUid] = i.Grade
}
return result, nil
}
//群组扶持奖励,利益分配者
type GroupSupportAwardAdmin struct {
mysql.Entity
......@@ -102,14 +120,14 @@ func (gsa *GroupSupportAwardMgr) Get(db *gorm.DB) ([]GroupSupportAwardMgr, error
}
//添加记录
func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mysql.ID, resGroupSupportId mysql.ID, userIds []mysql.ID, period string) (*GroupSupportAwardAdmin, []GroupSupportAwardMgr, error) {
//资源获取
resGroupSupport, err := res_m.GetResGroupSupportById(model, resGroupSupportId)
if err != nil {
return nil, nil, err
}
if int(resGroupSupport.MgrNum) < len(userIds) {
return nil, nil, myerr.NewSysErrorF("AddGroupSupportAward mgrNum:%v 同 len(userIds)=%v 不一致", resGroupSupport.MgrNum, len(userIds))
func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mysql.ID, resSupport *res_m.ResGroupSupport, userIds []mysql.ID, period string) (*GroupSupportAwardAdmin, []GroupSupportAwardMgr, error) {
////资源获取
//resGroupSupport, err := res_m.GetResGroupSupportById(model, resGroupSupportId)
//if err != nil {
// return nil, nil, err
//}
if int(resSupport.MgrNum) < len(userIds) {
return nil, nil, myerr.NewSysErrorF("AddGroupSupportAward mgrNum:%v 同 len(userIds)=%v 不一致", resSupport.MgrNum, len(userIds))
}
//增加群主奖励
......@@ -118,9 +136,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys
GroupUid: groupUid,
IssuerUserId: issuerUserId,
UserId: issuerUserId,
DiamondNum: resGroupSupport.AdminAward,
Grade: resGroupSupport.Grade,
ResGroupSupportId: resGroupSupport.ID,
DiamondNum: resSupport.AdminAward,
Grade: resSupport.Grade,
ResGroupSupportId: resSupport.ID,
Period: period,
}
......@@ -133,9 +151,9 @@ func AddGroupSupportAward(model *domain.Model, groupUid string, issuerUserId mys
GroupUid: groupUid,
IssuerUserId: issuerUserId,
UserId: userIds[i],
DiamondNum: resGroupSupport.MgrAward,
Grade: resGroupSupport.Grade,
ResGroupSupportId: resGroupSupport.ID,
DiamondNum: resSupport.MgrAward,
Grade: resSupport.Grade,
ResGroupSupportId: resSupport.ID,
Period: period,
})
}
......
......@@ -103,7 +103,9 @@ func (rb *RoomBanner) GetRoomBanners(db *gorm.DB, vcAllow bool) ([]RoomBanner, e
}
res := make([]RoomBanner, 0, len(rows))
for _, v := range rows {
if !vcAllow && v.ID == 241 {
// 版本控制
if !vcAllow && (v.ID == 241 || v.ID == 781 || v.ID == 771 || v.ID == 911 || v.ID == 841 ||
v.ID == 851 || v.ID == 1001 || v.ID == 981 || v.ID == 1451 || v.ID == 1621) {
continue
}
res = append(res, v)
......
package mic_m
import (
"git.hilo.cn/hilo-common/_const/enum/timezone_e"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hilo-group/_const/redis_key/mic_k"
"time"
)
......@@ -17,14 +19,15 @@ type UserOnMic struct {
LastCalTs int64
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
Tz timezone_e.Timezone
}
// 获取用户当日上麦
// 允许返回gorm.ErrRecordNotFound
func GetUserOnMic(model *domain.Model, userId mysql.ID) (*UserOnMic, error) {
func GetUserOnMic(model *domain.Model, userId mysql.ID, tz timezone_e.Timezone) (*UserOnMic, error) {
res := new(UserOnMic)
day := time.Now().Format("2006-01-02")
if err := model.DB().Where("date = ? AND user_id = ?", day, userId).First(res).Error; err != nil {
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
if err := model.DB().Where("date = ? AND user_id = ? AND tz = ?", day, userId, tz).First(res).Error; err != nil {
return nil, err
}
return res, nil
......@@ -34,48 +37,90 @@ func GetUserOnMic(model *domain.Model, userId mysql.ID) (*UserOnMic, error) {
// 事务操作
func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
omMic, err := GetUserOnMic(model, userId)
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
day0Ts := utils.GetZeroTime(time.Now()).Unix()
if omMic != nil && joinMicTimestamp < omMic.LastCalTs { // 加入的时间比上次计算时间小
curTs = omMic.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
day := time.Now().Format("2006-01-02")
onMicNew := &UserOnMic{
Date: day,
UserId: userId,
Seconds: mysql.Num(score),
LastCalTs: nowTs,
for _, tz := range timezone_e.Timezones {
omMic, err := GetUserOnMic(model, userId, tz)
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
day0Ts := utils.GetZeroTime(time.Now().In(timezone_e.TimezoneLocMap[tz])).Unix()
if omMic != nil && joinMicTimestamp < omMic.LastCalTs { // 加入的时间比上次计算时间小
curTs = omMic.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
onMicNew := &UserOnMic{
Date: day,
UserId: userId,
Seconds: mysql.Num(score),
LastCalTs: nowTs,
Tz: tz,
}
if err := model.DB().Model(UserOnMic{}).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}, {Name: "tz"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"seconds": gorm.Expr("seconds + ?", onMicNew.Seconds),
"last_cal_ts": nowTs,
}),
}).Create(onMicNew).Error; err != nil {
model.Log.Errorf("IncrUserOnMic fail:%v", err)
return err
}
}
return nil
})
}
// 增加用户上麦时长
// 事务操作
func IncrUserOnMicV2(model *domain.Model, userId mysql.ID) error {
for _, tz := range timezone_e.Timezones {
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
if err := model.DB().Model(UserOnMic{}).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}},
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}, {Name: "tz"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"seconds": gorm.Expr("seconds + ?", onMicNew.Seconds),
"last_cal_ts": nowTs,
"seconds": gorm.Expr("seconds + ?", 60),
}),
}).Create(onMicNew).Error; err != nil {
}).Create(&UserOnMic{
Date: day,
UserId: userId,
Seconds: 60,
Tz: tz,
}).Error; err != nil {
model.Log.Errorf("IncrUserOnMic fail:%v", err)
return err
}
return nil
})
}
return nil
}
// 增加用户上麦时长
// Redis
func IncrUserOnMicV3(model *domain.Model, userId mysql.ID) error {
for _, tz := range timezone_e.Timezones {
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
tzStr := "bj"
if tz == timezone_e.TimezoneKSA {
tzStr = "ksa"
}
tzKey := mic_k.GetUserOnMicKey(userId, tzStr, day)
model.RedisCluster.IncrBy(model, tzKey, 60)
model.RedisCluster.Expire(model, tzKey, time.Hour*24*30) // 30天上麦时长
}
return nil
}
// 批量获取用户上麦时长
// @return userId->seconds
func MGetUserOnMicSeconds(model *domain.Model, day string, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
func MGetUserOnMicSeconds(model *domain.Model, day string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
var rows []UserOnMic
res := make(map[mysql.ID]mysql.Num)
if err := model.DB().Model(UserOnMic{}).Where("`date`= ? AND user_id in ?", day, userIds).Find(&rows).Error; err != nil {
if err := model.DB().Model(UserOnMic{}).Where("`date`= ? AND tz = ? AND user_id in ?", day, tz, userIds).Find(&rows).Error; err != nil {
model.Log.Errorf("MGetUserOnMic fail:%v", err)
return res, err
}
......@@ -84,3 +129,18 @@ func MGetUserOnMicSeconds(model *domain.Model, day string, userIds []uint64) (ma
}
return res, nil
}
// 批量获取用户上麦时长
// @return userId->seconds
func MGetUserOnMicSecondsRange(model *domain.Model, beginDate, endDate string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
var rows []UserOnMic
res := make(map[mysql.ID]mysql.Num)
if err := model.DB().Model(UserOnMic{}).Where("`date` >= ? AND `date` <= ? AND tz = ? AND user_id in ?", beginDate, endDate, tz, userIds).Find(&rows).Error; err != nil {
model.Log.Errorf("MGetUserOnMic fail:%v", err)
return res, err
}
for _, r := range rows {
res[r.UserId] += r.Seconds
}
return res, nil
}
......@@ -144,7 +144,7 @@ func BatchGetActiveNoble(db *gorm.DB, userIds []uint64) (map[uint64]UserNoble, e
start += NUM
end += NUM
}
mylogrus.MyLog.Infof("BatchGetActiveNoble expected:%v,actual:%v,notEndUids:%v", len(userIds), len(result), notEndUids)
//mylogrus.MyLog.Infof("BatchGetActiveNoble expected:%v,actual:%v,notEndUids:%v", len(userIds), len(result), notEndUids)
if len(userIds) != len(result) {
mylogrus.MyLog.Warnf("BatchGetActiveNoble expected:%v", userIds)
}
......@@ -177,4 +177,4 @@ func BatchGetNobleLevel(db *gorm.DB, userIds []uint64) (map[uint64]uint16, error
result[i] = m[i].Level
}
return result, nil
}
\ No newline at end of file
}
......@@ -23,6 +23,7 @@ type ResCountry struct {
StandardShortName mysql.Str
AreaCode mysql.Str
AreaCodeName mysql.Str
Area mysql.Str
}
type ResLanguage struct {
......@@ -81,6 +82,22 @@ func GetAllCountries(model *domain.Model) (map[string]string, error) {
return result, nil
}
// 获取所有国家的Area信息
func GetAllCountriesArea(model *domain.Model) (map[string]string, error) {
var countrys []ResCountry
if err := model.Db.Model(&ResCountry{}).Where(&ResCountry{
Status: mysql.USER,
}).Find(&countrys).Error; err != nil {
return nil, myerr.WrapErr(err)
}
result := make(map[string]string, 0)
for _, i := range countrys {
result[i.Name] = i.Area
}
return result, nil
}
func GetAllCountryByFilter(model *domain.Model, shortNames []string) ([]ResCountry, error) {
var countrys []ResCountry
if err := model.Db.Model(&ResCountry{}).Where(&ResCountry{
......@@ -197,3 +214,9 @@ func GetLangeByCountry(db *gorm.DB, country mysql.Str) (string, error) {
}
}
//获取所有国家名字列表
func GetCountryNameList(model *domain.Model) ([]string, error) {
res := make([]string, 0)
err := model.DB().Table("res_country").Select("distinct(name) name").Pluck("name", &res).Error
return res, myerr.WrapErr(err)
}
......@@ -10,10 +10,11 @@ import (
type ResHeadwear struct {
mysql.Entity
*domain.Model `gorm:"-"`
Name mysql.Str
PicUrl mysql.Str
EffectUrl mysql.Str
*domain.Model `gorm:"-"`
Name mysql.Str
PicUrl mysql.Str
EffectUrl mysql.Str
ReverseEffectUrl mysql.Str
}
func GetResHeadwearById(model *domain.Model, id mysql.ID) (*ResHeadwear, error) {
......
......@@ -325,7 +325,7 @@ func GetOnlineStatus(model *domain.Model, extIds []string) (map[string]uint, err
model.Log.Warnf("getOnlineStatus redis failed")
left = extIds
} else {
model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r)
//model.Log.Infof("getOnlineStatus redis return size = %d: %v", len(r), r)
if len(r) >= len(extIds) {
for i, e := range extIds {
......@@ -387,10 +387,10 @@ func getOnlineStatus(extIds []string) ([]interface{}, error) {
for _, e := range extIds {
keys = append(keys, redis_key.GetOnLineStatusKey(e))
}
return redisCli.RedisClient.MGet(context.Background(), keys...).Result()
return redisCli.RedisClusterClient.MGet(context.Background(), keys...).Result()
}
func setOnlineStatus(extId string, status uint, ttl time.Duration) error {
key := redis_key.GetOnLineStatusKey(extId)
return redisCli.RedisClient.Set(context.Background(), key, status, ttl).Err()
return redisCli.RedisClusterClient.Set(context.Background(), key, status, ttl).Err()
}
......@@ -3,10 +3,12 @@ package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr"
)
//获取用户的国家,和所属的区域(是否阿语区)
// 获取用户的国家,和所属的区域(是否阿语区)
// 默认国家给沙特
func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
type info struct {
Name string
......@@ -14,7 +16,11 @@ func GetUserCountryArea(model *domain.Model, id mysql.ID) (string, int, error) {
}
res := new(info)
if err := model.DB().Raw("select name, area from res_country where name = (select country from user where id = ?)", id).First(&res).Error; err != nil {
return "", 0, myerr.WrapErr(err)
if err != gorm.ErrRecordNotFound {
return "", 0, myerr.WrapErr(err)
}
// gorm.ErrRecordNotFound
return "KSA", 1, nil
}
return res.Name, res.Area, nil
}
......@@ -48,8 +48,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
if err != nil {
return nil, err
}
logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes)
logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList)
//logger.Infof("GetUserMedalLevelMap, user %d, medalMap %+v", medalTypes)
//logger.Infof("GetUserMedalLevelMap, user %d, medalList %+v", medalList)
maxGrades := make(map[uint8]int, 0)
maxMedalIds := make(map[uint8]uint32, 0)
......@@ -70,8 +70,8 @@ func GetUserMedalMerge(logger *logrus.Entry, db *gorm.DB, userId mysql.ID) ([]ui
}
}
}
logger.Infof("maxGrade %+v", maxGrades)
logger.Infof("maxMedalIds %+v", maxMedalIds)
//logger.Infof("maxGrade %+v", maxGrades)
//logger.Infof("maxMedalIds %+v", maxMedalIds)
mIds := result
result = make([]uint32, 0)
......
......@@ -3,13 +3,17 @@ package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr"
"strings"
)
type SuperManager struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId mysql.ID
IsAll bool
Countries string
}
func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) {
......@@ -22,6 +26,33 @@ func IsSuperManager(model *domain.Model, userId mysql.ID) (bool, error) {
return n > 0, nil
}
// 对某人是否有超管权限
func IsSuperManagerV2(model *domain.Model, userId, targetUserId mysql.ID) (bool, error) {
var man SuperManager
if err := model.Db.Model(&SuperManager{}).Where(&SuperManager{
UserId: userId,
}).First(&man).Error; err != nil {
if err != gorm.ErrRecordNotFound {
model.Log.Errorf("IsSuperManagerV2 fail:%v", err)
}
return false, nil
}
if man.IsAll {
return true, nil
}
targetUser, err := GetUser(model, targetUserId)
if err != nil {
return false, err
}
countries := strings.Split(man.Countries, ",")
for _, c := range countries {
if c == targetUser.Country {
return true, nil
}
}
return false, nil
}
func GetSuperManagerAll(model *domain.Model) ([]uint64, error) {
superManagers := []SuperManager{}
if err := model.Db.Model(&SuperManager{}).Find(&superManagers).Error; err != nil {
......@@ -51,4 +82,4 @@ func GetSuperManagerMap(userIds []uint64) (map[uint64]bool, error) {
rs[superManagers[i].UserId] = true
}
return rs, nil
}
\ No newline at end of file
}
......@@ -85,12 +85,29 @@ func GetUsersByIds(model *domain.Model, userIds []mysql.ID) ([]User, error) {
return users, nil
}
// 分批获取userIds
func GetUserMapByIds(model *domain.Model, userIds []mysql.ID) (map[mysql.ID]User, error) {
rows, err := GetUsersByIds(model, userIds)
if err != nil {
return nil, err
}
result := make(map[mysql.ID]User, 0)
end := 500
if end > len(userIds) {
end = len(userIds)
}
var rows []User
start := 0
for start < len(userIds) {
tmp, err := GetUsersByIds(model, userIds[start:end])
if err != nil {
return result, err
} else {
rows = append(rows, tmp...)
}
start += 500
end += 500
if end > len(userIds) {
end = len(userIds)
}
//model.Log.Infof("GetUserMapByIds start:%v-end:%v", start, end)
}
for _, i := range rows {
result[i.ID] = i
}
......@@ -127,3 +144,39 @@ func GetUsers(model *domain.Model, ids []mysql.ID) ([]*User, error) {
}
return res, nil
}
// 获取用户externalIds
// return []externalIds map[userId]extId map[userId]code
func GetUserExternalIds(model *domain.Model, userIds []mysql.ID) ([]string, map[uint64]string, map[uint64]string) {
var res []string
var m = make(map[uint64]string)
var c = make(map[uint64]string)
if len(userIds) <= 0 {
return res, m, c
}
var users []User
total := len(userIds)
const NUM = 500
start, end := 0, NUM
for start < total {
if end > total {
end = total
}
var tmp []User
tmpUserId := userIds[start:end]
if err := model.DB().Model(User{}).Where("id in (?)", tmpUserId).Select("id,external_id,code").Find(&tmp).Error; err != nil {
model.Log.Errorf("GetUserExternalIds fail:%v", err)
} else if len(tmp) > 0 {
users = append(users, tmp...)
}
start += NUM
end += NUM
}
for _, user := range users {
res = append(res, user.ExternalId)
m[user.ID] = user.ExternalId
c[user.ID] = user.Code
}
return res, m, c
}
......@@ -59,14 +59,34 @@ func GetVip(db *gorm.DB, userId uint64) (*UserVip, error) {
return nil, nil
}
// 分批获取
func BatchGetVips(userIds []uint64) (map[uint64]*int64, error) {
result := make(map[uint64]*int64, 0)
rows := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds).Find(&rows).Error
if err != nil {
return nil, err
end := 500
if end > len(userIds) {
end = len(userIds)
}
start := 0
for start < len(userIds) {
tmp := make([]UserVip, 0)
err := mysql.Db.Where("user_id IN ?", userIds[start:end]).Find(&tmp).Error
if err != nil {
return nil, err
}
if err != nil {
return result, err
} else {
rows = append(rows, tmp...)
}
start += 500
end += 500
if end > len(userIds) {
end = len(userIds)
}
//mylogrus.MyLog.Infof("BatchGetVips start:%v-end:%v", start, end)
}
result := make(map[uint64]*int64, 0)
for _, i := range userIds {
result[i] = nil
}
......
......@@ -8,6 +8,7 @@ import (
"hilo-group/domain/model/diamond_m"
"hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/res_m"
"hilo-group/domain/model/user_m"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
)
......@@ -24,6 +25,22 @@ func NewDiamondService(myContext *mycontext.MyContext) *DiamondService {
// 币商转账钻石-家族限制检查
func (this *DiamondService) CheckDealerTransferFamilyLimit(dealerId, userId uint64, lang string) error {
model := domain.CreateModelContext(this.svc.MyContext)
//获取国家信息
_, dealerArea, err := user_m.GetUserCountryArea(model, dealerId)
if err != nil {
model.Log.Errorf("CheckDealerTransferFamilyLimit 获取国家资源错误 dealerId:%d, err:%v", dealerId, err)
return err
}
_, area, err := user_m.GetUserCountryArea(model, userId)
if err != nil {
model.Log.Errorf("CheckDealerTransferFamilyLimit 获取国家资源错误 userId:%d, err:%v", userId, err)
return err
}
if dealerArea != area {
return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_CHARGE_NO_AREA, lang, bizerr.DealerCannotSaleToOtherArea))
}
// 代理、用户是否加入了家族
dealerFamily, err := groupPower_m.GetGroupPowerUserOrNil(model, dealerId)
if err != nil {
......@@ -40,25 +57,25 @@ func (this *DiamondService) CheckDealerTransferFamilyLimit(dealerId, userId uint
return err
}
// 用户的家族是否有家族代理
var userHasFamilyAgent bool
if userFamily != nil {
userHasFamilyAgent, err = groupPower_m.IsGroupPowerHasFamilyAgent(model, userFamily.GroupPowerId)
if err != nil {
return err
}
}
//var userHasFamilyAgent bool
//if userFamily != nil {
// userHasFamilyAgent, err = groupPower_m.IsGroupPowerHasFamilyAgent(model, userFamily.GroupPowerId)
// if err != nil {
// return err
// }
//}
if dealerFamily != nil && dealerFamily.GroupPowerId > 0 { // 代理加入了家族
if isFamilyAgent && (userFamily == nil || userFamily.GroupPowerId != dealerFamily.GroupPowerId) { // 是家族代理:只能向本家族成员转移钻石,如果向非家族成员转移钻石,则提示“非家族成员”
return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_NOT_FAMILY_MEMBER, lang, bizerr.GroupPowerDealerNotMember))
}
if !isFamilyAgent && userHasFamilyAgent { // 不是家族代理:如果用户加入了家族,且家族中有家族代理,那么也不能,“此用户已有家族代理,不能出售钻石”
return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_DEALER_CAN_NOT_SOLE, lang, bizerr.GroupPowerDealerCanNotSole))
}
//if !isFamilyAgent && userHasFamilyAgent { // 不是家族代理:如果用户加入了家族,且家族中有家族代理,那么也不能,“此用户已有家族代理,不能出售钻石”
// return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_DEALER_CAN_NOT_SOLE, lang, bizerr.GroupPowerDealerCanNotSole))
//}
} else { // 代理没有加入家族的
// 普通代理:不能向已经加入家族的成员(并且家族有家族代理)转移钻石,如果转移则提示“此用户已有家族代理,不能出售钻石”
if userHasFamilyAgent {
return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_DEALER_CAN_NOT_SOLE, lang, bizerr.GroupPowerDealerCanNotSole))
}
//if userHasFamilyAgent {
// return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, common.MSG_ID_DEALER_CAN_NOT_SOLE, lang, bizerr.GroupPowerDealerCanNotSole))
//}
}
return nil
}
......@@ -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)
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 {
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 {
cpEvent := &event_m.EventGiftSend{
Entity: mysql.Entity{
ID: events[k].ID,
......@@ -49,31 +48,30 @@ 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
}
if err := gift_ev.PublishSendGiftEvent(model, sendGiftEvent); err != nil {
model.Log.Errorf("PublishSendGiftEvent fail,event:%v,err:%v", string(cpEvent.Payload), err)
return err
continue
}
// 标记已经处理
// 标记已经处理,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
})
}
// 最后一次提交offset
if len(events) > 0 {
offset.MarkOffset = events[len(events)-1].ID
return offset.Persistence()
}
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 {
offset.MarkOffset = events[len(events)-1].ID
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
if err == nil {
return levels, nil
}
model.Log.Debugf("GetSupportLevelMap, GET %s: %v", period, levels)
// cache miss
result := make(map[string]uint8, 0)
if len(levels) > 0 {
for g, l := range levels {
le, err := strconv.ParseUint(l, 10, 8)
if err == nil {
result[g] = uint8(le)
}
}
} else {
result, err = group_m.GetAllGroupSupportResult(model.Db, period)
if err == nil {
ret, err := SaveAllSupportLevel(model, period, result)
model.Log.Infof("GetSupportLevelMap SAVE ret = %d, err: %v", ret, err)
}
result, err := group_m.GetAllGroupSupportResult(model.Db, period)
if err == nil {
SaveAllSupportLevel(model, period, result)
}
return result, nil
}
func SaveAllSupportLevel(model *domain.Model, date string, levels map[string]uint8) (int64, error) {
values := make(map[string]interface{}, 0)
for g, l := range levels {
if l > 0 {
values[g] = l
}
}
if len(values) <= 0 {
return 0, nil
}
key := redis_key.GetPrefixSupportLevel(date)
ret, err := model.Redis.HSet(model, key, values).Result()
//// 取本周最高的扶持等级
//func (s *GroupService) GetWeekMaxSupportLevelMapByIds(groupIds []string) (map[string]uint8, error) {
// return s.GetSupportLevelMapByIds(groupIds, time.Now().AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
//}
//
//func (s *GroupService) GetSupportLevelMapByIds(groupIds []string, now time.Time) (map[string]uint8, error) {
// model := domain.CreateModel(s.svc.CtxAndDb)
//
// _, _, period := group_m.GetSupportLevelTime(now)
//
// levels, err := GetAllSupportLevel(model, period)
// if err == nil {
// return levels, nil
// }
// // cache miss
//
// result, err := group_m.GetGroupSupportResult(model.DB(), period, groupIds)
// if err == nil {
// SaveAllSupportLevel(model, period, result)
// }
// return result, nil
//}
if err == nil {
// 设置一个TTL保险一些 TODO: 可以优化,保证数据总是有的
ttl := time.Hour
if !config.AppIsRelease() {
ttl = time.Minute
}
model.Redis.Expire(model, key, ttl)
}
return ret, err
// supportLevelLru Cache
var supportLevelCache = gcache.New(100).LRU().Build()
func SaveAllSupportLevel(model *domain.Model, date string, levels map[string]uint8) {
key := redis_key.GetPrefixSupportLevel(date)
_ = supportLevelCache.SetWithExpire(key, levels, time.Hour)
return
}
func GetAllSupportLevel(model *domain.Model, date string) (map[string]string, error) {
func GetAllSupportLevel(model *domain.Model, date string) (map[string]uint8, error) {
key := redis_key.GetPrefixSupportLevel(date)
return model.Redis.HGetAll(model, key).Result()
if data, err := supportLevelCache.Get(key); err == nil {
return data.(map[string]uint8), nil
} else {
return map[string]uint8{}, err
}
}
func (s *GroupService) GetJoinGroupLimit(userId mysql.ID) (uint, error) {
......
package group_s
import (
"context"
"git.hilo.cn/hilo-common/_const/rediskey"
"git.hilo.cn/hilo-common/domain"
"github.com/go-redis/redis/v8"
"hilo-group/_const/enum/gift_e"
"hilo-group/cv/gift_cv"
"hilo-group/domain/cache/room_c"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/res_m"
"sort"
"strconv"
"time"
)
func SortGroupCommonCountryList(model *domain.Model) {
// 常用的国家
countryMap := map[string]struct{}{"India": {}, "Indonesia": {}, "Iraq": {}, "KSA": {}, "Kuwait": {}, "Pakistan": {}, "Turkey": {}}
for country, _ := range countryMap {
sortGroupList, err := GetGroupSortList(model, country)
if err != nil {
model.Log.Errorf("SortGroupCommonCountryList err:%v", err)
return
}
// 写入redis
err = setToRedis(model, country, sortGroupList)
if err != nil {
model.Log.Errorf("SortGroupCommonCountryList country:%v, len(sortGroupList):%v, err:%v", country, len(sortGroupList), err)
return
}
time.Sleep(time.Second * 3)
}
}
func SortGroupNotCommonCountryList(model *domain.Model) {
// 常用的国家
countryMap := map[string]struct{}{"India": {}, "Indonesia": {}, "Iraq": {}, "KSA": {}, "Kuwait": {}, "Pakistan": {}, "Turkey": {}}
// 取所有的国家名字
allCountryList, err := res_m.GetCountryNameList(model)
if err != nil {
model.Log.Errorf("SortGroupNotCommonCountryList err:%v", err)
return
}
for _, country := range allCountryList {
if _, ok := countryMap[country]; ok {
continue
}
// 计算非常用国家
sortGroupList, err := GetGroupSortList(model, country)
if err != nil {
model.Log.Errorf("SortGroupNotCommonCountryList err:%v", err)
return
}
// 写入redis
err = setToRedis(model, country, sortGroupList)
if err != nil {
model.Log.Errorf("SortGroupNotCommonCountryList country:%v, len(sortGroupList):%v, err:%v", country, len(sortGroupList), err)
return
}
time.Sleep(time.Second * 5)
}
}
func setToRedis(model *domain.Model, country string, groupList []string) error {
// 写入redis
key := rediskey.GetGroupCountrySortList(country)
for idx, group := range groupList {
err := model.RedisCluster.ZRemRangeByRank(context.Background(), key, int64(idx), int64(idx)).Err() // 先删除旧的
if err != nil {
model.Log.Errorf("setToRedis SortGroup key:%v, idx:%v, err:%v", key, idx, err)
return err
}
// 插入
err = model.RedisCluster.ZAdd(context.Background(), key, &redis.Z{Score: float64(idx), Member: group}).Err()
if err != nil {
model.Log.Errorf("setToRedis SortGroup key:%v, idx:%v, group:%s, err:%v", key, idx, group, err)
return err
}
if idx%1000 == 0 {
time.Sleep(time.Millisecond * 50)
}
}
return nil
}
// 计算国家群组列表排序
func GetGroupSortList(model *domain.Model, country string) ([]string, error) {
bannedGroups, err := group_m.GetBannedGroupsMap(model)
if err != nil {
return nil, err
}
beginTime := time.Now()
groups, banCount, visitCount, err := GetCandidatesByCountry(model, bannedGroups, country)
if err != nil {
return nil, err
}
endTime := time.Now()
model.Log.Infof("GroupCountryListSort: candidates size = %d, takes %d ms banned = %d, visitCount size = %d",
len(groups), endTime.Sub(beginTime).Milliseconds(), banCount, len(visitCount))
// 获取麦上有人的所有群组及麦上人数
micGroupNum, err := group_m.GetMicHasInGroupNum(model)
if err != nil {
return nil, err
}
model.Log.Infof("GroupCountryListSort, micGroupNum : %v", micGroupNum)
model.Log.Infof("GroupCountryListSort cost2:%v", time.Now().Sub(beginTime))
sortedGroupIds := make([]string, 0)
diamondGroupIds := make([]string, 0)
for i, _ := range groups {
// 麦上没人也放出来
sortedGroupIds = append(sortedGroupIds, i)
// 麦上有人才计算流水
if micGroupNum[i] > 0 {
diamondGroupIds = append(diamondGroupIds, i)
}
}
now := time.Now()
bTime := now.Add(-time.Minute * 30)
g := gift_cv.GiftOperate{SceneType: gift_e.GroupSceneType}
diamonds, err := g.GetRangeConsumeSummaryV2(bTime, now, diamondGroupIds)
if err != nil {
return nil, err
}
model.Log.Infof("GroupCountryListSort, diamonds in 30 mins: %v", diamonds)
model.Log.Infof("GroupCountryListSort cost3:%v", time.Now().Sub(beginTime))
//supportLevels, err := NewGroupService(model.MyContext).GetWeekMaxSupportLevelMap()
//if err != nil {
// return nil, err
//}
//model.Log.Infof("GroupCountryListSort, supportLevels : %v", supportLevels)
model.Log.Infof("GroupCountryListSort cost4:%v", time.Now().Sub(beginTime))
// 排序优先级2022-07-25
sort.Slice(sortedGroupIds, func(i, j int) bool {
gi := sortedGroupIds[i]
gj := sortedGroupIds[j]
// 1、按麦上人数多少排序
if micGroupNum[gi] > micGroupNum[gj] {
return true
} else if micGroupNum[gi] < micGroupNum[gj] {
return false
}
// 2、麦上人数相同,按30分钟内送礼钻石数排序
if diamonds[gi] > diamonds[gj] {
return true
} else if diamonds[gi] < diamonds[gj] {
return false
}
// 3. 根据热度排序groupInUserDuration
if visitCount[gi] > visitCount[gj] {
return true
} else if visitCount[gi] < visitCount[gj] {
return false
}
// * Final resort: 群组CODE,短号优先,然后按字母序
return len(groups[gi].Code) < len(groups[gj].Code) || len(groups[gi].Code) == len(groups[gj].Code) && groups[gi].Code < groups[gj].Code
})
model.Log.Infof("GroupCountryListSort cost5:%v", time.Now().Sub(beginTime))
return sortedGroupIds, nil
}
// 国家群候选:没有密码且没被封禁的群, 有国家
func GetCandidatesByCountry(model *domain.Model, bannedGroups map[string]uint64, country string) (map[string]*group_m.GroupInfo, int, map[string]int64, error) {
noPwdGroups, err := group_m.FindOwnerCountryGroups(model, country)
if err != nil {
return nil, 0, nil, err
}
var groupIds []string
for _, v := range noPwdGroups {
groupIds = append(groupIds, v.ImGroupId) // imGroupId
}
//roomVisitCount, err := room_c.GetAllRoomVisitCount()
roomVisitCount, err := room_c.MGetRoomVisitCount(groupIds)
if err != nil {
return nil, 0, nil, err
}
gameRoom := group_m.GetGameGroupsMap(model)
banCount := 0
groups := make(map[string]*group_m.GroupInfo, 0)
visitCount := make(map[string]int64)
for i, v := range noPwdGroups {
// 过滤掉被封禁的群
if bannedGroups[v.ImGroupId] != 0 {
banCount++
continue
}
// 过滤游戏房
if gameRoom[v.ImGroupId] {
continue
}
// 先从二级缓存中找
if c, ok := roomVisitCount[v.ImGroupId]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
//model.Log.Debugf("getPopularCandidates, from roomVisitCount %s(%s) - %d", v.ImGroupId, v.Code, vc)
groups[v.ImGroupId] = &noPwdGroups[i]
visitCount[v.ImGroupId] = vc
}
} else {
// 如果没有,就从roomVisit中取
if vc, err := room_c.GetSetRoomVisitCount(v.ImGroupId); err == nil && vc > 0 {
model.Log.Infof("getPopularCandidates, from roomVisit %s(%s) - %d", v.ImGroupId, v.Code, vc)
groups[v.ImGroupId] = &noPwdGroups[i]
visitCount[v.ImGroupId] = vc
}
}
}
return groups, banCount, visitCount, nil
}
func GetVisitCount(groupIds []string) (map[string]int64, error) {
roomVisitCount, err := room_c.MGetRoomVisitCount(groupIds)
if err != nil {
return nil, err
}
visitCount := make(map[string]int64)
for _, v := range groupIds {
// 先从二级缓存中找
if c, ok := roomVisitCount[v]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
visitCount[v] = vc
}
} else {
// 如果没有,就从roomVisit中取
if vc, err := room_c.GetSetRoomVisitCount(v); err == nil && vc > 0 {
visitCount[v] = vc
}
}
}
return visitCount, nil
}
......@@ -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
}
channelId, token, err = agora.CreateGroupAgora(groupInfo.ChannelId, uint32(userId))
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,86 +28,157 @@ func (s *GroupService) GroupSupportList(groupId string, uids []uint64) ([]uint64
result := make([]uint64, 0)
out := make([]uint64, 0)
err := s.svc.Transactional(func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
model := domain.CreateModel(s.svc.CtxAndDb)
// 1. 去掉非群管理者
roles, _, err := group_m.GetRolesInGroup(model, groupId)
if err != nil {
return err
}
userIds := make([]uint64, 0)
for _, i := range uids {
if _, ok := roles[i]; ok {
userIds = append(userIds, i)
} else {
out = append(out, i)
model.Log.Infof("GroupSupportList: rule out %d, no role", i)
}
// 1. 去掉非群管理者
roles, _, err := group_m.GetRolesInGroup(model, groupId)
if err != nil {
model.Log.Errorf("GroupSupportList groupId:%v, uids:%v, err:%v", groupId, uids, err)
return nil, nil, err
}
userIds := make([]uint64, 0)
for _, i := range uids {
if _, ok := roles[i]; ok {
userIds = append(userIds, i)
} else {
out = append(out, i)
model.Log.Infof("GroupSupportList: rule out %d, no role", i)
}
}
// TODO: 去掉非群成员
// TODO: 去掉非群成员
//(4)1个账户只能做1个群组的管理员(5)1个设备下只允许领取1个管理奖励
_, _, period := group_m.GetLastSupportPeriod(time.Now())
gsa := group_m.GroupSupportAwardMgr{Period: period}
rows, err := gsa.Get(model.Db)
if err != nil {
model.Log.Errorf("GroupSupportList groupId:%v, uids:%v, err:%v", groupId, uids, err)
return nil, nil, err
}
awards := make(map[uint64]struct{}, 0)
for _, i := range rows {
awards[i.UserId] = struct{}{}
}
//(4)1个账户只能做1个群组的管理员(5)1个设备下只允许领取1个管理奖励
_, _, period := group_m.GetLastSupportPeriod(time.Now())
gsa := group_m.GroupSupportAwardMgr{Period: period}
rows, err := gsa.Get(model.Db)
uids = userIds
userIds = make([]uint64, 0)
m := make(map[uint64]uint64)
for _, u := range uids {
m, err := user_m.GetSameImeiMap(model, u)
if err != nil {
return err
model.Log.Errorf("GroupSupportList groupId:%v, uids:%v, err:%v", groupId, uids, err)
return nil, nil, err
}
awards := make(map[uint64]struct{}, 0)
for _, i := range rows {
awards[i.UserId] = struct{}{}
}
uids = userIds
userIds = make([]uint64, 0)
m := make(map[uint64]uint64)
for _, u := range uids {
m, err := user_m.GetSameImeiMap(model, u)
if err != nil {
return err
}
passed := true
for _, i := range m {
if _, ok := awards[i]; ok {
if i == u {
passed = false
model.Log.Infof("GroupSupportList: rule out %d, already awarded", i)
} else {
passed = false
model.Log.Infof("GroupSupportList: rule out %d, imei awarded", i)
}
passed := true
for _, i := range m {
if _, ok := awards[i]; ok {
if i == u {
passed = false
model.Log.Infof("GroupSupportList: rule out %d, already awarded", i)
} else {
passed = false
model.Log.Infof("GroupSupportList: rule out %d, imei awarded", i)
}
}
if passed == true {
userIds = append(userIds, u)
} else {
out = append(out, u)
}
}
model.Log.Infof("GroupSupportList: uids %v, map %v", uids, m)
_, supportLevel, err := s.GetSupportLevel(groupId)
if err != nil {
return err
if passed == true {
userIds = append(userIds, u)
} else {
out = append(out, u)
}
}
model.Log.Infof("GroupSupportList: uids %v, map %v", uids, m)
if uint32(len(userIds)) > supportLevel {
model.Log.Infof("GroupSupportList: rule out %v, limit exeeded", userIds[supportLevel:])
out = append(out, userIds[supportLevel:]...)
userIds = userIds[0:supportLevel]
}
result = userIds
return nil
})
if err == nil {
return result, out, nil
} else {
return nil, nil, err
if uint32(len(userIds)) > supportLevel {
model.Log.Infof("GroupSupportList: rule out %v, limit exeeded", userIds[supportLevel:])
out = append(out, userIds[supportLevel:]...)
userIds = userIds[0:supportLevel]
}
result = userIds
return result, out, nil
//err := s.svc.Transactional(func() error {
// model := domain.CreateModel(s.svc.CtxAndDb)
//
// // 1. 去掉非群管理者
// roles, _, err := group_m.GetRolesInGroup(model, groupId)
// if err != nil {
// return err
// }
// userIds := make([]uint64, 0)
// for _, i := range uids {
// if _, ok := roles[i]; ok {
// userIds = append(userIds, i)
// } else {
// out = append(out, i)
// model.Log.Infof("GroupSupportList: rule out %d, no role", i)
// }
// }
//
// // TODO: 去掉非群成员
//
// //(4)1个账户只能做1个群组的管理员(5)1个设备下只允许领取1个管理奖励
// _, _, period := group_m.GetLastSupportPeriod(time.Now())
// gsa := group_m.GroupSupportAwardMgr{Period: period}
// rows, err := gsa.Get(model.Db)
// if err != nil {
// return err
// }
// awards := make(map[uint64]struct{}, 0)
// for _, i := range rows {
// awards[i.UserId] = struct{}{}
// }
//
// uids = userIds
// userIds = make([]uint64, 0)
// m := make(map[uint64]uint64)
// for _, u := range uids {
// m, err := user_m.GetSameImeiMap(model, u)
// if err != nil {
// return err
// }
//
// passed := true
// for _, i := range m {
// if _, ok := awards[i]; ok {
// if i == u {
// passed = false
// model.Log.Infof("GroupSupportList: rule out %d, already awarded", i)
// } else {
// passed = false
// model.Log.Infof("GroupSupportList: rule out %d, imei awarded", i)
// }
// }
// }
// if passed == true {
// userIds = append(userIds, u)
// } else {
// out = append(out, u)
// }
// }
// model.Log.Infof("GroupSupportList: uids %v, map %v", uids, m)
//
// _, supportLevel, err := s.GetSupportLevel(groupId)
// if err != nil {
// return err
// }
//
// if uint32(len(userIds)) > supportLevel {
// model.Log.Infof("GroupSupportList: rule out %v, limit exeeded", userIds[supportLevel:])
// out = append(out, userIds[supportLevel:]...)
// userIds = userIds[0:supportLevel]
// }
// result = userIds
// return nil
//})
//
//if err == nil {
// return result, out, nil
//} else {
// return nil, nil, err
//}
}
func (s *GroupService) GetSupportLevel(groupId string) (uint64, uint32, error) {
......@@ -124,17 +202,50 @@ func (s *GroupService) GetSupportLevel(groupId string) (uint64, uint32, error) {
return 0, 0, nil
}
func (s *GroupService) GetSupportLevelByRedis(groupId string) (*res_m.ResGroupSupport, uint32, error) {
model := domain.CreateModel(s.svc.CtxAndDb)
_, _, period := group_m.GetLastSupportPeriod(time.Now())
consume, count, err := GetGroupConsumeCount(model, groupId, period)
if err != nil {
return nil, 0, err
}
rec, err := res_m.GetResGroupSupportBy(model, count, consume)
if err != nil {
return nil, 0, err
}
if rec != nil {
return rec, rec.MgrNum, nil
}
return rec, 0, nil
}
func GetGroupConsumeCount(model *domain.Model, imGroupId, period string) (uint64, uint32, error) {
// 流水
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
consume, err := model.RedisCluster.ZScore(context.Background(), keyDiamond, imGroupId).Result()
if err != nil && err != redis.Nil {
model.Log.Errorf("GetSupportLevelByRedis key:%v, groupId:%v, err:%v", keyDiamond, imGroupId, err)
return 0, 0, err
}
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, imGroupId)
count, err := model.RedisCluster.SCard(context.Background(), keySupportNum).Result()
if err != nil && err != redis.Nil {
model.Log.Errorf("GetSupportLevelByRedis key:%v, groupId:%v, err:%v", keySupportNum, imGroupId, err)
return 0, 0, err
}
return uint64(consume), uint32(count), nil
}
//群组支持奖励
func (s *GroupService) GroupSupportAward(groupId string, profitAllocator uint64, userIds []uint64, resId uint64, period string) error {
func (s *GroupService) GroupSupportAward(groupId string, profitAllocator uint64, userIds []uint64, resSupport *res_m.ResGroupSupport,
period string, groupInfo *group_m.GroupInfo) error {
return s.svc.Transactional(func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
//
groupInfo, err := group_m.GetGroupInfo(model, groupId)
if groupInfo == nil {
return bizerr.GroupNotFound
}
//发放奖励
groupSupportAwardAdmin, groupSupportAwardMgrs, err := group_m.AddGroupSupportAward(model, groupId, profitAllocator, resId, userIds, period)
groupSupportAwardAdmin, groupSupportAwardMgrs, err := group_m.AddGroupSupportAward(model, groupId, profitAllocator, resSupport, userIds, period)
if err != nil {
return err
}
......@@ -173,3 +284,128 @@ func (s *GroupService) RenewGroupSupporter(groupId string, userIds []uint64) err
return nil
})
}
func (s *GroupService) GroupSupportResult(time time.Time) error {
model := domain.CreateModelContext(s.svc.MyContext)
_, _, period := group_m.GetSupportLevelTime(time)
// 群组扶持数值
groupGradeMap, err := getGroupGradeMap(model, period)
if err != nil {
model.Log.Errorf("GroupSupportResult time:%v, err:%v", time, err)
return err
}
model.Log.Infof("GroupSupportResult period:%s, len:%d, groupUidGadeMap:%v", period, len(groupGradeMap), groupGradeMap)
// 房间访问人数
roomVisitCount, err := GetAllRoomNonZeroVisitCount()
if err != nil {
model.Log.Errorf("GroupSupportResult err:%v", err)
return err
}
// 入库群组扶持结果
for g, grade := range groupGradeMap {
r := group_m.InitGroupSupportResult(model, g, grade, period, roomVisitCount[g])
r.SetOnDuplicateKeyIGNORE()
if err = r.Persistent(); err != nil {
model.Log.Errorf("GroupSupportResult InitGroupSupportResult r:%+v, err:%v", r, err)
}
}
// 小助手通知
AssistantNotification(model, groupGradeMap)
return nil
}
func getGroupGradeMap(model *domain.Model, period string) (map[string]uint8, error) {
// 配置
gsConfig, err := res_m.GetResGroupSupportByValid(model)
if err != nil {
model.Log.Errorf("GroupSupportResult err:%v", err)
return nil, err
}
// 群组扶持数值
groupGradeMap := make(map[string]uint8, 0)
//userNum := make(map[string]uint32, 0)
// 流水
keyDiamond := rediskey.GetGroupSupportConsumeSummary(period)
var start int64
count := int64(999)
var zList []redis.Z
// 一次取1000个处理
for start == 0 || len(zList) > 0 {
stop := start + count
zList, err = model.RedisCluster.ZRangeWithScores(context.Background(), keyDiamond, start, stop).Result()
if err != nil {
model.Log.Errorf("GroupSupportResult err:%v", err)
return nil, err
}
if len(zList) == 0 {
break
}
for _, v := range zList {
imGroupId := v.Member.(string)
consume := mysql.Num(v.Score)
// 支持者数量
keySupportNum := rediskey.GetGroupSupportCountSupporter(period, imGroupId)
supportNum, err := model.RedisCluster.SCard(context.Background(), keySupportNum).Result()
if err != nil {
model.Log.Errorf("GroupSupportResult key:%s, err:%v", keySupportNum, err)
return nil, err
}
for j := len(gsConfig) - 1; j >= 0; j-- {
if mysql.Num(supportNum) >= gsConfig[j].ContributeUserNum && consume >= gsConfig[j].ContributeDiamondNum {
groupGradeMap[imGroupId] = gsConfig[j].Grade
//userNum[imGroupId] = uint32(supportNum)
break
}
}
}
start = stop + 1
}
return groupGradeMap, nil
}
func AssistantNotification(model *domain.Model, groupGradeMap map[string]uint8) {
// 小助手通知
for g, _ := range groupGradeMap {
userId, err := group_m.GetProfitAllocator(model, g)
if err != nil {
model.Log.Errorf("GroupSupportResult msg GetProfitAllocator err:%v, groupUid:%v", err, g)
continue
}
//推送
user, err := user_m.GetUser(model, userId)
if err != nil {
model.Log.Infof("GroupSupportResult msg GetUser userId:=%v, err:=%v", userId, err)
continue
}
record := msg_m.NewUserRecord(model, user.ID, msg_e.GroupSupportResult, "", 0, "", "", "", "", "")
if err := record.Persistent(); err != nil {
model.Log.Infof("GroupSupportResult msg record.Persistent() err:%v", err)
continue
}
msg_m.SendEmasMsgAssistant(model, user.ExternalId, user.DeviceType)
}
}
func GetAllRoomNonZeroVisitCount() (map[string]uint, error) {
m, err := GetAllRoomVisitCount()
if err != nil {
return nil, err
}
result := make(map[string]uint, 0)
for g, s := range m {
if c, err := strconv.Atoi(s); err == nil && c > 0 {
result[g] = uint(c)
}
}
return result, nil
}
func GetAllRoomVisitCount() (map[string]string, error) {
key := rediskey.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HGetAll(context.Background(), key).Result()
}
......@@ -93,6 +93,7 @@ require (
github.com/tencentyun/tls-sig-api-v2-golang v1.0.0 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e // indirect
......
......@@ -401,6 +401,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
......
......@@ -11,6 +11,8 @@ MYSQL_DB=hilo_code
[REDIS]
REDIS_HOST=47.244.34.27:6379
REDIS_PASSWORD=8QZ9JD1zLvPR3yHf
REDIS_CLUSTER_HOST=47.244.34.27:6379
REDIS_CLUSTER_PASSWORD=8QZ9JD1zLvPR3yHf
[JWT]
SECRET=hilo1632
ISSUER_API=hiloApi
......@@ -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)) // 启动服务
......
......@@ -49,26 +49,27 @@ var (
GroupMicBanTourist = myerr.NewBusinessCode(12010, "Mic need member", myerr.BusinessData{}) // 游客不能上麦
// 群组
GroupNotFound = myerr.NewBusinessCode(14001, "Group not found", myerr.BusinessData{}) // 找不到该群
NotGroupMember = myerr.NewBusinessCode(14002, "Not a group member", myerr.BusinessData{}) // 不是群成员
IncorrectPassword = myerr.NewBusinessCode(14003, "Incorrect password", myerr.BusinessData{}) // 密码错
NoPrivileges = myerr.NewBusinessCode(14004, "Not enough permission", myerr.BusinessData{}) // 操作权限不够
InBlacklist = myerr.NewBusinessCode(14005, "Can not join the group due to blacklist", myerr.BusinessData{}) // 在群黑名单中,不能进群
GroupInKick = myerr.NewBusinessCode(14007, "Kicked, can not join the group. Try again later", myerr.BusinessData{}) // 在被踢出的有效期中
OwnerCannotLeave = myerr.NewBusinessCode(14008, "Owner can not leave the group", myerr.BusinessData{}) // 群主不能退群
WrongPasswordLength = myerr.NewBusinessCode(14010, "Incorrect password length", myerr.BusinessData{}) // 密码长度错误
GroupIsBanned = myerr.NewBusinessCode(14011, "group is banned by ", myerr.BusinessData{}) // 群已经被管理员封禁
GroupLimitReached = myerr.NewBusinessCode(14012, "Join group limit reached", myerr.BusinessData{}) // 所在群已达上限
RoleLimitReached = myerr.NewBusinessCode(14013, "Role limit reached", myerr.BusinessData{}) // 所任角色已达上限
GroupCreateLimitReached = myerr.NewBusinessCode(14014, "Create group limit reached", myerr.BusinessData{}) // 你创建的群组数已达上限
GroupLimitReachedVip = myerr.NewBusinessCode(14015, "Join group limit reached. Please purchase VIP", myerr.BusinessData{}) // 所在群已达上限,请购买VIP
GroupAlreadyAwarded = myerr.NewBusinessCode(14016, "Group support awarded", myerr.BusinessData{}) // 群支持奖励已经发放过了
NotManagerOrAdmin = myerr.NewBusinessCode(14017, "Not manager or group admin", myerr.BusinessData{}) // 不是经理或管理员
UserAlreadyAwarded = myerr.NewBusinessCode(14018, "User already awarded", myerr.BusinessData{}) // 用户的群支持奖励已经发放过了
ImeiAlreadyAwarded = myerr.NewBusinessCode(14019, "Imei support awarded", myerr.BusinessData{}) // 设备的群支持奖励已经发放过了
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使用此权限
GroupNotFound = myerr.NewBusinessCode(14001, "Group not found", myerr.BusinessData{}) // 找不到该群
NotGroupMember = myerr.NewBusinessCode(14002, "Not a group member", myerr.BusinessData{}) // 不是群成员
IncorrectPassword = myerr.NewBusinessCode(14003, "Incorrect password", myerr.BusinessData{}) // 密码错
NoPrivileges = myerr.NewBusinessCode(14004, "Not enough permission", myerr.BusinessData{}) // 操作权限不够
InBlacklist = myerr.NewBusinessCode(14005, "Can not join the group due to blacklist", myerr.BusinessData{}) // 在群黑名单中,不能进群
GroupInKick = myerr.NewBusinessCode(14007, "Kicked, can not join the group. Try again later", myerr.BusinessData{}) // 在被踢出的有效期中
OwnerCannotLeave = myerr.NewBusinessCode(14008, "Owner can not leave the group", myerr.BusinessData{}) // 群主不能退群
WrongPasswordLength = myerr.NewBusinessCode(14010, "Incorrect password length", myerr.BusinessData{}) // 密码长度错误
GroupIsBanned = myerr.NewBusinessCode(14011, "group is banned by ", myerr.BusinessData{}) // 群已经被管理员封禁
GroupLimitReached = myerr.NewBusinessCode(14012, "Join group limit reached", myerr.BusinessData{}) // 所在群已达上限
RoleLimitReached = myerr.NewBusinessCode(14013, "Role limit reached", myerr.BusinessData{}) // 所任角色已达上限
GroupCreateLimitReached = myerr.NewBusinessCode(14014, "Create group limit reached", myerr.BusinessData{}) // 你创建的群组数已达上限
GroupLimitReachedVip = myerr.NewBusinessCode(14015, "Join group limit reached. Please purchase VIP", myerr.BusinessData{}) // 所在群已达上限,请购买VIP
GroupAlreadyAwarded = myerr.NewBusinessCode(14016, "Group support awarded", myerr.BusinessData{}) // 群支持奖励已经发放过了
NotManagerOrAdmin = myerr.NewBusinessCode(14017, "Not manager or group admin", myerr.BusinessData{}) // 不是经理或管理员
UserAlreadyAwarded = myerr.NewBusinessCode(14018, "User already awarded", myerr.BusinessData{}) // 用户的群支持奖励已经发放过了
ImeiAlreadyAwarded = myerr.NewBusinessCode(14019, "Imei support awarded", myerr.BusinessData{}) // 设备的群支持奖励已经发放过了
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{}) // 已经加入了其它国家势力
......@@ -93,12 +94,16 @@ var (
GroupPowerUserHaveNoJoin = myerr.NewBusinessCode(15020, "User have no joined power", myerr.BusinessData{}) // 还未加入国家势力
GroupPowerChangeNameplate = myerr.NewBusinessCode(15021, "Can only be modified at the silver level", myerr.BusinessData{}) // 修改铭牌不够等级
GroupPowerMemberMax = myerr.NewBusinessCode(15022, "The family size has reached the upper limit", myerr.BusinessData{}) // 家族人数达到上限
GroupPowerCannotJoin = myerr.NewBusinessCode(15023, "You cannot join", myerr.BusinessData{}) // 不能加入家族
DealerCannotSaleToOtherArea = myerr.NewBusinessCode(15024, "Fail", myerr.BusinessData{}) // 代理转账失败-不同地区
TaskHasAward = myerr.NewBusinessCode(19001, "task has award", myerr.BusinessData{})
//贵族
NobleNoMicSpeechCloseLevel5 = myerr.NewBusinessCode(21001, "Can't mute the King", myerr.BusinessData{}) //无法禁言贵族5
NobleNoKickLevel5 = myerr.NewBusinessCode(21002, "Can't kick the King", myerr.BusinessData{}) //无法禁言贵族5
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{})
......
......@@ -72,3 +72,18 @@ VALUES ('zh', '', '你已加入家族,和朋友们一起快乐玩耍吧!', '
('hi', '', 'आप परिवार में शामिल हो गए हैं, आइए अपने दोस्तों के साथ मस्ती करें!', '', 1, 53, 0, ''),
('vi', '', 'Bạn đã tham gia gia đình, hãy vui vẻ với bạn bè của bạn!', '', 1, 53, 0, ''),
('ur', '', 'آپ خاندان میں شامل ہو گئے ہیں، آئیے اپنے دوستوں کے ساتھ مزے کریں!', '', 1, 53, 0, '');
INSERT INTO hilo.res_msg_translate (`language`, title, content, icon_url, msg_type, `type`, action_type, action_url)
VALUES ('zh', '', '有新朋友申请加入你的家族叻,请尽快审核。', '', 1, 54, 0, ''),
('en', '', 'There are new friends applying to join your family, please review as soon as possible.', '', 1, 54,0, ''),
('ar', '', 'هناك أصدقاء جدد يتقدمون للانضمام إلى عائلتك ، يرجى المراجعة في أقرب وقت ممكن.', '', 1, 54, 0, ''),
('tr', '', 'Ailenize katılmak için başvuran yeni arkadaşlar var, lütfen en kısa zamanda gözden geçirin.', '', 1,54, 0, ''),
('id', '', 'Ada teman baru yang melamar untuk bergabung dengan keluarga Anda, harap tinjau sesegera mungkin.','', 1, 54, 0, ''),
('ru', '', 'Есть новые друзья, подающие заявку на присоединение к вашей семье, пожалуйста, просмотрите их как можно скорее.', '', 1, 54, 0, ''),
('ko', '', '가족에 가입하려는 새로운 친구가 있습니다. 가능한 한 빨리 검토하십시오.', '', 1, 54, 0, ''),
('pt', '', 'Há novos amigos se inscrevendo para se juntar à sua família, revise o mais rápido possível.', '', 1, 54, 0, ''),
('th', '', 'มีเพื่อนใหม่สมัครเข้าร่วมครอบครัวของคุณ โปรดตรวจสอบโดยเร็วที่สุด', '', 1, 54, 0, ''),
('ca', '', 'Hay nuevos amigos que solicitan unirse a su familia, revíselos lo antes posible.', '', 1, 54, 0, ''),
('hi', '', 'आपके परिवार में शामिल होने के लिए नए मित्र आवेदन कर रहे हैं, कृपया जल्द से जल्द समीक्षा करें।', '', 1, 54, 0, ''),
('vi', '', 'Có những người bạn mới đăng ký tham gia gia đình của bạn, vui lòng xem xét càng sớm càng tốt.', '', 1, 54, 0, ''),
('ur', '', 'آپ کے خاندان میں شامل ہونے کے لیے نئے دوست درخواست دے رہے ہیں، براہ کرم جلد از جلد جائزہ لیں۔', '', 1, 54, 0, '');
\ No newline at end of file
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"
......@@ -53,20 +54,38 @@ import (
// @Router /v1/groupPower/user [post]
func GroupPowerJoin(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
groupPowerId, err := strconv.ParseUint(c.PostForm("groupPowerId"), 10, 64)
if err != nil {
return myContext, err
}
//获取用户
userId, err := req.GetUserId(c)
if err != nil {
return myContext, err
}
if err := group_power_s.NewGroupPowerService(myContext).GroupPowerUserJoin(groupPowerId, userId); err != nil {
return myContext, err
}
resp.ResponseOk(c, nil)
return myContext, nil
return myContext, bizerr.UpgradeRequired
// 旧版本(3.5.0以下),提示升级
//_, major, minor, _, err := req.GetAppVersion(c)
//if err != nil {
// return myContext, err
//}
//if major <= 3 && minor < 5 {
// return myContext, bizerr.UpgradeRequired
//}
//
//groupPowerId, err := strconv.ParseUint(c.PostForm("groupPowerId"), 10, 64)
//if err != nil {
// return myContext, err
//}
////获取用户
//userId, err := req.GetUserId(c)
//if err != nil {
// return myContext, err
//}
//
//// Aoxi要求不能让这些人加入家族
//banUserMap := map[uint64]bool{251: true, 1384611: true, 4223511: true, 4338751: true, 4339471: true, 4339541: true,
// 4354581: true, 6541: true, 23971: true}
//if _, ok := banUserMap[userId]; ok {
// return myContext, bizerr.GroupPowerCannotJoin
//}
//
//if err := group_power_s.NewGroupPowerService(myContext).GroupPowerUserJoin(groupPowerId, userId); err != nil {
// return myContext, err
//}
//resp.ResponseOk(c, nil)
//return myContext, nil
}
// @Tags 国家势力
......@@ -756,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)
......@@ -801,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)
}
......@@ -958,6 +978,15 @@ func GroupPowerApplyJoin(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil {
return myContext, myerr.WrapErr(err)
}
// Aoxi要求不能让这些人加入家族
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
}
model := domain.CreateModelContext(myContext)
// 判断家族是否存在
......@@ -983,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
}
......@@ -994,6 +1024,18 @@ func GroupPowerApplyJoin(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
// 找到家族管理员们
mgrList, err := groupPower_m.GetGroupPowerMgrList(model, gpInfo.ID)
if err != nil {
model.Log.Errorf("GroupPowerApplyJoin err:%v, id:%v", err, gpInfo.ID)
} else {
for _, v := range mgrList {
// 发小助手通知用户
msg.SendLittleAssistantMsg(model, v, 0, "", "", "", "", "")
//msg.SendLittleAssistantMsg(model, v, msg_e.GroupPowerApplyJoinMsg, "", "", "", "", "")
}
}
resp.ResponseOk(c, nil)
return myContext, nil
}
......@@ -1026,6 +1068,12 @@ func GroupPowerApplyPass(c *gin.Context) (*mycontext.MyContext, error) {
if err != nil {
return myContext, err
}
// Aoxi要求不能让这些人加入家族
banUserMap := map[uint64]bool{251: true, 1384611: true, 4223511: true, 4338751: true, 4339471: true, 4339541: true,
4354581: true, 6541: true, 23971: true}
if _, ok := banUserMap[optUser.ID]; ok {
return myContext, bizerr.GroupPowerHaveNoPower
}
// 判断是否加入了家族
gpU := groupPower_m.GroupPowerUser{UserId: userId}
......@@ -1056,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
}
// 判断家族是否满人了
......@@ -1068,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
}
......@@ -1108,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
......@@ -1182,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.踢人"
......@@ -1469,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) {
......@@ -1511,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
......@@ -1521,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,74 +48,97 @@ 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)
}
response := group_power_cv.CvGroupPowerRank{}
myGroupPower, err := groupPower_m.GetGroupPowerUserOrNil(model, userId)
if err != nil {
return myContext, err
}
if myGroupPower != nil {
ids = append(ids, myGroupPower.GroupPowerId)
}
grades, err := groupPower_m.MGetGroupPowerGrade(model, ids)
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
}
groupPowers, err := groupPower_m.MGetGroupPowerInfoMap(model, ids)
var model = domain.CreateModelContext(myContext)
// 国家区域
var area int
// 我的家族
myGroupPower, err := groupPower_m.GetGroupPowerUserOrNil(model, userId)
if err != nil {
return myContext, err
}
if myGroupPower != nil {
myGroupPowerRank, err := groupPower_m.GetMyGroupPowerExpRank(model, beginDate, endDate, myGroupPower.GroupPowerId)
if myGroupPower != nil && myGroupPower.GroupPowerId > 0 {
//获取势力主
mgrUserId, err := groupPower_m.GetGroupPowerMgr(model, myGroupPower.GroupPowerId)
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,
_, area, err = user_m.GetUserCountryArea(model, mgrUserId)
if err != nil {
model.Log.Errorf("GroupPowerMonthRankAct 获取国家资源错误 userId:%d, err:%v", userId, err)
return myContext, err
}
}
for _, v := range rank {
if response.MyGroupPower != nil && v.GroupPowerId == response.MyGroupPower.Id {
response.MyGroupPower.Rank = v.Rank
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
}
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+
// 这个月
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
}
resp.ResponseOk(c, response)
// 上月
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
}
if response.MyGroupPower != nil {
response.MyGroupPower.StarList, err = group_power_s.GetGroupPowerStar(model, response.MyGroupPower.Id, groupPower_e.GroupPowerStarTypeFamous, 0, 10, month)
}
if err != nil {
return response, err
}
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
}
}
return response, nil
}
// @Tags 国家势力
// @Summary 家族日周月榜单top3
// @Param token header string true "token"
......@@ -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) {
// 版本控制
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,15 +943,174 @@ func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
if _, ok := roomUserMap[u]; ok {
inRoom = true
}
result.Members = append(result.Members, group_cv.MemberDetail{
CvUserExtend: userExtends[u],
Role: roles[u],
OnlineStatus: statusMap[users[u].ExternalId],
InRoom: inRoom,
result.Members = append(result.Members, group_cv.GroupVisitorsDetail{
CvGroupMember: user_cv.CvUserExtendToCvGroupMember(userExtends[u]),
Role: roles[u],
OnlineStatus: statusMap[users[u].ExternalId],
InRoom: inRoom,
})
}
}
resp.ResponseOk(c, result)
// 清理15天之前的访客
group_c.RemoveRoomVisitors(model, groupId)
return myContext, nil
}
// @Tags 群组
// @Summary 最近访问列表
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupId path string true "群ID"
// @Param pageSize query int false "分页大小 默认:10" default(10)
// @Param pageIndex query int false "第几个分页,从1开始 默认:1" default(1)
// @Success 200 {object} GetGroupVisitorsRsp
// @Router /v1/imGroup/visitors/{groupId} [get]
func GetGroupVisitorsV2(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
groupId := c.Param("groupId")
if len(groupId) <= 0 {
return myContext, bizerr.ParaMissing
}
pageSize, err := strconv.Atoi(c.Query("pageSize"))
if err != nil || pageSize <= 0 {
pageSize = 10
}
pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
if err != nil || pageIndex <= 0 {
pageIndex = 1
}
userId, _, err := req.GetUserIdAndExtId(c, myContext)
if err != nil {
return myContext, err
}
model := domain.CreateModelContext(myContext)
groupId, err = group_m.ToImGroupId(model, groupId)
if err != nil {
return myContext, err
}
// 获取最近进房用户
rows := group_c.GetLastRoomVisitors(model, groupId)
userIds := make([]uint64, 0)
for _, u := range rows {
userIds = append(userIds, u)
}
result := GetGroupVisitorsRsp{Total: uint(len(userIds))}
beginPos := pageSize * (pageIndex - 1)
if uint(beginPos) < result.Total {
// 取在线状态
extIds, userExtIdMap, userCodeMap := user_m.GetUserExternalIds(model, userIds)
statusMap, err := tim_m.GetOnlineStatus(model, extIds)
if err != nil {
return myContext, err
}
result.Online = 0
for _, v := range statusMap {
if v == online_e.IM_STATUS_ON_LINE {
result.Online++
}
}
// 获取群组角色
roles, _, err := group_m.GetRolesInGroup(model, groupId)
if err != nil {
return myContext, err
}
// 获取贵族
nobleLevels := user_c.BatchGetNobleLevel(model, userIds)
// 获取svip
svipLevels := user_c.MGetUserSvipLevel(model, userIds)
// 获取svip
vips := user_c.BatchGetVips(model, userIds)
roomUsers, err := group_m.RoomLivingExistsUserId(groupId)
if err != nil {
return myContext, err
}
roomUserMap := utils.SliceToMapUInt64(roomUsers)
// 排序规则 :在房间的优先,其次是在线,再次看角色,最后看贵族
sort.Slice(userIds, func(i, j int) bool {
ui := userIds[i]
uj := userIds[j]
_, ok1 := roomUserMap[ui]
_, ok2 := roomUserMap[uj]
if ok1 && !ok2 {
return true
} else if ok1 == ok2 {
ei := userExtIdMap[ui]
ej := userExtIdMap[uj]
if statusMap[ei] > statusMap[ej] {
return true
}
if statusMap[ei] == statusMap[ej] {
if roles[ui] > roles[uj] {
return true
}
if roles[ui] == roles[uj] {
// SVIP>贵族5>贵族4>贵族3>贵族2>VIP
if svipLevels[ui] > svipLevels[uj] {
return true
} else if svipLevels[ui] == svipLevels[uj] {
if nobleLevels[ui] > nobleLevels[uj] && nobleLevels[ui] >= 2 {
return true
}
if nobleLevels[ui] == nobleLevels[uj] || nobleLevels[ui] < 2 && nobleLevels[uj] < 2 {
if vips[ui] != nil {
if vips[uj] == nil {
return true
} else {
return userCodeMap[ui] < userCodeMap[uj]
}
} else if vips[uj] == nil {
return userCodeMap[ui] < userCodeMap[uj]
}
}
}
}
}
}
return false
})
endPos := pageSize * pageIndex
if endPos > len(userIds) {
endPos = len(userIds)
}
userIds = userIds[beginPos:endPos]
userExtends, err := user_cv.BatchGetUserExtend(model, userIds, userId) // 这里只是取出pageSize=10条数据
if err != nil {
return myContext, err
}
for _, u := range userIds {
inRoom := false
if _, ok := roomUserMap[u]; ok {
inRoom = true
}
result.Members = append(result.Members, group_cv.GroupVisitorsDetail{
CvGroupMember: user_cv.CvUserExtendToCvGroupMember(userExtends[u]),
Role: roles[u],
OnlineStatus: statusMap[userExtIdMap[u]],
InRoom: inRoom,
})
}
}
resp.ResponseOk(c, result)
// 清理15天之前的访客,定期
if time.Now().Second() == 0 {
group_c.RemoveRoomVisitors(model, groupId)
}
return myContext, nil
}
......@@ -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
}
roomVisitCount, err := room_c.GetAllRoomVisitCount()
countryShortName := c.Query("countryShortName")
if countryShortName == "" {
return myContext, myerr.NewSysError("countryShortName 为必填项")
}
pageSize, err := strconv.Atoi(c.Query("pageSize"))
if err != nil || pageSize <= 0 {
pageSize = 10
}
pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
if err != nil || pageIndex <= 0 {
pageIndex = 1
}
model := domain.CreateModelContext(myContext)
// 从redis分页取群组id
sortedGroupIds := make([]string, 0, pageSize)
beginPos := int64(pageSize * (pageIndex - 1))
endPos := int64(pageSize*pageIndex - 1)
key := rediskey.GetGroupCountrySortList(countryShortName)
zList, err := model.RedisCluster.ZRangeWithScores(context.Background(), key, beginPos, endPos).Result()
if err != nil {
return nil, 0, nil, err
model.Log.Errorf("GetGroupByCountry err:%v", err)
return myContext, err
}
for _, v := range zList {
sortedGroupIds = append(sortedGroupIds, v.Member.(string))
}
banCount := 0
groups := make(map[string]*group_m.GroupInfo, 0)
visitCount := make(map[string]int64)
for i, v := range noPwdGroups {
// 过滤掉被封禁的群
if bannedGroups[v.ImGroupId] != 0 {
banCount++
continue
hotGroupList := make([]*group_m.GroupInfo, 0)
// * 同语言区 ^ 麦上有人 + 开放群 - 需要等级的群
for _, i := range sortedGroupIds {
gInfo, err := group_m.GetGroupInfo(model, i)
if err != nil {
model.Log.Errorf("GetGroupByCountry err:%v", err)
return myContext, err
}
hotGroupList = append(hotGroupList, gInfo)
}
total, err := model.RedisCluster.ZCard(context.Background(), key).Uint64()
if err != nil {
model.Log.Errorf("GetGroupByCountry err:%v", err)
return myContext, err
}
// 先从二级缓存中找
if c, ok := roomVisitCount[v.ImGroupId]; ok {
if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
//model.Log.Debugf("getPopularCandidates, from roomVisitCount %s(%s) - %d", v.ImGroupId, v.Code, vc)
// 返回结果
result := make([]group_cv.PopularGroupInfo, 0)
groups[v.ImGroupId] = &noPwdGroups[i]
visitCount[v.ImGroupId] = vc
}
} else {
// 如果没有,就从roomVisit中取
if vc, err := room_c.GetSetRoomVisitCount(v.ImGroupId); err == nil && vc > 0 {
model.Log.Infof("getPopularCandidates, from roomVisit %s(%s) - %d", v.ImGroupId, v.Code, vc)
groupIds := make([]string, 0)
owners := make([]uint64, 0)
for _, i := range hotGroupList {
groupIds = append(groupIds, i.ImGroupId)
owners = append(owners, i.Owner)
}
powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners)
if err != nil {
return myContext, err
}
groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds)
if err != nil {
return myContext, err
}
resMedal, err := res_m.MedalGetAllMap(model.Db)
if err != nil {
return myContext, err
}
countryInfo, err := res_c.GetCountryIconMap(model)
if err != nil {
return myContext, err
}
groups[v.ImGroupId] = &noPwdGroups[i]
visitCount[v.ImGroupId] = vc
rr := rocket_m.RocketResult{}
maxStageMap, err := rr.GetMaxStage(model.DB(), groupIds)
if err != nil {
return myContext, err
}
roomCount, err := group_m.BatchGetRoomCount(model, groupIds)
if err != nil {
return nil, err
}
// 正在进行的游戏
games := game_m.GetNotEndGamesMap(model)
// 扶持等级
supportLevels, err := group_s.NewGroupService(myContext).GetWeekMaxSupportLevelMap()
if err != nil {
return myContext, err
}
visitCount, err := group_s.GetVisitCount(groupIds)
if err != nil {
model.Log.Errorf("GetGroupByCountry err:%v", err)
return myContext, err
}
// 获取麦上人数
micGroupNum, err := group_m.GetMicHasInGroupNum(model)
if err != nil {
return myContext, err
}
for _, i := range hotGroupList {
var maxStage *uint16 = nil
if s, ok := maxStageMap[i.ImGroupId]; ok {
maxStage = &s
}
medals := make([]medal_cv.PicElement, 0)
if m, ok := groupMedals[i.ImGroupId]; ok {
for _, j := range m {
mId := uint32(j)
if e, ok := resMedal[mId]; ok {
medals = append(medals, medal_cv.PicElement{
PicUrl: e.PicUrl,
})
}
}
}
// 补上房间流水勋章
var pe *medal_cv.PicElement
_, pe, err = medal_cv.GetGroupConsumeMedal(model, i.ImGroupId)
if err != nil {
model.Log.Infof("GetGroupByCountry: GetGroupConsumeMedal: %s", err.Error())
} else if pe != nil {
medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl})
}
var password *string = nil
if len(i.Password) > 0 && i.Owner != myUserId {
emptyStr := ""
password = &emptyStr
}
result = append(result, group_cv.PopularGroupInfo{
GroupInfo: group_cv.GroupInfo{
GroupBasicInfo: group_cv.GroupBasicInfo{
GroupId: i.TxGroupId,
Name: i.Name,
Introduction: i.Introduction,
Notification: i.Notification,
FaceUrl: i.FaceUrl,
Code: i.Code,
CountryIcon: countryInfo[i.Country],
Password: password,
SupportLevel: supportLevels[i.ImGroupId],
GroupInUserDuration: visitCount[i.ImGroupId],
MicNumType: int(i.MicNumType),
GroupMedals: medals,
},
HasOnMic: micGroupNum[i.ImGroupId] > 0,
GroupPowerId: powerIds[i.Owner],
GroupPowerName: powerNames[i.Owner],
GroupPowerNameplate: powerNameplates[i.Owner],
GroupPower: group_cv.GroupPower{
Id: powerIds[i.Owner],
Name: powerNames[i.Owner],
Nameplate: powerNameplates[i.Owner],
Grade: powerGrades[i.Owner],
},
},
MicUsers: []user_cv.CvUserTiny{},
RoomUserCount: uint(roomCount[i.ImGroupId]),
MaxStage: maxStage,
GameTypes: games[i.TxGroupId],
})
}
return groups, banCount, visitCount, nil
resp.ResponsePageOk(c, result, uint(total), pageIndex)
return myContext, nil
}
// @Tags 资源
......
......@@ -439,7 +439,7 @@ func GroupMicTaskInviteDialog(c *gin.Context) (*mycontext.MyContext, error) {
endTime := beginTime.AddDate(0, 0, 1)
var n int64
if err := mysql.Db.Model(&diamond_m.DiamondAccountDetail{}).Where(&diamond_m.DiamondAccountDetail{
if err := mysql.Db.Table(diamond_m.DiamondAccountDetail{}.TableName()).Where(&diamond_m.DiamondAccountDetail{
UserId: userId,
AddReduce: mysql.ADD,
}).Where("Created_Time <= ? and Created_Time >= ?", endTime, beginTime).Where("(Operate_Type = ? or Operate_Type = ?)", diamond_e.DailyInAppVip, diamond_e.DailyInAppCommon).Count(&n).Error; err != nil {
......@@ -550,12 +550,13 @@ func GroupMicIn(c *gin.Context) (*mycontext.MyContext, error) {
return myContext, err
}
if micUser != nil {
if iStr == "" {
// 同房间且上麦序列为空
if iStr == "" && micUser.GroupUuid == groupUuid {
// 非切麦操作
return myContext, bizerr.GroupMicUserHasIn
}
// 切换麦位,先下麦
if err := group_mic_s.NewGroupPowerService(myContext).GroupMicLeave(groupUuid, micUser.I, userId, externalId); err != nil {
if err := group_mic_s.NewGroupPowerService(myContext).GroupMicLeave(micUser.GroupUuid, micUser.I, userId, externalId); err != nil {
return myContext, err
}
}
......@@ -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
......@@ -993,7 +1001,7 @@ func AddPermanentMember(c *gin.Context) (*mycontext.MyContext, error) {
isInvite = 0
}
userId, externalId, _, nick, avatar, err := req.GetUserEx(c, myContext)
userId, externalId, nick, avatar, _, err := req.GetUserEx(c, myContext)
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)
......
......@@ -190,7 +190,7 @@ func SetGroupRole(c *gin.Context) (*mycontext.MyContext, error) {
}
}
userId, myExtId, _, nick, avatar, err := req.GetUserEx(c, myContext)
userId, myExtId, nick, avatar, _, err := req.GetUserEx(c, myContext)
if err != nil {
return myContext, err
}
......@@ -423,7 +423,7 @@ func AddGroupBlacklist(c *gin.Context) (*mycontext.MyContext, error) {
blackImei = false
}
userId, myExtId, _, nick, avatar, err := req.GetUserEx(c, myContext)
userId, myExtId, nick, avatar, _, err := req.GetUserEx(c, myContext)
if err != nil {
return myContext, err
}
......@@ -522,6 +522,8 @@ func AddGroupBlacklist(c *gin.Context) (*mycontext.MyContext, error) {
if err == nil {
signal_s.SendCustomMsg(model, groupId, nil, string(buf))
}
// socket通知被拉黑者退房
rpc.SendQuitRoom(user.ID, 1, txGroupId)
if err = group_s.NewGroupService(myContext).LeaveGroup(model, groupId, user.ID, externalId); err != nil {
return myContext, err
......@@ -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"
......@@ -10,14 +11,16 @@ import (
)
type MGetUserOnMicSecondsReq struct {
Day string `form:"day" binding:"required"`
Ids []mysql.ID `form:"ids" binding:"required"`
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")
}