Skip to content

Commit

Permalink
feat(calls): Allow to enforce a maximum call length
Browse files Browse the repository at this point in the history
Signed-off-by: Joas Schilling <[email protected]>
  • Loading branch information
nickvergessen committed Oct 2, 2024
1 parent 79805c8 commit 59fe55b
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 2 deletions.
3 changes: 2 additions & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* 🌉 **Sync with other chat solutions** With [Matterbridge](https://github.com/42wim/matterbridge/) being integrated in Talk, you can easily sync a lot of other chat solutions to Nextcloud Talk and vice-versa.
]]></description>

<version>21.0.0-dev.1</version>
<version>21.0.0-dev.2</version>
<licence>agpl</licence>

<author>Daniel Calviño Sánchez</author>
Expand Down Expand Up @@ -64,6 +64,7 @@
<job>OCA\Talk\BackgroundJob\CheckTurnCertificate</job>
<job>OCA\Talk\BackgroundJob\ExpireChatMessages</job>
<job>OCA\Talk\BackgroundJob\ExpireSignalingMessage</job>
<job>OCA\Talk\BackgroundJob\MaximumCallDuration</job>
<job>OCA\Talk\BackgroundJob\Reminder</job>
<job>OCA\Talk\BackgroundJob\RemoveEmptyRooms</job>
<job>OCA\Talk\BackgroundJob\ResetAssignedSignalingServer</job>
Expand Down
1 change: 1 addition & 0 deletions docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Legend:
| `bridge_bot_password` | string | | No | | Automatically generated password of the matterbridge bot user profile |
| `default_attachment_folder` | string | `/Talk` | No | | Specify default attachment folder location |
| `start_calls` | int | `0` | Yes | 🖌️ | Who can start a call, see [constants list](constants.md#start-call) |
| `max_call_duration` | int | `0` | No || Maximum duration of a call in seconds, 0 for unlimited |
| `max-gif-size` | int | `3145728` | No | | Maximum file size for clients to render gifs previews with animation |
| `session-ping-limit` | int | `200` | No | | Number of sessions the HPB can ping in a single request |
| `token_entropy` | int | `8` | No | | Length of conversation tokens, can be increased to make tokens harder to guess but reduces readability and dial-in comfort |
Expand Down
57 changes: 57 additions & 0 deletions lib/BackgroundJob/MaximumCallDuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Talk\BackgroundJob;

use OCA\Talk\Manager;
use OCA\Talk\Service\ParticipantService;
use OCA\Talk\Service\RoomService;
use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\TimedJob;

class MaximumCallDuration extends TimedJob {
public function __construct(
private IAppConfig $appConfig,
private Manager $manager,
private RoomService $roomService,
private ParticipantService $participantService,
ITimeFactory $time,
) {
parent::__construct($time);

// Every time the jobs run
$this->setInterval(1);
}

protected function run($argument): void {
$maxCallDuration = $this->appConfig->getAppValueInt('max_call_duration');
if ($maxCallDuration <= 0) {
return;
}

$now = $this->time->getDateTime();
$maxActiveSince = $now->sub(new \DateInterval('PT' . $maxCallDuration . 'S'));
$rooms = $this->manager->getRoomsLongerActiveSince($maxActiveSince);

foreach ($rooms as $room) {
if ($room->isFederatedConversation()) {
continue;
}

$result = $this->roomService->resetActiveSinceInDatabaseOnly($room);
if (!$result) {
// Someone else won the race condition, make sure this user disconnects directly and then return
continue;
}

$this->participantService->endCallForEveryone($room, null);
$this->roomService->resetActiveSinceInModelOnly($room);
}
}
}
22 changes: 22 additions & 0 deletions lib/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,28 @@ public function searchRoomsByToken(string $searchToken = '', ?int $limit = null,
return $rooms;
}

/**
* @return Room[]
*/
public function getRoomsLongerActiveSince(\DateTime $maxActiveSince): array {
$query = $this->db->getQueryBuilder();
$helper = new SelectHelper();
$helper->selectRoomsTable($query);
$query->from('talk_rooms', 'r')
->where($query->expr()->isNotNull('r.active_since'))
->andWhere($query->expr()->lte('r.active_since', $query->createNamedParameter($maxActiveSince, IQueryBuilder::PARAM_DATE)))
->orderBy('r.id', 'ASC');
$result = $query->executeQuery();

$rooms = [];
while ($row = $result->fetch()) {
$rooms[] = $this->createRoomObject($row);
}
$result->closeCursor();

return $rooms;
}

/**
* @param string $userId
* @param array $sessionIds A list of talk sessions to consider for loading (otherwise no session is loaded)
Expand Down
2 changes: 1 addition & 1 deletion lib/Service/ParticipantService.php
Original file line number Diff line number Diff line change
Expand Up @@ -1159,7 +1159,7 @@ public function cleanGuestParticipants(Room $room): void {
$this->resetCallStateWhenNeeded($room);
}

public function endCallForEveryone(Room $room, Participant $moderator): void {
public function endCallForEveryone(Room $room, ?Participant $moderator): void {
$oldActiveSince = $room->getActiveSince();
$event = new BeforeCallEndedForEveryoneEvent($room, $moderator, $oldActiveSince);
$this->dispatcher->dispatchTyped($event);
Expand Down

0 comments on commit 59fe55b

Please sign in to comment.