From 68873dc44caee1de9ad2f2607bd14a966ee157ab Mon Sep 17 00:00:00 2001 From: slawk0 Date: Fri, 7 Feb 2025 23:29:03 +0100 Subject: [PATCH] added proper types to structs, return empty arrays instead of null --- database/contacts.go | 43 +++++++++++++++++++++---------------------- database/messages.go | 14 +++++++------- model/model.go | 31 +++++++++++++++++-------------- router/router.go | 2 +- 4 files changed, 46 insertions(+), 44 deletions(-) diff --git a/database/contacts.go b/database/contacts.go index cecc899..c70e1b4 100644 --- a/database/contacts.go +++ b/database/contacts.go @@ -94,7 +94,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse `, userID).Scan(&conversationID) if err != nil && !errors.Is(err, sql.ErrNoRows) { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to check existing conversation: %w", err)) + return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to check existing conversation: %w", err)) } if conversationID == uuid.Nil { @@ -104,7 +104,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse RETURNING conversation_id; `).Scan(&conversationID) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create conversation: %w", err)) + return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create conversation: %w", err)) } _, err = db.Exec(` @@ -113,7 +113,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse ON CONFLICT (conversation_id, user_id) DO NOTHING; `, conversationID, userID) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create membership: %w", err)) + return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create membership: %w", err)) } } } else { @@ -128,7 +128,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse `, userID, contactID).Scan(&conversationID) if err != nil && !errors.Is(err, sql.ErrNoRows) { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to check existing conversation %w", err)) + return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to check existing conversation %w", err)) } if conversationID == uuid.Nil { @@ -138,7 +138,7 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse RETURNING conversation_id; `).Scan(&conversationID) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create conversation: %w", err)) + return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create conversation: %w", err)) } _, err = db.Exec(` @@ -147,19 +147,19 @@ func InsertContact(db *sql.DB, userID uuid.UUID, contactID uuid.UUID, contactUse ON CONFLICT (conversation_id, user_id) DO NOTHING; `, conversationID, userID, contactID) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create memberships: %w", err)) + return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to create memberships: %w", err)) } } } insertedContact, err := InsertContactByID(db, contactID, conversationID) if err != nil { - return nil, err + return &model.Contact{}, err } latestMessage, err := GetLatestMessage(db, conversationID) if err != nil { - return nil, err + return &model.Contact{}, err } contact := model.Contact{ @@ -186,9 +186,9 @@ func InsertContactByID(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) ( `, userID, conversationID).Scan(&contact.ID, &contact.ConversationID, &contact.UserID) if err == nil { - return nil, helpers.NewError(helpers.ErrInvalidInput, "Contact already exists", nil) + return &model.Contact{}, helpers.NewError(helpers.ErrInvalidInput, "Contact already exists", nil) } else if !errors.Is(err, sql.ErrNoRows) { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to check contact existence: %w", err)) + return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to check contact existence: %w", err)) } // Insert new contact @@ -199,7 +199,7 @@ func InsertContactByID(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID) ( `, userID, conversationID).Scan(&contact.ID, &contact.ConversationID, &contact.UserID) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "Failed to create contact", err) + return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "Failed to create contact", err) } return &contact, nil @@ -228,9 +228,9 @@ func GetLatestMessage(db *sql.DB, conversationId uuid.UUID) (*model.Contact, err if err != nil { if errors.Is(err, sql.ErrNoRows) { - return &model.Contact{}, nil // Return empty contact if no messages + return &model.Contact{}, nil } - return nil, helpers.NewError(helpers.ErrInternal, "Failed to get latest message", err) + return &model.Contact{}, helpers.NewError(helpers.ErrInternal, "Failed to get latest message", fmt.Errorf("failed to get latest message: %w", err)) } return &latestMessage, nil @@ -287,21 +287,20 @@ func GetContacts(db *sql.DB, userID uuid.UUID) ([]*model.Contact, error) { rows, err := db.Query(contactsQuery, userID) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "Failed to get contacts", err) + return []*model.Contact{}, helpers.NewError(helpers.ErrInternal, "Failed to get contacts", fmt.Errorf("failed to get contacts: %w", err)) } var contacts []*model.Contact for rows.Next() { contact := &model.Contact{} - err := rows.Scan(&contact.ID, &contact.UserID, &contact.Username, - &contact.ConversationID, &contact.Type) + err := rows.Scan(&contact.ID, &contact.UserID, &contact.Username, &contact.LastActive, &contact.ConversationID, &contact.Type, &contact.LastReadMessageID) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", err) + return []*model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to scan contact: %w", err)) } latestMessage, err := GetLatestMessage(db, contact.ConversationID) if err != nil { - return nil, err + return []*model.Contact{}, err } contact.LastMessageID = latestMessage.LastMessageID @@ -313,7 +312,7 @@ func GetContacts(db *sql.DB, userID uuid.UUID) ([]*model.Contact, error) { } if err = rows.Err(); err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process contacts: %w", err)) + return []*model.Contact{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process contacts: %w", err)) } return contacts, nil @@ -329,7 +328,7 @@ func ContactSuggestion(db *sql.DB, contactUsername string) ([]string, error) { rows, err := db.Query(query, "%"+strings.ToLower(contactUsername)+"%") if err != nil && !errors.Is(err, sql.ErrNoRows) { - return nil, helpers.NewError(helpers.ErrInternal, "Failed to get contact suggestions", err) + return []string{}, helpers.NewError(helpers.ErrInternal, "Failed to get contact suggestions", fmt.Errorf("failed to get contact suggestions: %w", err)) } var suggestions []string @@ -337,12 +336,12 @@ func ContactSuggestion(db *sql.DB, contactUsername string) ([]string, error) { var suggestion string err := rows.Scan(&suggestion) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", err) + return []string{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to scan contact suggestion: %w", err)) } suggestions = append(suggestions, suggestion) } if err = rows.Err(); err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process suggestions")) + return []string{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process suggestions: %w", err)) } return suggestions, nil } diff --git a/database/messages.go b/database/messages.go index 0ca4a75..403863f 100644 --- a/database/messages.go +++ b/database/messages.go @@ -11,7 +11,7 @@ import ( func GetMessages(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID, limit int, cursor int) ([]*model.Message, error) { _, err := checkMembership(db, userID, conversationID) if err != nil { - return nil, err + return []*model.Message{}, err } var query string var messages []*model.Message @@ -33,19 +33,19 @@ func GetMessages(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID, limit i ` rows, err := db.Query(query, conversationID, cursor, limit) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to get messages: %w", err)) + return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to get messages: %w", err)) } for rows.Next() { message := &model.Message{} err = rows.Scan(&message.MessageID, &message.Message, &message.SentAt, &message.AttachmentUrl, &message.Sender) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to scan message: %w", err)) + return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to scan message: %w", err)) } messages = append(messages, message) } if err = rows.Err(); err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process messages: %w", err)) + return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process messages: %w", err)) } } else { @@ -64,19 +64,19 @@ func GetMessages(db *sql.DB, userID uuid.UUID, conversationID uuid.UUID, limit i ` rows, err := db.Query(query, conversationID, cursor, limit) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to get messages: %w", err)) + return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to get messages: %w", err)) } for rows.Next() { message := &model.Message{} err = rows.Scan(&message.MessageID, &message.Message, &message.SentAt, &message.AttachmentUrl, &message.Sender) if err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to scan message: %w", err)) + return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "Failed to get messages", fmt.Errorf("failed to scan message: %w", err)) } messages = append(messages, message) } if err = rows.Err(); err != nil { - return nil, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process messages: %w", err)) + return []*model.Message{}, helpers.NewError(helpers.ErrInternal, "internal server error", fmt.Errorf("failed to process messages: %w", err)) } } if cursor != 0 { diff --git a/model/model.go b/model/model.go index 2933d8b..351db84 100644 --- a/model/model.go +++ b/model/model.go @@ -3,6 +3,7 @@ package model import ( "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" + "time" ) type UserClaims struct { @@ -11,15 +12,17 @@ type UserClaims struct { jwt.RegisteredClaims } type Contact struct { - ID int `json:"contact_id"` - ConversationID uuid.UUID `json:"conversation_id"` - UserID uuid.UUID `json:"user_id"` - Username string `json:"username"` - Type string `json:"type"` - LastMessageID int `json:"last_message_id"` - LastMessage string `json:"last_message"` - LastMessageTime string `json:"last_message_time"` - LastMessageSender string `json:"last_message_sender"` + ID int `json:"contact_id"` + ConversationID uuid.UUID `json:"conversation_id"` + UserID uuid.UUID `json:"user_id"` + Username string `json:"username"` + LastActive *time.Time `json:"last_active"` + Type string `json:"type"` + LastReadMessageID *int `json:"last_read_message_id"` + LastMessageID *int `json:"last_message_id"` + LastMessage *time.Time `json:"last_message"` + LastMessageTime *string `json:"last_message_time"` + LastMessageSender *string `json:"last_message_sender"` } type ContactSuggestion struct { @@ -27,9 +30,9 @@ type ContactSuggestion struct { } type Message struct { - MessageID int `json:"message_id"` - Message string `json:"message"` - SentAt string `json:"sent_at"` - Sender string `json:"sender"` - AttachmentUrl string `json:"attachment_url"` + MessageID int `json:"message_id"` + Message string `json:"message"` + SentAt time.Time `json:"sent_at"` + Sender string `json:"sender"` + AttachmentUrl *string `json:"attachment_url"` } diff --git a/router/router.go b/router/router.go index 8795aa3..3af0110 100644 --- a/router/router.go +++ b/router/router.go @@ -21,7 +21,7 @@ func SetupRoutes(app *fiber.App) { auth.Get("/validate", middleware.Protected(), handlers.ValidateToken) // Contacts group - contacts := chat.Group("/contact", middleware.Protected(), logger.New()) + contacts := chat.Group("/contacts", middleware.Protected(), logger.New()) contacts.Delete("/:contactID/:conversation_id", handlers.DeleteContact) contacts.Post("/:contactUsername", handlers.InsertContact) contacts.Get("/", handlers.GetContacts)