summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/Controller/TextToImageApiController.php14
-rw-r--r--core/ResponseDefinitions.php1
-rw-r--r--core/routes.php2
-rw-r--r--lib/private/TextToImage/Db/Task.php26
-rw-r--r--lib/private/TextToImage/Manager.php28
-rw-r--r--lib/public/TextToImage/IProvider.php4
-rw-r--r--lib/public/TextToImage/Task.php33
7 files changed, 64 insertions, 44 deletions
diff --git a/core/Controller/TextToImageApiController.php b/core/Controller/TextToImageApiController.php
index c7878d7cdc3..aee3a462f5f 100644
--- a/core/Controller/TextToImageApiController.php
+++ b/core/Controller/TextToImageApiController.php
@@ -80,6 +80,7 @@ class TextToImageApiController extends \OCP\AppFramework\OCSController {
* @param string $input Input text
* @param string $appId ID of the app that will execute the task
* @param string $identifier An arbitrary identifier for the task
+ * @param int $numberOfImages The number of images to generate
*
* @return DataResponse<Http::STATUS_OK, array{task: CoreTextToImageTask}, array{}>|DataResponse<Http::STATUS_PRECONDITION_FAILED, array{message: string}, array{}>
*
@@ -89,8 +90,8 @@ class TextToImageApiController extends \OCP\AppFramework\OCSController {
#[PublicPage]
#[UserRateLimit(limit: 20, period: 120)]
#[AnonRateLimit(limit: 5, period: 120)]
- public function schedule(string $input, string $appId, string $identifier = ''): DataResponse {
- $task = new Task($input, $appId, $this->userId, $identifier);
+ public function schedule(string $input, string $appId, string $identifier = '', int $numberOfImages = 8): DataResponse {
+ $task = new Task($input, $appId, $numberOfImages, $this->userId, $identifier);
try {
try {
$this->textToImageManager->runOrScheduleTask($task);
@@ -145,6 +146,7 @@ class TextToImageApiController extends \OCP\AppFramework\OCSController {
* This endpoint allows downloading the resulting image of a task
*
* @param int $id The id of the task
+ * @param int $index The index of the image to retrieve
*
* @return FileDisplayResponse<Http::STATUS_OK, array{'Content-Type': string}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
*
@@ -153,15 +155,17 @@ class TextToImageApiController extends \OCP\AppFramework\OCSController {
*/
#[PublicPage]
#[BruteForceProtection(action: 'text2image')]
- public function getImage(int $id): DataResponse|FileDisplayResponse {
+ public function getImage(int $id, int $index): DataResponse|FileDisplayResponse {
try {
$task = $this->textToImageManager->getUserTask($id, $this->userId);
try {
$folder = $this->appData->getFolder('text2image');
} catch(NotFoundException) {
- $folder = $this->appData->newFolder('text2image');
+ $res = new DataResponse(['message' => $this->l->t('Image not found')], Http::STATUS_NOT_FOUND);
+ $res->throttle(['action' => 'text2image']);
+ return $res;
}
- $file = $folder->getFile((string)$task->getId());
+ $file = $folder->getFolder((string) $task->getId())->getFile((string) $index);
$info = getimagesizefromstring($file->getContent());
return new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => image_type_to_mime_type($info[2])]);
diff --git a/core/ResponseDefinitions.php b/core/ResponseDefinitions.php
index 2548880395a..103d4f84a7f 100644
--- a/core/ResponseDefinitions.php
+++ b/core/ResponseDefinitions.php
@@ -152,6 +152,7 @@ namespace OCA\Core;
* appId: string,
* input: string,
* identifier: ?string,
+ * numberOfImages: int
* }
*/
class ResponseDefinitions {
diff --git a/core/routes.php b/core/routes.php
index a779b130ba2..fe1fe6fcd75 100644
--- a/core/routes.php
+++ b/core/routes.php
@@ -159,7 +159,7 @@ $application->registerRoutes($this, [
['root' => '/text2image', 'name' => 'TextToImageApi#isAvailable', 'url' => '/is_available', 'verb' => 'GET'],
['root' => '/text2image', 'name' => 'TextToImageApi#schedule', 'url' => '/schedule', 'verb' => 'POST'],
['root' => '/text2image', 'name' => 'TextToImageApi#getTask', 'url' => '/task/{id}', 'verb' => 'GET'],
- ['root' => '/text2image', 'name' => 'TextToImageApi#getImage', 'url' => '/task/{id}/image', 'verb' => 'GET'],
+ ['root' => '/text2image', 'name' => 'TextToImageApi#getImage', 'url' => '/task/{id}/image/{index}', 'verb' => 'GET'],
['root' => '/text2image', 'name' => 'TextToImageApi#deleteTask', 'url' => '/task/{id}', 'verb' => 'DELETE'],
['root' => '/text2image', 'name' => 'TextToImageApi#listTasksByApp', 'url' => '/tasks/app/{appId}', 'verb' => 'GET'],
],
diff --git a/lib/private/TextToImage/Db/Task.php b/lib/private/TextToImage/Db/Task.php
index bff827533a5..12818d956c2 100644
--- a/lib/private/TextToImage/Db/Task.php
+++ b/lib/private/TextToImage/Db/Task.php
@@ -27,10 +27,6 @@ namespace OC\TextToImage\Db;
use DateTime;
use OCP\AppFramework\Db\Entity;
-use OCP\Files\AppData\IAppDataFactory;
-use OCP\Files\NotFoundException;
-use OCP\Files\NotPermittedException;
-use OCP\Image;
use OCP\TextToImage\Task as OCPTask;
/**
@@ -48,6 +44,8 @@ use OCP\TextToImage\Task as OCPTask;
* @method string getAppId()
* @method setIdentifier(string $identifier)
* @method string|null getIdentifier()
+ * @method setNumberOfImages(int $numberOfImages)
+ * @method int getNumberOfImages()
*/
class Task extends Entity {
protected $lastUpdated;
@@ -57,16 +55,17 @@ class Task extends Entity {
protected $userId;
protected $appId;
protected $identifier;
+ protected $numberOfImages;
/**
* @var string[]
*/
- public static array $columns = ['id', 'last_updated', 'input', 'status', 'user_id', 'app_id', 'identifier'];
+ public static array $columns = ['id', 'last_updated', 'input', 'status', 'user_id', 'app_id', 'identifier', 'number_of_images'];
/**
* @var string[]
*/
- public static array $fields = ['id', 'lastUpdated', 'input', 'status', 'userId', 'appId', 'identifier'];
+ public static array $fields = ['id', 'lastUpdated', 'input', 'status', 'userId', 'appId', 'identifier', 'numberOfImages'];
public function __construct() {
@@ -78,6 +77,7 @@ class Task extends Entity {
$this->addType('userId', 'string');
$this->addType('appId', 'string');
$this->addType('identifier', 'string');
+ $this->addType('numberOfImages', 'integer');
}
public function toRow(): array {
@@ -92,6 +92,7 @@ class Task extends Entity {
'id' => $task->getId(),
'lastUpdated' => time(),
'status' => $task->getStatus(),
+ 'numberOfImages' => $task->getNumberOfImages(),
'input' => $task->getInput(),
'userId' => $task->getUserId(),
'appId' => $task->getAppId(),
@@ -101,20 +102,9 @@ class Task extends Entity {
}
public function toPublicTask(): OCPTask {
- $task = new OCPTask($this->getInput(), $this->getAppId(), $this->getuserId(), $this->getIdentifier());
+ $task = new OCPTask($this->getInput(), $this->getAppId(), $this->getNumberOfImages(), $this->getuserId(), $this->getIdentifier());
$task->setId($this->getId());
$task->setStatus($this->getStatus());
- $appData = \OC::$server->get(IAppDataFactory::class)->get('core');
- try {
- try {
- $folder = $appData->getFolder('text2image');
- } catch(NotFoundException) {
- $folder = $appData->newFolder('text2image');
- }
- $task->setOutputImage(new Image(base64_encode($folder->getFile((string)$task->getId())->getContent())));
- } catch (NotFoundException|NotPermittedException) {
- // noop
- }
return $task;
}
}
diff --git a/lib/private/TextToImage/Manager.php b/lib/private/TextToImage/Manager.php
index c309b7264e1..a48b202239d 100644
--- a/lib/private/TextToImage/Manager.php
+++ b/lib/private/TextToImage/Manager.php
@@ -139,17 +139,27 @@ class Manager implements IManager {
$this->logger->debug('Creating folder in appdata for Text2Image results');
$folder = $this->appData->newFolder('text2image');
}
- $this->logger->debug('Creating result file for Text2Image task');
- $file = $folder->newFile((string) $task->getId());
- $resource = $file->write();
- if ($resource === false) {
- throw new RuntimeException('Text2Image generation using provider ' . $provider->getName() . ' failed: Couldn\'t open file to write.');
+ try {
+ $folder = $folder->getFolder((string) $task->getId());
+ } catch(NotFoundException) {
+ $this->logger->debug('Creating new folder in appdata Text2Image results folder');
+ $folder = $this->appData->newFolder((string) $task->getId());
+ }
+ $this->logger->debug('Creating result files for Text2Image task');
+ $resources = [];
+ for ($i = 0; $i < $task->getNumberOfImages(); $i++) {
+ $resources[] = $folder->newFile((string) $i)->write();
+ if ($resource[count($resources) - 1] === false) {
+ throw new RuntimeException('Text2Image generation using provider ' . $provider->getName() . ' failed: Couldn\'t open file to write.');
+ }
}
$this->logger->debug('Calling Text2Image provider\'s generate method');
- $provider->generate($task->getInput(), $resource);
- if (is_resource($resource)) {
- // If $resource hasn't been closed yet, we'll do that here
- fclose($resource);
+ $provider->generate($task->getInput(), $resources);
+ for ($i = 0; $i < $task->getNumberOfImages(); $i++) {
+ if (is_resource($resources[$i])) {
+ // If $resource hasn't been closed yet, we'll do that here
+ fclose($resource[$i]);
+ }
}
$task->setStatus(Task::STATUS_SUCCESSFUL);
$this->logger->debug('Updating Text2Image task in DB');
diff --git a/lib/public/TextToImage/IProvider.php b/lib/public/TextToImage/IProvider.php
index 12cf39bb713..789a69ade67 100644
--- a/lib/public/TextToImage/IProvider.php
+++ b/lib/public/TextToImage/IProvider.php
@@ -43,12 +43,12 @@ interface IProvider {
* Processes a text
*
* @param string $prompt The input text
- * @param resource $resource The file resource to write the image to
+ * @param resource[] $resources The file resources to write the images to
* @return void
* @since 28.0.0
* @throws RuntimeException If the text could not be processed
*/
- public function generate(string $prompt, $resource): void;
+ public function generate(string $prompt, array $resources): void;
/**
* The expected runtime for one task with this provider in seconds
diff --git a/lib/public/TextToImage/Task.php b/lib/public/TextToImage/Task.php
index 545bd8bac5a..2f9869bc55a 100644
--- a/lib/public/TextToImage/Task.php
+++ b/lib/public/TextToImage/Task.php
@@ -25,7 +25,11 @@ declare(strict_types=1);
namespace OCP\TextToImage;
+use OCP\Files\AppData\IAppDataFactory;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
use OCP\IImage;
+use OCP\Image;
/**
* This is a text to image task
@@ -35,8 +39,6 @@ use OCP\IImage;
final class Task implements \JsonSerializable {
protected ?int $id = null;
- private ?IImage $image = null;
-
/**
* @since 28.0.0
*/
@@ -66,6 +68,7 @@ final class Task implements \JsonSerializable {
/**
* @param string $input
* @param string $appId
+ * @param int $numberOfImages
* @param string|null $userId
* @param null|string $identifier An arbitrary identifier for this task. max length: 255 chars
* @since 28.0.0
@@ -73,25 +76,36 @@ final class Task implements \JsonSerializable {
final public function __construct(
protected string $input,
protected string $appId,
+ protected int $numberOfImages,
protected ?string $userId,
protected ?string $identifier = '',
) {
}
/**
- * @return IImage|null
+ * @return IImage[]|null
* @since 28.0.0
*/
- final public function getOutputImage(): ?IImage {
- return $this->image;
+ final public function getOutputImages(): ?array {
+ $appData = \OC::$server->get(IAppDataFactory::class)->get('core');
+ try {
+ $folder = $appData->getFolder('text2image')->getFolder((string)$this->getId());
+ $images = [];
+ for ($i = 0; $i < $this->getNumberOfImages(); $i++) {
+ $images[] = new Image(base64_encode($folder->getFile((string) $i)->getContent()));
+ }
+ return $images;
+ } catch (NotFoundException|NotPermittedException) {
+ return null;
+ }
}
/**
- * @param IImage|null $image
+ * @return int
* @since 28.0.0
*/
- final public function setOutputImage(?IImage $image): void {
- $this->image = $image;
+ final public function getNumberOfImages(): int {
+ return $this->numberOfImages;
}
/**
@@ -159,7 +173,7 @@ final class Task implements \JsonSerializable {
}
/**
- * @psalm-return array{id: ?int, status: 0|1|2|3|4, userId: ?string, appId: string, input: string, identifier: ?string}
+ * @psalm-return array{id: ?int, status: 0|1|2|3|4, userId: ?string, appId: string, input: string, identifier: ?string, numberOfImages: int}
* @since 28.0.0
*/
public function jsonSerialize(): array {
@@ -168,6 +182,7 @@ final class Task implements \JsonSerializable {
'status' => $this->getStatus(),
'userId' => $this->getUserId(),
'appId' => $this->getAppId(),
+ 'numberOfImages' => $this->getNumberOfImages(),
'input' => $this->getInput(),
'identifier' => $this->getIdentifier(),
];