OhMyDitzzy commited on
Commit
4c8cf27
Β·
1 Parent(s): 33cfc81

fix: image editor

Browse files
src/server/plugins/ai/ai_image_editor.js CHANGED
@@ -4,6 +4,13 @@ import multer from "multer";
4
  import axios from "axios";
5
  import path from "path";
6
 
 
 
 
 
 
 
 
7
  const storage = multer.memoryStorage();
8
  const upload = multer({
9
  storage: storage,
@@ -20,13 +27,6 @@ const upload = multer({
20
  }
21
  });
22
 
23
- const ModelMap = {
24
- nano_banana: 2,
25
- seed_dream: 5,
26
- flux: 8,
27
- qwen_image: 9
28
- };
29
-
30
  /** @type {import("../../types/plugin.ts").ApiPluginHandler}*/
31
  const handler = {
32
  name: "AI Image Editor",
@@ -36,9 +36,6 @@ const handler = {
36
  category: ["ai"],
37
  alias: ["aiImageEditor"],
38
  tags: ["ai", "image"],
39
- disabled: true,
40
- disabledReason: "Temporarily disabled",
41
-
42
  parameters: {
43
  body: [
44
  {
@@ -137,14 +134,8 @@ const handler = {
137
  }
138
  },
139
  exec: async (req, res) => {
140
- console.log("πŸ”΅ [1] Request received at AI Image Editor");
141
- console.log("πŸ”΅ [1] Headers:", req.headers);
142
-
143
  upload.single('image')(req, res, async (err) => {
144
- console.log("πŸ”΅ [2] Inside multer middleware");
145
-
146
  if (err) {
147
- console.error("❌ [2] Multer error:", err);
148
  if (err instanceof multer.MulterError) {
149
  if (err.code === 'LIMIT_FILE_SIZE') {
150
  return res.status(413).json({
@@ -159,65 +150,43 @@ const handler = {
159
  });
160
  }
161
 
162
- console.log("πŸ”΅ [3] Multer successful");
163
- console.log("πŸ”΅ [3] Body:", req.body);
164
- console.log("πŸ”΅ [3] File:", req.file ? `${req.file.originalname} (${req.file.size} bytes)` : "No file");
165
-
166
  try {
167
- const { prompt, output_size, disable_safety_checker, model } = req.body;
168
 
169
- console.log("πŸ”΅ [4] Extracted params:", { prompt, output_size, model, disable_safety_checker });
170
-
171
- // Validate required parameters
172
  if (!prompt) {
173
- console.log("❌ [4] Missing prompt");
174
  return ErrorResponses.missingParameter(res, "prompt");
175
  }
176
  if (!output_size) {
177
- console.log("❌ [4] Missing output_size");
178
  return ErrorResponses.missingParameter(res, "output_size");
179
  }
180
  if (!model) {
181
- console.log("❌ [4] Missing model");
182
  return ErrorResponses.missingParameter(res, "model");
183
  }
184
 
185
- // Validate model
186
  if (!ModelMap[model]) {
187
- console.log("❌ [4] Invalid model:", model);
188
  return res.status(400).json({
189
  success: false,
190
  message: `Invalid model. Must be one of: ${Object.keys(ModelMap).join(', ')}`
191
  });
192
  }
193
 
194
- console.log("πŸ”΅ [5] Creating AIEnhancer instance");
195
  const ai = new AIEnhancer();
196
- console.log("βœ… [5] AIEnhancer created");
197
-
198
  let imageBuffer;
199
  let filename;
200
-
201
- // Handle uploaded file
202
  if (req.file) {
203
- console.log("πŸ”΅ [6] Using uploaded file");
204
  imageBuffer = req.file.buffer;
205
  filename = req.file.originalname;
206
  }
207
- // Handle URL
208
  else if (req.body.image && typeof req.body.image === 'string') {
209
- console.log("πŸ”΅ [6] Downloading from URL:", req.body.image);
210
  const imageUrl = req.body.image;
211
 
212
- // Validate URL
213
  try {
214
  new URL(imageUrl);
215
  } catch {
216
- console.log("❌ [6] Invalid URL");
217
  return ErrorResponses.invalidUrl(res, "Invalid image URL");
218
  }
219
-
220
- // Download image from URL
221
  const response = await axios.get(imageUrl, {
222
  responseType: 'arraybuffer',
223
  maxContentLength: 5 * 1024 * 1024,
@@ -229,21 +198,11 @@ const handler = {
229
 
230
  imageBuffer = Buffer.from(response.data);
231
  filename = path.basename(new URL(imageUrl).pathname) || 'image';
232
- console.log("βœ… [6] Downloaded from URL:", filename);
233
  } else {
234
- console.log("❌ [6] No image provided");
235
  return ErrorResponses.missingParameter(res, "image (file or URL)");
236
  }
237
 
238
- console.log("πŸ”΅ [7] Image buffer size:", imageBuffer.length);
239
-
240
- // Get model ID from map
241
- const modelId = ModelMap[model];
242
- console.log("πŸ”΅ [8] Model ID:", modelId);
243
-
244
- // Call AI Image Editor
245
- console.log("πŸ”΅ [9] Calling ImageAIEditor...");
246
- const edit = await ai.ImageAIEditor(imageBuffer, modelId, {
247
  size: output_size,
248
  aspect_ratio: "match_input_image",
249
  go_fast: true,
@@ -251,13 +210,10 @@ const handler = {
251
  output_quality: 100,
252
  disable_safety_checker: disable_safety_checker === 'true' || disable_safety_checker === true,
253
  });
254
-
255
- console.log("βœ… [9] ImageAIEditor response:", edit);
256
 
257
- return sendSuccess(res, edit.results || edit);
258
  } catch (e) {
259
- console.error("❌ [ERROR] Exception caught:", e);
260
- console.error("❌ [ERROR] Stack trace:", e.stack);
261
  return ErrorResponses.serverError(res, "An error occurred, try again later.");
262
  }
263
  });
 
4
  import axios from "axios";
5
  import path from "path";
6
 
7
+ const ModelMap = {
8
+ nano_banana: 2,
9
+ seed_dream: 5,
10
+ flux: 8,
11
+ qwen_image: 9
12
+ };
13
+
14
  const storage = multer.memoryStorage();
15
  const upload = multer({
16
  storage: storage,
 
27
  }
28
  });
29
 
 
 
 
 
 
 
 
30
  /** @type {import("../../types/plugin.ts").ApiPluginHandler}*/
31
  const handler = {
32
  name: "AI Image Editor",
 
36
  category: ["ai"],
37
  alias: ["aiImageEditor"],
38
  tags: ["ai", "image"],
 
 
 
39
  parameters: {
40
  body: [
41
  {
 
134
  }
135
  },
136
  exec: async (req, res) => {
 
 
 
137
  upload.single('image')(req, res, async (err) => {
 
 
138
  if (err) {
 
139
  if (err instanceof multer.MulterError) {
140
  if (err.code === 'LIMIT_FILE_SIZE') {
141
  return res.status(413).json({
 
150
  });
151
  }
152
 
 
 
 
 
153
  try {
154
+ const { prompt, output_size, disable_safety_checker, model } = req.body;
155
 
 
 
 
156
  if (!prompt) {
 
157
  return ErrorResponses.missingParameter(res, "prompt");
158
  }
159
  if (!output_size) {
 
160
  return ErrorResponses.missingParameter(res, "output_size");
161
  }
162
  if (!model) {
 
163
  return ErrorResponses.missingParameter(res, "model");
164
  }
165
 
 
166
  if (!ModelMap[model]) {
 
167
  return res.status(400).json({
168
  success: false,
169
  message: `Invalid model. Must be one of: ${Object.keys(ModelMap).join(', ')}`
170
  });
171
  }
172
 
 
173
  const ai = new AIEnhancer();
 
 
174
  let imageBuffer;
175
  let filename;
176
+
 
177
  if (req.file) {
 
178
  imageBuffer = req.file.buffer;
179
  filename = req.file.originalname;
180
  }
 
181
  else if (req.body.image && typeof req.body.image === 'string') {
 
182
  const imageUrl = req.body.image;
183
 
 
184
  try {
185
  new URL(imageUrl);
186
  } catch {
 
187
  return ErrorResponses.invalidUrl(res, "Invalid image URL");
188
  }
189
+
 
190
  const response = await axios.get(imageUrl, {
191
  responseType: 'arraybuffer',
192
  maxContentLength: 5 * 1024 * 1024,
 
198
 
199
  imageBuffer = Buffer.from(response.data);
200
  filename = path.basename(new URL(imageUrl).pathname) || 'image';
 
201
  } else {
 
202
  return ErrorResponses.missingParameter(res, "image (file or URL)");
203
  }
204
 
205
+ const edit = await ai.ImageAIEditor(imageBuffer, model, {
 
 
 
 
 
 
 
 
206
  size: output_size,
207
  aspect_ratio: "match_input_image",
208
  go_fast: true,
 
210
  output_quality: 100,
211
  disable_safety_checker: disable_safety_checker === 'true' || disable_safety_checker === true,
212
  });
 
 
213
 
214
+ return sendSuccess(res, edit.results);
215
  } catch (e) {
216
+ console.error("Exception caught:", e);
 
217
  return ErrorResponses.serverError(res, "An error occurred, try again later.");
218
  }
219
  });
src/server/plugins/ai/ai_image_utils.js CHANGED
@@ -1,3 +1,8 @@
 
 
 
 
 
1
  const ModelMap = {
2
  nano_banana: 2,
3
  seed_dream: 5,
 
1
+ import axios from "axios";
2
+ import { fileTypeFromBuffer } from "file-type";
3
+ import { readFileSync } from "fs";
4
+ import CryptoJS from "crypto-js";
5
+
6
  const ModelMap = {
7
  nano_banana: 2,
8
  seed_dream: 5,