[ 'allowed', 'folder', ], 'call' => [ 'predefined-backgrounds', 'predefined-backgrounds-v2', 'can-upload-background', 'start-without-media', 'blur-virtual-background', ], 'chat' => [ 'read-privacy', 'has-translation-providers', 'has-translation-task-providers', 'typing-privacy', 'summary-threshold', ], 'conversations' => [ 'can-create', 'list-style', 'description-length', ], 'federation' => [ 'enabled', 'incoming-enabled', 'outgoing-enabled', 'only-trusted-servers', ], 'previews' => [ 'max-gif-size', ], 'signaling' => [ 'session-ping-limit', 'hello-v2-token-key', ], ]; protected ICache $talkCache; public function __construct( protected IConfig $serverConfig, protected Config $talkConfig, protected IAppConfig $appConfig, protected ICommentsManager $commentsManager, protected IUserSession $userSession, protected IAppManager $appManager, protected ITranslationManager $translationManager, protected ITaskProcessingManager $taskProcessingManager, ICacheFactory $cacheFactory, ) { $this->talkCache = $cacheFactory->createLocal('talk::'); } /** * @return array{ * spreed?: TalkCapabilities, * } */ public function getCapabilities(): array { $user = $this->userSession->getUser(); if ($user instanceof IUser && $this->talkConfig->isDisabledForUser($user)) { return []; } $capabilities = [ 'features' => self::FEATURES, 'features-local' => self::LOCAL_FEATURES, 'config' => [ 'attachments' => [ 'allowed' => $user instanceof IUser, // 'folder' => string, ], 'call' => [ 'enabled' => ((int)$this->serverConfig->getAppValue('spreed', 'start_calls', (string)Room::START_CALL_EVERYONE)) !== Room::START_CALL_NOONE, 'breakout-rooms' => $this->talkConfig->isBreakoutRoomsEnabled(), 'recording' => $this->talkConfig->isRecordingEnabled(), 'recording-consent' => $this->talkConfig->recordingConsentRequired(), 'supported-reactions' => ['❤️', '🎉', '👏', '👋', '👍', '👎', '🔥', '😂', '🤩', '🤔', '😲', '😥'], // 'predefined-backgrounds' => list, // 'predefined-backgrounds-v2' => list, 'can-upload-background' => false, 'sip-enabled' => $this->talkConfig->isSIPConfigured(), 'sip-dialout-enabled' => $this->talkConfig->isSIPDialOutEnabled(), 'can-enable-sip' => false, 'start-without-media' => $this->talkConfig->getCallsStartWithoutMedia($user?->getUID()), 'max-duration' => $this->appConfig->getAppValueInt('max_call_duration'), 'blur-virtual-background' => $this->talkConfig->getBlurVirtualBackground($user?->getUID()), 'end-to-end-encryption' => $this->talkConfig->isCallEndToEndEncryptionEnabled(), ], 'chat' => [ 'max-length' => ChatManager::MAX_CHAT_LENGTH, 'read-privacy' => Participant::PRIVACY_PUBLIC, 'has-translation-providers' => $this->translationManager->hasProviders(), 'has-translation-task-providers' => false, 'typing-privacy' => Participant::PRIVACY_PUBLIC, 'summary-threshold' => 100, ], 'conversations' => [ 'can-create' => $user instanceof IUser && !$this->talkConfig->isNotAllowedToCreateConversations($user), 'force-passwords' => $this->talkConfig->isPasswordEnforced(), 'list-style' => $this->talkConfig->getConversationsListStyle($user?->getUID()), 'description-length' => Room::DESCRIPTION_MAXIMUM_LENGTH, ], 'federation' => [ 'enabled' => false, 'incoming-enabled' => false, 'outgoing-enabled' => false, 'only-trusted-servers' => true, ], 'previews' => [ 'max-gif-size' => (int)$this->serverConfig->getAppValue('spreed', 'max-gif-size', '3145728'), ], 'signaling' => [ 'session-ping-limit' => max(0, (int)$this->serverConfig->getAppValue('spreed', 'session-ping-limit', '200')), // 'hello-v2-token-key' => string, ], ], 'config-local' => self::LOCAL_CONFIGS, 'version' => $this->appManager->getAppVersion('spreed'), ]; if ($this->serverConfig->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'cron') { $capabilities['features'][] = 'message-expiration'; } if ($this->commentsManager->supportReactions()) { $capabilities['features'][] = 'reactions'; } if ($user instanceof IUser) { if ($this->talkConfig->isFederationEnabled() && $this->talkConfig->isFederationEnabledForUserId($user)) { $capabilities['config']['federation'] = [ 'enabled' => true, 'incoming-enabled' => $this->appConfig->getAppValueBool('federation_incoming_enabled', true), 'outgoing-enabled' => $this->appConfig->getAppValueBool('federation_outgoing_enabled', true), 'only-trusted-servers' => $this->appConfig->getAppValueBool('federation_only_trusted_servers'), ]; } $capabilities['config']['attachments']['folder'] = $this->talkConfig->getAttachmentFolder($user->getUID()); $capabilities['config']['chat']['read-privacy'] = $this->talkConfig->getUserReadPrivacy($user->getUID()); $capabilities['config']['chat']['typing-privacy'] = $this->talkConfig->getUserTypingPrivacy($user->getUID()); $capabilities['config']['call']['blur-virtual-background'] = $this->talkConfig->getBlurVirtualBackground($user->getUID()); } $pubKey = $this->talkConfig->getSignalingTokenPublicKey(); if ($pubKey) { $capabilities['config']['signaling']['hello-v2-token-key'] = $pubKey; } $includeBrandedBackgrounds = $user instanceof IUser || $this->appConfig->getAppValueBool('backgrounds_branded_for_guests'); $includeDefaultBackgrounds = !$user instanceof IUser || $this->appConfig->getAppValueBool('backgrounds_default_for_users', true); $predefinedBackgrounds = []; $defaultBackgrounds = $this->getBackgroundsFromDirectory(__DIR__ . '/../img/backgrounds', '_default'); if ($includeBrandedBackgrounds) { $predefinedBackgrounds = $this->getBackgroundsFromDirectory(\OC::$SERVERROOT . '/themes/talk-backgrounds', '_branded'); $predefinedBackgrounds = array_map(static fn ($fileName) => '/themes/talk-backgrounds/' . $fileName, $predefinedBackgrounds); } if ($includeDefaultBackgrounds) { $spreedWebPath = $this->appManager->getAppWebPath('spreed'); $prefixedDefaultBackgrounds = array_map(static fn ($fileName) => $spreedWebPath . '/img/backgrounds/' . $fileName, $defaultBackgrounds); $predefinedBackgrounds = array_merge($predefinedBackgrounds, $prefixedDefaultBackgrounds); } $capabilities['config']['call']['predefined-backgrounds'] = $defaultBackgrounds; $capabilities['config']['call']['predefined-backgrounds-v2'] = array_values($predefinedBackgrounds); if ($user instanceof IUser) { $userAllowedToUpload = $this->appConfig->getAppValueBool('backgrounds_upload_users', true); if ($userAllowedToUpload) { $quota = $user->getQuota(); if ($quota !== 'none') { $quota = Util::computerFileSize($quota); } $capabilities['config']['call']['can-upload-background'] = $quota === 'none' || $quota > 0; } $capabilities['config']['call']['can-enable-sip'] = $this->talkConfig->canUserEnableSIP($user); } $supportedTaskTypes = $this->taskProcessingManager->getAvailableTaskTypes(); if (isset($supportedTaskTypes[TextToTextSummary::ID])) { $capabilities['features'][] = 'chat-summary-api'; } if (isset($supportedTaskTypes[TextToTextTranslate::ID])) { $capabilities['config']['chat']['has-translation-task-providers'] = true; } if ($this->talkConfig->getSignalingMode() === Config::SIGNALING_EXTERNAL) { $capabilities['features'][] = 'call-end-to-end-encryption'; } return [ 'spreed' => $capabilities, ]; } /** * @return list */ protected function getBackgroundsFromDirectory(string $directory, string $cacheSuffix): array { $cacheKey = 'predefined_backgrounds' . $cacheSuffix; /** @var ?list $predefinedBackgrounds */ $predefinedBackgrounds = null; $cachedPredefinedBackgrounds = $this->talkCache->get($cacheKey); if ($cachedPredefinedBackgrounds !== null) { // Try using cached value /** @var list|null $predefinedBackgrounds */ $predefinedBackgrounds = json_decode($cachedPredefinedBackgrounds, true); } if (!is_array($predefinedBackgrounds)) { if (file_exists($directory) && is_dir($directory)) { $directoryIterator = new \DirectoryIterator($directory); foreach ($directoryIterator as $file) { if (!$file->isFile()) { continue; } if ($file->isDot()) { continue; } if ($file->getFilename() === 'COPYING') { continue; } $predefinedBackgrounds[] = $file->getFilename(); } sort($predefinedBackgrounds); } $this->talkCache->set($cacheKey, json_encode($predefinedBackgrounds), 300); } return $predefinedBackgrounds ?? []; } }