Files
im_manager/server/internal/logic/sys/im_group.go
T

457 lines
13 KiB
Go

// Package sys
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2026 HotGo
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
package sys
import (
"context"
"hotgo/internal/library/imtenant"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
)
type sSysImGroup struct{}
func NewSysImGroup() *sSysImGroup {
return &sSysImGroup{}
}
func init() {
service.RegisterSysImGroup(NewSysImGroup())
}
// List 获取IM群组列表
func (s *sSysImGroup) List(ctx context.Context, in *sysin.ImGroupListInp) (list []*sysin.ImGroupListModel, totalCount int, err error) {
if err = in.Filter(ctx); err != nil {
return
}
db, tenant, err := imtenant.DB(ctx, in.TenantId)
if err != nil {
return
}
mod := s.groupModel(ctx, db)
mod = s.applyGroupWhere(mod, in)
mod = mod.Page(in.Page, in.PerPage).OrderDesc("t.touchedat").OrderDesc("t.id")
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取IM群组列表失败,请稍后重试!")
return
}
for _, item := range list {
item.TenantId = tenant.Id
item.TenantName = tenant.Name
}
return
}
func (s *sSysImGroup) groupModel(ctx context.Context, db gdb.DB) *gdb.Model {
return db.Model("im_topics t").Safe().Ctx(ctx).
LeftJoin("im_group_settings gs", "gs.topic = t.name").
Fields(
"t.name topic",
"t.state",
"COALESCE(gs.owner_user_id, t.owner) owner_id",
"t.seqid seq_id",
"t.delid del_id",
"t.subcnt sub_cnt",
"t.touchedat touched_at",
"t.createdat created_at",
"t.updatedat updated_at",
"t.public public_json",
"t.trusted trusted_json",
"t.tags tags_json",
"t.aux aux_json",
"COALESCE(gs.name, '') group_name",
"COALESCE(gs.avatar_file_id, '') avatar_file_id",
"COALESCE(gs.description, '') description",
"COALESCE(gs.group_status, '') group_status",
"COALESCE(gs.join_approval, 0) join_approval",
"COALESCE(gs.mute_all, 0) mute_all",
"COALESCE(gs.member_upload_files, 0) member_upload_files",
"COALESCE(gs.member_private_chat, 0) member_private_chat",
"COALESCE(gs.member_invite, 0) member_invite",
"COALESCE(gs.max_member_count, 0) max_member_count",
"COALESCE(gs.max_admin_count, 0) max_admin_count",
"COALESCE(gs.member_count, 0) business_member_count",
"COALESCE(gs.version, 0) settings_version",
"gs.updated_at settings_updated_at",
).
WhereLike("t.name", "grp%")
}
func (s *sSysImGroup) applyGroupWhere(mod *gdb.Model, in *sysin.ImGroupListInp) *gdb.Model {
if in.Topic != "" {
mod = mod.WhereLike("t.name", "%"+in.Topic+"%")
}
if in.OwnerId > 0 {
mod = mod.Where("COALESCE(gs.owner_user_id, t.owner)", in.OwnerId)
}
if in.State != nil {
mod = mod.Where("t.state", *in.State)
}
if in.GroupStatus != "" {
mod = mod.Where("gs.group_status", in.GroupStatus)
}
if len(in.CreatedAt) == 2 {
mod = mod.WhereBetween("t.createdat", in.CreatedAt[0], in.CreatedAt[1])
}
if len(in.TouchedAt) == 2 {
mod = mod.WhereBetween("t.touchedat", in.TouchedAt[0], in.TouchedAt[1])
}
return mod
}
// View 获取IM群组指定信息
func (s *sSysImGroup) View(ctx context.Context, in *sysin.ImGroupViewInp) (res *sysin.ImGroupViewModel, err error) {
if err = in.Filter(ctx); err != nil {
return
}
db, tenant, err := imtenant.DB(ctx, in.TenantId)
if err != nil {
return
}
err = db.Model("im_topics t").Safe().Ctx(ctx).
LeftJoin("im_group_settings gs", "gs.topic = t.name").
Fields(
"t.name topic",
"t.state",
"COALESCE(gs.owner_user_id, t.owner) owner_id",
"t.seqid seq_id",
"t.delid del_id",
"t.subcnt sub_cnt",
"t.touchedat touched_at",
"t.createdat created_at",
"t.updatedat updated_at",
"t.public public_json",
"t.trusted trusted_json",
"t.tags tags_json",
"t.aux aux_json",
"t.access access_json",
"t.usebt use_bt",
"COALESCE(gs.name, '') group_name",
"COALESCE(gs.avatar_file_id, '') avatar_file_id",
"COALESCE(gs.description, '') description",
"COALESCE(gs.group_status, '') group_status",
"COALESCE(gs.join_approval, 0) join_approval",
"COALESCE(gs.mute_all, 0) mute_all",
"COALESCE(gs.member_upload_files, 0) member_upload_files",
"COALESCE(gs.member_private_chat, 0) member_private_chat",
"COALESCE(gs.member_invite, 0) member_invite",
"COALESCE(gs.max_member_count, 0) max_member_count",
"COALESCE(gs.max_admin_count, 0) max_admin_count",
"COALESCE(gs.member_count, 0) business_member_count",
"COALESCE(gs.version, 0) settings_version",
"gs.updated_at settings_updated_at",
).
Where("t.name", in.Topic).
WhereLike("t.name", "grp%").
Scan(&res)
if err != nil {
return nil, gerror.Wrap(err, "获取IM群组信息失败,请稍后重试!")
}
if res == nil {
return nil, nil
}
res.TenantId = tenant.Id
res.TenantName = tenant.Name
return
}
// MemberList 获取IM群成员列表
func (s *sSysImGroup) MemberList(ctx context.Context, in *sysin.ImGroupMemberListInp) (list []*sysin.ImGroupMemberListModel, totalCount int, err error) {
if err = in.Filter(ctx); err != nil {
return
}
db, _, err := imtenant.DB(ctx, in.TenantId)
if err != nil {
return
}
if s.hasGroupMemberTruth(ctx, db, in.Topic) {
return s.memberListFromBusiness(ctx, db, in)
}
return s.memberListFromProjection(ctx, db, in)
}
func (s *sSysImGroup) hasGroupMemberTruth(ctx context.Context, db gdb.DB, topic string) bool {
count, err := db.Model("im_group_members").Safe().Ctx(ctx).Where("topic", topic).Count()
return err == nil && count > 0
}
func (s *sSysImGroup) memberListFromBusiness(ctx context.Context, db gdb.DB, in *sysin.ImGroupMemberListInp) (list []*sysin.ImGroupMemberListModel, totalCount int, err error) {
mod := db.Model("im_group_members gm").Safe().Ctx(ctx).
LeftJoin("im_users u", "u.id = gm.user_id").
LeftJoin("im_user_profiles up", "up.user_id = gm.user_id").
LeftJoin("im_subscriptions s", "s.topic = gm.topic AND s.userid = gm.user_id").
Fields(
"gm.user_id",
"up.nickname",
"u.state",
"s.modewant mode_want",
"s.modegiven mode_given",
"s.recvseqid recv_seq_id",
"s.readseqid read_seq_id",
"s.delid del_id",
"s.deletedat deleted_at",
"s.createdat created_at",
"s.updatedat updated_at",
"s.private private_json",
"gm.role",
"gm.member_status",
"gm.nickname group_nickname",
"gm.pinned",
"gm.mute_notifications",
"gm.join_source",
"gm.joined_by",
"gm.joined_at",
"gm.left_at",
"gm.removed_by",
"gm.version",
).
Where("gm.topic", in.Topic)
if in.UserId > 0 {
mod = mod.Where("gm.user_id", in.UserId)
}
if in.Role != "" {
mod = mod.Where("gm.role", in.Role)
}
if in.MemberStatus != "" {
mod = mod.Where("gm.member_status", in.MemberStatus)
}
mod = mod.Page(in.Page, in.PerPage).OrderAsc("gm.member_status").OrderAsc("gm.role").OrderAsc("gm.id")
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取IM群成员列表失败,请稍后重试!")
return
}
return
}
func (s *sSysImGroup) memberListFromProjection(ctx context.Context, db gdb.DB, in *sysin.ImGroupMemberListInp) (list []*sysin.ImGroupMemberListModel, totalCount int, err error) {
mod := db.Model("im_subscriptions s").Safe().Ctx(ctx).
LeftJoin("im_users u", "u.id = s.userid").
LeftJoin("im_user_profiles up", "up.user_id = s.userid").
Fields(
"s.userid user_id",
"up.nickname",
"u.state",
"s.modewant mode_want",
"s.modegiven mode_given",
"s.recvseqid recv_seq_id",
"s.readseqid read_seq_id",
"s.delid del_id",
"s.deletedat deleted_at",
"s.createdat created_at",
"s.updatedat updated_at",
"s.private private_json",
"'member' role",
"IF(s.deletedat IS NULL, 'active', 'left') member_status",
"'' group_nickname",
"0 pinned",
"0 mute_notifications",
"'projection' join_source",
"0 joined_by",
"s.createdat joined_at",
"s.deletedat left_at",
"0 removed_by",
"0 version",
).
Where("s.topic", in.Topic)
if in.UserId > 0 {
mod = mod.Where("s.userid", in.UserId)
}
mod = mod.Page(in.Page, in.PerPage).OrderAsc("s.deletedat").OrderAsc("s.userid")
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取IM群成员列表失败,请稍后重试!")
return
}
return
}
// Governance 获取IM群治理配置
func (s *sSysImGroup) Governance(ctx context.Context, in *sysin.ImGroupTopicInp) (res *sysin.ImGroupGovernanceModel, err error) {
if err = in.Filter(ctx); err != nil {
return
}
db, tenant, err := imtenant.DB(ctx, in.TenantId)
if err != nil {
return nil, err
}
err = db.Model("im_group_settings").Safe().Ctx(ctx).
Fields(
"topic",
"owner_user_id",
"name",
"avatar_file_id",
"description",
"group_status",
"join_approval",
"mute_all",
"member_upload_files",
"member_private_chat",
"member_invite",
"max_member_count",
"max_admin_count",
"member_count",
"version",
"created_by",
"dissolved_by",
"dissolved_at",
"created_at",
"updated_at",
).
Where("topic", in.Topic).
Scan(&res)
if err != nil {
return nil, gerror.Wrap(err, "获取IM群治理配置失败,请稍后重试!")
}
if res == nil {
return nil, nil
}
res.TenantId = tenant.Id
res.TenantName = tenant.Name
return
}
// JoinRequestList 获取IM入群申请列表
func (s *sSysImGroup) JoinRequestList(ctx context.Context, in *sysin.ImGroupJoinRequestListInp) (list []*sysin.ImGroupJoinRequestListModel, totalCount int, err error) {
if err = in.Filter(ctx); err != nil {
return
}
db, _, err := imtenant.DB(ctx, in.TenantId)
if err != nil {
return
}
mod := db.Model("im_group_join_requests").Safe().Ctx(ctx).Where("topic", in.Topic)
if in.Status != "" {
mod = mod.Where("status", in.Status)
}
if in.ApplicantUserId > 0 {
mod = mod.Where("applicant_user_id", in.ApplicantUserId)
}
mod = mod.Page(in.Page, in.PerPage).OrderDesc("id")
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取IM入群申请列表失败,请稍后重试!")
}
return
}
// InvitationList 获取IM群邀请列表
func (s *sSysImGroup) InvitationList(ctx context.Context, in *sysin.ImGroupInvitationListInp) (list []*sysin.ImGroupInvitationListModel, totalCount int, err error) {
if err = in.Filter(ctx); err != nil {
return
}
db, _, err := imtenant.DB(ctx, in.TenantId)
if err != nil {
return
}
mod := db.Model("im_group_invitations").Safe().Ctx(ctx).Where("topic", in.Topic)
if in.Status != "" {
mod = mod.Where("status", in.Status)
}
if in.TargetUserId > 0 {
mod = mod.Where("target_user_id", in.TargetUserId)
}
if in.InviterUserId > 0 {
mod = mod.Where("inviter_user_id", in.InviterUserId)
}
mod = mod.Page(in.Page, in.PerPage).OrderDesc("id")
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取IM群邀请列表失败,请稍后重试!")
}
return
}
// AnnouncementList 获取IM群公告列表
func (s *sSysImGroup) AnnouncementList(ctx context.Context, in *sysin.ImGroupAnnouncementListInp) (list []*sysin.ImGroupAnnouncementListModel, totalCount int, err error) {
if err = in.Filter(ctx); err != nil {
return
}
db, _, err := imtenant.DB(ctx, in.TenantId)
if err != nil {
return
}
mod := db.Model("im_group_announcements").Safe().Ctx(ctx).Where("topic", in.Topic)
if in.Status != "" {
mod = mod.Where("status", in.Status)
}
mod = mod.Page(in.Page, in.PerPage).OrderDesc("published_at").OrderDesc("id")
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取IM群公告列表失败,请稍后重试!")
}
return
}
// MuteList 获取IM群禁言列表
func (s *sSysImGroup) MuteList(ctx context.Context, in *sysin.ImGroupMuteListInp) (list []*sysin.ImGroupMuteListModel, totalCount int, err error) {
if err = in.Filter(ctx); err != nil {
return
}
db, _, err := imtenant.DB(ctx, in.TenantId)
if err != nil {
return
}
mod := db.Model("im_group_mutes").Safe().Ctx(ctx).Where("topic", in.Topic)
if in.Status != "" {
mod = mod.Where("status", in.Status)
}
if in.UserId > 0 {
mod = mod.Where("user_id", in.UserId)
}
mod = mod.Page(in.Page, in.PerPage).OrderDesc("muted_at").OrderDesc("user_id")
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取IM群禁言列表失败,请稍后重试!")
}
return
}
// AdminLogList 获取IM群管理日志列表
func (s *sSysImGroup) AdminLogList(ctx context.Context, in *sysin.ImGroupAdminLogListInp) (list []*sysin.ImGroupAdminLogListModel, totalCount int, err error) {
if err = in.Filter(ctx); err != nil {
return
}
db, _, err := imtenant.DB(ctx, in.TenantId)
if err != nil {
return
}
mod := db.Model("im_group_admin_logs").Safe().Ctx(ctx).
Fields(
"id",
"log_id",
"topic",
"operator_id",
"target_user_id",
"action",
"object_type",
"object_id",
"CAST(before_data AS CHAR) before_data",
"CAST(after_data AS CHAR) after_data",
"request_id",
"idempotency_key",
"created_at",
).
Where("topic", in.Topic)
if in.Action != "" {
mod = mod.WhereLike("action", "%"+in.Action+"%")
}
if in.OperatorId > 0 {
mod = mod.Where("operator_id", in.OperatorId)
}
mod = mod.Page(in.Page, in.PerPage).OrderDesc("id")
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取IM群管理日志列表失败,请稍后重试!")
}
return
}