package store import ( "context" "errors" "github.com/jackc/pgx/v5" ) // InsertMessage creates a new message in a conversation and returns it. // mediaID, when non-nil, attaches a previously uploaded media object. func (s *Store) InsertMessage(ctx context.Context, conversationID, senderID int64, body string, mediaID *int64) (*Message, error) { var m Message err := s.pool.QueryRow(ctx, ` INSERT INTO messages(conversation_id, sender_id, body, media_id) VALUES($1, $2, $3, $4) RETURNING id, conversation_id, sender_id, body, media_id, created_at, edited_at, deleted_at `, conversationID, senderID, body, mediaID).Scan( &m.ID, &m.ConversationID, &m.SenderID, &m.Body, &m.MediaID, &m.CreatedAt, &m.EditedAt, &m.DeletedAt, ) if err != nil { return nil, err } return &m, nil } // GetMessageByID retrieves a message by ID or returns ErrNotFound. func (s *Store) GetMessageByID(ctx context.Context, id int64) (*Message, error) { var m Message err := s.pool.QueryRow(ctx, ` SELECT id, conversation_id, sender_id, body, media_id, created_at, edited_at, deleted_at FROM messages WHERE id=$1 `, id).Scan( &m.ID, &m.ConversationID, &m.SenderID, &m.Body, &m.MediaID, &m.CreatedAt, &m.EditedAt, &m.DeletedAt, ) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, ErrNotFound } return nil, err } return &m, nil } // ListMessages returns messages for a conversation in reverse chronological order. // If before > 0, only messages with ID less than before are returned. func (s *Store) ListMessages(ctx context.Context, conversationID int64, before int64, limit int) ([]Message, error) { var rows pgx.Rows var err error if before > 0 { rows, err = s.pool.Query(ctx, ` SELECT id, conversation_id, sender_id, body, media_id, created_at, edited_at, deleted_at FROM messages WHERE conversation_id=$1 AND id<$2 ORDER BY id DESC LIMIT $3 `, conversationID, before, limit) } else { rows, err = s.pool.Query(ctx, ` SELECT id, conversation_id, sender_id, body, media_id, created_at, edited_at, deleted_at FROM messages WHERE conversation_id=$1 ORDER BY id DESC LIMIT $2 `, conversationID, limit) } if err != nil { return nil, err } defer rows.Close() var msgs []Message for rows.Next() { var m Message if err := rows.Scan( &m.ID, &m.ConversationID, &m.SenderID, &m.Body, &m.MediaID, &m.CreatedAt, &m.EditedAt, &m.DeletedAt, ); err != nil { return nil, err } msgs = append(msgs, m) } return msgs, nil }