Upload 36 files
Browse files- plugins/aio.js +39 -0
- plugins/apple.js +213 -0
- plugins/brat.js +61 -0
- plugins/cloudflare-bypass.js +148 -0
- plugins/deepseek.js +52 -0
- plugins/douyin.js +70 -0
- plugins/fbdl.js +110 -0
- plugins/google.js +40 -0
- plugins/ig.js +39 -0
- plugins/igstalk.js +111 -0
- plugins/likee.js +88 -0
- plugins/mcstalk.js +39 -0
- plugins/nnbana.js +91 -0
- plugins/openai.js +39 -0
- plugins/perplexity.js +39 -0
- plugins/pinterest.js +40 -0
- plugins/qr-generator.js +60 -0
- plugins/random-generator.js +201 -0
- plugins/sc.js +39 -0
- plugins/spotifydl.js +39 -0
- plugins/spotifysearch.js +39 -0
- plugins/subdo.js +174 -0
- plugins/suno.js +263 -0
- plugins/sunov2.js +198 -0
- plugins/sunov3.js +254 -0
- plugins/terabox.js +52 -0
- plugins/text2img.js +60 -0
- plugins/text2video.js +296 -0
- plugins/threads.js +93 -0
- plugins/tiktok.js +39 -0
- plugins/ttstalk.js +131 -0
- plugins/twitter.js +103 -0
- plugins/twitters.js +147 -0
- plugins/xbox.js +39 -0
- plugins/ytdl.js +105 -0
- plugins/ytstalk.js +39 -0
plugins/aio.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { aio } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { url } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!url) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: url'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await aio(url);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
msg: result.data
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'All In One DL',
|
| 31 |
+
description: 'Download All Video Without WM',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/download/aio'],
|
| 34 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 35 |
+
parameters: ['url', 'key'],
|
| 36 |
+
enabled: true,
|
| 37 |
+
main: ['Downloader'],
|
| 38 |
+
handler
|
| 39 |
+
}
|
plugins/apple.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
|
| 3 |
+
const cookieString = "_ga=GA1.1.206983766.1756790346; PHPSESSID=jomn6brkleb5969a3opposidru; quality=m4a; dcount=2; _ga_382FSD5=GS2.1.s1756858170$o3$g1$t1756858172$j58$l0$h0";
|
| 4 |
+
|
| 5 |
+
const axiosInstance = axios.create({
|
| 6 |
+
headers: {
|
| 7 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
|
| 8 |
+
'Cookie': cookieString
|
| 9 |
+
}
|
| 10 |
+
});
|
| 11 |
+
|
| 12 |
+
function encodeDownloadUrl(url) {
|
| 13 |
+
if (!url) return url;
|
| 14 |
+
return url.replace(/ /g, '%20');
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
function detectUrlType(url) {
|
| 18 |
+
if (url.includes('/song/')) {
|
| 19 |
+
return 'song';
|
| 20 |
+
} else if (url.includes('/album/') && url.includes('?i=')) {
|
| 21 |
+
return 'song';
|
| 22 |
+
} else if (url.includes('/album/') && !url.includes('?i=')) {
|
| 23 |
+
return 'album';
|
| 24 |
+
} else {
|
| 25 |
+
return 'song';
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
async function apple(url) {
|
| 30 |
+
try {
|
| 31 |
+
const urlType = detectUrlType(url);
|
| 32 |
+
|
| 33 |
+
if (urlType === 'album') {
|
| 34 |
+
return await downloadAlbum(url);
|
| 35 |
+
} else {
|
| 36 |
+
return await downloadSong(url);
|
| 37 |
+
}
|
| 38 |
+
} catch (error) {
|
| 39 |
+
return {
|
| 40 |
+
author: "Herza",
|
| 41 |
+
status: 500,
|
| 42 |
+
source: "error",
|
| 43 |
+
data: {
|
| 44 |
+
error: error.message,
|
| 45 |
+
message: 'Download gagal dari aaplmusicdownloader'
|
| 46 |
+
}
|
| 47 |
+
};
|
| 48 |
+
}
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
async function downloadSong(url) {
|
| 52 |
+
await axiosInstance.get('https://aaplmusicdownloader.com/ifCaptcha.php');
|
| 53 |
+
|
| 54 |
+
const endpoint = url.includes('/song/')
|
| 55 |
+
? 'https://aaplmusicdownloader.com/api/song_url.php'
|
| 56 |
+
: 'https://aaplmusicdownloader.com/api/applesearch.php';
|
| 57 |
+
|
| 58 |
+
const searchResponse = await axiosInstance.get(`${endpoint}?url=${encodeURIComponent(url)}`, {
|
| 59 |
+
headers: {
|
| 60 |
+
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
| 61 |
+
'X-Requested-With': 'XMLHttpRequest',
|
| 62 |
+
'Referer': 'https://aaplmusicdownloader.com/'
|
| 63 |
+
}
|
| 64 |
+
});
|
| 65 |
+
|
| 66 |
+
const searchData = searchResponse.data;
|
| 67 |
+
|
| 68 |
+
await axiosInstance.get('https://aaplmusicdownloader.com/song.php', {
|
| 69 |
+
headers: {
|
| 70 |
+
'Referer': 'https://aaplmusicdownloader.com/'
|
| 71 |
+
}
|
| 72 |
+
});
|
| 73 |
+
|
| 74 |
+
await axiosInstance.get('https://aaplmusicdownloader.com/ifCaptcha.php', {
|
| 75 |
+
headers: {
|
| 76 |
+
'Referer': 'https://aaplmusicdownloader.com/song.php'
|
| 77 |
+
}
|
| 78 |
+
});
|
| 79 |
+
|
| 80 |
+
const formData = `song_name=${encodeURIComponent(searchData.name)}&artist_name=${encodeURIComponent(searchData.artist)}&url=${encodeURIComponent(url)}&token=none&zip_download=false&quality=m4a`;
|
| 81 |
+
|
| 82 |
+
const downloadResponse = await axiosInstance.post('https://aaplmusicdownloader.com/api/composer/swd.php', formData, {
|
| 83 |
+
headers: {
|
| 84 |
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
| 85 |
+
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
| 86 |
+
'X-Requested-With': 'XMLHttpRequest',
|
| 87 |
+
'Referer': 'https://aaplmusicdownloader.com/song.php'
|
| 88 |
+
}
|
| 89 |
+
});
|
| 90 |
+
|
| 91 |
+
const downloadData = downloadResponse.data;
|
| 92 |
+
const downloadLink = downloadData.dlink || downloadData.wmcode;
|
| 93 |
+
|
| 94 |
+
return {
|
| 95 |
+
author: "Herza",
|
| 96 |
+
status: 200,
|
| 97 |
+
source: "aaplmusicdownloader",
|
| 98 |
+
type: "song",
|
| 99 |
+
data: {
|
| 100 |
+
name: searchData.name,
|
| 101 |
+
albumname: searchData.albumname,
|
| 102 |
+
artist: searchData.artist,
|
| 103 |
+
thumb: searchData.thumb,
|
| 104 |
+
duration: searchData.duration,
|
| 105 |
+
downloadLink: encodeDownloadUrl(downloadLink),
|
| 106 |
+
status: downloadData.status
|
| 107 |
+
}
|
| 108 |
+
};
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
async function downloadAlbum(url) {
|
| 112 |
+
await axiosInstance.get('https://aaplmusicdownloader.com/ifCaptcha.php');
|
| 113 |
+
|
| 114 |
+
const playlistResponse = await axiosInstance.get(`https://aaplmusicdownloader.com/api/pl.php?url=${encodeURIComponent(url)}`, {
|
| 115 |
+
headers: {
|
| 116 |
+
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
| 117 |
+
'X-Requested-With': 'XMLHttpRequest',
|
| 118 |
+
'Referer': 'https://aaplmusicdownloader.com/'
|
| 119 |
+
}
|
| 120 |
+
});
|
| 121 |
+
|
| 122 |
+
const albumData = playlistResponse.data.album_details;
|
| 123 |
+
const firstSong = albumData[0];
|
| 124 |
+
|
| 125 |
+
await axiosInstance.get('https://aaplmusicdownloader.com/album.php', {
|
| 126 |
+
headers: {
|
| 127 |
+
'Referer': 'https://aaplmusicdownloader.com/'
|
| 128 |
+
}
|
| 129 |
+
});
|
| 130 |
+
|
| 131 |
+
await axiosInstance.get('https://aaplmusicdownloader.com/ifCaptcha.php', {
|
| 132 |
+
headers: {
|
| 133 |
+
'Referer': 'https://aaplmusicdownloader.com/album.php'
|
| 134 |
+
}
|
| 135 |
+
});
|
| 136 |
+
|
| 137 |
+
const formData = `song_name=${encodeURIComponent(firstSong.name)}&artist_name=${encodeURIComponent(firstSong.artist.replace(/&/g, '&'))}&url=${encodeURIComponent(firstSong.link)}&token=na&zip_download=false&quality=m4a`;
|
| 138 |
+
|
| 139 |
+
const downloadResponse = await axiosInstance.post('https://aaplmusicdownloader.com/api/composer/swd.php', formData, {
|
| 140 |
+
headers: {
|
| 141 |
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
| 142 |
+
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
| 143 |
+
'X-Requested-With': 'XMLHttpRequest',
|
| 144 |
+
'Referer': 'https://aaplmusicdownloader.com/album.php'
|
| 145 |
+
}
|
| 146 |
+
});
|
| 147 |
+
|
| 148 |
+
const downloadData = downloadResponse.data;
|
| 149 |
+
const downloadLink = downloadData.dlink || downloadData.wmcode;
|
| 150 |
+
|
| 151 |
+
return {
|
| 152 |
+
author: "Herza",
|
| 153 |
+
status: 200,
|
| 154 |
+
source: "aaplmusicdownloader",
|
| 155 |
+
type: "album",
|
| 156 |
+
data: {
|
| 157 |
+
name: firstSong.name,
|
| 158 |
+
albumname: firstSong.album,
|
| 159 |
+
artist: firstSong.artist.replace(/&/g, '&'),
|
| 160 |
+
thumb: firstSong.thumb,
|
| 161 |
+
duration: firstSong.duration,
|
| 162 |
+
downloadLink: encodeDownloadUrl(downloadLink),
|
| 163 |
+
status: downloadData.status
|
| 164 |
+
}
|
| 165 |
+
};
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
const handler = async (req, res) => {
|
| 169 |
+
try {
|
| 170 |
+
const { url } = req.query;
|
| 171 |
+
|
| 172 |
+
if (!url) {
|
| 173 |
+
return res.status(400).json({
|
| 174 |
+
success: false,
|
| 175 |
+
error: 'Missing required parameter: url'
|
| 176 |
+
});
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
const result = await apple(url);
|
| 180 |
+
|
| 181 |
+
if (result.status === 500) {
|
| 182 |
+
return res.status(500).json({
|
| 183 |
+
success: false,
|
| 184 |
+
error: result.data.error,
|
| 185 |
+
message: result.data.message
|
| 186 |
+
});
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
res.json({
|
| 190 |
+
author: "Herza",
|
| 191 |
+
success: true,
|
| 192 |
+
msg: result.data
|
| 193 |
+
});
|
| 194 |
+
|
| 195 |
+
} catch (error) {
|
| 196 |
+
res.status(500).json({
|
| 197 |
+
success: false,
|
| 198 |
+
error: error.message
|
| 199 |
+
});
|
| 200 |
+
}
|
| 201 |
+
};
|
| 202 |
+
|
| 203 |
+
module.exports = {
|
| 204 |
+
name: 'Apple Music DL',
|
| 205 |
+
description: 'Download Apple Music Song or Album',
|
| 206 |
+
type: 'GET',
|
| 207 |
+
routes: ['api/download/applemusic'],
|
| 208 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 209 |
+
parameters: ['url', 'key'],
|
| 210 |
+
enabled: true,
|
| 211 |
+
main: ['Downloader'],
|
| 212 |
+
handler
|
| 213 |
+
}
|
plugins/brat.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
const FormData = require('form-data');
|
| 3 |
+
|
| 4 |
+
const handler = async (req, res) => {
|
| 5 |
+
try {
|
| 6 |
+
const { text } = req.query;
|
| 7 |
+
|
| 8 |
+
if (!text) {
|
| 9 |
+
return res.status(400).json({
|
| 10 |
+
success: false,
|
| 11 |
+
error: 'Missing required parameter: text'
|
| 12 |
+
});
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
const imageUrl = `https://api.siputzx.my.id/api/m/brat?text=${encodeURIComponent(text)}&isAnimated=false&delay=500`;
|
| 16 |
+
|
| 17 |
+
const imageResponse = await axios.get(imageUrl, {
|
| 18 |
+
responseType: 'arraybuffer'
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
const formData = new FormData();
|
| 22 |
+
formData.append('file', Buffer.from(imageResponse.data), {
|
| 23 |
+
filename: 'image.jpg',
|
| 24 |
+
contentType: imageResponse.headers['content-type'] || 'image/jpeg'
|
| 25 |
+
});
|
| 26 |
+
|
| 27 |
+
const uploadResponse = await axios.post(
|
| 28 |
+
'https://cdnme.idnet.my.id/upload',
|
| 29 |
+
formData,
|
| 30 |
+
{
|
| 31 |
+
headers: {
|
| 32 |
+
...formData.getHeaders()
|
| 33 |
+
}
|
| 34 |
+
}
|
| 35 |
+
);
|
| 36 |
+
|
| 37 |
+
res.json({
|
| 38 |
+
author: "Herza",
|
| 39 |
+
success: true,
|
| 40 |
+
url: uploadResponse.data.url
|
| 41 |
+
});
|
| 42 |
+
|
| 43 |
+
} catch (error) {
|
| 44 |
+
res.status(500).json({
|
| 45 |
+
success: false,
|
| 46 |
+
error: error.message
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
};
|
| 50 |
+
|
| 51 |
+
module.exports = {
|
| 52 |
+
name: 'Brat Image Generator',
|
| 53 |
+
description: 'Generate brat style image and upload to CDN',
|
| 54 |
+
type: 'GET',
|
| 55 |
+
routes: ['api/maker/bratgen'],
|
| 56 |
+
tags: ['tools', 'image', 'generator'],
|
| 57 |
+
parameters: ['text'],
|
| 58 |
+
enabled: true,
|
| 59 |
+
main: ['Maker'],
|
| 60 |
+
handler
|
| 61 |
+
};
|
plugins/cloudflare-bypass.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const BASE_URL = 'https://shannz.zone.id';
|
| 2 |
+
|
| 3 |
+
async function callBypassAPI(endpoint, data = {}) {
|
| 4 |
+
const validEndpoints = ['stats', 'waf-session', 'solve-turnstile-min', 'solve-turnstile-max', 'get-source'];
|
| 5 |
+
if (!validEndpoints.includes(endpoint)) {
|
| 6 |
+
throw new Error(`Endpoint tidak valid: ${endpoint}`);
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
const url = `${BASE_URL}/api/${endpoint}`;
|
| 10 |
+
let options = {
|
| 11 |
+
headers: {
|
| 12 |
+
'Content-Type': 'application/json',
|
| 13 |
+
'Accept': 'application/json'
|
| 14 |
+
}
|
| 15 |
+
};
|
| 16 |
+
|
| 17 |
+
if (endpoint === 'stats') {
|
| 18 |
+
options.method = 'GET';
|
| 19 |
+
} else {
|
| 20 |
+
options.method = 'POST';
|
| 21 |
+
if (Object.keys(data).length > 0) {
|
| 22 |
+
options.body = JSON.stringify(data);
|
| 23 |
+
}
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
try {
|
| 27 |
+
const response = await fetch(url, options);
|
| 28 |
+
const json = await response.json();
|
| 29 |
+
|
| 30 |
+
if (json.success === true) {
|
| 31 |
+
return json.data;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
const errorMessage = json.error || `Error API pada endpoint /api/${endpoint}`;
|
| 35 |
+
throw new Error(errorMessage);
|
| 36 |
+
|
| 37 |
+
} catch (error) {
|
| 38 |
+
throw error;
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
const handler = async (req, res) => {
|
| 43 |
+
try {
|
| 44 |
+
const { url, sitekey, key, mode } = req.query;
|
| 45 |
+
|
| 46 |
+
if (!url) {
|
| 47 |
+
return res.status(400).json({
|
| 48 |
+
success: false,
|
| 49 |
+
error: 'Missing required parameter: url'
|
| 50 |
+
});
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
if (!key) {
|
| 54 |
+
return res.status(400).json({
|
| 55 |
+
success: false,
|
| 56 |
+
error: 'Missing required parameter: key'
|
| 57 |
+
});
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
const validModes = ['turnstile-min', 'turnstile-max', 'waf-session', 'source', 'stats'];
|
| 61 |
+
const selectedMode = mode || 'turnstile-min';
|
| 62 |
+
|
| 63 |
+
if (!validModes.includes(selectedMode)) {
|
| 64 |
+
return res.status(400).json({
|
| 65 |
+
success: false,
|
| 66 |
+
error: `Invalid mode. Valid modes: ${validModes.join(', ')}`
|
| 67 |
+
});
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
let endpoint;
|
| 71 |
+
let data = { url };
|
| 72 |
+
|
| 73 |
+
switch(selectedMode) {
|
| 74 |
+
case 'turnstile-min':
|
| 75 |
+
if (!sitekey) {
|
| 76 |
+
return res.status(400).json({
|
| 77 |
+
success: false,
|
| 78 |
+
error: 'Parameter sitekey required for turnstile-min mode'
|
| 79 |
+
});
|
| 80 |
+
}
|
| 81 |
+
endpoint = 'solve-turnstile-min';
|
| 82 |
+
data.siteKey = sitekey;
|
| 83 |
+
break;
|
| 84 |
+
case 'turnstile-max':
|
| 85 |
+
endpoint = 'solve-turnstile-max';
|
| 86 |
+
break;
|
| 87 |
+
case 'waf-session':
|
| 88 |
+
endpoint = 'waf-session';
|
| 89 |
+
break;
|
| 90 |
+
case 'source':
|
| 91 |
+
endpoint = 'get-source';
|
| 92 |
+
break;
|
| 93 |
+
case 'stats':
|
| 94 |
+
endpoint = 'stats';
|
| 95 |
+
data = {};
|
| 96 |
+
break;
|
| 97 |
+
default:
|
| 98 |
+
endpoint = 'solve-turnstile-min';
|
| 99 |
+
if (sitekey) {
|
| 100 |
+
data.siteKey = sitekey;
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
const result = await callBypassAPI(endpoint, data);
|
| 105 |
+
|
| 106 |
+
return res.json({
|
| 107 |
+
author: "Herza",
|
| 108 |
+
success: true,
|
| 109 |
+
data: {
|
| 110 |
+
result: result,
|
| 111 |
+
url: url,
|
| 112 |
+
sitekey: sitekey || null,
|
| 113 |
+
mode: selectedMode,
|
| 114 |
+
solvedAt: new Date().toISOString()
|
| 115 |
+
},
|
| 116 |
+
timestamp: new Date().toISOString()
|
| 117 |
+
});
|
| 118 |
+
|
| 119 |
+
} catch (error) {
|
| 120 |
+
res.status(500).json({
|
| 121 |
+
success: false,
|
| 122 |
+
error: error.message,
|
| 123 |
+
timestamp: new Date().toISOString()
|
| 124 |
+
});
|
| 125 |
+
}
|
| 126 |
+
};
|
| 127 |
+
|
| 128 |
+
const shannz = {
|
| 129 |
+
stats: () => callBypassAPI('stats'),
|
| 130 |
+
wafSession: (url, proxy) => callBypassAPI('waf-session', { url, proxy }),
|
| 131 |
+
turnstileMin: (url, siteKey, proxy) => callBypassAPI('solve-turnstile-min', { url, siteKey, proxy }),
|
| 132 |
+
turnstileMax: (url, proxy) => callBypassAPI('solve-turnstile-max', { url, proxy }),
|
| 133 |
+
source: (url, proxy) => callBypassAPI('get-source', { url, proxy })
|
| 134 |
+
};
|
| 135 |
+
|
| 136 |
+
module.exports = {
|
| 137 |
+
name: 'Cloudflare Bypass',
|
| 138 |
+
description: 'Bypass Cloudflare Turnstile protection',
|
| 139 |
+
type: 'GET',
|
| 140 |
+
routes: ['api/tools/bypass'],
|
| 141 |
+
tags: ['security', 'bypass', 'turnstile'],
|
| 142 |
+
parameters: ['url', 'sitekey', 'key', 'mode'],
|
| 143 |
+
limit: 8,
|
| 144 |
+
enabled: true,
|
| 145 |
+
main: ['tools'],
|
| 146 |
+
handler,
|
| 147 |
+
shannz
|
| 148 |
+
};
|
plugins/deepseek.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const Groq = require('groq-sdk');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { text } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!text) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
author: 'Herza',
|
| 10 |
+
success: false,
|
| 11 |
+
msg: 'Missing required parameter: text'
|
| 12 |
+
});
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
const client = new Groq({
|
| 16 |
+
apiKey: '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',
|
| 17 |
+
});
|
| 18 |
+
|
| 19 |
+
const chatCompletion = await client.chat.completions.create({
|
| 20 |
+
messages: [{ role: 'user', content: text }],
|
| 21 |
+
model: 'deepseek-r1-distill-llama-70b',
|
| 22 |
+
});
|
| 23 |
+
|
| 24 |
+
const result = chatCompletion.choices[0]?.message?.content || 'Maaf, saya tidak bisa menjawab itu.';
|
| 25 |
+
|
| 26 |
+
res.json({
|
| 27 |
+
author: 'Herza',
|
| 28 |
+
success: true,
|
| 29 |
+
msg: result
|
| 30 |
+
});
|
| 31 |
+
|
| 32 |
+
} catch (error) {
|
| 33 |
+
console.error('Error fetching from Deepseek:', error);
|
| 34 |
+
res.status(500).json({
|
| 35 |
+
author: 'Herza',
|
| 36 |
+
success: false,
|
| 37 |
+
msg: 'Terjadi kesalahan saat menghubungi AI.'
|
| 38 |
+
});
|
| 39 |
+
}
|
| 40 |
+
};
|
| 41 |
+
|
| 42 |
+
module.exports = {
|
| 43 |
+
name: 'DeepSeek AI',
|
| 44 |
+
description: 'Generate responses using DeepSeek AI via Groq',
|
| 45 |
+
type: 'GET',
|
| 46 |
+
routes: ['api/AI/deepseek'],
|
| 47 |
+
tags: ['ai', 'deepseek', 'groq'],
|
| 48 |
+
parameters: ['text', 'key'],
|
| 49 |
+
enabled: true,
|
| 50 |
+
main: ['AI'],
|
| 51 |
+
handler
|
| 52 |
+
};
|
plugins/douyin.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
|
| 3 |
+
async function douyin(url) {
|
| 4 |
+
if (!url) {
|
| 5 |
+
return {
|
| 6 |
+
author: "Herza",
|
| 7 |
+
success: false,
|
| 8 |
+
error: "URL is required"
|
| 9 |
+
};
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
try {
|
| 13 |
+
const response = await axios.post("https://snapdouyin.app/wp-json/mx-downloader/video-data/",
|
| 14 |
+
{ url },
|
| 15 |
+
{
|
| 16 |
+
headers: {
|
| 17 |
+
"Content-Type": "application/json",
|
| 18 |
+
"Origin": "https://snapdouyin.app",
|
| 19 |
+
"Referer": "https://snapdouyin.app/"
|
| 20 |
+
}
|
| 21 |
+
}
|
| 22 |
+
);
|
| 23 |
+
|
| 24 |
+
return {
|
| 25 |
+
author: "Herza",
|
| 26 |
+
success: true,
|
| 27 |
+
data: response.data
|
| 28 |
+
};
|
| 29 |
+
} catch (error) {
|
| 30 |
+
return {
|
| 31 |
+
author: "Herza",
|
| 32 |
+
success: false,
|
| 33 |
+
error: error.message
|
| 34 |
+
};
|
| 35 |
+
}
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
const handler = async (req, res) => {
|
| 39 |
+
try {
|
| 40 |
+
const { url } = req.query;
|
| 41 |
+
|
| 42 |
+
if (!url) {
|
| 43 |
+
return res.status(400).json({
|
| 44 |
+
success: false,
|
| 45 |
+
error: 'Missing required parameter: url'
|
| 46 |
+
});
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
const result = await douyin(url);
|
| 50 |
+
res.json(result);
|
| 51 |
+
|
| 52 |
+
} catch (error) {
|
| 53 |
+
res.status(500).json({
|
| 54 |
+
success: false,
|
| 55 |
+
error: error.message
|
| 56 |
+
});
|
| 57 |
+
}
|
| 58 |
+
};
|
| 59 |
+
|
| 60 |
+
module.exports = {
|
| 61 |
+
name: 'Douyin DL',
|
| 62 |
+
description: 'Download Douyin Video',
|
| 63 |
+
type: 'GET',
|
| 64 |
+
routes: ['api/download/douyin'],
|
| 65 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 66 |
+
parameters: ['url', 'key'],
|
| 67 |
+
enabled: true,
|
| 68 |
+
main: ['Downloader'],
|
| 69 |
+
handler
|
| 70 |
+
};
|
plugins/fbdl.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
|
| 3 |
+
async function fbdl(url) {
|
| 4 |
+
if (!url) {
|
| 5 |
+
return {
|
| 6 |
+
author: "Herza",
|
| 7 |
+
success: false,
|
| 8 |
+
error: "URL is required"
|
| 9 |
+
};
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
try {
|
| 13 |
+
const verifyResponse = await axios.post('https://fdownloader.net/api/userverify',
|
| 14 |
+
`url=${encodeURIComponent(url)}`,
|
| 15 |
+
{
|
| 16 |
+
headers: {
|
| 17 |
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
| 18 |
+
'Accept': '*/*',
|
| 19 |
+
'X-Requested-With': 'XMLHttpRequest'
|
| 20 |
+
}
|
| 21 |
+
}
|
| 22 |
+
);
|
| 23 |
+
|
| 24 |
+
if (!verifyResponse.data.success) {
|
| 25 |
+
return {
|
| 26 |
+
author: "Herza",
|
| 27 |
+
success: false,
|
| 28 |
+
error: 'User verification failed'
|
| 29 |
+
};
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
const token = verifyResponse.data.token;
|
| 33 |
+
const currentTime = Math.floor(Date.now() / 1000);
|
| 34 |
+
const k_exp = currentTime + 300;
|
| 35 |
+
|
| 36 |
+
const searchResponse = await axios.post('https://v3.fdownloader.net/api/ajaxSearch',
|
| 37 |
+
`k_exp=${k_exp}&k_token=${token.split('.')[2]}&q=${encodeURIComponent(url)}&lang=en&web=fdownloader.net&v=v2&w=&cftoken=${token}`,
|
| 38 |
+
{
|
| 39 |
+
headers: {
|
| 40 |
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
| 41 |
+
'Accept': '*/*'
|
| 42 |
+
}
|
| 43 |
+
}
|
| 44 |
+
);
|
| 45 |
+
|
| 46 |
+
const htmlData = searchResponse.data.data;
|
| 47 |
+
const titleMatch = htmlData.match(/<h3>(.+?)<\/h3>/);
|
| 48 |
+
const durationMatch = htmlData.match(/<p>(\d+:\d+)<\/p>/);
|
| 49 |
+
const thumbnailMatch = htmlData.match(/src="(https:\/\/scontent[^"]+)"/);
|
| 50 |
+
|
| 51 |
+
const hdMatch = htmlData.match(/href="(https:\/\/dl\.snapcdn\.app\/download\?token=[^"]+)"[^>]*title="Download 720p \(HD\)"/);
|
| 52 |
+
const sdMatch = htmlData.match(/href="(https:\/\/dl\.snapcdn\.app\/download\?token=[^"]+)"[^>]*title="Download 360p \(SD\)"/);
|
| 53 |
+
|
| 54 |
+
return {
|
| 55 |
+
author: 'Herza',
|
| 56 |
+
success: true,
|
| 57 |
+
data: {
|
| 58 |
+
title: titleMatch ? titleMatch[1] : 'Facebook Video',
|
| 59 |
+
duration: durationMatch ? durationMatch[1] : '0:00',
|
| 60 |
+
thumbnail: thumbnailMatch ? thumbnailMatch[1].replace(/&/g, '&') : null,
|
| 61 |
+
downloads: {
|
| 62 |
+
hd: hdMatch ? hdMatch[1] : null,
|
| 63 |
+
sd: sdMatch ? sdMatch[1] : null
|
| 64 |
+
}
|
| 65 |
+
}
|
| 66 |
+
};
|
| 67 |
+
} catch (error) {
|
| 68 |
+
return {
|
| 69 |
+
author: 'Herza',
|
| 70 |
+
success: false,
|
| 71 |
+
error: error.message
|
| 72 |
+
};
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
const handler = async (req, res) => {
|
| 77 |
+
try {
|
| 78 |
+
const { url } = req.query;
|
| 79 |
+
|
| 80 |
+
if (!url) {
|
| 81 |
+
return res.status(400).json({
|
| 82 |
+
author: "Herza",
|
| 83 |
+
success: false,
|
| 84 |
+
error: 'Missing required parameter: url'
|
| 85 |
+
});
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
const result = await fbdl(url);
|
| 89 |
+
res.json(result);
|
| 90 |
+
|
| 91 |
+
} catch (error) {
|
| 92 |
+
res.status(500).json({
|
| 93 |
+
author: "Herza",
|
| 94 |
+
success: false,
|
| 95 |
+
error: error.message
|
| 96 |
+
});
|
| 97 |
+
}
|
| 98 |
+
};
|
| 99 |
+
|
| 100 |
+
module.exports = {
|
| 101 |
+
name: 'Facebook DL',
|
| 102 |
+
description: 'Download Facebook Video',
|
| 103 |
+
type: 'GET',
|
| 104 |
+
routes: ['api/download/fbdl'],
|
| 105 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 106 |
+
parameters: ['url', 'key'],
|
| 107 |
+
enabled: true,
|
| 108 |
+
main: ['Downloader'],
|
| 109 |
+
handler
|
| 110 |
+
};
|
plugins/google.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { googleit } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { text } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!text) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: text'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const results = await googleit(text);
|
| 15 |
+
|
| 16 |
+
res.json({
|
| 17 |
+
author: 'Herza',
|
| 18 |
+
success: true,
|
| 19 |
+
data: results.data
|
| 20 |
+
});
|
| 21 |
+
|
| 22 |
+
} catch (error) {
|
| 23 |
+
res.status(500).json({
|
| 24 |
+
success: false,
|
| 25 |
+
error: error.message
|
| 26 |
+
});
|
| 27 |
+
}
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
module.exports = {
|
| 31 |
+
name: 'Google Search',
|
| 32 |
+
description: 'Search Google by keyword',
|
| 33 |
+
type: 'GET',
|
| 34 |
+
routes: ['api/search/google'],
|
| 35 |
+
tags: ['search', 'google', 'tools'],
|
| 36 |
+
parameters: ['text'],
|
| 37 |
+
enabled: true,
|
| 38 |
+
main: ['Search'],
|
| 39 |
+
handler
|
| 40 |
+
};
|
plugins/ig.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { instagram } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { url } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!url) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: url'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await instagram(url);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
data: result.data
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'Instagram DL',
|
| 31 |
+
description: 'Download Instagram Video Without WM',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/download/instagram'],
|
| 34 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 35 |
+
parameters: ['url', 'key'],
|
| 36 |
+
enabled: true,
|
| 37 |
+
main: ['Downloader'],
|
| 38 |
+
handler
|
| 39 |
+
}
|
plugins/igstalk.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
|
| 3 |
+
async function igstalk(user) {
|
| 4 |
+
try {
|
| 5 |
+
const profileResponse = await axios.post(
|
| 6 |
+
'https://api.boostfluence.com/api/instagram-profile-v2',
|
| 7 |
+
{ username: user },
|
| 8 |
+
{ headers: { 'Content-Type': 'application/json' } }
|
| 9 |
+
);
|
| 10 |
+
|
| 11 |
+
const profile = profileResponse.data;
|
| 12 |
+
|
| 13 |
+
let postsData = null;
|
| 14 |
+
try {
|
| 15 |
+
const initialPostsResponse = await axios.post(
|
| 16 |
+
'https://api.boostfluence.com/api/instagram-viewer-v2-2',
|
| 17 |
+
{ username: user, type: 'photo', pagination_token: null },
|
| 18 |
+
{ headers: { 'Content-Type': 'application/json' } }
|
| 19 |
+
);
|
| 20 |
+
|
| 21 |
+
if (initialPostsResponse.data.error === 'COMPUTE_REQUIRED') {
|
| 22 |
+
const { timestamp, expectedCompute } = initialPostsResponse.data.challenge;
|
| 23 |
+
|
| 24 |
+
const verifiedPostsResponse = await axios.post(
|
| 25 |
+
'https://api.boostfluence.com/api/instagram-viewer-v2-2',
|
| 26 |
+
{ username: user, type: 'photo', pagination_token: null },
|
| 27 |
+
{
|
| 28 |
+
headers: {
|
| 29 |
+
'Content-Type': 'application/json',
|
| 30 |
+
'X-Compute': expectedCompute.toString(),
|
| 31 |
+
'X-Timestamp': timestamp.toString()
|
| 32 |
+
}
|
| 33 |
+
}
|
| 34 |
+
);
|
| 35 |
+
|
| 36 |
+
postsData = verifiedPostsResponse.data;
|
| 37 |
+
} else {
|
| 38 |
+
postsData = initialPostsResponse.data;
|
| 39 |
+
}
|
| 40 |
+
} catch (postsError) {
|
| 41 |
+
console.error('Error fetching posts:', postsError.message);
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
return {
|
| 45 |
+
profile: {
|
| 46 |
+
username: profile.username,
|
| 47 |
+
full_name: profile.full_name,
|
| 48 |
+
biography: profile.biography,
|
| 49 |
+
follower_count: profile.follower_count,
|
| 50 |
+
following_count: profile.following_count,
|
| 51 |
+
media_count: profile.media_count,
|
| 52 |
+
profile_pic_url: profile.profile_pic_url,
|
| 53 |
+
profile_pic_url_hd: profile.profile_pic_url_hd,
|
| 54 |
+
is_verified: profile.is_verified,
|
| 55 |
+
is_private: profile.is_private,
|
| 56 |
+
external_url: profile.external_url,
|
| 57 |
+
category: profile.category
|
| 58 |
+
}
|
| 59 |
+
};
|
| 60 |
+
} catch (error) {
|
| 61 |
+
throw new Error(`Failed to fetch Instagram data: ${error.message}`);
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
const handler = async (req, res) => {
|
| 66 |
+
try {
|
| 67 |
+
const { username } = req.query;
|
| 68 |
+
|
| 69 |
+
if (!username) {
|
| 70 |
+
return res.status(400).json({
|
| 71 |
+
success: false,
|
| 72 |
+
error: 'Missing required parameter: username'
|
| 73 |
+
});
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
const usernameRegex = /^[a-zA-Z0-9._]{1,30}$/;
|
| 77 |
+
if (!usernameRegex.test(username)) {
|
| 78 |
+
return res.status(400).json({
|
| 79 |
+
success: false,
|
| 80 |
+
error: 'Invalid username format'
|
| 81 |
+
});
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
const result = await igstalk(username);
|
| 85 |
+
|
| 86 |
+
res.json({
|
| 87 |
+
author: "Herza",
|
| 88 |
+
success: true,
|
| 89 |
+
data: result
|
| 90 |
+
});
|
| 91 |
+
|
| 92 |
+
} catch (error) {
|
| 93 |
+
res.status(500).json({
|
| 94 |
+
author: "Herza",
|
| 95 |
+
success: false,
|
| 96 |
+
error: error.message
|
| 97 |
+
});
|
| 98 |
+
}
|
| 99 |
+
};
|
| 100 |
+
|
| 101 |
+
module.exports = {
|
| 102 |
+
name: 'Instagram Stalk',
|
| 103 |
+
description: 'Get Instagram user profile information including stats, bio, and posts',
|
| 104 |
+
type: 'GET',
|
| 105 |
+
routes: ['api/stalk/instagram'],
|
| 106 |
+
tags: ['social', 'instagram', 'stalk', 'profile'],
|
| 107 |
+
parameters: ['username', 'key'],
|
| 108 |
+
enabled: true,
|
| 109 |
+
main: ['Stalk'],
|
| 110 |
+
handler
|
| 111 |
+
};
|
plugins/likee.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
|
| 3 |
+
async function likee(url) {
|
| 4 |
+
try {
|
| 5 |
+
const apiResponse = await axios.post(
|
| 6 |
+
'https://steptodown.com/wp-json/aio-dl/video-data/',
|
| 7 |
+
{ url: url },
|
| 8 |
+
{
|
| 9 |
+
headers: {
|
| 10 |
+
'Content-Type': 'application/json',
|
| 11 |
+
'Origin': 'https://steptodown.com',
|
| 12 |
+
'Referer': 'https://steptodown.com/',
|
| 13 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
| 14 |
+
'Accept': 'application/json, text/plain, */*',
|
| 15 |
+
'Accept-Language': 'en-US,en;q=0.9',
|
| 16 |
+
'Sec-Fetch-Dest': 'empty',
|
| 17 |
+
'Sec-Fetch-Mode': 'cors',
|
| 18 |
+
'Sec-Fetch-Site': 'same-origin'
|
| 19 |
+
},
|
| 20 |
+
timeout: 15000
|
| 21 |
+
}
|
| 22 |
+
);
|
| 23 |
+
|
| 24 |
+
const apiData = apiResponse.data;
|
| 25 |
+
|
| 26 |
+
return {
|
| 27 |
+
url: apiData.url || url,
|
| 28 |
+
title: apiData.title || null,
|
| 29 |
+
thumbnail: apiData.thumbnail || null,
|
| 30 |
+
duration: apiData.duration || null,
|
| 31 |
+
source: apiData.source || 'likee',
|
| 32 |
+
medias: apiData.medias || [],
|
| 33 |
+
sid: apiData.sid || null
|
| 34 |
+
};
|
| 35 |
+
} catch (error) {
|
| 36 |
+
throw new Error(error.message);
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
const handler = async (req, res) => {
|
| 41 |
+
try {
|
| 42 |
+
const { url } = req.query;
|
| 43 |
+
|
| 44 |
+
if (!url) {
|
| 45 |
+
return res.status(400).json({
|
| 46 |
+
author: 'Herza',
|
| 47 |
+
success: false,
|
| 48 |
+
error: 'Missing required parameter: url',
|
| 49 |
+
message: 'Please provide a Likee video URL'
|
| 50 |
+
});
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
if (!url.includes('likee.video') && !url.includes('likee.com')) {
|
| 54 |
+
return res.status(400).json({
|
| 55 |
+
author: 'Herza',
|
| 56 |
+
success: false,
|
| 57 |
+
error: 'Invalid URL',
|
| 58 |
+
message: 'Please provide a valid Likee video URL'
|
| 59 |
+
});
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
const result = await likee(url);
|
| 63 |
+
|
| 64 |
+
res.json({
|
| 65 |
+
author: 'Herza',
|
| 66 |
+
success: true,
|
| 67 |
+
data: result
|
| 68 |
+
});
|
| 69 |
+
} catch (error) {
|
| 70 |
+
res.status(500).json({
|
| 71 |
+
author: 'Herza',
|
| 72 |
+
success: false,
|
| 73 |
+
error: error.message
|
| 74 |
+
});
|
| 75 |
+
}
|
| 76 |
+
};
|
| 77 |
+
|
| 78 |
+
module.exports = {
|
| 79 |
+
name: 'Likee Downloader',
|
| 80 |
+
description: 'Download Likee videos without watermark using steptodown API',
|
| 81 |
+
type: 'GET',
|
| 82 |
+
routes: ['api/download/likee'],
|
| 83 |
+
tags: ['tools', 'likee', 'downloader', 'social-media'],
|
| 84 |
+
main: ['Downloader'],
|
| 85 |
+
parameters: ['url', 'key'],
|
| 86 |
+
enabled: true,
|
| 87 |
+
handler
|
| 88 |
+
};
|
plugins/mcstalk.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { mcstalk } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { text } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!text) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: text'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await mcstalk(text);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
data: result.data
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'Minecraft Stalk',
|
| 31 |
+
description: 'Stalk someone Minecraft account with username',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/stalk/minecraft'],
|
| 34 |
+
tags: ['stalk', 'tools', 'misc'],
|
| 35 |
+
parameters: ['text', 'key'],
|
| 36 |
+
enabled: true,
|
| 37 |
+
main: ['Stalk'],
|
| 38 |
+
handler
|
| 39 |
+
}
|
plugins/nnbana.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require("axios");
|
| 2 |
+
|
| 3 |
+
async function NanoBanana(prompt, imageUrl, cookie) {
|
| 4 |
+
try {
|
| 5 |
+
const api = `https://anabot.my.id/api/ai/geminiOption?prompt=${encodeURIComponent(prompt)}&type=NanoBanana&imageUrl=${encodeURIComponent(imageUrl)}&imageUrl2=&imageUrl3=&imageUrl4=&cookie=${encodeURIComponent(cookie)}&apikey=freeApikey`;
|
| 6 |
+
|
| 7 |
+
const response = await axios.get(api, {
|
| 8 |
+
headers: { 'Accept': 'application/json' }
|
| 9 |
+
});
|
| 10 |
+
|
| 11 |
+
if (response.data && response.data.data && response.data.data.result) {
|
| 12 |
+
return {
|
| 13 |
+
success: true,
|
| 14 |
+
url: response.data.data.result.url,
|
| 15 |
+
prompt: prompt
|
| 16 |
+
};
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
throw new Error('Gagal memproses gambar');
|
| 20 |
+
} catch (err) {
|
| 21 |
+
throw new Error(err.response?.data?.message || err.message);
|
| 22 |
+
}
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
const handler = async (req, res) => {
|
| 26 |
+
try {
|
| 27 |
+
const { prompt, imageUrl, cookie, key } = req.query;
|
| 28 |
+
|
| 29 |
+
if (!key) {
|
| 30 |
+
return res.status(400).json({
|
| 31 |
+
success: false,
|
| 32 |
+
error: 'Missing required parameter: key'
|
| 33 |
+
});
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
if (!prompt) {
|
| 37 |
+
return res.status(400).json({
|
| 38 |
+
success: false,
|
| 39 |
+
error: 'Missing required parameter: prompt'
|
| 40 |
+
});
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
if (!imageUrl) {
|
| 44 |
+
return res.status(400).json({
|
| 45 |
+
success: false,
|
| 46 |
+
error: 'Missing required parameter: imageUrl'
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
if (!cookie) {
|
| 51 |
+
return res.status(400).json({
|
| 52 |
+
success: false,
|
| 53 |
+
error: 'Missing required parameter: cookie'
|
| 54 |
+
});
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
const result = await NanoBanana(prompt, imageUrl, cookie);
|
| 58 |
+
|
| 59 |
+
return res.json({
|
| 60 |
+
author: "Herza",
|
| 61 |
+
success: true,
|
| 62 |
+
data: {
|
| 63 |
+
prompt: result.prompt,
|
| 64 |
+
image_url: result.url,
|
| 65 |
+
original_url: imageUrl
|
| 66 |
+
},
|
| 67 |
+
timestamp: new Date().toISOString()
|
| 68 |
+
});
|
| 69 |
+
|
| 70 |
+
} catch (error) {
|
| 71 |
+
res.status(500).json({
|
| 72 |
+
success: false,
|
| 73 |
+
error: error.message,
|
| 74 |
+
timestamp: new Date().toISOString()
|
| 75 |
+
});
|
| 76 |
+
}
|
| 77 |
+
};
|
| 78 |
+
|
| 79 |
+
module.exports = {
|
| 80 |
+
name: 'Nano Banana',
|
| 81 |
+
description: 'AI Image Editing using Gemini - Edit images with text prompts',
|
| 82 |
+
type: 'GET',
|
| 83 |
+
routes: ['api/AI/nanobanana'],
|
| 84 |
+
tags: ['ai', 'image', 'editing', 'gemini', 'nanobanana'],
|
| 85 |
+
parameters: ['prompt', 'imageUrl', 'cookie', 'key'],
|
| 86 |
+
limit: 5,
|
| 87 |
+
enabled: true,
|
| 88 |
+
main: ['AI'],
|
| 89 |
+
handler,
|
| 90 |
+
NanoBanana
|
| 91 |
+
};
|
plugins/openai.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { openai } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { text } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!text) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: text'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await openai(text);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
msg: result.msg
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'ChatGPT AI',
|
| 31 |
+
description: 'Generate responses using OpenAI ChatGPT',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/AI/chatgpt'],
|
| 34 |
+
tags: ['ai', 'chatgpt', 'openai'],
|
| 35 |
+
main: ['AI'],
|
| 36 |
+
parameters: ['text', 'key'],
|
| 37 |
+
enabled: true,
|
| 38 |
+
handler
|
| 39 |
+
};
|
plugins/perplexity.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { perplexity } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { text } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!text) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: text'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await perplexity(text);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
msg: result.msg
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'Perplexity AI',
|
| 31 |
+
description: 'Generate responses using Perplexity AI',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/AI/perplexity'],
|
| 34 |
+
tags: ['ai', 'perplexity'],
|
| 35 |
+
parameters: ['text', 'key'],
|
| 36 |
+
enabled: true,
|
| 37 |
+
main: ['AI'],
|
| 38 |
+
handler
|
| 39 |
+
};
|
plugins/pinterest.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { pinsearch } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { text } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!text) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: text'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const results = await pinsearch(text);
|
| 15 |
+
|
| 16 |
+
res.json({
|
| 17 |
+
author: 'Herza',
|
| 18 |
+
success: true,
|
| 19 |
+
data: results.results
|
| 20 |
+
});
|
| 21 |
+
|
| 22 |
+
} catch (error) {
|
| 23 |
+
res.status(500).json({
|
| 24 |
+
success: false,
|
| 25 |
+
error: error.message
|
| 26 |
+
});
|
| 27 |
+
}
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
module.exports = {
|
| 31 |
+
name: 'Pinterest Search',
|
| 32 |
+
description: 'Search Pinterest images by keyword',
|
| 33 |
+
type: 'GET',
|
| 34 |
+
routes: ['api/search/pinsearch'],
|
| 35 |
+
tags: ['search', 'pinterest', 'tools'],
|
| 36 |
+
parameters: ['text'],
|
| 37 |
+
enabled: true,
|
| 38 |
+
main: ['Search'],
|
| 39 |
+
handler
|
| 40 |
+
};
|
plugins/qr-generator.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const handler = async (req, res) => {
|
| 2 |
+
try {
|
| 3 |
+
const { text, size = 200, format = 'png' } = req.query;
|
| 4 |
+
|
| 5 |
+
if (!text) {
|
| 6 |
+
return res.status(400).json({
|
| 7 |
+
success: false,
|
| 8 |
+
error: 'Missing required parameter: text'
|
| 9 |
+
});
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
const validSizes = [100, 150, 200, 250, 300, 400, 500];
|
| 13 |
+
const validFormats = ['png', 'svg'];
|
| 14 |
+
|
| 15 |
+
if (!validSizes.includes(parseInt(size))) {
|
| 16 |
+
return res.status(400).json({
|
| 17 |
+
success: false,
|
| 18 |
+
error: 'Invalid size. Valid sizes: ' + validSizes.join(', ')
|
| 19 |
+
});
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
if (!validFormats.includes(format.toLowerCase())) {
|
| 23 |
+
return res.status(400).json({
|
| 24 |
+
success: false,
|
| 25 |
+
error: 'Invalid format. Valid formats: ' + validFormats.join(', ')
|
| 26 |
+
});
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
const qrApiUrl = `https://api.qrserver.com/v1/create-qr-code/?size=${size}x${size}&data=${encodeURIComponent(text)}&format=${format}`;
|
| 30 |
+
|
| 31 |
+
res.json({
|
| 32 |
+
success: true,
|
| 33 |
+
data: {
|
| 34 |
+
text,
|
| 35 |
+
size: parseInt(size),
|
| 36 |
+
format,
|
| 37 |
+
qr_url: qrApiUrl,
|
| 38 |
+
download_url: qrApiUrl + '&download=1'
|
| 39 |
+
}
|
| 40 |
+
});
|
| 41 |
+
|
| 42 |
+
} catch (error) {
|
| 43 |
+
res.status(500).json({
|
| 44 |
+
success: false,
|
| 45 |
+
error: error.message
|
| 46 |
+
});
|
| 47 |
+
}
|
| 48 |
+
};
|
| 49 |
+
|
| 50 |
+
module.exports = {
|
| 51 |
+
name: 'QR Code Generator',
|
| 52 |
+
description: 'Generate QR codes for text, URLs, and more with custom sizes',
|
| 53 |
+
type: 'GET',
|
| 54 |
+
routes: ['api/tools/qr/generate'],
|
| 55 |
+
tags: ['utility', 'qr', 'generator'],
|
| 56 |
+
parameters: ['text', 'size', 'format', 'key'],
|
| 57 |
+
enabled: true,
|
| 58 |
+
main: ['tools'],
|
| 59 |
+
handler
|
| 60 |
+
};
|
plugins/random-generator.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const crypto = require('crypto');
|
| 2 |
+
|
| 3 |
+
const WORD_LISTS = {
|
| 4 |
+
lorem: [
|
| 5 |
+
'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit',
|
| 6 |
+
'sed', 'do', 'eiusmod', 'tempor', 'incididunt', 'ut', 'labore', 'et', 'dolore',
|
| 7 |
+
'magna', 'aliqua', 'enim', 'ad', 'minim', 'veniam', 'quis', 'nostrud',
|
| 8 |
+
'exercitation', 'ullamco', 'laboris', 'nisi', 'aliquip', 'ex', 'ea', 'commodo',
|
| 9 |
+
'consequat', 'duis', 'aute', 'irure', 'in', 'reprehenderit', 'voluptate',
|
| 10 |
+
'velit', 'esse', 'cillum', 'fugiat', 'nulla', 'pariatur', 'excepteur', 'sint',
|
| 11 |
+
'occaecat', 'cupidatat', 'non', 'proident', 'sunt', 'culpa', 'qui', 'officia',
|
| 12 |
+
'deserunt', 'mollit', 'anim', 'id', 'est', 'laborum'
|
| 13 |
+
],
|
| 14 |
+
english: [
|
| 15 |
+
'the', 'quick', 'brown', 'fox', 'jumps', 'over', 'lazy', 'dog', 'and', 'runs',
|
| 16 |
+
'through', 'forest', 'while', 'birds', 'sing', 'beautiful', 'songs', 'under',
|
| 17 |
+
'bright', 'sunny', 'sky', 'with', 'clouds', 'floating', 'peacefully', 'above',
|
| 18 |
+
'green', 'trees', 'beside', 'flowing', 'river', 'where', 'fish', 'swim',
|
| 19 |
+
'quietly', 'among', 'rocks', 'covered', 'moss', 'creating', 'natural', 'harmony'
|
| 20 |
+
],
|
| 21 |
+
tech: [
|
| 22 |
+
'algorithm', 'database', 'framework', 'library', 'function', 'variable', 'array',
|
| 23 |
+
'object', 'method', 'class', 'interface', 'component', 'module', 'package',
|
| 24 |
+
'deployment', 'server', 'client', 'backend', 'frontend', 'fullstack', 'api',
|
| 25 |
+
'endpoint', 'authentication', 'authorization', 'encryption', 'decryption',
|
| 26 |
+
'blockchain', 'machine', 'learning', 'artificial', 'intelligence', 'neural',
|
| 27 |
+
'network', 'deep', 'learning', 'data', 'science', 'analytics', 'visualization'
|
| 28 |
+
]
|
| 29 |
+
};
|
| 30 |
+
|
| 31 |
+
const CHARACTERS = {
|
| 32 |
+
lowercase: 'abcdefghijklmnopqrstuvwxyz',
|
| 33 |
+
uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
| 34 |
+
numbers: '0123456789',
|
| 35 |
+
symbols: '!@#$%^&*()_+-=[]{}|;:,.<>?',
|
| 36 |
+
special: '!@#$%^&*'
|
| 37 |
+
};
|
| 38 |
+
|
| 39 |
+
const generateRandomWords = (count, wordList) => {
|
| 40 |
+
const words = [];
|
| 41 |
+
for (let i = 0; i < count; i++) {
|
| 42 |
+
const randomIndex = Math.floor(Math.random() * wordList.length);
|
| 43 |
+
words.push(wordList[randomIndex]);
|
| 44 |
+
}
|
| 45 |
+
return words.join(' ');
|
| 46 |
+
};
|
| 47 |
+
|
| 48 |
+
const generateRandomString = (length, charset) => {
|
| 49 |
+
let result = '';
|
| 50 |
+
for (let i = 0; i < length; i++) {
|
| 51 |
+
result += charset.charAt(Math.floor(Math.random() * charset.length));
|
| 52 |
+
}
|
| 53 |
+
return result;
|
| 54 |
+
};
|
| 55 |
+
|
| 56 |
+
const generatePassword = (length, options) => {
|
| 57 |
+
let charset = '';
|
| 58 |
+
if (options.lowercase) charset += CHARACTERS.lowercase;
|
| 59 |
+
if (options.uppercase) charset += CHARACTERS.uppercase;
|
| 60 |
+
if (options.numbers) charset += CHARACTERS.numbers;
|
| 61 |
+
if (options.symbols) charset += CHARACTERS.symbols;
|
| 62 |
+
|
| 63 |
+
if (!charset) charset = CHARACTERS.lowercase + CHARACTERS.uppercase + CHARACTERS.numbers;
|
| 64 |
+
|
| 65 |
+
return generateRandomString(length, charset);
|
| 66 |
+
};
|
| 67 |
+
|
| 68 |
+
const generateSentences = (count, wordList, minWords = 5, maxWords = 15) => {
|
| 69 |
+
const sentences = [];
|
| 70 |
+
for (let i = 0; i < count; i++) {
|
| 71 |
+
const wordCount = Math.floor(Math.random() * (maxWords - minWords + 1)) + minWords;
|
| 72 |
+
const words = [];
|
| 73 |
+
for (let j = 0; j < wordCount; j++) {
|
| 74 |
+
const randomIndex = Math.floor(Math.random() * wordList.length);
|
| 75 |
+
words.push(wordList[randomIndex]);
|
| 76 |
+
}
|
| 77 |
+
let sentence = words.join(' ');
|
| 78 |
+
sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1) + '.';
|
| 79 |
+
sentences.push(sentence);
|
| 80 |
+
}
|
| 81 |
+
return sentences.join(' ');
|
| 82 |
+
};
|
| 83 |
+
|
| 84 |
+
const handler = async (req, res) => {
|
| 85 |
+
try {
|
| 86 |
+
const {
|
| 87 |
+
type = 'words',
|
| 88 |
+
count = 10,
|
| 89 |
+
length = 12,
|
| 90 |
+
wordType = 'lorem',
|
| 91 |
+
includeNumbers = true,
|
| 92 |
+
includeUppercase = true,
|
| 93 |
+
includeLowercase = true,
|
| 94 |
+
includeSymbols = false,
|
| 95 |
+
minWords = 5,
|
| 96 |
+
maxWords = 15
|
| 97 |
+
} = req.query;
|
| 98 |
+
|
| 99 |
+
const validTypes = ['words', 'sentences', 'paragraphs', 'password', 'string', 'uuid'];
|
| 100 |
+
const validWordTypes = Object.keys(WORD_LISTS);
|
| 101 |
+
|
| 102 |
+
if (!validTypes.includes(type)) {
|
| 103 |
+
return res.status(400).json({
|
| 104 |
+
success: false,
|
| 105 |
+
error: `Invalid type. Valid types: ${validTypes.join(', ')}`
|
| 106 |
+
});
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
if (!validWordTypes.includes(wordType) && ['words', 'sentences', 'paragraphs'].includes(type)) {
|
| 110 |
+
return res.status(400).json({
|
| 111 |
+
success: false,
|
| 112 |
+
error: `Invalid wordType. Valid wordTypes: ${validWordTypes.join(', ')}`
|
| 113 |
+
});
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
let result = '';
|
| 117 |
+
const wordList = WORD_LISTS[wordType] || WORD_LISTS.lorem;
|
| 118 |
+
|
| 119 |
+
switch (type) {
|
| 120 |
+
case 'words':
|
| 121 |
+
result = generateRandomWords(parseInt(count), wordList);
|
| 122 |
+
break;
|
| 123 |
+
|
| 124 |
+
case 'sentences':
|
| 125 |
+
result = generateSentences(parseInt(count), wordList, parseInt(minWords), parseInt(maxWords));
|
| 126 |
+
break;
|
| 127 |
+
|
| 128 |
+
case 'paragraphs':
|
| 129 |
+
const paragraphs = [];
|
| 130 |
+
for (let i = 0; i < parseInt(count); i++) {
|
| 131 |
+
const sentenceCount = Math.floor(Math.random() * 6) + 3;
|
| 132 |
+
paragraphs.push(generateSentences(sentenceCount, wordList, parseInt(minWords), parseInt(maxWords)));
|
| 133 |
+
}
|
| 134 |
+
result = paragraphs.join('\n\n');
|
| 135 |
+
break;
|
| 136 |
+
|
| 137 |
+
case 'password':
|
| 138 |
+
const passwordOptions = {
|
| 139 |
+
lowercase: includeLowercase === 'true',
|
| 140 |
+
uppercase: includeUppercase === 'true',
|
| 141 |
+
numbers: includeNumbers === 'true',
|
| 142 |
+
symbols: includeSymbols === 'true'
|
| 143 |
+
};
|
| 144 |
+
result = generatePassword(parseInt(length), passwordOptions);
|
| 145 |
+
break;
|
| 146 |
+
|
| 147 |
+
case 'string':
|
| 148 |
+
let charset = '';
|
| 149 |
+
if (includeLowercase === 'true') charset += CHARACTERS.lowercase;
|
| 150 |
+
if (includeUppercase === 'true') charset += CHARACTERS.uppercase;
|
| 151 |
+
if (includeNumbers === 'true') charset += CHARACTERS.numbers;
|
| 152 |
+
if (includeSymbols === 'true') charset += CHARACTERS.symbols;
|
| 153 |
+
if (!charset) charset = CHARACTERS.lowercase + CHARACTERS.numbers;
|
| 154 |
+
result = generateRandomString(parseInt(length), charset);
|
| 155 |
+
break;
|
| 156 |
+
|
| 157 |
+
case 'uuid':
|
| 158 |
+
result = crypto.randomUUID();
|
| 159 |
+
break;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
res.json({
|
| 163 |
+
success: true,
|
| 164 |
+
data: {
|
| 165 |
+
type,
|
| 166 |
+
result,
|
| 167 |
+
length: result.length,
|
| 168 |
+
word_count: result.split(' ').length,
|
| 169 |
+
generated_at: new Date().toISOString(),
|
| 170 |
+
parameters: {
|
| 171 |
+
type,
|
| 172 |
+
count: parseInt(count),
|
| 173 |
+
length: parseInt(length),
|
| 174 |
+
wordType,
|
| 175 |
+
includeNumbers: includeNumbers === 'true',
|
| 176 |
+
includeUppercase: includeUppercase === 'true',
|
| 177 |
+
includeLowercase: includeLowercase === 'true',
|
| 178 |
+
includeSymbols: includeSymbols === 'true'
|
| 179 |
+
}
|
| 180 |
+
}
|
| 181 |
+
});
|
| 182 |
+
|
| 183 |
+
} catch (error) {
|
| 184 |
+
res.status(500).json({
|
| 185 |
+
success: false,
|
| 186 |
+
error: error.message
|
| 187 |
+
});
|
| 188 |
+
}
|
| 189 |
+
};
|
| 190 |
+
|
| 191 |
+
module.exports = {
|
| 192 |
+
name: 'Random Text Generator',
|
| 193 |
+
description: 'Generate random text, words, sentences, passwords, and UUIDs',
|
| 194 |
+
type: 'GET',
|
| 195 |
+
routes: ['api/tools/random/text'],
|
| 196 |
+
tags: ['utility', 'random', 'generator', 'text'],
|
| 197 |
+
parameters: ['type', 'count', 'length', 'wordType', 'includeNumbers', 'includeUppercase', 'includeLowercase', 'includeSymbols'],
|
| 198 |
+
enabled: true,
|
| 199 |
+
main: ['tools'],
|
| 200 |
+
handler
|
| 201 |
+
};
|
plugins/sc.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { soundcloud } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { url } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!url) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: url'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await soundcloud(url);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
data: result.data
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'SoundCloud DL',
|
| 31 |
+
description: 'Download Soundcloud Music from our server',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/download/soundcloud'],
|
| 34 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 35 |
+
parameters: ['url', 'key'],
|
| 36 |
+
enabled: true,
|
| 37 |
+
main: ['Downloader'],
|
| 38 |
+
handler
|
| 39 |
+
}
|
plugins/spotifydl.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { spotydl } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { url } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!url) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: url'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await spotydl(url);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
msg: result.data
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'Spotify DL',
|
| 31 |
+
description: 'Download Spotify Music Without Effort',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/download/spotifydl'],
|
| 34 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 35 |
+
parameters: ['url', 'key'],
|
| 36 |
+
enabled: true,
|
| 37 |
+
main: ['Downloader'],
|
| 38 |
+
handler
|
| 39 |
+
}
|
plugins/spotifysearch.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { spotifysearch } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { text } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!text) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: text'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await spotifysearch(text);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
data: result.results
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'Spotify Search',
|
| 31 |
+
description: 'Generate responses using OpenAI ChatGPT',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/search/spotify'],
|
| 34 |
+
tags: ['tools', 'spotify', 'downloader'],
|
| 35 |
+
main: ['Search'],
|
| 36 |
+
parameters: ['text', 'key'],
|
| 37 |
+
enabled: true,
|
| 38 |
+
handler
|
| 39 |
+
};
|
plugins/subdo.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { shannz: cf } = require('bycf');
|
| 2 |
+
|
| 3 |
+
async function getTurnstileToken() {
|
| 4 |
+
try {
|
| 5 |
+
const token = await cf.turnstileMin(
|
| 6 |
+
"https://www.subdomainfinder.in",
|
| 7 |
+
"0x4AAAAAAAj7jyMV3Zv9ZMN-",
|
| 8 |
+
"host:port"
|
| 9 |
+
);
|
| 10 |
+
return token;
|
| 11 |
+
} catch (error) {
|
| 12 |
+
throw new Error("Gagal mendapatkan Turnstile token: " + error.message);
|
| 13 |
+
}
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
async function findSubdomains(domain, token) {
|
| 17 |
+
const response = await fetch(`https://api.subdomainfinder.in/?domain=${domain}`, {
|
| 18 |
+
method: 'GET',
|
| 19 |
+
headers: {
|
| 20 |
+
'X-Secure-Token': token,
|
| 21 |
+
'X-Referer': 'https://www.google.com/',
|
| 22 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
| 23 |
+
}
|
| 24 |
+
});
|
| 25 |
+
|
| 26 |
+
if (!response.ok) {
|
| 27 |
+
throw new Error(`HTTP error! status: ${response.status}`);
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
return await response.json();
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
async function resolveDNS(subdomain) {
|
| 34 |
+
const response = await fetch(`https://lookup.subdomainfinder.in/resolve?name=${subdomain}&rd=1`, {
|
| 35 |
+
method: 'GET',
|
| 36 |
+
headers: {
|
| 37 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
| 38 |
+
}
|
| 39 |
+
});
|
| 40 |
+
|
| 41 |
+
if (!response.ok) {
|
| 42 |
+
throw new Error(`HTTP error! status: ${response.status}`);
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
return await response.json();
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
async function getIPInfo(ip) {
|
| 49 |
+
const response = await fetch(`https://ipresolver.subdomainfinder.in/${ip}`, {
|
| 50 |
+
method: 'GET',
|
| 51 |
+
headers: {
|
| 52 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
| 53 |
+
}
|
| 54 |
+
});
|
| 55 |
+
|
| 56 |
+
if (!response.ok) {
|
| 57 |
+
throw new Error(`HTTP error! status: ${response.status}`);
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
return await response.json();
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
function extractIPFromDNS(dnsData) {
|
| 64 |
+
if (!dnsData || !dnsData.Answer) return null;
|
| 65 |
+
|
| 66 |
+
for (const answer of dnsData.Answer) {
|
| 67 |
+
if (answer.type === 1 && answer.data) {
|
| 68 |
+
return answer.data;
|
| 69 |
+
}
|
| 70 |
+
}
|
| 71 |
+
return null;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
async function subdo(domain) {
|
| 75 |
+
const token = await getTurnstileToken();
|
| 76 |
+
|
| 77 |
+
const subdomainData = await findSubdomains(domain, token);
|
| 78 |
+
|
| 79 |
+
const results = [];
|
| 80 |
+
|
| 81 |
+
for (const sub of subdomainData.data) {
|
| 82 |
+
try {
|
| 83 |
+
const dnsData = await resolveDNS(sub.subdomain);
|
| 84 |
+
|
| 85 |
+
const ip = extractIPFromDNS(dnsData);
|
| 86 |
+
|
| 87 |
+
let result = {
|
| 88 |
+
subdomain: sub.subdomain,
|
| 89 |
+
ip: ip || 'N/A',
|
| 90 |
+
cloudflare: sub.cloudflare,
|
| 91 |
+
dnsStatus: dnsData.Status
|
| 92 |
+
};
|
| 93 |
+
|
| 94 |
+
if (ip) {
|
| 95 |
+
try {
|
| 96 |
+
const ipInfo = await getIPInfo(ip);
|
| 97 |
+
if (ipInfo.success && ipInfo.result && ipInfo.result.ip) {
|
| 98 |
+
result.ipInfo = {
|
| 99 |
+
location: ipInfo.result.ip.locationName,
|
| 100 |
+
asn: ipInfo.result.ip.asnName,
|
| 101 |
+
country: ipInfo.result.ip.location,
|
| 102 |
+
flag: ipInfo.result.ip.flag
|
| 103 |
+
};
|
| 104 |
+
}
|
| 105 |
+
} catch (e) {
|
| 106 |
+
result.ipInfo = null;
|
| 107 |
+
}
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
results.push(result);
|
| 111 |
+
} catch (error) {
|
| 112 |
+
results.push({
|
| 113 |
+
subdomain: sub.subdomain,
|
| 114 |
+
error: error.message
|
| 115 |
+
});
|
| 116 |
+
}
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
return {
|
| 120 |
+
domain: domain,
|
| 121 |
+
count: subdomainData.count,
|
| 122 |
+
data: results
|
| 123 |
+
};
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
const handler = async (req, res) => {
|
| 127 |
+
try {
|
| 128 |
+
const { domain } = req.query;
|
| 129 |
+
|
| 130 |
+
if (!domain) {
|
| 131 |
+
return res.status(400).json({
|
| 132 |
+
success: false,
|
| 133 |
+
error: 'Missing required parameter: domain'
|
| 134 |
+
});
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?\.([a-zA-Z]{2,}\.?)+$/;
|
| 138 |
+
if (!domainRegex.test(domain)) {
|
| 139 |
+
return res.status(400).json({
|
| 140 |
+
success: false,
|
| 141 |
+
error: 'Invalid domain format'
|
| 142 |
+
});
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
const result = await subdo(domain);
|
| 146 |
+
|
| 147 |
+
res.json({
|
| 148 |
+
success: true,
|
| 149 |
+
data: {
|
| 150 |
+
domain: result.domain,
|
| 151 |
+
total_subdomains: result.count,
|
| 152 |
+
subdomains: result.data
|
| 153 |
+
}
|
| 154 |
+
});
|
| 155 |
+
|
| 156 |
+
} catch (error) {
|
| 157 |
+
res.status(500).json({
|
| 158 |
+
success: false,
|
| 159 |
+
error: error.message
|
| 160 |
+
});
|
| 161 |
+
}
|
| 162 |
+
};
|
| 163 |
+
|
| 164 |
+
module.exports = {
|
| 165 |
+
name: 'Subdomain Finder',
|
| 166 |
+
description: 'Find subdomains with IP addresses and location information',
|
| 167 |
+
type: 'GET',
|
| 168 |
+
routes: ['api/tools/subdomain/finder'],
|
| 169 |
+
tags: ['security', 'subdomain', 'dns', 'recon'],
|
| 170 |
+
parameters: ['domain', 'key'],
|
| 171 |
+
enabled: true,
|
| 172 |
+
main: ['tools', "Search"],
|
| 173 |
+
handler
|
| 174 |
+
};
|
plugins/suno.js
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
const { v4: uuidv4 } = require('uuid');
|
| 3 |
+
const readline = require('readline');
|
| 4 |
+
|
| 5 |
+
const sonu = {
|
| 6 |
+
api: {
|
| 7 |
+
base: 'https://musicai.apihub.today/api/v1',
|
| 8 |
+
endpoints: {
|
| 9 |
+
register: '/users',
|
| 10 |
+
create: '/song/create',
|
| 11 |
+
checkStatus: '/song/user'
|
| 12 |
+
}
|
| 13 |
+
},
|
| 14 |
+
|
| 15 |
+
headers: {
|
| 16 |
+
'user-agent': 'NB Android/1.0.0',
|
| 17 |
+
'content-type': 'application/json',
|
| 18 |
+
'accept': 'application/json',
|
| 19 |
+
'x-platform': 'android',
|
| 20 |
+
'x-app-version': '1.0.0',
|
| 21 |
+
'x-country': 'ID',
|
| 22 |
+
'accept-language': 'id-ID',
|
| 23 |
+
'x-client-timezone': 'Asia/Jakarta'
|
| 24 |
+
},
|
| 25 |
+
|
| 26 |
+
deviceId: uuidv4(),
|
| 27 |
+
userId: null,
|
| 28 |
+
fcmToken: 'eqnTqlxMTSKQL5NQz6r5aP:APA91bHa3CvL5Nlcqx2yzqTDAeqxm_L_vIYxXqehkgmTsCXrV29eAak6_jqXv5v1mQrdw4BGMLXl_BFNrJ67Em0vmdr3hQPVAYF8kR7RDtTRHQ08F3jLRRI',
|
| 29 |
+
|
| 30 |
+
register: async () => {
|
| 31 |
+
const msgId = uuidv4();
|
| 32 |
+
const time = Date.now().toString();
|
| 33 |
+
const header = {
|
| 34 |
+
...sonu.headers,
|
| 35 |
+
'x-device-id': sonu.deviceId,
|
| 36 |
+
'x-request-id': msgId,
|
| 37 |
+
'x-message-id': msgId,
|
| 38 |
+
'x-request-time': time
|
| 39 |
+
};
|
| 40 |
+
|
| 41 |
+
try {
|
| 42 |
+
const response = await axios.put(
|
| 43 |
+
`${sonu.api.base}${sonu.api.endpoints.register}`,
|
| 44 |
+
{
|
| 45 |
+
deviceId: sonu.deviceId,
|
| 46 |
+
fcmToken: sonu.fcmToken
|
| 47 |
+
},
|
| 48 |
+
{ headers: header }
|
| 49 |
+
);
|
| 50 |
+
sonu.userId = response.data.id;
|
| 51 |
+
return {
|
| 52 |
+
success: true,
|
| 53 |
+
code: 200,
|
| 54 |
+
result: { userId: sonu.userId }
|
| 55 |
+
};
|
| 56 |
+
} catch (err) {
|
| 57 |
+
return {
|
| 58 |
+
success: false,
|
| 59 |
+
code: err.response?.status || 500,
|
| 60 |
+
result: { error: err.message }
|
| 61 |
+
};
|
| 62 |
+
}
|
| 63 |
+
},
|
| 64 |
+
|
| 65 |
+
create: async ({ title, mood, genre, lyrics, gender }) => {
|
| 66 |
+
if (!title || title.trim() === '') {
|
| 67 |
+
return {
|
| 68 |
+
success: false,
|
| 69 |
+
code: 400,
|
| 70 |
+
result: { error: "Judul lagunya kagak boleh kosong bree 😂" }
|
| 71 |
+
};
|
| 72 |
+
}
|
| 73 |
+
if (!lyrics || lyrics.trim() === '') {
|
| 74 |
+
return {
|
| 75 |
+
success: false,
|
| 76 |
+
code: 400,
|
| 77 |
+
result: { error: "Lirik lagunya mana? Mau generate lagu kan? Yaa mana liriknya 😂" }
|
| 78 |
+
};
|
| 79 |
+
}
|
| 80 |
+
if (lyrics.length > 1500) {
|
| 81 |
+
return {
|
| 82 |
+
success: false,
|
| 83 |
+
code: 400,
|
| 84 |
+
result: { error: "Lirik lagu kagak boleh lebih dari 1500 karakter yak bree 🗿"}
|
| 85 |
+
};
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
const msgId = uuidv4();
|
| 89 |
+
const time = Date.now().toString();
|
| 90 |
+
const header = {
|
| 91 |
+
...sonu.headers,
|
| 92 |
+
'x-device-id': sonu.deviceId,
|
| 93 |
+
'x-client-id': sonu.userId,
|
| 94 |
+
'x-request-id': msgId,
|
| 95 |
+
'x-message-id': msgId,
|
| 96 |
+
'x-request-time': time
|
| 97 |
+
};
|
| 98 |
+
|
| 99 |
+
const body = {
|
| 100 |
+
type: 'lyrics',
|
| 101 |
+
name: title,
|
| 102 |
+
lyrics
|
| 103 |
+
};
|
| 104 |
+
if (mood && mood.trim() !== '') body.mood = mood;
|
| 105 |
+
if (genre && genre.trim() !== '') body.genre = genre;
|
| 106 |
+
if (gender && gender.trim() !== '') body.gender = gender;
|
| 107 |
+
|
| 108 |
+
try {
|
| 109 |
+
const response = await axios.post(
|
| 110 |
+
`${sonu.api.base}${sonu.api.endpoints.create}`,
|
| 111 |
+
body,
|
| 112 |
+
{ headers: header }
|
| 113 |
+
);
|
| 114 |
+
|
| 115 |
+
return {
|
| 116 |
+
success: true,
|
| 117 |
+
code: 200,
|
| 118 |
+
result: { songId: response.data.id }
|
| 119 |
+
};
|
| 120 |
+
} catch (err) {
|
| 121 |
+
return {
|
| 122 |
+
success: false,
|
| 123 |
+
code: err.response?.status || 500,
|
| 124 |
+
result: { error: err.message }
|
| 125 |
+
};
|
| 126 |
+
}
|
| 127 |
+
},
|
| 128 |
+
|
| 129 |
+
task: async (songId) => {
|
| 130 |
+
const header = {
|
| 131 |
+
...sonu.headers,
|
| 132 |
+
'x-client-id': sonu.userId
|
| 133 |
+
};
|
| 134 |
+
|
| 135 |
+
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
| 136 |
+
|
| 137 |
+
try {
|
| 138 |
+
let attempt = 0;
|
| 139 |
+
let found = null;
|
| 140 |
+
|
| 141 |
+
while (true) {
|
| 142 |
+
const response = await axios.get(
|
| 143 |
+
`${sonu.api.base}${sonu.api.endpoints.checkStatus}`,
|
| 144 |
+
{
|
| 145 |
+
params: {
|
| 146 |
+
userId: sonu.userId,
|
| 147 |
+
isFavorite: false,
|
| 148 |
+
page: 1,
|
| 149 |
+
searchText: ''
|
| 150 |
+
},
|
| 151 |
+
headers: header
|
| 152 |
+
}
|
| 153 |
+
);
|
| 154 |
+
|
| 155 |
+
found = response.data.datas.find(song => song.id === songId);
|
| 156 |
+
if (!found) {
|
| 157 |
+
return {
|
| 158 |
+
success: false,
|
| 159 |
+
code: 404,
|
| 160 |
+
result: { error: "Lagunya belum jadi keknya bree, soalnya kagak ada 😂" }
|
| 161 |
+
};
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
attempt++;
|
| 165 |
+
|
| 166 |
+
if (found.url) {
|
| 167 |
+
return {
|
| 168 |
+
success: true,
|
| 169 |
+
code: 200,
|
| 170 |
+
result: {
|
| 171 |
+
status: found.status,
|
| 172 |
+
songId: found.id,
|
| 173 |
+
title: found.name,
|
| 174 |
+
username: found.username,
|
| 175 |
+
url: found.url,
|
| 176 |
+
thumbnail: found.thumbnail_url
|
| 177 |
+
}
|
| 178 |
+
};
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
await delay(3000);
|
| 182 |
+
}
|
| 183 |
+
} catch (err) {
|
| 184 |
+
return {
|
| 185 |
+
success: false,
|
| 186 |
+
code: err.response?.status || 500,
|
| 187 |
+
result: { error: err.message }
|
| 188 |
+
};
|
| 189 |
+
}
|
| 190 |
+
}
|
| 191 |
+
};
|
| 192 |
+
|
| 193 |
+
const handler = async (req, res) => {
|
| 194 |
+
try {
|
| 195 |
+
const { title, mood, genre, lyrics, gender } = req.query;
|
| 196 |
+
|
| 197 |
+
if (!title) {
|
| 198 |
+
return res.status(400).json({
|
| 199 |
+
success: false,
|
| 200 |
+
error: 'Missing required parameter: title'
|
| 201 |
+
});
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
if (!lyrics) {
|
| 205 |
+
return res.status(400).json({
|
| 206 |
+
success: false,
|
| 207 |
+
error: 'Missing required parameter: lyrics'
|
| 208 |
+
});
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
const registerResult = await sonu.register();
|
| 212 |
+
if (!registerResult.success) {
|
| 213 |
+
return res.status(registerResult.code).json({
|
| 214 |
+
author: "Herza",
|
| 215 |
+
success: false,
|
| 216 |
+
error: registerResult.result.error
|
| 217 |
+
});
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
const createResult = await sonu.create({ title, mood, genre, lyrics, gender });
|
| 221 |
+
if (!createResult.success) {
|
| 222 |
+
return res.status(createResult.code).json({
|
| 223 |
+
author: "Herza",
|
| 224 |
+
success: false,
|
| 225 |
+
error: createResult.result.error
|
| 226 |
+
});
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
const taskResult = await sonu.task(createResult.result.songId);
|
| 230 |
+
if (!taskResult.success) {
|
| 231 |
+
return res.status(taskResult.code).json({
|
| 232 |
+
author: "Herza",
|
| 233 |
+
success: false,
|
| 234 |
+
error: taskResult.result.error
|
| 235 |
+
});
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
res.json({
|
| 239 |
+
author: "Herza",
|
| 240 |
+
success: true,
|
| 241 |
+
result: taskResult.result
|
| 242 |
+
});
|
| 243 |
+
|
| 244 |
+
} catch (error) {
|
| 245 |
+
res.status(500).json({
|
| 246 |
+
success: false,
|
| 247 |
+
error: error.message
|
| 248 |
+
});
|
| 249 |
+
}
|
| 250 |
+
};
|
| 251 |
+
|
| 252 |
+
module.exports = {
|
| 253 |
+
name: 'Suno AI Music Generator',
|
| 254 |
+
description: 'Generate music using Suno AI with custom lyrics',
|
| 255 |
+
type: 'GET',
|
| 256 |
+
routes: ['api/AI/sunov1'],
|
| 257 |
+
tags: ['ai', 'music', 'suno', 'generator'],
|
| 258 |
+
main: ['AI'],
|
| 259 |
+
limit: 6,
|
| 260 |
+
parameters: ['title', 'lyrics', 'mood', 'genre', 'gender', 'key'],
|
| 261 |
+
enabled: true,
|
| 262 |
+
handler
|
| 263 |
+
};
|
plugins/sunov2.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
const { shannz: cf } = require('bycf');
|
| 3 |
+
|
| 4 |
+
class YesChatMusicGenerator {
|
| 5 |
+
constructor() {
|
| 6 |
+
this.userAgent = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Mobile Safari/537.36";
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
async getBypassToken() {
|
| 10 |
+
try {
|
| 11 |
+
const token = await cf.turnstileMin(
|
| 12 |
+
"https://www.yeschat.ai/",
|
| 13 |
+
"0x4AAAAAAATOXAtQtziH-Rwq"
|
| 14 |
+
);
|
| 15 |
+
return token;
|
| 16 |
+
} catch (error) {
|
| 17 |
+
throw new Error(`Failed to get bypass token: ${error.message}`);
|
| 18 |
+
}
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
async generateSongLyrics({
|
| 22 |
+
prompt,
|
| 23 |
+
title = "Tanpa Judul",
|
| 24 |
+
style = "Happy",
|
| 25 |
+
instrumental = false,
|
| 26 |
+
customMode = true,
|
| 27 |
+
}) {
|
| 28 |
+
const token = await this.getBypassToken();
|
| 29 |
+
if (!token || typeof token !== "string") {
|
| 30 |
+
throw new Error("Failed to get bypass token.");
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
const res = await axios.post(
|
| 34 |
+
"https://aiarticle.erweima.ai/api/v1/secondary-page/api/create",
|
| 35 |
+
{
|
| 36 |
+
prompt,
|
| 37 |
+
channel: "MUSIC",
|
| 38 |
+
id: 1018,
|
| 39 |
+
type: "features",
|
| 40 |
+
source: "yeschat.ai",
|
| 41 |
+
style,
|
| 42 |
+
title,
|
| 43 |
+
customMode,
|
| 44 |
+
instrumental,
|
| 45 |
+
},
|
| 46 |
+
{
|
| 47 |
+
headers: {
|
| 48 |
+
authority: "aiarticle.erweima.ai",
|
| 49 |
+
accept: "application/json, text/plain, */*",
|
| 50 |
+
"accept-language": "ms-MY,ms;q=0.9,en-US;q=0.8,en;q=0.7,id;q=0.6",
|
| 51 |
+
origin: "https://www.yeschat.ai",
|
| 52 |
+
referer: "https://www.yeschat.ai/",
|
| 53 |
+
"sec-ch-ua": '"Not A(Brand";v="8", "Chromium";v="132"',
|
| 54 |
+
"sec-ch-ua-mobile": "?1",
|
| 55 |
+
"sec-ch-ua-platform": '"Android"',
|
| 56 |
+
"sec-fetch-dest": "empty",
|
| 57 |
+
"sec-fetch-mode": "cors",
|
| 58 |
+
"sec-fetch-site": "cross-site",
|
| 59 |
+
"user-agent": this.userAgent,
|
| 60 |
+
uniqueid: Date.now(),
|
| 61 |
+
verify: token,
|
| 62 |
+
},
|
| 63 |
+
}
|
| 64 |
+
);
|
| 65 |
+
|
| 66 |
+
if (res.data.code !== 200) {
|
| 67 |
+
throw new Error(res.data.msg || "Failed to generate lyrics");
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
const recordId = res.data?.data?.recordId;
|
| 71 |
+
return this.pollGeneratedResult(recordId);
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
pollGeneratedResult(recordId, interval = 5000) {
|
| 75 |
+
return new Promise((resolve, reject) => {
|
| 76 |
+
const url = `https://aiarticle.erweima.ai/api/v1/secondary-page/api/${recordId}`;
|
| 77 |
+
const timer = setInterval(async () => {
|
| 78 |
+
try {
|
| 79 |
+
const { data } = await axios.get(url, {
|
| 80 |
+
headers: {
|
| 81 |
+
authority: "aiarticle.erweima.ai",
|
| 82 |
+
accept: "application/json, text/plain, */*",
|
| 83 |
+
"accept-language": "ms-MY,ms;q=0.9,en-US;q=0.8,en;q=0.7,id;q=0.6",
|
| 84 |
+
origin: "https://www.yeschat.ai",
|
| 85 |
+
referer: "https://www.yeschat.ai/",
|
| 86 |
+
"sec-ch-ua": '"Not A(Brand";v="8", "Chromium";v="132"',
|
| 87 |
+
"sec-ch-ua-mobile": "?1",
|
| 88 |
+
"sec-ch-ua-platform": '"Android"',
|
| 89 |
+
"sec-fetch-dest": "empty",
|
| 90 |
+
"sec-fetch-mode": "cors",
|
| 91 |
+
"sec-fetch-site": "cross-site",
|
| 92 |
+
"user-agent": this.userAgent,
|
| 93 |
+
},
|
| 94 |
+
});
|
| 95 |
+
|
| 96 |
+
if (data.code !== 200) {
|
| 97 |
+
clearInterval(timer);
|
| 98 |
+
return reject(new Error(data.msg || "Unexpected error"));
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
if (data.data?.failCode && data.data?.failMsg) {
|
| 102 |
+
clearInterval(timer);
|
| 103 |
+
return reject(new Error(data.data.failMsg));
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
if (data.data?.state && data.data.completeData) {
|
| 107 |
+
clearInterval(timer);
|
| 108 |
+
return resolve(JSON.parse(data.data.completeData));
|
| 109 |
+
}
|
| 110 |
+
} catch (err) {
|
| 111 |
+
clearInterval(timer);
|
| 112 |
+
return reject(err);
|
| 113 |
+
}
|
| 114 |
+
}, interval);
|
| 115 |
+
});
|
| 116 |
+
}
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
const handler = async (req, res) => {
|
| 120 |
+
try {
|
| 121 |
+
const { mode, prompt, lyrics, title, style, instrumental } = req.query;
|
| 122 |
+
|
| 123 |
+
if (!mode) {
|
| 124 |
+
return res.status(400).json({
|
| 125 |
+
success: false,
|
| 126 |
+
error: 'Missing required parameter: mode (custom/ai)'
|
| 127 |
+
});
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
const modeNormalized = mode.toLowerCase();
|
| 131 |
+
|
| 132 |
+
if (modeNormalized !== 'custom' && modeNormalized !== 'ai') {
|
| 133 |
+
return res.status(400).json({
|
| 134 |
+
success: false,
|
| 135 |
+
error: 'Invalid mode. Use "custom" for Custom Lyrics or "ai" for AI Lyrics'
|
| 136 |
+
});
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
let finalPrompt;
|
| 140 |
+
let customMode;
|
| 141 |
+
|
| 142 |
+
if (modeNormalized === 'custom') {
|
| 143 |
+
if (!lyrics) {
|
| 144 |
+
return res.status(400).json({
|
| 145 |
+
success: false,
|
| 146 |
+
error: 'Missing required parameter: lyrics (required for Custom Lyrics mode)'
|
| 147 |
+
});
|
| 148 |
+
}
|
| 149 |
+
finalPrompt = lyrics;
|
| 150 |
+
customMode = true;
|
| 151 |
+
} else {
|
| 152 |
+
if (!prompt) {
|
| 153 |
+
return res.status(400).json({
|
| 154 |
+
success: false,
|
| 155 |
+
error: 'Missing required parameter: prompt (required for AI Lyrics mode)'
|
| 156 |
+
});
|
| 157 |
+
}
|
| 158 |
+
finalPrompt = prompt;
|
| 159 |
+
customMode = false;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
const generator = new YesChatMusicGenerator();
|
| 163 |
+
|
| 164 |
+
const result = await generator.generateSongLyrics({
|
| 165 |
+
prompt: finalPrompt,
|
| 166 |
+
title: title || "Tanpa Judul",
|
| 167 |
+
style: style || "Happy",
|
| 168 |
+
instrumental: instrumental === 'true',
|
| 169 |
+
customMode: customMode
|
| 170 |
+
});
|
| 171 |
+
|
| 172 |
+
res.json({
|
| 173 |
+
author: "Herza",
|
| 174 |
+
success: true,
|
| 175 |
+
mode: modeNormalized === 'custom' ? 'Custom Lyrics' : 'AI Lyrics',
|
| 176 |
+
result: result
|
| 177 |
+
});
|
| 178 |
+
|
| 179 |
+
} catch (error) {
|
| 180 |
+
res.status(500).json({
|
| 181 |
+
success: false,
|
| 182 |
+
error: error.message
|
| 183 |
+
});
|
| 184 |
+
}
|
| 185 |
+
};
|
| 186 |
+
|
| 187 |
+
module.exports = {
|
| 188 |
+
name: 'SunoV2 Music Generator',
|
| 189 |
+
description: 'Generate music using YesChat AI with custom lyrics or AI-generated lyrics',
|
| 190 |
+
type: 'GET',
|
| 191 |
+
routes: ['api/AI/sunov2'],
|
| 192 |
+
tags: ['ai', 'music', 'yeschat', 'generator'],
|
| 193 |
+
main: ['AI'],
|
| 194 |
+
limit: 12,
|
| 195 |
+
parameters: ['mode', 'prompt', 'lyrics', 'title', 'style', 'instrumental', 'key'],
|
| 196 |
+
enabled: true,
|
| 197 |
+
handler
|
| 198 |
+
};
|
plugins/sunov3.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require("axios");
|
| 2 |
+
const { v4: uuidv4 } = require("uuid");
|
| 3 |
+
|
| 4 |
+
function randomHex(length) {
|
| 5 |
+
const chars = "abcdef0123456789";
|
| 6 |
+
return Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join("");
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
function gieneticTrace() {
|
| 10 |
+
return `${randomHex(32)}-${randomHex(16)}`;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
async function login(deviceId) {
|
| 14 |
+
const res = await axios.post(
|
| 15 |
+
"https://api.sunora.mavtao.com/api/auth/login",
|
| 16 |
+
{ device_id: deviceId },
|
| 17 |
+
{
|
| 18 |
+
headers: {
|
| 19 |
+
"user-agent": "Dart/3.4 (gienetic_build)",
|
| 20 |
+
"version": "2.2.2",
|
| 21 |
+
"accept-encoding": "gzip",
|
| 22 |
+
"content-type": "application/json",
|
| 23 |
+
"buildnumber": "105",
|
| 24 |
+
"platform": "android",
|
| 25 |
+
"sentry-trace": gieneticTrace()
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
);
|
| 29 |
+
return res.data?.data?.token || null;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
async function polllll(xAuth, maxAttempts = 30, delayMs = 30000) {
|
| 33 |
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
| 34 |
+
try {
|
| 35 |
+
const res = await axios.get(
|
| 36 |
+
"https://api.sunora.mavtao.com/api/music/music_page?page=1&pagesize=50",
|
| 37 |
+
{
|
| 38 |
+
headers: {
|
| 39 |
+
"user-agent": "Dart/3.4 (gienetic_build)",
|
| 40 |
+
"version": "2.2.2",
|
| 41 |
+
"accept-encoding": "gzip",
|
| 42 |
+
"x-auth": xAuth,
|
| 43 |
+
"buildnumber": "105",
|
| 44 |
+
"platform": "android",
|
| 45 |
+
"sentry-trace": gieneticTrace()
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
);
|
| 49 |
+
|
| 50 |
+
const records = res.data?.data?.records || [];
|
| 51 |
+
const doneSongs = records.filter(r => r.status === "complete");
|
| 52 |
+
|
| 53 |
+
if (doneSongs.length > 0) {
|
| 54 |
+
return doneSongs.map(r => ({
|
| 55 |
+
id: r.song_id,
|
| 56 |
+
title: r.title || "Sniff By: Gienetic",
|
| 57 |
+
tags: r.meta_tags,
|
| 58 |
+
prompt: r.meta_prompt,
|
| 59 |
+
audioUrl: r.audio_url,
|
| 60 |
+
videoUrl: r.video_url,
|
| 61 |
+
imageUrl: r.image_url,
|
| 62 |
+
model: r.model_name
|
| 63 |
+
}));
|
| 64 |
+
}
|
| 65 |
+
} catch (err) {
|
| 66 |
+
console.error("⚠️ Polling error:", err.response?.data || err.message);
|
| 67 |
+
}
|
| 68 |
+
await new Promise(r => setTimeout(r, delayMs));
|
| 69 |
+
}
|
| 70 |
+
return [];
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
async function generateNormal(description) {
|
| 74 |
+
const deviceId = uuidv4();
|
| 75 |
+
const token = await login(deviceId);
|
| 76 |
+
if (!token) throw new Error("⚠️ Error: gagal login (makanya tag author ny kalau recode :v)");
|
| 77 |
+
|
| 78 |
+
await axios.post(
|
| 79 |
+
"https://api.sunora.mavtao.com/api/music/advanced_custom_generate",
|
| 80 |
+
{
|
| 81 |
+
continue_at: null,
|
| 82 |
+
continue_clip_id: null,
|
| 83 |
+
mv: null,
|
| 84 |
+
description,
|
| 85 |
+
title: "",
|
| 86 |
+
mood: "",
|
| 87 |
+
music_style: "",
|
| 88 |
+
instrumental_only: false
|
| 89 |
+
},
|
| 90 |
+
{
|
| 91 |
+
headers: {
|
| 92 |
+
"user-agent": "Dart/3.4 (gienetic_build)",
|
| 93 |
+
"version": "2.2.2",
|
| 94 |
+
"accept-encoding": "gzip",
|
| 95 |
+
"x-auth": token,
|
| 96 |
+
"content-type": "application/json",
|
| 97 |
+
"buildnumber": "105",
|
| 98 |
+
"platform": "android",
|
| 99 |
+
"sentry-trace": gieneticTrace()
|
| 100 |
+
}
|
| 101 |
+
}
|
| 102 |
+
);
|
| 103 |
+
|
| 104 |
+
return await polllll(token);
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
async function generateCustom({ title, style, lyrics }) {
|
| 108 |
+
const deviceId = uuidv4();
|
| 109 |
+
const token = await login(deviceId);
|
| 110 |
+
if (!token) throw new Error("⚠️ Error: gagal login (makanya tag author ny kalau recode :v)");
|
| 111 |
+
|
| 112 |
+
await axios.post(
|
| 113 |
+
"https://api.sunora.mavtao.com/api/music/custom_generate",
|
| 114 |
+
{
|
| 115 |
+
continue_at: null,
|
| 116 |
+
continue_clip_id: null,
|
| 117 |
+
mv: null,
|
| 118 |
+
prompt: lyrics,
|
| 119 |
+
title,
|
| 120 |
+
tags: style
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
headers: {
|
| 124 |
+
"user-agent": "Dart/3.4 (gienetic_build)",
|
| 125 |
+
"version": "2.2.2",
|
| 126 |
+
"accept-encoding": "gzip",
|
| 127 |
+
"x-auth": token,
|
| 128 |
+
"content-type": "application/json",
|
| 129 |
+
"buildnumber": "105",
|
| 130 |
+
"platform": "android",
|
| 131 |
+
"sentry-trace": gieneticTrace()
|
| 132 |
+
}
|
| 133 |
+
}
|
| 134 |
+
);
|
| 135 |
+
|
| 136 |
+
return await polllll(token);
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
async function generateInstrumental(description) {
|
| 140 |
+
const deviceId = uuidv4();
|
| 141 |
+
const token = await login(deviceId);
|
| 142 |
+
if (!token) throw new Error("⚠️ Error: gagal login (makanya tag author ny kalau recode :v)");
|
| 143 |
+
|
| 144 |
+
await axios.post(
|
| 145 |
+
"https://api.sunora.mavtao.com/api/music/advanced_custom_generate",
|
| 146 |
+
{
|
| 147 |
+
continue_at: null,
|
| 148 |
+
continue_clip_id: null,
|
| 149 |
+
mv: null,
|
| 150 |
+
description,
|
| 151 |
+
title: "",
|
| 152 |
+
mood: "",
|
| 153 |
+
music_style: "",
|
| 154 |
+
instrumental_only: true
|
| 155 |
+
},
|
| 156 |
+
{
|
| 157 |
+
headers: {
|
| 158 |
+
"user-agent": "Dart/3.4 (gienetic_build)",
|
| 159 |
+
"version": "2.2.2",
|
| 160 |
+
"accept-encoding": "gzip",
|
| 161 |
+
"x-auth": token,
|
| 162 |
+
"content-type": "application/json",
|
| 163 |
+
"buildnumber": "105",
|
| 164 |
+
"platform": "android",
|
| 165 |
+
"sentry-trace": gieneticTrace()
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
);
|
| 169 |
+
|
| 170 |
+
return await polllll(token);
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
const handler = async (req, res) => {
|
| 174 |
+
try {
|
| 175 |
+
const { mode, description, title, style, lyrics } = req.query;
|
| 176 |
+
|
| 177 |
+
if (!mode) {
|
| 178 |
+
return res.status(400).json({
|
| 179 |
+
success: false,
|
| 180 |
+
error: 'Missing required parameter: mode (normal/custom/instrumental)'
|
| 181 |
+
});
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
const modeNormalized = mode.toLowerCase();
|
| 185 |
+
|
| 186 |
+
if (!['normal', 'custom', 'instrumental'].includes(modeNormalized)) {
|
| 187 |
+
return res.status(400).json({
|
| 188 |
+
success: false,
|
| 189 |
+
error: 'Invalid mode. Use "normal", "custom", or "instrumental"'
|
| 190 |
+
});
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
let result;
|
| 194 |
+
|
| 195 |
+
if (modeNormalized === 'normal') {
|
| 196 |
+
if (!description) {
|
| 197 |
+
return res.status(400).json({
|
| 198 |
+
success: false,
|
| 199 |
+
error: 'Missing required parameter: description (required for normal mode)'
|
| 200 |
+
});
|
| 201 |
+
}
|
| 202 |
+
result = await generateNormal(description);
|
| 203 |
+
} else if (modeNormalized === 'custom') {
|
| 204 |
+
if (!title || !style || !lyrics) {
|
| 205 |
+
return res.status(400).json({
|
| 206 |
+
success: false,
|
| 207 |
+
error: 'Missing required parameters: title, style, lyrics (required for custom mode)'
|
| 208 |
+
});
|
| 209 |
+
}
|
| 210 |
+
result = await generateCustom({ title, style, lyrics });
|
| 211 |
+
} else if (modeNormalized === 'instrumental') {
|
| 212 |
+
if (!description) {
|
| 213 |
+
return res.status(400).json({
|
| 214 |
+
success: false,
|
| 215 |
+
error: 'Missing required parameter: description (required for instrumental mode)'
|
| 216 |
+
});
|
| 217 |
+
}
|
| 218 |
+
result = await generateInstrumental(description);
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
if (!result || result.length === 0) {
|
| 222 |
+
return res.status(500).json({
|
| 223 |
+
success: false,
|
| 224 |
+
error: 'Failed to generate music or timeout'
|
| 225 |
+
});
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
res.json({
|
| 229 |
+
author: "Herza",
|
| 230 |
+
success: true,
|
| 231 |
+
mode: modeNormalized,
|
| 232 |
+
result: result
|
| 233 |
+
});
|
| 234 |
+
|
| 235 |
+
} catch (error) {
|
| 236 |
+
res.status(500).json({
|
| 237 |
+
success: false,
|
| 238 |
+
error: error.message
|
| 239 |
+
});
|
| 240 |
+
}
|
| 241 |
+
};
|
| 242 |
+
|
| 243 |
+
module.exports = {
|
| 244 |
+
name: 'Suno V3 Music Generator',
|
| 245 |
+
description: 'Generate music using Suno V3 AI with multiple modes',
|
| 246 |
+
type: 'GET',
|
| 247 |
+
routes: ['api/AI/sunov3'],
|
| 248 |
+
tags: ['ai', 'music', 'suno', 'generator'],
|
| 249 |
+
main: ['AI'],
|
| 250 |
+
parameters: ['mode', 'description', 'title', 'style', 'lyrics', 'key'],
|
| 251 |
+
enabled: true,
|
| 252 |
+
limit: 15,
|
| 253 |
+
handler
|
| 254 |
+
};
|
plugins/terabox.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { url } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!url) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: url'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const match = url.match(/\/s\/([^/?#]+)/);
|
| 15 |
+
if (!match || !match[1]) {
|
| 16 |
+
return res.status(400).json({
|
| 17 |
+
success: false,
|
| 18 |
+
error: 'Invalid URL format'
|
| 19 |
+
});
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
const id = match[1];
|
| 23 |
+
const { data } = await axios.get(`https://tera2.sylyt93.workers.dev/info?s=${id}`);
|
| 24 |
+
|
| 25 |
+
res.json({
|
| 26 |
+
author: "Herza",
|
| 27 |
+
success: data.status === 'ok',
|
| 28 |
+
data: data.status === 'ok' ? {
|
| 29 |
+
file: data.file,
|
| 30 |
+
dlink: data.dlink
|
| 31 |
+
} : {}
|
| 32 |
+
});
|
| 33 |
+
|
| 34 |
+
} catch (error) {
|
| 35 |
+
res.status(500).json({
|
| 36 |
+
success: false,
|
| 37 |
+
error: error.message
|
| 38 |
+
});
|
| 39 |
+
}
|
| 40 |
+
};
|
| 41 |
+
|
| 42 |
+
module.exports = {
|
| 43 |
+
name: 'TeraBox DL',
|
| 44 |
+
description: 'Auto extract ID and get file info from TeraBox URL',
|
| 45 |
+
type: 'GET',
|
| 46 |
+
routes: ['api/download/terabox'],
|
| 47 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 48 |
+
parameters: ['url', 'key'],
|
| 49 |
+
enabled: true,
|
| 50 |
+
main: ['Downloader'],
|
| 51 |
+
handler
|
| 52 |
+
};
|
plugins/text2img.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios')
|
| 2 |
+
const FormData = require('form-data')
|
| 3 |
+
const fetch = require('node-fetch')
|
| 4 |
+
|
| 5 |
+
const handler = async (req, res) => {
|
| 6 |
+
try {
|
| 7 |
+
const { text } = req.query;
|
| 8 |
+
|
| 9 |
+
if (!text) {
|
| 10 |
+
return res.status(400).json({
|
| 11 |
+
success: false,
|
| 12 |
+
error: 'Missing required parameter: text'
|
| 13 |
+
});
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
let result = await axios.get(`https://ab-text-toimgfast.abrahamdw882.workers.dev/?text=${encodeURIComponent(text)}`, {
|
| 17 |
+
responseType: 'arraybuffer'
|
| 18 |
+
})
|
| 19 |
+
|
| 20 |
+
let buffer = Buffer.from(result.data)
|
| 21 |
+
|
| 22 |
+
let form = new FormData()
|
| 23 |
+
form.append('file', buffer, {
|
| 24 |
+
filename: 'image.webp',
|
| 25 |
+
contentType: 'image/webp'
|
| 26 |
+
})
|
| 27 |
+
|
| 28 |
+
let uploadRes = await fetch('https://tmpfiles.org/api/v1/upload', {
|
| 29 |
+
method: 'POST',
|
| 30 |
+
body: form
|
| 31 |
+
})
|
| 32 |
+
|
| 33 |
+
let uploadData = await uploadRes.json()
|
| 34 |
+
let fileUrl = uploadData.data.url.replace('tmpfiles.org/', 'tmpfiles.org/dl/')
|
| 35 |
+
|
| 36 |
+
res.json({
|
| 37 |
+
author: "Herza",
|
| 38 |
+
success: true,
|
| 39 |
+
url: fileUrl
|
| 40 |
+
});
|
| 41 |
+
|
| 42 |
+
} catch (error) {
|
| 43 |
+
res.status(500).json({
|
| 44 |
+
success: false,
|
| 45 |
+
error: error.message
|
| 46 |
+
});
|
| 47 |
+
}
|
| 48 |
+
};
|
| 49 |
+
|
| 50 |
+
module.exports = {
|
| 51 |
+
name: 'Text2IMG AI',
|
| 52 |
+
description: 'Generate Image using OpenAI ChatGPT',
|
| 53 |
+
type: 'GET',
|
| 54 |
+
routes: ['api/AI/text2img'],
|
| 55 |
+
tags: ['ai', 'text2img', 'openai'],
|
| 56 |
+
main: ['AI'],
|
| 57 |
+
parameters: ['text'],
|
| 58 |
+
enabled: true,
|
| 59 |
+
handler
|
| 60 |
+
};
|
plugins/text2video.js
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
const FormData = require('form-data');
|
| 3 |
+
|
| 4 |
+
const aiLabs = {
|
| 5 |
+
api: {
|
| 6 |
+
base: 'https://text2video.aritek.app',
|
| 7 |
+
endpoints: {
|
| 8 |
+
text2img: '/text2img',
|
| 9 |
+
generate: '/txt2videov3',
|
| 10 |
+
video: '/video'
|
| 11 |
+
}
|
| 12 |
+
},
|
| 13 |
+
|
| 14 |
+
headers: {
|
| 15 |
+
'user-agent': 'NB Android/1.0.0',
|
| 16 |
+
'accept-encoding': 'gzip',
|
| 17 |
+
'content-type': 'application/json',
|
| 18 |
+
authorization: ''
|
| 19 |
+
},
|
| 20 |
+
|
| 21 |
+
state: {
|
| 22 |
+
token: null
|
| 23 |
+
},
|
| 24 |
+
|
| 25 |
+
setup: {
|
| 26 |
+
cipher: 'hbMcgZLlzvghRlLbPcTbCpfcQKM0PcU0zhPcTlOFMxBZ1oLmruzlVp9remPgi0QWP0QW',
|
| 27 |
+
shiftValue: 3,
|
| 28 |
+
|
| 29 |
+
dec(text, shift) {
|
| 30 |
+
return [...text].map(c =>
|
| 31 |
+
/[a-z]/.test(c)
|
| 32 |
+
? String.fromCharCode((c.charCodeAt(0) - 97 - shift + 26) % 26 + 97)
|
| 33 |
+
: /[A-Z]/.test(c)
|
| 34 |
+
? String.fromCharCode((c.charCodeAt(0) - 65 - shift + 26) % 26 + 65)
|
| 35 |
+
: c
|
| 36 |
+
).join('');
|
| 37 |
+
},
|
| 38 |
+
|
| 39 |
+
decrypt: async () => {
|
| 40 |
+
if (aiLabs.state.token) return aiLabs.state.token;
|
| 41 |
+
|
| 42 |
+
const input = aiLabs.setup.cipher;
|
| 43 |
+
const shift = aiLabs.setup.shiftValue;
|
| 44 |
+
const decrypted = aiLabs.setup.dec(input, shift);
|
| 45 |
+
|
| 46 |
+
aiLabs.state.token = decrypted;
|
| 47 |
+
aiLabs.headers.authorization = decrypted;
|
| 48 |
+
return decrypted;
|
| 49 |
+
}
|
| 50 |
+
},
|
| 51 |
+
|
| 52 |
+
deviceId() {
|
| 53 |
+
return Array.from({ length: 16 }, () =>
|
| 54 |
+
Math.floor(Math.random() * 16).toString(16)
|
| 55 |
+
).join('');
|
| 56 |
+
},
|
| 57 |
+
|
| 58 |
+
text2img: async (prompt) => {
|
| 59 |
+
if (!prompt?.trim()) {
|
| 60 |
+
return {
|
| 61 |
+
success: false,
|
| 62 |
+
code: 400,
|
| 63 |
+
result: {
|
| 64 |
+
error: 'Yang bener aja anjirr, inputnya kosong begitu 🗿'
|
| 65 |
+
}
|
| 66 |
+
};
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
const token = await aiLabs.setup.decrypt();
|
| 70 |
+
const form = new FormData();
|
| 71 |
+
form.append('prompt', prompt);
|
| 72 |
+
form.append('token', token);
|
| 73 |
+
|
| 74 |
+
try {
|
| 75 |
+
const url = aiLabs.api.base + aiLabs.api.endpoints.text2img;
|
| 76 |
+
const res = await axios.post(url, form, {
|
| 77 |
+
headers: {
|
| 78 |
+
...aiLabs.headers,
|
| 79 |
+
...form.getHeaders()
|
| 80 |
+
}
|
| 81 |
+
});
|
| 82 |
+
|
| 83 |
+
const { code, url: imageUrl } = res.data;
|
| 84 |
+
if (code !== 0 || !imageUrl) {
|
| 85 |
+
return {
|
| 86 |
+
success: false,
|
| 87 |
+
code: res.status,
|
| 88 |
+
result: {
|
| 89 |
+
error: 'Error bree 😂'
|
| 90 |
+
}
|
| 91 |
+
};
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
return {
|
| 95 |
+
success: true,
|
| 96 |
+
code: res.status,
|
| 97 |
+
result: {
|
| 98 |
+
url: imageUrl.trim(),
|
| 99 |
+
prompt
|
| 100 |
+
}
|
| 101 |
+
};
|
| 102 |
+
} catch (err) {
|
| 103 |
+
return {
|
| 104 |
+
success: false,
|
| 105 |
+
code: err.response?.status || 500,
|
| 106 |
+
result: {
|
| 107 |
+
error: err.message || 'Error bree 😂'
|
| 108 |
+
}
|
| 109 |
+
};
|
| 110 |
+
}
|
| 111 |
+
},
|
| 112 |
+
|
| 113 |
+
generate: async ({ prompt = '', type = 'video', isPremium = 1 } = {}) => {
|
| 114 |
+
if (!prompt?.trim() || !/^[a-zA-Z0-9\s.,!?'-]+$/.test(prompt)) {
|
| 115 |
+
return {
|
| 116 |
+
success: false,
|
| 117 |
+
code: 400,
|
| 118 |
+
result: {
|
| 119 |
+
error: 'Promptnya kagak boleh kosong bree.. apalagi ada karakternya aneh begitu :v kagak boleh yak 😂'
|
| 120 |
+
}
|
| 121 |
+
};
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
if (!/^(image|video)$/.test(type)) {
|
| 125 |
+
return {
|
| 126 |
+
success: false,
|
| 127 |
+
code: 400,
|
| 128 |
+
result: {
|
| 129 |
+
error: 'Tipenya kagak valid.. lu bisa pake image atau video yak.. ☺️'
|
| 130 |
+
}
|
| 131 |
+
};
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
if (type === 'image') {
|
| 135 |
+
return await aiLabs.text2img(prompt);
|
| 136 |
+
} else {
|
| 137 |
+
await aiLabs.setup.decrypt();
|
| 138 |
+
const payload = {
|
| 139 |
+
deviceID: aiLabs.deviceId(),
|
| 140 |
+
isPremium,
|
| 141 |
+
prompt,
|
| 142 |
+
used: [],
|
| 143 |
+
versionCode: 59
|
| 144 |
+
};
|
| 145 |
+
|
| 146 |
+
try {
|
| 147 |
+
const url = aiLabs.api.base + aiLabs.api.endpoints.generate;
|
| 148 |
+
const res = await axios.post(url, payload, { headers: aiLabs.headers });
|
| 149 |
+
|
| 150 |
+
const { code, key } = res.data;
|
| 151 |
+
if (code !== 0 || !key || typeof key !== 'string') {
|
| 152 |
+
return {
|
| 153 |
+
success: false,
|
| 154 |
+
code: res.status,
|
| 155 |
+
result: {
|
| 156 |
+
error: 'Heumm.. Gagal bree ngambil Keynya 🫵🏻🐷'
|
| 157 |
+
}
|
| 158 |
+
};
|
| 159 |
+
}
|
| 160 |
+
return await aiLabs.video(key);
|
| 161 |
+
} catch (err) {
|
| 162 |
+
return {
|
| 163 |
+
success: false,
|
| 164 |
+
code: err.response?.status || 500,
|
| 165 |
+
result: {
|
| 166 |
+
error: err.message || 'Error bree... 😂'
|
| 167 |
+
}
|
| 168 |
+
};
|
| 169 |
+
}
|
| 170 |
+
}
|
| 171 |
+
},
|
| 172 |
+
|
| 173 |
+
video: async (key) => {
|
| 174 |
+
if (!key || typeof key !== 'string') {
|
| 175 |
+
return {
|
| 176 |
+
success: false,
|
| 177 |
+
code: 400,
|
| 178 |
+
result: {
|
| 179 |
+
error: 'Keynya kagak valid bree... 😏😂'
|
| 180 |
+
}
|
| 181 |
+
};
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
await aiLabs.setup.decrypt();
|
| 185 |
+
const payload = { keys: [key] };
|
| 186 |
+
const url = aiLabs.api.base + aiLabs.api.endpoints.video;
|
| 187 |
+
const maxAttempts = 100;
|
| 188 |
+
const delay = 2000;
|
| 189 |
+
let attempt = 0;
|
| 190 |
+
|
| 191 |
+
while (attempt < maxAttempts) {
|
| 192 |
+
attempt++;
|
| 193 |
+
try {
|
| 194 |
+
const res = await axios.post(url, payload, {
|
| 195 |
+
headers: aiLabs.headers,
|
| 196 |
+
timeout: 15000
|
| 197 |
+
});
|
| 198 |
+
|
| 199 |
+
const { code, datas } = res.data;
|
| 200 |
+
if (code === 0 && Array.isArray(datas) && datas.length > 0) {
|
| 201 |
+
const data = datas[0];
|
| 202 |
+
if (!data.url || data.url.trim() === '') {
|
| 203 |
+
await new Promise(r => setTimeout(r, delay));
|
| 204 |
+
continue;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
return {
|
| 208 |
+
success: true,
|
| 209 |
+
code: res.status,
|
| 210 |
+
result: {
|
| 211 |
+
url: data.url.trim(),
|
| 212 |
+
safe: data.safe === 'true',
|
| 213 |
+
key: data.key,
|
| 214 |
+
progress: '100%'
|
| 215 |
+
}
|
| 216 |
+
};
|
| 217 |
+
}
|
| 218 |
+
} catch (err) {
|
| 219 |
+
const retry = ['ECONNRESET', 'ECONNABORTED', 'ETIMEDOUT'].includes(err.code);
|
| 220 |
+
if (retry && attempt < maxAttempts) {
|
| 221 |
+
await new Promise(r => setTimeout(r, delay));
|
| 222 |
+
continue;
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
return {
|
| 226 |
+
success: false,
|
| 227 |
+
code: err.response?.status || 500,
|
| 228 |
+
result: {
|
| 229 |
+
error: 'Error bree...',
|
| 230 |
+
attempt
|
| 231 |
+
}
|
| 232 |
+
};
|
| 233 |
+
}
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
return {
|
| 237 |
+
success: false,
|
| 238 |
+
code: 504,
|
| 239 |
+
result: {
|
| 240 |
+
error: 'Proses videonya kelamaan, keknya lagi ngambek tuh Server AI nya wkwk... ',
|
| 241 |
+
attempt
|
| 242 |
+
}
|
| 243 |
+
};
|
| 244 |
+
}
|
| 245 |
+
};
|
| 246 |
+
|
| 247 |
+
const handler = async (req, res) => {
|
| 248 |
+
try {
|
| 249 |
+
const { prompt } = req.query;
|
| 250 |
+
|
| 251 |
+
if (!prompt) {
|
| 252 |
+
return res.status(400).json({
|
| 253 |
+
success: false,
|
| 254 |
+
error: 'Missing required parameter: prompt'
|
| 255 |
+
});
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
const result = await aiLabs.generate({
|
| 259 |
+
prompt: prompt,
|
| 260 |
+
type: 'video',
|
| 261 |
+
isPremium: 1
|
| 262 |
+
});
|
| 263 |
+
|
| 264 |
+
if (!result.success) {
|
| 265 |
+
return res.status(result.code).json({
|
| 266 |
+
author: "Herza",
|
| 267 |
+
success: false,
|
| 268 |
+
error: result.result.error
|
| 269 |
+
});
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
res.json({
|
| 273 |
+
author: "Herza",
|
| 274 |
+
success: true,
|
| 275 |
+
result: result.result
|
| 276 |
+
});
|
| 277 |
+
|
| 278 |
+
} catch (error) {
|
| 279 |
+
res.status(500).json({
|
| 280 |
+
success: false,
|
| 281 |
+
error: error.message
|
| 282 |
+
});
|
| 283 |
+
}
|
| 284 |
+
};
|
| 285 |
+
|
| 286 |
+
module.exports = {
|
| 287 |
+
name: 'AI Labs Text to Video',
|
| 288 |
+
description: 'Generate video from text prompt using AI Labs',
|
| 289 |
+
type: 'GET',
|
| 290 |
+
routes: ['api/AI/text2video'],
|
| 291 |
+
tags: ['ai', 'video', 'text-to-video', 'generator'],
|
| 292 |
+
main: ['AI'],
|
| 293 |
+
parameters: ['prompt', 'key'],
|
| 294 |
+
enabled: true,
|
| 295 |
+
handler
|
| 296 |
+
};
|
plugins/threads.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
|
| 3 |
+
async function threads(url) {
|
| 4 |
+
try {
|
| 5 |
+
const response = await axios.get('https://api.threadsphotodownloader.com/v2/media', {
|
| 6 |
+
params: {
|
| 7 |
+
url: url
|
| 8 |
+
},
|
| 9 |
+
headers: {
|
| 10 |
+
'Accept': '*/*',
|
| 11 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
| 12 |
+
}
|
| 13 |
+
});
|
| 14 |
+
|
| 15 |
+
const data = response.data;
|
| 16 |
+
|
| 17 |
+
if (!data.image_urls && !data.video_urls) {
|
| 18 |
+
return {
|
| 19 |
+
author: 'Herza',
|
| 20 |
+
status: 400,
|
| 21 |
+
data: {
|
| 22 |
+
error: true,
|
| 23 |
+
message: 'No media found'
|
| 24 |
+
}
|
| 25 |
+
};
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
return {
|
| 29 |
+
author: 'Herza',
|
| 30 |
+
status: 200,
|
| 31 |
+
data: {
|
| 32 |
+
images: data.image_urls || [],
|
| 33 |
+
videos: data.video_urls || []
|
| 34 |
+
}
|
| 35 |
+
};
|
| 36 |
+
|
| 37 |
+
} catch (error) {
|
| 38 |
+
return {
|
| 39 |
+
author: 'Herza',
|
| 40 |
+
status: 500,
|
| 41 |
+
data: {
|
| 42 |
+
error: true,
|
| 43 |
+
message: error.message
|
| 44 |
+
}
|
| 45 |
+
};
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
const handler = async (req, res) => {
|
| 50 |
+
try {
|
| 51 |
+
const { url } = req.query;
|
| 52 |
+
|
| 53 |
+
if (!url) {
|
| 54 |
+
return res.status(400).json({
|
| 55 |
+
success: false,
|
| 56 |
+
error: 'Missing required parameter: url'
|
| 57 |
+
});
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
const result = await threads(url);
|
| 61 |
+
|
| 62 |
+
if (result.status !== 200) {
|
| 63 |
+
return res.status(result.status).json({
|
| 64 |
+
success: false,
|
| 65 |
+
error: result.data.message
|
| 66 |
+
});
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
res.json({
|
| 70 |
+
author: "Herza",
|
| 71 |
+
success: true,
|
| 72 |
+
msg: result.data
|
| 73 |
+
});
|
| 74 |
+
|
| 75 |
+
} catch (error) {
|
| 76 |
+
res.status(500).json({
|
| 77 |
+
success: false,
|
| 78 |
+
error: error.message
|
| 79 |
+
});
|
| 80 |
+
}
|
| 81 |
+
};
|
| 82 |
+
|
| 83 |
+
module.exports = {
|
| 84 |
+
name: 'Threads DL',
|
| 85 |
+
description: 'Download Threads Media',
|
| 86 |
+
type: 'GET',
|
| 87 |
+
routes: ['api/download/threads'],
|
| 88 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 89 |
+
parameters: ['url', 'key'],
|
| 90 |
+
enabled: true,
|
| 91 |
+
main: ['Downloader'],
|
| 92 |
+
handler
|
| 93 |
+
}
|
plugins/tiktok.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { tiktok } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { url } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!url) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: url'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await tiktok(url);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
msg: result.data
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'TikTok DL',
|
| 31 |
+
description: 'Download TikTok Video Without WM',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/download/tiktok'],
|
| 34 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 35 |
+
parameters: ['url', 'key'],
|
| 36 |
+
enabled: true,
|
| 37 |
+
main: ['Downloader'],
|
| 38 |
+
handler
|
| 39 |
+
}
|
plugins/ttstalk.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
const cheerio = require('cheerio');
|
| 3 |
+
const { shannz: cf } = require('bycf');
|
| 4 |
+
|
| 5 |
+
async function getTurnstileToken() {
|
| 6 |
+
try {
|
| 7 |
+
const token = await cf.turnstileMin(
|
| 8 |
+
"https://claptools.com/tiktok-profile-viewer/",
|
| 9 |
+
"0x4AAAAAAA0aU62HwPRV0j1U"
|
| 10 |
+
);
|
| 11 |
+
return token;
|
| 12 |
+
} catch (error) {
|
| 13 |
+
throw new Error("Gagal mendapatkan Turnstile token: " + error.message);
|
| 14 |
+
}
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
async function getNonce() {
|
| 18 |
+
const response = await axios.get('https://claptools.com/tiktok-profile-viewer/', {
|
| 19 |
+
headers: {
|
| 20 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
| 21 |
+
}
|
| 22 |
+
});
|
| 23 |
+
|
| 24 |
+
const $ = cheerio.load(response.data);
|
| 25 |
+
const nonce = $('input[name="tt_nonce"]').val();
|
| 26 |
+
return nonce;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
async function tiktokStalk(username) {
|
| 30 |
+
const token = await getTurnstileToken();
|
| 31 |
+
const nonce = await getNonce();
|
| 32 |
+
|
| 33 |
+
const formData = new URLSearchParams();
|
| 34 |
+
formData.append('username', username);
|
| 35 |
+
formData.append('tt_nonce', nonce);
|
| 36 |
+
formData.append('cf-turnstile-response', token);
|
| 37 |
+
|
| 38 |
+
const response = await axios.post('https://claptools.com/tiktok-profile-viewer/', formData, {
|
| 39 |
+
headers: {
|
| 40 |
+
'Content-Type': 'application/x-www-form-urlencoded',
|
| 41 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
| 42 |
+
'Referer': 'https://claptools.com/tiktok-profile-viewer/',
|
| 43 |
+
'Origin': 'https://claptools.com'
|
| 44 |
+
}
|
| 45 |
+
});
|
| 46 |
+
|
| 47 |
+
const $ = cheerio.load(response.data);
|
| 48 |
+
|
| 49 |
+
const avatar = $('.profile img').attr('src');
|
| 50 |
+
const fullText = $('.profile-details h2').text().trim();
|
| 51 |
+
const bio = $('.profile-details p').text().trim();
|
| 52 |
+
|
| 53 |
+
const nameMatch = fullText.match(/^(.+?)\s*\(@(.+?)\)$/);
|
| 54 |
+
const nickname = nameMatch ? nameMatch[1].trim() : '';
|
| 55 |
+
const usernameFromPage = nameMatch ? nameMatch[2].trim() : username;
|
| 56 |
+
|
| 57 |
+
const followers = $('.stats .box').eq(0).find('.number').text().trim();
|
| 58 |
+
const likes = $('.stats .box').eq(1).find('.number').text().trim();
|
| 59 |
+
const videos = $('.stats .box').eq(2).find('.number').text().trim();
|
| 60 |
+
|
| 61 |
+
const videoList = [];
|
| 62 |
+
$('.thumb').each((i, elem) => {
|
| 63 |
+
const thumbnail = $(elem).find('img').attr('src');
|
| 64 |
+
if (thumbnail) {
|
| 65 |
+
videoList.push({
|
| 66 |
+
thumbnail: thumbnail
|
| 67 |
+
});
|
| 68 |
+
}
|
| 69 |
+
});
|
| 70 |
+
|
| 71 |
+
return {
|
| 72 |
+
username: usernameFromPage,
|
| 73 |
+
nickname: nickname,
|
| 74 |
+
bio: bio,
|
| 75 |
+
avatar: avatar,
|
| 76 |
+
stats: {
|
| 77 |
+
followers: followers,
|
| 78 |
+
likes: likes,
|
| 79 |
+
videos: videos
|
| 80 |
+
},
|
| 81 |
+
videoList: videoList
|
| 82 |
+
};
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
const handler = async (req, res) => {
|
| 86 |
+
try {
|
| 87 |
+
const { username } = req.query;
|
| 88 |
+
|
| 89 |
+
if (!username) {
|
| 90 |
+
return res.status(400).json({
|
| 91 |
+
success: false,
|
| 92 |
+
error: 'Missing required parameter: username'
|
| 93 |
+
});
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
const usernameRegex = /^[a-zA-Z0-9._]{1,24}$/;
|
| 97 |
+
if (!usernameRegex.test(username)) {
|
| 98 |
+
return res.status(400).json({
|
| 99 |
+
success: false,
|
| 100 |
+
error: 'Invalid username format'
|
| 101 |
+
});
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
const result = await tiktokStalk(username);
|
| 105 |
+
|
| 106 |
+
res.json({
|
| 107 |
+
author: "Herza",
|
| 108 |
+
success: true,
|
| 109 |
+
data: result
|
| 110 |
+
});
|
| 111 |
+
|
| 112 |
+
} catch (error) {
|
| 113 |
+
res.status(500).json({
|
| 114 |
+
author: "Herza",
|
| 115 |
+
success: false,
|
| 116 |
+
error: error.message
|
| 117 |
+
});
|
| 118 |
+
}
|
| 119 |
+
};
|
| 120 |
+
|
| 121 |
+
module.exports = {
|
| 122 |
+
name: 'TikTok Stalk',
|
| 123 |
+
description: 'Get TikTok user profile information including stats and avatar',
|
| 124 |
+
type: 'GET',
|
| 125 |
+
routes: ['api/stalk/tiktok'],
|
| 126 |
+
tags: ['social', 'tiktok', 'stalk', 'profile'],
|
| 127 |
+
parameters: ['username', 'key'],
|
| 128 |
+
enabled: true,
|
| 129 |
+
main: ['Stalk'],
|
| 130 |
+
handler
|
| 131 |
+
};
|
plugins/twitter.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
const cheerio = require('cheerio');
|
| 3 |
+
const crypto = require('crypto');
|
| 4 |
+
|
| 5 |
+
async function twitterDownloader(url) {
|
| 6 |
+
try {
|
| 7 |
+
const urlParams = new URLSearchParams(url.split('?')[1]);
|
| 8 |
+
const tweetUrl = urlParams.get('url') || url;
|
| 9 |
+
const decodedUrl = decodeURIComponent(tweetUrl);
|
| 10 |
+
|
| 11 |
+
const timestamp = Math.floor(Date.now() / 1000);
|
| 12 |
+
const hash = crypto.createHash('md5');
|
| 13 |
+
hash.update(timestamp.toString() + 'ssstwitter');
|
| 14 |
+
const tt = hash.digest('hex');
|
| 15 |
+
|
| 16 |
+
const postData = new URLSearchParams({
|
| 17 |
+
'id': decodedUrl,
|
| 18 |
+
'locale': 'en',
|
| 19 |
+
'tt': tt,
|
| 20 |
+
'ts': timestamp.toString(),
|
| 21 |
+
'source': 'form'
|
| 22 |
+
});
|
| 23 |
+
|
| 24 |
+
const { data: html } = await axios.post('https://ssstwitter.com/', postData, {
|
| 25 |
+
headers: {
|
| 26 |
+
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
| 27 |
+
'HX-Request': 'true',
|
| 28 |
+
'HX-Target': 'target',
|
| 29 |
+
'HX-Current-URL': 'https://ssstwitter.com/en-2',
|
| 30 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
| 31 |
+
'Origin': 'https://ssstwitter.com',
|
| 32 |
+
'Referer': 'https://ssstwitter.com/en-2'
|
| 33 |
+
}
|
| 34 |
+
});
|
| 35 |
+
|
| 36 |
+
const $ = cheerio.load(html);
|
| 37 |
+
const title = $('h2').first().text().trim();
|
| 38 |
+
const downloads = [];
|
| 39 |
+
|
| 40 |
+
$('.download-btn').each((i, elem) => {
|
| 41 |
+
const $elem = $(elem);
|
| 42 |
+
const downloadUrl = $elem.attr('href');
|
| 43 |
+
const qualityText = $elem.find('span').text().trim();
|
| 44 |
+
const quality = qualityText.replace('Download', '').trim();
|
| 45 |
+
|
| 46 |
+
if (downloadUrl && downloadUrl.startsWith('http')) {
|
| 47 |
+
downloads.push({
|
| 48 |
+
quality: quality,
|
| 49 |
+
url: downloadUrl
|
| 50 |
+
});
|
| 51 |
+
}
|
| 52 |
+
});
|
| 53 |
+
|
| 54 |
+
const mediaType = downloads.length > 0 ? 'video' : 'unknown';
|
| 55 |
+
const hdDownload = downloads.find(d => d.quality.includes('HD')) || downloads[0];
|
| 56 |
+
|
| 57 |
+
return {
|
| 58 |
+
title: title || 'Twitter Media',
|
| 59 |
+
mediaType: mediaType,
|
| 60 |
+
downloads: downloads,
|
| 61 |
+
hdUrl: hdDownload ? hdDownload.url : null,
|
| 62 |
+
hdQuality: hdDownload ? hdDownload.quality : null
|
| 63 |
+
};
|
| 64 |
+
|
| 65 |
+
} catch (error) {
|
| 66 |
+
throw new Error(error.message);
|
| 67 |
+
}
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
const handler = async (req, res) => {
|
| 71 |
+
try {
|
| 72 |
+
const { url } = req.query;
|
| 73 |
+
if (!url) {
|
| 74 |
+
return res.status(400).json({
|
| 75 |
+
success: false,
|
| 76 |
+
error: 'Missing required parameter: url'
|
| 77 |
+
});
|
| 78 |
+
}
|
| 79 |
+
const result = await twitterDownloader(url);
|
| 80 |
+
res.json({
|
| 81 |
+
author: "Herza",
|
| 82 |
+
success: true,
|
| 83 |
+
msg: result
|
| 84 |
+
});
|
| 85 |
+
} catch (error) {
|
| 86 |
+
res.status(500).json({
|
| 87 |
+
success: false,
|
| 88 |
+
error: error.message
|
| 89 |
+
});
|
| 90 |
+
}
|
| 91 |
+
};
|
| 92 |
+
|
| 93 |
+
module.exports = {
|
| 94 |
+
name: 'Twitter DL',
|
| 95 |
+
description: 'Download Twitter/X Video and Images',
|
| 96 |
+
type: 'GET',
|
| 97 |
+
routes: ['api/download/twitter'],
|
| 98 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 99 |
+
parameters: ['url', 'key'],
|
| 100 |
+
enabled: true,
|
| 101 |
+
main: ['Downloader'],
|
| 102 |
+
handler
|
| 103 |
+
};
|
plugins/twitters.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const axios = require('axios');
|
| 2 |
+
|
| 3 |
+
async function twitterStalk(username) {
|
| 4 |
+
try {
|
| 5 |
+
const profileResponse = await axios.get(
|
| 6 |
+
`https://www.archivlyx.com/api/x/user?username=${username}`,
|
| 7 |
+
{
|
| 8 |
+
headers: {
|
| 9 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
| 10 |
+
'Accept': 'application/json'
|
| 11 |
+
}
|
| 12 |
+
}
|
| 13 |
+
);
|
| 14 |
+
|
| 15 |
+
if (!profileResponse.data.success) {
|
| 16 |
+
throw new Error('Failed to fetch profile data');
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
const profile = profileResponse.data.data;
|
| 20 |
+
|
| 21 |
+
const tweetsResponse = await axios.get(
|
| 22 |
+
`https://www.archivlyx.com/api/x/user-tweets?user=${profile.restId}&cursor=`,
|
| 23 |
+
{
|
| 24 |
+
headers: {
|
| 25 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
| 26 |
+
'Accept': 'application/json'
|
| 27 |
+
}
|
| 28 |
+
}
|
| 29 |
+
);
|
| 30 |
+
|
| 31 |
+
if (!tweetsResponse.data.success) {
|
| 32 |
+
throw new Error('Failed to fetch tweets data');
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
const tweetsData = tweetsResponse.data.data;
|
| 36 |
+
|
| 37 |
+
return {
|
| 38 |
+
profile: {
|
| 39 |
+
display_name: profile.displayName,
|
| 40 |
+
handle: profile.handle,
|
| 41 |
+
bio: profile.bio,
|
| 42 |
+
avatar: profile.avatar,
|
| 43 |
+
banner: profile.banner || null,
|
| 44 |
+
is_verified: profile.isVerified,
|
| 45 |
+
is_protected: profile.protected,
|
| 46 |
+
rest_id: profile.restId,
|
| 47 |
+
stats: {
|
| 48 |
+
tweets: profile.tweetsCount,
|
| 49 |
+
followers: profile.followersCount,
|
| 50 |
+
following: profile.followingCount
|
| 51 |
+
},
|
| 52 |
+
website: profile.website || null,
|
| 53 |
+
location: profile.location || null,
|
| 54 |
+
join_date: profile.joinDate
|
| 55 |
+
},
|
| 56 |
+
tweets: tweetsData.tweets.map(tweet => ({
|
| 57 |
+
id: tweet.id,
|
| 58 |
+
text: tweet.text,
|
| 59 |
+
created_at: tweet.createdAt,
|
| 60 |
+
author: {
|
| 61 |
+
id: tweet.author.id,
|
| 62 |
+
display_name: tweet.author.displayName,
|
| 63 |
+
handle: tweet.author.handle,
|
| 64 |
+
avatar: tweet.author.avatar,
|
| 65 |
+
banner: tweet.author.bannerProfile || null,
|
| 66 |
+
is_verified: tweet.author.isVerified
|
| 67 |
+
},
|
| 68 |
+
stats: {
|
| 69 |
+
likes: tweet.stats.likes,
|
| 70 |
+
retweets: tweet.stats.retweets,
|
| 71 |
+
replies: tweet.stats.replies,
|
| 72 |
+
quotes: tweet.stats.quotes,
|
| 73 |
+
views: tweet.stats.views,
|
| 74 |
+
bookmarks: tweet.stats.bookmarks
|
| 75 |
+
},
|
| 76 |
+
media: tweet.media.map(m => ({
|
| 77 |
+
type: m.type,
|
| 78 |
+
url: m.url,
|
| 79 |
+
media_key: m.mediaKey,
|
| 80 |
+
video_url: m.videoUrl || null
|
| 81 |
+
})),
|
| 82 |
+
is_quote: tweet.isQuote,
|
| 83 |
+
is_retweet: tweet.isRetweet,
|
| 84 |
+
quoted_tweet: tweet.quotedTweet,
|
| 85 |
+
retweeted_tweet: tweet.retweetedTweet
|
| 86 |
+
})),
|
| 87 |
+
pagination: {
|
| 88 |
+
next_cursor: tweetsData.pagination.nextCursor,
|
| 89 |
+
prev_cursor: tweetsData.pagination.prevCursor,
|
| 90 |
+
has_more: tweetsData.pagination.hasMore
|
| 91 |
+
}
|
| 92 |
+
};
|
| 93 |
+
} catch (error) {
|
| 94 |
+
if (error.response) {
|
| 95 |
+
throw new Error(`API Error: ${error.response.status} - ${error.response.statusText}`);
|
| 96 |
+
}
|
| 97 |
+
throw new Error(`Failed to fetch Twitter data: ${error.message}`);
|
| 98 |
+
}
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
const handler = async (req, res) => {
|
| 102 |
+
try {
|
| 103 |
+
const { username } = req.query;
|
| 104 |
+
|
| 105 |
+
if (!username) {
|
| 106 |
+
return res.status(400).json({
|
| 107 |
+
success: false,
|
| 108 |
+
error: 'Missing required parameter: username'
|
| 109 |
+
});
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
const usernameRegex = /^[a-zA-Z0-9_]{1,15}$/;
|
| 113 |
+
if (!usernameRegex.test(username)) {
|
| 114 |
+
return res.status(400).json({
|
| 115 |
+
success: false,
|
| 116 |
+
error: 'Invalid username format'
|
| 117 |
+
});
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
const result = await twitterStalk(username);
|
| 121 |
+
|
| 122 |
+
res.json({
|
| 123 |
+
author: "Herza",
|
| 124 |
+
success: true,
|
| 125 |
+
data: result
|
| 126 |
+
});
|
| 127 |
+
|
| 128 |
+
} catch (error) {
|
| 129 |
+
res.status(500).json({
|
| 130 |
+
author: "Herza",
|
| 131 |
+
success: false,
|
| 132 |
+
error: error.message
|
| 133 |
+
});
|
| 134 |
+
}
|
| 135 |
+
};
|
| 136 |
+
|
| 137 |
+
module.exports = {
|
| 138 |
+
name: 'Twitter Stalk',
|
| 139 |
+
description: 'Get Twitter/X user profile information including stats, bio, and recent tweets',
|
| 140 |
+
type: 'GET',
|
| 141 |
+
routes: ['api/stalk/twitter'],
|
| 142 |
+
tags: ['social', 'twitter', 'x', 'stalk', 'profile'],
|
| 143 |
+
parameters: ['username', 'key'],
|
| 144 |
+
enabled: true,
|
| 145 |
+
main: ['Stalk'],
|
| 146 |
+
handler
|
| 147 |
+
};
|
plugins/xbox.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { sxbox } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { text } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!text) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: text'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await sxbox(text);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
data: result.data
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'Xbox Stalk',
|
| 31 |
+
description: 'Stalk someone Xbox account with username',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/stalk/xbox'],
|
| 34 |
+
tags: ['stalk', 'tools', 'misc'],
|
| 35 |
+
parameters: ['text', 'key'],
|
| 36 |
+
enabled: true,
|
| 37 |
+
main: ['Stalk'],
|
| 38 |
+
handler
|
| 39 |
+
}
|
plugins/ytdl.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { youtube } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { url, type, quality } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!url) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
author: "Herza",
|
| 10 |
+
success: false,
|
| 11 |
+
error: 'Missing required parameter: url'
|
| 12 |
+
});
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
if (!type) {
|
| 16 |
+
return res.status(400).json({
|
| 17 |
+
author: "Herza",
|
| 18 |
+
success: false,
|
| 19 |
+
error: 'Missing required parameter: type'
|
| 20 |
+
});
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
const validTypes = ['mp3', 'mp4'];
|
| 24 |
+
if (!validTypes.includes(type.toLowerCase())) {
|
| 25 |
+
return res.status(400).json({
|
| 26 |
+
author: "Herza",
|
| 27 |
+
success: false,
|
| 28 |
+
error: `${type} is not available, only mp3 and mp4`
|
| 29 |
+
});
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
if (type.toLowerCase() === 'mp4') {
|
| 33 |
+
const validQualities = ['144', '240', '360', '480', '720', '1080'];
|
| 34 |
+
|
| 35 |
+
if (!quality) {
|
| 36 |
+
return res.status(400).json({
|
| 37 |
+
author: "Herza",
|
| 38 |
+
success: false,
|
| 39 |
+
error: 'Missing required parameter: quality',
|
| 40 |
+
formats: ['144', '240', '360', '480', '720', '1080']
|
| 41 |
+
});
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
if (!validQualities.includes(quality)) {
|
| 45 |
+
return res.status(400).json({
|
| 46 |
+
author: "Herza",
|
| 47 |
+
success: false,
|
| 48 |
+
error: `Quality ${quality} is not available`,
|
| 49 |
+
formats: ['144', '240', '360', '480', '720', '1080']
|
| 50 |
+
});
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
const result = await youtube(`yt${type.toLowerCase()}`, url, quality);
|
| 54 |
+
|
| 55 |
+
if (result.status !== 200) {
|
| 56 |
+
return res.status(result.status).json({
|
| 57 |
+
author: "Herza",
|
| 58 |
+
success: false,
|
| 59 |
+
error: result.data.message || 'Failed to download video'
|
| 60 |
+
});
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
return res.json({
|
| 64 |
+
author: "Herza",
|
| 65 |
+
success: true,
|
| 66 |
+
data: result.data
|
| 67 |
+
});
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
const result = await youtube(`yt${type.toLowerCase()}`, url);
|
| 71 |
+
|
| 72 |
+
if (result.status !== 200) {
|
| 73 |
+
return res.status(result.status).json({
|
| 74 |
+
author: "Herza",
|
| 75 |
+
success: false,
|
| 76 |
+
error: result.data.message || 'Failed to download audio'
|
| 77 |
+
});
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
res.json({
|
| 81 |
+
author: "Herza",
|
| 82 |
+
success: true,
|
| 83 |
+
data: result.data
|
| 84 |
+
});
|
| 85 |
+
|
| 86 |
+
} catch (error) {
|
| 87 |
+
res.status(500).json({
|
| 88 |
+
author: "Herza",
|
| 89 |
+
success: false,
|
| 90 |
+
error: error.message
|
| 91 |
+
});
|
| 92 |
+
}
|
| 93 |
+
};
|
| 94 |
+
|
| 95 |
+
module.exports = {
|
| 96 |
+
name: 'YouTube DL',
|
| 97 |
+
description: 'Download YouTube Video/Audio',
|
| 98 |
+
type: 'GET',
|
| 99 |
+
routes: ['api/download/youtube'],
|
| 100 |
+
tags: ['downloader', 'tools', 'misc'],
|
| 101 |
+
parameters: ['url', 'type', 'quality', 'key'],
|
| 102 |
+
enabled: true,
|
| 103 |
+
main: ['Downloader'],
|
| 104 |
+
handler
|
| 105 |
+
};
|
plugins/ytstalk.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { ytstalk } = require('notmebotz-tools');
|
| 2 |
+
|
| 3 |
+
const handler = async (req, res) => {
|
| 4 |
+
try {
|
| 5 |
+
const { text } = req.query;
|
| 6 |
+
|
| 7 |
+
if (!text) {
|
| 8 |
+
return res.status(400).json({
|
| 9 |
+
success: false,
|
| 10 |
+
error: 'Missing required parameter: text'
|
| 11 |
+
});
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const result = await ytstalk(text);
|
| 15 |
+
res.json({
|
| 16 |
+
author: "Herza",
|
| 17 |
+
success: true,
|
| 18 |
+
data: result.data
|
| 19 |
+
});
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
res.status(500).json({
|
| 23 |
+
success: false,
|
| 24 |
+
error: error.message
|
| 25 |
+
});
|
| 26 |
+
}
|
| 27 |
+
};
|
| 28 |
+
|
| 29 |
+
module.exports = {
|
| 30 |
+
name: 'YouTube Stalk',
|
| 31 |
+
description: 'Stalk someone YouTube account with username',
|
| 32 |
+
type: 'GET',
|
| 33 |
+
routes: ['api/stalk/youtube'],
|
| 34 |
+
tags: ['stalk', 'tools', 'misc'],
|
| 35 |
+
parameters: ['text', 'key'],
|
| 36 |
+
enabled: true,
|
| 37 |
+
main: ['Stalk'],
|
| 38 |
+
handler
|
| 39 |
+
}
|