HerzaJ commited on
Commit
3d28d9b
·
verified ·
1 Parent(s): d48fdca

Update plugins/img2gta.js

Browse files
Files changed (1) hide show
  1. plugins/img2gta.js +187 -109
plugins/img2gta.js CHANGED
@@ -101,29 +101,32 @@ class LightXBot {
101
  console.log('Response status:', response.status);
102
  console.log('Response data:', JSON.stringify(response.data));
103
 
104
- if (!response.data) {
105
- throw new Error('Response data is null or undefined');
106
- }
 
107
 
108
- if (!response.data.email || !response.data.token) {
109
- throw new Error(`Missing email or token in response: ${JSON.stringify(response.data)}`);
 
110
  }
111
 
112
- this.email = response.data.email;
113
- this.token = response.data.token;
114
-
115
  console.log(`Email created: ${this.email}`);
116
  return { email: this.email, token: this.token };
117
 
118
  } catch (error) {
119
  console.error(`Attempt ${i + 1} failed:`, error.message);
120
- console.error('Error details:', error.response?.data || error.stack);
 
 
 
 
121
 
122
  if (i === retries - 1) {
123
- throw new Error(`Failed to create temp email after ${retries} attempts: ${error.message}`);
124
  }
125
 
126
- await new Promise(resolve => setTimeout(resolve, 5000 * (i + 1)));
127
  }
128
  }
129
  }
@@ -134,21 +137,29 @@ class LightXBot {
134
 
135
  console.log(`Registering account for ${this.email}...`);
136
 
137
- const response = await axios.post(
138
- 'https://www.instagraphe.mobi/andor-login-1.0/mobile/emailSignup',
139
- {
140
- name: name,
141
- email: this.email,
142
- password: hashedPassword
143
- },
144
- {
145
- headers: { ...this.lightxHeaders, auth: JSON.stringify(this.authPayload) },
146
- timeout: 30000
 
 
 
 
 
 
 
 
 
 
147
  }
148
- );
149
-
150
- console.log('Registration response:', JSON.stringify(response.data));
151
- return response.data;
152
  }
153
 
154
  async waitForVerificationEmail(maxRetries = 40, interval = 6000) {
@@ -167,15 +178,13 @@ class LightXBot {
167
  if (response.data && response.data.length > 0) {
168
  console.log(`Found ${response.data.length} messages`);
169
 
170
- const verificationEmail = response.data.find(msg =>
171
- msg.subject === 'Welcome to LightX' && msg.body_text.includes('validate-email')
172
- );
173
-
174
- if (verificationEmail) {
175
- const linkMatch = verificationEmail.body_text.match(/https:\/\/www\.lightxeditor\.com\/validate-email\?[^\s)]+/);
176
- if (linkMatch) {
177
- console.log('Verification link found');
178
- return linkMatch[0];
179
  }
180
  }
181
  }
@@ -212,23 +221,48 @@ class LightXBot {
212
  console.log('Logging in...');
213
  const hashedPassword = this.hashPassword(this.password);
214
 
215
- const response = await axios.post(
216
- 'https://www.instagraphe.mobi/andor-login-1.0/mobile/login',
217
- {
218
- password: hashedPassword,
219
- type: 'EMAIL',
220
- value: this.email
221
- },
222
- {
223
- headers: { ...this.lightxHeaders, auth: JSON.stringify(this.authPayload) },
224
- timeout: 30000
 
 
 
 
 
 
 
 
 
225
  }
226
- );
227
-
228
- this.bearerToken = response.data.body.token.accessToken;
229
- this.systemRefKey = response.data.body.user.systemRefKey;
230
- console.log('Login successful');
231
- return response.data;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  }
233
 
234
  async checkCredits() {
@@ -238,16 +272,21 @@ class LightXBot {
238
  systemRefKey: this.systemRefKey
239
  };
240
 
241
- const response = await axios.get(
242
- 'https://www.instagraphe.mobi/andor-login-1.0/user/getAPIUsageDetails?apiId=1',
243
- {
244
- headers: { ...this.lightxHeaders, auth: JSON.stringify(authWithToken) },
245
- timeout: 25000
246
- }
247
- );
248
-
249
- console.log(`Credits remaining: ${response.data.body.remainingCalls}`);
250
- return response.data.body;
 
 
 
 
 
251
  }
252
 
253
  async uploadImage(imageBuffer, fileName, size) {
@@ -258,38 +297,43 @@ class LightXBot {
258
  systemRefKey: this.systemRefKey
259
  };
260
 
261
- const presignResponse = await axios.post(
262
- 'https://www.instagraphe.mobi/andor-media-1.0/content/generatePresignedUrls',
263
- {
264
- featureType: 'photoshoot',
265
- contents: [{
266
- size: size,
267
- contentType: 'image/jpeg',
268
- assetType: 'IMG',
269
- assetRefId: '1',
270
- name: fileName
271
- }]
272
- },
273
- {
274
- headers: { ...this.lightxHeaders, auth: JSON.stringify(authWithToken) },
275
- timeout: 30000
276
- }
277
- );
278
-
279
- const uploadData = presignResponse.data.body.contents[0];
280
- const presignedUrl = uploadData.presignedUrl;
281
- const imageUrl = uploadData.contentUrl;
282
-
283
- await axios.put(presignedUrl, imageBuffer, {
284
- headers: {
285
- 'Content-Type': 'image/jpeg',
286
- 'Content-Length': size
287
- },
288
- timeout: 60000
289
- });
290
-
291
- console.log('Image uploaded');
292
- return imageUrl;
 
 
 
 
 
293
  }
294
 
295
  async convertToGTAStyle(imageUrl, styleId) {
@@ -343,24 +387,29 @@ class LightXBot {
343
  };
344
 
345
  for (let i = 0; i < maxRetries; i++) {
346
- const response = await axios.post(
347
- 'https://www.instagraphe.mobi/andor-media-1.0/aiart/checkStatus',
348
- { assetId: assetId },
349
- {
350
- headers: { ...this.lightxHeaders, auth: JSON.stringify(authWithToken) },
351
- timeout: 25000
 
 
 
 
 
 
 
 
 
 
352
  }
353
- );
354
-
355
- const status = response.data.body.status;
356
- console.log(`Status check ${i + 1}: ${status}`);
357
-
358
- if (status === 'active') {
359
- console.log('Generation complete!');
360
- return response.data.body;
361
  }
362
-
363
- await new Promise(resolve => setTimeout(resolve, interval));
364
  }
365
 
366
  throw new Error('Generation timeout');
@@ -373,32 +422,49 @@ async function img2gta(imageUrl, styleId = 5, maxRetries = 3) {
373
  const bot = new LightXBot();
374
 
375
  try {
 
376
  await bot.createTempEmail();
377
 
 
378
  const randomName = 'User' + bot.generateRandomString(6);
379
  const randomPassword = 'Pass' + bot.generateRandomString(10) + '!';
380
 
 
381
  await bot.registerAccount(randomName, randomPassword);
 
 
382
  const verificationLink = await bot.waitForVerificationEmail();
 
 
383
  await bot.verifyEmail(verificationLink);
 
 
384
  await new Promise(resolve => setTimeout(resolve, 5000));
 
 
385
  await bot.login();
386
 
 
387
  const credits = await bot.checkCredits();
388
 
389
  if (credits.remainingCalls < 1) {
390
  throw new Error('No credits available');
391
  }
392
 
 
393
  const imageResponse = await axios.get(imageUrl, {
394
  responseType: 'arraybuffer',
395
  timeout: 45000
396
  });
397
  const imageBuffer = Buffer.from(imageResponse.data);
398
 
 
399
  const uploadedUrl = await bot.uploadImage(imageBuffer, 'image.jpg', imageBuffer.length);
 
 
400
  const result = await bot.convertToGTAStyle(uploadedUrl, styleId);
401
 
 
402
  return {
403
  success: true,
404
  styleName: bot.gtaStyles[styleId].name,
@@ -412,6 +478,7 @@ async function img2gta(imageUrl, styleId = 5, maxRetries = 3) {
412
 
413
  } catch (error) {
414
  console.error(`Attempt ${attempt} failed:`, error.message);
 
415
 
416
  if (attempt === maxRetries) {
417
  return {
@@ -421,15 +488,18 @@ async function img2gta(imageUrl, styleId = 5, maxRetries = 3) {
421
  };
422
  }
423
 
 
424
  await new Promise(resolve => setTimeout(resolve, 5000));
425
  }
426
  }
427
  }
428
 
 
429
  const handler = async (req, res) => {
430
  try {
431
  const { image, style, key } = req.query;
432
 
 
433
  if (!image || !key) {
434
  return res.status(400).json({
435
  success: false,
@@ -437,8 +507,10 @@ const handler = async (req, res) => {
437
  });
438
  }
439
 
 
440
  const styleId = style ? parseInt(style) : 5;
441
 
 
442
  if (styleId < 1 || styleId > 8) {
443
  return res.status(400).json({
444
  success: false,
@@ -456,8 +528,10 @@ const handler = async (req, res) => {
456
  });
457
  }
458
 
 
459
  const result = await img2gta(image, styleId);
460
 
 
461
  if (!result.success) {
462
  return res.status(500).json({
463
  success: false,
@@ -466,6 +540,7 @@ const handler = async (req, res) => {
466
  });
467
  }
468
 
 
469
  res.json({
470
  author: "Herza",
471
  success: true,
@@ -481,13 +556,16 @@ const handler = async (req, res) => {
481
  });
482
 
483
  } catch (error) {
 
484
  res.status(500).json({
485
  success: false,
486
- error: error.message
 
487
  });
488
  }
489
  };
490
 
 
491
  module.exports = {
492
  name: 'Image to GTA Converter',
493
  description: 'Convert photos to GTA style using AI with 8 different GTA game themes from 1997 to 2025',
 
101
  console.log('Response status:', response.status);
102
  console.log('Response data:', JSON.stringify(response.data));
103
 
104
+ // Langsung assign tanpa banyak validasi
105
+ const responseData = response.data;
106
+ this.email = responseData.email;
107
+ this.token = responseData.token;
108
 
109
+ // Validasi setelah assign
110
+ if (!this.email || !this.token) {
111
+ throw new Error(`Invalid data: email=${this.email}, token=${this.token}`);
112
  }
113
 
 
 
 
114
  console.log(`Email created: ${this.email}`);
115
  return { email: this.email, token: this.token };
116
 
117
  } catch (error) {
118
  console.error(`Attempt ${i + 1} failed:`, error.message);
119
+ if (error.response) {
120
+ console.error('Response status:', error.response.status);
121
+ console.error('Response headers:', error.response.headers);
122
+ console.error('Response data:', error.response.data);
123
+ }
124
 
125
  if (i === retries - 1) {
126
+ throw new Error(`Failed after ${retries} attempts: ${error.message}`);
127
  }
128
 
129
+ await new Promise(resolve => setTimeout(resolve, 3000));
130
  }
131
  }
132
  }
 
137
 
138
  console.log(`Registering account for ${this.email}...`);
139
 
140
+ try {
141
+ const response = await axios.post(
142
+ 'https://www.instagraphe.mobi/andor-login-1.0/mobile/emailSignup',
143
+ {
144
+ name: name,
145
+ email: this.email,
146
+ password: hashedPassword
147
+ },
148
+ {
149
+ headers: { ...this.lightxHeaders, auth: JSON.stringify(this.authPayload) },
150
+ timeout: 30000
151
+ }
152
+ );
153
+
154
+ console.log('Registration response:', JSON.stringify(response.data));
155
+ return response.data;
156
+ } catch (error) {
157
+ console.error('Registration error:', error.message);
158
+ if (error.response) {
159
+ console.error('Registration response:', error.response.data);
160
  }
161
+ throw error;
162
+ }
 
 
163
  }
164
 
165
  async waitForVerificationEmail(maxRetries = 40, interval = 6000) {
 
178
  if (response.data && response.data.length > 0) {
179
  console.log(`Found ${response.data.length} messages`);
180
 
181
+ for (const msg of response.data) {
182
+ if (msg.body_text && msg.body_text.includes('validate-email')) {
183
+ const linkMatch = msg.body_text.match(/https:\/\/www\.lightxeditor\.com\/validate-email\?[^\s)]+/);
184
+ if (linkMatch) {
185
+ console.log('Verification link found');
186
+ return linkMatch[0];
187
+ }
 
 
188
  }
189
  }
190
  }
 
221
  console.log('Logging in...');
222
  const hashedPassword = this.hashPassword(this.password);
223
 
224
+ try {
225
+ const response = await axios.post(
226
+ 'https://www.instagraphe.mobi/andor-login-1.0/mobile/login',
227
+ {
228
+ password: hashedPassword,
229
+ type: 'EMAIL',
230
+ value: this.email
231
+ },
232
+ {
233
+ headers: { ...this.lightxHeaders, auth: JSON.stringify(this.authPayload) },
234
+ timeout: 30000
235
+ }
236
+ );
237
+
238
+ console.log('Login response:', JSON.stringify(response.data));
239
+
240
+ // Validasi response structure
241
+ if (!response.data || !response.data.body) {
242
+ throw new Error(`Invalid login response: ${JSON.stringify(response.data)}`);
243
  }
244
+
245
+ if (!response.data.body.token || !response.data.body.user) {
246
+ throw new Error(`Missing token or user: ${JSON.stringify(response.data.body)}`);
247
+ }
248
+
249
+ this.bearerToken = response.data.body.token.accessToken;
250
+ this.systemRefKey = response.data.body.user.systemRefKey;
251
+
252
+ if (!this.bearerToken || !this.systemRefKey) {
253
+ throw new Error(`Token/RefKey is null: token=${this.bearerToken}, refKey=${this.systemRefKey}`);
254
+ }
255
+
256
+ console.log('Login successful');
257
+ return response.data;
258
+
259
+ } catch (error) {
260
+ console.error('Login error:', error.message);
261
+ if (error.response) {
262
+ console.error('Login response:', error.response.data);
263
+ }
264
+ throw error;
265
+ }
266
  }
267
 
268
  async checkCredits() {
 
272
  systemRefKey: this.systemRefKey
273
  };
274
 
275
+ try {
276
+ const response = await axios.get(
277
+ 'https://www.instagraphe.mobi/andor-login-1.0/user/getAPIUsageDetails?apiId=1',
278
+ {
279
+ headers: { ...this.lightxHeaders, auth: JSON.stringify(authWithToken) },
280
+ timeout: 25000
281
+ }
282
+ );
283
+
284
+ console.log(`Credits remaining: ${response.data.body.remainingCalls}`);
285
+ return response.data.body;
286
+ } catch (error) {
287
+ console.error('Check credits error:', error.message);
288
+ throw error;
289
+ }
290
  }
291
 
292
  async uploadImage(imageBuffer, fileName, size) {
 
297
  systemRefKey: this.systemRefKey
298
  };
299
 
300
+ try {
301
+ const presignResponse = await axios.post(
302
+ 'https://www.instagraphe.mobi/andor-media-1.0/content/generatePresignedUrls',
303
+ {
304
+ featureType: 'photoshoot',
305
+ contents: [{
306
+ size: size,
307
+ contentType: 'image/jpeg',
308
+ assetType: 'IMG',
309
+ assetRefId: '1',
310
+ name: fileName
311
+ }]
312
+ },
313
+ {
314
+ headers: { ...this.lightxHeaders, auth: JSON.stringify(authWithToken) },
315
+ timeout: 30000
316
+ }
317
+ );
318
+
319
+ const uploadData = presignResponse.data.body.contents[0];
320
+ const presignedUrl = uploadData.presignedUrl;
321
+ const imageUrl = uploadData.contentUrl;
322
+
323
+ await axios.put(presignedUrl, imageBuffer, {
324
+ headers: {
325
+ 'Content-Type': 'image/jpeg',
326
+ 'Content-Length': size
327
+ },
328
+ timeout: 60000
329
+ });
330
+
331
+ console.log('Image uploaded');
332
+ return imageUrl;
333
+ } catch (error) {
334
+ console.error('Upload image error:', error.message);
335
+ throw error;
336
+ }
337
  }
338
 
339
  async convertToGTAStyle(imageUrl, styleId) {
 
387
  };
388
 
389
  for (let i = 0; i < maxRetries; i++) {
390
+ try {
391
+ const response = await axios.post(
392
+ 'https://www.instagraphe.mobi/andor-media-1.0/aiart/checkStatus',
393
+ { assetId: assetId },
394
+ {
395
+ headers: { ...this.lightxHeaders, auth: JSON.stringify(authWithToken) },
396
+ timeout: 25000
397
+ }
398
+ );
399
+
400
+ const status = response.data.body.status;
401
+ console.log(`Status check ${i + 1}: ${status}`);
402
+
403
+ if (status === 'active') {
404
+ console.log('Generation complete!');
405
+ return response.data.body;
406
  }
407
+
408
+ await new Promise(resolve => setTimeout(resolve, interval));
409
+ } catch (error) {
410
+ console.error(`Status check error: ${error.message}`);
411
+ if (i === maxRetries - 1) throw error;
 
 
 
412
  }
 
 
413
  }
414
 
415
  throw new Error('Generation timeout');
 
422
  const bot = new LightXBot();
423
 
424
  try {
425
+ // Step 1: Create temp email
426
  await bot.createTempEmail();
427
 
428
+ // Step 2: Generate random credentials
429
  const randomName = 'User' + bot.generateRandomString(6);
430
  const randomPassword = 'Pass' + bot.generateRandomString(10) + '!';
431
 
432
+ // Step 3: Register account
433
  await bot.registerAccount(randomName, randomPassword);
434
+
435
+ // Step 4: Wait for verification email
436
  const verificationLink = await bot.waitForVerificationEmail();
437
+
438
+ // Step 5: Verify email
439
  await bot.verifyEmail(verificationLink);
440
+
441
+ // Step 6: Wait before login
442
  await new Promise(resolve => setTimeout(resolve, 5000));
443
+
444
+ // Step 7: Login
445
  await bot.login();
446
 
447
+ // Step 8: Check credits
448
  const credits = await bot.checkCredits();
449
 
450
  if (credits.remainingCalls < 1) {
451
  throw new Error('No credits available');
452
  }
453
 
454
+ // Step 9: Download image
455
  const imageResponse = await axios.get(imageUrl, {
456
  responseType: 'arraybuffer',
457
  timeout: 45000
458
  });
459
  const imageBuffer = Buffer.from(imageResponse.data);
460
 
461
+ // Step 10: Upload image
462
  const uploadedUrl = await bot.uploadImage(imageBuffer, 'image.jpg', imageBuffer.length);
463
+
464
+ // Step 11: Convert to GTA style
465
  const result = await bot.convertToGTAStyle(uploadedUrl, styleId);
466
 
467
+ // Success!
468
  return {
469
  success: true,
470
  styleName: bot.gtaStyles[styleId].name,
 
478
 
479
  } catch (error) {
480
  console.error(`Attempt ${attempt} failed:`, error.message);
481
+ console.error('Error stack:', error.stack);
482
 
483
  if (attempt === maxRetries) {
484
  return {
 
488
  };
489
  }
490
 
491
+ // Wait before retry
492
  await new Promise(resolve => setTimeout(resolve, 5000));
493
  }
494
  }
495
  }
496
 
497
+ // API Handler for Hugging Face
498
  const handler = async (req, res) => {
499
  try {
500
  const { image, style, key } = req.query;
501
 
502
+ // Validate required parameters
503
  if (!image || !key) {
504
  return res.status(400).json({
505
  success: false,
 
507
  });
508
  }
509
 
510
+ // Parse style ID
511
  const styleId = style ? parseInt(style) : 5;
512
 
513
+ // Validate style ID
514
  if (styleId < 1 || styleId > 8) {
515
  return res.status(400).json({
516
  success: false,
 
528
  });
529
  }
530
 
531
+ // Process image
532
  const result = await img2gta(image, styleId);
533
 
534
+ // Check if conversion failed
535
  if (!result.success) {
536
  return res.status(500).json({
537
  success: false,
 
540
  });
541
  }
542
 
543
+ // Return success response
544
  res.json({
545
  author: "Herza",
546
  success: true,
 
556
  });
557
 
558
  } catch (error) {
559
+ console.error('Handler error:', error);
560
  res.status(500).json({
561
  success: false,
562
+ error: error.message,
563
+ stack: error.stack
564
  });
565
  }
566
  };
567
 
568
+ // Export for Hugging Face
569
  module.exports = {
570
  name: 'Image to GTA Converter',
571
  description: 'Convert photos to GTA style using AI with 8 different GTA game themes from 1997 to 2025',