diff --git a/convertions.go b/convertions.go index dcd6110..ec2e307 100644 --- a/convertions.go +++ b/convertions.go @@ -14,20 +14,28 @@ func ConvertStringUint32(s string) (uint32, error) { return uint32(v), err } -func ConvertStringToRgb(str string) ([3]uint8, error) { - parts := strings.SplitN(str, ",", 4) - if len(parts) != 3 { - return [3]uint8{}, fmt.Errorf("invalid rgb") +func ConvertStringToRgba(str string) (*Rgba, error) { + parts := strings.SplitN(str, ",", 5) + if len(parts) != 4 { + return nil, fmt.Errorf("invalid rgba") } - var rgb [3]uint8 + rgba := &Rgba{} for i, p := range parts { n, err := strconv.ParseUint(strings.TrimSpace(p), 10, 8) if err != nil { - return [3]uint8{}, fmt.Errorf("invalid component %d: %w", i, err) + return nil, fmt.Errorf("invalid component %d: %w", i, err) } - rgb[i] = uint8(n) + rgba[i] = uint8(n) } - return rgb, nil + return rgba, nil +} + +func RgbaToUint32(r *Rgba) uint32 { + return uint32(r[0])<<24 | uint32(r[1])<<16 | uint32(r[2])<<8 | uint32(r[3]) +} + +func Uint32ToRgba(v uint32) *Rgba { + return &Rgba{uint8(v >> 24), uint8(v >> 16), uint8(v >> 8), uint8(v)} } func ConvertStringUuid(str string) (uuid.UUID, error) { diff --git a/database.go b/database.go index 311aed5..8a72ffe 100644 --- a/database.go +++ b/database.go @@ -29,10 +29,8 @@ func DbInit(ctx context.Context) { name TEXT UNIQUE NOT NULL, pass_hash TEXT NOT NULL, pronouns TEXT DEFAULT NULL, - color_red SMALLINT DEFAULT NULL, - color_green SMALLINT DEFAULT NULL, - color_blue SMALLINT DEFAULT NULL, - created_at TIMESTAMP NOT NULL DEFAULT NOW() + rgba BIGINT NOT NULL DEFAULT 0 CHECK (rgba BETWEEN 0 AND 4294967295), + created_at TIMESTAMP NOT NULL DEFAULT NOW() ) `) if err != nil { @@ -69,10 +67,10 @@ func DbInit(ctx context.Context) { func DbUserSave(ctx context.Context, user *User) error { err := dbConn.QueryRow(ctx, ` - INSERT INTO users (name, pass_hash, pronouns, color_red, color_green, color_blue, created_at) - VALUES ($1, $2, $3, $4, $5, $6, $7) + INSERT INTO users (name, pass_hash, pronouns, rgba, created_at) + VALUES ($1, $2, $3, $4, $5) RETURNING id - `, user.Name, user.PasswordHash, user.Pronouns, user.Color[0], user.Color[1], user.Color[2], user.CreatedAt). + `, user.Name, user.PasswordHash, user.Pronouns, RgbaToUint32(user.Color), user.CreatedAt). Scan(&user.Id) return err } @@ -85,23 +83,31 @@ func DbUserDelete(ctx context.Context, id uuid.UUID) error { } func DbUserGetStandardInfoByName(ctx context.Context, user *User) error { + var rgba int64 err := dbConn.QueryRow(ctx, ` - SELECT id, name, pass_hash, COALESCE(pronouns, ''), color_red, color_green, color_blue, created_at FROM users WHERE name = $1 - `, user.Name).Scan(&user.Id, &user.Name, &user.PasswordHash, &user.Pronouns, &user.Color[0], &user.Color[1], &user.Color[2], &user.CreatedAt) + SELECT id, name, pass_hash, COALESCE(pronouns, ''), rgba, created_at FROM users WHERE name = $1 + `, user.Name).Scan(&user.Id, &user.Name, &user.PasswordHash, &user.Pronouns, &rgba, &user.CreatedAt) + if err == nil { + user.Color = Uint32ToRgba(uint32(rgba)) + } return err } func DbUserGetById(ctx context.Context, user *User) error { + var rgba int64 err := dbConn.QueryRow(ctx, ` - SELECT name, pass_hash, COALESCE(pronouns, ''), color_red, color_green, color_blue, created_at FROM users WHERE id = $1 - `, user.Id).Scan(&user.Name, &user.PasswordHash, &user.Pronouns, &user.Color[0], &user.Color[1], &user.Color[2], &user.CreatedAt) + SELECT name, pass_hash, COALESCE(pronouns, ''), rgba, created_at FROM users WHERE id = $1 + `, user.Id).Scan(&user.Name, &user.PasswordHash, &user.Pronouns, &rgba, &user.CreatedAt) + if err == nil { + user.Color = Uint32ToRgba(uint32(rgba)) + } return err } func DbUserSetColor(ctx context.Context, user *User) error { _, err := dbConn.Exec(ctx, ` - UPDATE users SET color_red = $1, color_green = $2, color_blue = $3 WHERE id = $4 - `, user.Color[0], user.Color[1], user.Color[2], user.Id) + UPDATE users SET rgba = $1 WHERE id = $2 + `, RgbaToUint32(user.Color), user.Id) return err } @@ -211,4 +217,3 @@ func DbConnectionGetMessagesBefore(ctx context.Context, before time.Time, connec } return messages, rows.Err() } - diff --git a/globals.go b/globals.go index 2c1f07e..5c839a2 100644 --- a/globals.go +++ b/globals.go @@ -1,6 +1,5 @@ package main const ( - MaxDirectMsgCache uint32 = 12 - MessagesPartitions uint8 = 2 + MaxDirectMsgCache uint32 = 12 ) diff --git a/httpUser.go b/httpUser.go index 2f059e5..ef3b05a 100644 --- a/httpUser.go +++ b/httpUser.go @@ -84,12 +84,6 @@ func HttpHandleUserNew(response http.ResponseWriter, request *http.Request) { return } - color, err := ConvertStringToRgb(request.FormValue("color")) - if err != nil { - http.Error(response, "bad color", http.StatusBadRequest) - return - } - hashedPassword, err := PasswordHash(password) if err != nil { http.Error(response, "internal server error", http.StatusInternalServerError) @@ -99,7 +93,7 @@ func HttpHandleUserNew(response http.ResponseWriter, request *http.Request) { newUser := &User{ Name: username, PasswordHash: hashedPassword, - Color: color, + Color: Rgba{}.GetRandom(), CreatedAt: time.Now(), } @@ -149,7 +143,7 @@ func HttpHandleUserModifyAppearance(response http.ResponseWriter, request *http. return } - color, err := ConvertStringToRgb(request.FormValue("color")) + color, err := ConvertStringToRgba(request.FormValue("color")) if err != nil { http.Error(response, "invalid color", http.StatusBadRequest) return diff --git a/todo.txt b/todo.txt index 4299382..b87a046 100644 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,6 @@ -add hubs - -media support - fix color saving to use INT (002255255035) rgba +media support +more user customization (avatar, banners, desc) -more user customization (avatar, banners, desc) \ No newline at end of file + +add hubs \ No newline at end of file diff --git a/structs.go b/type.go similarity index 94% rename from structs.go rename to type.go index cdfc5dc..e7b8c99 100644 --- a/structs.go +++ b/type.go @@ -1,6 +1,7 @@ package main import ( + "math/rand/v2" "sync" "time" @@ -11,6 +12,15 @@ import ( "github.com/google/uuid" ) +type Rgba [4]uint8 + +func (r Rgba) GetRandom() *Rgba { + for i := range r { + r[i] = uint8(rand.IntN(256)) + } + return &r +} + type User struct { Mu sync.RWMutex Name string @@ -20,7 +30,7 @@ type User struct { WsConn *websocket.Conn Id uuid.UUID Connections map[uuid.UUID]*Connection - Color [3]uint8 + Color *Rgba } type Connection struct {