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"` Avatar string `json:"avatar"` ProfileBg string `json:"profileBackground"` 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 NewConnection() *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 RolePermission uint32 const ( // Hub permissions PermissionSetHubName RolePermission = iota PermissionSetHubBg PermissionSetHubColor PermissionRemoveHub PermissionSetUserColorAllowed // User permissions PermissionAddUser PermissionRemoveUser PermissionRenameUser PermissionMuteUser // Role permissions PermissionAddRole PermissionRemoveRole PermissionChangeRoleName PermissionChangeRoleColor PermissionChangeRolePermissions PermissionOnlySelfRoleRemove // Channel group permissions PermissionAddChannelGroup PermissionRemoveChannelGroup PermissionSetChannelGroupName PermissionSetChannelGroupColor PermissionSetChannelGroupPermittedVisibleRoles // Channel permissions PermissionAddChannel PermissionRemoveChannel PermissionSetChannelName PermissionSetChannelPermittedVisibleRoles PermissionSetChannelPermittedSendMessageRoles PermissionSetChannelPermittedReadHistoryRoles ) type Hub struct { Mu sync.RWMutex `json:"-"` Id uuid.UUID `json:"id"` CreatedAt time.Time `json:"createdAt"` MessagesBuff []*Message `json:"-"` NextBuffIdx uint32 `json:"-"` HaveOverflowed bool `json:"-"` Users map[uuid.UUID]*HubUser `json:"-"` Roles map[uint8]*HubRole `json:"-"` Creator uuid.UUID `json:"creator"` Name string `json:"name"` Color Rgba `json:"color"` AllowUserColor bool `json:"allowUserColor"` } func NewHub() *Hub { return &Hub{ MessagesBuff: make([]*Message, config.MaxHubMsgCache), Users: make(map[uuid.UUID]*HubUser), Roles: make(map[uint8]*HubRole), } } type HubChannelGroup struct { Id uuid.UUID `json:"id"` Name string `json:"name"` Color Rgba `json:"color"` } type HubChannel struct { Id uuid.UUID `json:"id"` Name uuid.UUID `json:"name"` ParentGroupId uuid.UUID `json:"parentGroupId"` } type HubUser struct { Id uuid.UUID `json:"id"` Username string `json:"username"` Roles []uint8 `json:"roles"` CreatedAt time.Time `json:"createdAt"` } type HubRole struct { Name string `json:"role"` Id uint8 `json:"id"` RolePermission RolePermission `json:"rolePermission"` Color Rgba `json:"color"` } func (h HubRole) GrantPermission(r RolePermission) { h.RolePermission |= r } func (h HubRole) GrantPermissions(rs []RolePermission) { for _, r := range rs { h.RolePermission |= r } } func (h HubRole) RevokePermission(r RolePermission) { h.RolePermission &^= r } func (h HubRole) RevokePermissions(rs []RolePermission) { for _, r := range rs { h.RolePermission &^= r } } func (h HubRole) HasPermission(r RolePermission) bool { return h.RolePermission&r != 0 }