- Added support for Faster Whisper transcription via Jigasi and Skynet. - Updated .env.example to include new environment variables for transcription settings. - Enhanced Jitsi Docker Compose configuration to include Skynet and Jigasi services. - Introduced new API endpoints for managing organizational folders in the drive service. - Updated Nextcloud initialization script to enable external file mounting. - Improved error handling and response structures in the drive API. - Added new properties for organization settings related to transcription and agenda management.
120 lines
2.4 KiB
Go
120 lines
2.4 KiB
Go
package meet
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
type Config struct {
|
|
AppID string
|
|
AppSecret string
|
|
Domain string
|
|
}
|
|
|
|
type RoomToken struct {
|
|
Token string `json:"token"`
|
|
Room string `json:"room"`
|
|
Domain string `json:"domain"`
|
|
MeetURL string `json:"meet_url"`
|
|
}
|
|
|
|
type UserInfo struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Email string `json:"email"`
|
|
Avatar string `json:"avatar,omitempty"`
|
|
IsMod bool `json:"is_moderator"`
|
|
}
|
|
|
|
// TokenOptions toggles JWT feature flags for Jitsi.
|
|
type TokenOptions struct {
|
|
Transcription bool
|
|
}
|
|
|
|
func NewConfig(appID, appSecret, domain string) *Config {
|
|
return &Config{
|
|
AppID: appID,
|
|
AppSecret: appSecret,
|
|
Domain: domain,
|
|
}
|
|
}
|
|
|
|
func (c *Config) GenerateToken(room string, user *UserInfo, ttl time.Duration, opts TokenOptions) (*RoomToken, error) {
|
|
now := time.Now()
|
|
exp := now.Add(ttl)
|
|
|
|
header := map[string]string{
|
|
"alg": "HS256",
|
|
"typ": "JWT",
|
|
}
|
|
|
|
userCtx := map[string]any{
|
|
"id": user.ID,
|
|
"name": user.Name,
|
|
"email": user.Email,
|
|
"avatar": user.Avatar,
|
|
"moderator": user.IsMod,
|
|
}
|
|
contextPayload := map[string]any{
|
|
"user": userCtx,
|
|
}
|
|
if opts.Transcription {
|
|
contextPayload["features"] = map[string]any{
|
|
"transcription": "true",
|
|
"recording": "false",
|
|
"livestreaming": "false",
|
|
}
|
|
}
|
|
|
|
payload := map[string]any{
|
|
"iss": c.AppID,
|
|
"sub": "meet.jitsi",
|
|
"aud": "ulti",
|
|
"iat": now.Unix(),
|
|
"exp": exp.Unix(),
|
|
"room": room,
|
|
"context": contextPayload,
|
|
}
|
|
|
|
token, err := signJWT(header, payload, c.AppSecret)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &RoomToken{
|
|
Token: token,
|
|
Room: room,
|
|
Domain: "meet.jitsi",
|
|
MeetURL: fmt.Sprintf("https://%s/meet/%s?jwt=%s", c.Domain, room, token),
|
|
}, nil
|
|
}
|
|
|
|
func signJWT(header map[string]string, payload map[string]any, secret string) (string, error) {
|
|
headerJSON, err := json.Marshal(header)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
payloadJSON, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
headerB64 := base64URLEncode(headerJSON)
|
|
payloadB64 := base64URLEncode(payloadJSON)
|
|
signingInput := headerB64 + "." + payloadB64
|
|
|
|
mac := hmac.New(sha256.New, []byte(secret))
|
|
mac.Write([]byte(signingInput))
|
|
signature := base64URLEncode(mac.Sum(nil))
|
|
|
|
return signingInput + "." + signature, nil
|
|
}
|
|
|
|
func base64URLEncode(data []byte) string {
|
|
return base64.RawURLEncoding.EncodeToString(data)
|
|
}
|