From d8a5b3898f7afb6d26e1d88bc22ec63ada93f7fd Mon Sep 17 00:00:00 2001 From: Namekuji Date: Tue, 6 Dec 2022 01:09:15 -0500 Subject: [PATCH] fix instant room creation --- audon-fe/src/main.js | 2 +- error.go | 1 + room.go | 64 ++++++++++++++++++++++++++++++++++++-------- schema.go | 7 +++++ 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/audon-fe/src/main.js b/audon-fe/src/main.js index 74f8e16..45c6583 100644 --- a/audon-fe/src/main.js +++ b/audon-fe/src/main.js @@ -32,5 +32,5 @@ app.use(createPinia()); app.use(vuetify); app.use(router); -app.config.compilerOptions.delimiters = ["{%", "%}"]; +// app.config.compilerOptions.delimiters = ["{%", "%}"]; app.mount("#app"); diff --git a/error.go b/error.go index 89a23b5..65238f9 100644 --- a/error.go +++ b/error.go @@ -14,6 +14,7 @@ var ( ErrRoomNotFound = echo.NewHTTPError(http.StatusNotFound, "room_not_found") ErrOperationNotPermitted = echo.NewHTTPError(http.StatusForbidden, "operation_not_permitted") ErrUserNotFound = echo.NewHTTPError(http.StatusNotFound, "user_not_found") + ErrAlreadyEnded = echo.NewHTTPError(http.StatusGone, "already_ended") ) func wrapValidationError(err error) error { diff --git a/room.go b/room.go index db0431d..3089b89 100644 --- a/room.go +++ b/room.go @@ -32,20 +32,56 @@ func createRoomHandler(c echo.Context) error { return wrapValidationError(err) } + host := c.Get("user").(*AudonUser) + room.Host = host + + coll := mainDB.Collection(COLLECTION_ROOM) + + now := time.Now().UTC() + if now.After(room.ScheduledAt) { + // host is trying to create an instant room even though there is another instant room that wasn't used, assumed that host won't use such rooms + if cur, err := coll.Find(c.Request().Context(), + bson.D{ + {Key: "host.audon_id", Value: host.AudonID}, + {Key: "ended_at", Value: time.Time{}}, // host didn't close + {Key: "$expr", Value: bson.D{ // instant room + {Key: "$eq", Value: bson.A{"$created_at", "$scheduled_at"}}, + }}, + }); err == nil { + defer cur.Close(c.Request().Context()) + + roomIDsToBeDeleted := []string{} + for cur.Next(c.Request().Context()) { + emptyRoom := new(Room) + if err := cur.Decode(emptyRoom); err == nil { + if !emptyRoom.IsAnyomeInLivekitRoom(c.Request().Context()) { + roomIDsToBeDeleted = append(roomIDsToBeDeleted, emptyRoom.RoomID) + } + } + } + if len(roomIDsToBeDeleted) > 0 { + coll.DeleteMany(c.Request().Context(), bson.D{{ + Key: "room_id", + Value: bson.D{{Key: "$in", Value: roomIDsToBeDeleted}}}, + }) + } + } + + room.ScheduledAt = now + } else { + // TODO: limit the number of rooms one can schedule? + } + + // TODO: use a job scheduler to manage rooms? + + room.EndedAt = time.Time{} + canonic, err := nanoid.Standard(16) if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } room.RoomID = canonic() - host := c.Get("user").(*AudonUser) - room.Host = host - - now := time.Now().UTC() - if now.After(room.ScheduledAt) { - room.ScheduledAt = now - } - // if cohosts are already registered, retrieve their data from DB for i, cohost := range room.CoHost { cohostUser, err := findUserByRemote(c.Request().Context(), cohost.RemoteID, cohost.RemoteURL) @@ -55,7 +91,6 @@ func createRoomHandler(c echo.Context) error { } room.CreatedAt = now - coll := mainDB.Collection(COLLECTION_ROOM) if _, insertErr := coll.InsertOne(c.Request().Context(), room); insertErr != nil { c.Logger().Error(insertErr) return echo.NewHTTPError(http.StatusInternalServerError) @@ -65,6 +100,8 @@ func createRoomHandler(c echo.Context) error { } func joinRoomHandler(c echo.Context) (err error) { + // TODO: decline the request if user is already in the room + roomID := c.Param("id") if err := mainValidator.Var(&roomID, "required,printascii"); err != nil { return wrapValidationError(err) @@ -86,7 +123,7 @@ func joinRoomHandler(c echo.Context) (err error) { // check if room has already ended if !room.EndedAt.IsZero() && room.EndedAt.Before(now) { - return echo.NewHTTPError(http.StatusGone, "already_ended") + return ErrAlreadyEnded } // return 403 if one has been kicked @@ -138,6 +175,11 @@ func closeRoomHandler(c echo.Context) error { return echo.NewHTTPError(http.StatusInternalServerError) } + // return 410 if the room has already ended + if !room.EndedAt.IsZero() { + return ErrAlreadyEnded + } + // only host can close the room user := c.Get("user").(*AudonUser) if !room.IsHost(user) { @@ -220,7 +262,7 @@ func getRoomToken(room *Room, user *AudonUser, canTalk bool) (string, error) { func getRoomInLivekit(ctx context.Context, roomID string) (*livekit.Room, bool) { rooms, _ := lkRoomServiceClient.ListRooms(ctx, &livekit.ListRoomsRequest{Names: []string{roomID}}) - if len(rooms.GetRooms()) != 0 { + if len(rooms.GetRooms()) == 0 { return nil, false } diff --git a/schema.go b/schema.go index c8c7980..cbb1d26 100644 --- a/schema.go +++ b/schema.go @@ -85,6 +85,13 @@ func (r *Room) IsUserInLivekitRoom(ctx context.Context, userID string) bool { return false } +func (r *Room) IsAnyomeInLivekitRoom(ctx context.Context) bool { + participantsInfo, _ := lkRoomServiceClient.ListParticipants(ctx, &livekit.ListParticipantsRequest{Room: r.RoomID}) + participants := participantsInfo.GetParticipants() + + return len(participants) > 0 +} + func createIndexes(ctx context.Context) error { userColl := mainDB.Collection(COLLECTION_USER) userIndexes, err := userColl.Indexes().ListSpecifications(ctx)