Skip to content
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
a8b9a87
Documentation
vitormattos May 5, 2022
1df40ae
Add mocked endpoints
vitormattos May 6, 2022
465bbf0
Add field to room table
vitormattos May 6, 2022
5bdaa16
Implement logic in controller to change the ttl
vitormattos May 9, 2022
b74d06b
Bump app version to run migration
vitormattos May 9, 2022
87fd76e
Add integration tests
vitormattos May 9, 2022
03fb81d
Add job to apply ttl
vitormattos May 13, 2022
3ab61a3
Only set ttl capability if systemcron is enabled
vitormattos May 13, 2022
fa3f98e
Enable to run in drone
vitormattos May 13, 2022
d0cc257
Delete messages when ttl expire and send system message
vitormattos May 17, 2022
05b0808
Method moved and change argument
vitormattos May 17, 2022
2680803
Remove expire job from background job list
vitormattos May 19, 2022
751d18f
Rename ttl to message expire
vitormattos May 23, 2022
ddf59cf
Convert string to ::class
vitormattos May 23, 2022
467cd71
Change default value of backgroundjobs_mode to ajax
vitormattos May 23, 2022
afb8d07
Move deleteExpiredTtl method to ChatManager
vitormattos May 23, 2022
67f49f1
File moved to maintain the pattern "message expire"
vitormattos May 23, 2022
5b6dc78
Use DataResponse and returning 404
vitormattos May 23, 2022
84bdaaf
Replace count by !empty
vitormattos May 23, 2022
e216553
Priorize to run job than send system message
vitormattos May 23, 2022
7a31b9d
Fix tests
vitormattos May 23, 2022
3145bac
Rename time to live to message expire
vitormattos Jun 2, 2022
22a0a7f
Changed to use Nextcloud wrapper to this class
vitormattos Jun 2, 2022
b39f9ae
use DI in the constructor
vitormattos Jun 2, 2022
0c5b047
Set expire time
vitormattos Jun 2, 2022
eb91f78
Removed the system message to sinalize when the message was expired.
vitormattos Jun 2, 2022
7fe6f4a
Moved integration tests to folder of chat tests
vitormattos Jun 2, 2022
6c7d0d3
Rename more ttl to message-expire
vitormattos Jun 2, 2022
7915753
Remove unused namespace
vitormattos Jun 9, 2022
9a5cee6
Add typed argument
vitormattos Jun 9, 2022
0cdf6c0
Fix tests
vitormattos Jun 9, 2022
31c6495
Add method to get message expire time
vitormattos Jun 10, 2022
fac67ee
Parse system message
vitormattos Jun 10, 2022
1f808eb
Expire message using attribute from message
vitormattos Jun 10, 2022
bd9913e
Rename message expire to expire date
vitormattos Jun 13, 2022
68e19e5
Make the error message more clear
vitormattos Jun 13, 2022
545914a
Bump psalm dependencies
vitormattos Jun 27, 2022
47ea1cc
Rename to follow the pattern "-"
vitormattos Jun 30, 2022
7b42dfb
solve conflict
vitormattos Jun 30, 2022
26cb438
Fix date
vitormattos Jul 1, 2022
05e830f
Add system message in chat.md
vitormattos Jul 1, 2022
21134fc
Remove no more used method
vitormattos Jul 1, 2022
5a9ca1b
Replace _ by -
vitormattos Jul 1, 2022
af34125
Rename text
vitormattos Jul 1, 2022
d184f0b
Adjust language handling in the system message
nickvergessen Jul 1, 2022
3c16d95
Rename integration test
nickvergessen Jul 1, 2022
82a0613
Fix event name
nickvergessen Jul 1, 2022
30cd60e
Only remove the job when expiration is "done"
nickvergessen Jul 1, 2022
b89a064
Remove unused property
vitormattos Jul 1, 2022
86080fa
Revert the wrong previous argument rename
vitormattos Jul 1, 2022
9bd7b56
Remove unecessary method
vitormattos Jul 1, 2022
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
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ And in the works for the [coming versions](https://github.com/nextcloud/spreed/m

]]></description>

<version>15.0.0-dev.4</version>
<version>15.0.0-dev.5</version>
<licence>agpl</licence>

<author>Aleksandra Lazarević</author>
Expand Down
2 changes: 2 additions & 0 deletions appinfo/routes/routesRoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,7 @@
['name' => 'Room#setLobby', 'url' => '/api/{apiVersion}/room/{token}/webinar/lobby', 'verb' => 'PUT', 'requirements' => $requirementsWithToken],
/** @see \OCA\Talk\Controller\RoomController::setSIPEnabled() */
['name' => 'Room#setSIPEnabled', 'url' => '/api/{apiVersion}/room/{token}/webinar/sip', 'verb' => 'PUT', 'requirements' => $requirementsWithToken],
/** @see \OCA\Talk\Controller\RoomController::setMessageExpiration() */
['name' => 'Room#setMessageExpiration', 'url' => '/api/{apiVersion}/room/{token}/message-expiration', 'verb' => 'POST', 'requirements' => $requirements],
],
];
10 changes: 5 additions & 5 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions docs/capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ title: Capabilities
* `unified-search` - When the extended attributes of unified search results are there
* `chat-permission` - When permission 128 is required to post chat messages, reaction or share items to the conversation
* `silent-send` - Whether the chat API allows to send chat messages without triggering notifications
* `message-expiration` - Message expiration time for a conversation
* `sip-support-nopin` - Whether SIP can be configured to not require a custom attendee PIN
* `send-call-notification` - When the API allows to resend call notifications for individual users that did not join yet
* `silent-call` - Allow to start calls without sending notification
Expand Down
3 changes: 2 additions & 1 deletion docs/chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,4 +384,5 @@ See [OCP\RichObjectStrings\Definitions](https://github.com/nextcloud/server/blob
* Creating a poll is an `object_shared` with a poll object
* `poll_voted` - {actor} voted on the poll {poll}
* `poll_closed` - {actor} closed the poll {poll}

* `message_expiration_enabled` - {actor} set the message expiration to 3 hours
* `message_expiration_disabled` - {actor} disabled message expiration
19 changes: 19 additions & 0 deletions docs/conversation.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
`participantFlags` | int | v1 | | "In call" flags of the user's session making the request (only available with `in-call-flags` capability)
`readOnly` | int | v1 | | Read-only state for the current user (only available with `read-only-rooms` capability)
`listable` | int | v3 | | Listable scope for the room (only available with `listable-rooms` capability)
`messageExpiration` | int | v4 | | The message expiration time in seconds in this chat. Zero if disabled. (only available with `message-expiration` capability)
`count` | int | v1 | v2 | **Removed:** Count the users on the [Get list of participants in a conversation](participant.md#get-list-of-participants-in-a-conversation) endpoint
`numGuests` | int | v1 | v2 | **Removed:** Count the guests on the [Get list of participants in a conversation](participant.md#get-list-of-participants-in-a-conversation) endpoin
`lastPing` | int | v1 | | Timestamp of the user's session making the request
Expand Down Expand Up @@ -336,6 +337,24 @@
+ `401 Unauthorized` When the participant is a guest
+ `404 Not Found` When the conversation could not be found for the participant

## Set message expiration

* Required capability: `message-expiration`
* Method: `POST`
* Endpoint: `/room/{token}/message-expiration`
* Data:

field | type | Description
---|---|---
`seconds` | int | The messages expiration in seconds. If is zero, messages will not be deleted automatically.

* Response:
- Status code:
+ `200 OK`
+ `400 Bad Request` Invalid value
+ `403 Forbidden` When the current user is not a moderator, owner or guest moderator
+ `404 Not Found` When the conversation could not be found for the participant

## Open a conversation

* Required capability: `listable-rooms`
Expand Down
71 changes: 71 additions & 0 deletions lib/BackgroundJob/ExpireChatMessages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Vitor Mattos <[email protected]>
*
* @author Vitor Mattos <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\Talk\BackgroundJob;

use OCA\Talk\Chat\ChatManager;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJob;
use OCP\BackgroundJob\IJobList;
use OCP\BackgroundJob\TimedJob;

class ExpireChatMessages extends TimedJob {
private IJobList $jobList;
private Manager $roomManager;
private ChatManager $chatManager;

public function __construct(ITimeFactory $timeFactory,
IJobList $jobList,
Manager $roomManager,
ChatManager $chatManager) {
parent::__construct($timeFactory);
$this->jobList = $jobList;
$this->roomManager = $roomManager;
$this->chatManager = $chatManager;

// Every 5 minutes
$this->setInterval(5 * 60);
$this->setTimeSensitivity(IJob::TIME_SENSITIVE);
}

/**
* @param array $argument
*/
protected function run($argument): void {
$this->chatManager->deleteExpiredMessages($argument['room_id']);

try {
$room = $this->roomManager->getRoomById($argument['room_id']);
if ($room->getMessageExpiration() === 0) {
// FIXME check if there are still messages to expire in the database
$this->jobList->remove(ExpireChatMessages::class, $argument);
}
} catch (RoomNotFoundException $e) {
$this->jobList->remove(ExpireChatMessages::class, $argument);
}
}
}
4 changes: 4 additions & 0 deletions lib/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ public function getCapabilities(): array {
'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';
}
Expand Down
21 changes: 21 additions & 0 deletions lib/Chat/ChatManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@

namespace OCA\Talk\Chat;

use DateInterval;
use OC\Memcache\ArrayCache;
use OC\Memcache\NullCache;
use OCA\Talk\Events\ChatEvent;
use OCA\Talk\Events\ChatParticipantEvent;
use OCA\Talk\Manager;
use OCA\Talk\Model\Attendee;
use OCA\Talk\Participant;
use OCA\Talk\Room;
Expand Down Expand Up @@ -84,6 +86,7 @@ class ChatManager {
private IDBConnection $connection;
private INotificationManager $notificationManager;
private IManager $shareManager;
private Manager $manager;
private RoomShareProvider $shareProvider;
private ParticipantService $participantService;
private PollService $pollService;
Expand All @@ -98,6 +101,7 @@ public function __construct(CommentsManager $commentsManager,
IDBConnection $connection,
INotificationManager $notificationManager,
IManager $shareManager,
Manager $manager,
RoomShareProvider $shareProvider,
ParticipantService $participantService,
PollService $pollService,
Expand All @@ -110,6 +114,7 @@ public function __construct(CommentsManager $commentsManager,
$this->connection = $connection;
$this->notificationManager = $notificationManager;
$this->shareManager = $shareManager;
$this->manager = $manager;
$this->shareProvider = $shareProvider;
$this->participantService = $participantService;
$this->pollService = $pollService;
Expand Down Expand Up @@ -258,6 +263,7 @@ public function sendMessage(Room $chat, Participant $participant, string $actorT
if ($referenceId !== '') {
$comment->setReferenceId($referenceId);
}
$this->setMessageExpiration($chat, $comment);

$event = new ChatParticipantEvent($chat, $comment, $participant, $silent);
$this->dispatcher->dispatch(self::EVENT_BEFORE_MESSAGE_SEND, $event);
Expand Down Expand Up @@ -303,6 +309,17 @@ public function sendMessage(Room $chat, Participant $participant, string $actorT
return $comment;
}

private function setMessageExpiration(Room $room, IComment $comment): void {
$messageExpiration = $room->getMessageExpiration();
if (!$messageExpiration) {
return;
}

$dateTime = $this->timeFactory->getDateTime();
$dateTime->add(DateInterval::createFromDateString($messageExpiration . ' seconds'));
$comment->setExpireDate($dateTime);
}

/**
* @param Room $room
* @param Participant $participant
Expand Down Expand Up @@ -693,4 +710,8 @@ private function searchIsPartOfConversationNameOrAtAll(string $search, string $r
}
return false;
}

public function deleteExpiredMessages(int $roomId): void {
$this->commentsManager->deleteMessageExpiredAtObject('chat', (string) $roomId);
}
}
28 changes: 28 additions & 0 deletions lib/Chat/Parser/SystemMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,34 @@ public function parseMessage(Message $chatMessage): void {
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You deleted a reaction');
}
} elseif ($message === 'message_expiration_enabled') {
$weeks = $parameters['seconds'] > (86400 * 7) ? (int) round($parameters['seconds'] / (86400 * 7)) : 0;
$days = $parameters['seconds'] > 86400 ? (int) round($parameters['seconds'] / 86400) : 0;
$hours = $parameters['seconds'] ? (int) round($parameters['seconds'] / 3600) : 0;

$parsedParameters['seconds'] = $parameters['seconds'];
if ($currentUserIsActor) {
if ($weeks > 0) {
$parsedMessage = $this->l->n('You set the message expiration to %n week', 'You set the message expiration to %n weeks', $weeks);
} elseif ($days > 0) {
$parsedMessage = $this->l->n('You set the message expiration to %n day', 'You set the message expiration to %n days', $days);
} else {
$parsedMessage = $this->l->n('You set the message expiration to %n hour', 'You set the message expiration to %n hours', $hours);
}
} else {
if ($weeks > 0) {
$parsedMessage = $this->l->n('{actor} set the message expiration to %n week', '{actor} set the message expiration to %n weeks', $weeks);
} elseif ($days > 0) {
$parsedMessage = $this->l->n('{actor} set the message expiration to %n day', '{actor} set the message expiration to %n days', $days);
} else {
$parsedMessage = $this->l->n('{actor} set the message expiration to %n hour', '{actor} set the message expiration to %n hours', $hours);
}
}
} elseif ($message === 'message_expiration_disabled') {
$parsedMessage = $this->l->t('{actor} disabled message expiration');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You disabled message expiration');
}
} elseif ($message === 'history_cleared') {
$parsedMessage = $this->l->t('{actor} cleared the history of the conversation');
if ($currentUserIsActor) {
Expand Down
14 changes: 14 additions & 0 deletions lib/Controller/RoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ protected function formatRoomV4(Room $room, ?Participant $currentParticipant, ?a
'lastCommonReadMessage' => 0,
'listable' => Room::LISTABLE_NONE,
'callFlag' => Participant::FLAG_DISCONNECTED,
'messageExpiration' => 0,
];

$lastActivity = $room->getLastActivity();
Expand Down Expand Up @@ -466,6 +467,7 @@ protected function formatRoomV4(Room $room, ?Participant $currentParticipant, ?a
'defaultPermissions' => $room->getDefaultPermissions(),
'description' => $room->getDescription(),
'listable' => $room->getListable(),
'messageExpiration' => $this->roomService->getMessageExpiration($room),
]);

if ($currentParticipant->getAttendee()->getReadPrivacy() === Participant::PRIVACY_PUBLIC) {
Expand Down Expand Up @@ -1706,4 +1708,16 @@ public function resendInvitations(?int $attendeeId): DataResponse {
}
return new DataResponse();
}

/**
* @PublicPage
* @RequireModeratorParticipant
*/
public function setMessageExpiration(int $seconds): DataResponse {
if ($seconds < 0) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
$this->roomService->setMessageExpiration($this->room, $this->getParticipant(), $seconds);
return new DataResponse();
}
}
1 change: 1 addition & 0 deletions lib/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ public function createRoomObject(array $row): Room {
(int) $row['type'],
(int) $row['read_only'],
(int) $row['listable'],
(int) $row['message_expiration'],
(int) $row['lobby_state'],
(int) $row['sip_enabled'],
$assignedSignalingServer,
Expand Down
56 changes: 56 additions & 0 deletions lib/Migration/Version15000Date20220506005058.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

/**
* @copyright Copyright (c) 2022 Vitor Mattos <[email protected]>
*
* @author Vitor Mattos <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\Talk\Migration;

use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

class Version15000Date20220506005058 extends SimpleMigrationStep {

/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();

$table = $schema->getTable('talk_rooms');
if (!$table->hasColumn('message_expiration')) {
$table->addColumn('message_expiration', Types::INTEGER, [
'default' => 0,
]);
return $schema;
}
return null;
}
}
1 change: 1 addition & 0 deletions lib/Model/SelectHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public function selectRoomsTable(IQueryBuilder $query, string $alias = 'r'): voi
->addSelect($alias . 'object_type')
->addSelect($alias . 'object_id')
->addSelect($alias . 'listable')
->addSelect($alias . 'message_expiration')
->addSelect($alias . 'remote_server')
->addSelect($alias . 'remote_token')
->selectAlias($alias . 'id', 'r_id');
Expand Down
Loading