Completed
Push — master ( 75407a...975524 )
by Joas
24:00
created
lib/public/TaskProcessing/EShapeType.php 1 patch
Indentation   +170 added lines, -170 removed lines patch added patch discarded remove patch
@@ -17,181 +17,181 @@
 block discarded – undo
17 17
  * @since 30.0.0
18 18
  */
19 19
 enum EShapeType: int {
20
-	case Number = 0;
21
-	case Text = 1;
22
-	case Image = 2;
23
-	case Audio = 3;
24
-	case Video = 4;
25
-	case File = 5;
26
-	case Enum = 6;
27
-	case ListOfNumbers = 10;
28
-	case ListOfTexts = 11;
29
-	case ListOfImages = 12;
30
-	case ListOfAudios = 13;
31
-	case ListOfVideos = 14;
32
-	case ListOfFiles = 15;
20
+    case Number = 0;
21
+    case Text = 1;
22
+    case Image = 2;
23
+    case Audio = 3;
24
+    case Video = 4;
25
+    case File = 5;
26
+    case Enum = 6;
27
+    case ListOfNumbers = 10;
28
+    case ListOfTexts = 11;
29
+    case ListOfImages = 12;
30
+    case ListOfAudios = 13;
31
+    case ListOfVideos = 14;
32
+    case ListOfFiles = 15;
33 33
 
34
-	/**
35
-	 * @param mixed $value
36
-	 * @param ShapeEnumValue[] $enumValues
37
-	 * @return void
38
-	 * @throws ValidationException
39
-	 * @since 30.0.0
40
-	 */
41
-	public function validateEnum(mixed $value, array $enumValues): void {
42
-		if ($this !== EShapeType::Enum) {
43
-			throw new ValidationException('Provider provided enum values for non-enum slot');
44
-		}
45
-		foreach ($enumValues as $enumValue) {
46
-			if ($value === $enumValue->getValue()) {
47
-				return;
48
-			}
49
-		}
50
-		throw new ValidationException('Wrong value given for Enum slot. Got "' . $value . '", but expected one of the provided enum values: "' . implode('", "', array_map(fn ($enumValue) => $enumValue->getValue(), $enumValues)) . '"');
51
-	}
34
+    /**
35
+     * @param mixed $value
36
+     * @param ShapeEnumValue[] $enumValues
37
+     * @return void
38
+     * @throws ValidationException
39
+     * @since 30.0.0
40
+     */
41
+    public function validateEnum(mixed $value, array $enumValues): void {
42
+        if ($this !== EShapeType::Enum) {
43
+            throw new ValidationException('Provider provided enum values for non-enum slot');
44
+        }
45
+        foreach ($enumValues as $enumValue) {
46
+            if ($value === $enumValue->getValue()) {
47
+                return;
48
+            }
49
+        }
50
+        throw new ValidationException('Wrong value given for Enum slot. Got "' . $value . '", but expected one of the provided enum values: "' . implode('", "', array_map(fn ($enumValue) => $enumValue->getValue(), $enumValues)) . '"');
51
+    }
52 52
 
53
-	/**
54
-	 * @param mixed $value
55
-	 * @return void
56
-	 * @throws ValidationException
57
-	 * @since 30.0.0
58
-	 */
59
-	private function validateNonFileType(mixed $value): void {
60
-		if ($this === EShapeType::Enum && !is_string($value)) {
61
-			throw new ValidationException('Non-text item provided for Enum slot');
62
-		}
63
-		if ($this === EShapeType::Text && !is_string($value)) {
64
-			throw new ValidationException('Non-text item provided for Text slot');
65
-		}
66
-		if ($this === EShapeType::ListOfTexts && (!is_array($value) || count(array_filter($value, fn ($item) => !is_string($item))) > 0)) {
67
-			throw new ValidationException('Non-text list item provided for ListOfTexts slot');
68
-		}
69
-		if ($this === EShapeType::Number && !is_numeric($value)) {
70
-			throw new ValidationException('Non-numeric item provided for Number slot');
71
-		}
72
-		if ($this === EShapeType::ListOfNumbers && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
73
-			throw new ValidationException('Non-numeric list item provided for ListOfNumbers slot');
74
-		}
75
-	}
53
+    /**
54
+     * @param mixed $value
55
+     * @return void
56
+     * @throws ValidationException
57
+     * @since 30.0.0
58
+     */
59
+    private function validateNonFileType(mixed $value): void {
60
+        if ($this === EShapeType::Enum && !is_string($value)) {
61
+            throw new ValidationException('Non-text item provided for Enum slot');
62
+        }
63
+        if ($this === EShapeType::Text && !is_string($value)) {
64
+            throw new ValidationException('Non-text item provided for Text slot');
65
+        }
66
+        if ($this === EShapeType::ListOfTexts && (!is_array($value) || count(array_filter($value, fn ($item) => !is_string($item))) > 0)) {
67
+            throw new ValidationException('Non-text list item provided for ListOfTexts slot');
68
+        }
69
+        if ($this === EShapeType::Number && !is_numeric($value)) {
70
+            throw new ValidationException('Non-numeric item provided for Number slot');
71
+        }
72
+        if ($this === EShapeType::ListOfNumbers && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
73
+            throw new ValidationException('Non-numeric list item provided for ListOfNumbers slot');
74
+        }
75
+    }
76 76
 
77
-	/**
78
-	 * @param mixed $value
79
-	 * @return void
80
-	 * @throws Exception\ValidationException
81
-	 * @since 30.0.0
82
-	 */
83
-	public function validateInput(mixed $value): void {
84
-		$this->validateNonFileType($value);
85
-		if ($this === EShapeType::Text && is_string($value) && strlen($value) > 64_000) {
86
-			throw new ValidationException('Text is too long');
87
-		}
88
-		if ($this === EShapeType::Image && !is_numeric($value)) {
89
-			throw new ValidationException('Non-image item provided for Image slot');
90
-		}
91
-		if ($this === EShapeType::ListOfImages && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
92
-			throw new ValidationException('Non-image list item provided for ListOfImages slot');
93
-		}
94
-		if ($this === EShapeType::Audio && !is_numeric($value)) {
95
-			throw new ValidationException('Non-audio item provided for Audio slot');
96
-		}
97
-		if ($this === EShapeType::ListOfAudios && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
98
-			throw new ValidationException('Non-audio list item provided for ListOfAudio slot');
99
-		}
100
-		if ($this === EShapeType::Video && !is_numeric($value)) {
101
-			throw new ValidationException('Non-video item provided for Video slot');
102
-		}
103
-		if ($this === EShapeType::ListOfVideos && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
104
-			throw new ValidationException('Non-video list item provided for ListOfTexts slot');
105
-		}
106
-		if ($this === EShapeType::File && !is_numeric($value)) {
107
-			throw new ValidationException('Non-file item provided for File slot');
108
-		}
109
-		if ($this === EShapeType::ListOfFiles && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
110
-			throw new ValidationException('Non-audio list item provided for ListOfFiles slot');
111
-		}
112
-	}
77
+    /**
78
+     * @param mixed $value
79
+     * @return void
80
+     * @throws Exception\ValidationException
81
+     * @since 30.0.0
82
+     */
83
+    public function validateInput(mixed $value): void {
84
+        $this->validateNonFileType($value);
85
+        if ($this === EShapeType::Text && is_string($value) && strlen($value) > 64_000) {
86
+            throw new ValidationException('Text is too long');
87
+        }
88
+        if ($this === EShapeType::Image && !is_numeric($value)) {
89
+            throw new ValidationException('Non-image item provided for Image slot');
90
+        }
91
+        if ($this === EShapeType::ListOfImages && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
92
+            throw new ValidationException('Non-image list item provided for ListOfImages slot');
93
+        }
94
+        if ($this === EShapeType::Audio && !is_numeric($value)) {
95
+            throw new ValidationException('Non-audio item provided for Audio slot');
96
+        }
97
+        if ($this === EShapeType::ListOfAudios && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
98
+            throw new ValidationException('Non-audio list item provided for ListOfAudio slot');
99
+        }
100
+        if ($this === EShapeType::Video && !is_numeric($value)) {
101
+            throw new ValidationException('Non-video item provided for Video slot');
102
+        }
103
+        if ($this === EShapeType::ListOfVideos && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
104
+            throw new ValidationException('Non-video list item provided for ListOfTexts slot');
105
+        }
106
+        if ($this === EShapeType::File && !is_numeric($value)) {
107
+            throw new ValidationException('Non-file item provided for File slot');
108
+        }
109
+        if ($this === EShapeType::ListOfFiles && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
110
+            throw new ValidationException('Non-audio list item provided for ListOfFiles slot');
111
+        }
112
+    }
113 113
 
114
-	/**
115
-	 * @throws ValidationException
116
-	 * @since 30.0.0
117
-	 */
118
-	public function validateOutputWithFileData(mixed $value): void {
119
-		$this->validateNonFileType($value);
120
-		if ($this === EShapeType::Image && !is_string($value)) {
121
-			throw new ValidationException('Non-image item provided for Image slot');
122
-		}
123
-		if ($this === EShapeType::ListOfImages && (!is_array($value) || count(array_filter($value, fn ($item) => !is_string($item))) > 0)) {
124
-			throw new ValidationException('Non-image list item provided for ListOfImages slot');
125
-		}
126
-		if ($this === EShapeType::Audio && !is_string($value)) {
127
-			throw new ValidationException('Non-audio item provided for Audio slot');
128
-		}
129
-		if ($this === EShapeType::ListOfAudios && (!is_array($value) || count(array_filter($value, fn ($item) => !is_string($item))) > 0)) {
130
-			throw new ValidationException('Non-audio list item provided for ListOfAudio slot');
131
-		}
132
-		if ($this === EShapeType::Video && !is_string($value)) {
133
-			throw new ValidationException('Non-video item provided for Video slot');
134
-		}
135
-		if ($this === EShapeType::ListOfVideos && (!is_array($value) || count(array_filter($value, fn ($item) => !is_string($item))) > 0)) {
136
-			throw new ValidationException('Non-video list item provided for ListOfTexts slot');
137
-		}
138
-		if ($this === EShapeType::File && !is_string($value)) {
139
-			throw new ValidationException('Non-file item provided for File slot');
140
-		}
141
-		if ($this === EShapeType::ListOfFiles && (!is_array($value) || count(array_filter($value, fn ($item) => !is_string($item))) > 0)) {
142
-			throw new ValidationException('Non-audio list item provided for ListOfFiles slot');
143
-		}
144
-	}
114
+    /**
115
+     * @throws ValidationException
116
+     * @since 30.0.0
117
+     */
118
+    public function validateOutputWithFileData(mixed $value): void {
119
+        $this->validateNonFileType($value);
120
+        if ($this === EShapeType::Image && !is_string($value)) {
121
+            throw new ValidationException('Non-image item provided for Image slot');
122
+        }
123
+        if ($this === EShapeType::ListOfImages && (!is_array($value) || count(array_filter($value, fn ($item) => !is_string($item))) > 0)) {
124
+            throw new ValidationException('Non-image list item provided for ListOfImages slot');
125
+        }
126
+        if ($this === EShapeType::Audio && !is_string($value)) {
127
+            throw new ValidationException('Non-audio item provided for Audio slot');
128
+        }
129
+        if ($this === EShapeType::ListOfAudios && (!is_array($value) || count(array_filter($value, fn ($item) => !is_string($item))) > 0)) {
130
+            throw new ValidationException('Non-audio list item provided for ListOfAudio slot');
131
+        }
132
+        if ($this === EShapeType::Video && !is_string($value)) {
133
+            throw new ValidationException('Non-video item provided for Video slot');
134
+        }
135
+        if ($this === EShapeType::ListOfVideos && (!is_array($value) || count(array_filter($value, fn ($item) => !is_string($item))) > 0)) {
136
+            throw new ValidationException('Non-video list item provided for ListOfTexts slot');
137
+        }
138
+        if ($this === EShapeType::File && !is_string($value)) {
139
+            throw new ValidationException('Non-file item provided for File slot');
140
+        }
141
+        if ($this === EShapeType::ListOfFiles && (!is_array($value) || count(array_filter($value, fn ($item) => !is_string($item))) > 0)) {
142
+            throw new ValidationException('Non-audio list item provided for ListOfFiles slot');
143
+        }
144
+    }
145 145
 
146
-	/**
147
-	 * @param mixed $value
148
-	 * @return void
149
-	 * @throws ValidationException
150
-	 * @since 30.0.0
151
-	 */
152
-	public function validateOutputWithFileIds(mixed $value): void {
153
-		$this->validateNonFileType($value);
154
-		if ($this === EShapeType::Image && !is_numeric($value)) {
155
-			throw new ValidationException('Non-image item provided for Image slot');
156
-		}
157
-		if ($this === EShapeType::ListOfImages && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
158
-			throw new ValidationException('Non-image list item provided for ListOfImages slot');
159
-		}
160
-		if ($this === EShapeType::Audio && !is_numeric($value)) {
161
-			throw new ValidationException('Non-audio item provided for Audio slot');
162
-		}
163
-		if ($this === EShapeType::ListOfAudios && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
164
-			throw new ValidationException('Non-audio list item provided for ListOfAudio slot');
165
-		}
166
-		if ($this === EShapeType::Video && !is_numeric($value)) {
167
-			throw new ValidationException('Non-video item provided for Video slot');
168
-		}
169
-		if ($this === EShapeType::ListOfVideos && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
170
-			throw new ValidationException('Non-video list item provided for ListOfTexts slot');
171
-		}
172
-		if ($this === EShapeType::File && !is_numeric($value)) {
173
-			throw new ValidationException('Non-file item provided for File slot');
174
-		}
175
-		if ($this === EShapeType::ListOfFiles && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
176
-			throw new ValidationException('Non-audio list item provided for ListOfFiles slot');
177
-		}
178
-	}
146
+    /**
147
+     * @param mixed $value
148
+     * @return void
149
+     * @throws ValidationException
150
+     * @since 30.0.0
151
+     */
152
+    public function validateOutputWithFileIds(mixed $value): void {
153
+        $this->validateNonFileType($value);
154
+        if ($this === EShapeType::Image && !is_numeric($value)) {
155
+            throw new ValidationException('Non-image item provided for Image slot');
156
+        }
157
+        if ($this === EShapeType::ListOfImages && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
158
+            throw new ValidationException('Non-image list item provided for ListOfImages slot');
159
+        }
160
+        if ($this === EShapeType::Audio && !is_numeric($value)) {
161
+            throw new ValidationException('Non-audio item provided for Audio slot');
162
+        }
163
+        if ($this === EShapeType::ListOfAudios && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
164
+            throw new ValidationException('Non-audio list item provided for ListOfAudio slot');
165
+        }
166
+        if ($this === EShapeType::Video && !is_numeric($value)) {
167
+            throw new ValidationException('Non-video item provided for Video slot');
168
+        }
169
+        if ($this === EShapeType::ListOfVideos && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
170
+            throw new ValidationException('Non-video list item provided for ListOfTexts slot');
171
+        }
172
+        if ($this === EShapeType::File && !is_numeric($value)) {
173
+            throw new ValidationException('Non-file item provided for File slot');
174
+        }
175
+        if ($this === EShapeType::ListOfFiles && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) {
176
+            throw new ValidationException('Non-audio list item provided for ListOfFiles slot');
177
+        }
178
+    }
179 179
 
180
-	/**
181
-	 * @param EShapeType $type
182
-	 * @return EShapeType
183
-	 * @since 30.0.0
184
-	 */
185
-	public static function getScalarType(EShapeType $type): EShapeType {
186
-		return EShapeType::from($type->value % 10);
187
-	}
180
+    /**
181
+     * @param EShapeType $type
182
+     * @return EShapeType
183
+     * @since 30.0.0
184
+     */
185
+    public static function getScalarType(EShapeType $type): EShapeType {
186
+        return EShapeType::from($type->value % 10);
187
+    }
188 188
 
189
-	/**
190
-	 * @param EShapeType $type
191
-	 * @return bool
192
-	 * @since 30.0.0
193
-	 */
194
-	public static function isFileType(EShapeType $type): bool {
195
-		return in_array(EShapeType::getScalarType($type), [EShapeType::File, EShapeType::Image, EShapeType::Audio, EShapeType::Video], true);
196
-	}
189
+    /**
190
+     * @param EShapeType $type
191
+     * @return bool
192
+     * @since 30.0.0
193
+     */
194
+    public static function isFileType(EShapeType $type): bool {
195
+        return in_array(EShapeType::getScalarType($type), [EShapeType::File, EShapeType::Image, EShapeType::Audio, EShapeType::Video], true);
196
+    }
197 197
 }
Please login to merge, or discard this patch.
core/Controller/TextProcessingApiController.php 1 patch
Indentation   +177 added lines, -177 removed lines patch added patch discarded remove patch
@@ -38,181 +38,181 @@
 block discarded – undo
38 38
  * @psalm-import-type CoreTextProcessingTask from ResponseDefinitions
39 39
  */
40 40
 class TextProcessingApiController extends OCSController {
41
-	public function __construct(
42
-		string $appName,
43
-		IRequest $request,
44
-		private IManager $textProcessingManager,
45
-		private IL10N $l,
46
-		private ?string $userId,
47
-		private ContainerInterface $container,
48
-		private LoggerInterface $logger,
49
-	) {
50
-		parent::__construct($appName, $request);
51
-	}
52
-
53
-	/**
54
-	 * This endpoint returns all available LanguageModel task types
55
-	 *
56
-	 * @return DataResponse<Http::STATUS_OK, array{types: list<array{id: string, name: string, description: string}>}, array{}>
57
-	 *
58
-	 * 200: Task types returned
59
-	 */
60
-	#[PublicPage]
61
-	#[ApiRoute(verb: 'GET', url: '/tasktypes', root: '/textprocessing')]
62
-	public function taskTypes(): DataResponse {
63
-		$typeClasses = $this->textProcessingManager->getAvailableTaskTypes();
64
-		$types = [];
65
-		/** @var string $typeClass */
66
-		foreach ($typeClasses as $typeClass) {
67
-			try {
68
-				/** @var ITaskType $object */
69
-				$object = $this->container->get($typeClass);
70
-			} catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) {
71
-				$this->logger->warning('Could not find ' . $typeClass, ['exception' => $e]);
72
-				continue;
73
-			}
74
-			$types[] = [
75
-				'id' => $typeClass,
76
-				'name' => $object->getName(),
77
-				'description' => $object->getDescription(),
78
-			];
79
-		}
80
-
81
-		return new DataResponse([
82
-			'types' => $types,
83
-		]);
84
-	}
85
-
86
-	/**
87
-	 * This endpoint allows scheduling a language model task
88
-	 *
89
-	 * @param string $input Input text
90
-	 * @param string $type Type of the task
91
-	 * @param string $appId ID of the app that will execute the task
92
-	 * @param string $identifier An arbitrary identifier for the task
93
-	 *
94
-	 * @return DataResponse<Http::STATUS_OK, array{task: CoreTextProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_BAD_REQUEST|Http::STATUS_PRECONDITION_FAILED, array{message: string}, array{}>
95
-	 *
96
-	 * 200: Task scheduled successfully
97
-	 * 400: Scheduling task is not possible
98
-	 * 412: Scheduling task is not possible
99
-	 */
100
-	#[NoAdminRequired]
101
-	#[UserRateLimit(limit: 20, period: 120)]
102
-	#[AnonRateLimit(limit: 5, period: 120)]
103
-	#[ApiRoute(verb: 'POST', url: '/schedule', root: '/textprocessing')]
104
-	public function schedule(string $input, string $type, string $appId, string $identifier = ''): DataResponse {
105
-		if (strlen($input) > 64_000) {
106
-			return new DataResponse(['message' => $this->l->t('Input text is too long')], Http::STATUS_BAD_REQUEST);
107
-		}
108
-		try {
109
-			$task = new Task($type, $input, $appId, $this->userId, $identifier);
110
-		} catch (InvalidArgumentException) {
111
-			return new DataResponse(['message' => $this->l->t('Requested task type does not exist')], Http::STATUS_BAD_REQUEST);
112
-		}
113
-		try {
114
-			try {
115
-				$this->textProcessingManager->runOrScheduleTask($task);
116
-			} catch (TaskFailureException) {
117
-				// noop, because the task object has the failure status set already, we just return the task json
118
-			}
119
-
120
-			$json = $task->jsonSerialize();
121
-
122
-			return new DataResponse([
123
-				'task' => $json,
124
-			]);
125
-		} catch (PreConditionNotMetException) {
126
-			return new DataResponse(['message' => $this->l->t('Necessary language model provider is not available')], Http::STATUS_PRECONDITION_FAILED);
127
-		} catch (Exception) {
128
-			return new DataResponse(['message' => 'Internal server error'], Http::STATUS_INTERNAL_SERVER_ERROR);
129
-		}
130
-	}
131
-
132
-	/**
133
-	 * This endpoint allows checking the status and results of a task.
134
-	 * Tasks are removed 1 week after receiving their last update.
135
-	 *
136
-	 * @param int $id The id of the task
137
-	 *
138
-	 * @return DataResponse<Http::STATUS_OK, array{task: CoreTextProcessingTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
139
-	 *
140
-	 * 200: Task returned
141
-	 * 404: Task not found
142
-	 */
143
-	#[NoAdminRequired]
144
-	#[ApiRoute(verb: 'GET', url: '/task/{id}', root: '/textprocessing')]
145
-	public function getTask(int $id): DataResponse {
146
-		try {
147
-			$task = $this->textProcessingManager->getUserTask($id, $this->userId);
148
-
149
-			$json = $task->jsonSerialize();
150
-
151
-			return new DataResponse([
152
-				'task' => $json,
153
-			]);
154
-		} catch (NotFoundException $e) {
155
-			return new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
156
-		} catch (\RuntimeException $e) {
157
-			return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
158
-		}
159
-	}
160
-
161
-	/**
162
-	 * This endpoint allows to delete a scheduled task for a user
163
-	 *
164
-	 * @param int $id The id of the task
165
-	 *
166
-	 * @return DataResponse<Http::STATUS_OK, array{task: CoreTextProcessingTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
167
-	 *
168
-	 * 200: Task returned
169
-	 * 404: Task not found
170
-	 */
171
-	#[NoAdminRequired]
172
-	#[ApiRoute(verb: 'DELETE', url: '/task/{id}', root: '/textprocessing')]
173
-	public function deleteTask(int $id): DataResponse {
174
-		try {
175
-			$task = $this->textProcessingManager->getUserTask($id, $this->userId);
176
-
177
-			$this->textProcessingManager->deleteTask($task);
178
-
179
-			$json = $task->jsonSerialize();
180
-
181
-			return new DataResponse([
182
-				'task' => $json,
183
-			]);
184
-		} catch (NotFoundException $e) {
185
-			return new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
186
-		} catch (\RuntimeException $e) {
187
-			return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
188
-		}
189
-	}
190
-
191
-
192
-	/**
193
-	 * This endpoint returns a list of tasks of a user that are related
194
-	 * with a specific appId and optionally with an identifier
195
-	 *
196
-	 * @param string $appId ID of the app
197
-	 * @param string|null $identifier An arbitrary identifier for the task
198
-	 * @return DataResponse<Http::STATUS_OK, array{tasks: list<CoreTextProcessingTask>}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
199
-	 *
200
-	 * 200: Task list returned
201
-	 */
202
-	#[NoAdminRequired]
203
-	#[ApiRoute(verb: 'GET', url: '/tasks/app/{appId}', root: '/textprocessing')]
204
-	public function listTasksByApp(string $appId, ?string $identifier = null): DataResponse {
205
-		try {
206
-			$tasks = $this->textProcessingManager->getUserTasksByApp($this->userId, $appId, $identifier);
207
-			$json = array_values(array_map(static function (Task $task) {
208
-				return $task->jsonSerialize();
209
-			}, $tasks));
210
-
211
-			return new DataResponse([
212
-				'tasks' => $json,
213
-			]);
214
-		} catch (\RuntimeException $e) {
215
-			return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
216
-		}
217
-	}
41
+    public function __construct(
42
+        string $appName,
43
+        IRequest $request,
44
+        private IManager $textProcessingManager,
45
+        private IL10N $l,
46
+        private ?string $userId,
47
+        private ContainerInterface $container,
48
+        private LoggerInterface $logger,
49
+    ) {
50
+        parent::__construct($appName, $request);
51
+    }
52
+
53
+    /**
54
+     * This endpoint returns all available LanguageModel task types
55
+     *
56
+     * @return DataResponse<Http::STATUS_OK, array{types: list<array{id: string, name: string, description: string}>}, array{}>
57
+     *
58
+     * 200: Task types returned
59
+     */
60
+    #[PublicPage]
61
+    #[ApiRoute(verb: 'GET', url: '/tasktypes', root: '/textprocessing')]
62
+    public function taskTypes(): DataResponse {
63
+        $typeClasses = $this->textProcessingManager->getAvailableTaskTypes();
64
+        $types = [];
65
+        /** @var string $typeClass */
66
+        foreach ($typeClasses as $typeClass) {
67
+            try {
68
+                /** @var ITaskType $object */
69
+                $object = $this->container->get($typeClass);
70
+            } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) {
71
+                $this->logger->warning('Could not find ' . $typeClass, ['exception' => $e]);
72
+                continue;
73
+            }
74
+            $types[] = [
75
+                'id' => $typeClass,
76
+                'name' => $object->getName(),
77
+                'description' => $object->getDescription(),
78
+            ];
79
+        }
80
+
81
+        return new DataResponse([
82
+            'types' => $types,
83
+        ]);
84
+    }
85
+
86
+    /**
87
+     * This endpoint allows scheduling a language model task
88
+     *
89
+     * @param string $input Input text
90
+     * @param string $type Type of the task
91
+     * @param string $appId ID of the app that will execute the task
92
+     * @param string $identifier An arbitrary identifier for the task
93
+     *
94
+     * @return DataResponse<Http::STATUS_OK, array{task: CoreTextProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_BAD_REQUEST|Http::STATUS_PRECONDITION_FAILED, array{message: string}, array{}>
95
+     *
96
+     * 200: Task scheduled successfully
97
+     * 400: Scheduling task is not possible
98
+     * 412: Scheduling task is not possible
99
+     */
100
+    #[NoAdminRequired]
101
+    #[UserRateLimit(limit: 20, period: 120)]
102
+    #[AnonRateLimit(limit: 5, period: 120)]
103
+    #[ApiRoute(verb: 'POST', url: '/schedule', root: '/textprocessing')]
104
+    public function schedule(string $input, string $type, string $appId, string $identifier = ''): DataResponse {
105
+        if (strlen($input) > 64_000) {
106
+            return new DataResponse(['message' => $this->l->t('Input text is too long')], Http::STATUS_BAD_REQUEST);
107
+        }
108
+        try {
109
+            $task = new Task($type, $input, $appId, $this->userId, $identifier);
110
+        } catch (InvalidArgumentException) {
111
+            return new DataResponse(['message' => $this->l->t('Requested task type does not exist')], Http::STATUS_BAD_REQUEST);
112
+        }
113
+        try {
114
+            try {
115
+                $this->textProcessingManager->runOrScheduleTask($task);
116
+            } catch (TaskFailureException) {
117
+                // noop, because the task object has the failure status set already, we just return the task json
118
+            }
119
+
120
+            $json = $task->jsonSerialize();
121
+
122
+            return new DataResponse([
123
+                'task' => $json,
124
+            ]);
125
+        } catch (PreConditionNotMetException) {
126
+            return new DataResponse(['message' => $this->l->t('Necessary language model provider is not available')], Http::STATUS_PRECONDITION_FAILED);
127
+        } catch (Exception) {
128
+            return new DataResponse(['message' => 'Internal server error'], Http::STATUS_INTERNAL_SERVER_ERROR);
129
+        }
130
+    }
131
+
132
+    /**
133
+     * This endpoint allows checking the status and results of a task.
134
+     * Tasks are removed 1 week after receiving their last update.
135
+     *
136
+     * @param int $id The id of the task
137
+     *
138
+     * @return DataResponse<Http::STATUS_OK, array{task: CoreTextProcessingTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
139
+     *
140
+     * 200: Task returned
141
+     * 404: Task not found
142
+     */
143
+    #[NoAdminRequired]
144
+    #[ApiRoute(verb: 'GET', url: '/task/{id}', root: '/textprocessing')]
145
+    public function getTask(int $id): DataResponse {
146
+        try {
147
+            $task = $this->textProcessingManager->getUserTask($id, $this->userId);
148
+
149
+            $json = $task->jsonSerialize();
150
+
151
+            return new DataResponse([
152
+                'task' => $json,
153
+            ]);
154
+        } catch (NotFoundException $e) {
155
+            return new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
156
+        } catch (\RuntimeException $e) {
157
+            return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
158
+        }
159
+    }
160
+
161
+    /**
162
+     * This endpoint allows to delete a scheduled task for a user
163
+     *
164
+     * @param int $id The id of the task
165
+     *
166
+     * @return DataResponse<Http::STATUS_OK, array{task: CoreTextProcessingTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
167
+     *
168
+     * 200: Task returned
169
+     * 404: Task not found
170
+     */
171
+    #[NoAdminRequired]
172
+    #[ApiRoute(verb: 'DELETE', url: '/task/{id}', root: '/textprocessing')]
173
+    public function deleteTask(int $id): DataResponse {
174
+        try {
175
+            $task = $this->textProcessingManager->getUserTask($id, $this->userId);
176
+
177
+            $this->textProcessingManager->deleteTask($task);
178
+
179
+            $json = $task->jsonSerialize();
180
+
181
+            return new DataResponse([
182
+                'task' => $json,
183
+            ]);
184
+        } catch (NotFoundException $e) {
185
+            return new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
186
+        } catch (\RuntimeException $e) {
187
+            return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
188
+        }
189
+    }
190
+
191
+
192
+    /**
193
+     * This endpoint returns a list of tasks of a user that are related
194
+     * with a specific appId and optionally with an identifier
195
+     *
196
+     * @param string $appId ID of the app
197
+     * @param string|null $identifier An arbitrary identifier for the task
198
+     * @return DataResponse<Http::STATUS_OK, array{tasks: list<CoreTextProcessingTask>}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
199
+     *
200
+     * 200: Task list returned
201
+     */
202
+    #[NoAdminRequired]
203
+    #[ApiRoute(verb: 'GET', url: '/tasks/app/{appId}', root: '/textprocessing')]
204
+    public function listTasksByApp(string $appId, ?string $identifier = null): DataResponse {
205
+        try {
206
+            $tasks = $this->textProcessingManager->getUserTasksByApp($this->userId, $appId, $identifier);
207
+            $json = array_values(array_map(static function (Task $task) {
208
+                return $task->jsonSerialize();
209
+            }, $tasks));
210
+
211
+            return new DataResponse([
212
+                'tasks' => $json,
213
+            ]);
214
+        } catch (\RuntimeException $e) {
215
+            return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
216
+        }
217
+    }
218 218
 }
Please login to merge, or discard this patch.
core/Controller/TextToImageApiController.php 1 patch
Indentation   +200 added lines, -200 removed lines patch added patch discarded remove patch
@@ -35,204 +35,204 @@
 block discarded – undo
35 35
  * @psalm-import-type CoreTextToImageTask from ResponseDefinitions
36 36
  */
37 37
 class TextToImageApiController extends OCSController {
38
-	public function __construct(
39
-		string $appName,
40
-		IRequest $request,
41
-		private IManager $textToImageManager,
42
-		private IL10N $l,
43
-		private ?string $userId,
44
-		private AppData $appData,
45
-	) {
46
-		parent::__construct($appName, $request);
47
-	}
48
-
49
-	/**
50
-	 * Check whether this feature is available
51
-	 *
52
-	 * @return DataResponse<Http::STATUS_OK, array{isAvailable: bool}, array{}>
53
-	 *
54
-	 * 200: Returns availability status
55
-	 */
56
-	#[NoAdminRequired]
57
-	#[ApiRoute(verb: 'GET', url: '/is_available', root: '/text2image')]
58
-	public function isAvailable(): DataResponse {
59
-		return new DataResponse([
60
-			'isAvailable' => $this->textToImageManager->hasProviders(),
61
-		]);
62
-	}
63
-
64
-	/**
65
-	 * This endpoint allows scheduling a text to image task
66
-	 *
67
-	 * @param string $input Input text
68
-	 * @param string $appId ID of the app that will execute the task
69
-	 * @param string $identifier An arbitrary identifier for the task
70
-	 * @param int $numberOfImages The number of images to generate
71
-	 *
72
-	 * @return DataResponse<Http::STATUS_OK, array{task: CoreTextToImageTask}, array{}>|DataResponse<Http::STATUS_PRECONDITION_FAILED|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
73
-	 *
74
-	 * 200: Task scheduled successfully
75
-	 * 412: Scheduling task is not possible
76
-	 */
77
-	#[NoAdminRequired]
78
-	#[UserRateLimit(limit: 20, period: 120)]
79
-	#[ApiRoute(verb: 'POST', url: '/schedule', root: '/text2image')]
80
-	public function schedule(string $input, string $appId, string $identifier = '', int $numberOfImages = 8): DataResponse {
81
-		if (strlen($input) > 64_000) {
82
-			return new DataResponse(['message' => $this->l->t('Input text is too long')], Http::STATUS_PRECONDITION_FAILED);
83
-		}
84
-		$task = new Task($input, $appId, $numberOfImages, $this->userId, $identifier);
85
-		try {
86
-			try {
87
-				$this->textToImageManager->runOrScheduleTask($task);
88
-			} catch (TaskFailureException) {
89
-				// Task status was already updated by the manager, nothing to do here
90
-			}
91
-
92
-			$json = $task->jsonSerialize();
93
-
94
-			return new DataResponse([
95
-				'task' => $json,
96
-			]);
97
-		} catch (PreConditionNotMetException) {
98
-			return new DataResponse(['message' => $this->l->t('No text to image provider is available')], Http::STATUS_PRECONDITION_FAILED);
99
-		} catch (Exception) {
100
-			return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
101
-		}
102
-	}
103
-
104
-	/**
105
-	 * This endpoint allows checking the status and results of a task.
106
-	 * Tasks are removed 1 week after receiving their last update.
107
-	 *
108
-	 * @param int $id The id of the task
109
-	 *
110
-	 * @return DataResponse<Http::STATUS_OK, array{task: CoreTextToImageTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
111
-	 *
112
-	 * 200: Task returned
113
-	 * 404: Task not found
114
-	 */
115
-	#[NoAdminRequired]
116
-	#[BruteForceProtection(action: 'text2image')]
117
-	#[ApiRoute(verb: 'GET', url: '/task/{id}', root: '/text2image')]
118
-	public function getTask(int $id): DataResponse {
119
-		try {
120
-			$task = $this->textToImageManager->getUserTask($id, $this->userId);
121
-
122
-			$json = $task->jsonSerialize();
123
-
124
-			return new DataResponse([
125
-				'task' => $json,
126
-			]);
127
-		} catch (TaskNotFoundException) {
128
-			$res = new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
129
-			$res->throttle(['action' => 'text2image']);
130
-			return $res;
131
-		} catch (\RuntimeException) {
132
-			return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
133
-		}
134
-	}
135
-
136
-	/**
137
-	 * This endpoint allows downloading the resulting image of a task
138
-	 *
139
-	 * @param int $id The id of the task
140
-	 * @param int $index The index of the image to retrieve
141
-	 *
142
-	 * @return FileDisplayResponse<Http::STATUS_OK, array{'Content-Type': string}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
143
-	 *
144
-	 * 200: Image returned
145
-	 * 404: Task or image not found
146
-	 */
147
-	#[NoAdminRequired]
148
-	#[BruteForceProtection(action: 'text2image')]
149
-	#[ApiRoute(verb: 'GET', url: '/task/{id}/image/{index}', root: '/text2image')]
150
-	public function getImage(int $id, int $index): DataResponse|FileDisplayResponse {
151
-		try {
152
-			$task = $this->textToImageManager->getUserTask($id, $this->userId);
153
-			try {
154
-				$folder = $this->appData->getFolder('text2image');
155
-			} catch (NotFoundException) {
156
-				$res = new DataResponse(['message' => $this->l->t('Image not found')], Http::STATUS_NOT_FOUND);
157
-				$res->throttle(['action' => 'text2image']);
158
-				return $res;
159
-			}
160
-			$file = $folder->getFolder((string)$task->getId())->getFile((string)$index);
161
-			$info = getimagesizefromstring($file->getContent());
162
-
163
-			return new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => image_type_to_mime_type($info[2])]);
164
-		} catch (TaskNotFoundException) {
165
-			$res = new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
166
-			$res->throttle(['action' => 'text2image']);
167
-			return $res;
168
-		} catch (\RuntimeException) {
169
-			return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
170
-		} catch (NotFoundException) {
171
-			$res = new DataResponse(['message' => $this->l->t('Image not found')], Http::STATUS_NOT_FOUND);
172
-			$res->throttle(['action' => 'text2image']);
173
-			return $res;
174
-		}
175
-	}
176
-
177
-	/**
178
-	 * This endpoint allows to delete a scheduled task for a user
179
-	 *
180
-	 * @param int $id The id of the task
181
-	 *
182
-	 * @return DataResponse<Http::STATUS_OK, array{task: CoreTextToImageTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
183
-	 *
184
-	 * 200: Task returned
185
-	 * 404: Task not found
186
-	 */
187
-	#[NoAdminRequired]
188
-	#[BruteForceProtection(action: 'text2image')]
189
-	#[ApiRoute(verb: 'DELETE', url: '/task/{id}', root: '/text2image')]
190
-	public function deleteTask(int $id): DataResponse {
191
-		try {
192
-			$task = $this->textToImageManager->getUserTask($id, $this->userId);
193
-
194
-			$this->textToImageManager->deleteTask($task);
195
-
196
-			$json = $task->jsonSerialize();
197
-
198
-			return new DataResponse([
199
-				'task' => $json,
200
-			]);
201
-		} catch (TaskNotFoundException) {
202
-			$res = new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
203
-			$res->throttle(['action' => 'text2image']);
204
-			return $res;
205
-		} catch (\RuntimeException) {
206
-			return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
207
-		}
208
-	}
209
-
210
-
211
-	/**
212
-	 * This endpoint returns a list of tasks of a user that are related
213
-	 * with a specific appId and optionally with an identifier
214
-	 *
215
-	 * @param string $appId ID of the app
216
-	 * @param string|null $identifier An arbitrary identifier for the task
217
-	 * @return DataResponse<Http::STATUS_OK, array{tasks: list<CoreTextToImageTask>}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
218
-	 *
219
-	 * 200: Task list returned
220
-	 */
221
-	#[NoAdminRequired]
222
-	#[AnonRateLimit(limit: 5, period: 120)]
223
-	#[ApiRoute(verb: 'GET', url: '/tasks/app/{appId}', root: '/text2image')]
224
-	public function listTasksByApp(string $appId, ?string $identifier = null): DataResponse {
225
-		try {
226
-			$tasks = $this->textToImageManager->getUserTasksByApp($this->userId, $appId, $identifier);
227
-			$json = array_values(array_map(static function (Task $task) {
228
-				return $task->jsonSerialize();
229
-			}, $tasks));
230
-
231
-			return new DataResponse([
232
-				'tasks' => $json,
233
-			]);
234
-		} catch (\RuntimeException) {
235
-			return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
236
-		}
237
-	}
38
+    public function __construct(
39
+        string $appName,
40
+        IRequest $request,
41
+        private IManager $textToImageManager,
42
+        private IL10N $l,
43
+        private ?string $userId,
44
+        private AppData $appData,
45
+    ) {
46
+        parent::__construct($appName, $request);
47
+    }
48
+
49
+    /**
50
+     * Check whether this feature is available
51
+     *
52
+     * @return DataResponse<Http::STATUS_OK, array{isAvailable: bool}, array{}>
53
+     *
54
+     * 200: Returns availability status
55
+     */
56
+    #[NoAdminRequired]
57
+    #[ApiRoute(verb: 'GET', url: '/is_available', root: '/text2image')]
58
+    public function isAvailable(): DataResponse {
59
+        return new DataResponse([
60
+            'isAvailable' => $this->textToImageManager->hasProviders(),
61
+        ]);
62
+    }
63
+
64
+    /**
65
+     * This endpoint allows scheduling a text to image task
66
+     *
67
+     * @param string $input Input text
68
+     * @param string $appId ID of the app that will execute the task
69
+     * @param string $identifier An arbitrary identifier for the task
70
+     * @param int $numberOfImages The number of images to generate
71
+     *
72
+     * @return DataResponse<Http::STATUS_OK, array{task: CoreTextToImageTask}, array{}>|DataResponse<Http::STATUS_PRECONDITION_FAILED|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
73
+     *
74
+     * 200: Task scheduled successfully
75
+     * 412: Scheduling task is not possible
76
+     */
77
+    #[NoAdminRequired]
78
+    #[UserRateLimit(limit: 20, period: 120)]
79
+    #[ApiRoute(verb: 'POST', url: '/schedule', root: '/text2image')]
80
+    public function schedule(string $input, string $appId, string $identifier = '', int $numberOfImages = 8): DataResponse {
81
+        if (strlen($input) > 64_000) {
82
+            return new DataResponse(['message' => $this->l->t('Input text is too long')], Http::STATUS_PRECONDITION_FAILED);
83
+        }
84
+        $task = new Task($input, $appId, $numberOfImages, $this->userId, $identifier);
85
+        try {
86
+            try {
87
+                $this->textToImageManager->runOrScheduleTask($task);
88
+            } catch (TaskFailureException) {
89
+                // Task status was already updated by the manager, nothing to do here
90
+            }
91
+
92
+            $json = $task->jsonSerialize();
93
+
94
+            return new DataResponse([
95
+                'task' => $json,
96
+            ]);
97
+        } catch (PreConditionNotMetException) {
98
+            return new DataResponse(['message' => $this->l->t('No text to image provider is available')], Http::STATUS_PRECONDITION_FAILED);
99
+        } catch (Exception) {
100
+            return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
101
+        }
102
+    }
103
+
104
+    /**
105
+     * This endpoint allows checking the status and results of a task.
106
+     * Tasks are removed 1 week after receiving their last update.
107
+     *
108
+     * @param int $id The id of the task
109
+     *
110
+     * @return DataResponse<Http::STATUS_OK, array{task: CoreTextToImageTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
111
+     *
112
+     * 200: Task returned
113
+     * 404: Task not found
114
+     */
115
+    #[NoAdminRequired]
116
+    #[BruteForceProtection(action: 'text2image')]
117
+    #[ApiRoute(verb: 'GET', url: '/task/{id}', root: '/text2image')]
118
+    public function getTask(int $id): DataResponse {
119
+        try {
120
+            $task = $this->textToImageManager->getUserTask($id, $this->userId);
121
+
122
+            $json = $task->jsonSerialize();
123
+
124
+            return new DataResponse([
125
+                'task' => $json,
126
+            ]);
127
+        } catch (TaskNotFoundException) {
128
+            $res = new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
129
+            $res->throttle(['action' => 'text2image']);
130
+            return $res;
131
+        } catch (\RuntimeException) {
132
+            return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
133
+        }
134
+    }
135
+
136
+    /**
137
+     * This endpoint allows downloading the resulting image of a task
138
+     *
139
+     * @param int $id The id of the task
140
+     * @param int $index The index of the image to retrieve
141
+     *
142
+     * @return FileDisplayResponse<Http::STATUS_OK, array{'Content-Type': string}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
143
+     *
144
+     * 200: Image returned
145
+     * 404: Task or image not found
146
+     */
147
+    #[NoAdminRequired]
148
+    #[BruteForceProtection(action: 'text2image')]
149
+    #[ApiRoute(verb: 'GET', url: '/task/{id}/image/{index}', root: '/text2image')]
150
+    public function getImage(int $id, int $index): DataResponse|FileDisplayResponse {
151
+        try {
152
+            $task = $this->textToImageManager->getUserTask($id, $this->userId);
153
+            try {
154
+                $folder = $this->appData->getFolder('text2image');
155
+            } catch (NotFoundException) {
156
+                $res = new DataResponse(['message' => $this->l->t('Image not found')], Http::STATUS_NOT_FOUND);
157
+                $res->throttle(['action' => 'text2image']);
158
+                return $res;
159
+            }
160
+            $file = $folder->getFolder((string)$task->getId())->getFile((string)$index);
161
+            $info = getimagesizefromstring($file->getContent());
162
+
163
+            return new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => image_type_to_mime_type($info[2])]);
164
+        } catch (TaskNotFoundException) {
165
+            $res = new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
166
+            $res->throttle(['action' => 'text2image']);
167
+            return $res;
168
+        } catch (\RuntimeException) {
169
+            return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
170
+        } catch (NotFoundException) {
171
+            $res = new DataResponse(['message' => $this->l->t('Image not found')], Http::STATUS_NOT_FOUND);
172
+            $res->throttle(['action' => 'text2image']);
173
+            return $res;
174
+        }
175
+    }
176
+
177
+    /**
178
+     * This endpoint allows to delete a scheduled task for a user
179
+     *
180
+     * @param int $id The id of the task
181
+     *
182
+     * @return DataResponse<Http::STATUS_OK, array{task: CoreTextToImageTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
183
+     *
184
+     * 200: Task returned
185
+     * 404: Task not found
186
+     */
187
+    #[NoAdminRequired]
188
+    #[BruteForceProtection(action: 'text2image')]
189
+    #[ApiRoute(verb: 'DELETE', url: '/task/{id}', root: '/text2image')]
190
+    public function deleteTask(int $id): DataResponse {
191
+        try {
192
+            $task = $this->textToImageManager->getUserTask($id, $this->userId);
193
+
194
+            $this->textToImageManager->deleteTask($task);
195
+
196
+            $json = $task->jsonSerialize();
197
+
198
+            return new DataResponse([
199
+                'task' => $json,
200
+            ]);
201
+        } catch (TaskNotFoundException) {
202
+            $res = new DataResponse(['message' => $this->l->t('Task not found')], Http::STATUS_NOT_FOUND);
203
+            $res->throttle(['action' => 'text2image']);
204
+            return $res;
205
+        } catch (\RuntimeException) {
206
+            return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
207
+        }
208
+    }
209
+
210
+
211
+    /**
212
+     * This endpoint returns a list of tasks of a user that are related
213
+     * with a specific appId and optionally with an identifier
214
+     *
215
+     * @param string $appId ID of the app
216
+     * @param string|null $identifier An arbitrary identifier for the task
217
+     * @return DataResponse<Http::STATUS_OK, array{tasks: list<CoreTextToImageTask>}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
218
+     *
219
+     * 200: Task list returned
220
+     */
221
+    #[NoAdminRequired]
222
+    #[AnonRateLimit(limit: 5, period: 120)]
223
+    #[ApiRoute(verb: 'GET', url: '/tasks/app/{appId}', root: '/text2image')]
224
+    public function listTasksByApp(string $appId, ?string $identifier = null): DataResponse {
225
+        try {
226
+            $tasks = $this->textToImageManager->getUserTasksByApp($this->userId, $appId, $identifier);
227
+            $json = array_values(array_map(static function (Task $task) {
228
+                return $task->jsonSerialize();
229
+            }, $tasks));
230
+
231
+            return new DataResponse([
232
+                'tasks' => $json,
233
+            ]);
234
+        } catch (\RuntimeException) {
235
+            return new DataResponse(['message' => $this->l->t('Internal error')], Http::STATUS_INTERNAL_SERVER_ERROR);
236
+        }
237
+    }
238 238
 }
Please login to merge, or discard this patch.
core/Controller/TranslationApiController.php 1 patch
Indentation   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -25,65 +25,65 @@
 block discarded – undo
25 25
 use OCP\Translation\ITranslationManager;
26 26
 
27 27
 class TranslationApiController extends OCSController {
28
-	public function __construct(
29
-		string $appName,
30
-		IRequest $request,
31
-		private ITranslationManager $translationManager,
32
-		private IL10N $l10n,
33
-	) {
34
-		parent::__construct($appName, $request);
35
-	}
28
+    public function __construct(
29
+        string $appName,
30
+        IRequest $request,
31
+        private ITranslationManager $translationManager,
32
+        private IL10N $l10n,
33
+    ) {
34
+        parent::__construct($appName, $request);
35
+    }
36 36
 
37
-	/**
38
-	 * Get the list of supported languages
39
-	 *
40
-	 * @return DataResponse<Http::STATUS_OK, array{languages: list<array{from: string, fromLabel: string, to: string, toLabel: string}>, languageDetection: bool}, array{}>
41
-	 *
42
-	 * 200: Supported languages returned
43
-	 */
44
-	#[PublicPage]
45
-	#[ApiRoute(verb: 'GET', url: '/languages', root: '/translation')]
46
-	public function languages(): DataResponse {
47
-		return new DataResponse([
48
-			'languages' => array_values(array_map(fn ($lang) => $lang->jsonSerialize(), $this->translationManager->getLanguages())),
49
-			'languageDetection' => $this->translationManager->canDetectLanguage(),
50
-		]);
51
-	}
37
+    /**
38
+     * Get the list of supported languages
39
+     *
40
+     * @return DataResponse<Http::STATUS_OK, array{languages: list<array{from: string, fromLabel: string, to: string, toLabel: string}>, languageDetection: bool}, array{}>
41
+     *
42
+     * 200: Supported languages returned
43
+     */
44
+    #[PublicPage]
45
+    #[ApiRoute(verb: 'GET', url: '/languages', root: '/translation')]
46
+    public function languages(): DataResponse {
47
+        return new DataResponse([
48
+            'languages' => array_values(array_map(fn ($lang) => $lang->jsonSerialize(), $this->translationManager->getLanguages())),
49
+            'languageDetection' => $this->translationManager->canDetectLanguage(),
50
+        ]);
51
+    }
52 52
 
53
-	/**
54
-	 * Translate a text
55
-	 *
56
-	 * @param string $text Text to be translated
57
-	 * @param string|null $fromLanguage Language to translate from
58
-	 * @param string $toLanguage Language to translate to
59
-	 * @return DataResponse<Http::STATUS_OK, array{text: string, from: ?string}, array{}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_PRECONDITION_FAILED|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string, from?: ?string}, array{}>
60
-	 *
61
-	 * 200: Translated text returned
62
-	 * 400: Language not detected or unable to translate
63
-	 * 412: Translating is not possible
64
-	 */
65
-	#[PublicPage]
66
-	#[UserRateLimit(limit: 25, period: 120)]
67
-	#[AnonRateLimit(limit: 10, period: 120)]
68
-	#[ApiRoute(verb: 'POST', url: '/translate', root: '/translation')]
69
-	public function translate(string $text, ?string $fromLanguage, string $toLanguage): DataResponse {
70
-		if (strlen($text) > 64_000) {
71
-			return new DataResponse(['message' => $this->l10n->t('Input text is too long')], Http::STATUS_BAD_REQUEST);
72
-		}
73
-		try {
74
-			$translation = $this->translationManager->translate($text, $fromLanguage, $toLanguage);
53
+    /**
54
+     * Translate a text
55
+     *
56
+     * @param string $text Text to be translated
57
+     * @param string|null $fromLanguage Language to translate from
58
+     * @param string $toLanguage Language to translate to
59
+     * @return DataResponse<Http::STATUS_OK, array{text: string, from: ?string}, array{}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_PRECONDITION_FAILED|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string, from?: ?string}, array{}>
60
+     *
61
+     * 200: Translated text returned
62
+     * 400: Language not detected or unable to translate
63
+     * 412: Translating is not possible
64
+     */
65
+    #[PublicPage]
66
+    #[UserRateLimit(limit: 25, period: 120)]
67
+    #[AnonRateLimit(limit: 10, period: 120)]
68
+    #[ApiRoute(verb: 'POST', url: '/translate', root: '/translation')]
69
+    public function translate(string $text, ?string $fromLanguage, string $toLanguage): DataResponse {
70
+        if (strlen($text) > 64_000) {
71
+            return new DataResponse(['message' => $this->l10n->t('Input text is too long')], Http::STATUS_BAD_REQUEST);
72
+        }
73
+        try {
74
+            $translation = $this->translationManager->translate($text, $fromLanguage, $toLanguage);
75 75
 
76
-			return new DataResponse([
77
-				'text' => $translation,
78
-				'from' => $fromLanguage,
76
+            return new DataResponse([
77
+                'text' => $translation,
78
+                'from' => $fromLanguage,
79 79
 
80
-			]);
81
-		} catch (PreConditionNotMetException) {
82
-			return new DataResponse(['message' => $this->l10n->t('No translation provider available')], Http::STATUS_PRECONDITION_FAILED);
83
-		} catch (InvalidArgumentException) {
84
-			return new DataResponse(['message' => $this->l10n->t('Could not detect language')], Http::STATUS_BAD_REQUEST);
85
-		} catch (CouldNotTranslateException $e) {
86
-			return new DataResponse(['message' => $this->l10n->t('Unable to translate'), 'from' => $e->getFrom()], Http::STATUS_BAD_REQUEST);
87
-		}
88
-	}
80
+            ]);
81
+        } catch (PreConditionNotMetException) {
82
+            return new DataResponse(['message' => $this->l10n->t('No translation provider available')], Http::STATUS_PRECONDITION_FAILED);
83
+        } catch (InvalidArgumentException) {
84
+            return new DataResponse(['message' => $this->l10n->t('Could not detect language')], Http::STATUS_BAD_REQUEST);
85
+        } catch (CouldNotTranslateException $e) {
86
+            return new DataResponse(['message' => $this->l10n->t('Unable to translate'), 'from' => $e->getFrom()], Http::STATUS_BAD_REQUEST);
87
+        }
88
+    }
89 89
 }
Please login to merge, or discard this patch.