audon/room.go

665 wiersze
19 KiB
Go

2022-12-03 03:20:49 +00:00
package main
import (
2022-12-05 01:11:44 +00:00
"context"
2023-01-23 12:10:21 +00:00
"encoding/base64"
2022-12-06 01:48:03 +00:00
"encoding/json"
2022-12-05 01:11:44 +00:00
"errors"
2023-01-23 12:10:21 +00:00
"fmt"
"io"
2022-12-03 03:20:49 +00:00
"net/http"
2023-01-23 12:10:21 +00:00
"net/url"
"os"
2022-12-03 03:20:49 +00:00
"time"
"github.com/jaevor/go-nanoid"
2023-01-23 12:10:21 +00:00
"github.com/jellydator/ttlcache/v3"
2022-12-03 03:20:49 +00:00
"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-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
2023-01-29 03:16:21 +00:00
// check if user is already hosting or cohosting
2023-01-26 18:28:25 +00:00
lkRooms, err := host.GetCurrentLivekitRooms(c.Request().Context())
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
for _, r := range lkRooms {
meta, err := getRoomMetadataFromLivekitRoom(r)
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
2023-01-29 03:16:21 +00:00
if meta.IsHost(host) || meta.IsCoHost(host) {
2023-01-26 18:28:25 +00:00
return ErrOperationNotPermitted
}
}
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-06 06:09:15 +00:00
// 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
2023-01-26 22:31:53 +00:00
room.CreatedAt = now
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 {
cohostUser, err := findUserByWebfinger(c.Request().Context(), cohost.Webfinger)
2022-12-03 03:20:49 +00:00
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
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)
}
2023-01-26 22:31:53 +00:00
// Create livekit room
2023-01-29 03:16:21 +00:00
roomMetadata := &RoomMetadata{Room: room, Speakers: []*AudonUser{}, Kicked: []*AudonUser{}, MastodonAccounts: make(map[string]*MastodonAccount)}
2023-01-26 22:31:53 +00:00
metadata, _ := json.Marshal(roomMetadata)
_, err = lkRoomServiceClient.CreateRoom(c.Request().Context(), &livekit.CreateRoomRequest{
Name: room.RoomID,
Metadata: string(metadata),
})
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusConflict)
}
countdown := time.NewTimer(mainConfig.Livekit.EmptyRoomTimeout)
orphanRooms.Set(room.RoomID, true, ttlcache.DefaultTTL)
go func(r *Room, logger echo.Logger) {
<-countdown.C
if orphaned := orphanRooms.Get(r.RoomID); orphaned == nil {
return
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if !r.IsAnyomeInLivekitRoom(ctx) {
if err := endRoom(ctx, r); err != nil {
logger.Error(err)
}
}
}(room, c.Logger())
2022-12-04 17:52:44 +00:00
return c.String(http.StatusCreated, room.RoomID)
2022-12-03 03:20:49 +00:00
}
type RoomUpdateRequest struct {
Title string `bson:"title" json:"title" validate:"required,max=100,printascii|multibyte"`
Description string `bson:"description" json:"description" validate:"max=500,ascii|multibyte"`
Restriction JoinRestriction `bson:"restriction" json:"restriction"`
}
func updateRoomHandler(c echo.Context) (err error) {
roomID := c.Param("id")
if err := mainValidator.Var(&roomID, "required,printascii"); err != nil {
return wrapValidationError(err)
}
user := c.Get("user").(*AudonUser)
var room *RoomMetadata
lkRoom, _ := getRoomInLivekit(c.Request().Context(), roomID)
if lkRoom != nil {
room, _ = getRoomMetadataFromLivekitRoom(lkRoom)
} else {
dbRoom, err := findRoomByID(c.Request().Context(), roomID)
if err != nil {
return ErrRoomNotFound
}
room = new(RoomMetadata)
room.Room = dbRoom
}
if !room.IsHost(user) {
return ErrOperationNotPermitted
}
req := new(RoomUpdateRequest)
if err = c.Bind(req); err != nil {
return ErrInvalidRequestFormat
}
if err = mainValidator.Struct(req); err != nil {
return wrapValidationError(err)
}
coll := mainDB.Collection(COLLECTION_ROOM)
if _, err = coll.UpdateOne(c.Request().Context(),
bson.D{{Key: "room_id", Value: roomID}},
bson.D{{Key: "$set", Value: req}}); err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
if lkRoom != nil {
room.Title = req.Title
room.Description = req.Description
room.Restriction = req.Restriction
newMetadata, _ := json.Marshal(room)
if _, err := lkRoomServiceClient.UpdateRoomMetadata(c.Request().Context(), &livekit.UpdateRoomMetadataRequest{Room: roomID, Metadata: string(newMetadata)}); err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
}
return c.JSON(http.StatusOK, room)
}
2023-01-04 10:48:24 +00:00
// handler for GET to /r/:id
func renderRoomHandler(c echo.Context) error {
roomID := c.Param("id")
if err := mainValidator.Var(&roomID, "required,printascii"); err != nil {
return wrapValidationError(err)
}
room, err := findRoomByID(c.Request().Context(), roomID)
if err != nil {
return echo.NotFoundHandler(c)
}
return c.Render(http.StatusOK, "tmpl", &TemplateData{Config: &mainConfig.AppConfigBase, Room: room})
}
// for preview, this bypasses authentication
2022-12-29 14:53:42 +00:00
func previewRoomHandler(c echo.Context) (err error) {
roomID := c.Param("id")
if err := mainValidator.Var(&roomID, "required,printascii"); err != nil {
return wrapValidationError(err)
}
room, _ := findRoomByID(c.Request().Context(), roomID)
if room != nil && !room.EndedAt.IsZero() && room.EndedAt.Before(time.Now()) {
return ErrAlreadyEnded
}
2022-12-29 14:53:42 +00:00
lkRoom, _ := getRoomInLivekit(c.Request().Context(), roomID)
if lkRoom == nil {
return ErrRoomNotFound
}
roomMetadata, err := getRoomMetadataFromLivekitRoom(lkRoom)
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
if roomMetadata.Restriction != EVERYONE {
return ErrOperationNotPermitted
}
participants, err := lkRoomServiceClient.ListParticipants(c.Request().Context(), &livekit.ListParticipantsRequest{Room: roomID})
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
userMetadata := map[string]*AudonUser{}
for _, part := range participants.GetParticipants() {
user := new(AudonUser)
if err := json.Unmarshal([]byte(part.GetMetadata()), user); err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
userMetadata[part.Identity] = user
}
return c.JSON(http.StatusOK, map[string]interface{}{"roomInfo": roomMetadata, "participants": userMetadata})
}
2022-12-05 02:38:34 +00:00
func joinRoomHandler(c echo.Context) (err error) {
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 ErrRoomNotFound
2022-12-08 08:56:29 +00:00
}
2022-12-05 01:11:44 +00:00
now := time.Now().UTC()
// 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
}
2022-12-10 03:16:43 +00:00
canTalk := room.IsHost(user) || room.IsCoHost(user) // host and cohost can talk from the beginning
2022-12-15 20:28:41 +00:00
// check room restriction
if room.IsPrivate() && !canTalk {
2022-12-17 02:30:46 +00:00
return c.String(http.StatusForbidden, string(room.Restriction))
2022-12-15 20:28:41 +00:00
}
if !canTalk && (room.IsFollowingOnly() || room.IsFollowerOnly() || room.IsFollowingOrFollowerOnly() || room.IsMutualOnly()) {
2023-01-23 12:10:21 +00:00
data, _ := getSessionData(c)
mastoClient := getMastodonClient(data)
2022-12-15 20:28:41 +00:00
if mastoClient == nil {
return echo.NewHTTPError(http.StatusInternalServerError)
}
search, err := mastoClient.AccountsSearch(c.Request().Context(), room.Host.Webfinger, 1)
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
if len(search) != 1 {
return ErrOperationNotPermitted
}
rels, err := mastoClient.GetAccountRelationships(c.Request().Context(), []string{string(search[0].ID)})
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
if len(rels) != 1 {
return ErrOperationNotPermitted
}
rel := rels[0]
if (room.IsFollowingOnly() && !rel.FollowedBy) ||
(room.IsFollowerOnly() && !rel.Following) ||
(room.IsFollowingOrFollowerOnly() && !(rel.FollowedBy || rel.Following)) ||
(room.IsMutualOnly() && !(rel.FollowedBy && rel.Following)) {
2022-12-15 21:43:50 +00:00
return c.String(http.StatusForbidden, string(room.Restriction))
2022-12-15 20:28:41 +00:00
}
}
2023-01-29 04:33:16 +00:00
lkRoom, _ := getRoomInLivekit(c.Request().Context(), room.RoomID) // lkRoom will be nil if it doesn't exist
if lkRoom == nil {
return ErrRoomNotFound
}
roomMetadata, _ := getRoomMetadataFromLivekitRoom(lkRoom)
2023-01-29 03:16:21 +00:00
// return 403 if one has been kicked
for _, kicked := range roomMetadata.Kicked {
if kicked.Equal(user) {
return echo.NewHTTPError(http.StatusForbidden)
}
}
2022-12-10 03:16:43 +00:00
// Allows the user to talk if the user is a speaker
2023-01-29 03:16:21 +00:00
for _, speaker := range roomMetadata.Speakers {
if speaker.AudonID == user.AudonID {
canTalk = true
break
2022-12-10 03:16:43 +00:00
}
}
token, err := getRoomToken(room, user, canTalk)
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{
2023-01-23 12:10:21 +00:00
Url: mainConfig.Livekit.URL.String(),
Token: token,
Audon: user,
}
2023-01-25 06:37:31 +00:00
mastoAccount := new(MastodonAccount)
if err := c.Bind(&mastoAccount); err != nil {
c.Logger().Error(err)
return ErrInvalidRequestFormat
2023-01-23 12:10:21 +00:00
}
2023-01-25 06:37:31 +00:00
roomMetadata.MastodonAccounts[user.AudonID] = mastoAccount
2023-01-25 20:58:15 +00:00
// Get user's stored avatar if exists
if user.AvatarFile != "" {
orig, err := os.ReadFile(user.getAvatarImagePath(user.AvatarFile))
if err == nil && orig != nil {
resp.Original = fmt.Sprintf("data:image/png;base64,%s", base64.StdEncoding.EncodeToString(orig))
2023-01-25 20:58:15 +00:00
} else if orig == nil {
user.AvatarFile = ""
2023-01-25 06:37:31 +00:00
}
2023-01-25 20:58:15 +00:00
// icon, err := os.ReadFile(user.GetGIFAvatarPath())
// if err == nil && icon != nil {
// resp.Indicator = fmt.Sprintf("data:image/gif;base64,%s", base64.StdEncoding.EncodeToString(icon))
// }
}
avatarLink := mastoAccount.Avatar
if err := mainValidator.Var(&avatarLink, "required"); err != nil {
return wrapValidationError(err)
}
avatarURL, err := url.Parse(avatarLink)
if err != nil {
c.Logger().Error(err)
return ErrInvalidRequestFormat
}
// Retrieve user's current avatar if the old one doesn't exist in Audon.
// Skips if user is still in another room.
if already, err := user.InLivekit(c.Request().Context()); !already && err == nil && user.AvatarFile == "" {
// Download user's avatar
req, err := http.NewRequest(http.MethodGet, avatarURL.String(), nil)
2023-01-23 12:10:21 +00:00
if err != nil {
2023-01-25 06:37:31 +00:00
c.Logger().Error(err)
2023-01-23 12:10:21 +00:00
return ErrInvalidRequestFormat
}
2023-01-25 20:58:15 +00:00
req.Header.Set("User-Agent", USER_AGENT)
2023-01-23 12:10:21 +00:00
2023-01-25 20:58:15 +00:00
avatarResp, err := http.DefaultClient.Do(req)
if err != nil {
c.Logger().Error(err)
return ErrInvalidRequestFormat
}
defer avatarResp.Body.Close()
2023-01-23 12:10:21 +00:00
2023-01-25 20:58:15 +00:00
fnew, err := io.ReadAll(avatarResp.Body)
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
2023-01-23 12:10:21 +00:00
2023-01-25 20:58:15 +00:00
// Generate indicator GIF
2023-05-28 12:36:24 +00:00
// indicator, original, isGIF, err := user.GetIndicator(c.Request().Context(), fnew, room)
_, original, isGIF, err := user.GetIndicator(c.Request().Context(), fnew, room)
2023-01-28 13:21:01 +00:00
origMime := "image/png"
if isGIF {
origMime = "image/gif"
}
2023-01-25 20:58:15 +00:00
if err != nil {
2023-01-23 12:10:21 +00:00
c.Logger().Error(err)
2023-01-25 20:58:15 +00:00
return echo.NewHTTPError(http.StatusInternalServerError)
2023-01-23 12:10:21 +00:00
}
2023-01-28 13:21:01 +00:00
resp.Original = fmt.Sprintf("data:%s;base64,%s", origMime, base64.StdEncoding.EncodeToString(original))
2023-05-28 12:36:24 +00:00
// resp.Indicator = fmt.Sprintf("data:image/gif;base64,%s", base64.StdEncoding.EncodeToString(indicator))
2023-01-25 20:58:15 +00:00
} else if err != nil {
c.Logger().Error(err)
2022-12-05 07:45:51 +00:00
}
2023-01-26 22:31:53 +00:00
// Update room metadata
2023-01-29 03:16:21 +00:00
roomMetadata.MastodonAccounts[user.AudonID] = mastoAccount
newMetadata, err := json.Marshal(roomMetadata)
2023-01-26 22:31:53 +00:00
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
_, err = lkRoomServiceClient.UpdateRoomMetadata(c.Request().Context(), &livekit.UpdateRoomMetadataRequest{
Room: roomID,
Metadata: string(newMetadata),
})
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
2022-12-05 07:45:51 +00:00
}
2022-12-05 02:38:34 +00:00
2023-01-23 12:10:21 +00:00
// Store user's session data in cache
2023-01-26 22:31:53 +00:00
orphanRooms.Delete(roomID)
2023-01-23 12:10:21 +00:00
2022-12-05 07:45:51 +00:00
return c.JSON(http.StatusOK, resp)
2022-12-05 01:11:44 +00:00
}
2023-01-29 03:16:21 +00:00
// intended to be called by room's host or cohost
2022-12-05 01:11:44 +00:00
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
}
2023-01-29 03:16:21 +00:00
meta := room.getRoomMetadata(c.Request().Context())
if meta == nil {
return ErrRoomNotFound
}
2023-01-28 20:08:15 +00:00
// only host or cohost can close the room
2022-12-05 01:11:44 +00:00
user := c.Get("user").(*AudonUser)
2023-01-29 03:16:21 +00:00
if !meta.IsHost(user) && !meta.IsCoHost(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)
}
2023-01-23 12:10:21 +00:00
// Client notifies server that user left room
func leaveRoomHandler(c echo.Context) error {
user := c.Get("user").(*AudonUser)
still, err := user.InLivekit(c.Request().Context())
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
} else if still {
2023-01-25 06:37:31 +00:00
return c.NoContent(http.StatusConflict)
2023-01-23 12:10:21 +00:00
}
if err := user.ClearUserAvatar(c.Request().Context()); err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
return c.NoContent(http.StatusOK)
}
2023-01-29 03:16:21 +00:00
func updateRoleHandler(c echo.Context) error {
roomID := c.Param("id")
2022-12-06 01:48:03 +00:00
2022-12-10 03:16:43 +00:00
// look up lkRoom in livekit
lkRoom, exists := getRoomInLivekit(c.Request().Context(), roomID)
2022-12-06 01:48:03 +00:00
if !exists {
return ErrRoomNotFound
}
2022-12-10 03:16:43 +00:00
lkRoomMetadata, err := getRoomMetadataFromLivekitRoom(lkRoom)
2022-12-06 01:48:03 +00:00
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
iam := c.Get("user").(*AudonUser)
2022-12-10 03:16:43 +00:00
if !(lkRoomMetadata.IsHost(iam) || lkRoomMetadata.IsCoHost(iam)) {
2022-12-06 01:48:03 +00:00
return ErrOperationNotPermitted
}
2023-01-29 03:16:21 +00:00
params := make(map[string]string)
if err := c.Bind(&params); err != nil {
return ErrInvalidRequestFormat
}
audonID := params["identity"]
operation := params["op"]
2023-01-23 12:10:21 +00:00
if !lkRoomMetadata.IsUserInLivekitRoom(c.Request().Context(), audonID) {
2022-12-10 03:16:43 +00:00
return ErrUserNotFound
}
2023-01-23 12:10:21 +00:00
tgtUser, err := findUserByID(c.Request().Context(), audonID)
2022-12-10 03:16:43 +00:00
if err != nil {
2022-12-06 01:48:03 +00:00
return ErrUserNotFound
}
2022-12-10 03:16:43 +00:00
if lkRoomMetadata.IsHost(tgtUser) || lkRoomMetadata.IsCoHost(tgtUser) {
return ErrOperationNotPermitted
}
2022-12-05 08:33:11 +00:00
2022-12-10 03:16:43 +00:00
newPermission := &livekit.ParticipantPermission{
CanPublishData: true,
CanSubscribe: true,
2023-01-29 03:16:21 +00:00
CanPublish: true,
2022-12-10 03:16:43 +00:00
}
2023-01-29 03:16:21 +00:00
if operation == "speaker" {
2022-12-10 03:16:43 +00:00
for _, speaker := range lkRoomMetadata.Speakers {
if speaker.Equal(tgtUser) {
return echo.NewHTTPError(http.StatusConflict, "already_speaking")
}
}
lkRoomMetadata.Speakers = append(lkRoomMetadata.Speakers, tgtUser)
2023-01-29 03:16:21 +00:00
} else if operation == "cohost" {
lkRoomMetadata.CoHosts = append(lkRoomMetadata.CoHosts, tgtUser)
coll := mainDB.Collection(COLLECTION_ROOM)
if _, err = coll.UpdateOne(c.Request().Context(),
bson.D{{Key: "room_id", Value: roomID}},
bson.D{{Key: "$set", Value: bson.D{{
Key: "cohosts",
Value: lkRoomMetadata.CoHosts,
}}}}); err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
} else if operation == "kick" {
lkRoomMetadata.Kicked = append(lkRoomMetadata.Kicked, tgtUser)
lkRoomServiceClient.RemoveParticipant(c.Request().Context(), &livekit.RoomParticipantIdentity{
Room: roomID,
Identity: tgtUser.AudonID,
})
} else if operation == "demote" {
newPermission.CanPublish = false
} else {
return ErrInvalidRequestFormat
}
if operation == "demote" || operation == "cohost" {
newSpeakers := make([]*AudonUser, 0, len(lkRoomMetadata.Speakers))
for _, v := range lkRoomMetadata.Speakers {
if v.AudonID != tgtUser.AudonID {
newSpeakers = append(newSpeakers, v)
}
}
lkRoomMetadata.Speakers = newSpeakers
2022-12-10 03:16:43 +00:00
}
newMetadata, err := json.Marshal(lkRoomMetadata)
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
2023-01-29 03:16:21 +00:00
if operation != "kick" {
_, err = lkRoomServiceClient.UpdateParticipant(c.Request().Context(), &livekit.UpdateParticipantRequest{
Room: roomID,
Identity: audonID,
Permission: newPermission,
})
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
2022-12-06 01:48:03 +00:00
}
2023-01-29 03:16:21 +00:00
metadataRequest := &livekit.UpdateRoomMetadataRequest{Room: roomID, Metadata: string(newMetadata)}
_, err = lkRoomServiceClient.UpdateRoomMetadata(context.Background(), metadataRequest)
2022-12-06 01:48:03 +00:00
if err != nil {
c.Logger().Error(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
2023-01-29 03:16:21 +00:00
return c.NoContent(http.StatusOK)
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,
}
2022-12-29 14:53:42 +00:00
metadata, _ := json.Marshal(user)
2022-12-06 01:48:03 +00:00
2022-12-13 18:02:25 +00:00
at.AddGrant(grant).SetIdentity(user.AudonID).SetValidFor(24 * time.Hour).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) {
2023-01-20 15:39:51 +00:00
if err := mainValidator.Var(&roomID, "required,printascii"); err != nil {
return nil, err
}
2022-12-05 01:11:44 +00:00
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
}