spark-server/internal/module/group/logic/member_update.go
2026-09-18 14:50:41 +08:00

90 lines
2.7 KiB
Go

package logic
import (
"context"
"strings"
"spark-server/internal/module/group/entity"
"spark-server/internal/pkg/errs"
"spark-server/internal/pkg/i18n"
"spark-server/internal/pkg/reqctx"
"spark-server/internal/pkg/validate"
)
type UpdateMemberInput struct {
Role *entity.Role `json:"role" validate:"omitempty,oneof=2 3" label:"field.role" errmsg:"oneof:validate.group.role_invalid"`
SpeakMuted *bool `json:"speak_muted"`
Nickname *string `json:"nickname" validate:"omitempty,max=32" label:"field.group_nickname" errmsg:"max:validate.group.nickname_invalid"`
Remark *string `json:"remark" validate:"omitempty,max=32" label:"field.group_remark" errmsg:"max:validate.group.remark_invalid"`
}
func (s *Service) UpdateMember(ctx context.Context, actorID, groupID, targetID int64, in *UpdateMemberInput) (*MemberView, error) {
if !s.ready() || actorID <= 0 {
return nil, errs.ErrUnauthorized
}
if in == nil || targetID <= 0 {
return nil, errs.ErrInvalidArgument
}
if err := validate.StructLang(reqctx.Lang(ctx), in); err != nil {
return nil, err
}
if in.Role == nil && in.SpeakMuted == nil && in.Nickname == nil && in.Remark == nil {
return nil, errs.ErrInvalidArgument
}
g, err := s.loadActive(ctx, groupID)
if err != nil {
return nil, err
}
target, err := s.requireMember(ctx, groupID, targetID)
if err != nil {
return nil, err
}
if err := s.applyMemberPatch(ctx, g, actorID, target, in); err != nil {
return nil, err
}
if err := s.repo.UpdateMember(ctx, target); err != nil {
return nil, err
}
u, _ := s.users.Get(ctx, target.UserID)
return memberViewOf(target, u), nil
}
func (s *Service) applyMemberPatch(ctx context.Context, g *entity.Group, actorID int64, target *entity.Member, in *UpdateMemberInput) error {
lang := reqctx.Lang(ctx)
self := actorID == target.UserID
if in.Remark != nil {
if !self {
return errs.ErrForbidden.WithMsg(i18n.T(lang, i18n.KeyGroupRoleDenied, nil))
}
target.Remark = strings.TrimSpace(*in.Remark)
}
if in.Nickname != nil {
if !self {
if _, err := s.requireManage(ctx, g.ID, actorID); err != nil {
return err
}
}
target.Nickname = strings.TrimSpace(*in.Nickname)
}
if in.Role != nil {
if err := s.requireOwner(ctx, g, actorID); err != nil {
return err
}
if self || (*in.Role != entity.RoleAdmin && *in.Role != entity.RoleMember) {
return errs.ErrForbidden.WithMsg(i18n.T(lang, i18n.KeyGroupRoleDenied, nil))
}
target.Role = *in.Role
}
if in.SpeakMuted != nil {
actor, err := s.requireManage(ctx, g.ID, actorID)
if err != nil {
return err
}
if !actor.CanModerate(target) {
return errs.ErrForbidden.WithMsg(i18n.T(lang, i18n.KeyGroupRoleDenied, nil))
}
target.SpeakMuted = *in.SpeakMuted
}
return nil
}