Skip to content

Commit

Permalink
feat: send media message
Browse files Browse the repository at this point in the history
  • Loading branch information
litsynp committed Aug 15, 2024
1 parent d5cc866 commit a719c1a
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 23 deletions.
2 changes: 1 addition & 1 deletion cmd/server/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func NewRouter(app *firebaseinfra.FirebaseApp) (*echo.Echo, error) {
// }

upgrader := wschat.NewDefaultUpgrader()
wsServerV2 := wschat.NewWSServer(upgrader, authService)
wsServerV2 := wschat.NewWSServer(upgrader, authService, *mediaService)

go wsServerV2.LoopOverClientMessages()

Expand Down
9 changes: 9 additions & 0 deletions internal/domain/media/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ func ToDetailViewFromCreated(media databasegen.CreateMediaRow) *DetailView {
}
}

func ToDetailViewFromFindByIDs(media *databasegen.FindMediasByIDsRow) *DetailView {
return &DetailView{
ID: int64(media.ID),
MediaType: Type(media.MediaType),
URL: media.Url,
CreatedAt: media.CreatedAt,
}
}

func ToDetailViewFromResourceMediaRows(resourceMedia databasegen.FindResourceMediaRow) *DetailView {
return &DetailView{
ID: int64(resourceMedia.MediaID),
Expand Down
56 changes: 56 additions & 0 deletions internal/infra/database/gen/media.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions internal/service/media_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package service
import (
"context"
"io"
"sort"

bucketinfra "github.com/pet-sitter/pets-next-door-api/internal/infra/bucket"

Expand Down Expand Up @@ -79,3 +80,42 @@ func (s *MediaService) FindMediaByID(ctx context.Context, id int64) (*media.Deta

return media.ToDetailView(mediaData), nil
}

func (s *MediaService) FindMediasByIDs(ctx context.Context, ids []int64) ([]media.DetailView, *pnd.AppError) {
if len(ids) == 0 {
return make([]media.DetailView, 0), nil
}

// TODO: filter unique IDs
idsToGet := make([]int32, 0)
for _, id := range ids {
idsToGet = append(idsToGet, int32(id))
}
mediaDataList, err := databasegen.New(s.conn).FindMediasByIDs(ctx, databasegen.FindMediasByIDsParams{
Ids: idsToGet,
IncludeDeleted: false,
})
if err != nil {
return nil, pnd.FromPostgresError(err)
}
views := make([]media.DetailView, 0)
for _, mediaData := range mediaDataList {
views = append(views, *media.ToDetailViewFromFindByIDs(&mediaData))
}

// Sort by given IDs
sort.Slice(views, func(i, j int) bool {
return FindIndex(ids, views[i].ID) < FindIndex(ids, views[j].ID)
})

return views, nil
}

func FindIndex(arr []int64, val int64) int {
for i, v := range arr {
if v == val {
return i
}
}
return -1
}
104 changes: 82 additions & 22 deletions internal/wschat/server.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package wschat

import (
"context"
"net/http"
"strconv"
"time"

"github.com/gorilla/websocket"
"github.com/labstack/echo/v4"
"github.com/pet-sitter/pets-next-door-api/internal/domain/media"
"github.com/pet-sitter/pets-next-door-api/internal/service"
"github.com/rs/zerolog/log"
)
Expand All @@ -17,18 +19,21 @@ type WSServer struct {
broadcast chan MessageRequest
upgrader websocket.Upgrader

authService service.AuthService
authService service.AuthService
mediaService service.MediaService
}

func NewWSServer(
upgrader websocket.Upgrader,
authService service.AuthService,
mediaService service.MediaService,
) *WSServer {
return &WSServer{
clients: make(map[int64]WSClient),
broadcast: make(chan MessageRequest),
upgrader: upgrader,
authService: authService,
clients: make(map[int64]WSClient),
broadcast: make(chan MessageRequest),
upgrader: upgrader,
authService: authService,
mediaService: mediaService,
}
}

Expand Down Expand Up @@ -91,6 +96,7 @@ func (s *WSServer) HandleConnections(
// Broadcast messages to all clients
func (s *WSServer) LoopOverClientMessages() {
log.Info().Msg("Looping over client messages")
ctx := context.Background()

for {
msgReq := <-s.broadcast
Expand All @@ -101,8 +107,36 @@ func (s *WSServer) LoopOverClientMessages() {
strconv.Itoa(int(client.userID)) +
" to user: " + strconv.Itoa(int(msgReq.Sender.ID)))

// Message print
log.Info().Msg("Message: " + msgReq.String())

// TODO: Check if the message is for the room
msg := NewPlainMessageResponse(msgReq.MessageID, msgReq.Sender, msgReq.Room, msgReq.Message, time.Now())
var msg MessageResponse
switch msgReq.MessageType {
case "plain":
msg = NewPlainMessageResponse(msgReq.MessageID, msgReq.Sender, msgReq.Room, msgReq.Message, time.Now())
break
case "media":
if len(msgReq.Medias) == 0 {
log.Error().Msg("No media found")
msg = NewErrorMessageResponse(msgReq.MessageID, msgReq.Sender, msgReq.Room, "No media found", time.Now())
} else {
ids := make([]int64, 0)
for _, mediaReq := range msgReq.Medias {
ids = append(ids, mediaReq.ID)
}
medias, err := s.mediaService.FindMediasByIDs(ctx, ids)
if err != nil {
log.Error().Err(err.Err).Msg("Failed to find media")
msg = NewErrorMessageResponse(msgReq.MessageID, msgReq.Sender, msgReq.Room, "Failed to find media", time.Now())
}
msg = NewMediaMessageResponse(msgReq.MessageID, msgReq.Sender, msgReq.Room, medias, time.Now())
}
break
default:
log.Error().Msg("Unknown message type")
return
}

if err := client.WriteJSON(msg); err != nil {
// No way but to close the connection
Expand Down Expand Up @@ -140,24 +174,32 @@ func (c *WSClient) Close() error {
return c.conn.Close()
}

type MediaRequest struct {
ID int64 `json:"id"`
}

type MessageRequest struct {
Sender Sender `json:"sender"`
Room Room `json:"room"`
MessageID string `json:"messageId"`
MessageType string `json:"messageType"`
Media *Media `json:"media,omitempty"`
Message string `json:"message"`
Sender Sender `json:"sender"`
Room Room `json:"room"`
MessageID string `json:"messageId"`
MessageType string `json:"messageType"`
Medias []MediaRequest `json:"medias,omitempty"`
Message string `json:"message"`
}

func (m MessageRequest) String() string {
return "Sender: " + strconv.Itoa(int(m.Sender.ID)) + " Room: " + strconv.Itoa(int(m.Room.ID)) + " MessageID: " + m.MessageID + " MessageType: " + m.MessageType + " Message: " + m.Message + " Medias: " + strconv.Itoa(len(m.Medias))
}

type MessageResponse struct {
Sender Sender `json:"sender"`
Room Room `json:"room"`
MessageID string `json:"messageId"`
MessageType string `json:"messageType"`
Media *Media `json:"media,omitempty"`
Message string `json:"message"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Sender Sender `json:"sender"`
Room Room `json:"room"`
MessageID string `json:"messageId"`
MessageType string `json:"messageType"`
Medias []media.DetailView `json:"medias,omitempty"`
Message string `json:"message"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}

type Sender struct {
Expand Down Expand Up @@ -192,19 +234,37 @@ func NewPlainMessageResponse(
}
}

func NewErrorMessageResponse(
messageID string,
sender Sender,
room Room,
message string,
now time.Time,
) MessageResponse {
return MessageResponse{
MessageID: messageID,
Sender: sender,
Room: room,
MessageType: "error",
Message: message,
CreatedAt: now.Format(time.RFC3339),
UpdatedAt: now.Format(time.RFC3339),
}
}

func NewMediaMessageResponse(
messageID string,
sender Sender,
room Room,
media *Media,
medias []media.DetailView,
now time.Time,
) MessageResponse {
return MessageResponse{
MessageID: messageID,
Sender: sender,
Room: room,
MessageType: "media",
Media: media,
Medias: medias,
CreatedAt: now.Format(time.RFC3339),
UpdatedAt: now.Format(time.RFC3339),
}
Expand Down
10 changes: 10 additions & 0 deletions queries/media.sql
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,13 @@ WHERE (id = sqlc.narg('id') OR sqlc.narg('id') IS NULL)
AND (sqlc.arg('include_deleted')::BOOLEAN = TRUE OR
(sqlc.arg('include_deleted')::BOOLEAN = FALSE AND deleted_at IS NULL));

-- name: FindMediasByIDs :many
SELECT id,
media_type,
url,
created_at,
updated_at
FROM media
WHERE id = ANY (sqlc.arg('ids')::int[]) -- Assuming 'ids' is passed as an array of UUIDs
AND (sqlc.arg('include_deleted')::BOOLEAN = TRUE OR
(sqlc.arg('include_deleted')::BOOLEAN = FALSE AND deleted_at IS NULL));

0 comments on commit a719c1a

Please sign in to comment.