package voice import ( "context" "fmt" "time" "github.com/livekit/protocol/auth" "github.com/livekit/protocol/livekit" lksdk "github.com/livekit/server-sdk-go/v2" ) type Client struct { apiKey string apiSecret string url string roomClient *lksdk.RoomServiceClient } func NewClient(apiKey, apiSecret, url string) *Client { if apiKey == "" || apiSecret == "" { return nil } roomClient := lksdk.NewRoomServiceClient(url, apiKey, apiSecret) return &Client{ apiKey: apiKey, apiSecret: apiSecret, url: url, roomClient: roomClient, } } func (c *Client) GenerateToken(roomName, participantID, identity string) (string, error) { if c == nil { return "", fmt.Errorf("voice client not configured") } at := auth.NewAccessToken(c.apiKey, c.apiSecret) grant := &auth.VideoGrant{ RoomJoin: true, Room: roomName, CanPublish: boolPtr(true), CanSubscribe: boolPtr(true), } at.SetVideoGrant(grant) at.SetIdentity(identity) at.SetValidFor(time.Hour) token, err := at.ToJWT() if err != nil { return "", fmt.Errorf("generate token: %w", err) } return token, nil } func (c *Client) CreateRoom(name string) (*livekit.Room, error) { if c == nil { return nil, fmt.Errorf("voice client not configured") } room, err := c.roomClient.CreateRoom(context.Background(), &livekit.CreateRoomRequest{ Name: name, EmptyTimeout: 300, // 5 minutes before auto-delete when empty MaxParticipants: 20, }) if err != nil { return nil, fmt.Errorf("create room: %w", err) } return room, nil } func (c *Client) DeleteRoom(name string) error { if c == nil { return fmt.Errorf("voice client not configured") } _, err := c.roomClient.DeleteRoom(context.Background(), &livekit.DeleteRoomRequest{ Room: name, }) return err } func (c *Client) ListParticipants(roomName string) ([]*livekit.ParticipantInfo, error) { if c == nil { return nil, fmt.Errorf("voice client not configured") } resp, err := c.roomClient.ListParticipants(context.Background(), &livekit.ListParticipantsRequest{ Room: roomName, }) if err != nil { return nil, fmt.Errorf("list participants: %w", err) } return resp.Participants, nil } func (c *Client) MuteParticipant(roomName string, identity string) error { if c == nil { return fmt.Errorf("voice client not configured") } participant, err := c.roomClient.GetParticipant(context.Background(), &livekit.RoomParticipantIdentity{ Room: roomName, Identity: identity, }) if err != nil { return fmt.Errorf("get participant: %w", err) } for _, track := range participant.Tracks { _, err := c.roomClient.MutePublishedTrack(context.Background(), &livekit.MuteRoomTrackRequest{ Room: roomName, Identity: identity, TrackSid: track.Sid, Muted: true, }) if err != nil { return fmt.Errorf("mute track %s: %w", track.Sid, err) } } return nil } func boolPtr(b bool) *bool { return &b }