From b5acdd2a4b82814ce27961ed4bb0d16deb9ec7b7 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 23 Sep 2022 13:45:53 +0200 Subject: Add a reference provider for /call/ links Signed-off-by: Joas Schilling --- lib/AppInfo/Application.php | 3 + .../Reference/TalkReferenceProvider.php | 161 +++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 lib/Collaboration/Reference/TalkReferenceProvider.php (limited to 'lib') diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 3e44c14c7..965abbf85 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace OCA\Talk\AppInfo; +use OCA\Talk\Collaboration\Reference\TalkReferenceProvider; use OCP\Util; use OCA\Circles\Events\AddingCircleMemberEvent; use OCA\Circles\Events\CircleDestroyedEvent; @@ -145,6 +146,8 @@ class Application extends App implements IBootstrap { $context->registerProfileLinkAction(TalkAction::class); + $context->registerReferenceProvider(TalkReferenceProvider::class); + $context->registerTalkBackend(TalkBackend::class); } diff --git a/lib/Collaboration/Reference/TalkReferenceProvider.php b/lib/Collaboration/Reference/TalkReferenceProvider.php new file mode 100644 index 000000000..acfa43e74 --- /dev/null +++ b/lib/Collaboration/Reference/TalkReferenceProvider.php @@ -0,0 +1,161 @@ + + * + * @author Joas Schilling + * + * @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 . + */ + + +namespace OCA\Talk\Collaboration\Reference; + +use OCA\Talk\Exceptions\RoomNotFoundException; +use OCA\Talk\Manager; +use OCA\Talk\Room; +use OCP\Collaboration\Reference\IReference; +use OCP\Collaboration\Reference\IReferenceProvider; +use OCP\Collaboration\Reference\Reference; +use OCP\IURLGenerator; + +class TalkReferenceProvider implements IReferenceProvider { + + protected IURLGenerator $urlGenerator; + protected Manager $manager; + protected ?string $userId; + + public function __construct(IURLGenerator $urlGenerator, + Manager $manager, + ?string $userId) { + $this->urlGenerator = $urlGenerator; + $this->manager = $manager; + $this->userId = $userId; + } + + + public function matchReference(string $referenceText): bool { + return $this->getTalkAppLinkToken($referenceText) !== null; + } + + private function getTalkAppLinkToken(string $referenceText): ?string { + $indexPhpUrl = $this->urlGenerator->getAbsoluteURL('/index.php/call/'); + if (str_starts_with($referenceText, $indexPhpUrl)) { + return substr($referenceText, strlen($indexPhpUrl)) ?: null; + } + + $rewriteUrl = $this->urlGenerator->getAbsoluteURL('/call/'); + if (str_starts_with($referenceText, $rewriteUrl)) { + return substr($referenceText, strlen($rewriteUrl)) ?: null; + } + + return null; + } + + /** + * @inheritDoc + */ + public function resolveReference(string $referenceText): ?IReference { + if ($this->matchReference($referenceText)) { + $reference = new Reference($referenceText); + try { + $this->fetchReference($reference); + } catch (RoomNotFoundException $e) { + $reference->setRichObject('call', null); + $reference->setAccessible(false); + } + return $reference; + } + + return null; + } + + /** + * @throws RoomNotFoundException + */ + private function fetchReference(Reference $reference): void { + if ($this->userId === null) { + throw new RoomNotFoundException(); + } + + $token = $this->getTalkAppLinkToken($reference->getId()); + if ($token === null) { + throw new RoomNotFoundException(); + } + + $room = $this->manager->getRoomByToken($token, $this->userId); + + $reference->setTitle($room->getDisplayName($this->userId)); + $reference->setDescription($room->getDescription()); + $reference->setUrl($this->urlGenerator->linkToRouteAbsolute('spreed.Page.showCall', ['token' => $room->getToken()])); + $reference->setImageUrl($this->getRoomIconUrl($room, $this->userId)); + + $reference->setRichObject('call', [ + 'id' => $room->getToken(), + 'name' => $reference->getTitle(), + 'link' => $reference->getUrl(), + 'call-type' => $this->getRoomType($room), + ]); + } + + /** + * @inheritDoc + */ + public function getCachePrefix(string $referenceId): string { + return $this->getTalkAppLinkToken($referenceId) ?? ''; + } + + /** + * @inheritDoc + */ + public function getCacheKey(string $referenceId): ?string { + return $this->userId ?? ''; + } + + protected function getRoomIconUrl(Room $room, string $userId): string { + if ($room->getType() === Room::TYPE_ONE_TO_ONE) { + $participants = json_decode($room->getName(), true); + + foreach ($participants as $p) { + if ($p !== $userId) { + return $this->urlGenerator->linkToRouteAbsolute( + 'core.avatar.getAvatar', + [ + 'userId' => $p, + 'size' => 64, + ] + ); + } + } + } + + return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('spreed', 'changelog.svg')); + } + + protected function getRoomType(Room $room): string { + switch ($room->getType()) { + case Room::TYPE_ONE_TO_ONE: + return 'one2one'; + case Room::TYPE_GROUP: + return 'group'; + case Room::TYPE_PUBLIC: + return 'public'; + default: + return 'unknown'; + } + } +} -- cgit v1.2.3