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>
74 lines
1.7 KiB
Go
74 lines
1.7 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
|
|
"spark-server/internal/pkg/errs"
|
|
)
|
|
|
|
func (s *Service) ListMembers(ctx context.Context, userID, groupID int64, limit int) (*MemberList, error) {
|
|
if !s.ready() || userID <= 0 {
|
|
return nil, errs.ErrUnauthorized
|
|
}
|
|
if _, err := s.loadActive(ctx, groupID); err != nil {
|
|
return nil, err
|
|
}
|
|
if _, err := s.requireMember(ctx, groupID, userID); err != nil {
|
|
return nil, err
|
|
}
|
|
rows, err := s.repo.ListMembers(ctx, groupID, limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
items := make([]*MemberView, 0, len(rows))
|
|
for _, mem := range rows {
|
|
u, err := s.users.Get(ctx, mem.UserID)
|
|
if err != nil {
|
|
items = append(items, memberViewOf(mem, nil))
|
|
continue
|
|
}
|
|
items = append(items, memberViewOf(mem, u))
|
|
}
|
|
return &MemberList{Items: items}, nil
|
|
}
|
|
|
|
func (s *Service) MemberIDs(ctx context.Context, conversationID int64) ([]int64, error) {
|
|
if !s.ready() || conversationID <= 0 {
|
|
return nil, errs.ErrInvalidArgument
|
|
}
|
|
if ids, ok := s.cachedMemberIDs(conversationID); ok {
|
|
return ids, nil
|
|
}
|
|
g, err := s.repo.GetByConversation(ctx, conversationID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !g.Active() {
|
|
return []int64{}, nil
|
|
}
|
|
ids, err := s.repo.ListMemberIDs(ctx, g.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s.putMemberIDs(conversationID, ids)
|
|
return ids, nil
|
|
}
|
|
|
|
func (s *Service) CanSend(ctx context.Context, userID, conversationID int64) error {
|
|
if !s.ready() || userID <= 0 || conversationID <= 0 {
|
|
return errs.ErrForbidden
|
|
}
|
|
g, err := s.repo.GetByConversation(ctx, conversationID)
|
|
if err != nil || !g.Active() {
|
|
return errs.ErrForbidden
|
|
}
|
|
mem, err := s.repo.GetMember(ctx, g.ID, userID)
|
|
if err != nil {
|
|
return errs.ErrForbidden
|
|
}
|
|
if !mem.CanSpeak(g.MutedAll) {
|
|
return errs.ErrForbidden
|
|
}
|
|
return nil
|
|
}
|