366 lines
10 KiB
Go
366 lines
10 KiB
Go
package controllers
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"log"
|
|
"net/http"
|
|
"openvidu/go/config"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/livekit/protocol/livekit"
|
|
lksdk "github.com/livekit/server-sdk-go/v2"
|
|
)
|
|
|
|
var (
|
|
roomClient *lksdk.RoomServiceClient
|
|
ctx = context.Background()
|
|
)
|
|
|
|
func RoomRoutes(router *gin.Engine) {
|
|
// Initialize RoomServiceClient
|
|
roomClient = lksdk.NewRoomServiceClient(config.LivekitUrl, config.LivekitApiKey, config.LivekitApiSecret)
|
|
|
|
roomGroup := router.Group("/rooms")
|
|
{
|
|
roomGroup.POST("", createRoom)
|
|
roomGroup.GET("", listRooms)
|
|
roomGroup.POST("/:roomName/metadata", updateRoomMetadata)
|
|
roomGroup.POST("/:roomName/send-data", sendData)
|
|
roomGroup.DELETE("/:roomName", deleteRoom)
|
|
roomGroup.GET("/:roomName/participants", listParticipants)
|
|
roomGroup.GET("/:roomName/participants/:participantIdentity", getParticipant)
|
|
roomGroup.PATCH("/:roomName/participants/:participantIdentity", updateParticipant)
|
|
roomGroup.DELETE("/:roomName/participants/:participantIdentity", removeParticipant)
|
|
roomGroup.POST("/:roomName/participants/:participantIdentity/mute", muteParticipant)
|
|
roomGroup.POST("/:roomName/participants/:participantIdentity/subscribe", subscribeParticipant)
|
|
roomGroup.POST("/:roomName/participants/:participantIdentity/unsubscribe", unsubscribeParticipant)
|
|
}
|
|
}
|
|
|
|
// Create a new room
|
|
func createRoom(c *gin.Context) {
|
|
var body struct {
|
|
RoomName string `json:"roomName" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"errorMessage": "'roomName' is required"})
|
|
return
|
|
}
|
|
|
|
req := &livekit.CreateRoomRequest{
|
|
Name: body.RoomName,
|
|
}
|
|
room, err := roomClient.CreateRoom(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error creating room"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{"room": room})
|
|
}
|
|
|
|
// List rooms. If a room name is provided, only that room is listed
|
|
func listRooms(c *gin.Context) {
|
|
roomName := c.Query("roomName")
|
|
|
|
var roomNames []string
|
|
if roomName != "" {
|
|
roomNames = []string{roomName}
|
|
}
|
|
|
|
req := &livekit.ListRoomsRequest{
|
|
Names: roomNames,
|
|
}
|
|
res, err := roomClient.ListRooms(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error listing rooms"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
rooms := res.Rooms
|
|
if rooms == nil {
|
|
rooms = []*livekit.Room{}
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"rooms": rooms})
|
|
}
|
|
|
|
// Update room metadata
|
|
func updateRoomMetadata(c *gin.Context) {
|
|
roomName := c.Param("roomName")
|
|
|
|
var body struct {
|
|
Metadata string `json:"metadata" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"errorMessage": "'metadata' is required"})
|
|
return
|
|
}
|
|
|
|
req := &livekit.UpdateRoomMetadataRequest{
|
|
Room: roomName,
|
|
Metadata: body.Metadata,
|
|
}
|
|
room, err := roomClient.UpdateRoomMetadata(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error updating room metadata"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"room": room})
|
|
}
|
|
|
|
// Send data message to participants in a room
|
|
func sendData(c *gin.Context) {
|
|
roomName := c.Param("roomName")
|
|
|
|
var body struct {
|
|
Data json.RawMessage `json:"data" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"errorMessage": "'data' is required"})
|
|
return
|
|
}
|
|
|
|
rawData, err := json.Marshal(body.Data)
|
|
if err != nil {
|
|
log.Println("Error encoding data message:", err)
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": "Error encoding data message"})
|
|
return
|
|
}
|
|
|
|
topic := "chat"
|
|
req := &livekit.SendDataRequest{
|
|
Room: roomName,
|
|
Data: rawData,
|
|
Kind: livekit.DataPacket_RELIABLE,
|
|
Topic: &topic,
|
|
DestinationIdentities: []string{},
|
|
}
|
|
_, err = roomClient.SendData(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error sending data message"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Data message sent"})
|
|
}
|
|
|
|
// Delete a room
|
|
func deleteRoom(c *gin.Context) {
|
|
roomName := c.Param("roomName")
|
|
|
|
req := &livekit.DeleteRoomRequest{
|
|
Room: roomName,
|
|
}
|
|
_, err := roomClient.DeleteRoom(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error deleting room"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Room deleted"})
|
|
}
|
|
|
|
// List participants in a room
|
|
func listParticipants(c *gin.Context) {
|
|
roomName := c.Param("roomName")
|
|
|
|
req := &livekit.ListParticipantsRequest{
|
|
Room: roomName,
|
|
}
|
|
res, err := roomClient.ListParticipants(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error listing participants"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
participants := res.Participants
|
|
if participants == nil {
|
|
participants = []*livekit.ParticipantInfo{}
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"participants": participants})
|
|
}
|
|
|
|
// Get a participant in a room
|
|
func getParticipant(c *gin.Context) {
|
|
roomName := c.Param("roomName")
|
|
participantIdentity := c.Param("participantIdentity")
|
|
|
|
req := &livekit.RoomParticipantIdentity{
|
|
Room: roomName,
|
|
Identity: participantIdentity,
|
|
}
|
|
participant, err := roomClient.GetParticipant(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error getting participant"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"participant": participant})
|
|
}
|
|
|
|
// Update a participant in a room
|
|
func updateParticipant(c *gin.Context) {
|
|
roomName := c.Param("roomName")
|
|
participantIdentity := c.Param("participantIdentity")
|
|
|
|
var body struct {
|
|
Metadata string `json:"metadata" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"errorMessage": "'metadata' is required"})
|
|
return
|
|
}
|
|
|
|
req := &livekit.UpdateParticipantRequest{
|
|
Room: roomName,
|
|
Identity: participantIdentity,
|
|
Metadata: body.Metadata,
|
|
Permission: &livekit.ParticipantPermission{
|
|
CanPublish: false,
|
|
CanSubscribe: true,
|
|
},
|
|
}
|
|
participant, err := roomClient.UpdateParticipant(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error updating participant"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"participant": participant})
|
|
}
|
|
|
|
// Remove a participant from a room
|
|
func removeParticipant(c *gin.Context) {
|
|
roomName := c.Param("roomName")
|
|
participantIdentity := c.Param("participantIdentity")
|
|
|
|
req := &livekit.RoomParticipantIdentity{
|
|
Room: roomName,
|
|
Identity: participantIdentity,
|
|
}
|
|
_, err := roomClient.RemoveParticipant(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error removing participant"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Participant removed"})
|
|
}
|
|
|
|
// Mute published track of a participant in a room
|
|
func muteParticipant(c *gin.Context) {
|
|
roomName := c.Param("roomName")
|
|
participantIdentity := c.Param("participantIdentity")
|
|
|
|
var body struct {
|
|
TrackId string `json:"trackId" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&body); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"errorMessage": "'trackSid' is required"})
|
|
return
|
|
}
|
|
|
|
req := &livekit.MuteRoomTrackRequest{
|
|
Room: roomName,
|
|
Identity: participantIdentity,
|
|
TrackSid: body.TrackId,
|
|
Muted: true,
|
|
}
|
|
res, err := roomClient.MutePublishedTrack(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error muting track"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"track": res.Track})
|
|
}
|
|
|
|
// Subscribe participant to tracks in a room
|
|
func subscribeParticipant(c *gin.Context) {
|
|
roomName := c.Param("roomName")
|
|
participantIdentity := c.Param("participantIdentity")
|
|
|
|
var body struct {
|
|
TrackIds []string `json:"trackIds" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&body); err != nil || len(body.TrackIds) == 0 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"errorMessage": "'trackIds' is required and must be an array"})
|
|
return
|
|
}
|
|
|
|
req := &livekit.UpdateSubscriptionsRequest{
|
|
Room: roomName,
|
|
Identity: participantIdentity,
|
|
TrackSids: body.TrackIds,
|
|
Subscribe: true,
|
|
}
|
|
_, err := roomClient.UpdateSubscriptions(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error subscribing participant to tracks"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Participant subscribed to tracks"})
|
|
}
|
|
|
|
// Unsubscribe participant from tracks in a room
|
|
func unsubscribeParticipant(c *gin.Context) {
|
|
roomName := c.Param("roomName")
|
|
participantIdentity := c.Param("participantIdentity")
|
|
|
|
var body struct {
|
|
TrackIds []string `json:"trackIds" binding:"required"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&body); err != nil || len(body.TrackIds) == 0 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"errorMessage": "'trackIds' is required and must be an array"})
|
|
return
|
|
}
|
|
|
|
req := &livekit.UpdateSubscriptionsRequest{
|
|
Room: roomName,
|
|
Identity: participantIdentity,
|
|
TrackSids: body.TrackIds,
|
|
Subscribe: false,
|
|
}
|
|
_, err := roomClient.UpdateSubscriptions(ctx, req)
|
|
if err != nil {
|
|
errorMessage := "Error unsubscribing participant from tracks"
|
|
log.Println(errorMessage+":", err.Error())
|
|
c.JSON(http.StatusInternalServerError, gin.H{"errorMessage": errorMessage})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Participant unsubscribed from tracks"})
|
|
}
|