Puruu Puruu commited on
Commit
60a7dd1
·
1 Parent(s): 8065f56

Ghibli AI

Browse files
Files changed (2) hide show
  1. features/ghibli-remix.js +125 -0
  2. index.js +5 -2
features/ghibli-remix.js ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Lokasi: features/ghibli-remix.js
3
+ * Versi: v1
4
+ */
5
+
6
+ const axios = require('axios');
7
+ const { createDecipheriv } = require('crypto');
8
+
9
+ async function sendCallback(url, payload) {
10
+ try {
11
+ await axios.post(url, payload, { headers: { 'Content-Type': 'application/json' } });
12
+ } catch (error) {
13
+ console.error('Callback failed:', error.response ? error.response.data : error.message);
14
+ }
15
+ }
16
+
17
+ const ghibai = {
18
+ api: {
19
+ base: 'https://generate-api.ghibli-gpt.net',
20
+ endpoints: {
21
+ generate: '/v1/gpt4o-image/generate',
22
+ task: '/v1/gpt4o-image/record-info',
23
+ },
24
+ },
25
+ headers: {
26
+ accept: '*/*',
27
+ 'content-type': 'application/json',
28
+ origin: 'https://ghibli-gpt.net',
29
+ referer: 'https://ghibli-gpt.net/',
30
+ 'user-agent': 'NB Android/1.0.0',
31
+ authorization: ''
32
+ },
33
+ state: { token: null },
34
+ security: {
35
+ keyBase64: 'UBsnTxs80g8p4iW72eYyPaDvGZbpzun8K2cnoSSEz1Y',
36
+ ivBase64: 'fG1SBDUyE2IG8kPw',
37
+ ciphertextBase64: '2QpqZCkOD/WMHixMqt46AvhdKRYgy5aUMLXi6D0nOPGuDbH4gbNKDV0ZW/+9w9I=',
38
+ decrypt: async () => {
39
+ if (ghibai.state.token) return ghibai.state.token;
40
+ const buf = k => Buffer.from(ghibai.security[k], 'base64');
41
+ const [key, iv, ciphertext] = ['keyBase64', 'ivBase64', 'ciphertextBase64'].map(buf);
42
+ const decipher = createDecipheriv('aes-256-gcm', key, iv);
43
+ decipher.setAuthTag(ciphertext.slice(-16));
44
+ const decrypted = decipher.update(ciphertext.slice(0, -16), undefined, 'utf8') + decipher.final('utf8');
45
+ ghibai.state.token = decrypted;
46
+ ghibai.headers.authorization = `Bearer ${decrypted}`;
47
+ return decrypted;
48
+ }
49
+ },
50
+ getTask: async (jobDetails) => {
51
+ const { taskId, prompt, jobId, callbackUrl, callbackKey } = jobDetails;
52
+ await ghibai.security.decrypt();
53
+
54
+ for (let i = 0; i < 60; i++) {
55
+ try {
56
+ const { data } = await axios.get(`${ghibai.api.base}${ghibai.api.endpoints.task}?taskId=${taskId}`, { headers: ghibai.headers });
57
+ const d = data?.data || {};
58
+ const status = d.status || 'unknown';
59
+
60
+ if (status === 'SUCCESS' && d.response?.resultUrls?.length) {
61
+ return await sendCallback(callbackUrl, {
62
+ jobId, callbackKey, status: 'success',
63
+ result: {
64
+ prompt,
65
+ imageUrl: d.response.resultUrls[0],
66
+ thumbnailUrl: d.response.thumbnailUrls?.[0],
67
+ }
68
+ });
69
+ }
70
+ await new Promise(r => setTimeout(r, 3000));
71
+ } catch (err) {
72
+ if (err.response?.status === 429) {
73
+ await new Promise(r => setTimeout(r, 5000));
74
+ continue;
75
+ }
76
+ return await sendCallback(callbackUrl, {
77
+ jobId, callbackKey, status: 'failed',
78
+ result: { error: 'Failed to poll task status.', details: err.message }
79
+ });
80
+ }
81
+ }
82
+ await sendCallback(callbackUrl, {
83
+ jobId, callbackKey, status: 'failed',
84
+ result: { error: 'Task polling timed out after several attempts.' }
85
+ });
86
+ },
87
+ generate: async (jobDetails) => {
88
+ const { imageDataUri, prompt, size } = jobDetails;
89
+ await ghibai.security.decrypt();
90
+
91
+ try {
92
+ const { data } = await axios.post(
93
+ `${ghibai.api.base}${ghibai.api.endpoints.generate}`,
94
+ { filesUrl: [''], files: [imageDataUri], prompt, size, nVariants: 1 },
95
+ { headers: ghibai.headers }
96
+ );
97
+ const taskId = data?.data?.taskId;
98
+ if (!taskId) {
99
+ throw new Error('Failed to retrieve Task ID from the generation API.');
100
+ }
101
+ await ghibai.getTask({ ...jobDetails, taskId });
102
+ } catch (err) {
103
+ if (err.response?.status === 429) {
104
+ await new Promise(r => setTimeout(r, 5000));
105
+ return await ghibai.generate(jobDetails);
106
+ }
107
+ await sendCallback(jobDetails.callbackUrl, {
108
+ jobId: jobDetails.jobId, callbackKey: jobDetails.callbackKey, status: 'failed',
109
+ result: { error: 'Failed to initiate image generation.', details: err.message }
110
+ });
111
+ }
112
+ }
113
+ };
114
+
115
+ module.exports = async function(req, res) {
116
+ const { imageDataUri, prompt, size, jobId, callbackUrl, callbackKey } = req.body;
117
+
118
+ if (!imageDataUri || !prompt || !jobId || !callbackUrl || !callbackKey) {
119
+ return res.status(400).json({ error: 'Missing required parameters for worker.' });
120
+ }
121
+
122
+ res.status(202).json({ message: 'Job accepted by worker and is being processed in the background.' });
123
+
124
+ ghibai.generate({ imageDataUri, prompt, size, jobId, callbackUrl, callbackKey });
125
+ };
index.js CHANGED
@@ -1,16 +1,18 @@
1
  /*
2
  * Lokasi: index.js
3
- * Versi: v2
4
  */
5
 
6
  const express = require('express');
7
  const upscaleFeature = require('./features/upscale.js');
8
  const imageDescribeFeature = require('./features/image-describe.js');
 
9
 
10
  const app = express();
11
  const port = process.env.PORT || 7860;
12
 
13
- app.use(express.json());
 
14
 
15
  app.get('/', (req, res) => {
16
  res.status(200).json({ status: 'ok', message: 'Worker server is running.' });
@@ -18,6 +20,7 @@ app.get('/', (req, res) => {
18
 
19
  app.post('/upscale', upscaleFeature);
20
  app.post('/image-describe', imageDescribeFeature);
 
21
 
22
  app.listen(port, () => {
23
  console.log(`Worker server listening on port ${port}`);
 
1
  /*
2
  * Lokasi: index.js
3
+ * Versi: v3
4
  */
5
 
6
  const express = require('express');
7
  const upscaleFeature = require('./features/upscale.js');
8
  const imageDescribeFeature = require('./features/image-describe.js');
9
+ const ghibliRemixFeature = require('./features/ghibli-remix.js');
10
 
11
  const app = express();
12
  const port = process.env.PORT || 7860;
13
 
14
+ app.use(express.json({ limit: '10mb' }));
15
+ app.use(express.urlencoded({ extended: true, limit: '10mb' }));
16
 
17
  app.get('/', (req, res) => {
18
  res.status(200).json({ status: 'ok', message: 'Worker server is running.' });
 
20
 
21
  app.post('/upscale', upscaleFeature);
22
  app.post('/image-describe', imageDescribeFeature);
23
+ app.post('/ghibli-remix', ghibliRemixFeature);
24
 
25
  app.listen(port, () => {
26
  console.log(`Worker server listening on port ${port}`);