Add HTTP /v1 MVC, TCP send path, groups with server-side member-avatar collage, object-storage upload, and friends/favorites around the architecture-v3 layout. Co-authored-by: Cursor <cursoragent@cursor.com>
60 lines
1.7 KiB
Go
60 lines
1.7 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
|
|
"spark-server/internal/module/group/entity"
|
|
"spark-server/internal/pkg/errs"
|
|
"spark-server/internal/pkg/i18n"
|
|
"spark-server/internal/pkg/reqctx"
|
|
)
|
|
|
|
func (s *Service) RemoveMember(ctx context.Context, actorID, groupID, targetID int64) error {
|
|
if !s.ready() || actorID <= 0 {
|
|
return errs.ErrUnauthorized
|
|
}
|
|
if targetID <= 0 {
|
|
return errs.ErrInvalidArgument
|
|
}
|
|
g, err := s.loadActive(ctx, groupID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
target, err := s.repo.GetMember(ctx, groupID, targetID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if actorID == targetID {
|
|
return s.leave(ctx, g, target)
|
|
}
|
|
return s.kick(ctx, g, actorID, target)
|
|
}
|
|
|
|
func (s *Service) leave(ctx context.Context, g *entity.Group, self *entity.Member) error {
|
|
if self.Role == entity.RoleOwner {
|
|
return errs.ErrForbidden.WithMsg(i18n.T(reqctx.Lang(ctx), i18n.KeyGroupOwnerLeave, nil))
|
|
}
|
|
if err := s.repo.RemoveMember(ctx, g.ID, self.UserID); err != nil {
|
|
return err
|
|
}
|
|
s.invalidateMembers(g.ConversationID)
|
|
_ = s.notice(ctx, g, self.UserID, entity.SystemKindLeave, []int64{self.UserID})
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) kick(ctx context.Context, g *entity.Group, actorID int64, target *entity.Member) error {
|
|
actor, err := s.requireManage(ctx, g.ID, actorID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if target.Role == entity.RoleOwner || (target.Role == entity.RoleAdmin && actor.Role != entity.RoleOwner) {
|
|
return errs.ErrForbidden.WithMsg(i18n.T(reqctx.Lang(ctx), i18n.KeyGroupRoleDenied, nil))
|
|
}
|
|
if err := s.repo.RemoveMember(ctx, g.ID, target.UserID); err != nil {
|
|
return err
|
|
}
|
|
s.invalidateMembers(g.ConversationID)
|
|
_ = s.notice(ctx, g, actorID, entity.SystemKindKick, []int64{target.UserID})
|
|
return nil
|
|
}
|