package group_r 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" "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/utils" "github.com/gin-gonic/gin" "gorm.io/gorm" "hilo-group/_const/enum/diamond_e" "hilo-group/_const/enum/group_e" "hilo-group/_const/enum/mgr_e" "hilo-group/_const/enum/msg_e" "hilo-group/cv/diamond_cv" "hilo-group/cv/user_cv" "hilo-group/domain/cache/group_c" "hilo-group/domain/model/diamond_m" "hilo-group/domain/model/game_m" "hilo-group/domain/model/group_m" "hilo-group/domain/model/mgr_m" "hilo-group/domain/model/noble_m" "hilo-group/domain/model/res_m" "hilo-group/domain/model/user_m" "hilo-group/domain/service/group_s" "hilo-group/domain/service/signal_s" "hilo-group/myerr" "hilo-group/myerr/bizerr" "hilo-group/req" "hilo-group/resp" "strconv" "time" ) // @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" // @Success 200 {object} bool // @Router /v1/imGroup/password/{groupId} [get] func GetGroupPassword(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) userId, err := req.GetUserId(c) if err != nil { return myContext, err } groupId := c.Param("groupId") if len(groupId) <= 0 { return myContext, myerr.NewSysError("groupId 为必填项") } 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 result := false if gi != nil && len(gi.Password) > 0 && userId != gi.Owner { result = true } resp.ResponseOk(c, result) return myContext, nil } type SimpleRoleInfo struct { ExternalId string `json:"externalId"` Role group_e.GroupRoleType `json:"role"` } // @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 role query int false "指定的角色,不填的话代表全选" // @Success 200 {object} []SimpleRoleInfo // @Router /v1/imGroup/role/{groupId} [get] func GetGroupRole(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) groupId := c.Param("groupId") if len(groupId) <= 0 { return myContext, myerr.NewSysError("groupId 为必填项") } var role group_e.GroupRoleType = 0 r, err := strconv.Atoi(c.Query("role")) if err == nil { role = group_e.GroupRoleType(r) } userId, err := req.GetUserId(c) if err != nil { return myContext, err } model := domain.CreateModelContext(myContext) groupId, err = group_m.ToImGroupId(model, groupId) if err != nil { return myContext, err } roles, orderList, err := group_m.GetRolesInGroup(model, groupId) if err != nil { return myContext, err } result := make([]SimpleRoleInfo, 0) userBases, err := user_cv.GetUserBaseMap(orderList, userId) if err != nil { return myContext, err } for _, i := range orderList { if role == 0 || role == roles[i] { result = append(result, SimpleRoleInfo{ ExternalId: *userBases[i].ExternalId, Role: roles[i], }) } } resp.ResponseOk(c, result) 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 role formData int true "要赋予的角色" // @Param externalId formData string true "用户的externalId" // @Success 200 // @Router /v1/imGroup/role/{groupId} [put] func SetGroupRole(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) groupId := c.Param("groupId") if len(groupId) <= 0 { return myContext, myerr.NewSysError("groupId 为必填项") } r, err := strconv.Atoi(c.PostForm("role")) if err != nil { return myContext, err } role := group_e.GroupRoleType(r) if role != group_e.GROUP_MANAGER && role != group_e.GROUP_ADMIN && role != group_e.GROUP_MEMBER && role != group_e.GROUP_VISITOR { return myContext, myerr.NewSysError("Invalid role") } model := domain.CreateModelContext(myContext) groupId, err = group_m.ToImGroupId(model, groupId) if err != nil { return myContext, err } // 删除角色时没必要检查上限 if role > group_e.GROUP_MEMBER { // 检查有没有超过上限 TODO: 如何防止并发? count, err := group_m.GetRoleCountInGroup(model, groupId, role) if err != nil { return myContext, err } if role == group_e.GROUP_MANAGER && count >= group_e.GROUP_MANAGER_LIMIT { return myContext, bizerr.RoleLimitReached } if role == group_e.GROUP_ADMIN && count >= group_e.GROUP_ADMIN_LIMIT { return myContext, bizerr.RoleLimitReached } } userId, myExtId, nick, avatar, _, err := req.GetUserEx(c, myContext) if err != nil { return myContext, err } // 检查用户是否有权限做操作 myRole, err := group_m.GetRoleInGroup(model, userId, groupId) if err != nil { return myContext, err } // 管理员以下不能改变任何角色 if myRole <= group_e.GROUP_ADMIN { return myContext, bizerr.NoPrivileges } if role == group_e.GROUP_MANAGER && myRole != group_e.GROUP_OWNER { return myContext, bizerr.NoPrivileges } if role == group_e.GROUP_ADMIN && myRole != group_e.GROUP_OWNER && myRole != group_e.GROUP_MANAGER { return myContext, bizerr.NoPrivileges } if (role == group_e.GROUP_VISITOR || role == group_e.GROUP_MEMBER) && myRole != group_e.GROUP_OWNER && myRole != group_e.GROUP_MANAGER { return myContext, bizerr.NoPrivileges } externalId := c.PostForm("externalId") model.Log.Info("externalId: ", externalId) // targetUser, err := user_m.GetUserByExtId(model, externalId) if err != nil { return myContext, err } isGroupMember, err := group_m.IsGroupMember(model.Db, groupId, targetUser.ID) if err != nil && err != gorm.ErrRecordNotFound { return myContext, err } // 邀请用户加入群组会员、把用户设置成游客 if role == group_e.GROUP_VISITOR || (role == group_e.GROUP_MEMBER && !isGroupMember) { err = SetGroupMemberTourist(model, role, isGroupMember, targetUser.ID, userId, externalId, myExtId, groupId) if err != nil { return myContext, err } resp.ResponseOk(c, nil) return myContext, nil } if !isGroupMember { return myContext, bizerr.NotGroupMember } // 先读取旧角色 oldRole, err := group_m.GetRoleInGroup(model, targetUser.ID, groupId) if err != nil { return myContext, err } if oldRole >= myRole { // 不能调整更高级者的角色! return myContext, bizerr.NoPrivileges } if role <= group_e.GROUP_MEMBER { // 如果已经没有角色,则不需要取消 if oldRole != role { err = RemoveGroupRole(model, groupId, myExtId, externalId, nick, avatar, targetUser.Nick, targetUser.Avatar, targetUser.ID, oldRole) if err != nil { return myContext, err } } } else if err = group_m.CreateGroupRole(model, groupId, targetUser.ID, role); err == nil { // 发送信令 systemMsg := group_m.GroupSystemMsg{MsgId: group_e.GroupRoleChangeSignal, Source: myExtId, Target: externalId, Content: "add"} signal_s.SendSignalMsg(model, groupId, systemMsg, false) nobleLevel, err := noble_m.GetNobleLevel(model.Db, targetUser.ID) if err != nil { return myContext, err } // 发公屏消息 msg := group_m.CommonPublicMsg{Type: group_e.RoleAssignedPublicScreenMsg, OperatorExternalId: myExtId, OperatorNick: nick, OperatorAvatar: avatar, ExternalId: targetUser.ExternalId, Nick: targetUser.Nick, Avatar: targetUser.Avatar, NobleLevel: nobleLevel, Role: role} buf, err := json.Marshal(msg) if err == nil { signal_s.SendCustomMsg(model, groupId, nil, string(buf)) } } else { return myContext, err } // 发送腾讯云信令 con := &GroupRoleChangeMsg{Role: int(role)} msgContent, _ := json.Marshal(con) signal_s.SendSignalMsg(model, groupId, group_m.GroupSystemMsg{ MsgId: group_e.GroupRoleChange, Source: myExtId, Target: externalId, Content: string(msgContent), }, false) // 新角色不是经理角度时,将其(可能)设置的欢迎语清除 if role < group_e.GROUP_MANAGER { gwt := group_m.GroupWelcomeText{} if err = gwt.Remove(model.Db, groupId, targetUser.ID); err != nil { model.Log.Warnf("Can't remove group %s user %d's welcome text.", groupId, userId) } } resp.ResponseOk(c, nil) return myContext, nil } func RemoveGroupRole(model *domain.Model, groupId, myExtId, externalId, nick, avatar, targetNick, targetAvatar string, targetUserId uint64, oldRole group_e.GroupRoleType) error { if err := group_m.RemoveGroupRole(model, groupId, targetUserId); err == nil { // 发送信令 systemMsg := group_m.GroupSystemMsg{MsgId: group_e.GroupRoleChangeSignal, Source: myExtId, Target: externalId, Content: "remove"} signal_s.SendSignalMsg(model, groupId, systemMsg, false) nobleLevel, err := noble_m.GetNobleLevel(model.Db, targetUserId) if err != nil { return err } // 发公屏消息 msg := group_m.CommonPublicMsg{Type: group_e.RoleRemovedPublicScreenMsg, OperatorExternalId: myExtId, OperatorNick: nick, OperatorAvatar: avatar, ExternalId: externalId, Nick: targetNick, Avatar: targetAvatar, NobleLevel: nobleLevel, Role: oldRole} buf, err := json.Marshal(msg) if err != nil { return err } signal_s.SendCustomMsg(model, groupId, nil, string(buf)) } return nil } func SetGroupMemberTourist(model *domain.Model, role group_e.GroupRoleType, isGroupMember bool, userId, inviteUserId uint64, externalId, myExtId, imGroupId string) (err error) { var msgId group_e.TypeSignalMsg var msgContent string switch role { case group_e.GROUP_MEMBER: if isGroupMember { // 已经是成员,直接返回 return nil } // 邀请对方成为成员 // 插入邀请表 err = group_m.InsertGroupInviteJoin(model, userId, inviteUserId, imGroupId) if err != nil { return err } msgId = group_e.GroupMemberInvite case group_e.GROUP_VISITOR: if !isGroupMember { // 不是成员,直接返回 return nil } // 移除成员 if err = group_s.NewGroupService(nil).LeaveGroupMember(model, imGroupId, userId, externalId); err != nil { return err } msgId = group_e.GroupRoleChange con := &GroupRoleChangeMsg{Role: int(group_e.GROUP_VISITOR)} jData, _ := json.Marshal(con) msgContent = string(jData) } if msgId > 0 { // 发送腾讯云信令 signal_s.SendSignalMsg(model, imGroupId, group_m.GroupSystemMsg{ MsgId: msgId, Source: myExtId, Target: externalId, Content: msgContent, }, false) } return nil } type GroupRoleChangeMsg struct { Role int `json:"role"` } // @Tags 群组 // @Summary 接受邀请-成为永久成员 // @Param groupId formData string true "群ID" // @Success 200 // @Router /v1/imGroup/role/accept [post] func AcceptMemberInvite(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) groupId := c.Param("groupId") if len(groupId) <= 0 { return myContext, myerr.NewSysError("groupId 为必填项") } resp.ResponseOk(c, group_e.ADD_GROUP_DONE) 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 externalId formData string true "用户的externalId" // @Param removeHistory formData bool true "是否删除聊天记录" // @Param blackImei formData bool false "SVIP是否封禁设备和ip" // @Success 200 // @Router /v1/imGroup/blacklist/{groupId} [put] func AddGroupBlacklist(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) groupId := c.Param("groupId") if len(groupId) <= 0 { return myContext, myerr.NewSysError("groupId 为必填项") } removeHistory, err := strconv.ParseBool(c.PostForm("removeHistory")) if err != nil { return myContext, myerr.NewSysError("removeHistory 为必填项") } blackImei, err := strconv.ParseBool(c.PostForm("blackImei")) if err != nil { blackImei = false } userId, myExtId, nick, avatar, _, err := req.GetUserEx(c, myContext) if err != nil { return myContext, err } _, 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 } myRole, err := group_m.GetRoleInGroup(model, userId, groupId) if err != nil { return myContext, err } if myRole < group_e.GROUP_ADMIN { return myContext, bizerr.NoPrivileges } externalId := c.PostForm("externalId") user, err := user_m.GetUserByExtId(model, externalId) if err != nil { return myContext, err } //超级管理人 if flag, err := user_m.IsSuperManager(domain.CreateModelContext(myContext), user.ID); err != nil { return myContext, err } else if flag { return myContext, bizerr.OfficialStaffLimit } role, err := group_m.GetRoleInGroup(model, user.ID, groupId) if err != nil { return myContext, err } isGaming, err := game_m.IsGaming(model, user.ID, txGroupId) if err != nil { return myContext, err } if isGaming { return myContext, bizerr.GamingCannotKick } if err = CheckOptToSvip6(model, userId, user.ID, lang, 10); err != nil { return myContext, err } // svip svipMap, err := rpc.MGetUserSvip(model, []mysql.ID{userId, user.ID}) if err != nil { return myContext, err } if myRole > role { // 是否svip封禁设备 var userImei, userIp string if blackImei && role != group_e.GROUP_OWNER && role != group_e.GROUP_MANAGER { if v, ok := svipMap[userId]; ok && v.SvipLevel > 0 { userImei, err = user_m.GetUserImeiStr(model, user.ID) if err != nil { return myContext, err } userIpInfo, err := user_m.GetUserIpOrInit(model, user.ID) if err != nil { return myContext, err } userIp = userIpInfo.Ip } } // TODO: 先发信令和公屏消息,避免被封之人收不到 // 发送信令 type removeHistoryParam struct { RemoveHistory bool `json:"removeHistory"` } r := removeHistoryParam{RemoveHistory: removeHistory} buf, err := json.Marshal(r) if err == nil { systemMsg := group_m.GroupSystemMsg{MsgId: group_e.GroupMemberRemoveSignal, Source: myExtId, Target: externalId, Content: string(buf)} signal_s.SendSignalMsg(model, groupId, systemMsg, false) } // 发公屏消息 msg := group_m.CommonPublicMsg{Type: group_e.UserBannedPublicScreenMsg, OperatorExternalId: myExtId, OperatorNick: nick, OperatorAvatar: avatar, ExternalId: user.ExternalId, Nick: user.Nick, Avatar: user.Avatar} buf, err = json.Marshal(msg) 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 } gb := group_m.GroupBlacklist{ImGroupId: groupId, UserId: user.ID, Imei: userImei, Ip: userIp} err = group_m.AddBlacklist(model, &gb) if err != nil { model.Log.Errorf("AddBlacklist failed for %s, user %d", groupId, user.ID) } } else { return myContext, bizerr.NoPrivileges } resp.ResponseOk(c, nil) return myContext, nil } // 检查是否可以对svip6进行操作 optUserId:被操作的用户id func CheckOptToSvip6(model *domain.Model, userId, optUserId uint64, lang string, privilegeId int) error { // 是否超管 isM, err := user_m.IsSuperManagerV2(model, userId, optUserId) if err != nil { return err } // svip svipMap, err := rpc.MGetUserSvip(model, []mysql.ID{userId, optUserId}) if err != nil { return err } if !isM { if svip, ok := svipMap[userId]; !ok || svip.SvipLevel < 6 { // 非svip6(svip6可以对svip6进行操作) // 是否禁止被封禁 if svip, ok := svipMap[optUserId]; ok { for _, v := range svip.Privileges { if v.Type == privilegeId { return myerr.WrapErr(res_m.GetErrByLanguage(model.Db, msg_e.MSG_ID_NO_POWER_TO_SVIP6, lang, bizerr.GroupNoPowerToSvip6)) } } } } } return 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 externalId query string true "用户的externalId" // @Success 200 // @Router /v1/imGroup/blacklist/{groupId} [delete] func RemoveGroupBlacklist(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) groupId := c.Param("groupId") if len(groupId) <= 0 { return myContext, myerr.NewSysError("groupId 为必填项") } userId, err := req.GetUserId(c) if err != nil { return myContext, err } model := domain.CreateModelContext(myContext) groupId, err = group_m.ToImGroupId(model, groupId) if err != nil { return myContext, err } myRole, err := group_m.GetRoleInGroup(model, userId, groupId) if err != nil { return myContext, err } if myRole < group_e.GROUP_ADMIN { return myContext, bizerr.NoPrivileges } externalId := c.Query("externalId") if len(externalId) <= 0 { return myContext, myerr.NewSysError("externalId 为必填项") } user, err := user_m.GetUserByExtId(model, externalId) if err != nil { return myContext, err } err = group_m.RemoveBlacklist(model, &group_m.GroupBlacklist{ImGroupId: groupId, UserId: user.ID}) if err != nil { return myContext, err } resp.ResponseOk(c, nil) return myContext, nil } //拉黑列表视图 type GroupBlackList struct { //拉黑时间 BlockTime int64 `json:"blockTime"` //用户基本信息 UserBase user_cv.CvUserBase `json:"userBase"` } // @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" // @Success 200 {object} GroupBlackList // @Router /v1/imGroup/blacklist/{groupId} [get] func GetGroupBlacklist(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) groupId := c.Param("groupId") if len(groupId) <= 0 { return myContext, myerr.NewSysError("groupId 为必填项") } userId, err := req.GetUserId(c) if err != nil { return myContext, err } model := domain.CreateModelContext(myContext) groupId, err = group_m.ToImGroupId(model, groupId) if err != nil { return myContext, err } // TODO: 非群成员不能看 rows, err := group_m.FindGroupBlackList(model, groupId) if err != nil { return myContext, err } userIds := make([]uint64, 0) for _, i := range rows { userIds = append(userIds, i.UserId) } users, err := user_cv.GetUserBaseMap(userIds, userId) if err != nil { return myContext, err } result := make([]GroupBlackList, 0) for _, i := range rows { result = append(result, GroupBlackList{ BlockTime: i.CreatedTime.Unix(), UserBase: *users[i.UserId], }) } resp.ResponsePageOk(c, result, uint(len(result)), 1) 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 externalId formData string true "用户的externalId" // @Param removeHistory formData bool true "是否删除聊天记录" // @Success 200 // @Router /v1/imGroup/kick/{groupId} [put] func KickGroupMembers(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) groupId := c.Param("groupId") if len(groupId) <= 0 { return myContext, myerr.NewSysError("groupId 为必填项") } removeHistory, err := strconv.ParseBool(c.PostForm("removeHistory")) if err != nil { return myContext, myerr.NewSysError("removeHistory 为必填项") } userId, myExtId, _, _, _, err := req.GetUserEx(c, myContext) if err != nil { return myContext, err } if !user_m.IsSuperUser(userId) { return myContext, bizerr.NoPrivileges } model := domain.CreateModelContext(myContext) txGroupId := groupId groupId, err = group_m.ToImGroupId(model, groupId) if err != nil { return myContext, err } externalId := c.PostForm("externalId") user, err := user_m.GetUserByExtId(model, externalId) if err != nil { return myContext, err } role, err := group_m.GetRoleInGroup(model, user.ID, groupId) if err != nil { return myContext, err } if role > group_e.GROUP_MEMBER { // 不能踢有角色的人出去 return myContext, bizerr.NoPrivileges } // 发送信令? type removeHistoryParam struct { RemoveHistory bool `json:"removeHistory"` } r := removeHistoryParam{RemoveHistory: removeHistory} buf, err := json.Marshal(r) if err == nil { systemMsg := group_m.GroupSystemMsg{MsgId: group_e.GroupMemberRemoveSignal, 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 } 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 path string true "群ID" // @Param text formData string true "欢迎语" // @Success 200 // @Router /v1/imGroup/welcomeText/{groupId} [put] func SetWelcomeText(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) groupId := c.Param("groupId") if len(groupId) <= 0 { return myContext, myerr.NewSysError("groupId 为必填项") } text := c.PostForm("text") if len(text) <= 0 { return myContext, bizerr.EmptyContent } if len([]rune(text)) > group_e.GROUP_INTRODUCTION_LENGTH_LIMIT { return myContext, bizerr.ContentTooLong } 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 } if group_c.IsEditGroupCd(model, groupId) { return myContext, bizerr.EditCd } myRole, err := group_m.GetRoleInGroup(model, userId, groupId) if err != nil { return myContext, err } if myRole != group_e.GROUP_OWNER && myRole != group_e.GROUP_MANAGER { return myContext, bizerr.NoPrivileges } gwt := group_m.GroupWelcomeText{GroupId: groupId, UserId: userId, Text: text} if err = gwt.Save(model.Db); err != nil { return myContext, err } resp.ResponseOk(c, nil) return myContext, nil } // @Tags 群组 // @Summary 设置群成员上限(obsolete) // @Accept application/x-www-form-urlencoded // @Param token header string true "token" // @Param nonce header string true "随机数字" // @Param groupId formData string true "群组ID" // @Param limit formData int true "成员上限" // @Success 200 // @Router /v1/imGroup/memberLimit [put] func SetGroupMemberLimit(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) groupId := c.PostForm("groupId") if len(groupId) <= 0 { return myContext, bizerr.ParaMissing } slimit := c.PostForm("limit") limit, err := strconv.Atoi(slimit) if err != nil || limit <= 0 { return myContext, bizerr.InvalidParameter } model := domain.CreateModelContext(myContext) groupInfo, err := group_m.GetInfoByTxGroupId(model, groupId) if err == nil && groupInfo != nil { err = tencentyun.SetGroupMaxMemberNum(groupInfo.ImGroupId, uint(limit)) if err != nil { model.Log.Warn("SetGroupMemberLimit failed for ", groupId) } } else { model.Log.Warn("Skip group ", groupId) } 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 externalId formData string true "externalId" // @Success 200 // @Router /v1/imGroup/info/reset [put] func ResetGroupInfo(c *gin.Context) (*mycontext.MyContext, error) { myContext := mycontext.CreateMyContext(c.Keys) userId, err := req.GetUserId(c) if err != nil { return myContext, err } externalId := c.PostForm("externalId") if len(externalId) <= 0 { return myContext, bizerr.ParaMissing } model := domain.CreateModelContext(myContext) //isMgr, err := user_m.IsCommunityManager(model.Db, userId) //if err != nil { // return myContext, err //} //if !isMgr { // return myContext, bizerr.UserGlobalBroadcastManagerNo //} globalManager, countryManager, err := group_s.NewGroupService(myContext).CheckAppManager(userId) if err != nil { return myContext, err } if !globalManager && !countryManager { return myContext, bizerr.UserGlobalBroadcastManagerNo } user, err := user_m.GetUserByExtId(model, externalId) if err != nil { return myContext, err } if user == nil || user.ID <= 0 { return myContext, bizerr.ExternalIdNoExist } gi, err := group_m.FindGroupByOwner(model, user.ID) if err != nil { return myContext, err } if len(gi) <= 0 { return myContext, bizerr.GroupNotFound } // 额外判断国家管理员权限 if !globalManager && countryManager { if isManager, _ := group_s.NewGroupService(myContext).CheckCountryManagerPermission(userId, user.ID); !isManager { return myContext, bizerr.UserGlobalBroadcastManagerNo } } if err = group_m.ResetGroupInfo(model, gi[0].ImGroupId, gi[0].Code); err != nil { return myContext, err } c.Set(mgr_e.OperationLogKey, mgr_m.MgrOperationLog{ Content: "管理员重置群信息", TargetUid: user.ID, OperUid: userId, }) 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" // @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 }