diff options
author | Joas Schilling <213943+nickvergessen@users.noreply.github.com> | 2023-02-22 13:37:54 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-22 13:37:54 +0100 |
commit | 822e1898ee83544c61a72fc59b06809d533c930e (patch) | |
tree | c106ccb9dab8ff2b763cd28b93464452876fb534 | |
parent | 69b43cc0134a4487d58b1eb2f76485a1f5161236 (diff) | |
parent | 84747d40df631aeba406cf3b1c535cf6803a94e0 (diff) |
Merge pull request #8720 from nextcloud/change-recording-status-when-notified-by-recording-server
Change recording status when notified by recording server
32 files changed, 1350 insertions, 74 deletions
diff --git a/appinfo/routes/routesRecordingController.php b/appinfo/routes/routesRecordingController.php index 6d984ad3d..d2d0ad690 100644 --- a/appinfo/routes/routesRecordingController.php +++ b/appinfo/routes/routesRecordingController.php @@ -34,6 +34,8 @@ return [ ['name' => 'Recording#getWelcomeMessage', 'url' => '/api/{apiVersion}/recording/welcome/{serverId}', 'verb' => 'GET', 'requirements' => array_merge($requirements, [ 'serverId' => '\d+', ])], + /** @see \OCA\Talk\Controller\RecordingController::backend() */ + ['name' => 'Recording#backend', 'url' => '/api/{apiVersion}/recording/backend', 'verb' => 'POST', 'requirements' => $requirements], /** @see \OCA\Talk\Controller\RecordingController::start() */ ['name' => 'Recording#start', 'url' => '/api/{apiVersion}/recording/{token}', 'verb' => 'POST', 'requirements' => $requirements], /** @see \OCA\Talk\Controller\RecordingController::stop() */ diff --git a/docs/constants.md b/docs/constants.md index e9d8933bc..f227a894c 100644 --- a/docs/constants.md +++ b/docs/constants.md @@ -111,6 +111,9 @@ title: Constants * `0` - No recording * `1` - Recording video * `2` - Recording audio +* `3` - Starting video recording +* `4` - Starting audio recording +* `5` - Recording failed ## Chat diff --git a/docs/recording.md b/docs/recording.md index 6797d1ea9..bef05eae0 100644 --- a/docs/recording.md +++ b/docs/recording.md @@ -110,3 +110,88 @@ + `400 Bad Request` Error: `system`: Internal system error + `403 Forbidden` When the user is not a moderator/owne + `404 Not Found` Room not found + +## Recording server requests + +* Required capability: `recording-v1` +* Method: `POST` +* Endpoint: `/recording/backend` + +* Header: + +| field | type | Description | +| ------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------- | +| `TALK_RECORDING_RANDOM` | string | Random string that needs to be concatenated with request body to generate the checksum using the secret configured for the backend. | +| `TALK_RECORDING_CHECKSUM` | string | The checksum generated with `TALK_RECORDING_RANDOM`. | + +* Data: + + - Body as a JSON encoded string; format depends on the request type, see below. + +* Response: + - Status code: + + `200 OK` + + `400 Bad Request`: When the body data does not match the expected format. + + `403 Forbidden`: When the request validation failed. + +### Started call recording + +* Data format: + + ```json + { + "type": "started", + "started": { + "token": "the-token-of-the-room", + "status": "the-type-of-recording (see [Constants - Call recording status](constants.md#call-recording-status))", + "actor": { + "type": "the-type-of-the-actor", + "id": "the-id-of-the-actor", + }, + }, + } + ``` + +* Response: + - (Additional) Status code: + + `404 Not Found`: When the room is not found. + +### Stopped call recording + +* Data format: + + ```json + { + "type": "stopped", + "stopped": { + "token": "the-token-of-the-room", + "actor": { + "type": "the-type-of-the-actor", + "id": "the-id-of-the-actor", + }, + }, + } + ``` + + - `actor` is optional + +* Response: + - (Additional) Status code: + + `404 Not Found`: When the room is not found. + +### Failed call recording + +* Data format: + + ```json + { + "type": "failed", + "failed": { + "token": "the-token-of-the-room", + }, + } + ``` + +* Response: + - (Additional) Status code: + + `404 Not Found`: When the room is not found. diff --git a/lib/Activity/Listener.php b/lib/Activity/Listener.php index 52a54725e..e42b63278 100644 --- a/lib/Activity/Listener.php +++ b/lib/Activity/Listener.php @@ -150,8 +150,8 @@ class Listener { return false; } - if ($room->getCallRecording() !== Room::RECORDING_NONE) { - $this->recordingService->stop($room); + if ($room->getCallRecording() !== Room::RECORDING_NONE && $room->getCallRecording() !== Room::RECORDING_FAILED) { + $this->recordingService->stop($room, $actor); } if ($actor instanceof Participant) { $actorId = $actor->getAttendee()->getActorId(); diff --git a/lib/Chat/Parser/SystemMessage.php b/lib/Chat/Parser/SystemMessage.php index 673d7121f..503d722ee 100644 --- a/lib/Chat/Parser/SystemMessage.php +++ b/lib/Chat/Parser/SystemMessage.php @@ -544,6 +544,8 @@ class SystemMessage { if ($currentUserIsActor) { $parsedMessage = $this->l->t('You stopped the audio recording'); } + } elseif ($message === 'recording_failed') { + $parsedMessage = $this->l->t('The recording failed'); } elseif ($message === 'poll_voted') { $parsedParameters['poll'] = $parameters['poll']; $parsedParameters['poll']['id'] = (string) $parsedParameters['poll']['id']; diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php index 9e33a8aca..e54972e22 100644 --- a/lib/Chat/SystemMessage/Listener.php +++ b/lib/Chat/SystemMessage/Listener.php @@ -501,12 +501,23 @@ class Listener implements IEventListener { } public static function setCallRecording(ModifyRoomEvent $event): void { + $recordingHasStarted = in_array($event->getOldValue(), [Room::RECORDING_NONE, Room::RECORDING_VIDEO_STARTING, Room::RECORDING_AUDIO_STARTING, Room::RECORDING_FAILED]) + && in_array($event->getNewValue(), [Room::RECORDING_VIDEO, Room::RECORDING_AUDIO]); + $recordingHasStopped = in_array($event->getOldValue(), [Room::RECORDING_VIDEO, Room::RECORDING_AUDIO]) + && $event->getNewValue() === Room::RECORDING_NONE; + $recordingHasFailed = in_array($event->getOldValue(), [Room::RECORDING_VIDEO, Room::RECORDING_AUDIO]) + && $event->getNewValue() === Room::RECORDING_FAILED; + + if (!$recordingHasStarted && !$recordingHasStopped && !$recordingHasFailed) { + return; + } + $prefix = self::getCallRecordingPrefix($event); $suffix = self::getCallRecordingSuffix($event); $systemMessage = $prefix . 'recording_' . $suffix; $listener = Server::get(self::class); - $listener->sendSystemMessage($event->getRoom(), $systemMessage); + $listener->sendSystemMessage($event->getRoom(), $systemMessage, [], $event->getActor()); } private static function getCallRecordingSuffix(ModifyRoomEvent $event): string { @@ -515,15 +526,20 @@ class Listener implements IEventListener { Room::RECORDING_VIDEO, Room::RECORDING_AUDIO, ]; - $suffix = in_array($newStatus, $startStatus) ? 'started' : 'stopped'; - return $suffix; + if (in_array($newStatus, $startStatus)) { + return 'started'; + } + if ($newStatus === Room::RECORDING_FAILED) { + return 'failed'; + } + return 'stopped'; } private static function getCallRecordingPrefix(ModifyRoomEvent $event): string { $newValue = $event->getNewValue(); $oldValue = $event->getOldValue(); $isAudioStatus = $newValue === Room::RECORDING_AUDIO - || $oldValue === Room::RECORDING_AUDIO; + || ($oldValue === Room::RECORDING_AUDIO && $newValue !== Room::RECORDING_FAILED); return $isAudioStatus ? 'audio_' : ''; } diff --git a/lib/Controller/RecordingController.php b/lib/Controller/RecordingController.php index a79cf2148..1f55bee1d 100644 --- a/lib/Controller/RecordingController.php +++ b/lib/Controller/RecordingController.php @@ -28,7 +28,13 @@ namespace OCA\Talk\Controller; use InvalidArgumentException; use GuzzleHttp\Exception\ConnectException; use OCA\Talk\Config; +use OCA\Talk\Exceptions\ParticipantNotFoundException; +use OCA\Talk\Exceptions\RoomNotFoundException; +use OCA\Talk\Manager; +use OCA\Talk\Room; +use OCA\Talk\Service\ParticipantService; use OCA\Talk\Service\RecordingService; +use OCA\Talk\Service\RoomService; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\Http\Client\IClientService; @@ -42,7 +48,10 @@ class RecordingController extends AEnvironmentAwareController { private ?string $userId, private Config $talkConfig, private IClientService $clientService, + private Manager $manager, + private ParticipantService $participantService, private RecordingService $recordingService, + private RoomService $roomService, private LoggerInterface $logger ) { parent::__construct($appName, $request); @@ -110,12 +119,157 @@ class RecordingController extends AEnvironmentAwareController { } /** + * Return the body of the backend request. This can be overridden in + * tests. + * + * @return string + */ + protected function getInputStream(): string { + return file_get_contents('php://input'); + } + + /** + * Backend API to update recording status by backends. + * + * @PublicPage + * @BruteForceProtection(action=talkRecordingSecret) + * + * @return DataResponse + */ + public function backend(): DataResponse { + $json = $this->getInputStream(); + if (!$this->validateBackendRequest($json)) { + $response = new DataResponse([ + 'type' => 'error', + 'error' => [ + 'code' => 'invalid_request', + 'message' => 'The request could not be authenticated.', + ], + ], Http::STATUS_FORBIDDEN); + $response->throttle(); + return $response; + } + + $message = json_decode($json, true); + switch ($message['type'] ?? '') { + case 'started': + return $this->backendStarted($message['started']); + case 'stopped': + return $this->backendStopped($message['stopped']); + case 'failed': + return $this->backendFailed($message['failed']); + default: + return new DataResponse([ + 'type' => 'error', + 'error' => [ + 'code' => 'unknown_type', + 'message' => 'The given type ' . json_encode($message) . ' is not supported.', + ], + ], Http::STATUS_BAD_REQUEST); + } + } + + private fu |