Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions lib/Controller/PresetController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Talk\Controller;

use OCA\Talk\ResponseDefinitions;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\DataResponse;
use OCP\IRequest;

/**
* @psalm-import-type TalkConversationPreset from ResponseDefinitions
*/
class PresetController extends AEnvironmentAwareOCSController {

public function __construct(
string $appName,
IRequest $request,
) {
parent::__construct($appName, $request);
}

/**
* Get the list of available presets
*
* @return DataResponse<Http::STATUS_OK, list<TalkConversationPreset>, array{}>
*
* 200: Successfully got presets
*/
#[NoAdminRequired]
#[ApiRoute(verb: 'GET', url: '/api/{apiVersion}/preset', requirements: [
'apiVersion' => '(v1)',
'token' => '[a-z0-9]{4,30}',
])]
public function getPresets(): DataResponse {
return new DataResponse([], Http::STATUS_OK);
}
}
82 changes: 46 additions & 36 deletions lib/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
use OCA\Talk\Participant;
use OCA\Talk\ResponseDefinitions;
use OCA\Talk\Room;
use OCA\Talk\RoomPresets\Parameter;
use OCA\Talk\RoomPresets\Preset;
use OCA\Talk\Service\BanService;
use OCA\Talk\Service\BreakoutRoomService;
use OCA\Talk\Service\ChecksumVerificationService;
Expand All @@ -64,6 +66,7 @@
use OCA\Talk\Service\PhoneService;
use OCA\Talk\Service\RecordingService;
use OCA\Talk\Service\RoomFormatter;
use OCA\Talk\Service\RoomPresetService;
use OCA\Talk\Service\RoomService;
use OCA\Talk\Service\SessionService;
use OCA\Talk\Service\ThreadService;
Expand Down Expand Up @@ -153,6 +156,7 @@ public function __construct(
protected IURLGenerator $url,
protected IL10N $l,
protected ThreadService $threadService,
protected RoomPresetService $presetService,
) {
parent::__construct($appName, $request);
}
Expand Down Expand Up @@ -590,37 +594,39 @@ protected function formatRoom(
* In case the `$roomType` is {@see Room::TYPE_ONE_TO_ONE} only the `$invite`
* or `$participants` parameter is supported.
*
* @param int $roomType Type of the room
* @param ?int $roomType Type of the room
* @psalm-param Room::TYPE_* $roomType
* @param string $invite User, group, … ID to invite @deprecated Use the `$participants` array instead
* @param string $roomName Name of the room, unless the legacy mode providing `$invite` and `$source` is used, the name must no longer be empty with the `conversation-creation-all` capability (Ignored if `$roomType` is {@see Room::TYPE_ONE_TO_ONE})
* @param 'groups'|'circles'|'' $source Source of the invite ID ('circles' to create a room with a circle, etc.) @deprecated Use the `$participants` array instead
* @param string $objectType Type of the object (Ignored if `$roomType` is {@see Room::TYPE_ONE_TO_ONE})
* @param string $objectId ID of the object (Ignored if `$roomType` is {@see Room::TYPE_ONE_TO_ONE})
* @param string $password The room password (only available with `conversation-creation-password` capability) (Ignored if `$roomType` is not {@see Room::TYPE_PUBLIC})
* @param 0|1 $readOnly Read only state of the conversation (Default writable) (only available with `conversation-creation-all` capability)
* @psalm-param Room::READ_* $readOnly
* @param 0|1|2 $listable Scope where the conversation is listable (Default not listable for anyone) (only available with `conversation-creation-all` capability)
* @psalm-param Room::LISTABLE_* $listable
* @param int $messageExpiration Seconds after which messages will disappear, 0 disables expiration (Default 0) (only available with `conversation-creation-all` capability)
* @psalm-param non-negative-int $messageExpiration
* @param 0|1 $lobbyState Lobby state of the conversation (Default lobby is disabled) (only available with `conversation-creation-all` capability)
* @psalm-param Webinary::LOBBY_* $lobbyState
* @param 0|1|null $readOnly Read only state of the conversation (Default writable) (only available with `conversation-creation-all` capability)
* @psalm-param ?Room::READ_* $readOnly
* @param 0|1|2|null $listable Scope where the conversation is listable (Default not listable for anyone) (only available with `conversation-creation-all` capability)
* @psalm-param ?Room::LISTABLE_* $listable
* @param ?int $messageExpiration Seconds after which messages will disappear, 0 disables expiration (Default 0) (only available with `conversation-creation-all` capability)
* @psalm-param ?non-negative-int $messageExpiration
* @param 0|1|null $lobbyState Lobby state of the conversation (Default lobby is disabled) (only available with `conversation-creation-all` capability)
* @psalm-param ?Webinary::LOBBY_* $lobbyState
* @param int|null $lobbyTimer Timer when the lobby will be removed (Default null, will not be disabled automatically) (only available with `conversation-creation-all` capability)
* @psalm-param non-negative-int|null $lobbyTimer
* @param 0|1|2 $sipEnabled Whether SIP dial-in shall be enabled (only available with `conversation-creation-all` capability)
* @psalm-param Webinary::SIP_* $sipEnabled
* @param int<0, 255> $permissions Default permissions for participants (only available with `conversation-creation-all` capability)
* @psalm-param int-mask-of<Attendee::PERMISSIONS_*> $permissions
* @param 0|1 $recordingConsent Whether participants need to agree to a recording before joining a call (only available with `conversation-creation-all` capability)
* @psalm-param RecordingService::CONSENT_REQUIRED_NO|RecordingService::CONSENT_REQUIRED_YES $recordingConsent
* @param 0|1 $mentionPermissions Who can mention at-all in the chat (only available with `conversation-creation-all` capability)
* @psalm-param Room::MENTION_PERMISSIONS_* $mentionPermissions
* @psalm-param ?non-negative-int $lobbyTimer
* @param 0|1|2|null $sipEnabled Whether SIP dial-in shall be enabled (only available with `conversation-creation-all` capability)
* @psalm-param ?Webinary::SIP_* $sipEnabled
* @param int<0, 255>|null $permissions Default permissions for participants (only available with `conversation-creation-all` capability)
* @psalm-param ?int-mask-of<Attendee::PERMISSIONS_*> $permissions
* @param 0|1|null $recordingConsent Whether participants need to agree to a recording before joining a call (only available with `conversation-creation-all` capability)
* @psalm-param RecordingService::CONSENT_REQUIRED_NO|RecordingService::CONSENT_REQUIRED_YES|null $recordingConsent
* @param 0|1|null $mentionPermissions Who can mention at-all in the chat (only available with `conversation-creation-all` capability)
* @psalm-param ?Room::MENTION_PERMISSIONS_* $mentionPermissions
* @param string $description Description for the conversation (limited to 2.000 characters) (only available with `conversation-creation-all` capability)
* @param ?non-empty-string $emoji Emoji for the avatar of the conversation (only available with `conversation-creation-all` capability)
* @param ?non-empty-string $avatarColor Background color of the avatar (Only considered when an emoji was provided) (only available with `conversation-creation-all` capability)
* @param array<string, list<string>> $participants List of participants to add grouped by type (only available with `conversation-creation-all` capability)
* @psalm-param TalkInvitationList $participants
* @param 0|1|2|3|null $preset Which preset should be used for not-given (null) parameters (only available with `conversation-preset` capability)
* @psalm-param ?Preset $preset
* @return DataResponse<Http::STATUS_OK|Http::STATUS_CREATED, TalkRoom, array{}>|DataResponse<Http::STATUS_ACCEPTED, TalkRoomWithInvalidInvitations, array{}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, array{error: 'avatar'|'description'|'invite'|'listable'|'lobby'|'lobby-timer'|'mention-permissions'|'message-expiration'|'name'|'object'|'object-id'|'object-type'|'password'|'permissions'|'read-only'|'recording-consent'|'sip-enabled'|'type', message?: string}, array{}>
*
* 200: Room already existed
Expand All @@ -635,26 +641,27 @@ protected function formatRoom(
'apiVersion' => '(v4)',
])]
public function createRoom(
int $roomType = Room::TYPE_GROUP,
?int $roomType = null,
string $invite = '', /* @deprecated */
string $roomName = '',
string $source = '', /* @deprecated */
string $objectType = '',
string $objectId = '',
string $password = '',
int $readOnly = Room::READ_WRITE,
int $listable = Room::LISTABLE_NONE,
int $messageExpiration = 0,
int $lobbyState = Webinary::LOBBY_NONE,
?int $readOnly = null,
?int $listable = null,
?int $messageExpiration = null,
?int $lobbyState = null,
?int $lobbyTimer = null,
int $sipEnabled = Webinary::SIP_DISABLED,
int $permissions = Attendee::PERMISSIONS_DEFAULT,
int $recordingConsent = RecordingService::CONSENT_REQUIRED_NO,
int $mentionPermissions = Room::MENTION_PERMISSIONS_EVERYONE,
?int $sipEnabled = null,
?int $permissions = null,
?int $recordingConsent = null,
?int $mentionPermissions = null,
string $description = '',
?string $emoji = null,
?string $avatarColor = null,
array $participants = [],
?int $preset = null,
): DataResponse {
if ($roomType === Room::TYPE_ONE_TO_ONE) {
if ($invite === ''
Expand Down Expand Up @@ -744,23 +751,26 @@ public function createRoom(
$objectId = Room::OBJECT_ID_PHONE_OUTGOING;
}

$selectedPreset = Preset::from($preset ?? 0);


try {
$room = $this->roomService->createConversation(
$roomType,
$this->presetService->getDefaultForPreset($selectedPreset, Parameter::ROOM_TYPE, $roomType),
$roomName,
$user,
$objectType,
$objectId,
$password,
$readOnly,
$listable,
$messageExpiration,
$lobbyState,
$this->presetService->getDefaultForPreset($selectedPreset, Parameter::READ_ONLY, $readOnly),
$this->presetService->getDefaultForPreset($selectedPreset, Parameter::LISTABLE, $listable),
$this->presetService->getDefaultForPreset($selectedPreset, Parameter::MESSAGE_EXPIRATION, $messageExpiration),
$this->presetService->getDefaultForPreset($selectedPreset, Parameter::LOBBY_STATE, $lobbyState),
$lobbyTimer,
$sipEnabled,
$permissions,
$recordingConsent,
$mentionPermissions,
$this->presetService->getDefaultForPreset($selectedPreset, Parameter::SIP_ENABLED, $sipEnabled),
$this->presetService->getDefaultForPreset($selectedPreset, Parameter::PERMISSIONS, $permissions),
$this->presetService->getDefaultForPreset($selectedPreset, Parameter::RECORDING_CONSENT, $recordingConsent),
$this->presetService->getDefaultForPreset($selectedPreset, Parameter::MENTION_PERMISSIONS, $mentionPermissions),
$description,
$emoji,
$avatarColor,
Expand Down
7 changes: 7 additions & 0 deletions lib/ResponseDefinitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,13 @@
* sendAt: int,
* silent: bool,
* }
*
* @psalm-type TalkConversationPreset = {
* // Identifier of the preset, currently known: default, webinar, presentation, hallway
* id: string,
* // Translated name of the preset in user's language
* name: string,
* }
*/
class ResponseDefinitions {
}
31 changes: 31 additions & 0 deletions lib/RoomPresets/DefaultPreset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Talk\RoomPresets;

use OCA\Talk\Model\Attendee;
use OCA\Talk\Room;
use OCA\Talk\Service\RecordingService;
use OCA\Talk\Webinary;

class DefaultPreset implements IPreset {
#[\Override]
public static function getDefault(Parameter $parameter): int {
return match ($parameter) {
Parameter::ROOM_TYPE => Room::TYPE_GROUP,
Parameter::READ_ONLY => Room::READ_WRITE,
Parameter::LISTABLE => Room::LISTABLE_NONE,
Parameter::MESSAGE_EXPIRATION => 0,
Parameter::LOBBY_STATE => Webinary::LOBBY_NONE,
Parameter::SIP_ENABLED => Webinary::SIP_DISABLED,
Parameter::PERMISSIONS => Attendee::PERMISSIONS_DEFAULT,
Parameter::RECORDING_CONSENT => RecordingService::CONSENT_REQUIRED_NO,
Parameter::MENTION_PERMISSIONS => Room::MENTION_PERMISSIONS_EVERYONE,
};
}
}
24 changes: 24 additions & 0 deletions lib/RoomPresets/Hallway.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Talk\RoomPresets;

use OCA\Talk\Room;

class Hallway implements IPreset {
#[\Override]
public static function getDefault(Parameter $parameter): ?int {
return match ($parameter) {
// Users but no guest users (by default)
Parameter::LISTABLE => Room::LISTABLE_USERS,
// If you were not there, you were not there …
Parameter::MESSAGE_EXPIRATION => 3600,
default => null,
};
}
}
13 changes: 13 additions & 0 deletions lib/RoomPresets/IPreset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Talk\RoomPresets;

interface IPreset {
public static function getDefault(Parameter $parameter): ?int;
}
22 changes: 22 additions & 0 deletions lib/RoomPresets/Parameter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Talk\RoomPresets;


enum Parameter: string {
case ROOM_TYPE = 'roomType';
case READ_ONLY = 'readOnly';
case LISTABLE = 'listable';
case MESSAGE_EXPIRATION = 'messageExpiration';
case LOBBY_STATE = 'lobbyState';
case SIP_ENABLED = 'sipEnabled';
case PERMISSIONS = 'permissions';
case RECORDING_CONSENT = 'recordingConsent';
case MENTION_PERMISSIONS = 'mentionPermissions';
}
27 changes: 27 additions & 0 deletions lib/RoomPresets/Presentation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Talk\RoomPresets;

use OCA\Talk\Model\Attendee;
use OCA\Talk\Room;
use OCA\Talk\Service\RecordingService;

class Presentation implements IPreset {
#[\Override]
public static function getDefault(Parameter $parameter): ?int {
return match ($parameter) {
Parameter::MENTION_PERMISSIONS => Room::MENTION_PERMISSIONS_MODERATORS,
Parameter::PERMISSIONS => Attendee::PERMISSIONS_CUSTOM
| Attendee::PERMISSIONS_CALL_JOIN
| Attendee::PERMISSIONS_CHAT,
Parameter::RECORDING_CONSENT => RecordingService::CONSENT_REQUIRED_YES,
default => null,
};
}
}
17 changes: 17 additions & 0 deletions lib/RoomPresets/Preset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Talk\RoomPresets;


enum Preset: int {
case DEFAULT = 0;
case WEBINAR = 1;
case PRESENTATION = 2;
case HALLWAY = 3;
}
30 changes: 30 additions & 0 deletions lib/RoomPresets/Webinar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Talk\RoomPresets;

use OCA\Talk\Model\Attendee;
use OCA\Talk\Room;
use OCA\Talk\Service\RecordingService;
use OCA\Talk\Webinary;

class Webinar implements IPreset {
#[\Override]
public static function getDefault(Parameter $parameter): ?int {
return match ($parameter) {
Parameter::LOBBY_STATE => Webinary::LOBBY_NON_MODERATORS,
Parameter::MESSAGE_EXPIRATION => Room::MENTION_PERMISSIONS_MODERATORS,
Parameter::PERMISSIONS => Attendee::PERMISSIONS_CUSTOM
| Attendee::PERMISSIONS_CALL_JOIN
| Attendee::PERMISSIONS_CHAT,
Parameter::RECORDING_CONSENT => RecordingService::CONSENT_REQUIRED_YES,
Parameter::ROOM_TYPE => Room::TYPE_PUBLIC,
default => null,
};
}
}
Loading
Loading