- 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.
170 lines
5.8 KiB
Go
170 lines
5.8 KiB
Go
package orgpolicy
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
)
|
|
|
|
// MeetPostActions configures transcript delivery after a meeting.
|
|
type MeetPostActions struct {
|
|
EmailEnabled bool `json:"email_enabled"`
|
|
EmailRecipients string `json:"email_recipients"`
|
|
EmailCustomAddresses string `json:"email_custom_addresses"`
|
|
DriveEnabled bool `json:"drive_enabled"`
|
|
DriveFolderPath string `json:"drive_folder_path"`
|
|
LLMEnabled bool `json:"llm_enabled"`
|
|
LLMProviderID string `json:"llm_provider_id"`
|
|
LLMPrompt string `json:"llm_prompt"`
|
|
LLMThenEmail bool `json:"llm_then_email"`
|
|
LLMThenDrive bool `json:"llm_then_drive"`
|
|
}
|
|
|
|
// MeetPolicy is the organisation UltiMeet / transcription policy.
|
|
type MeetPolicy struct {
|
|
TranscriptionEnabled bool `json:"transcription_enabled"`
|
|
TranscriptionMode string `json:"transcription_mode"`
|
|
TranscriptionEngine string `json:"transcription_engine"`
|
|
SkynetURL string `json:"skynet_url"`
|
|
WhisperModel string `json:"whisper_model"`
|
|
ExternalAPIURL string `json:"external_api_url"`
|
|
ExternalAPIKey string `json:"external_api_key"`
|
|
ExternalAPIProvider string `json:"external_api_provider"`
|
|
AutoStartTranscription bool `json:"auto_start_transcription"`
|
|
PostActions MeetPostActions `json:"post_actions"`
|
|
}
|
|
|
|
// PublicMeetPolicy is exposed to authenticated clients (no secrets).
|
|
type PublicMeetPolicy struct {
|
|
TranscriptionEnabled bool `json:"transcription_enabled"`
|
|
TranscriptionMode string `json:"transcription_mode"`
|
|
AutoStartTranscription bool `json:"auto_start_transcription"`
|
|
}
|
|
|
|
func defaultMeetPolicy() map[string]any {
|
|
return map[string]any{
|
|
"transcription_enabled": false,
|
|
"transcription_mode": "live",
|
|
"transcription_engine": "faster_whisper_local",
|
|
"skynet_url": "http://skynet:8000",
|
|
"whisper_model": "tiny",
|
|
"external_api_url": "",
|
|
"external_api_provider": "openai_compatible",
|
|
"external_api_key": "",
|
|
"auto_start_transcription": false,
|
|
"post_actions": map[string]any{
|
|
"email_enabled": false,
|
|
"email_recipients": "organizer",
|
|
"email_custom_addresses": "",
|
|
"drive_enabled": true,
|
|
"drive_folder_path": "/UltiMeet/Transcripts",
|
|
"llm_enabled": false,
|
|
"llm_provider_id": "",
|
|
"llm_prompt": "Résume cette réunion en français : points clés, décisions et actions à suivre.",
|
|
"llm_then_email": true,
|
|
"llm_then_drive": true,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (l *Loader) MeetPolicy(ctx context.Context) (MeetPolicy, error) {
|
|
var raw []byte
|
|
err := l.db.QueryRow(ctx, `
|
|
SELECT settings FROM org_settings WHERE id = $1
|
|
`, orgSettingsSingletonID).Scan(&raw)
|
|
if err != nil && err != pgx.ErrNoRows {
|
|
return MeetPolicy{}, err
|
|
}
|
|
|
|
stored := map[string]any{}
|
|
if len(raw) > 0 {
|
|
if err := json.Unmarshal(raw, &stored); err != nil {
|
|
return MeetPolicy{}, err
|
|
}
|
|
}
|
|
|
|
meet, _ := stored["meet"].(map[string]any)
|
|
if meet == nil {
|
|
meet = defaultMeetPolicy()
|
|
}
|
|
|
|
postRaw, _ := meet["post_actions"].(map[string]any)
|
|
if postRaw == nil {
|
|
postRaw, _ = defaultMeetPolicy()["post_actions"].(map[string]any)
|
|
}
|
|
|
|
mode, _ := meet["transcription_mode"].(string)
|
|
if mode == "" {
|
|
mode = "live"
|
|
}
|
|
engine, _ := meet["transcription_engine"].(string)
|
|
if engine == "" {
|
|
engine = "faster_whisper_local"
|
|
}
|
|
skynetURL, _ := meet["skynet_url"].(string)
|
|
if skynetURL == "" {
|
|
skynetURL = "http://skynet:8000"
|
|
}
|
|
whisperModel, _ := meet["whisper_model"].(string)
|
|
if whisperModel == "" {
|
|
whisperModel = "tiny"
|
|
}
|
|
provider, _ := meet["external_api_provider"].(string)
|
|
if provider == "" {
|
|
provider = "openai_compatible"
|
|
}
|
|
driveFolder, _ := postRaw["drive_folder_path"].(string)
|
|
if driveFolder == "" {
|
|
driveFolder = "/UltiMeet/Transcripts"
|
|
}
|
|
emailRecipients, _ := postRaw["email_recipients"].(string)
|
|
if emailRecipients == "" {
|
|
emailRecipients = "organizer"
|
|
}
|
|
llmPrompt, _ := postRaw["llm_prompt"].(string)
|
|
if llmPrompt == "" {
|
|
llmPrompt = "Résume cette réunion en français : points clés, décisions et actions à suivre."
|
|
}
|
|
|
|
return MeetPolicy{
|
|
TranscriptionEnabled: boolField(meet, "transcription_enabled"),
|
|
TranscriptionMode: mode,
|
|
TranscriptionEngine: engine,
|
|
SkynetURL: skynetURL,
|
|
WhisperModel: whisperModel,
|
|
ExternalAPIURL: stringValue(meet["external_api_url"]),
|
|
ExternalAPIKey: stringValue(meet["external_api_key"]),
|
|
ExternalAPIProvider: provider,
|
|
AutoStartTranscription: boolField(meet, "auto_start_transcription"),
|
|
PostActions: MeetPostActions{
|
|
EmailEnabled: boolField(postRaw, "email_enabled"),
|
|
EmailRecipients: emailRecipients,
|
|
EmailCustomAddresses: stringValue(postRaw["email_custom_addresses"]),
|
|
DriveEnabled: boolField(postRaw, "drive_enabled"),
|
|
DriveFolderPath: driveFolder,
|
|
LLMEnabled: boolField(postRaw, "llm_enabled"),
|
|
LLMProviderID: stringValue(postRaw["llm_provider_id"]),
|
|
LLMPrompt: llmPrompt,
|
|
LLMThenEmail: boolField(postRaw, "llm_then_email"),
|
|
LLMThenDrive: boolField(postRaw, "llm_then_drive"),
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (l *Loader) PublicMeetPolicy(ctx context.Context) (PublicMeetPolicy, error) {
|
|
policy, err := l.MeetPolicy(ctx)
|
|
if err != nil {
|
|
return PublicMeetPolicy{}, err
|
|
}
|
|
return PublicMeetPolicy{
|
|
TranscriptionEnabled: policy.TranscriptionEnabled,
|
|
TranscriptionMode: policy.TranscriptionMode,
|
|
AutoStartTranscription: policy.AutoStartTranscription,
|
|
}, nil
|
|
}
|
|
|
|
func (p MeetPolicy) LiveTranscriptionJWT() bool {
|
|
return p.TranscriptionEnabled && p.TranscriptionMode == "live"
|
|
}
|