| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/jaevor/go-nanoid" | 
					
						
							|  |  |  | 	"github.com/labstack/echo/v4" | 
					
						
							|  |  |  | 	"github.com/livekit/protocol/auth" | 
					
						
							| 
									
										
										
										
											2022-12-05 02:38:34 +00:00
										 |  |  | 	"github.com/livekit/protocol/livekit" | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	"go.mongodb.org/mongo-driver/bson" | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | 	"go.mongodb.org/mongo-driver/mongo" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 08:33:11 +00:00
										 |  |  | type ( | 
					
						
							|  |  |  | 	TokenResponse struct { | 
					
						
							| 
									
										
										
										
											2022-12-06 13:20:36 +00:00
										 |  |  | 		Url   string `json:"url"` | 
					
						
							|  |  |  | 		Token string `json:"token"` | 
					
						
							| 
									
										
										
										
											2022-12-05 08:33:11 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2022-12-05 07:45:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 19:50:55 +00:00
										 |  |  | // handler for POST to /api/room
 | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | func createRoomHandler(c echo.Context) error { | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | 	room := new(Room) | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	if err := c.Bind(room); err != nil { | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | 		return ErrInvalidRequestFormat | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	if err := mainValidator.StructExcept(room, "RoomID"); err != nil { // New RoomID will be created, so one in request doesn't matter
 | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | 		return wrapValidationError(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	host := c.Get("user").(*AudonUser) | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | 	room.Host = host | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-06 06:09:15 +00:00
										 |  |  | 	coll := mainDB.Collection(COLLECTION_ROOM) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 17:52:44 +00:00
										 |  |  | 	now := time.Now().UTC() | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	if now.After(room.ScheduledAt) { | 
					
						
							| 
									
										
										
										
											2022-12-06 06:09:15 +00:00
										 |  |  | 		// 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}}}, | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 17:52:44 +00:00
										 |  |  | 		room.ScheduledAt = now | 
					
						
							| 
									
										
										
										
											2022-12-06 06:09:15 +00:00
										 |  |  | 	} 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()) | 
					
						
							| 
									
										
										
										
											2022-12-04 17:52:44 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-06 06:09:15 +00:00
										 |  |  | 	room.RoomID = canonic() | 
					
						
							| 
									
										
										
										
											2022-12-04 17:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	// if cohosts are already registered, retrieve their data from DB
 | 
					
						
							| 
									
										
										
										
											2022-12-07 19:03:22 +00:00
										 |  |  | 	for i, cohost := range room.CoHosts { | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | 		cohostUser, err := findUserByRemote(c.Request().Context(), cohost.RemoteID, cohost.RemoteURL) | 
					
						
							|  |  |  | 		if err == nil { | 
					
						
							| 
									
										
										
										
											2022-12-07 19:03:22 +00:00
										 |  |  | 			room.CoHosts[i] = cohostUser | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-04 05:19:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 17:52:44 +00:00
										 |  |  | 	room.CreatedAt = now | 
					
						
							|  |  |  | 	if _, insertErr := coll.InsertOne(c.Request().Context(), room); insertErr != nil { | 
					
						
							|  |  |  | 		c.Logger().Error(insertErr) | 
					
						
							| 
									
										
										
										
											2022-12-04 05:19:41 +00:00
										 |  |  | 		return echo.NewHTTPError(http.StatusInternalServerError) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 17:52:44 +00:00
										 |  |  | 	return c.String(http.StatusCreated, room.RoomID) | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 02:38:34 +00:00
										 |  |  | func joinRoomHandler(c echo.Context) (err error) { | 
					
						
							| 
									
										
										
										
											2022-12-06 06:09:15 +00:00
										 |  |  | 	// TODO: decline the request if user is already in the room
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	roomID := c.Param("id") | 
					
						
							|  |  |  | 	if err := mainValidator.Var(&roomID, "required,printascii"); err != nil { | 
					
						
							|  |  |  | 		return wrapValidationError(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	user := c.Get("user").(*AudonUser) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	room, err := findRoomByID(c.Request().Context(), roomID) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return echo.NewHTTPError(http.StatusNotFound) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	now := time.Now().UTC() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check if room is not yet started
 | 
					
						
							|  |  |  | 	if room.ScheduledAt.After(now) { | 
					
						
							|  |  |  | 		return echo.NewHTTPError(http.StatusConflict, "not_yet_started") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check if room has already ended
 | 
					
						
							|  |  |  | 	if !room.EndedAt.IsZero() && room.EndedAt.Before(now) { | 
					
						
							| 
									
										
										
										
											2022-12-06 06:09:15 +00:00
										 |  |  | 		return ErrAlreadyEnded | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// return 403 if one has been kicked
 | 
					
						
							|  |  |  | 	for _, kicked := range room.Kicked { | 
					
						
							|  |  |  | 		if kicked.Equal(user) { | 
					
						
							|  |  |  | 			return echo.NewHTTPError(http.StatusForbidden) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 	token, err := getRoomToken(room, user, room.IsHost(user) || room.IsCoHost(user)) // host and cohost can talk from the beginning
 | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Logger().Error(err) | 
					
						
							|  |  |  | 		return echo.NewHTTPError(http.StatusInternalServerError) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 08:33:11 +00:00
										 |  |  | 	resp := &TokenResponse{ | 
					
						
							| 
									
										
										
										
											2022-12-06 13:20:36 +00:00
										 |  |  | 		Url:   mainConfig.Livekit.URL.String(), | 
					
						
							|  |  |  | 		Token: token, | 
					
						
							| 
									
										
										
										
											2022-12-05 07:45:51 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 	// Create room in LiveKit if it doesn't exist
 | 
					
						
							|  |  |  | 	metadata, _ := json.Marshal(room) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 07:45:51 +00:00
										 |  |  | 	_, err = lkRoomServiceClient.CreateRoom(c.Request().Context(), &livekit.CreateRoomRequest{ | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 		Name:     room.RoomID, | 
					
						
							|  |  |  | 		Metadata: string(metadata), | 
					
						
							| 
									
										
										
										
											2022-12-05 07:45:51 +00:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Logger().Error(err) | 
					
						
							|  |  |  | 		return echo.NewHTTPError(http.StatusConflict) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-05 02:38:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 07:45:51 +00:00
										 |  |  | 	return c.JSON(http.StatusOK, resp) | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // intended to be called by room's host
 | 
					
						
							|  |  |  | func closeRoomHandler(c echo.Context) error { | 
					
						
							|  |  |  | 	roomID := c.Param("id") | 
					
						
							|  |  |  | 	if err := mainValidator.Var(&roomID, "required,printascii"); err != nil { | 
					
						
							|  |  |  | 		return wrapValidationError(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// retrieve room info from the given room ID
 | 
					
						
							|  |  |  | 	room, err := findRoomByID(c.Request().Context(), roomID) | 
					
						
							|  |  |  | 	if err == mongo.ErrNoDocuments { | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 		return ErrRoomNotFound | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	} else if err != nil { | 
					
						
							|  |  |  | 		c.Logger().Error(err) | 
					
						
							|  |  |  | 		return echo.NewHTTPError(http.StatusInternalServerError) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-06 06:09:15 +00:00
										 |  |  | 	// return 410 if the room has already ended
 | 
					
						
							|  |  |  | 	if !room.EndedAt.IsZero() { | 
					
						
							|  |  |  | 		return ErrAlreadyEnded | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	// only host can close the room
 | 
					
						
							|  |  |  | 	user := c.Get("user").(*AudonUser) | 
					
						
							|  |  |  | 	if !room.IsHost(user) { | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 		return ErrOperationNotPermitted | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := endRoom(c.Request().Context(), room); err != nil { | 
					
						
							|  |  |  | 		c.Logger().Error(err) | 
					
						
							|  |  |  | 		return echo.NewHTTPError(http.StatusInternalServerError) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return c.NoContent(http.StatusOK) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 08:33:11 +00:00
										 |  |  | func updatePermissionHandler(c echo.Context) error { | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 	roomID := c.Param("room") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// look up room in livekit
 | 
					
						
							|  |  |  | 	room, exists := getRoomInLivekit(c.Request().Context(), roomID) | 
					
						
							|  |  |  | 	if !exists { | 
					
						
							|  |  |  | 		return ErrRoomNotFound | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	audonRoom := new(Room) | 
					
						
							|  |  |  | 	err := json.Unmarshal([]byte(room.Metadata), audonRoom) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Logger().Error(err) | 
					
						
							|  |  |  | 		return echo.NewHTTPError(http.StatusInternalServerError) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	iam := c.Get("user").(*AudonUser) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !(audonRoom.IsHost(iam) || audonRoom.IsCoHost(iam)) { | 
					
						
							|  |  |  | 		return ErrOperationNotPermitted | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tgtAudonID := c.Param("user") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !audonRoom.IsUserInLivekitRoom(c.Request().Context(), tgtAudonID) { | 
					
						
							|  |  |  | 		return ErrUserNotFound | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-12-05 08:33:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 	permission := new(livekit.ParticipantPermission) | 
					
						
							|  |  |  | 	if err := c.Bind(permission); err != nil { | 
					
						
							|  |  |  | 		return ErrInvalidRequestFormat | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	info, err := lkRoomServiceClient.UpdateParticipant(c.Request().Context(), &livekit.UpdateParticipantRequest{ | 
					
						
							|  |  |  | 		Room:       roomID, | 
					
						
							|  |  |  | 		Identity:   tgtAudonID, | 
					
						
							|  |  |  | 		Permission: permission, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		c.Logger().Error(err) | 
					
						
							|  |  |  | 		return echo.NewHTTPError(http.StatusInternalServerError) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return c.JSON(http.StatusOK, info) | 
					
						
							| 
									
										
										
										
											2022-12-05 08:33:11 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | func getRoomToken(room *Room, user *AudonUser, canTalk bool) (string, error) { | 
					
						
							| 
									
										
										
										
											2022-12-04 05:19:41 +00:00
										 |  |  | 	at := auth.NewAccessToken(mainConfig.Livekit.APIKey, mainConfig.Livekit.APISecret) | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 	canPublishData := true | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | 	grant := &auth.VideoGrant{ | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 		Room:           room.RoomID, | 
					
						
							|  |  |  | 		RoomJoin:       true, | 
					
						
							|  |  |  | 		RoomCreate:     false, | 
					
						
							|  |  |  | 		CanPublish:     &canTalk, | 
					
						
							|  |  |  | 		CanPublishData: &canPublishData, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	metadata, _ := json.Marshal(map[string]string{ | 
					
						
							|  |  |  | 		"remote_id":  user.RemoteID, | 
					
						
							|  |  |  | 		"remote_url": user.RemoteURL, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	at.AddGrant(grant).SetIdentity(user.AudonID).SetValidFor(10 * time.Minute).SetMetadata(string(metadata)) | 
					
						
							| 
									
										
										
										
											2022-12-03 03:20:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return at.ToJWT() | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | func getRoomInLivekit(ctx context.Context, roomID string) (*livekit.Room, bool) { | 
					
						
							|  |  |  | 	rooms, _ := lkRoomServiceClient.ListRooms(ctx, &livekit.ListRoomsRequest{Names: []string{roomID}}) | 
					
						
							| 
									
										
										
										
											2022-12-06 06:09:15 +00:00
										 |  |  | 	if len(rooms.GetRooms()) == 0 { | 
					
						
							| 
									
										
										
										
											2022-12-06 01:48:03 +00:00
										 |  |  | 		return nil, false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return rooms.GetRooms()[0], true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | func findRoomByID(ctx context.Context, roomID string) (*Room, error) { | 
					
						
							|  |  |  | 	var room Room | 
					
						
							|  |  |  | 	collRoom := mainDB.Collection(COLLECTION_ROOM) | 
					
						
							|  |  |  | 	if err := collRoom.FindOne(ctx, bson.D{{Key: "room_id", Value: roomID}}).Decode(&room); err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return &room, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func endRoom(ctx context.Context, room *Room) error { | 
					
						
							|  |  |  | 	if room == nil { | 
					
						
							|  |  |  | 		return errors.New("room cannot be nil") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !room.EndedAt.IsZero() { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	now := time.Now().UTC() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	collRoom := mainDB.Collection(COLLECTION_ROOM) | 
					
						
							|  |  |  | 	if _, err := collRoom.UpdateOne(ctx, | 
					
						
							|  |  |  | 		bson.D{{Key: "room_id", Value: room.RoomID}}, | 
					
						
							|  |  |  | 		bson.D{ | 
					
						
							|  |  |  | 			{Key: "$set", Value: bson.D{{Key: "ended_at", Value: now}}}, | 
					
						
							|  |  |  | 		}); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 02:38:34 +00:00
										 |  |  | 	rooms, err := lkRoomServiceClient.ListRooms(ctx, &livekit.ListRoomsRequest{Names: []string{room.RoomID}}) | 
					
						
							|  |  |  | 	if err == nil && len(rooms.Rooms) != 0 { | 
					
						
							|  |  |  | 		_, err := lkRoomServiceClient.DeleteRoom(ctx, &livekit.DeleteRoomRequest{Room: room.RoomID}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-05 01:11:44 +00:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } |