From 8a3464fea1a183e595a908c8cb972792ae45fa05 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 15 Mar 2023 19:37:39 +0100 Subject: [PATCH] feat(notifications): Expose an attribute whether there is a desktop client handling it Signed-off-by: Joas Schilling --- docs/ocs-endpoint-v2.md | 1 + lib/Controller/EndpointController.php | 78 +++++++++++++++------------ lib/Service/ClientService.php | 44 +++++++++++++++ 3 files changed, 90 insertions(+), 33 deletions(-) create mode 100644 lib/Service/ClientService.php diff --git a/docs/ocs-endpoint-v2.md b/docs/ocs-endpoint-v2.md index 8c94b074..1c679db5 100644 --- a/docs/ocs-endpoint-v2.md +++ b/docs/ocs-endpoint-v2.md @@ -77,6 +77,7 @@ The user needs to be identified/logged in by the server. Then you can just run a "messageRichParameters": [], "link": "http://localhost/index.php/apps/files_sharing/pending", "icon": "http://localhost/img/icon.svg", + "shouldNotify": true, "actions": [ { "label": "Accept", diff --git a/lib/Controller/EndpointController.php b/lib/Controller/EndpointController.php index bc82a7c5..2f83ffe7 100644 --- a/lib/Controller/EndpointController.php +++ b/lib/Controller/EndpointController.php @@ -27,9 +27,11 @@ namespace OCA\Notifications\Controller; use OCA\Notifications\Exceptions\NotificationNotFoundException; use OCA\Notifications\Handler; use OCA\Notifications\Push; +use OCA\Notifications\Service\ClientService; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; +use OCP\AppFramework\Utility\ITimeFactory; use OCP\IRequest; use OCP\IUser; use OCP\IUserSession; @@ -41,35 +43,19 @@ use OCP\UserStatus\IManager as IUserStatusManager; use OCP\UserStatus\IUserStatus; class EndpointController extends OCSController { - /** @var Handler */ - private $handler; - /** @var IManager */ - private $manager; - /** @var IFactory */ - private $l10nFactory; - /** @var IUserSession */ - private $session; - /** @var IUserStatusManager */ - private $userStatusManager; - /** @var Push */ - private $push; - - public function __construct(string $appName, - IRequest $request, - Handler $handler, - IManager $manager, - IFactory $l10nFactory, - IUserSession $session, - IUserStatusManager $userStatusManager, - Push $push) { + public function __construct( + string $appName, + IRequest $request, + protected Handler $handler, + protected IManager $manager, + protected IFactory $l10nFactory, + protected IUserSession $session, + protected ITimeFactory $timeFactory, + protected IUserStatusManager $userStatusManager, + protected ClientService $clientService, + protected Push $push, + ) { parent::__construct($appName, $request); - - $this->handler = $handler; - $this->manager = $manager; - $this->l10nFactory = $l10nFactory; - $this->session = $session; - $this->userStatusManager = $userStatusManager; - $this->push = $push; } /** @@ -96,13 +82,22 @@ class EndpointController extends OCSController { return new DataResponse(null, Http::STATUS_NO_CONTENT, $headers); } + $user = $this->session->getUser(); $filter = $this->manager->createNotification(); $filter->setUser($this->getCurrentUser()); - $language = $this->l10nFactory->getUserLanguage($this->session->getUser()); + $language = $this->l10nFactory->getUserLanguage($user); $notifications = $this->handler->get($filter); $shouldFlush = $this->manager->defer(); + $hasActiveTalkDesktop = false; + if ($user instanceof IUser) { + $hasActiveTalkDesktop = $this->clientService->hasTalkDesktop( + $user->getUID(), + $this->timeFactory->getTime() - ClientService::DESKTOP_CLIENT_TIMEOUT + ); + } + $data = []; $notificationIds = []; foreach ($notifications as $notificationId => $notification) { @@ -115,7 +110,7 @@ class EndpointController extends OCSController { } $notificationIds[] = $notificationId; - $data[] = $this->notificationToArray($notificationId, $notification, $apiVersion); + $data[] = $this->notificationToArray($notificationId, $notification, $apiVersion, $hasActiveTalkDesktop); } if ($shouldFlush) { @@ -153,7 +148,8 @@ class EndpointController extends OCSController { return new DataResponse(null, Http::STATUS_NOT_FOUND); } - $language = $this->l10nFactory->getUserLanguage($this->session->getUser()); + $user = $this->session->getUser(); + $language = $this->l10nFactory->getUserLanguage($user); try { $notification = $this->manager->prepare($notification, $language); @@ -162,7 +158,15 @@ class EndpointController extends OCSController { return new DataResponse(null, Http::STATUS_NOT_FOUND); } - return new DataResponse($this->notificationToArray($id, $notification, $apiVersion)); + $hasActiveTalkDesktop = false; + if ($user instanceof IUser) { + $hasActiveTalkDesktop = $this->clientService->hasTalkDesktop( + $user->getUID(), + $this->timeFactory->getTime() - ClientService::DESKTOP_CLIENT_TIMEOUT + ); + } + + return new DataResponse($this->notificationToArray($id, $notification, $apiVersion, $hasActiveTalkDesktop)); } /** @@ -231,9 +235,10 @@ class EndpointController extends OCSController { * @param int $notificationId * @param INotification $notification * @param string $apiVersion + * @param bool $hasActiveTalkDesktop * @return array */ - protected function notificationToArray(int $notificationId, INotification $notification, string $apiVersion): array { + protected function notificationToArray(int $notificationId, INotification $notification, string $apiVersion, bool $hasActiveTalkDesktop = false): array { $data = [ 'notification_id' => $notificationId, 'app' => $notification->getApp(), @@ -247,12 +252,19 @@ class EndpointController extends OCSController { ]; if ($apiVersion !== 'v1') { + if ($this->request->isUserAgent([IRequest::USER_AGENT_TALK_DESKTOP])) { + $shouldNotify = $notification->getApp() === 'spreed'; + } else { + $shouldNotify = !$hasActiveTalkDesktop || $notification->getApp() !== 'spreed'; + } + $data = array_merge($data, [ 'subjectRich' => $notification->getRichSubject(), 'subjectRichParameters' => $notification->getRichSubjectParameters(), 'messageRich' => $notification->getRichMessage(), 'messageRichParameters' => $notification->getRichMessageParameters(), 'icon' => $notification->getIcon(), + 'shouldNotify' => $shouldNotify, ]); } diff --git a/lib/Service/ClientService.php b/lib/Service/ClientService.php new file mode 100644 index 00000000..bfb34386 --- /dev/null +++ b/lib/Service/ClientService.php @@ -0,0 +1,44 @@ +connection->getQueryBuilder(); + $query->select('name') + ->from('authtoken') + ->where($query->expr()->eq('uid', $query->createNamedParameter($userId))); + + if ($maxAge !== 0) { + $query->andWhere($query->expr()->gte( + 'last_activity', + $query->createNamedParameter($maxAge, IQueryBuilder::PARAM_INT) + )); + } + + $result = $query->executeQuery(); + while ($row = $result->fetch()) { + \OC::$server->getLogger()->error(json_encode($row['name'])); + if (preg_match('/ \(Talk Desktop Client - [A-Za-z ]+\)$/', $row['name'])) { + $result->closeCursor(); + return true; + } + } + $result->closeCursor(); + + return false; + } +}