zona.mjs
javascript•Created 26 Mar 2026, 11:31•97 views
Ai song generator with lyrics or description, Wrapper from Zona apk
#ai#music#song
javascript
0 lines
/***
@ Base: https://play.google.com/store/apps/details?id=com.zona.aimusic
@ Author: Shannz
@ Note: Ai song generator with lyrics or description, Wrapper from Zona apk
***/
import jwt from 'jsonwebtoken';
import crypto from 'crypto';
const CONFIG = {
BASE_URL: "https://zona-backend-production.onrender.com",
SECRET_KEY: "c5933031d2b07fa4a3133cbd3f5a21fe8a0e0e9b6cb52d36e70402e81688d3b4",
POLL_INTERVAL: 5000,
MAX_RETRIES: 24,
HEADERS: {
'User-Agent': 'okhttp/4.12.0',
'Accept': 'application/json',
'Content-Type': 'application/json',
'platform': 'android',
'locale': 'en',
'app-version': '7.5.7'
}
};
const utils = {
generateDeviceId: () => crypto.randomBytes(8).toString('hex'),
generateAuthPayload: (deviceId) => jwt.sign({ device_id: deviceId }, CONFIG.SECRET_KEY, { noTimestamp: true }),
sleep: (ms) => new Promise(resolve => setTimeout(resolve, ms)),
filterResponse: (data) => {
const transform = (item) => ({
id: item.id,
status: item.status,
title: item.title || "Untitled",
audio_url: item.audio_url,
image_url: item.image_large_url || item.image_url,
created_at: item.created_at
});
if (Array.isArray(data)) return data.map(transform);
if (data && data.rows) return data.rows.map(transform);
return data ? transform(data) : null;
}
};
export const zona = {
getToken: async (deviceId = utils.generateDeviceId()) => {
try {
const tokenJwt = utils.generateAuthPayload(deviceId);
const response = await fetch(`${CONFIG.BASE_URL}/register`, {
method: 'POST',
headers: CONFIG.HEADERS,
body: tokenJwt
});
const resData = await response.json();
return resData.token;
} catch (error) {
return null;
}
},
pollStatus: async (token, targetIds) => {
console.log(`[wait] Sedang memproses musik (${targetIds.join('& ')})...`);
let retries = 0;
while (retries < CONFIG.MAX_RETRIES) {
await utils.sleep(CONFIG.POLL_INTERVAL);
const library = await zona.getLibrary(token);
const matches = library.filter(item => targetIds.includes(item.id));
const isReady = matches.every(m => m.status === 'streaming' || m.audio_url);
if (isReady && matches.length > 0) {
console.log(`[✔] Musik siap!`);
return matches;
}
retries++;
console.log(`[..] Masih diproses... (Percobaan ${retries}/${CONFIG.MAX_RETRIES})`);
}
console.error("[-] Timeout: Musik memakan waktu terlalu lama.");
return null;
},
genSmart: async (prompt, isInstrumental = false) => {
const token = await zona.getToken();
try {
const response = await fetch(`${CONFIG.BASE_URL}/prediction/predict/smart`, {
method: 'POST',
headers: { ...CONFIG.HEADERS, 'authorization': `Bearer ${token}` },
body: JSON.stringify({
gpt_description_prompt: prompt,
make_instrumental: isInstrumental
})
});
const resData = await response.json();
const initialData = utils.filterResponse(resData);
const ids = initialData.map(item => item.id);
return await zona.pollStatus(token, ids);
} catch (error) {
return null;
}
},
genLyrics: async ({ title, lyrics, tags, isInstrumental = false }) => {
const token = await zona.getToken();
try {
const response = await fetch(`${CONFIG.BASE_URL}/prediction/predict/custom`, {
method: 'POST',
headers: { ...CONFIG.HEADERS, 'authorization': `Bearer ${token}` },
body: JSON.stringify({
prompt: lyrics,
tags: tags,
title: title,
instrumental: isInstrumental
})
});
const resData = await response.json();
const initialData = utils.filterResponse(resData);
const ids = initialData.map(item => item.id);
return await zona.pollStatus(token, ids);
} catch (error) {
return null;
}
},
getLibrary: async (token, page = 1) => {
try {
const response = await fetch(`${CONFIG.BASE_URL}/users/library/prediction/list`, {
method: 'POST',
headers: { ...CONFIG.HEADERS, 'authorization': `Bearer ${token}` },
body: JSON.stringify({ page: page, sort: "new_to_old" })
});
const resData = await response.json();
return utils.filterResponse(resData);
} catch (error) {
return [];
}
}
};
/*
(async () => {
// 1. Generate by prompt
console.log('--- GENERATE MUSIC SMART BY PROMPT ---');
const res1 = await zona.genSmart("Lagu galau akustik tentang kopi", false);
console.log("Hasil Generate Smart:", res1);
// 2. Generate by lyrics
console.log('--- GENERATE MUSIC BY LYRICS ---');
const res2 = await zona.genLyrics({
prompt: "[Intro]\nWhispers of yesterday, echoes in my mind\nTrying to find peace, leaving you behind\n\n[Verse 1]\nWe danced through storms, glimpses of a brighter view\nNow I walk alone, trying to forget you\nMemories like shadows, flicker in the night\nHoping someday, I'll find the light\n\n[Pre-Chorus]\nStill feel your voice, in the silent air\nEvery word, a ghost that lingers there\nBut I know I must move on, set myself free\nFrom the love that used to be\n\n[Chorus]\nSurat cinta untuk mantan, words left unsaid\nLetters of longing, traces of what we had\nThough time has passed, your shadow still remains\nIn my heart, in my veins\n\n[Bridge]\nMaybe someday, I’ll read these lines again\nAnd smile at love’s bittersweet pain\nUntil then, I hold on to the past\nHoping it won’t last\n\n[Outro]\nGoodbye, my love, tears fall like rain\nSurat cinta untuk mantan, easing the pain\nFarewell to what we used to be\nYou set me free",
tags: "Emotional pop ballad, acoustic guitar, piano, gentle drums, heartfelt vocals",
title: "Surat Cinta untuk Mantan",
isInstrumental: false
});
console.log("Hasil Generate By Lyrics:", res2);
})();
*/