Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions lib/Listener/FileActionTaskSuccessfulListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
namespace OCA\Assistant\Listener;

use OCA\Assistant\Service\NotificationService;
use OCA\Assistant\Service\SystemTagService;
use OCA\Assistant\Service\TaskProcessingService;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\IRootFolder;
use OCP\SystemTag\TagNotFoundException;
use OCP\TaskProcessing\Events\TaskSuccessfulEvent;
use OCP\TaskProcessing\TaskTypes\TextToTextSummary;
use Psr\Log\LoggerInterface;
Expand All @@ -28,6 +30,7 @@ public function __construct(
private NotificationService $notificationService,
private IRootFolder $rootFolder,
private LoggerInterface $logger,
private SystemTagService $systemTagService,
) {
}

Expand Down Expand Up @@ -79,6 +82,11 @@ class_exists('OCP\\TaskProcessing\\TaskTypes\\TextToSpeech')
$targetFile = $sourceFileParent->newFile($targetFileName, $textResult);
$this->logger->debug('FileActionTaskListener wrote file', ['target' => $targetFileName]);
}
try {
$this->systemTagService->assignAiTagToFile((string)$targetFile->getId());
} catch (TagNotFoundException $e) {
$this->logger->warning('FileActionTaskListener could not write AI tag to file', ['target' => $targetFileName, 'exception' => $e]);
}
$this->notificationService->sendFileActionNotification(
$task->getUserId(), $taskTypeId, $task->getId(),
$sourceFileId, $sourceFile->getName(), $userFolder->getRelativePath($sourceFile->getPath()),
Expand Down
10 changes: 9 additions & 1 deletion lib/Listener/NewFileMenuTaskSuccessfulListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@

use OCA\Assistant\Service\AssistantService;
use OCA\Assistant\Service\NotificationService;
use OCA\Assistant\Service\SystemTagService;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\IRootFolder;
use OCP\SystemTag\TagNotFoundException;
use OCP\TaskProcessing\Events\TaskSuccessfulEvent;
use Psr\Log\LoggerInterface;

Expand All @@ -25,6 +27,7 @@ public function __construct(
private AssistantService $assistantService,
private LoggerInterface $logger,
private IRootFolder $rootFolder,
private SystemTagService $systemTagService,
) {
}

Expand All @@ -50,6 +53,11 @@ public function handle(Event $event): void {
$fileId = (int)$task->getOutput()['images'][0];
try {
$targetFile = $this->assistantService->saveNewFileMenuActionFile($task->getUserId(), $task->getId(), $fileId, $directoryId);
try {
$this->systemTagService->assignAiTagToFile((string)$targetFile->getId());
} catch (TagNotFoundException $e) {
$this->logger->warning('NewFileMenuTaskListener could not write AI tag to file', ['target' => $targetFile->getName(), 'exception' => $e]);
}
$userFolder = $this->rootFolder->getUserFolder($task->getUserId());
$directory = $targetFile->getParent();
$this->notificationService->sendNewImageFileNotification(
Expand All @@ -58,7 +66,7 @@ public function handle(Event $event): void {
$targetFile->getId(), $targetFile->getName(), $userFolder->getRelativePath($targetFile->getPath()),
);
} catch (\Exception $e) {
$this->logger->error('TaskSuccessfulListener: Failed to save new file menu action file.', [
$this->logger->error('NewFileMenuTaskListener: Failed to save new file menu action file.', [
'task' => $task->jsonSerialize(),
'exception' => $e,
]);
Expand Down
16 changes: 13 additions & 3 deletions lib/Service/AssistantService.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use OCP\PreConditionNotMetException;
use OCP\Share\IManager as IShareManager;
use OCP\Share\IShare;
use OCP\SystemTag\TagNotFoundException;
use OCP\TaskProcessing\EShapeType;
use OCP\TaskProcessing\Exception\Exception as TaskProcessingException;
use OCP\TaskProcessing\Exception\NotFoundException;
Expand Down Expand Up @@ -89,6 +90,7 @@ public function __construct(
private ITempManager $tempManager,
private IConfig $config,
private IShareManager $shareManager,
private SystemTagService $systemTagService,
) {
$this->informationSources = [
'ask_context_chat' => $this->l10n->t('Context Chat'),
Expand Down Expand Up @@ -540,16 +542,24 @@ private function saveFile(string $userId, int $ocpTaskId, int $fileId): File {
$existingTarget = $assistantDataFolder->get($targetFileName);
if ($existingTarget instanceof File) {
if ($existingTarget->getSize() === $taskOutputFile->getSize()) {
return $existingTarget;
$file = $existingTarget;
} else {
return $assistantDataFolder->newFile($targetFileName, $taskOutputFile->fopen('rb'));
$file = $assistantDataFolder->newFile($targetFileName, $taskOutputFile->fopen('rb'));
}
} else {
throw new Exception('Impossible to copy output file, a directory with this name already exists', Http::STATUS_UNAUTHORIZED);
}
} else {
return $assistantDataFolder->newFile($targetFileName, $taskOutputFile->fopen('rb'));
$file = $assistantDataFolder->newFile($targetFileName, $taskOutputFile->fopen('rb'));
}

try {
$this->systemTagService->assignAiTagToFile((string)$file->getId());
} catch (TagNotFoundException $e) {
$this->logger->warning('Could not write AI tag to file', ['target' => $file->getName(), 'exception' => $e]);
}

return $file;
}

/**
Expand Down
43 changes: 43 additions & 0 deletions lib/Service/SystemTagService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php


declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Assistant\Service;

use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;

class SystemTagService {

public const AI_TAG_NAME = 'Generated using AI';

public function __construct(
private ISystemTagManager $systemTagManager,
private ISystemTagObjectMapper $systemTagObjectMapper,
) {
}

public function getAiTag() {
try {
return $this->systemTagManager->getTag(self::AI_TAG_NAME, true, true);
} catch (TagNotFoundException $e) {
return $this->systemTagManager->createTag(self::AI_TAG_NAME, true, true);
}
}

/**
* @param string $fileId
* @return void
* @throws TagNotFoundException
*/
public function assignAiTagToFile(string $fileId) {
$this->systemTagObjectMapper->assignTags($fileId, 'files', $this->getAiTag()->getId());
Comment on lines +27 to +41
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps the tag can be created in a migration so we're sure it exists and then store the tag's ID in a config. It might be a little better to not create ISystemTag every time or is it not that impactful?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps the tag can be created in a migration so we're sure it exists

can they be deleted by users? If yes, then ignore this review.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes :)

}
}