diff --git a/database.go b/database.go index 69df436..8563c87 100644 --- a/database.go +++ b/database.go @@ -2,8 +2,10 @@ package main import ( "context" + "fmt" "time" + "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) @@ -17,6 +19,8 @@ func DbInit(ctx context.Context) { panic(err) } + _, err = dbConn.Exec(ctx, `CREATE EXTENSION IF NOT EXISTS "gen_random_uuid";`) + _, err = dbConn.Exec(ctx, ` CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, @@ -35,11 +39,11 @@ func DbInit(ctx context.Context) { _, err = dbConn.Exec(ctx, ` CREATE TABLE IF NOT EXISTS user_connections ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), requestor_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, recipient_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, state TINYINT NOT NULL DEFAULT 0 created_at TIMESTAMP NOT NULL DEFAULT NOW(), - PRIMARY KEY (requestor_id, recipient_id) ) `) if err != nil { @@ -48,12 +52,16 @@ func DbInit(ctx context.Context) { _, err = dbConn.Exec(ctx, ` CREATE TABLE IF NOT EXISTS messages ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), sender_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, receiver_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, content TEXT NOT NULL, is_group_message BOOLEAN DEFAULT FALSE ) `) + if err != nil { + panic(err) + } _, err = dbConn.Exec(ctx, ` CREATE TABLE IF NOT EXISTS chat_groups ( @@ -158,25 +166,37 @@ func DbGroupSetColor(ctx context.Context, group *Group) error { return err } -func DbConnectionSave(ctx context.Context, creationDate time.Time, requestorId uint32, recipientId uint32, isAccepted bool) error { - _, err := dbConn.Exec(ctx, ` - INSERT INTO user_connections (created_at, requestor_id, recipient_id, is_accepted) VALUES ($1, $2, $3, $4) - `, creationDate, requestorId, recipientId, isAccepted) - return err +func DbConnectionSave(ctx context.Context, conn *Connection) error { + return dbConn.QueryRow(ctx, ` + INSERT INTO user_connections (requestor_id, recipient_id, state, created_at) VALUES ($1, $2, $3, $4) + RETURNING id + `, conn.RequestorId, conn.RecipientId, conn.State, conn.CreatedAt).Scan(&conn.Id) } -func DbConnectionAccept(ctx context.Context, requestorId uint32, recipientId uint32) error { - _, err := dbConn.Exec(ctx, ` - UPDATE user_connections SET is_accepted = true WHERE requestor_id = $1 AND recipient_id = $2 - `, requestorId, recipientId) - return err -} +func DbConnectionGetBelongingToUser(ctx context.Context, user *User) error { + rows, err := dbConn.Query(ctx, ` + SELECT id, requestor_id, recipient_id, state, created_at + FROM connections + WHERE requestor_id = $1 OR recipient_id = $1 + `, user.Id) + if err != nil { + return err + } + defer rows.Close() -func DbConnectionDelete(ctx context.Context, requestorId uint32, recipientId uint32) error { - _, err := dbConn.Exec(ctx, ` - DELETE FROM user_connections WHERE requestor_id = $1 AND recipient_id = $2 - `, requestorId, recipientId) - return err + if user.Connections == nil { + user.Connections = make(map[uuid.UUID]*Connection) + } + + for rows.Next() { + conn := &Connection{} + if err = rows.Scan(&conn.Id, &conn.RequestorId, &conn.RecipientId, &conn.State, &conn.CreatedAt); err != nil { + return fmt.Errorf("scanning connection row: %w", err) + } + user.Connections[conn.Id] = conn + } + + return rows.Err() } func DbGroupSave(ctx context.Context, group *Group) error { diff --git a/go.mod b/go.mod index e6bf2fb..394e0a1 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( ) require ( + github.com/google/uuid v1.6.0 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect golang.org/x/sync v0.20.0 // indirect ) diff --git a/structs.go b/structs.go index e8fac2f..a4722b8 100644 --- a/structs.go +++ b/structs.go @@ -4,6 +4,7 @@ import ( "time" "github.com/coder/websocket" + "github.com/google/uuid" ) type User struct { @@ -14,23 +15,25 @@ type User struct { WsConn *websocket.Conn Id uint32 Groups map[uint32]struct{} - Connections map[uint32]*Connection + Connections map[uuid.UUID]*Connection Color [3]uint8 } type Connection struct { + Id uuid.UUID `json:"id"` CreatedAt time.Time `json:"createdAt"` MessagesBuf [MaxDirectMsgCache]*Message `json:"-"` - Id uint32 `json:"id"` RequestorId uint32 `json:"requestorId"` RecipientId uint32 `json:"recipientId"` State uint8 `json:"state"` } type Message struct { - Content string `json:"content"` - CreatedAt time.Time `json:"createdAt"` - Sender uint32 `json:"sender"` + Id uuid.UUID `json:"id"` + Content string `json:"content"` + CreatedAt time.Time `json:"createdAt"` + Sender uint32 `json:"sender"` + IsGroupMessage bool `json:"isGroupMessage"` } type Group struct { diff --git a/todo.txt b/todo.txt index 106cc19..514b281 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,6 @@ chat history +rewrite to use uuid media support fix color saving to use INT (002255255035) rgba