Commit 76ea952d authored by hujiebin's avatar hujiebin

feat:hiloGroup

parent 65297deb
package game_e package game_e
import "fmt"
type GameType uint32 type GameType uint32
var GameLudoDiamondList = []uint32{0, 100, 500, 1000, 5000, 10000} var GameLudoDiamondList = []uint32{0, 100, 500, 1000, 5000, 10000}
...@@ -8,3 +10,9 @@ const ( ...@@ -8,3 +10,9 @@ const (
GameTypeLudo GameType = 1 // ludo GameTypeLudo GameType = 1 // ludo
GameTypeUno GameType = 2 // uno GameTypeUno GameType = 2 // uno
) )
const GameAutoMathEnterRoom = "game:autoEnter:%d:%s" // 快速游戏,进入某个房间
func GetAutoMathEnterRoom(userId uint64, imGroupId string) string {
return fmt.Sprintf(GameAutoMathEnterRoom, userId, imGroupId)
}
package task_e
import "git.hilo.cn/hilo-common/resource/mysql"
type RateTypeTaskConfig = mysql.Type
const (
Daily RateTypeTaskConfig = 1
OnlyOne RateTypeTaskConfig = 2
)
type TypeTaskConfig = mysql.Type
const (
MicIn TypeTaskConfig = 1 //上麦10分钟
SendGift TypeTaskConfig = 2 //送礼物
SendGift5Person TypeTaskConfig = 3 //给5个人送出礼物
GroupImMass TypeTaskConfig = 4 //发布会员广播
SendGlobalBroadcast TypeTaskConfig = 5 //发布全球广播
PayFirst TypeTaskConfig = 6 //首次充值
Level5 TypeTaskConfig = 7 //任意等级达到5级(财富,活跃,魅力)
WatchAd TypeTaskConfig = 8 // 观看广告
VideoChat TypeTaskConfig = 9 // 视频任务(暂只统计匹配)
)
package mic_k
import (
"fmt"
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-group/_const/redis_key"
"time"
)
const (
MicPrefix = "mic:"
MicDayInvite = MicPrefix + "day:invite:${userId}:${date}" // string 自动被邀请上麦,1天一次,TTL:24H
)
func GetUserMicDayInvite(userId mysql.ID) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicDayInvite, fmt.Sprintf("%d", userId), date)
}
...@@ -206,6 +206,29 @@ type RoomMedalInfo struct { ...@@ -206,6 +206,29 @@ type RoomMedalInfo struct {
Desc string `json:"desc"` Desc string `json:"desc"`
} }
type GroupChannelId struct {
ChannelId string `json:"channelId"`
Token string `json:"token"`
AgoraId uint32 `json:"agoraId"`
MicNumType uint8 `json:"micNumType"`
}
//国籍视图
type CvCountry struct {
//名字
Name *string `json:"name"`
//缩写
ShortName *string `json:"shortName"`
//图标地址
Icon *string `json:"icon"`
//code
Code *string `json:"code"`
// 手机区号
AreaCode *string `json:"areaCode"`
//手机号国家域名缩写
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, groupIds []string, pageSize, pageIndex int) ([]JoinedGroupInfo, int, error) {
model := domain.CreateModel(myService.CtxAndDb) model := domain.CreateModel(myService.CtxAndDb)
......
package group_cv
import (
"hilo-group/domain/model/group_m"
"time"
)
//麦位信息,
type CvMic struct {
//麦位
I int `json:"i"`
//锁,是否有锁 true:锁了, false:没锁
Lock bool `json:"lock"`
//静音 true:静音,false:没有静音
Forbid bool `json:"forbid"`
//如果 nil 则代表这个位置上没有人
ExternalId *string `json:"externalId"`
//声网agoraId 如果 nil 则代表这个位置上没有人
AgoraId *uint32 `json:"agoraId"`
//上麦时间戳
Timestamp int64 `json:"timestamp"`
}
//获取群组中所有的mic位信息
func GetGroupMicAll(mics []group_m.Mic, micUsers []group_m.MicUser) ([]CvMic, error) {
timestamp := time.Now().Unix()
micUserMap := map[int]*group_m.MicUser{}
for i := 0; i < len(micUsers); i++ {
micUserMap[micUsers[i].I] = &(micUsers[i])
}
//
var cvMics []CvMic
for _, v := range mics {
forbid := false
var externalId *string = nil
var agoraId *uint32 = nil
if u, ok := micUserMap[v.I]; ok {
forbid = u.Forbid
externalId = &u.ExternalId
tmp := uint32(u.UserId)
agoraId = &tmp
}
cvMics = append(cvMics, CvMic{
I: v.I,
Lock: v.Lock,
Forbid: forbid,
ExternalId: externalId,
AgoraId: agoraId,
Timestamp: timestamp,
})
}
return cvMics, nil
}
package mic_cv
//麦位表情
type CvMicEmoji struct {
//Id
Id uint64 `json:"id"`
//名字
Name string `json:"name"`
//图片地址
IconUrl string `json:"iconUrl"`
//特效地址
SvagUrl string `json:"svagUrl"`
}
...@@ -232,3 +232,71 @@ func GetPropertyList(db *gorm.DB, userId uint64) ([]CvProperty, error) { ...@@ -232,3 +232,71 @@ func GetPropertyList(db *gorm.DB, userId uint64) ([]CvProperty, error) {
} }
return result, nil return result, nil
} }
type PropertyExt struct {
Id uint64
PicUrl mysql.Str
EffectUrl mysql.Str
Using bool
TimeLeft int64 // 离到期还有多少秒(过期则是负数)
SenderAvatar string
ReceiverAvatar string
}
func GetExtendedProperty(db *gorm.DB) (map[uint64]PropertyExt, error) {
rp := res_m.ResProperty{}
properties, err := rp.GetAll(mysql.Db)
if err != nil {
return nil, err
}
//获取座驾头像
propertieAvatarMap, err := (&res_m.ResPropertyAvatar{}).GetAll(mysql.Db)
userIds := []uint64{}
for _, value := range propertieAvatarMap {
if value.SendUserId > 0 {
userIds = append(userIds, value.SendUserId)
}
if value.ReceiverUserId > 0 {
userIds = append(userIds, value.ReceiverUserId)
}
}
//获取用户信息
users := []user_m.User{}
if err := db.Model(&user_m.User{}).Where("id in (?)", userIds).Find(&users).Error; err != nil {
return nil, myerr.WrapErr(err)
}
userAvatarMap := map[mysql.ID]string{}
for _, r := range users {
userAvatarMap[r.ID] = r.Avatar
}
result := map[uint64]PropertyExt{}
for _, r := range properties {
var senderAvatar string = ""
var receiverAvatar string = ""
if propertieAvatar, flag := propertieAvatarMap[r.ID]; flag {
if propertieAvatar.SendUserId > 0 {
if avatar, flag := userAvatarMap[propertieAvatar.SendUserId]; flag {
senderAvatar = avatar
}
}
if propertieAvatar.ReceiverUserId > 0 {
if avatar, flag := userAvatarMap[propertieAvatar.ReceiverUserId]; flag {
receiverAvatar = avatar
}
}
}
result[r.ID] = PropertyExt{
Id: r.ID,
PicUrl: r.PicUrl,
EffectUrl: r.EffectUrl,
SenderAvatar: senderAvatar,
ReceiverAvatar: receiverAvatar,
}
}
return result, nil
}
package game_c
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/resource/redisCli"
"hilo-group/_const/enum/game_e"
"time"
)
type gameAutoJoinMsg struct {
TraceId string
Token string
EnterType string
GameCode string
}
func SetAutoMathEnterRoom(userId uint64, imGroupId, traceId, token, enterType, gameCode string) error {
key := game_e.GetAutoMathEnterRoom(userId, imGroupId)
info := gameAutoJoinMsg{traceId, token, enterType, gameCode}
data, err := json.Marshal(info)
if err != nil {
return err
}
err = redisCli.GetRedis().LPush(context.Background(), key, data).Err()
if err != nil {
return err
}
redisCli.GetRedis().Expire(context.Background(), key, time.Second*3)
return nil
}
func IsAutoMathEnterRoom(userId uint64, imGroupId string) (bool, string, string, string, string) {
key := game_e.GetAutoMathEnterRoom(userId, imGroupId)
data, err := redisCli.GetRedis().RPop(context.Background(), key).Bytes()
if err != nil {
return false, "", "", "", ""
}
info := gameAutoJoinMsg{}
err = json.Unmarshal(data, &info)
if err != nil {
return false, "", "", "", ""
}
if info.Token != "" && info.TraceId != "" && info.EnterType != "" && info.GameCode != "" {
redisCli.GetRedis().Del(context.Background(), key)
return true, info.TraceId, info.Token, info.EnterType, info.GameCode
}
return false, "", "", "", ""
}
...@@ -62,20 +62,9 @@ func addGroupMember(groupId string, extIds []string) (int64, error) { ...@@ -62,20 +62,9 @@ func addGroupMember(groupId string, extIds []string) (int64, error) {
return redisCli.RedisClient.SAdd(context.Background(), key, extIds).Result() return redisCli.RedisClient.SAdd(context.Background(), key, extIds).Result()
} }
func AddGroupMember(model *domain.Model, groupId string, extId string) error { func AddGroupMember(groupId string, extIds []string) (int64, error) {
key := getGroupMemberKey(groupId) key := getGroupMemberKey(groupId)
ret, err := redisCli.RedisClient.Exists(context.Background(), key).Result() return redisCli.RedisClient.SAdd(context.Background(), key, extIds).Result()
if err != nil {
model.Log.Infof("AddGroupMember %s, skip because set does not exist", groupId)
return err
}
if ret == 0 {
// 集合不存在,不要加进去!
return nil
}
ret, err = addGroupMember(groupId, []string{extId})
model.Log.Infof("AddGroupMember %s, %s ret = %d, err: %v", groupId, extId, ret, err)
return err
} }
func RemoveGroupMember(groupId string, externalId string) (int64, error) { func RemoveGroupMember(groupId string, externalId string) (int64, error) {
......
package mic_c
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/mysql"
"hilo-group/_const/redis_key/mic_k"
"time"
)
// 增加上麦邀请次数,一天只需要第一次进房弹出
// return show:true 今天已经展示过了
func IsMicDayInviteDialogShowToday(model *domain.Model, userId mysql.ID) (show bool, err error) {
key := mic_k.GetUserMicDayInvite(userId)
ttl := time.Hour * 24
if !config.AppIsRelease() {
ttl = time.Hour
}
lock, err := model.Redis.SetNX(model, key, 1, ttl).Result()
if err != nil {
model.Log.Errorf("IsMicDayInviteDialogShowToday uid:%v, fail:%v", userId, err)
return false, err
}
// !lock = show
return !lock, err
}
...@@ -12,6 +12,37 @@ import ( ...@@ -12,6 +12,37 @@ import (
"time" "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())
}
}
// 马上更新roomVisitCount
if _, err := GetSetRoomVisitCount(groupId); err != nil {
mylogrus.MyLog.Warnf("ProcessRoomVisit, failed for key %s, err: %s", key, err.Error())
}
return nil
}
func ProcessUserRoomVisit(userId uint64, groupId string) error { func ProcessUserRoomVisit(userId uint64, groupId string) error {
key := redis_key.GetUserEnterRoomKey(userId) key := redis_key.GetUserEnterRoomKey(userId)
now := time.Now() now := time.Now()
...@@ -80,3 +111,17 @@ func saveRoomVisitCount(groupId string, count int64) (int64, error) { ...@@ -80,3 +111,17 @@ func saveRoomVisitCount(groupId string, count int64) (int64, error) {
key := redis_key.GetPrefixRoomVisitCount() key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HSet(context.Background(), key, groupId, strconv.FormatInt(count, 10)).Result() 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
}
return ret, nil
}
func GetAllRoomVisitCount() (map[string]string, error) {
key := redis_key.GetPrefixRoomVisitCount()
return redisCli.GetRedis().HGetAll(context.Background(), key).Result()
}
package tim_c
import (
"git.hilo.cn/hilo-common/domain"
"hilo-group/domain/cache/group_c"
"time"
)
func setGroupMember(model *domain.Model, groupId string, extIds []string) error {
err := BatchAddGroupMember(model, groupId, extIds)
if err == nil {
ret, err := group_c.SetGroupMemberTTL(groupId, time.Hour)
model.Log.Infof("SetGroupMemberTTL %s, ret = %t, err: %v", groupId, ret, err)
}
return err
}
func BatchAddGroupMember(model *domain.Model, groupId string, extIds []string) error {
ret, err := group_c.AddGroupMember(groupId, extIds)
model.Log.Infof("BatchAddGroupMember %s, %v ret = %d, err: %v", groupId, extIds, ret, err)
return err
}
func AddGroupMember(model *domain.Model, groupId string, extId string) error {
ret, err := group_c.SetExists(groupId)
if err != nil {
model.Log.Infof("AddGroupMember %s, skip because set does not exist", groupId)
return err
}
if ret == 0 {
// 集合不存在,不要加进去!
return nil
}
ret, err = group_c.AddGroupMember(groupId, []string{extId})
model.Log.Infof("AddGroupMember %s, %s ret = %d, err: %v", groupId, extId, ret, err)
return err
}
func RemoveGroupMember(model *domain.Model, groupId string, extId string) error {
ret, err := group_c.RemoveGroupMember(groupId, extId)
model.Log.Infof("RemoveGroupMember %s, %s ret = %d, err: %v", groupId, extId, ret, err)
return err
}
func GetGroupMemberCount(model *domain.Model, groupId string) (uint, error) {
ret, err := group_c.GetGroupMemberCard(groupId)
model.Log.Infof("GetGroupMemberCount %s, ret = %d, err: %v", groupId, ret, err)
return uint(ret), err
}
package group_ev
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
)
type BuyGroupCustomThemeEvent struct {
GroupCustomThemeId mysql.ID
UserId mysql.ID
}
//注册监听
var buyGroupCustomThemeListen = new(domain.EventBase)
//添加领域事件,在每个领域模型中init中添加,因为这是静态业务,非动态的。
func AddBuyGroupCustomThemeSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(buyGroupCustomThemeListen, callback)
}
//加入到异步操作中
func AddBuyGroupCustomThemeAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(buyGroupCustomThemeListen, callback)
}
//领域事件发布
func PublishBuyGroupCustomTheme(model *domain.Model, event *BuyGroupCustomThemeEvent) error {
return domain.PublishEvent(buyGroupCustomThemeListen, model, event)
}
package group_ev
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
)
/**
* IM群发
*/
type GroupImMassEvent struct {
GroupId string
UserId mysql.ID
Members []uint64
Content string
}
//注册监听
var groupImMassListen = new(domain.EventBase)
//添加领域事件,在每个领域模型中init中添加,因为这是静态业务,非动态的。
func AddGroupImMassSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(groupImMassListen, callback)
}
//加入到异步操作中
func AddGroupImMassAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(groupImMassListen, callback)
}
//领域事件发布
func PublishGroupImMass(model *domain.Model, event *GroupImMassEvent) error {
return domain.PublishEvent(groupImMassListen, model, event)
}
package group_ev
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
)
type GroupInEvent struct {
GroupId string
UserId mysql.ID
ExternalId string
Nick string
Avatar string
IsMember bool //是否永久成员
IsVip bool
NobleLevel uint16
}
//注册监听
var groupInListen = new(domain.EventBase)
//添加领域事件,在每个领域模型中init中添加,因为这是静态业务,非动态的。
func AddGroupInSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(groupInListen, callback)
}
//加入到异步操作中
func AddGroupInAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(groupInListen, callback)
}
//领域事件发布
func PublishGroupIn(model *domain.Model, event *GroupInEvent) error {
return domain.PublishEvent(groupInListen, model, event)
}
package group_ev
import (
"git.hilo.cn/hilo-common/domain"
)
/**
*
*/
type GroupKickOutEvent struct {
GroupId string
OperatorExternalId string `json:"operatorExternalId"`
OperatorName string `json:"operatorName"`
OperatorFaceUrl string `json:"operatorFaceUrl"`
MemberExternalId string `json:"memberExternalId"`
MemberName string `json:"memberName"`
MemberAvatar string `json:"memberAvatar"`
}
//注册监听
var groupKickOutListen = new(domain.EventBase)
//添加领域事件,在每个领域模型中init中添加,因为这是静态业务,非动态的。
func AddGroupKickOutSync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventSync(groupKickOutListen, callback)
}
//加入到异步操作中
func AddGroupKickOutAsync(callback func(model *domain.Model, event interface{}) error) {
domain.AddEventAsync(groupKickOutListen, callback)
}
//领域事件发布
func PublishGroupKickOut(model *domain.Model, event interface{}) error {
return domain.PublishEvent(groupKickOutListen, model, event)
}
...@@ -268,3 +268,13 @@ func (diamondAccountDetail *DiamondAccountDetail) Persistent() error { ...@@ -268,3 +268,13 @@ func (diamondAccountDetail *DiamondAccountDetail) Persistent() error {
func (diamondAccount *DiamondAccount) GroupSupportMgr(groupSupportAwardId mysql.ID, diamondNum uint32) (*DiamondAccountDetail, error) { func (diamondAccount *DiamondAccount) GroupSupportMgr(groupSupportAwardId mysql.ID, diamondNum uint32) (*DiamondAccountDetail, error) {
return diamondAccount.addDiamondAccountDetail(diamond_e.GroupSupportMgr, groupSupportAwardId, diamondNum) return diamondAccount.addDiamondAccountDetail(diamond_e.GroupSupportMgr, groupSupportAwardId, diamondNum)
} }
//群组IM群发
func (diamondAccount *DiamondAccount) GroupImMass() (*DiamondAccountDetail, error) {
return diamondAccount.addDiamondAccountDetail(diamond_e.GroupIMMass, 0, 0)
}
//购买自定义群组主题
func (diamondAccount *DiamondAccount) BuyGroupCustomTheme(diamondAccountDetailId mysql.ID) (*DiamondAccountDetail, error) {
return diamondAccount.addDiamondAccountDetail(diamond_e.GroupCustomTheme, diamondAccountDetailId, 0)
}
...@@ -457,7 +457,7 @@ type UserEnterRoom struct { ...@@ -457,7 +457,7 @@ type UserEnterRoom struct {
EnterTime time.Time EnterTime time.Time
} }
func (uer *UserEnterRoom) save(db *gorm.DB) error { func (uer *UserEnterRoom) Save(db *gorm.DB) error {
return db.Clauses(clause.OnConflict{UpdateAll: true}).Create(uer).Error return db.Clauses(clause.OnConflict{UpdateAll: true}).Create(uer).Error
} }
......
package mgr_m
import (
"hilo-group/domain/model"
"hilo-group/myerr"
)
func (mgrReportGroup *MgrReportGroup) Persistent() error {
if err := model.Persistent(mgrReportGroup.Db, mgrReportGroup); err != nil {
return myerr.WrapErr(err)
}
return nil
}
package mgr_m
import (
"fmt"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/_const/enum/mgr_e"
"hilo-group/myerr"
)
//投诉
type MgrReport struct {
mysql.Entity
*domain.Model `gorm:"-"`
FromUserId mysql.ID
ToUserId mysql.ID
FromPageType mgr_e.ReportPageType
ReasonType mgr_e.ReportReasonType
OriginId mysql.ID
ImageUrl mysql.Str
Reason mysql.Str
Status mgr_e.ReportStatus
ReportDealId mysql.ID
}
//投诉-群组
type MgrReportGroup struct {
mysql.Entity
*domain.Model `gorm:"-"`
FromUserId mysql.ID
GroupId mysql.Str
ReasonType mgr_e.ReportReasonType
ImageUrl mysql.Str
Reason mysql.Str
Status mgr_e.ReportStatus
ReportDealId mysql.ID
}
func ReportAdd(model *domain.Model, fromUserId mysql.ID, toUserId mysql.ID, fromPageType mgr_e.ReportPageType, originId mysql.ID, reasonType mgr_e.ReportReasonType, imageUrl mysql.Str, reason mysql.Str) *MgrReport {
return &MgrReport{
Model: model,
FromUserId: fromUserId,
ToUserId: toUserId,
FromPageType: fromPageType,
ReasonType: reasonType,
OriginId: originId,
ImageUrl: imageUrl,
Reason: reason,
Status: mgr_e.NoDealReportStatus,
}
}
func ReportGroupAdd(model *domain.Model, fromUserId mysql.ID, groupId mysql.Str, reasonType mgr_e.ReportReasonType, imageUrl mysql.Str, reason mysql.Str) *MgrReportGroup {
return &MgrReportGroup{
Model: model,
FromUserId: fromUserId,
GroupId: groupId,
ReasonType: reasonType,
ImageUrl: imageUrl,
Reason: reason,
Status: mgr_e.NoDealReportStatus,
}
}
//检查投诉
func checkReport(model *domain.Model, reportId mysql.ID) (*MgrReport, error) {
//var report = new(MgrReport)
var report MgrReport
if err := model.Db.First(&report, reportId).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, myerr.NewSysError("投诉不存在, Id:" + fmt.Sprintf("%d", reportId))
} else {
return nil, myerr.WrapErr(err)
}
}
/* if report.Status == mgr_m.HasDealReportStatus {
return nil, myerr.NewSysError("投诉已被处理。, Id:" + mysql.IdToStr(reportId))
}*/
return &report, nil
}
//投诉处理
func ReportDeal(model *domain.Model, reportId mysql.ID) (*MgrReport, error) {
report, err := checkReport(model, reportId)
if err != nil {
return nil, err
}
report.Status = mgr_e.HasDealReportStatus
return report, nil
}
func GetMyReport(userId mysql.ID) ([]uint64, error) {
users := make([]uint64, 0)
report := make([]MgrReport, 0)
if err := mysql.Db.Where("from_user_id = ?", userId).Find(&report).Error; err != nil && err != gorm.ErrRecordNotFound {
return nil, myerr.WrapErr(err)
}
for _, i := range report {
users = append(users, i.ToUserId)
}
return users, nil
}
package res_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
)
type ResMicEmoji struct {
mysql.Entity
*domain.Model `gorm:"-"`
Name mysql.Str
IconUrl mysql.Str
SvagUrl mysql.Str
N mysql.Num
Status mysql.UserYesNo
}
//不可用
func (resMicEmoji *ResMicEmoji) Disable() *ResMicEmoji {
resMicEmoji.Status = mysql.NOUSER
return resMicEmoji
}
//上架
func (resMicEmoji *ResMicEmoji) Enable() *ResMicEmoji {
resMicEmoji.Status = mysql.USER
return resMicEmoji
}
func (resMicEmoji *ResMicEmoji) EditN(n uint32) *ResMicEmoji {
resMicEmoji.N = n
return resMicEmoji
}
func (resMicEmoji *ResMicEmoji) EditName(name string) *ResMicEmoji {
resMicEmoji.Name = name
return resMicEmoji
}
func (resMicEmoji *ResMicEmoji) EditIconUrl(iconUrl string) *ResMicEmoji {
resMicEmoji.IconUrl = iconUrl
return resMicEmoji
}
func (resMicEmoji *ResMicEmoji) EditSvagUrl(svagUrl string) *ResMicEmoji {
resMicEmoji.SvagUrl = svagUrl
return resMicEmoji
}
package task_m
import (
"hilo-group/domain/model"
"hilo-group/myerr"
)
func (taskUser *TaskUser) Persistent() error {
if err := model.Persistent(taskUser.Db, taskUser); err != nil {
return myerr.WrapErr(err)
}
return nil
}
func (taskUserDetail *TaskUserDetail) Persistent() error {
if err := model.Persistent(taskUserDetail.Db, taskUserDetail); err != nil {
return myerr.WrapErr(err)
}
return nil
}
\ No newline at end of file
package task_m
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/task_e"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
"strconv"
"time"
)
type TaskConfig struct {
mysql.Entity
*domain.Model `gorm:"-"`
Name mysql.Str
Diamond mysql.Num
//任务类型
Type task_e.TypeTaskConfig
//频率类型
RateType task_e.RateTypeTaskConfig
//完成次数
FinishN mysql.Num
//排序
I mysql.Num
//奖励次数
AwardN mysql.Num
Status mysql.UserYesNo
}
type TaskUser struct {
mysql.Entity
*domain.Model `gorm:"-"`
TaskConfigId mysql.ID
UserId mysql.ID
DayStr mysql.Str
HasFinish mysql.YesNo
HasAward mysql.YesNo //整个完成奖励了
AwardN mysql.Num //获取奖励次数
FinishN mysql.Num
}
type TaskUserDetail struct {
mysql.Entity
*domain.Model `gorm:"-"`
TaskConfigId mysql.ID
UserId mysql.ID
TaskUserId mysql.ID
OriginId mysql.ID
}
func addTaskUserDetail(model *domain.Model, taskConfigId mysql.ID, userId mysql.ID, taskUserId mysql.ID, originId mysql.ID) error {
taskUserDetail := &TaskUserDetail{
Model: model,
TaskConfigId: taskConfigId,
UserId: userId,
TaskUserId: taskUserId,
OriginId: originId,
}
return taskUserDetail.Persistent()
}
func GetTaskUserOrErr(model *domain.Model, userId uint64, taskConfigId uint64) (*TaskUser, TaskConfig, error) {
//获取任务配置
taskConfig := TaskConfig{}
if err := model.Db.Model(&TaskConfig{}).Where(&TaskConfig{
Status: mysql.USER,
}).First(&taskConfig, taskConfigId).Error; err != nil {
return nil, TaskConfig{}, myerr.WrapErr(err)
}
//
paramTaskUser := TaskUser{
TaskConfigId: taskConfig.ID,
UserId: userId,
}
if taskConfig.RateType == task_e.Daily {
paramTaskUser.DayStr = time.Now().Format(utils.COMPACT_DATE_FORMAT)
}
//
taskUser := TaskUser{}
if err := model.Db.Model(&TaskUser{}).Where(&paramTaskUser).First(&taskUser).Error; err != nil {
return nil, TaskConfig{}, myerr.WrapErr(err)
}
taskUser.Model = model
//
return &taskUser, taskConfig, nil
}
func getTaskUserOrInit(model *domain.Model, userId uint64, taskConfig TaskConfig) (*TaskUser, error) {
//获取任务用户
taskUser := TaskUser{}
paramTaskUser := TaskUser{
TaskConfigId: taskConfig.ID,
UserId: userId,
}
if taskConfig.RateType == task_e.Daily {
paramTaskUser.DayStr = time.Now().Format(utils.COMPACT_DATE_FORMAT)
}
if err := model.Db.Model(&TaskUser{}).Where(&paramTaskUser).First(&taskUser).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return &TaskUser{
Model: model,
TaskConfigId: taskConfig.ID,
UserId: userId,
DayStr: paramTaskUser.DayStr,
HasFinish: mysql.NO,
HasAward: mysql.NO,
FinishN: 0,
}, nil
} else {
return nil, myerr.WrapErr(err)
}
}
taskUser.Model = model
return &taskUser, nil
}
// 次数加1
func (taskUser *TaskUser) addFinishN(taskConfig TaskConfig) bool {
//没有使用sql悲观锁,update set where,第一:观察业务,都是用户自动触发,有时间性 第二:验证业务这样写,被投诉的概率,以证明此场景业务。
if taskUser.HasFinish == mysql.YES {
return false
} else {
taskUser.FinishN = taskUser.FinishN + 1
if taskUser.FinishN >= taskConfig.FinishN {
taskUser.HasFinish = mysql.YES
}
return true
}
}
// 次数覆盖
func (taskUser *TaskUser) beFinishN(taskConfig TaskConfig, finishN uint32) bool {
//没有使用sql悲观锁,update set where,第一:观察业务,都是用户自动触发,有时间性 第二:验证业务这样写,被投诉的概率,以证明此场景业务。
if taskUser.HasFinish == mysql.YES {
return false
} else {
taskUser.FinishN = finishN
if taskUser.FinishN >= taskConfig.FinishN {
taskUser.HasFinish = mysql.YES
}
return true
}
}
func (taskUser *TaskUser) Award(taskConfig TaskConfig) error {
if taskUser.HasAward == mysql.YES {
return bizerr.TaskHasAward
}
taskUser.AwardN = taskUser.AwardN + 1
if taskUser.AwardN >= taskConfig.AwardN {
taskUser.HasAward = mysql.YES
}
taskUser.SetCheckUpdateCondition("has_award = " + strconv.Itoa(int(mysql.NO)))
return nil
}
func AddTaskUser(model *domain.Model, t task_e.TypeTaskConfig, userId uint64, orginId uint64) (mysql.ID, error) {
//获取任务配置
taskConfig := TaskConfig{}
if err := model.Db.Model(&TaskConfig{}).Where(&TaskConfig{
Type: t,
Status: mysql.USER,
}).First(&taskConfig).Error; err != nil {
return 0, myerr.WrapErr(err)
}
//
taskUser, err := getTaskUserOrInit(model, userId, taskConfig)
if err != nil {
return 0, err
}
if taskUser.addFinishN(taskConfig) {
if err := taskUser.Persistent(); err != nil {
return 0, myerr.WrapErr(err)
}
return taskConfig.ID, addTaskUserDetail(taskUser.Model, taskConfig.ID, userId, taskUser.ID, orginId)
}
return taskConfig.ID, nil
}
// return true:已经完成 false:未完成
func isTaskUserFinish(model *domain.Model, t task_e.TypeTaskConfig, userId uint64) (bool, error) {
//获取任务配置
taskConfig := TaskConfig{}
if err := model.Db.Model(&TaskConfig{}).Where(&TaskConfig{
Type: t,
Status: mysql.USER,
}).First(&taskConfig).Error; err != nil {
return false, myerr.WrapErr(err)
}
//
taskUser, err := getTaskUserOrInit(model, userId, taskConfig)
if err != nil {
return false, err
}
return taskUser.HasFinish == mysql.YES, nil
}
func addTaskUserFinishN(model *domain.Model, t task_e.TypeTaskConfig, userId uint64, finishN uint32) error {
//获取任务配置
taskConfig := TaskConfig{}
if err := model.Db.Model(&TaskConfig{}).Where(&TaskConfig{
Type: t,
Status: mysql.USER,
}).First(&taskConfig).Error; err != nil {
return myerr.WrapErr(err)
}
//
taskUser, err := getTaskUserOrInit(model, userId, taskConfig)
if err != nil {
return err
}
if taskUser.beFinishN(taskConfig, finishN) {
if err := taskUser.Persistent(); err != nil {
return myerr.WrapErr(err)
}
return addTaskUserDetail(taskUser.Model, taskConfig.ID, userId, taskUser.ID, 0)
}
return nil
}
\ No newline at end of file
package user_m
import (
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm"
"hilo-group/myerr"
)
//腾讯云的拉黑名单,临时表
type UserBlackTencentyunTmp struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserExternal mysql.Str
BlockExternal mysql.Str
}
//黑名单
type UserBlock struct {
mysql.Entity
*domain.Model `gorm:"-"`
UserId mysql.ID
BlockUserId mysql.ID
}
func initUserBlock(model *domain.Model, userId mysql.ID) *UserBlock {
return &UserBlock{
Model: model,
UserId: userId,
}
}
//拉黑
func (ub *UserBlock) block(blockUserId mysql.ID) (*UserBlock, error) {
err := ub.Db.Where(&UserBlock{
UserId: ub.UserId,
BlockUserId: blockUserId,
}).First(ub).Error
//已经拉黑了
if err == nil {
ub.SetLasyLoad()
return ub, nil
//return nil, myerr.NewWaring("已经标记拉黑")
} else if err == gorm.ErrRecordNotFound {
ub.BlockUserId = blockUserId
return ub, nil
} else {
return nil, myerr.WrapErr(err)
}
}
//取消拉黑
func (ub *UserBlock) blockCancel(blockUserId mysql.ID) (*UserBlock, error) {
err := ub.Db.Where(&UserBlock{
UserId: ub.UserId,
BlockUserId: blockUserId,
}).First(ub).Error
//
if err == nil {
ub.SetDel()
return ub, nil
} else if err == gorm.ErrRecordNotFound {
return nil, myerr.NewWaring("没有拉黑的记录")
} else {
return nil, myerr.WrapErr(err)
}
}
//检查是否存在拉黑
/*func CheckBlock(model *domain.Model, userId mysql.ID, blockUserId mysql.ID) (bool, error) {
var n int64
if err := model.Db.Model(&UserBlock{}).Where(&UserBlock{
UserId: userId,
BlockUserId: blockUserId,
}).Count(&n).Error; err != nil {
return false, myerr.WrapErr(err)
}
return n > 0, nil
}*/
//检查是否存在拉黑(无论是我拉黑别人,还是别人拉黑我), true:拉黑, false:不拉黑
func CheckBlockOr(model *domain.Model, userId mysql.ID, blockUserId mysql.ID) (bool, error) {
var n int64
if err := model.Db.Model(&UserBlock{}).Where(&UserBlock{
UserId: userId,
BlockUserId: blockUserId,
}).Count(&n).Error; err != nil {
return false, myerr.WrapErr(err)
}
if n == 0 {
if err := model.Db.Model(&UserBlock{}).Where(&UserBlock{
BlockUserId: userId,
UserId: blockUserId,
}).Count(&n).Error; err != nil {
return false, myerr.WrapErr(err)
}
}
return n > 0, nil
}
func CheckBlock(model *domain.Model, userId mysql.ID, blockUserId mysql.ID) (bool, error) {
var n int64
if err := model.Db.WithContext(model).Model(&UserBlock{}).Where(&UserBlock{
UserId: userId,
BlockUserId: blockUserId,
}).Count(&n).Error; err != nil {
return false, myerr.WrapErr(err)
}
return n > 0, nil
}
//检查互相拉黑的成员
func FilterBlock(model *domain.Model, userId mysql.ID, otherUserIds []mysql.ID) ([]mysql.ID, error) {
if len(otherUserIds) == 0 {
return otherUserIds, nil
}
userBlocks1 := []UserBlock{}
if err := model.Db.Model(&UserBlock{}).Where(&UserBlock{
UserId: userId,
}).Where("block_user_id in (?)", otherUserIds).Find(&userBlocks1).Error; err != nil {
return nil, myerr.WrapErr(err)
}
userBlocks2 := []UserBlock{}
if err := model.Db.Model(&UserBlock{}).Where(&UserBlock{
BlockUserId: userId,
}).Where("user_id in (?)", otherUserIds).Find(&userBlocks2).Error; err != nil {
return nil, myerr.WrapErr(err)
}
blockSet := map[uint64]struct{}{}
for i, _ := range userBlocks1 {
blockSet[userBlocks1[i].BlockUserId] = struct{}{}
}
for i, _ := range userBlocks2 {
blockSet[userBlocks2[i].UserId] = struct{}{}
}
//
resultUserIds := make([]mysql.ID, 0, len(otherUserIds))
for i, r := range otherUserIds {
if _, flag := blockSet[r]; !flag {
resultUserIds = append(resultUserIds, otherUserIds[i])
}
}
return resultUserIds, nil
}
// 获取用户拉黑的用户ids
func GetBlockUserIds(model *domain.Model, userId mysql.ID) ([]mysql.ID, error) {
var userBlocks []UserBlock
if err := model.Db.Where(&UserBlock{
UserId: userId,
}).Find(&userBlocks).Error; err != nil {
return nil, myerr.WrapErr(err)
}
var userIds []mysql.ID
for _, v := range userBlocks {
userIds = append(userIds, v.BlockUserId)
}
return userIds, nil
}
\ No newline at end of file
package event_s package event_s
import ( import (
"encoding/json"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/rpc"
"git.hilo.cn/hilo-common/sdk/tencentyun"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/msg_e" "hilo-group/_const/enum/msg_e"
"hilo-group/_const/enum/task_e"
"hilo-group/domain/event/group_ev" "hilo-group/domain/event/group_ev"
"hilo-group/domain/event/group_power_ev" "hilo-group/domain/event/group_power_ev"
"hilo-group/domain/model/diamond_m" "hilo-group/domain/model/diamond_m"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m"
"hilo-group/domain/model/msg_m" "hilo-group/domain/model/msg_m"
"hilo-group/domain/model/task_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/myerr"
"strconv" "strconv"
"time"
) )
func EventInit() { func EventInit() {
GroupPowerEvents() GroupPowerEvents()
GroupSupportEvents() GroupSupportEvents()
GroupEvents()
GroupImMass()
GroupTheme()
} }
func GroupSupportEvents() { func GroupSupportEvents() {
...@@ -144,3 +156,240 @@ func GroupPowerEvents() { ...@@ -144,3 +156,240 @@ func GroupPowerEvents() {
return nil return nil
}) })
} }
func GroupEvents() {
// 进房事件
group_ev.AddGroupInAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*group_ev.GroupInEvent)
if !ok {
model.Log.Errorf("AddGroupInAsync for room: %+v", event)
return nil
}
model.Log.Infof("AddGroupInAsync for room: %+v", event)
uer := group_m.UserEnterRoom{
UserId: event.UserId,
GroupId: event.GroupId,
EnterTime: time.Now(),
}
err := uer.Save(model.Db)
model.Log.Infof("AddGroupInAsync, UserEnterRoom err: %v", err)
return err
})
// 进入房间时,
group_ev.AddGroupInAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*group_ev.GroupInEvent)
if !ok {
model.Log.Errorf("AddGroupInAsync for room: %+v", event)
return nil
}
model.Log.Infof("AddGroupInAsync for user: %+v", event)
user, err := user_m.GetUser(model, event.UserId)
if err != nil {
return err
}
medals, err := user_m.GetUserMedalMerge(model.Log, model.Db, event.UserId)
if err != nil {
model.Log.Errorf("tim_m user AddGroupInAsync GetUserMedal err:%v, userId:%v", err, event.UserId)
return err
}
wealthGrade, _, err := user_m.GetWealthGrade(model, event.UserId)
if err != nil {
return err
}
charmGrade, _, err := user_m.GetCharmGrade(model, event.UserId)
if err != nil {
return err
}
if err = FlushGrades(event.ExternalId, wealthGrade, charmGrade); err != nil {
model.Log.Info("AddGroupInAsync, FlushGrades failed: ", err)
}
_, powerName, err := groupPower_m.GetUserGroupPower(model, event.UserId)
if err != nil {
return err
}
if err = FlushHiloInfo(user.ExternalId, event.IsVip, user.Code != user.OriginCode, medals, powerName, event.NobleLevel); err != nil {
model.Log.Info("AddGroupInAsync, FlushHiloInfo failed: ", err)
}
return nil
})
//被踢出
group_ev.AddGroupKickOutAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*group_ev.GroupKickOutEvent)
if !ok {
model.Log.Errorf("AddGroupKickOutAsync fail data")
return nil
}
model.Log.Infof("publicScreenMsg AddGroupKickOutAsync GroupId:%v, OperatorExternalId:%v, MemberExternalId:%v", event.GroupId, event.OperatorExternalId, event.MemberExternalId)
groupKickOutMsg := group_m.CommonPublicMsg{
Type: group_e.UserKickPublicScreenMsg,
OperatorExternalId: event.OperatorExternalId,
OperatorNick: event.OperatorName,
OperatorAvatar: event.OperatorFaceUrl,
ExternalId: event.MemberExternalId,
Nick: event.MemberName,
Avatar: event.MemberAvatar,
}
//
body, err := json.Marshal(groupKickOutMsg)
if err != nil {
return myerr.WrapErr(err)
}
txGroupId, err := group_m.ToTxGroupId(model, event.GroupId)
if err != nil {
return err
}
//发送公屏消息,
u, err := tencentyun.SendCustomMsg(model.Log, txGroupId, nil, string(body), "")
model.Log.Infof("publicScreenMsg AddGroupKickOutAsync result response.MsgSeq:%v, err:%v", u, err)
return err
})
}
func GroupImMass() {
//支付群主群发IM
group_ev.AddGroupImMassSync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*group_ev.GroupImMassEvent)
if !ok {
model.Log.Errorf("AddGroupImMassSync data fail")
return nil
}
model.Log.Infof("diamond AddGroupImMass groupId:%v userId:%v", event.GroupId, event.UserId)
diamondAccount, err := diamond_m.GetDiamondAccountByUserId(model, event.UserId)
if err != nil {
return err
}
diamondAccountDetail, err := diamondAccount.GroupImMass()
if err != nil {
return err
}
return diamondAccountDetail.Persistent()
})
// 任务
group_ev.AddGroupImMassAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*group_ev.GroupImMassEvent)
if !ok {
model.Log.Errorf("AddGroupImMassSync data fail")
return nil
}
model.Log.Infof("task AddGroupImMassAsync %+v", event)
_, err := task_m.AddTaskUser(model, task_e.GroupImMass, event.UserId, 0)
return err
})
// 麦上的人/管理员群发消息,弹窗 fixme:放在这里已经不合适了
group_ev.AddGroupImMassAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*group_ev.GroupImMassEvent)
if !ok {
model.Log.Errorf("AddGroupImMassSync data fail")
return nil
}
model.Log.Infof("AddGroupImMassAsync begin groupId = %s, userId %d, members: %v, content: %s",
event.GroupId, event.UserId, event.Members, event.Content)
flag, err := group_m.IsHiddenGroup(model.Db, event.GroupId)
if err != nil {
return err
}
if flag {
model.Log.Infof("AddGroupImMassAsync, skip hidden group %s", event.GroupId)
return nil
}
if len(event.Members) <= 0 {
return nil
}
user, err := user_m.GetUser(model, event.UserId)
if err != nil {
return err
}
//过滤用户黑名单,只要单方面拉黑就不发
memberUserIds, err := user_m.FilterBlock(model, event.UserId, event.Members)
if err != nil {
return err
}
groupInfo, err := group_m.GetGroupInfo(model, event.GroupId)
if err != nil {
return err
}
userInCount, err := group_m.GetRoomVisitCount(event.GroupId)
if err != nil {
return err
}
if userInCount < 0 {
userInCount = 0
}
// 注意发消息使用了TxGroupId
err = rpc.SendGroupChatNotice(event.UserId, memberUserIds, user.ExternalId, user.Code, uint32(user.Sex), user.Avatar,
event.Content, groupInfo.TxGroupId, groupInfo.Name, groupInfo.Code, groupInfo.FaceUrl, uint32(userInCount))
model.Log.Infof("AddGroupImMassAsync, groupId = %s ended, err = %v", event.GroupId, err)
return nil
})
}
func GroupTheme() {
//购买自定义主题
group_ev.AddBuyGroupCustomThemeSync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*group_ev.BuyGroupCustomThemeEvent)
if !ok {
model.Log.Errorf("AddBuyGroupCustomThemeSync data fail")
return nil
}
model.Log.Infof("diamond AddBuyGroupCustomTheme userId:%v, GroupCustomThemeId:%v", event.UserId, event.GroupCustomThemeId)
diamondAccount, err := diamond_m.GetDiamondAccountByUserId(model, event.UserId)
if err != nil {
return err
}
diamondAccountDetail, err := diamondAccount.BuyGroupCustomTheme(event.GroupCustomThemeId)
if err != nil {
return err
}
if err := diamondAccountDetail.Persistent(); err != nil {
return err
}
return nil
})
}
func FlushGrades(userExtId string, wealthGrade uint32, charmGrade uint32) error {
level := (charmGrade & 0x000000FF << 8) | wealthGrade&0x000000FF
return tencentyun.SetUserLevel(userExtId, level)
}
type TimHiloInfo struct {
IsVip bool `json:"isVip"`
IsPretty bool `json:"isPretty"`
Medals []uint32 `json:"medals"`
PowerName string `json:"powerName"` // 用户加入的国家势力的绑定群组的名称
NobleLevel uint16 `json:"nobleLevel"`
}
func FlushHiloInfo(extId string, isVip bool, isPrettyCode bool, medals []uint32, groupPowerName string, nobleLevel uint16) error {
info := TimHiloInfo{IsVip: isVip, IsPretty: isPrettyCode, Medals: medals, PowerName: groupPowerName, NobleLevel: nobleLevel}
buf, err := json.Marshal(info)
if err != nil {
return err
}
if err = tencentyun.SetUserHiloInfo(extId, string(buf)); err != nil {
return err
}
return nil
}
package group_mic_s
import (
"context"
"encoding/json"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/redisCli"
uuid "github.com/satori/go.uuid"
"hilo-group/_const/enum/group_e"
"hilo-group/_const/redis_key"
"hilo-group/domain/event/group_ev"
"hilo-group/domain/model/group_m"
"hilo-group/domain/service/signal_s"
"hilo-group/myerr"
"hilo-group/myerr/bizerr"
"time"
)
type GroupMicService struct {
svc *domain.Service
}
func NewGroupPowerService(myContext *mycontext.MyContext) *GroupMicService {
svc := domain.CreateService(myContext)
return &GroupMicService{svc}
}
//修改群组中麦的数量
func (s *GroupMicService) GroupMicNumChange(groupId string, userId uint64, micNumType group_e.GroupMicNumType, micOn bool) error {
model := domain.CreateModelContext(s.svc.MyContext)
//数据库修改群组麦的数量
//检查权限
if err := group_m.CheckPermission(model, groupId, userId); err != nil {
return err
}
//删除麦位数量类型缓存
group_m.InitMicNumType(model, groupId, micNumType).ClearCache()
//
groupInfo, _ := group_m.GetGroupInfo(model, groupId)
if groupInfo == nil {
return bizerr.GroupNotFound
}
//判断数据是否发生了变化
//关闭麦位
if micOn == false {
if groupInfo.MicOn == micOn {
return nil
}
} else {
if groupInfo.MicOn == micOn && groupInfo.MicNumType == micNumType {
return nil
}
}
//修改数据,然后数据持久化,
g := group_m.GroupInfo{
MicOn: micOn,
}
fields := []string{"mic_on"}
//开启麦位才修改micNumType
returnMicNumType := g.MicNumType
if micOn == true {
g.MicNumType = micNumType
fields = append(fields, "mic_num_type")
returnMicNumType = micNumType
}
db := g.Update(model, groupId, fields)
if db.Error != nil {
return myerr.WrapErr(db.Error)
}
//增加麦位数量类型缓存
group_m.InitMicNumType(model, groupId, micNumType).AddCache()
//麦位上的信息,清理
group_m.ClearMic(groupId)
type Content struct {
MicOn bool `json:"micOn"`
MicNumType group_e.GroupMicNumType `json:"micNumType"`
Timestamp int64 `json:"timestamp"`
}
r := Content{
MicOn: micOn,
MicNumType: returnMicNumType,
Timestamp: time.Now().Unix(),
}
buf, err := json.Marshal(r)
if err != nil {
model.Log.Errorf("GroupMicNumChange Content json.Marshal err:%v", err)
}
// 发信令,让前端重新拉取,接受容错,
signal_s.SendSignalMsg(model, groupId, group_m.GroupSystemMsg{
MsgId: group_e.GroupMicChangeSignal,
Content: string(buf),
}, false)
group_m.MicNumChangeRPush(model, groupId, returnMicNumType, micOn)
return nil
}
//加锁, sign作为密钥存在(预防被别人删除,比如:先者删除了后者的锁),
func redisLock(key string, sign string, expiration time.Duration, callBack func() error) error {
flag, err := redisCli.GetRedis().SetNX(context.Background(), key, sign, expiration).Result()
if err != nil {
return myerr.WrapErr(err)
}
if flag {
err = callBack()
redisSign, _ := redisCli.GetRedis().Get(context.Background(), key).Result()
if redisSign == sign {
redisCli.GetRedis().Del(context.Background(), key)
}
return err
} else {
return bizerr.GroupConcurrencyLock
}
}
//加入麦位,锁两秒
func (s *GroupMicService) GroupMicIn(groupUuid string, i int, userId uint64, externalId string) error {
return 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, i)
if err != nil {
return err
}
return mic.In(userId, externalId)
})
}
//离开麦位
func (s *GroupMicService) GroupMicLeave(groupUuid string, i int, userId uint64, externalId string) error {
return redisLock(redis_key.GetPrefixGroupMicUserDelLock(groupUuid, i), uuid.NewV4().String(), time.Second*2, func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
micUser, err := group_m.GetMicUser(model, groupUuid, i)
if err != nil {
return err
}
if micUser != nil {
return micUser.LeaveByUser(userId, externalId)
}
return nil
})
}
//邀请上麦,锁两秒
func (s *GroupMicService) GroupMicInvite(groupUuid string, operateUserId uint64, beInvitedExternalId string) error {
model := domain.CreateModelContext(s.svc.MyContext)
if err := group_m.InviteMicIn(model, groupUuid, operateUserId, beInvitedExternalId); err != nil {
return err
}
return nil
}
//麦位加锁,
func (s *GroupMicService) GroupMicLock(userId uint64, externalId string, groupUuid string, i int) error {
//后果等级不高,不需要加锁
model := domain.CreateModelContext(s.svc.MyContext)
mic, err := group_m.GetMic(model, groupUuid, i)
if err != nil {
return err
}
return mic.MgrLock(userId, externalId)
}
//麦位解锁
func (s *GroupMicService) GroupMicUnLock(userId uint64, externalId string, groupUuid string, i int) error {
//后果等级不高,不需要加锁
model := domain.CreateModelContext(s.svc.MyContext)
mic, err := group_m.GetMic(model, groupUuid, i)
if err != nil {
return err
}
return mic.MgrUnLock(userId, externalId)
}
// 麦位静音
func (s *GroupMicService) GroupMicMute(userId uint64, externalId string, groupUuid string, i int) error {
//后果等级不高,不需要加锁
model := domain.CreateModelContext(s.svc.MyContext)
mic, err := group_m.GetMic(model, groupUuid, i)
if err != nil {
return err
}
return mic.MgrMute(userId, externalId)
}
// 麦位解除静音
func (s *GroupMicService) GroupMicUnMute(userId uint64, externalId string, groupUuid string, i int) error {
//后果等级不高,不需要加锁
model := domain.CreateModelContext(s.svc.MyContext)
mic, err := group_m.GetMic(model, groupUuid, i)
if err != nil {
return err
}
return mic.MgrUnMute(userId, externalId)
}
//开启麦
func (s *GroupMicService) GroupMicSpeechOpen(userId uint64, externalId string, groupUuid 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.SpeechOpen(userId, externalId)
}
//关闭麦
func (s *GroupMicService) GroupMicSpeechClose(userId uint64, externalId string, groupUuid 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)
}
//麦上的人群发消息
func (s *GroupMicService) GroupIMMassByInMic(groupId string, userId uint64, externalId string, content string) error {
return s.svc.Transactional(func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
micUser, err := group_m.GetMicUserByExternalId(model, externalId)
if err != nil {
return err
}
if err := micUser.ImMass(externalId); err != nil {
return err
}
//校验群组ID
if micUser.GroupUuid != groupId {
return myerr.NewSysError("groupId 不一致, http:groupId <> micUser.groupId")
}
//获取群成员
gm, err := group_m.GetMembers(model.Db, groupId)
if err != nil {
return err
}
uids := make([]uint64, 0)
for _, i := range gm {
//排除自己
if userId != i.UserId {
uids = append(uids, i.UserId)
}
}
return group_ev.PublishGroupImMass(model, &group_ev.GroupImMassEvent{
GroupId: groupId,
UserId: userId,
Members: uids,
Content: content,
})
})
}
// 群管理人群发消息
func (s *GroupMicService) GroupIMMassByMgr(groupId string, userId uint64, externalId string, content string) error {
return s.svc.Transactional(func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
//检查权限
if err := group_m.CheckPermission(model, groupId, userId); err != nil {
return err
}
//获取群成员
gm, err := group_m.GetMembers(model.Db, groupId)
if err != nil {
return err
}
uids := make([]uint64, 0)
for _, i := range gm {
//排除自己
if userId != i.UserId {
uids = append(uids, i.UserId)
}
}
return group_ev.PublishGroupImMass(model, &group_ev.GroupImMassEvent{
GroupId: groupId,
UserId: userId,
Members: uids,
Content: content,
})
})
}
package group_s package group_s
import ( import (
"encoding/json"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/config" "git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/mgr_e"
"hilo-group/_const/redis_key" "hilo-group/_const/redis_key"
"hilo-group/domain/event/group_ev"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/mgr_m"
"hilo-group/domain/model/noble_m" "hilo-group/domain/model/noble_m"
"hilo-group/domain/model/res_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/domain/service/signal_s"
"hilo-group/myerr"
"strconv" "strconv"
"time" "time"
) )
...@@ -116,3 +123,169 @@ func (s *GroupService) GetJoinGroupLimit(userId mysql.ID) (uint, error) { ...@@ -116,3 +123,169 @@ func (s *GroupService) GetJoinGroupLimit(userId mysql.ID) (uint, error) {
} }
return maxJoin, nil return maxJoin, nil
} }
//更新用户在群上的消息状态
func (s *GroupService) GroupUserMsgStatus(userId uint64, groupUuid string, msgStatus group_e.MsgStatusGroupUser) error {
return s.svc.Transactional(func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
//var groupInfo group_m.GroupInfo
//if err := model.Db.Where(&group_m.GroupInfo{
// ImGroupId: groupUuid,
//}).First(&groupInfo).Error; err != nil {
// return nil, nil, myerr.WrapErr(err)
//}
//
groupUser, err := group_m.GetGroupUserOrInit(model, groupUuid, userId)
if err != nil {
return err
}
if msgStatus == group_e.NormalMsgStatusGroupUser {
groupUser.MsgStatusNormal()
} else if msgStatus == group_e.MuteMsgStatusGroupUser {
groupUser.MsgStatusMute()
} else if msgStatus == group_e.DoNotDisturbMsgStatusGroupUser {
groupUser.MsgStatusDoNotDisturb()
}
return groupUser.Persistent()
})
}
//举报群组
func (s *GroupService) ReportGroup(fromUserId mysql.ID, groupId mysql.Str, reasonType mgr_e.ReportReasonType, imageUrl mysql.Str, reason mysql.Str) error {
return s.svc.Transactional(func() error {
model := domain.CreateModelContext(s.svc.MyContext)
reportGroup := mgr_m.ReportGroupAdd(model, fromUserId, groupId, reasonType, imageUrl, reason)
err := reportGroup.Persistent()
if err != nil {
return err
}
return nil
})
}
//群组自定义主题修改
func (s *GroupService) GroupCustomThemeUsing(userId mysql.ID, externalId string, imGroupId string, groupCustomThemeId uint64) error {
err1 := s.svc.Transactional(func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
groupCustomTheme, err := group_m.GetGroupCustomThemeById(model, imGroupId, groupCustomThemeId)
if err != nil {
return err
}
groupCustomTheme, err = groupCustomTheme.SetUsing(userId)
if err != nil {
return err
}
if err := groupCustomTheme.Persistent(); err != nil {
return err
}
//修改数据,然后数据持久化,
g := group_m.GroupInfo{
ThemeId: 0,
}
fields := []string{"theme_id"}
db := g.Update(model, imGroupId, fields)
if db.Error != nil {
return myerr.WrapErr(db.Error)
}
if err := groupCustomTheme.Persistent(); err != nil {
return err
} else {
return nil
}
})
if err1 == nil {
type signalMsg struct {
Name string `json:"name"`
Introduction string `json:"introduction"`
Notification string `json:"notification"`
FaceUrl string `json:"faceUrl"`
MicOn bool `json:"micOn"`
MicNumType group_e.GroupMicNumType
ThemeId uint64 `json:"themeId"`
ThemeUrl string `json:"themeUrl"`
//1: 官方 2:自定义
ThemeType uint8 `json:"themeType"`
}
model := domain.CreateModelContext(s.svc.MyContext)
groupInfo, err := group_m.GetGroupInfo(model, imGroupId)
if err != nil {
model.Log.Error(err)
return nil
}
signal := signalMsg{
Name: groupInfo.Name,
Introduction: groupInfo.Introduction,
Notification: groupInfo.Notification,
FaceUrl: groupInfo.FaceUrl,
MicOn: groupInfo.MicOn,
MicNumType: groupInfo.MicNumType,
ThemeId: 0,
ThemeUrl: "",
ThemeType: 0,
}
if groupInfo.ThemeId != 0 {
//signal.ThemeId = groupInfo.ThemeId
signal.ThemeType = 1
if rows, err := res_m.GroupThemeGetAllInUse(model.Db); err == nil {
for _, i := range rows {
if i.ID == uint64(groupInfo.ThemeId) {
signal.ThemeId = i.ID
signal.ThemeUrl = i.Url
break
}
}
}
} else {
//可能是自定义主题
id, url, err := group_m.GetShowCustomTheme(model, imGroupId)
if err != nil {
model.Log.Error(err)
return nil
}
if id > 0 {
signal.ThemeId = id
signal.ThemeUrl = url
signal.ThemeType = 2
}
}
buf, err := json.Marshal(signal)
if err == nil {
systemMsg := group_m.GroupSystemMsg{MsgId: group_e.GroupEditProfileSignal, Source: externalId, Content: string(buf)}
signal_s.SendSignalMsg(model, imGroupId, systemMsg, false)
}
}
return err1
}
//增加群组自定义主题
func (s *GroupService) AddGroupCustomTheme(userId mysql.ID, imGroupId string, picUrl string) (uint64, string, error) {
var themeId uint64 = 0
var themeUrl string = ""
return themeId, themeUrl, s.svc.Transactional(func() error {
model := domain.CreateModel(s.svc.CtxAndDb)
groupCustomTheme, err := group_m.AddGroupCustomTheme(model, userId, imGroupId, picUrl)
if err != nil {
return err
}
//将group_info的theme_id设置为0
//修改数据,然后数据持久化,
g := group_m.GroupInfo{
ThemeId: 0,
}
fields := []string{"theme_id"}
db := g.Update(model, imGroupId, fields)
if db.Error != nil {
return myerr.WrapErr(db.Error)
}
if err := groupCustomTheme.Persistent(); err != nil {
return err
}
themeId = groupCustomTheme.ID
themeUrl = groupCustomTheme.PicUrl
return group_ev.PublishBuyGroupCustomTheme(model, &group_ev.BuyGroupCustomThemeEvent{
GroupCustomThemeId: groupCustomTheme.ID,
UserId: userId,
})
})
}
This diff is collapsed.
...@@ -41,15 +41,20 @@ var ( ...@@ -41,15 +41,20 @@ var (
GroupMicNoUser = myerr.NewBusinessCode(12002, "No one on Mic", myerr.BusinessData{}) // 麦位上没有人 GroupMicNoUser = myerr.NewBusinessCode(12002, "No one on Mic", myerr.BusinessData{}) // 麦位上没有人
GroupMicLock = myerr.NewBusinessCode(12003, "Mic is locked", myerr.BusinessData{}) // 麦位加锁了 GroupMicLock = myerr.NewBusinessCode(12003, "Mic is locked", myerr.BusinessData{}) // 麦位加锁了
GroupMicHasUser = myerr.NewBusinessCode(12004, "Mic occupied", myerr.BusinessData{}) // 麦位中已经有人了 GroupMicHasUser = myerr.NewBusinessCode(12004, "Mic occupied", myerr.BusinessData{}) // 麦位中已经有人了
GroupConcurrencyLock = myerr.NewBusinessCode(12005, "concurrent Mic operation, please try ageain later", myerr.BusinessData{}) // 麦位并发操作,请重试
GroupMicUserHasIn = myerr.NewBusinessCode(12006, "Already on Mic", myerr.BusinessData{}) // 你已经在别的麦位上了 GroupMicUserHasIn = myerr.NewBusinessCode(12006, "Already on Mic", myerr.BusinessData{}) // 你已经在别的麦位上了
GroupMicNoYou = myerr.NewBusinessCode(12007, "Not on Mic", myerr.BusinessData{}) // 你不在该麦位上 GroupMicNoYou = myerr.NewBusinessCode(12007, "Not on Mic", myerr.BusinessData{}) // 你不在该麦位上
GroupMicInByInviteFail = myerr.NewBusinessCode(12008, "从邀请中上麦失败", myerr.BusinessData{})
GroupInfoMicClosed = myerr.NewBusinessCode(12009, "The Group does not open the mic positions", myerr.BusinessData{}) GroupInfoMicClosed = myerr.NewBusinessCode(12009, "The Group does not open the mic positions", myerr.BusinessData{})
GroupMicBanTourist = myerr.NewBusinessCode(12010, "Mic need member", myerr.BusinessData{}) // 游客不能上麦
// 群组 // 群组
GroupNotFound = myerr.NewBusinessCode(14001, "Group not found", myerr.BusinessData{}) // 找不到该群 GroupNotFound = myerr.NewBusinessCode(14001, "Group not found", myerr.BusinessData{}) // 找不到该群
NotGroupMember = myerr.NewBusinessCode(14002, "Not a group member", 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{}) // 操作权限不够 NoPrivileges = myerr.NewBusinessCode(14004, "Not enough permission", myerr.BusinessData{}) // 操作权限不够
InBlacklist = myerr.NewBusinessCode(14005, "Can not join the group due to blacklist", 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{}) // 群主不能退群 OwnerCannotLeave = myerr.NewBusinessCode(14008, "Owner can not leave the group", myerr.BusinessData{}) // 群主不能退群
WrongPasswordLength = myerr.NewBusinessCode(14010, "Incorrect password length", myerr.BusinessData{}) // 密码长度错误 WrongPasswordLength = myerr.NewBusinessCode(14010, "Incorrect password length", myerr.BusinessData{}) // 密码长度错误
GroupIsBanned = myerr.NewBusinessCode(14011, "group is banned by ", myerr.BusinessData{}) // 群已经被管理员封禁 GroupIsBanned = myerr.NewBusinessCode(14011, "group is banned by ", myerr.BusinessData{}) // 群已经被管理员封禁
...@@ -73,8 +78,11 @@ var ( ...@@ -73,8 +78,11 @@ var (
GroupPowerNoOwner = myerr.NewBusinessCode(15005, "power owner not exits or unique", myerr.BusinessData{}) // 国家势力主不存在或不唯一 GroupPowerNoOwner = myerr.NewBusinessCode(15005, "power owner not exits or unique", myerr.BusinessData{}) // 国家势力主不存在或不唯一
GroupPowerStayTooShort = myerr.NewBusinessCode(15006, "You joined this power not more than 10 days ago", myerr.BusinessData{}) // 加入国家势力不超过10天 GroupPowerStayTooShort = myerr.NewBusinessCode(15006, "You joined this power not more than 10 days ago", myerr.BusinessData{}) // 加入国家势力不超过10天
TaskHasAward = myerr.NewBusinessCode(19001, "task has award", myerr.BusinessData{})
//贵族 //贵族
NobleNoMicSpeechCloseLevel5 = myerr.NewBusinessCode(21001, "Can't mute 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
// 超级管理人 // 超级管理人
OfficialStaffLimit = myerr.NewBusinessCode(22001, "Operation failed", myerr.BusinessData{}) OfficialStaffLimit = myerr.NewBusinessCode(22001, "Operation failed", myerr.BusinessData{})
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -25,9 +25,14 @@ import ( ...@@ -25,9 +25,14 @@ import (
"hilo-group/cv/gift_cv" "hilo-group/cv/gift_cv"
"hilo-group/cv/group_cv" "hilo-group/cv/group_cv"
"hilo-group/cv/user_cv" "hilo-group/cv/user_cv"
"hilo-group/domain/cache/game_c"
"hilo-group/domain/cache/group_c" "hilo-group/domain/cache/group_c"
"hilo-group/domain/cache/res_c" "hilo-group/domain/cache/res_c"
"hilo-group/domain/cache/room_c"
"hilo-group/domain/cache/tim_c"
"hilo-group/domain/cache/user_c"
"hilo-group/domain/model/diamond_m" "hilo-group/domain/model/diamond_m"
"hilo-group/domain/model/game_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/noble_m" "hilo-group/domain/model/noble_m"
"hilo-group/domain/model/res_m" "hilo-group/domain/model/res_m"
...@@ -1101,7 +1106,7 @@ func AddPermanentMember(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -1101,7 +1106,7 @@ func AddPermanentMember(c *gin.Context) (*mycontext.MyContext, error) {
// fixme: 这些缓存还需要吗? // fixme: 这些缓存还需要吗?
group_c.ClearGroupMemberCount(groupId) group_c.ClearGroupMemberCount(groupId)
group_c.AddGroupMember(model, groupId, externalId) tim_c.AddGroupMember(model, groupId, externalId)
if isInvite == 1 && !needCost { // 已经接受了进群邀请 if isInvite == 1 && !needCost { // 已经接受了进群邀请
group_m.AcceptGroupInviteJoin(model, userId, groupId) group_m.AcceptGroupInviteJoin(model, userId, groupId)
...@@ -1703,3 +1708,218 @@ func downgradeRoom(myContext *mycontext.MyContext, gi *group_m.GroupInfo) error ...@@ -1703,3 +1708,218 @@ func downgradeRoom(myContext *mycontext.MyContext, gi *group_m.GroupInfo) error
} }
return nil return nil
} }
// @Tags 群组
// @Summary 进入房间
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @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 gameCode formData string false "gameCode"
// @Success 200 {object} group_cv.GroupChannelId
// @Router /v1/imGroup/in [put]
func GroupIn(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, externalId, err := req.GetUserIdAndExtId(c, myContext)
if err != nil {
return myContext, err
}
groupId := c.PostForm("groupId")
password := c.PostForm("password")
enterType := c.PostForm("enterType")
gameCode := c.PostForm("gameCode")
model := domain.CreateModelContext(myContext)
gi, err := group_m.GetInfoByTxGroupId(model, groupId)
if err != nil {
return myContext, err
}
if gi == nil {
return myContext, bizerr.GroupNotFound
}
groupId = gi.ImGroupId
ip := req.GetRequestIP(c)
imei, err := req.GetAppImei(c)
if err != nil {
imei, err = user_m.GetUserImeiStr(model, userId)
if err != nil {
return myContext, err
}
}
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 {
return myContext, err
} else {
// 加入房间缓存
if err = room_c.ProcessRoomVisit(groupId, userId); err != nil {
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())
}
resp.ResponseOk(c, group_cv.GroupChannelId{
ChannelId: channelId,
Token: token,
AgoraId: uint32(userId),
MicNumType: gi.MicNumType,
})
// v2.26及以后,客户端自己加TIM群,不再由服务器代加
_, major, minor, _, err := req.GetAppVersion(c)
if err != nil || major < 2 || major == 2 && minor < 26 {
go func() {
defer func() {
if r := recover(); r != nil {
//打印错误堆栈信息
mylogrus.MyLog.Errorf("GroupIn - JoinGroup, SYSTEM ACTION PANIC: %v, stack: %v", r, string(debug.Stack()))
}
}()
err := group_s.NewGroupService(myContext).JoinGroup(userId, externalId, gi.TxGroupId)
mylogrus.MyLog.Infof("myService.JoinGroup %s, user %d, err:%v", groupId, userId, err)
}()
}
// 判断是否需要执行游戏逻辑
if enterType != "" && gameCode != "" {
traceId := c.Writer.Header().Get(mycontext.TRACEID)
token := c.Writer.Header().Get(mycontext.TOKEN)
err := game_c.SetAutoMathEnterRoom(userId, gi.ImGroupId, traceId, token, enterType, gameCode)
if err != nil {
model.Log.Errorf("GroupIn cache.SetAutoMathEnterRoom userId:%v, imGroupId:%v, err:%v", userId, gi.ImGroupId, err)
}
//go proxy.GameAfterEnterRoom(model, userId, externalId, traceId, token, enterType, gameCode, gi)
}
//// 临时
//go func() {
// time.Sleep(time.Second * 2)
// //发送全麦信息
// myContext.Log.Infof("imCallBack CallbackAfterNewMemberJoin MicAllRPush begin MemberAccount:%v, gi:%v", externalId, gi)
// if err := group_m.MicAllRPush(domain.CreateModelContext(myContext), groupId, externalId); err != nil {
// myContext.Log.Errorf("imCallBack CallbackAfterNewMemberJoin MicAllRPush err MemberAccount:%v, gi:%v,err:%v", externalId, gi, err)
// } else {
// myContext.Log.Infof("imCallBack CallbackAfterNewMemberJoin MicAllRPush success MemberAccount:%v, gi:%v,err:%v", externalId, gi, err)
// }
// //加入在线列表
// user, err := user_m.GetUserByExtId(domain.CreateModelContext(myContext), externalId)
// if err != nil {
// myContext.Log.Errorf("imCallBack CallbackAfterNewMemberJoin RoomLivingIn GetUserByExtId err:%+v, MemberAccount:%v", err, externalId)
// }
// //添加用户在线列表
// err = group_m.RoomLivingIn(domain.CreateModelContext(myContext), groupId, user.ID, user.ExternalId, false)
// if err != nil {
// myContext.Log.Errorf("imCallBack CallbackAfterNewMemberJoin err:%+v, userId:%v", err, user.ID)
// } else {
// myContext.Log.Infof("imCallBack CallbackAfterNewMemberJoin RoomLivingIn success MemberAccount:%v, gi:%v", externalId, gi)
// }
//}()
return myContext, nil
}
}
// @Tags 群组
// @Summary 离开房间
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupId formData string true "群ID"
// @Success 200
// @Router /v1/imGroup/leave [post]
func GroupLeave(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, exteranlId, err := req.GetUserIdAndExtId(c, myContext)
if err != nil {
return myContext, err
}
groupId := c.PostForm("groupId")
if len(groupId) <= 0 {
return myContext, bizerr.InvalidParameter
}
model := domain.CreateModelContext(myContext)
groupId, err = group_m.ToImGroupId(model, groupId)
if err != nil {
return myContext, err
}
if err := group_s.NewGroupService(myContext).GroupLeave(userId, exteranlId, groupId); err != nil {
myContext.Log.Errorf("GroupLeave GroupLeave err:%v", err)
return myContext, err
} else {
/* roomOnlineUser, err := cv.GetGroupInUser(domain.CreateModelContext(myContext), groupId)
if err != nil {
myContext.Log.Errorf("cron socketStatus cv.GetGroupInUser err:%v", err)
}
buf, err := json.Marshal(roomOnlineUser)
if err != nil {
myContext.Log.Errorf("cron socketStatus json.Marshal err:%v", err)
}
service.SendSignalMsg(groupId, group_m.GroupSystemMsg{
MsgId: group_enum.GroupOnlineUser,
Content: string(buf),
} , true)*/
}
resp.ResponseOk(c, nil)
return myContext, nil
}
// @Tags 群组
// @Summary 踢人
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupId formData string true "群ID"
// @Param externalId formData string true "用户的externalId"
// @Success 200
// @Router /v1/imGroup/kick [post]
func GroupKick(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, externalId, nick, avatar, _, err := req.GetUserEx(c, myContext)
if err != nil {
return myContext, err
}
groupId := c.PostForm("groupId")
if len(groupId) <= 0 {
return myContext, bizerr.InvalidParameter
}
_, lang, err := req.GetUserIdLang(c, myContext)
if err != nil {
return myContext, err
}
model := domain.CreateModelContext(myContext)
txGroupId := groupId
groupId, err = group_m.ToImGroupId(model, groupId)
if err != nil {
return myContext, err
}
beKickExternalId := c.PostForm("externalId")
beKickUser, err := user_c.GetUserByExternalId(domain.CreateModelContext(myContext), beKickExternalId)
if err != nil {
return myContext, err
}
isGaming, err := game_m.IsGaming(model, beKickUser.ID, txGroupId)
if err != nil {
return myContext, err
}
if isGaming {
return myContext, bizerr.GamingCannotKick
}
if err = CheckOptToSvip6(model, userId, beKickUser.ID, lang, 10); err != nil {
return myContext, err
}
//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 {
return myContext, err
}
resp.ResponseOk(c, nil)
return myContext, nil
}
...@@ -4,16 +4,22 @@ import ( ...@@ -4,16 +4,22 @@ import (
"encoding/json" "encoding/json"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/mycontext" "git.hilo.cn/hilo-common/mycontext"
"git.hilo.cn/hilo-common/resource/config"
"git.hilo.cn/hilo-common/resource/mysql" "git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/rpc" "git.hilo.cn/hilo-common/rpc"
"git.hilo.cn/hilo-common/sdk/aws"
"git.hilo.cn/hilo-common/sdk/tencentyun" "git.hilo.cn/hilo-common/sdk/tencentyun"
"git.hilo.cn/hilo-common/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gorm.io/gorm" "gorm.io/gorm"
"hilo-group/_const/enum/diamond_e"
"hilo-group/_const/enum/group_e" "hilo-group/_const/enum/group_e"
"hilo-group/_const/enum/mgr_e" "hilo-group/_const/enum/mgr_e"
"hilo-group/_const/enum/msg_e" "hilo-group/_const/enum/msg_e"
"hilo-group/cv/diamond_cv"
"hilo-group/cv/user_cv" "hilo-group/cv/user_cv"
"hilo-group/domain/cache/group_c" "hilo-group/domain/cache/group_c"
"hilo-group/domain/model/diamond_m"
"hilo-group/domain/model/game_m" "hilo-group/domain/model/game_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/mgr_m" "hilo-group/domain/model/mgr_m"
...@@ -27,6 +33,7 @@ import ( ...@@ -27,6 +33,7 @@ import (
"hilo-group/req" "hilo-group/req"
"hilo-group/resp" "hilo-group/resp"
"strconv" "strconv"
"time"
) )
// @Tags 群组 // @Tags 群组
...@@ -921,3 +928,214 @@ func ResetGroupInfo(c *gin.Context) (*mycontext.MyContext, error) { ...@@ -921,3 +928,214 @@ func ResetGroupInfo(c *gin.Context) (*mycontext.MyContext, error) {
resp.ResponseOk(c, nil) resp.ResponseOk(c, nil)
return myContext, nil return myContext, nil
} }
// @Tags 群组
// @Summary 清理公屏
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupId formData string true "群ID"
// @Success 200
// @Router /v1/imGroup/mgr/clearScreen [post]
func GroupMgrClearScreen(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, err := req.GetUserId(c)
if err != nil {
return myContext, err
}
groupId := c.PostForm("groupId")
if len(groupId) <= 0 {
return myContext, bizerr.InvalidParameter
}
model := domain.CreateModelContext(myContext)
groupId, err = group_m.ToImGroupId(model, groupId)
if err != nil {
return myContext, err
}
if err := group_s.NewGroupService(myContext).GroupClearScreenByMgr(groupId, userId); err != nil {
return myContext, err
}
resp.ResponseOk(c, "")
return myContext, nil
}
type ReturnGroupThemeConfig struct {
Days int `json:"days"`
NumLimit int `json:"numLimit"`
DiamondNum int `json:"diamondNum"`
}
// @Tags 群组
// @Summary 查询自定义主题
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Success 200 {object} ReturnGroupThemeConfig
// @Router /v1/imGroup/theme/custom/config [get]
func GroupThemeConfig(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
diamondOperateSet := diamond_m.DiamondOperateSet{}
if err := mysql.Db.Model(&diamond_m.DiamondOperateSet{}).Where(&diamond_m.DiamondOperateSet{
Type: diamond_e.GroupCustomTheme,
}).First(&diamondOperateSet).Error; err != nil {
return myContext, err
}
resp.ResponseOk(c, ReturnGroupThemeConfig{
Days: config.GetGroupCustomThemeConfig().DAY,
NumLimit: config.GetGroupCustomThemeConfig().PIC_LIMIT,
DiamondNum: diamondOperateSet.DiamondNum,
})
return myContext, nil
}
type ReturnGroupThemeAdd struct {
DiamondNum uint32 `json:"diamondNum"`
ThemeId uint64 `json:"themeId"`
ThemeUrl string `json:"themeUrl"`
}
// @Tags 群组
// @Summary 上传自定义主题
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param picUrl formData string true "主题URL"
// @Param groupId formData string true "群ID"
// @Success 200 {object} ReturnGroupThemeAdd
// @Router /v1/imGroup/theme/custom [post]
func GroupThemeAdd(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, err := req.GetUserId(c)
if err != nil {
return myContext, err
}
picUrl := c.PostForm("picUrl")
if picUrl == "" {
return myContext, myerr.NewSysError("参数 picUrl 不能为空")
}
groupId := c.PostForm("groupId")
if len(groupId) <= 0 {
return myContext, bizerr.InvalidParameter
}
model := domain.CreateModelContext(myContext)
groupId, err = group_m.ToImGroupId(model, groupId)
if err != nil {
return myContext, err
}
switch config.GetConfigApp().MODERATE {
case "AWS":
passed, err := aws.ModerateLabels(model.Log, userId, picUrl)
if err == nil {
if !passed {
return myContext, bizerr.ImagePolicyViolation
}
} else {
model.Log.Warnf("ModerateLabels err:%v", err)
}
case "TENCENT":
label, err := tencentyun.ModerateImage(model, userId, "", utils.StripAwsPrefix(picUrl), picUrl)
if err == nil && label != "Pass" {
return myContext, bizerr.ImagePolicyViolation
}
}
themeId, themeUrl, err := group_s.NewGroupService(myContext).AddGroupCustomTheme(userId, groupId, picUrl)
if err != nil {
return myContext, err
}
diamond, err := diamond_cv.GetDiamond(userId)
if err != nil {
return nil, myerr.WrapErr(err)
}
resp.ResponseOk(c, ReturnGroupThemeAdd{
DiamondNum: *diamond.DiamondNum,
ThemeId: themeId,
ThemeUrl: themeUrl,
})
return myContext, nil
}
// @Tags 群组
// @Summary 使用自定义主题
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupCustomThemeId formData int true "自定义主题ID"
// @Param groupId formData string true "群ID"
// @Success 200
// @Router /v1/imGroup/theme/custom/using [put]
func GroupThemeUsing(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
userId, externalId, err := req.GetUserIdAndExtId(c, myContext)
if err != nil {
return myContext, err
}
groupId := c.PostForm("groupId")
if len(groupId) <= 0 {
return myContext, bizerr.InvalidParameter
}
model := domain.CreateModelContext(myContext)
groupId, err = group_m.ToImGroupId(model, groupId)
if err != nil {
return myContext, err
}
id, err := strconv.ParseUint(c.PostForm("groupCustomThemeId"), 10, 64)
if err != nil {
return myContext, err
}
if err := group_s.NewGroupService(myContext).GroupCustomThemeUsing(userId, externalId, groupId, id); err != nil {
return myContext, err
}
resp.ResponseOk(c, nil)
return myContext, nil
}
type ResultGroupTheme struct {
Id uint64 `json:"id"`
PicUrl string `json:"picUrl"`
RemainSecond int64 `json:"remainSecond"`
}
// @Tags 群组
// @Summary 查询有效的全部自定义主题
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupId query string true "群ID"
// @Success 200 {object} ResultGroupTheme
// @Router /v1/imGroup/theme/custom/all [get]
func GroupThemeValidAll(c *gin.Context) (*mycontext.MyContext, error) {
myContext := mycontext.CreateMyContext(c.Keys)
groupId := c.Query("groupId")
if len(groupId) <= 0 {
return myContext, bizerr.InvalidParameter
}
model := domain.CreateModelContext(myContext)
groupId, err := group_m.ToImGroupId(model, groupId)
if err != nil {
return myContext, err
}
var groupCustomThemes []group_m.GroupCustomTheme
if err := mysql.Db.Where(&group_m.GroupCustomTheme{ImGroupId: groupId}).Where("expire_time > ?", time.Now()).Order("expire_time asc").Find(&groupCustomThemes).Error; err != nil {
return myContext, err
}
//
resultGroupThemes := make([]ResultGroupTheme, 0, len(groupCustomThemes))
now := time.Now().Unix()
for _, r := range groupCustomThemes {
resultGroupThemes = append(resultGroupThemes, ResultGroupTheme{
Id: r.ID,
PicUrl: r.PicUrl,
RemainSecond: r.ExpireTime.Unix() - now,
})
}
resp.ResponseOk(c, resultGroupThemes)
return myContext, nil
}
...@@ -73,47 +73,47 @@ func InitRouter() *gin.Engine { ...@@ -73,47 +73,47 @@ func InitRouter() *gin.Engine {
imGroup.PUT("/upgrade", wrapper(group_r.UpgradeGroup)) imGroup.PUT("/upgrade", wrapper(group_r.UpgradeGroup))
imGroup.PUT("/downgrade", wrapper(group_r.DowngradeGroup)) imGroup.PUT("/downgrade", wrapper(group_r.DowngradeGroup))
// //
//imGroup.GET("/mic/all", wrapper(GroupMicAllInfoFive)) imGroup.GET("/mic/all", wrapper(group_r.GroupMicAllInfoFive))
//imGroup.GET("/mic/all/type", wrapper(GroupMicAllInfoTen)) imGroup.GET("/mic/all/type", wrapper(group_r.GroupMicAllInfoTen))
//imGroup.GET("/mic/all/type/new", wrapper(GroupMicAllInfoType)) imGroup.GET("/mic/all/type/new", wrapper(group_r.GroupMicAllInfoType))
//imGroup.PUT("/mic/num", wrapper(GroupMicNumChange)) imGroup.PUT("/mic/num", wrapper(group_r.GroupMicNumChange))
//imGroup.GET("/mic/num", wrapper(GroupMicNum)) imGroup.GET("/mic/num", wrapper(group_r.GroupMicNum))
//imGroup.POST("/mic/emoji/msg", wrapper(GroupSendMicSystemMsg)) imGroup.POST("/mic/emoji/msg", wrapper(group_r.GroupSendMicSystemMsg))
//imGroup.POST("/mic/in/invite/dialog", wrapper(GroupMicInInviteDialog)) imGroup.POST("/mic/in/invite/dialog", wrapper(group_r.GroupMicInInviteDialog))
//imGroup.POST("/mic/task/invite/dialog", wrapper(GroupMicTaskInviteDialog)) imGroup.POST("/mic/task/invite/dialog", wrapper(group_r.GroupMicTaskInviteDialog))
//imGroup.POST("/mic/in", LogRequestTime, wrapper(GroupMicIn)) imGroup.POST("/mic/in", wrapper(group_r.GroupMicIn))
//imGroup.POST("/mic/invite", LogRequestTime, wrapper(GroupMicInvite)) imGroup.POST("/mic/invite", wrapper(group_r.GroupMicInvite))
//imGroup.POST("/mic/leave", LogRequestTime, wrapper(GroupMicLeave)) imGroup.POST("/mic/leave", wrapper(group_r.GroupMicLeave))
//imGroup.POST("/mic/lock", wrapper(GroupMicLock)) imGroup.POST("/mic/lock", wrapper(group_r.GroupMicLock))
//imGroup.POST("/mic/unlock", wrapper(GroupMicUnLock)) imGroup.POST("/mic/unlock", wrapper(group_r.GroupMicUnLock))
//imGroup.POST("/mic/speech/open", wrapper(GroupMicSpeechOpen)) imGroup.POST("/mic/speech/open", wrapper(group_r.GroupMicSpeechOpen))
//imGroup.POST("/mic/speech/close", wrapper(GroupMicSpeechClose)) imGroup.POST("/mic/speech/close", wrapper(group_r.GroupMicSpeechClose))
//imGroup.POST("/mic/mute", wrapper(GroupMicMute)) imGroup.POST("/mic/mute", wrapper(group_r.GroupMicMute))
//imGroup.POST("/mic/unmute", wrapper(GroupMicUnmute)) imGroup.POST("/mic/unmute", wrapper(group_r.GroupMicUnmute))
//imGroup.PUT("/in", LogRequestTime, wrapper(GroupIn)) imGroup.PUT("/in", wrapper(group_r.GroupIn))
//imGroup.POST("/leave", wrapper(GroupLeave)) imGroup.POST("/leave", wrapper(group_r.GroupLeave))
//imGroup.POST("/kick", wrapper(GroupKick)) imGroup.POST("/kick", wrapper(group_r.GroupKick))
//imGroup.PUT("/user/msg/status", wrapper(GroupUserMsg)) imGroup.PUT("/user/msg/status", wrapper(group_r.GroupUserMsg))
//imGroup.POST("/report", wrapper(GroupReport)) imGroup.POST("/report", wrapper(group_r.GroupReport))
//imGroup.GET("/banner/list", wrapper(GroupBannerList)) imGroup.GET("/banner/list", wrapper(group_r.GroupBannerList))
//imGroup.GET("/roomBanners", wrapper(RoomBannerList)) imGroup.GET("/roomBanners", wrapper(group_r.RoomBannerList))
//imGroup.PUT("/roomBanners", wrapper(NotifyRoomBannerListChange)) imGroup.PUT("/roomBanners", wrapper(group_r.NotifyRoomBannerListChange))
//imGroup.POST("/mic/gift", wrapper(GroupMicGift)) //imGroup.POST("/mic/gift", wrapper(GroupMicGift)) // todo 先留在biz,内容有点多
//imGroup.POST("/mic/mass", wrapper(GroupMicMass)) imGroup.POST("/mic/mass", wrapper(group_r.GroupMicMass))
//imGroup.POST("/mgr/mass", wrapper(GroupMgrMass)) imGroup.POST("/mgr/mass", wrapper(group_r.GroupMgrMass))
//imGroup.POST("/mgr/clearScreen", wrapper(GroupMgrClearScreen)) imGroup.POST("/mgr/clearScreen", wrapper(group_r.GroupMgrClearScreen))
//imGroup.GET("/online/users", wrapper(GroupInUsers)) imGroup.GET("/online/users", wrapper(group_r.GroupInUsers))
//imGroup.GET("/online/users/new", wrapper(GroupInUserNew)) imGroup.GET("/online/users/new", wrapper(group_r.GroupInUserNew))
//imGroup.GET("/country", wrapper(GetGroupByCountry)) imGroup.GET("/country", wrapper(group_r.GetGroupByCountry))
//imGroup.GET("/country/prior", wrapper(GroupountryPrior)) imGroup.GET("/country/prior", wrapper(group_r.GroupountryPrior))
// //
//imGroup.POST("/theme/custom", wrapper(GroupThemeAdd)) imGroup.POST("/theme/custom", wrapper(group_r.GroupThemeAdd))
//imGroup.GET("/theme/custom/config", wrapper(GroupThemeConfig)) imGroup.GET("/theme/custom/config", wrapper(group_r.GroupThemeConfig))
//imGroup.PUT("/theme/custom/using", wrapper(GroupThemeUsing)) imGroup.PUT("/theme/custom/using", wrapper(group_r.GroupThemeUsing))
//imGroup.GET("/theme/custom/all", wrapper(GroupThemeValidAll)) imGroup.GET("/theme/custom/all", wrapper(group_r.GroupThemeValidAll))
// //
//imGroup.GET("/medal/all", wrapper(GroupMedalAll)) imGroup.GET("/medal/all", wrapper(group_r.GroupMedalAll))
//imGroup.GET("/medal/room", wrapper(GetRoomMedal)) imGroup.GET("/medal/room", wrapper(group_r.GetRoomMedal))
} }
groupPower := v1.Group("/groupPower") groupPower := v1.Group("/groupPower")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment