mirror of
https://github.com/nextcloud/spreed.git
synced 2025-12-17 21:12:20 +01:00
194 lines
5.4 KiB
PHP
194 lines
5.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
/**
|
|
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
namespace OCA\Talk\Chat;
|
|
|
|
use OCA\Talk\Exceptions\ReactionAlreadyExistsException;
|
|
use OCA\Talk\Exceptions\ReactionNotSupportedException;
|
|
use OCA\Talk\Exceptions\ReactionOutOfContextException;
|
|
use OCA\Talk\Participant;
|
|
use OCA\Talk\ResponseDefinitions;
|
|
use OCA\Talk\Room;
|
|
use OCP\AppFramework\Utility\ITimeFactory;
|
|
use OCP\Comments\IComment;
|
|
use OCP\Comments\NotFoundException;
|
|
use OCP\IL10N;
|
|
use OCP\PreConditionNotMetException;
|
|
|
|
/**
|
|
* @psalm-import-type TalkReaction from ResponseDefinitions
|
|
*/
|
|
class ReactionManager {
|
|
|
|
public function __construct(
|
|
private ChatManager $chatManager,
|
|
private CommentsManager $commentsManager,
|
|
private IL10N $l,
|
|
private MessageParser $messageParser,
|
|
private Notifier $notifier,
|
|
protected ITimeFactory $timeFactory,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Add reaction
|
|
*
|
|
* @param Room $chat
|
|
* @param string $actorType
|
|
* @param string $actorId
|
|
* @param integer $messageId
|
|
* @param string $reaction
|
|
* @return IComment
|
|
* @throws NotFoundException
|
|
* @throws ReactionAlreadyExistsException
|
|
* @throws ReactionNotSupportedException
|
|
* @throws ReactionOutOfContextException
|
|
*/
|
|
public function addReactionMessage(Room $chat, string $actorType, string $actorId, int $messageId, string $reaction): IComment {
|
|
$parentMessage = $this->getCommentToReact($chat, (string) $messageId);
|
|
try {
|
|
// Check if the user already reacted with the same reaction
|
|
$this->commentsManager->getReactionComment(
|
|
(int) $parentMessage->getId(),
|
|
$actorType,
|
|
$actorId,
|
|
$reaction
|
|
);
|
|
throw new ReactionAlreadyExistsException();
|
|
} catch (NotFoundException $e) {
|
|
}
|
|
|
|
$comment = $this->commentsManager->create(
|
|
$actorType,
|
|
$actorId,
|
|
'chat',
|
|
(string) $chat->getId()
|
|
);
|
|
$comment->setParentId($parentMessage->getId());
|
|
$comment->setMessage($reaction);
|
|
$comment->setVerb(ChatManager::VERB_REACTION);
|
|
$this->commentsManager->save($comment);
|
|
|
|
$this->notifier->notifyReacted($chat, $parentMessage, $comment);
|
|
return $comment;
|
|
}
|
|
|
|
/**
|
|
* Delete reaction
|
|
*
|
|
* @param Room $chat
|
|
* @param string $actorType
|
|
* @param string $actorId
|
|
* @param integer $messageId
|
|
* @param string $reaction
|
|
* @return IComment
|
|
* @throws NotFoundException
|
|
* @throws ReactionNotSupportedException
|
|
* @throws ReactionOutOfContextException
|
|
*/
|
|
public function deleteReactionMessage(Room $chat, string $actorType, string $actorId, int $messageId, string $reaction): IComment {
|
|
// Just to verify that messageId is part of the room and throw error if not.
|
|
$parentComment = $this->getCommentToReact($chat, (string) $messageId);
|
|
|
|
$comment = $this->commentsManager->getReactionComment(
|
|
$messageId,
|
|
$actorType,
|
|
$actorId,
|
|
$reaction
|
|
);
|
|
$comment->setMessage(
|
|
json_encode([
|
|
'deleted_by_type' => $actorType,
|
|
'deleted_by_id' => $actorId,
|
|
'deleted_on' => $this->timeFactory->getDateTime()->getTimestamp(),
|
|
])
|
|
);
|
|
$comment->setVerb(ChatManager::VERB_REACTION_DELETED);
|
|
$this->commentsManager->save($comment);
|
|
|
|
$this->chatManager->addSystemMessage(
|
|
$chat,
|
|
$actorType,
|
|
$actorId,
|
|
json_encode(['message' => 'reaction_revoked', 'parameters' => ['message' => (int) $comment->getId()]]),
|
|
$this->timeFactory->getDateTime(),
|
|
false,
|
|
null,
|
|
$parentComment,
|
|
true
|
|
);
|
|
|
|
return $comment;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, TalkReaction[]>
|
|
* @throws PreConditionNotMetException
|
|
*/
|
|
public function retrieveReactionMessages(Room $chat, Participant $participant, int $messageId, ?string $reaction = null): array {
|
|
if ($reaction) {
|
|
$comments = $this->commentsManager->retrieveAllReactionsWithSpecificReaction($messageId, $reaction);
|
|
} else {
|
|
$comments = $this->commentsManager->retrieveAllReactions($messageId);
|
|
}
|
|
|
|
$reactions = [];
|
|
foreach ($comments as $comment) {
|
|
$message = $this->messageParser->createMessage($chat, $participant, $comment, $this->l);
|
|
$this->messageParser->parseMessage($message);
|
|
|
|
$reactions[$comment->getMessage()][] = [
|
|
'actorType' => $comment->getActorType(),
|
|
'actorId' => $comment->getActorId(),
|
|
'actorDisplayName' => $message->getActorDisplayName(),
|
|
'timestamp' => $comment->getCreationDateTime()->getTimestamp(),
|
|
];
|
|
}
|
|
return $reactions;
|
|
}
|
|
|
|
/**
|
|
* @param Participant $participant
|
|
* @param array $messageIds
|
|
* @return array[]
|
|
* @psalm-return array<int, string[]>
|
|
*/
|
|
public function getReactionsByActorForMessages(Participant $participant, array $messageIds): array {
|
|
return $this->commentsManager->retrieveReactionsByActor(
|
|
$participant->getAttendee()->getActorType(),
|
|
$participant->getAttendee()->getActorId(),
|
|
$messageIds
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param Room $chat
|
|
* @param string $messageId
|
|
* @return IComment
|
|
* @throws NotFoundException
|
|
* @throws ReactionNotSupportedException
|
|
* @throws ReactionOutOfContextException
|
|
*/
|
|
public function getCommentToReact(Room $chat, string $messageId): IComment {
|
|
if (!$this->commentsManager->supportReactions()) {
|
|
throw new ReactionNotSupportedException();
|
|
}
|
|
$comment = $this->commentsManager->get($messageId);
|
|
|
|
if ($comment->getObjectType() !== 'chat'
|
|
|| $comment->getObjectId() !== (string) $chat->getId()
|
|
|| !in_array($comment->getVerb(), [
|
|
ChatManager::VERB_MESSAGE,
|
|
ChatManager::VERB_OBJECT_SHARED,
|
|
], true)) {
|
|
throw new ReactionOutOfContextException();
|
|
}
|
|
|
|
return $comment;
|
|
}
|
|
}
|