package types import ( "crypto/sha256" "math/rand/v2" "sync" "time" "go-socket/packages/Enums/ConnectionState" "go-socket/packages/Enums/WsEventType" "go-socket/packages/config" "github.com/coder/websocket" "github.com/google/uuid" ) type Rgba [4]uint8 type Sha256Hash [sha256.Size]byte func (r Rgba) GetRandom() Rgba { for i := range r { r[i] = uint8(rand.IntN(256)) } return r } type User struct { Mu sync.RWMutex `json:"-"` Name string `json:"name"` Pronouns string `json:"pronouns"` Description string `json:"description"` AvatarUrl string `json:"avatarUrl"` ProfileBgUrl string `json:"profileBackgroundUrl"` PasswordHash string `json:"-"` CreatedAt time.Time `json:"createdAt"` WsConn *websocket.Conn `json:"-"` Id uuid.UUID `json:"-"` Connections map[uuid.UUID]*Connection `json:"-"` Color Rgba `json:"color"` } type UserProfileUpdateList struct { Pronouns bool Description bool Color bool Avatar bool ProfileBg bool } type Connection struct { Mu sync.RWMutex `json:"-"` Id uuid.UUID `json:"id"` CreatedAt time.Time `json:"createdAt"` MessagesBuff []*Message `json:"-"` NextBuffIdx uint32 `json:"-"` RequestorId uuid.UUID `json:"requestorId"` RecipientId uuid.UUID `json:"recipientId"` UserWantingToElevate uuid.UUID `json:"userWantingToElevate"` // TODO add to database HaveOverflowed bool `json:"-"` State ConnectionState.ConnectionState `json:"state"` } func NewConn() *Connection { return &Connection{ MessagesBuff: make([]*Message, config.MaxDirectMsgCache), } } func (conn *Connection) AddMessageToBuff(message *Message) { conn.Mu.Lock() defer conn.Mu.Unlock() size := uint32(len(conn.MessagesBuff)) conn.MessagesBuff[conn.NextBuffIdx%size] = message conn.NextBuffIdx++ if conn.NextBuffIdx >= size { conn.HaveOverflowed = true } } // GetSortedMessagesBuff returns slice and its valid length. func (conn *Connection) GetSortedMessagesBuff() ([]*Message, uint32) { conn.Mu.RLock() defer conn.Mu.RUnlock() size := uint32(len(conn.MessagesBuff)) if !conn.HaveOverflowed { return conn.MessagesBuff, conn.NextBuffIdx } sorted := make([]*Message, size) for i := uint32(0); i < size; i++ { sorted[i] = conn.MessagesBuff[(conn.NextBuffIdx+i)%size] } return sorted, size } type ConnectionStatusSetData struct { Id uuid.UUID `json:"id"` NewState ConnectionState.ConnectionState `json:"newState"` } type Message struct { Id uuid.UUID `json:"id"` AttachedFile string `json:"attachedFile"` Content string `json:"content"` CreatedAt time.Time `json:"createdAt"` Sender uuid.UUID `json:"sender"` Receiver uuid.UUID `json:"receiver"` } type LoginReturn struct { Token string `json:"token"` UserId uuid.UUID `json:"userId"` } type WsEventMessage struct { Type WsEventType.WsEventType `json:"type"` Event any `json:"event"` } type WsAuthMessage struct { Success bool `json:"success"` Error string `json:"error"` } type Permissions uint32 const ( // Hub permissions PermissionSetHubName Permissions = 1 << iota PermissionSetHubIcon PermissionSetHubBg PermissionSetHubColor PermissionRemoveHub PermissionSetUserColorAllowed // User permissions PermissionAddUser PermissionRemoveUser PermissionRenameUser PermissionMuteUser // Role permissions PermissionAddRole PermissionRemoveRole PermissionChangeRoleName PermissionChangeRoleColor PermissionChangeRoleGlobals PermissionOnlySelfRoleRemove // Channel group permissions PermissionAddChannelGroup PermissionRemoveChannelGroup PermissionSetChannelGroupName PermissionSetChannelGroupColor PermissionSetChannelGroupPermittedVisibleRoles // Channel permissions PermissionAddChannel PermissionRemoveChannel PermissionSetChannelName PermissionSetChannelIcon PermissionSetChannelPermittedVisibleRoles PermissionSetChannelPermittedSendMessageRoles PermissionSetChannelPermittedReadHistoryRoles ) type Hub struct { Mu sync.RWMutex `json:"-"` Roles []*HubRole `json:"-"` Users []*HubUser `json:"-"` Groups []*HubGroup `json:"-"` Channels []*HubChannel `json:"-"` Name string `json:"name"` IconUrl string `json:"iconUrl"` BgUrl string `json:"bgUrl"` Id uuid.UUID `json:"id"` Color Rgba `json:"color"` UserColorAllowed bool `json:"userColorAllowed"` } func NewHub() *Hub { return &Hub{ Roles: make([]*HubRole, 0, 255), Users: make([]*HubUser, 0, 255), Groups: make([]*HubGroup, 0, 255), Channels: make([]*HubChannel, 0, 255), } } type HubRole struct { Name string `json:"role"` CreatedAt time.Time `json:"createdAt"` Permissions Permissions `json:"permissions"` Color Rgba `json:"color"` Id uint8 `json:"id"` BoundedGroup uint8 `json:"boundedGroup"` // BoundedGroup 0 for global } func (h *HubRole) GrantPermission(r Permissions) { h.Permissions |= r } func (h *HubRole) RevokePermission(r Permissions) { h.Permissions &^= r } func (h *HubRole) HasPermission(r Permissions) bool { return h.Permissions&r != 0 } type HubGroup struct { Name string `json:"name"` CreatedAt time.Time `json:"createdAt"` Color Rgba `json:"color"` Id uint8 `json:"id"` // Id 0 for unused } type HubUser struct { Mu sync.RWMutex `json:"mu"` Roles []*HubRole `json:"roles"` Name string `json:"name"` OriginalId uuid.UUID `json:"originalId"` IsMuted bool `json:"isMuted"` } func NewHubUser() *HubUser { return &HubUser{ Roles: make([]*HubRole, 0, config.MaxUserHubRoles), } } type HubChannel struct { Mu sync.RWMutex `json:"-"` MessagesBuff []*Message `json:"-"` Name string `json:"name"` Description string `json:"description"` IconUrl string `json:"iconUrl"` CreatedAt time.Time `json:"createdAt"` NextBuffIdx uint32 `json:"-"` Id uint8 `json:"id"` HaveOverflowed bool `json:"-"` } func NewHubChannel() *HubChannel { return &HubChannel{ MessagesBuff: make([]*Message, config.MaxHubChannelMsgCache), } } func (conn *HubChannel) AddMessageToBuff(message *Message) { conn.Mu.Lock() defer conn.Mu.Unlock() size := uint32(len(conn.MessagesBuff)) conn.MessagesBuff[conn.NextBuffIdx%size] = message conn.NextBuffIdx++ if conn.NextBuffIdx >= size { conn.HaveOverflowed = true } } // GetSortedMessagesBuff returns slice and its valid length. func (conn *HubChannel) GetSortedMessagesBuff() ([]*Message, uint32) { conn.Mu.RLock() defer conn.Mu.RUnlock() size := uint32(len(conn.MessagesBuff)) if !conn.HaveOverflowed { return conn.MessagesBuff, conn.NextBuffIdx } sorted := make([]*Message, size) for i := uint32(0); i < size; i++ { sorted[i] = conn.MessagesBuff[(conn.NextBuffIdx+i)%size] } return sorted, size }