package entity const ( RoleOwner Role = 1 RoleAdmin Role = 2 RoleMember Role = 3 ) // Role is persisted as group_members.role. type Role int func (r Role) Valid() bool { return r == RoleOwner || r == RoleAdmin || r == RoleMember } // Member is a row in group_members. SpeakMuted is send-ban, not 免打扰. type Member struct { GroupID int64 UserID int64 Role Role Nickname string Remark string SpeakMuted bool JoinedAtMS int64 } func ValidRole(role int) bool { return Role(role).Valid() } func (m *Member) CanManage() bool { return m != nil && (m.Role == RoleOwner || m.Role == RoleAdmin) } // CanModerate is kick / mute: owner may act on admin and member; admin may act on member only. func (m *Member) CanModerate(target *Member) bool { if m == nil || target == nil || !m.CanManage() { return false } if target.Role == RoleOwner { return false } if target.Role == RoleAdmin && m.Role != RoleOwner { return false } return true } func (m *Member) CanSpeak(mutedAll bool) bool { if m == nil || m.SpeakMuted { return false } if mutedAll && m.Role == RoleMember { return false } return true } func UniqueUIDs(ids []int64) []int64 { seen := make(map[int64]struct{}, len(ids)) out := make([]int64, 0, len(ids)) for _, id := range ids { if id <= 0 { continue } if _, ok := seen[id]; ok { continue } seen[id] = struct{}{} out = append(out, id) } return out }