feat(videochat): implement LiveKit integration for video chat functionality

- Add LiveKit client setup and token generation for room access.
- Implement room management functions including CreateRoom, OpenRoom, ListRooms, and DeleteRoom.
- Introduce participant management with ListParticipants and RemoveParticipant functions.
- Create tests for room and participant management, ensuring proper authentication and authorization.
- Add error handling for LiveKit API interactions.
- Define data structures for room metadata and token responses.
- Implement status endpoint for service availability check.
This commit is contained in:
fabio
2026-09-29 18:45:21 +02:00
parent a051eef991
commit 0fe1bc2292
21 changed files with 1904 additions and 12 deletions

57
videochat/tokens.go Normal file
View File

@@ -0,0 +1,57 @@
package videochat
import (
"context"
"encore.dev/beta/auth"
"encore.dev/beta/errs"
)
type TokenParams struct {
RoomName string `json:"room_name"`
}
type TokenResponse struct {
OwnerID string `json:"owner_id"`
Role string `json:"role"`
ServerURL string `json:"server_url"`
ParticipantToken string `json:"participant_token" encore:"sensitive"`
RoomName string `json:"room_name"`
Identity string `json:"identity"`
ExpiresIn int64 `json:"expires_in"`
}
// CreateToken grants the authenticated user access to an existing room by name.
//
//encore:api auth method=POST path=/videochat/token
func CreateToken(ctx context.Context, p *TokenParams) (*TokenResponse, error) {
uid, ok := auth.UserID()
if !ok {
return nil, &errs.Error{Code: errs.Unauthenticated, Message: "must be logged in"}
}
if err := validateRoomName(p.RoomName); err != nil {
return nil, err
}
client, serverURL, err := liveKitClient()
if err != nil {
return nil, err
}
ctx, cancel := context.WithTimeout(ctx, apiTimeout)
defer cancel()
_, metadata, err := findBroadcast(ctx, client, p.RoomName)
if err != nil {
return nil, err
}
token, err := signJoinToken(secrets.LiveKitAPIKey, secrets.LiveKitAPISecret, string(uid), p.RoomName, metadata.OwnerID == string(uid))
if err != nil {
return nil, errs.WrapCode(err, errs.Internal, "failed to generate LiveKit token")
}
role := "viewer"
if metadata.OwnerID == string(uid) {
role = "owner"
}
return &TokenResponse{OwnerID: metadata.OwnerID, Role: role,
ServerURL: serverURL, ParticipantToken: token, RoomName: p.RoomName,
Identity: string(uid), ExpiresIn: int64(tokenTTL.Seconds()),
}, nil
}