HerzaJ commited on
Commit
2cbfb34
·
verified ·
1 Parent(s): 96a61fd

Create suno4.js

Browse files
Files changed (1) hide show
  1. plugins/suno4.js +416 -0
plugins/suno4.js ADDED
@@ -0,0 +1,416 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const crypto = require('crypto');
3
+
4
+ const aiMu = {
5
+ api: {
6
+ base: 'https://aimu.1010diy.com',
7
+ endpoint: {
8
+ credits: '/and/getUserActualCredits',
9
+ musicAI: '/music/MusicAI',
10
+ taskStatus: '/music/getTaskStatus',
11
+ generateList: '/and/data/generateList',
12
+ options: '/and/home/index',
13
+ },
14
+ },
15
+
16
+ headers: {
17
+ 'user-agent': 'NB Android/1.0.0',
18
+ 'accept-encoding': 'gzip',
19
+ 'x-version-code': '27',
20
+ 'x-token': '',
21
+ },
22
+
23
+ sid: null,
24
+
25
+ setDeviceId: (id) => {
26
+ aiMu.sid = id;
27
+ },
28
+
29
+ getDeviceId: () => {
30
+ if (!aiMu.sid) {
31
+ aiMu.sid = crypto.randomBytes(8).toString('hex');
32
+ }
33
+ return aiMu.sid;
34
+ },
35
+
36
+ opts: async () => {
37
+ try {
38
+ const res = await axios.get(
39
+ `${aiMu.api.base}${aiMu.api.endpoint.options}`,
40
+ { headers: { ...aiMu.headers, 'x-device-id': aiMu.getDeviceId() } }
41
+ );
42
+
43
+ const { code, msg, data } = res.data;
44
+ if (code !== 200) {
45
+ return {
46
+ success: false,
47
+ code,
48
+ author: 'Daffa ~',
49
+ team: 'NB Team',
50
+ result: {
51
+ error: { msg }
52
+ }
53
+ };
54
+ }
55
+
56
+ const moods = [...(data.mood?.default || []), ...(data.mood?.more || [])].map(m => m.text);
57
+ const genres = [...(data.genre?.default || []), ...(data.genre?.more || [])].map(g => g.text);
58
+ const voices = ['female', 'male', 'random'];
59
+
60
+ return {
61
+ success: true,
62
+ code: 200,
63
+ author: 'Daffa ~',
64
+ team: 'NB Team',
65
+ result: {
66
+ moods,
67
+ genres,
68
+ voices
69
+ }
70
+ };
71
+ } catch (err) {
72
+ return {
73
+ success: false,
74
+ code: err.response?.status || 500,
75
+ author: 'Daffa ~',
76
+ team: 'NB Team',
77
+ result: {
78
+ error: err.message
79
+ }
80
+ };
81
+ }
82
+ },
83
+
84
+ getCredits: async () => {
85
+ try {
86
+ const res = await axios.get(
87
+ `${aiMu.api.base}${aiMu.api.endpoint.credits}`,
88
+ { headers: { ...aiMu.headers, 'x-device-id': aiMu.getDeviceId() } }
89
+ );
90
+ const { code, msg, data } = res.data;
91
+ if (code === 200) {
92
+ return {
93
+ success: true,
94
+ code: 200,
95
+ author: 'Daffa ~',
96
+ team: 'NB Team',
97
+ result: {
98
+ ...data
99
+ }
100
+ };
101
+ }
102
+ return {
103
+ success: false,
104
+ code,
105
+ author: 'Daffa ~',
106
+ team: 'NB Team',
107
+ result: {
108
+ error: msg
109
+ }
110
+ };
111
+ } catch (err) {
112
+ return {
113
+ success: false,
114
+ code: err.response?.status || 500,
115
+ author: 'Daffa ~',
116
+ team: 'NB Team',
117
+ result: {
118
+ error: err.message
119
+ }
120
+ };
121
+ }
122
+ },
123
+
124
+ generate: async (params) => {
125
+ let make_instrumental = params.make_instrumental ? 1 : 0;
126
+ let vocal_only = params.vocal_only ? 1 : 0;
127
+ if (make_instrumental === 1) vocal_only = 0;
128
+
129
+ const { lyrics = '', prompt = '' } = params;
130
+ if (!lyrics.trim() && !prompt.trim()) {
131
+ return {
132
+ success: false,
133
+ code: 400,
134
+ author: 'Daffa ~',
135
+ team: 'NB Team',
136
+ result: {
137
+ error: 'Lu bisa pilih Lyric atau Prompt bree'
138
+ }
139
+ };
140
+ }
141
+
142
+ if (prompt && prompt.length > 1000) {
143
+ return {
144
+ success: false,
145
+ code: 400,
146
+ author: 'Daffa ~',
147
+ team: 'NB Team',
148
+ result: {
149
+ error: 'Promptnya kepanjangan yak, max 1k karakter aja.. '
150
+ }
151
+ };
152
+ }
153
+
154
+ const payload = { make_instrumental, vocal_only, lyrics, prompt, ...params };
155
+
156
+ try {
157
+ const res = await axios.post(
158
+ `${aiMu.api.base}${aiMu.api.endpoint.musicAI}`,
159
+ payload,
160
+ {
161
+ headers: {
162
+ ...aiMu.headers,
163
+ 'content-type': 'application/json',
164
+ 'x-device-id': aiMu.getDeviceId(),
165
+ },
166
+ }
167
+ );
168
+ const { code, msg, data } = res.data;
169
+ if (code === 200) {
170
+ return {
171
+ success: true,
172
+ code: 200,
173
+ author: 'Daffa ~',
174
+ team: 'NB Team',
175
+ result: {
176
+ taskId: data?.task_id,
177
+ inputType: prompt ? 'prompt' : 'lyrics',
178
+ inputValue: prompt || lyrics
179
+ }
180
+ };
181
+ }
182
+ return {
183
+ success: false,
184
+ code,
185
+ author: 'Daffa ~',
186
+ team: 'NB Team',
187
+ result: {
188
+ error: msg
189
+ }
190
+ };
191
+ } catch (err) {
192
+ return {
193
+ success: false,
194
+ code: err.response?.status || 500,
195
+ author: 'Daffa ~',
196
+ team: 'NB Team',
197
+ result: {
198
+ error: err.message
199
+ }
200
+ };
201
+ }
202
+ },
203
+
204
+ polling: async (taskId) => {
205
+ if (!String(taskId)?.trim()) {
206
+ return {
207
+ success: false,
208
+ code: 400,
209
+ author: 'Daffa ~',
210
+ team: 'NB Team',
211
+ result: {
212
+ error: 'Task IDnya kagak boleh kosong bree... '
213
+ }
214
+ };
215
+ }
216
+ try {
217
+ const res = await axios.get(
218
+ `${aiMu.api.base}${aiMu.api.endpoint.taskStatus}`,
219
+ {
220
+ params: { task_id: taskId },
221
+ headers: { ...aiMu.headers, 'x-device-id': aiMu.getDeviceId() },
222
+ }
223
+ );
224
+ const { code, msg, data } = res.data;
225
+ if (code === 200) {
226
+ return {
227
+ success: true,
228
+ code: 200,
229
+ author: 'Daffa ~',
230
+ team: 'NB Team',
231
+ result: {
232
+ status: data?.status,
233
+ }
234
+ };
235
+ }
236
+ return {
237
+ success: false,
238
+ code,
239
+ author: 'Daffa ~',
240
+ team: 'NB Team',
241
+ result: {
242
+ error: msg
243
+ }
244
+ };
245
+ } catch (err) {
246
+ return {
247
+ success: false,
248
+ code: err.response?.status || 500,
249
+ author: 'Daffa ~',
250
+ team: 'NB Team',
251
+ result: {
252
+ error: err.message
253
+ }
254
+ };
255
+ }
256
+ },
257
+
258
+ getGenerateList: async () => {
259
+ try {
260
+ const res = await axios.get(
261
+ `${aiMu.api.base}${aiMu.api.endpoint.generateList}`,
262
+ { headers: { ...aiMu.headers, 'x-device-id': aiMu.getDeviceId() } }
263
+ );
264
+ const { code, msg, data } = res.data;
265
+ if (code === 200) {
266
+ const results = (data || []).map((item) => ({
267
+ taskId: item.task_id,
268
+ title: item.title,
269
+ duration: item.duration,
270
+ mp3: item.conversion_path,
271
+ cover: item.album_cover_path,
272
+ input: item.lyrics,
273
+ created_at: item.created_at,
274
+ updated_at: item.updated_at,
275
+ }));
276
+ return {
277
+ success: true,
278
+ code: 200,
279
+ author: 'Daffa ~',
280
+ team: 'NB Team',
281
+ result: {
282
+ results
283
+ }
284
+ };
285
+ }
286
+ return {
287
+ success: false,
288
+ code,
289
+ author: 'Daffa ~',
290
+ team: 'NB Team',
291
+ result: {
292
+ error: msg
293
+ }
294
+ };
295
+ } catch (err) {
296
+ return {
297
+ success: false,
298
+ code: err.response?.status || 500,
299
+ author: 'Daffa ~',
300
+ team: 'NB Team',
301
+ result: {
302
+ error: err.message
303
+ }
304
+ };
305
+ }
306
+ },
307
+
308
+ task: async (taskId, inputType, inputValue, intervalMs = 5000) => {
309
+ if (!String(taskId)?.trim()) {
310
+ return {
311
+ success: false,
312
+ code: 400,
313
+ author: 'Daffa ~',
314
+ team: 'NB Team',
315
+ result: {
316
+ error: 'Task IDnya kagak boleh kosong bree... '
317
+ }
318
+ };
319
+ }
320
+
321
+ while (true) {
322
+ const resx = await aiMu.polling(taskId);
323
+ if (!resx.success) return resx;
324
+
325
+ if (resx.result.status === 'complete') {
326
+ const re = await aiMu.getGenerateList();
327
+ if (!re.success) return re;
328
+
329
+ const tracks = re.result.results.filter((r) => String(r.taskId) === String(taskId));
330
+
331
+ const avr = tracks.every((t) => t.mp3.includes('vocal-remover.s3.us-west-2.amazonaws.com'));
332
+
333
+ if (tracks.length > 0 && avr) {
334
+ return {
335
+ success: true,
336
+ code: 200,
337
+ author: 'Daffa ~',
338
+ team: 'NB Team',
339
+ result: {
340
+ taskId: String(taskId),
341
+ count: tracks.length,
342
+ tracks: tracks.map((t) => ({
343
+ title: t.title,
344
+ duration: t.duration,
345
+ audio: t.mp3,
346
+ cover: t.cover,
347
+ [inputType]: t.input,
348
+ created_at: t.created_at,
349
+ updated_at: t.updated_at,
350
+ })),
351
+ inputValue
352
+ }
353
+ };
354
+ }
355
+ }
356
+
357
+ await new Promise((r) => setTimeout(r, intervalMs));
358
+ }
359
+ },
360
+ };
361
+
362
+ const handler = async (req, res) => {
363
+ try {
364
+ const { prompt, lyrics, mood, genre, voice, key } = req.query;
365
+
366
+ if (!prompt && !lyrics) {
367
+ return res.status(400).json({
368
+ success: false,
369
+ error: 'Missing required parameter: prompt or lyrics'
370
+ });
371
+ }
372
+
373
+ const params = {
374
+ prompt: prompt || '',
375
+ lyrics: lyrics || '',
376
+ mood: mood || '',
377
+ genre: genre || '',
378
+ voice: voice || 'random',
379
+ make_instrumental: false,
380
+ vocal_only: false
381
+ };
382
+
383
+ const genResult = await aiMu.generate(params);
384
+
385
+ if (!genResult.success) {
386
+ return res.status(400).json(genResult);
387
+ }
388
+
389
+ const taskId = genResult.result.taskId;
390
+ const inputType = genResult.result.inputType;
391
+ const inputValue = genResult.result.inputValue;
392
+
393
+ const taskResult = await aiMu.task(taskId, inputType, inputValue);
394
+
395
+ res.json(taskResult);
396
+
397
+ } catch (error) {
398
+ res.status(500).json({
399
+ success: false,
400
+ error: error.message
401
+ });
402
+ }
403
+ };
404
+
405
+ module.exports = {
406
+ name: 'AiMu Music Generator',
407
+ description: 'Generate music using AiMu AI model',
408
+ type: 'GET',
409
+ routes: ['api/AI/suno4'],
410
+ tags: ['ai', 'music', 'aimu', 'suno'],
411
+ main: ['AI'],
412
+ parameters: ['prompt', 'lyrics', 'mood', 'genre', 'voice', 'key'],
413
+ enabled: true,
414
+ limit: 18,
415
+ handler
416
+ };