diff --git a/lib/Chat/Parser/SystemMessage.php b/lib/Chat/Parser/SystemMessage.php
index b510242cf6a..be9e06ec677 100644
--- a/lib/Chat/Parser/SystemMessage.php
+++ b/lib/Chat/Parser/SystemMessage.php
@@ -143,13 +143,18 @@ protected function parseMessage(Message $chatMessage): void {
$participant->getAttendee()->getActorId() === $parsedParameters['actor']['id'];
}
$cliIsActor = $parsedParameters['actor']['type'] === 'guest' &&
- 'guest/cli' === $parsedParameters['actor']['id'];
+ 'guest/' . Attendee::ACTOR_ID_CLI === $parsedParameters['actor']['id'];
if ($message === 'conversation_created') {
+ $systemIsActor = $parsedParameters['actor']['type'] === 'guest' &&
+ 'guest/' . Attendee::ACTOR_ID_SYSTEM === $parsedParameters['actor']['id'];
+
$parsedMessage = $this->l->t('{actor} created the conversation');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You created the conversation');
- } elseif ($cliIsActor) {
+ } elseif ($systemIsActor) {
+ $parsedMessage = $this->l->t('System created the conversation');
+ }if ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator created the conversation');
}
} elseif ($message === 'conversation_renamed') {
diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php
index 69716b25b63..f671dff8a72 100644
--- a/lib/Chat/SystemMessage/Listener.php
+++ b/lib/Chat/SystemMessage/Listener.php
@@ -45,6 +45,7 @@
use OCA\Talk\Model\Session;
use OCA\Talk\Participant;
use OCA\Talk\Room;
+use OCA\Talk\Service\NoteToSelfService;
use OCA\Talk\Service\ParticipantService;
use OCA\Talk\TalkSession;
use OCA\Talk\Webinary;
@@ -157,7 +158,11 @@ protected function sendSystemMessageAboutCallLeft(ParticipantModifiedEvent $even
}
protected function sendSystemMessageAboutConversationCreated(RoomCreatedEvent $event): void {
- $this->sendSystemMessage($event->getRoom(), 'conversation_created');
+ if ($event->getRoom()->getType() === Room::TYPE_CHANGELOG || $this->isCreatingNoteToSelfAutomatically($event)) {
+ $this->sendSystemMessage($event->getRoom(), 'conversation_created', forceSystemAsActor: true);
+ } else {
+ $this->sendSystemMessage($event->getRoom(), 'conversation_created');
+ }
}
protected function sendSystemMessageAboutConversationRenamed(RoomModifiedEvent $event): void {
@@ -174,6 +179,10 @@ protected function sendSystemMessageAboutConversationRenamed(RoomModifiedEvent $
protected function sendSystemMessageAboutRoomDescriptionChanges(RoomModifiedEvent $event): void {
if ($event->getNewValue() !== '') {
+ if ($this->isCreatingNoteToSelf($event)) {
+ return;
+ }
+
$this->sendSystemMessage($event->getRoom(), 'description_set', [
'newDescription' => $event->getNewValue(),
]);
@@ -253,6 +262,10 @@ protected function addSystemMessageUserAdded(AttendeesAddedEvent $event, Attende
return;
}
+ if ($room->getType() === Room::TYPE_CHANGELOG) {
+ return;
+ }
+
$userJoinedFileRoom = $room->getObjectType() === Room::OBJECT_TYPE_FILE && $attendee->getParticipantType() !== Participant::USER_SELF_JOINED;
// add a message "X joined the conversation", whenever user $userId:
@@ -407,10 +420,13 @@ protected function attendeesRemovedEvent(AttendeesRemovedEvent $event): void {
}
}
- protected function sendSystemMessage(Room $room, string $message, array $parameters = [], Participant $participant = null, bool $shouldSkipLastMessageUpdate = false, bool $silent = false): IComment {
+ protected function sendSystemMessage(Room $room, string $message, array $parameters = [], Participant $participant = null, bool $shouldSkipLastMessageUpdate = false, bool $silent = false, bool $forceSystemAsActor = false): IComment {
if ($participant instanceof Participant) {
$actorType = $participant->getAttendee()->getActorType();
$actorId = $participant->getAttendee()->getActorId();
+ } elseif ($forceSystemAsActor) {
+ $actorType = Attendee::ACTOR_GUESTS;
+ $actorId = Attendee::ACTOR_ID_SYSTEM;
} else {
$user = $this->userSession->getUser();
if ($user instanceof IUser) {
@@ -524,6 +540,10 @@ protected function getCallRecordingPrefix(RoomModifiedEvent $event): string {
protected function avatarChanged(RoomModifiedEvent $event): void {
if ($event->getNewValue()) {
+ if ($this->isCreatingNoteToSelf($event)) {
+ return;
+ }
+
$message = 'avatar_set';
} else {
$message = 'avatar_removed';
@@ -531,4 +551,44 @@ protected function avatarChanged(RoomModifiedEvent $event): void {
$this->sendSystemMessage($event->getRoom(), $message);
}
+
+ protected function isCreatingNoteToSelf(RoomModifiedEvent $event): bool {
+ if ($event->getRoom()->getType() !== Room::TYPE_NOTE_TO_SELF) {
+ return false;
+ }
+
+ $exception = new \Exception();
+ $trace = $exception->getTrace();
+
+ foreach ($trace as $step) {
+ if (isset($step['class']) && $step['class'] === NoteToSelfService::class &&
+ isset($step['function']) && $step['function'] === 'initialCreateNoteToSelfForUser') {
+ return true;
+ }
+ if (isset($step['class']) && $step['class'] === NoteToSelfService::class &&
+ isset($step['function']) && $step['function'] === 'ensureNoteToSelfExistsForUser') {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected function isCreatingNoteToSelfAutomatically(RoomCreatedEvent $event): bool {
+ if ($event->getRoom()->getType() !== Room::TYPE_NOTE_TO_SELF) {
+ return false;
+ }
+
+ $exception = new \Exception();
+ $trace = $exception->getTrace();
+
+ foreach ($trace as $step) {
+ if (isset($step['class']) && $step['class'] === NoteToSelfService::class &&
+ isset($step['function']) && $step['function'] === 'initialCreateNoteToSelfForUser') {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
diff --git a/lib/Model/Attendee.php b/lib/Model/Attendee.php
index 41c27c98da2..0e0f2abd018 100644
--- a/lib/Model/Attendee.php
+++ b/lib/Model/Attendee.php
@@ -79,6 +79,7 @@ class Attendee extends Entity {
// Special actor IDs
public const ACTOR_BOT_PREFIX = 'bot-';
public const ACTOR_ID_CLI = 'cli';
+ public const ACTOR_ID_SYSTEM = 'system';
public const ACTOR_ID_CHANGELOG = 'changelog';
public const PERMISSIONS_DEFAULT = 0;
diff --git a/tests/integration/features/bootstrap/FeatureContext.php b/tests/integration/features/bootstrap/FeatureContext.php
index 30c2ed4f455..d0bfbffe3df 100644
--- a/tests/integration/features/bootstrap/FeatureContext.php
+++ b/tests/integration/features/bootstrap/FeatureContext.php
@@ -171,6 +171,7 @@ public function setUp() {
self::$tokenToIdentifier = [];
self::$sessionIdToUser = [
'cli' => 'cli',
+ 'system' => 'system',
'failed-to-get-session' => 'failed-to-get-session',
];
self::$userToSessionId = [];
@@ -283,24 +284,31 @@ public function userCanFindListedRoomsWithTerm(string $user, string $term, strin
}
/**
- * @Then /^user "([^"]*)" is participant of the following (unordered )?rooms \((v4)\)$/
+ * @Then /^user "([^"]*)" is participant of the following (unordered )?(note-to-self )?rooms \((v4)\)$/
*
* @param string $user
* @param string $shouldOrder
* @param string $apiVersion
* @param TableNode|null $formData
*/
- public function userIsParticipantOfRooms(string $user, string $shouldOrder, string $apiVersion, TableNode $formData = null): void {
+ public function userIsParticipantOfRooms(string $user, string $shouldOrder, string $shouldFilter, string $apiVersion, TableNode $formData = null): void {
$this->setCurrentUser($user);
$this->sendRequest('GET', '/apps/spreed/api/' . $apiVersion . '/room');
$this->assertStatusCode($this->response, 200);
$rooms = $this->getDataFromResponse($this->response);
- $rooms = array_filter($rooms, function ($room) {
- // Filter out "Talk updates" and "Note to self" conversations
- return $room['type'] !== 4 && $room['type'] !== 6;
- });
+ if ($shouldFilter === '') {
+ $rooms = array_filter($rooms, function ($room) {
+ // Filter out "Talk updates" and "Note to self" conversations
+ return $room['type'] !== 4 && $room['type'] !== 6;
+ });
+ } elseif ($shouldFilter === 'note-to-self ') {
+ $rooms = array_filter($rooms, function ($room) {
+ // Filter out "Talk updates" conversations
+ return $room['type'] !== 4;
+ });
+ }
if ($formData === null) {
Assert::assertEmpty($rooms);
@@ -912,6 +920,17 @@ public function userCreatesNoteToSelf(string $user, string $apiVersion): void {
self::$tokenToIdentifier[$response['token']] = $user . '-note-to-self';
}
+ /**
+ * @Then /^user "([^"]*)" reset note-to-self preference$/
+ *
+ * @param string $user
+ */
+ public function userResetNoteToSelfPreference(string $user): void {
+ $this->setCurrentUser($user);
+ $this->sendRequest('DELETE', '/apps/provisioning_api/api/v1/config/users/spreed/note_to_self');
+ $this->assertStatusCode($this->response, 200);
+ }
+
/**
* @Then /^user "([^"]*)" creates room "([^"]*)" with (\d+) \((v4)\)$/
*
diff --git a/tests/integration/features/chat/mentions.feature b/tests/integration/features/chat/mentions.feature
index 77d6de42517..fcff252362e 100644
--- a/tests/integration/features/chat/mentions.feature
+++ b/tests/integration/features/chat/mentions.feature
@@ -627,9 +627,9 @@ Feature: chat/mentions
Scenario: At-all in note-to-self broke the mention parsing
And user "participant1" creates note-to-self (v4)
And user "participant1" sends message "Test @all" to room "participant1-note-to-self" with 201
- And user "participant1" is participant of the following rooms (v4)
-# | id | type | name |
-# | participant1-note-to-self | 6 | Note to self |
+ And user "participant1" is participant of the following note-to-self rooms (v4)
+ | id | type | name |
+ | participant1-note-to-self | 6 | Note to self |
Then user "participant1" sees the following messages in room "participant1-note-to-self" with 200
| room | actorType | actorId | actorDisplayName | message | messageParameters |
| participant1-note-to-self | users | participant1 | participant1-displayname | Test {mention-call1} | "IGNORE" |
diff --git a/tests/integration/features/chat/note-to-self.feature b/tests/integration/features/chat/note-to-self.feature
new file mode 100644
index 00000000000..3e44131ff03
--- /dev/null
+++ b/tests/integration/features/chat/note-to-self.feature
@@ -0,0 +1,24 @@
+Feature: chat/note-to-self
+
+ Background:
+ Given user "participant1" exists
+
+ Scenario: Created manually via the endpoint
+ When user "participant1" reset note-to-self preference
+ When user "participant1" creates note-to-self (v4)
+ And user "participant1" is participant of the following note-to-self rooms (v4)
+ | id | type | name |
+ | participant1-note-to-self | 6 | Note to self |
+ Then user "participant1" sees the following system messages in room "participant1-note-to-self" with 200
+ | room | actorType | actorId | actorDisplayName | message | messageParameters | systemMessage |
+ | participant1-note-to-self | users | participant1 | participant1-displayname | You created the conversation | {"actor":{"type":"user","id":"participant1","name":"participant1-displayname"}} | conversation_created |
+
+
+ Scenario: Created automatically when fetching the room list
+ When user "participant1" reset note-to-self preference
+ And user "participant1" is participant of the following note-to-self rooms (v4)
+ | id | type | name |
+ | Note to self | 6 | Note to self |
+ Then user "participant1" sees the following system messages in room "Note to self" with 200
+ | room | actorType | actorId | actorDisplayName | message | messageParameters | systemMessage |
+ | Note to self | guests | system | | System created the conversation | {"actor":{"type":"guest","id":"guest\/system","name":"Guest"}} | conversation_created |
diff --git a/tests/integration/spreedcheats/lib/AppInfo/Application.php b/tests/integration/spreedcheats/lib/AppInfo/Application.php
index 910c0f0aa19..17636b2f3c4 100644
--- a/tests/integration/spreedcheats/lib/AppInfo/Application.php
+++ b/tests/integration/spreedcheats/lib/AppInfo/Application.php
@@ -23,12 +23,14 @@
namespace OCA\SpreedCheats\AppInfo;
+use OCA\SpreedCheats\PreferenceListener;
use OCA\SpreedCheats\SpeechToText\LoremIpsumSpeechToTextProvider;
use OCA\SpreedCheats\Translation\LoremIpsumTranslationProvider;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
+use OCP\Config\BeforePreferenceDeletedEvent;
class Application extends App implements IBootstrap {
public const APP_ID = 'spreedcheats';
@@ -40,6 +42,7 @@ public function __construct() {
public function register(IRegistrationContext $context): void {
$context->registerSpeechToTextProvider(LoremIpsumSpeechToTextProvider::class);
$context->registerTranslationProvider(LoremIpsumTranslationProvider::class);
+ $context->registerEventListener(BeforePreferenceDeletedEvent::class, PreferenceListener::class);
}
public function boot(IBootContext $context): void {
diff --git a/tests/integration/spreedcheats/lib/PreferenceListener.php b/tests/integration/spreedcheats/lib/PreferenceListener.php
new file mode 100644
index 00000000000..434600ff31e
--- /dev/null
+++ b/tests/integration/spreedcheats/lib/PreferenceListener.php
@@ -0,0 +1,43 @@
+
+ *
+ * @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\SpreedCheats;
+
+use OCP\Config\BeforePreferenceDeletedEvent;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+
+/**
+ * @template-implements IEventListener
+ */
+class PreferenceListener implements IEventListener {
+ public function handle(Event $event): void {
+ if (!$event instanceof BeforePreferenceDeletedEvent) {
+ return;
+ }
+
+ if ($event->getAppId() === 'spreed') {
+ $event->setValid(true);
+ }
+ }
+}