package model import ( "context" "time" "spark-server/internal/module/group/entity" "spark-server/internal/pkg/errs" ) func (m *MemoryRepo) CreateGroup(_ context.Context, g *entity.Group, members []*entity.Member) error { if g == nil || g.ConversationID <= 0 || len(members) == 0 { return errs.ErrInvalidArgument } m.mu.Lock() defer m.mu.Unlock() if _, ok := m.byConv[g.ConversationID]; ok { return errs.ErrDuplicate } m.nextID++ cp := *g cp.ID = m.nextID cp.MemberCount = len(members) if cp.Status == 0 { cp.Status = entity.StatusActive } if cp.CreatedAtMS <= 0 { cp.CreatedAtMS = time.Now().UnixMilli() } if cp.UpdatedAtMS <= 0 { cp.UpdatedAtMS = cp.CreatedAtMS } m.groups[cp.ID] = &cp m.byConv[cp.ConversationID] = cp.ID g.ID = cp.ID byUser := make(map[int64]*entity.Member, len(members)) for _, mem := range members { if mem == nil || mem.UserID <= 0 { continue } row := *mem row.GroupID = cp.ID if row.JoinedAtMS <= 0 { row.JoinedAtMS = cp.CreatedAtMS } if row.Role == 0 { row.Role = entity.RoleMember } byUser[row.UserID] = &row } m.members[cp.ID] = byUser return nil } func (m *MemoryRepo) AddMembers(_ context.Context, groupID int64, members []*entity.Member) error { if groupID <= 0 || len(members) == 0 { return errs.ErrInvalidArgument } m.mu.Lock() defer m.mu.Unlock() g, ok := m.groups[groupID] if !ok || g.Status != entity.StatusActive { return errs.ErrNotFound } byUser := m.members[groupID] if byUser == nil { byUser = make(map[int64]*entity.Member) m.members[groupID] = byUser } now := time.Now().UnixMilli() for _, mem := range members { if mem == nil || mem.UserID <= 0 { continue } if _, ok := byUser[mem.UserID]; ok { return errs.ErrDuplicate } row := *mem row.GroupID = groupID if row.JoinedAtMS <= 0 { row.JoinedAtMS = now } if row.Role == 0 { row.Role = entity.RoleMember } byUser[row.UserID] = &row } g.MemberCount = len(byUser) g.UpdatedAtMS = now return nil } func (m *MemoryRepo) RemoveMember(_ context.Context, groupID, userID int64) error { m.mu.Lock() defer m.mu.Unlock() g, ok := m.groups[groupID] if !ok || g.Status != entity.StatusActive { return errs.ErrNotFound } byUser := m.members[groupID] if byUser == nil { return errs.ErrNotFound } if _, ok := byUser[userID]; !ok { return errs.ErrNotFound } delete(byUser, userID) g.MemberCount = len(byUser) g.UpdatedAtMS = time.Now().UnixMilli() return nil } func (m *MemoryRepo) Dissolve(_ context.Context, groupID int64) error { m.mu.Lock() defer m.mu.Unlock() g, ok := m.groups[groupID] if !ok || g.Status != entity.StatusActive { return errs.ErrNotFound } g.Status = entity.StatusDissolved g.MemberCount = 0 g.UpdatedAtMS = time.Now().UnixMilli() delete(m.members, groupID) return nil } func (m *MemoryRepo) TransferOwner(_ context.Context, groupID, fromID, toID int64) error { m.mu.Lock() defer m.mu.Unlock() g, ok := m.groups[groupID] if !ok || g.Status != entity.StatusActive || g.OwnerID != fromID { return errs.ErrNotFound } byUser := m.members[groupID] from, ok := byUser[fromID] if !ok { return errs.ErrNotFound } to, ok := byUser[toID] if !ok { return errs.ErrNotFound } from.Role = entity.RoleMember to.Role = entity.RoleOwner to.SpeakMuted = false g.OwnerID = toID g.UpdatedAtMS = time.Now().UnixMilli() return nil }