HerzaJ commited on
Commit
7c363b0
·
verified ·
1 Parent(s): b4af9ba

Upload 56 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
plugins/aimodel.js ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const { v4: uuidv4 } = require('uuid');
3
+
4
+ const models = {
5
+ 'gpt-4o-mini': '25865',
6
+ 'gpt-5-nano': '25871',
7
+ 'gemini': '25874',
8
+ 'deepseek': '25873',
9
+ 'claude': '25875',
10
+ 'grok': '25872',
11
+ 'meta-ai': '25870',
12
+ 'qwen': '25869'
13
+ };
14
+
15
+ async function aichat(question, model) {
16
+ let { data: html } = await axios.get(`https://px.nekolabs.my.id/${encodeURIComponent('https://chatgptfree.ai/')}`);
17
+
18
+ let nonce = html.data.content.match(/"nonce"\s*:\s*"([^&]+)"/);
19
+ if (!nonce) throw new Error('Nonce not found.');
20
+
21
+ let { data } = await axios.post(`https://px.nekolabs.my.id/${encodeURIComponent('https://chatgptfree.ai/wp-admin/admin-ajax.php')}`, new URLSearchParams({
22
+ action: 'aipkit_frontend_chat_message',
23
+ _ajax_nonce: nonce[1],
24
+ bot_id: models[model],
25
+ session_id: uuidv4(),
26
+ conversation_uuid: uuidv4(),
27
+ post_id: '6',
28
+ message: question
29
+ }).toString(), {
30
+ headers: {
31
+ 'Content-Type': 'application/x-www-form-urlencoded',
32
+ 'Origin': 'https://chatgptfree.ai',
33
+ 'Referer': 'https://chatgptfree.ai/',
34
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 15; SM-F958 Build/AP3A.240905.015) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.86 Mobile Safari/537.36'
35
+ }
36
+ });
37
+
38
+ return data.data.content.data.reply;
39
+ }
40
+
41
+ const handler = async (req, res) => {
42
+ try {
43
+ const { text, model } = req.query;
44
+
45
+ if (!text) {
46
+ return res.status(400).json({
47
+ author: 'Herza',
48
+ success: false,
49
+ msg: 'Missing required parameter: text'
50
+ });
51
+ }
52
+
53
+ if (!model || !models[model]) {
54
+ return res.status(400).json({
55
+ author: 'Herza',
56
+ success: false,
57
+ msg: 'Invalid or missing model parameter',
58
+ available_models: Object.keys(models)
59
+ });
60
+ }
61
+
62
+ const result = await aichat(text, model);
63
+
64
+ res.json({
65
+ author: 'Herza',
66
+ success: true,
67
+ model: model,
68
+ msg: result.trim()
69
+ });
70
+
71
+ } catch (error) {
72
+ console.error('Error fetching from AI:', error);
73
+ res.status(500).json({
74
+ author: 'Herza',
75
+ success: false,
76
+ msg: error.message || 'Terjadi kesalahan saat menghubungi AI.'
77
+ });
78
+ }
79
+ };
80
+
81
+ module.exports = {
82
+ name: 'Model AI Chat',
83
+ description: 'Generate responses using multiple AI models, availabe models is Claude, gpt-4o-mini, gpt-5-nano, gemini, deepseek, grok, meta-ai, qwen',
84
+ type: 'GET',
85
+ routes: ['api/AI/chat'],
86
+ tags: ['ai', 'gpt', 'gemini', 'claude', 'deepseek'],
87
+ parameters: ['text', 'model', 'key'],
88
+ enabled: true,
89
+ main: ['AI'],
90
+ handler
91
+ };
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/cloudflare-bypass.js ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+
3
+ const handler = async (req, res) => {
4
+ try {
5
+ const { site_url, site_key, key } = req.query;
6
+
7
+ if (!site_url || !site_key || !key) {
8
+ return res.status(400).json({
9
+ author: 'Herza',
10
+ success: false,
11
+ error: 'Missing required parameters: site_url, site_key, or key'
12
+ });
13
+ }
14
+
15
+ const solverUrl = `https://herzaj-turnstile-solver.hf.space/turnstile?url=${encodeURIComponent(site_url)}&sitekey=${encodeURIComponent(site_key)}`;
16
+
17
+ const firstResponse = await axios.get(solverUrl, {
18
+ timeout: 30000
19
+ });
20
+
21
+ const taskId = firstResponse.data?.task_id;
22
+ if (!taskId) {
23
+ return res.status(400).json({
24
+ author: 'Herza',
25
+ success: false,
26
+ error: 'Failed to obtain task_id from solver service'
27
+ });
28
+ }
29
+
30
+ await new Promise(resolve => setTimeout(resolve, 8000));
31
+
32
+ const resultUrl = `https://herzaj-turnstile-solver.hf.space/result?id=${encodeURIComponent(taskId)}`;
33
+
34
+ const secondResponse = await axios.get(resultUrl, {
35
+ timeout: 30000
36
+ });
37
+
38
+ const { elapsed_time, value } = secondResponse.data;
39
+
40
+ if (!value) {
41
+ return res.status(400).json({
42
+ author: 'Herza',
43
+ success: false,
44
+ error: 'Failed to retrieve token value from solver service'
45
+ });
46
+ }
47
+
48
+ return res.json({
49
+ author: 'Herza',
50
+ success: true,
51
+ data: {
52
+ elapsed_time,
53
+ value,
54
+ site_url,
55
+ site_key
56
+ }
57
+ });
58
+
59
+ } catch (error) {
60
+ return res.status(500).json({
61
+ author: 'Herza',
62
+ success: false,
63
+ error: error.message
64
+ });
65
+ }
66
+ };
67
+
68
+ module.exports = {
69
+ name: 'Cloudflare Turnstile Bypass',
70
+ description: 'Generate Cloudflare Turnstile tokens with custom site URL and site key',
71
+ type: 'GET',
72
+ routes: ['api/tools/bypasscf'],
73
+ tags: ['utility', 'turnstile', 'solver'],
74
+ parameters: ['site_url', 'site_key', 'key'],
75
+ enabled: true,
76
+ main: ['tools'],
77
+ limit: 8,
78
+ handler
79
+ };
plugins/copilot-think.js ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const WebSocket = require('ws')
2
+ const axios = require('axios')
3
+
4
+ class CopilotThink {
5
+ constructor() {
6
+ this.conversationId = null
7
+ this.headers = {
8
+ origin: 'https://copilot.microsoft.com',
9
+ 'user-agent': 'Mozilla/5.0 (Linux; Android 15; SM-F958 Build/AP3A.240905.015) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.86 Mobile Safari/537.36'
10
+ }
11
+ }
12
+
13
+ async createConversation() {
14
+ let { data } = await axios.post('https://copilot.microsoft.com/c/api/conversations', null, { headers: this.headers })
15
+ this.conversationId = data.id
16
+ return this.conversationId
17
+ }
18
+
19
+ async chat(message) {
20
+ if (!this.conversationId) await this.createConversation()
21
+ return new Promise((resolve, reject) => {
22
+ const ws = new WebSocket(`wss://copilot.microsoft.com/c/api/chat?api-version=2&features=-,ncedge,edgepagecontext&setflight=-,ncedge,edgepagecontext&ncedge=1`, { headers: this.headers })
23
+ const response = { text: '', citations: [] }
24
+ ws.on('open', () => {
25
+ ws.send(JSON.stringify({
26
+ event: 'setOptions',
27
+ supportedFeatures: ['partial-generated-images'],
28
+ supportedCards: ['weather', 'local', 'image', 'sports', 'video', 'ads', 'safetyHelpline', 'quiz', 'finance', 'recipe'],
29
+ ads: { supportedTypes: ['text', 'product', 'multimedia', 'tourActivity', 'propertyPromotion'] }
30
+ }))
31
+ ws.send(JSON.stringify({
32
+ event: 'send',
33
+ mode: 'reasoning',
34
+ conversationId: this.conversationId,
35
+ content: [{ type: 'text', text: message }],
36
+ context: {}
37
+ }))
38
+ })
39
+ ws.on('message', (chunk) => {
40
+ try {
41
+ const parsed = JSON.parse(chunk.toString())
42
+ switch (parsed.event) {
43
+ case 'appendText':
44
+ response.text += parsed.text || ''
45
+ break
46
+ case 'citation':
47
+ response.citations.push({ title: parsed.title, icon: parsed.iconUrl, url: parsed.url })
48
+ break
49
+ case 'done':
50
+ resolve(response)
51
+ ws.close()
52
+ break
53
+ case 'error':
54
+ reject(new Error(parsed.message))
55
+ ws.close()
56
+ break
57
+ }
58
+ } catch (error) {
59
+ reject(error.message)
60
+ }
61
+ })
62
+ ws.on('error', reject)
63
+ })
64
+ }
65
+ }
66
+
67
+ const handler = async (req, res) => {
68
+ try {
69
+ const { text } = req.query
70
+
71
+ if (!text) {
72
+ return res.status(400).json({
73
+ author: 'Herza',
74
+ success: false,
75
+ msg: 'Missing required parameter: text'
76
+ })
77
+ }
78
+
79
+ const copilot = new CopilotThink()
80
+ const result = await copilot.chat(text)
81
+
82
+ res.json({
83
+ author: 'Herza',
84
+ success: true,
85
+ model: 'copilot-think',
86
+ msg: result.text.trim(),
87
+ citations: result.citations
88
+ })
89
+
90
+ } catch (error) {
91
+ console.error('Error fetching from Copilot Think:', error)
92
+ res.status(500).json({
93
+ author: 'Herza',
94
+ success: false,
95
+ msg: 'Terjadi kesalahan saat menghubungi AI.'
96
+ })
97
+ }
98
+ }
99
+
100
+ module.exports = {
101
+ name: 'Copilot Think AI',
102
+ description: 'Generate responses using Microsoft Copilot with Reasoning/Think Deeper',
103
+ type: 'GET',
104
+ routes: ['api/AI/copilot-think'],
105
+ tags: ['ai', 'copilot', 'reasoning', 'think-deeper'],
106
+ parameters: ['text'],
107
+ enabled: true,
108
+ main: ['AI'],
109
+ handler
110
+ }
plugins/copilot.js ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const WebSocket = require('ws')
2
+ const axios = require('axios')
3
+
4
+ class Copilot {
5
+ constructor() {
6
+ this.conversationId = null
7
+ this.headers = {
8
+ origin: 'https://copilot.microsoft.com',
9
+ 'user-agent': 'Mozilla/5.0 (Linux; Android 15; SM-F958 Build/AP3A.240905.015) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.86 Mobile Safari/537.36'
10
+ }
11
+ }
12
+
13
+ async createConversation() {
14
+ let { data } = await axios.post('https://copilot.microsoft.com/c/api/conversations', null, { headers: this.headers })
15
+ this.conversationId = data.id
16
+ return this.conversationId
17
+ }
18
+
19
+ async chat(message) {
20
+ if (!this.conversationId) await this.createConversation()
21
+ return new Promise((resolve, reject) => {
22
+ const ws = new WebSocket(`wss://copilot.microsoft.com/c/api/chat?api-version=2&features=-,ncedge,edgepagecontext&setflight=-,ncedge,edgepagecontext&ncedge=1`, { headers: this.headers })
23
+ const response = { text: '', citations: [] }
24
+ ws.on('open', () => {
25
+ ws.send(JSON.stringify({
26
+ event: 'setOptions',
27
+ supportedFeatures: ['partial-generated-images'],
28
+ supportedCards: ['weather', 'local', 'image', 'sports', 'video', 'ads', 'safetyHelpline', 'quiz', 'finance', 'recipe'],
29
+ ads: { supportedTypes: ['text', 'product', 'multimedia', 'tourActivity', 'propertyPromotion'] }
30
+ }))
31
+ ws.send(JSON.stringify({
32
+ event: 'send',
33
+ mode: 'chat',
34
+ conversationId: this.conversationId,
35
+ content: [{ type: 'text', text: message }],
36
+ context: {}
37
+ }))
38
+ })
39
+ ws.on('message', (chunk) => {
40
+ try {
41
+ const parsed = JSON.parse(chunk.toString())
42
+ switch (parsed.event) {
43
+ case 'appendText':
44
+ response.text += parsed.text || ''
45
+ break
46
+ case 'citation':
47
+ response.citations.push({ title: parsed.title, icon: parsed.iconUrl, url: parsed.url })
48
+ break
49
+ case 'done':
50
+ resolve(response)
51
+ ws.close()
52
+ break
53
+ case 'error':
54
+ reject(new Error(parsed.message))
55
+ ws.close()
56
+ break
57
+ }
58
+ } catch (error) {
59
+ reject(error.message)
60
+ }
61
+ })
62
+ ws.on('error', reject)
63
+ })
64
+ }
65
+ }
66
+
67
+ const handler = async (req, res) => {
68
+ try {
69
+ const { text } = req.query
70
+
71
+ if (!text) {
72
+ return res.status(400).json({
73
+ author: 'Herza',
74
+ success: false,
75
+ msg: 'Missing required parameter: text'
76
+ })
77
+ }
78
+
79
+ const copilot = new Copilot()
80
+ const result = await copilot.chat(text)
81
+
82
+ res.json({
83
+ author: 'Herza',
84
+ success: true,
85
+ model: 'copilot',
86
+ msg: result.text.trim(),
87
+ citations: result.citations
88
+ })
89
+
90
+ } catch (error) {
91
+ console.error('Error fetching from Copilot:', error)
92
+ res.status(500).json({
93
+ author: 'Herza',
94
+ success: false,
95
+ msg: 'Terjadi kesalahan saat menghubungi AI.'
96
+ })
97
+ }
98
+ }
99
+
100
+ module.exports = {
101
+ name: 'Copilot AI',
102
+ description: 'Generate responses using Microsoft Copilot',
103
+ type: 'GET',
104
+ routes: ['api/AI/copilot'],
105
+ tags: ['ai', 'copilot'],
106
+ parameters: ['text'],
107
+ enabled: true,
108
+ main: ['AI'],
109
+ handler
110
+ }
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/faceswap.js ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const upload = require('../lib/uploadImage');
3
+
4
+ async function faceSwap(img_url1, img_url2) {
5
+ try {
6
+ const response1 = await axios.get(img_url1, { responseType: 'arraybuffer' });
7
+ const base64_1 = Buffer.from(response1.data).toString('base64');
8
+
9
+ const response2 = await axios.get(img_url2, { responseType: 'arraybuffer' });
10
+ const base64_2 = Buffer.from(response2.data).toString('base64');
11
+
12
+ const swapResponse = await axios.post('https://api.faceswapper.ai/swap', {
13
+ target: base64_1,
14
+ source: base64_2,
15
+ type: 'invisible',
16
+ id: 'faceswapper'
17
+ }, {
18
+ headers: {
19
+ 'Accept': 'application/json, text/plain, */*',
20
+ 'Content-Type': 'application/json',
21
+ 'type': 'rapid'
22
+ }
23
+ });
24
+
25
+ const base64Data = swapResponse.data.result.replace(/^data:image\/\w+;base64,/, '');
26
+ const buffer = Buffer.from(base64Data, 'base64');
27
+
28
+ const imageUrl = await upload(buffer);
29
+
30
+ return {
31
+ success: true,
32
+ elapsedTime: swapResponse.data.elapsedTime,
33
+ result: swapResponse.data.result,
34
+ url: imageUrl
35
+ };
36
+
37
+ } catch (error) {
38
+ throw error;
39
+ }
40
+ }
41
+
42
+ const handler = async (req, res) => {
43
+ try {
44
+ const { img, img2, key } = req.query;
45
+
46
+ if (!img) {
47
+ return res.status(400).json({
48
+ success: false,
49
+ error: 'Missing required parameter: img'
50
+ });
51
+ }
52
+
53
+ if (!img2) {
54
+ return res.status(400).json({
55
+ success: false,
56
+ error: 'Missing required parameter: img2'
57
+ });
58
+ }
59
+
60
+ if (!key) {
61
+ return res.status(400).json({
62
+ success: false,
63
+ error: 'Missing required parameter: key'
64
+ });
65
+ }
66
+
67
+ const result = await faceSwap(img, img2);
68
+
69
+ return res.json({
70
+ author: "Herza",
71
+ success: true,
72
+ data: {
73
+ elapsedTime: result.elapsedTime,
74
+ result: result.result,
75
+ url: result.url
76
+ }
77
+ });
78
+
79
+ } catch (error) {
80
+ res.status(500).json({
81
+ success: false,
82
+ error: error.message,
83
+ timestamp: new Date().toISOString()
84
+ });
85
+ }
86
+ };
87
+
88
+ module.exports = {
89
+ name: 'Face Swap',
90
+ description: 'Swap faces between two images using AI',
91
+ type: 'GET',
92
+ routes: ['api/AI/faceswap'],
93
+ tags: ['AI', 'tools'],
94
+ parameters: ['img', 'img2', 'key'],
95
+ limit: 3,
96
+ enabled: true,
97
+ main: ['AI', 'tools'],
98
+ handler
99
+ };
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(/&amp;/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/flixer.js ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const puppeteer = require('puppeteer');
2
+
3
+ const scrapeFlixer = async (searchQuery) => {
4
+ const browser = await puppeteer.launch({
5
+ headless: true,
6
+ args: [
7
+ '--no-sandbox',
8
+ '--disable-setuid-sandbox',
9
+ '--disable-dev-shm-usage',
10
+ '--disable-gpu'
11
+ ]
12
+ });
13
+
14
+ const page = await browser.newPage();
15
+
16
+ await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
17
+
18
+ const searchUrl = `https://flixer.sh/search?q=${encodeURIComponent(searchQuery)}`;
19
+ await page.goto(searchUrl, { waitUntil: 'networkidle0', timeout: 30000 });
20
+
21
+ await new Promise(resolve => setTimeout(resolve, 2000));
22
+
23
+ const searchResults = await page.evaluate(() => {
24
+ const results = [];
25
+ const images = document.querySelectorAll('img[alt]');
26
+
27
+ images.forEach(img => {
28
+ const link = img.closest('a');
29
+ if (link && img.alt) {
30
+ results.push({
31
+ title: img.alt,
32
+ image: img.src,
33
+ url: link.href
34
+ });
35
+ }
36
+ });
37
+
38
+ return results;
39
+ });
40
+
41
+ if (searchResults.length === 0) {
42
+ await browser.close();
43
+ throw new Error('No results found');
44
+ }
45
+
46
+ const movieUrl = searchResults[0].url;
47
+ await page.goto(movieUrl, { waitUntil: 'networkidle0', timeout: 30000 });
48
+
49
+ await new Promise(resolve => setTimeout(resolve, 3000));
50
+
51
+ const servers = await page.evaluate(() => {
52
+ const serverList = [];
53
+ const buttons = document.querySelectorAll('button');
54
+
55
+ buttons.forEach(btn => {
56
+ const nameEl = btn.querySelector('.font-medium');
57
+ const statusEl = btn.querySelector('.text-green-400');
58
+
59
+ if (nameEl && statusEl && statusEl.textContent.includes('AVAILABLE')) {
60
+ serverList.push({
61
+ name: nameEl.textContent.trim(),
62
+ available: true
63
+ });
64
+ }
65
+ });
66
+
67
+ return serverList;
68
+ });
69
+
70
+ let videoUrl = null;
71
+
72
+ page.on('response', async response => {
73
+ const url = response.url();
74
+ if (url.includes('.m3u8') || url.includes('.mp4') || url.includes('stream')) {
75
+ videoUrl = url;
76
+ }
77
+ });
78
+
79
+ for (const server of servers) {
80
+ try {
81
+ await page.evaluate((serverName) => {
82
+ const buttons = Array.from(document.querySelectorAll('button'));
83
+ const btn = buttons.find(b => {
84
+ const nameEl = b.querySelector('.font-medium');
85
+ return nameEl && nameEl.textContent.trim() === serverName;
86
+ });
87
+ if (btn) btn.click();
88
+ }, server.name);
89
+
90
+ await new Promise(resolve => setTimeout(resolve, 5000));
91
+
92
+ const currentVideoUrl = await page.evaluate(() => {
93
+ const video = document.querySelector('video');
94
+ return video ? video.src : null;
95
+ });
96
+
97
+ if (currentVideoUrl && !currentVideoUrl.startsWith('blob:')) {
98
+ videoUrl = currentVideoUrl;
99
+ break;
100
+ }
101
+
102
+ if (videoUrl && !videoUrl.startsWith('blob:')) {
103
+ break;
104
+ }
105
+ } catch (e) {
106
+ continue;
107
+ }
108
+ }
109
+
110
+ await browser.close();
111
+
112
+ return {
113
+ title: searchResults[0].title,
114
+ image: searchResults[0].image,
115
+ movieUrl: movieUrl,
116
+ servers: servers,
117
+ videoUrl: videoUrl,
118
+ allResults: searchResults
119
+ };
120
+ };
121
+
122
+ const handler = async (req, res) => {
123
+ try {
124
+ const { q } = req.query;
125
+
126
+ if (!q) {
127
+ return res.status(400).json({
128
+ success: false,
129
+ error: 'Missing required parameter: q'
130
+ });
131
+ }
132
+
133
+ const result = await scrapeFlixer(q);
134
+ res.json({
135
+ author: "Herza",
136
+ success: true,
137
+ msg: result
138
+ });
139
+
140
+ } catch (error) {
141
+ res.status(500).json({
142
+ success: false,
143
+ error: error.message
144
+ });
145
+ }
146
+ };
147
+
148
+ module.exports = {
149
+ name: 'Flixer Search',
150
+ description: 'Search and get video from Flixer',
151
+ type: 'GET',
152
+ routes: ['api/search/flixer'],
153
+ tags: ['search', 'movie', 'tools'],
154
+ parameters: ['q', 'key'],
155
+ enabled: true,
156
+ main: ['Downloader', 'Search'],
157
+ handler
158
+ };
plugins/flux.js ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ async function fluxImage(prompt, width = 1024, height = 1024, server = "Azure Lite Supercomputer Server") {
6
+ try {
7
+ const { data: init } = await axios.post(
8
+ "https://nihalgazi-flux-unlimited.hf.space/gradio_api/call/generate_image",
9
+ { data: [prompt, width, height, 3, true, server] },
10
+ {
11
+ headers: {
12
+ "Content-Type": "application/json",
13
+ Origin: "https://chrunos.com",
14
+ Referer: "https://chrunos.com/",
15
+ },
16
+ }
17
+ );
18
+
19
+ const eventId = init.event_id;
20
+ if (!eventId) throw new Error("Failed to obtain event_id.");
21
+
22
+ const streamUrl = `https://nihalgazi-flux-unlimited.hf.space/gradio_api/call/generate_image/${eventId}`;
23
+ let imageUrl = null;
24
+
25
+ for (let i = 0; i < 15; i++) {
26
+ const { data } = await axios.get(streamUrl, {
27
+ headers: { Accept: "text/event-stream" },
28
+ });
29
+
30
+ const match = data.match(/"url":\s*"([^"]+)"/);
31
+ if (match) {
32
+ imageUrl = match[1];
33
+ break;
34
+ }
35
+
36
+ await new Promise(r => setTimeout(r, 2000));
37
+ }
38
+
39
+ if (!imageUrl) throw new Error("Failed to retrieve image URL from stream.");
40
+ return imageUrl;
41
+ } catch (err) {
42
+ throw new Error(`fluxImage error: ${err.message}`);
43
+ }
44
+ }
45
+
46
+ async function downloadAndSaveImage(imageUrl, fileId) {
47
+ const tmpDir = path.join(process.cwd(), 'tmp');
48
+
49
+ if (!fs.existsSync(tmpDir)) {
50
+ fs.mkdirSync(tmpDir, { recursive: true });
51
+ }
52
+
53
+ const filePath = path.join(tmpDir, `flux-${fileId}.webp`);
54
+
55
+ const response = await axios.get(imageUrl, {
56
+ responseType: 'arraybuffer',
57
+ timeout: 30000
58
+ });
59
+
60
+ fs.writeFileSync(filePath, Buffer.from(response.data));
61
+
62
+ setTimeout(() => {
63
+ if (fs.existsSync(filePath)) {
64
+ fs.unlinkSync(filePath);
65
+ }
66
+ }, 60000);
67
+
68
+ return `flux-${fileId}.webp`;
69
+ }
70
+
71
+ const handler = async (req, res) => {
72
+ try {
73
+ const { prompt, key, width, height, server } = req.query;
74
+
75
+ if (!prompt) {
76
+ return res.status(400).json({
77
+ author: "Herza",
78
+ success: false,
79
+ error: 'Missing required parameter: prompt'
80
+ });
81
+ }
82
+
83
+ if (!key) {
84
+ return res.status(400).json({
85
+ author: "Herza",
86
+ success: false,
87
+ error: 'Missing required parameter: key'
88
+ });
89
+ }
90
+
91
+ const imgWidth = width ? parseInt(width) : 1024;
92
+ const imgHeight = height ? parseInt(height) : 1024;
93
+ const selectedServer = server || "NSFW-Core: Uncensored Server 2";
94
+
95
+ const imageUrl = await fluxImage(prompt, imgWidth, imgHeight, selectedServer);
96
+
97
+ if (!imageUrl) {
98
+ return res.status(500).json({
99
+ author: "Herza",
100
+ success: false,
101
+ error: 'Failed to generate image'
102
+ });
103
+ }
104
+
105
+ const fileId = Date.now() + '_' + Math.random().toString(36).substring(7);
106
+ const filename = await downloadAndSaveImage(imageUrl, fileId);
107
+
108
+ const baseUrl = `${req.protocol}://${req.get('host')}`;
109
+ const localUrl = `${baseUrl}/tmp/${filename}`;
110
+
111
+ res.json({
112
+ author: "Herza",
113
+ success: true,
114
+ data: {
115
+ result: localUrl
116
+ }
117
+ });
118
+
119
+ } catch (error) {
120
+ res.status(500).json({
121
+ author: "Herza",
122
+ success: false,
123
+ error: error.message
124
+ });
125
+ }
126
+ };
127
+
128
+ module.exports = {
129
+ name: 'Flux Image Generator',
130
+ description: 'Generate images using Flux AI model',
131
+ type: 'GET',
132
+ routes: ['api/AI/Flux'],
133
+ tags: ['ai', 'image', 'flux', 'generator'],
134
+ main: ['AI'],
135
+ parameters: ['prompt', 'key', 'width', 'height', 'server'],
136
+ enabled: true,
137
+ handler
138
+ };
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/gpt-5.js ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const WebSocket = require('ws')
2
+ const axios = require('axios')
3
+
4
+ class GPT5 {
5
+ constructor() {
6
+ this.conversationId = null
7
+ this.headers = {
8
+ origin: 'https://copilot.microsoft.com',
9
+ 'user-agent': 'Mozilla/5.0 (Linux; Android 15; SM-F958 Build/AP3A.240905.015) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.86 Mobile Safari/537.36'
10
+ }
11
+ }
12
+
13
+ async createConversation() {
14
+ let { data } = await axios.post('https://copilot.microsoft.com/c/api/conversations', null, { headers: this.headers })
15
+ this.conversationId = data.id
16
+ return this.conversationId
17
+ }
18
+
19
+ async chat(message) {
20
+ if (!this.conversationId) await this.createConversation()
21
+ return new Promise((resolve, reject) => {
22
+ const ws = new WebSocket(`wss://copilot.microsoft.com/c/api/chat?api-version=2&features=-,ncedge,edgepagecontext&setflight=-,ncedge,edgepagecontext&ncedge=1`, { headers: this.headers })
23
+ const response = { text: '', citations: [] }
24
+ ws.on('open', () => {
25
+ ws.send(JSON.stringify({
26
+ event: 'setOptions',
27
+ supportedFeatures: ['partial-generated-images'],
28
+ supportedCards: ['weather', 'local', 'image', 'sports', 'video', 'ads', 'safetyHelpline', 'quiz', 'finance', 'recipe'],
29
+ ads: { supportedTypes: ['text', 'product', 'multimedia', 'tourActivity', 'propertyPromotion'] }
30
+ }))
31
+ ws.send(JSON.stringify({
32
+ event: 'send',
33
+ mode: 'smart',
34
+ conversationId: this.conversationId,
35
+ content: [{ type: 'text', text: message }],
36
+ context: {}
37
+ }))
38
+ })
39
+ ws.on('message', (chunk) => {
40
+ try {
41
+ const parsed = JSON.parse(chunk.toString())
42
+ switch (parsed.event) {
43
+ case 'appendText':
44
+ response.text += parsed.text || ''
45
+ break
46
+ case 'citation':
47
+ response.citations.push({ title: parsed.title, icon: parsed.iconUrl, url: parsed.url })
48
+ break
49
+ case 'done':
50
+ resolve(response)
51
+ ws.close()
52
+ break
53
+ case 'error':
54
+ reject(new Error(parsed.message))
55
+ ws.close()
56
+ break
57
+ }
58
+ } catch (error) {
59
+ reject(error.message)
60
+ }
61
+ })
62
+ ws.on('error', reject)
63
+ })
64
+ }
65
+ }
66
+
67
+ const handler = async (req, res) => {
68
+ try {
69
+ const { text } = req.query
70
+
71
+ if (!text) {
72
+ return res.status(400).json({
73
+ author: 'Herza',
74
+ success: false,
75
+ msg: 'Missing required parameter: text'
76
+ })
77
+ }
78
+
79
+ const gpt5 = new GPT5()
80
+ const result = await gpt5.chat(text)
81
+
82
+ res.json({
83
+ author: 'Herza',
84
+ success: true,
85
+ model: 'gpt-5',
86
+ msg: result.text.trim(),
87
+ citations: result.citations
88
+ })
89
+
90
+ } catch (error) {
91
+ console.error('Error fetching from GPT-5:', error)
92
+ res.status(500).json({
93
+ author: 'Herza',
94
+ success: false,
95
+ msg: 'Terjadi kesalahan saat menghubungi AI.'
96
+ })
97
+ }
98
+ }
99
+
100
+ module.exports = {
101
+ name: 'GPT-5 AI',
102
+ description: 'Generate responses using GPT-5 Smart Model via Copilot',
103
+ type: 'GET',
104
+ routes: ['api/AI/gpt-5'],
105
+ tags: ['ai', 'gpt-5', 'smart'],
106
+ parameters: ['text'],
107
+ enabled: true,
108
+ main: ['AI'],
109
+ handler
110
+ }
plugins/herxa ADDED
File without changes
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/img2pixel.js ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const fs = require('fs');
3
+ const os = require('os');
4
+ const path = require('path');
5
+
6
+ async function img2pixel(imgUrl) {
7
+ let tempFilePath = null;
8
+
9
+ try {
10
+ const response = await axios.get(imgUrl, {
11
+ responseType: 'arraybuffer',
12
+ timeout: 30000
13
+ });
14
+
15
+ const imageBuffer = Buffer.from(response.data);
16
+
17
+ const tempFileName = `img2pixel_${Date.now()}_${Math.random().toString(36).substring(7)}.jpg`;
18
+ tempFilePath = path.join(os.tmpdir(), tempFileName);
19
+ fs.writeFileSync(tempFilePath, imageBuffer);
20
+
21
+ const filename = imgUrl.split('/').pop().split('?')[0] || tempFileName;
22
+ const contentType = 'image/jpeg';
23
+
24
+ const presignedResponse = await axios.post(
25
+ 'https://pixelartgenerator.app/api/upload/presigned-url',
26
+ {
27
+ filename: filename,
28
+ contentType: contentType,
29
+ type: 'pixel-art-source'
30
+ },
31
+ {
32
+ headers: {
33
+ 'Content-Type': 'application/json'
34
+ }
35
+ }
36
+ );
37
+
38
+ const { uploadUrl, key, publicUrl } = presignedResponse.data.data;
39
+
40
+ await axios.put(uploadUrl, imageBuffer, {
41
+ headers: {
42
+ 'Content-Type': contentType
43
+ }
44
+ });
45
+
46
+ if (tempFilePath && fs.existsSync(tempFilePath)) {
47
+ fs.unlinkSync(tempFilePath);
48
+ tempFilePath = null;
49
+ }
50
+
51
+ const generateResponse = await axios.post(
52
+ 'https://pixelartgenerator.app/api/pixel/generate',
53
+ {
54
+ size: '1:1',
55
+ type: 'image',
56
+ imageKey: key,
57
+ prompt: ''
58
+ },
59
+ {
60
+ headers: {
61
+ 'Content-Type': 'application/json'
62
+ }
63
+ }
64
+ );
65
+
66
+ const { taskId } = generateResponse.data.data;
67
+
68
+ let attempts = 0;
69
+ const maxAttempts = 60;
70
+
71
+ while (attempts < maxAttempts) {
72
+ const statusResponse = await axios.get(
73
+ `https://pixelartgenerator.app/api/pixel/status?taskId=${taskId}`
74
+ );
75
+
76
+ const { status, progress, images, error } = statusResponse.data.data;
77
+
78
+ if (status === 'SUCCESS' && images.length > 0) {
79
+ return images[0];
80
+ }
81
+
82
+ if (error) {
83
+ throw new Error(`Generation failed: ${error}`);
84
+ }
85
+
86
+ attempts++;
87
+ await new Promise(resolve => setTimeout(resolve, 3000));
88
+ }
89
+
90
+ throw new Error('Timeout: Generation took too long');
91
+
92
+ } catch (error) {
93
+ if (tempFilePath && fs.existsSync(tempFilePath)) {
94
+ try {
95
+ fs.unlinkSync(tempFilePath);
96
+ } catch (cleanupError) {
97
+ console.error('Failed to cleanup temp file:', cleanupError);
98
+ }
99
+ }
100
+ throw new Error(`img2pixel error: ${error.message}`);
101
+ }
102
+ }
103
+
104
+ const handler = async (req, res) => {
105
+ try {
106
+ const { img, key } = req.query;
107
+
108
+ if (!img) {
109
+ return res.status(400).json({
110
+ author: "Herza",
111
+ success: false,
112
+ error: 'Missing required parameter: img (image URL)'
113
+ });
114
+ }
115
+
116
+ if (!key) {
117
+ return res.status(400).json({
118
+ author: "Herza",
119
+ success: false,
120
+ error: 'Missing required parameter: key'
121
+ });
122
+ }
123
+
124
+ try {
125
+ new URL(img);
126
+ } catch (e) {
127
+ return res.status(400).json({
128
+ author: "Herza",
129
+ success: false,
130
+ error: 'Invalid image URL format'
131
+ });
132
+ }
133
+
134
+ const result = await img2pixel(img);
135
+
136
+ res.json({
137
+ author: "Herza",
138
+ success: true,
139
+ data: {
140
+ result: result
141
+ }
142
+ });
143
+
144
+ } catch (error) {
145
+ res.status(500).json({
146
+ author: "Herza",
147
+ success: false,
148
+ error: error.message
149
+ });
150
+ }
151
+ };
152
+
153
+ module.exports = {
154
+ name: 'Image to Pixel Art',
155
+ description: 'Convert image to pixel art style',
156
+ type: 'GET',
157
+ routes: ['api/AI/img2pixel'],
158
+ tags: ['ai', 'image', 'pixel-art'],
159
+ main: ['AI'],
160
+ parameters: ['img', 'key'],
161
+ enabled: true,
162
+ handler
163
+ };
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/lyrics.js ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+
3
+ const handler = async (req, res) => {
4
+ try {
5
+ const { query } = req.query;
6
+
7
+ if (!query) {
8
+ return res.status(400).json({
9
+ success: false,
10
+ error: 'Missing required parameter: query'
11
+ });
12
+ }
13
+
14
+ let result = await axios.get(`https://lyrics.lewdhutao.my.eu.org/v2/youtube/lyrics?title=${encodeURIComponent(query)}`)
15
+ res.json({
16
+ author: "Herza",
17
+ success: true,
18
+ data: result.data.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: 'Lyrics Search',
31
+ description: 'Input song name and system will get the lyrics for you',
32
+ type: 'GET',
33
+ routes: ['api/search/lyrics'],
34
+ tags: ['Youtube', 'Genius Lyrics', 'Lyrics'],
35
+ main: ['Search'],
36
+ parameters: ['query', 'key'],
37
+ enabled: true,
38
+ limit: 5,
39
+ handler
40
+ };
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/mediafire.js ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const cheerio = require('cheerio');
2
+ const { basename, extname } = require('path');
3
+
4
+ async function mediafire(url) {
5
+ const $ = cheerio.load(await (await fetch(url.trim())).text())
6
+ const title = $("meta[property='og:title']").attr("content")?.trim() || "Unknown"
7
+ const size = /Download\s*\(([\d.]+\s*[KMGT]?B)\)/i.exec($.html())?.[1] || "Unknown"
8
+ const dl = $("a.popsok[href^='https://download']").attr("href")?.trim() || $("a.popsok:not([href^='javascript'])").attr("href")?.trim() || (() => { throw new Error("Download URL not found.") })()
9
+ return { name: title, filename: basename(dl), type: extname(dl), size, download: dl, link: url.trim() }
10
+ }
11
+
12
+ const handler = async (req, res) => {
13
+ try {
14
+ const { url } = req.query;
15
+
16
+ if (!url) {
17
+ return res.status(400).json({
18
+ success: false,
19
+ error: 'Missing required parameter: url'
20
+ });
21
+ }
22
+
23
+ const result = await mediafire(url);
24
+ res.json({
25
+ author: "Herza",
26
+ success: true,
27
+ data: result
28
+ });
29
+
30
+ } catch (error) {
31
+ res.status(500).json({
32
+ success: false,
33
+ error: error.message
34
+ });
35
+ }
36
+ };
37
+
38
+ module.exports = {
39
+ name: 'MediaFire DL',
40
+ description: 'Download File From Mediafire',
41
+ type: 'GET',
42
+ routes: ['api/download/mediafire'],
43
+ tags: ['downloader', 'tools', 'misc'],
44
+ parameters: ['url', 'key'],
45
+ enabled: true,
46
+ main: ['Downloader'],
47
+ handler
48
+ }
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/pinlens.js ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const FormData = require('form-data');
3
+ const crypto = require('crypto');
4
+ // SCRAPE BY SIPUTZX
5
+ class PinterestLensScraper {
6
+ constructor(authToken) {
7
+ this.authToken = authToken;
8
+ }
9
+
10
+ getRandomHeaders() {
11
+ const devices = [
12
+ { model: 'SM-G991B', manufacturer: 'samsung', name: 'Samsung Galaxy S21' },
13
+ { model: 'SM-A525F', manufacturer: 'samsung', name: 'Samsung Galaxy A52' },
14
+ { model: 'Pixel 6', manufacturer: 'Google', name: 'Google Pixel 6' },
15
+ { model: 'Pixel 7 Pro', manufacturer: 'Google', name: 'Google Pixel 7 Pro' },
16
+ { model: 'M2101K6G', manufacturer: 'Xiaomi', name: 'Xiaomi Redmi Note 10' },
17
+ { model: '2201117TG', manufacturer: 'Xiaomi', name: 'Xiaomi 11T' },
18
+ { model: 'CPH2121', manufacturer: 'OPPO', name: 'OPPO Reno5' },
19
+ { model: 'RMX3085', manufacturer: 'realme', name: 'realme 8 Pro' },
20
+ { model: 'itel S665L', manufacturer: 'ITEL', name: 'itel S665L' },
21
+ { model: 'TECNO KE5', manufacturer: 'TECNO', name: 'TECNO Spark 7' }
22
+ ];
23
+
24
+ const versions = ['13.36.2', '13.35.0', '13.34.1', '13.33.0', '13.32.1'];
25
+ const androidVersions = ['11', '12', '13'];
26
+
27
+ const device = devices[Math.floor(Math.random() * devices.length)];
28
+ const version = versions[Math.floor(Math.random() * versions.length)];
29
+ const androidVer = androidVersions[Math.floor(Math.random() * androidVersions.length)];
30
+ const advertisingId = crypto.randomUUID();
31
+ const hardwareId = crypto.randomBytes(8).toString('hex');
32
+ const installId = crypto.randomBytes(16).toString('hex');
33
+
34
+ return {
35
+ 'User-Agent': `Pinterest for Android/${version} (${device.model}; ${androidVer})`,
36
+ 'accept-language': 'id-ID',
37
+ 'x-pinterest-advertising-id': advertisingId,
38
+ 'x-pinterest-app-type-detailed': '3',
39
+ 'x-pinterest-device': device.model,
40
+ 'x-pinterest-device-hardwareid': hardwareId,
41
+ 'x-pinterest-device-manufacturer': device.manufacturer,
42
+ 'x-pinterest-installid': installId,
43
+ 'x-pinterest-webview-supported': 'false',
44
+ 'x-pinterest-appstate': 'active',
45
+ 'x-node-id': 'true',
46
+ 'authorization': `Bearer ${this.authToken}`
47
+ };
48
+ }
49
+
50
+ async searchByImage(imageUrl, pageSize = 12) {
51
+ const data = new FormData();
52
+ data.append('camera_type', '0');
53
+ data.append('source_type', '1');
54
+ data.append('video_autoplay_disabled', '0');
55
+ data.append('fields', this.getFields());
56
+ data.append('page_size', pageSize.toString());
57
+ data.append('image_url', imageUrl);
58
+
59
+ const headers = this.getRandomHeaders();
60
+ const response = await axios.post(
61
+ 'https://api.pinterest.com/v3/visual_search/lens/search/',
62
+ data,
63
+ { headers: { ...headers, ...data.getHeaders() } }
64
+ );
65
+
66
+ return this.parseResults(response.data);
67
+ }
68
+
69
+ async getMoreResults(bookmark, url, pageSize = 12) {
70
+ const params = new URLSearchParams({
71
+ bookmark,
72
+ camera_type: '0',
73
+ source_type: '1',
74
+ video_autoplay_disabled: '0',
75
+ fields: this.getFields(),
76
+ url,
77
+ page_size: pageSize.toString(),
78
+ view_type: '119',
79
+ view_parameter: '3064'
80
+ });
81
+
82
+ const headers = this.getRandomHeaders();
83
+ const response = await axios.get(
84
+ `https://api.pinterest.com/v3/visual_search/lens/search/?${params}`,
85
+ { headers }
86
+ );
87
+
88
+ return this.parseResults(response.data);
89
+ }
90
+
91
+ async scrapeAll(imageUrl, maxPages = 5) {
92
+ const allResults = [];
93
+
94
+ const firstPage = await this.searchByImage(imageUrl);
95
+ allResults.push(...firstPage.pins);
96
+
97
+ let bookmark = firstPage.bookmark;
98
+ let url = firstPage.url;
99
+ let page = 2;
100
+
101
+ while (bookmark && page <= maxPages) {
102
+ const nextPage = await this.getMoreResults(bookmark, url);
103
+ allResults.push(...nextPage.pins);
104
+ bookmark = nextPage.bookmark;
105
+ page++;
106
+ await this.delay(100);
107
+ }
108
+
109
+ return {
110
+ total: allResults.length,
111
+ pins: allResults,
112
+ visualObjects: firstPage.visualObjects,
113
+ searchIdentifier: firstPage.searchIdentifier
114
+ };
115
+ }
116
+
117
+ parseResults(response) {
118
+ const pins = response.data.map(pin => ({
119
+ id: pin.id,
120
+ title: pin.title || '',
121
+ description: pin.description || '',
122
+ imageUrl: pin.images?.['736x']?.url || pin.images?.originals?.url,
123
+ thumbnailUrl: pin.images?.['236x']?.url,
124
+ dominantColor: pin.dominant_color,
125
+ creator: {
126
+ id: pin.pinner?.id,
127
+ username: pin.pinner?.username,
128
+ fullName: pin.pinner?.full_name,
129
+ imageUrl: pin.pinner?.image_medium_url
130
+ },
131
+ board: {
132
+ id: pin.board?.id,
133
+ name: pin.board?.name,
134
+ url: pin.board?.url
135
+ },
136
+ stats: {
137
+ saves: pin.aggregated_pin_data?.aggregated_stats?.saves || 0,
138
+ comments: pin.comment_count || 0
139
+ },
140
+ createdAt: pin.created_at,
141
+ isVideo: pin.is_video || false,
142
+ link: pin.link,
143
+ domain: pin.domain
144
+ }));
145
+
146
+ return {
147
+ pins,
148
+ bookmark: response.bookmark,
149
+ url: response.url,
150
+ visualObjects: response.visual_objects,
151
+ searchIdentifier: response.search_identifier
152
+ };
153
+ }
154
+
155
+ getFields() {
156
+ return 'pin.{id,title,description,images[736x,236x],dominant_color,pinner(),board(),aggregated_pin_data(),comment_count,created_at,is_video,link,domain},user.{id,username,full_name,image_medium_url},board.{id,name,url},aggregatedpindata.{aggregated_stats}';
157
+ }
158
+
159
+ delay(ms) {
160
+ return new Promise(resolve => setTimeout(resolve, ms));
161
+ }
162
+ }
163
+
164
+ const handler = async (req, res) => {
165
+ try {
166
+ const { imageUrl, token, maxPages = 5, key } = req.query;
167
+
168
+ if (!imageUrl) {
169
+ return res.status(400).json({
170
+ success: false,
171
+ error: 'Missing required parameter: imageUrl'
172
+ });
173
+ }
174
+
175
+ if (!token) {
176
+ return res.status(400).json({
177
+ success: false,
178
+ error: 'Missing required parameter: token'
179
+ });
180
+ }
181
+
182
+ const scraper = new PinterestLensScraper(token);
183
+ const results = await scraper.scrapeAll(imageUrl, parseInt(maxPages));
184
+
185
+ res.json({
186
+ author: 'siputzx',
187
+ success: true,
188
+ data: results
189
+ });
190
+
191
+ } catch (error) {
192
+ res.status(500).json({
193
+ success: false,
194
+ error: error.message
195
+ });
196
+ }
197
+ };
198
+
199
+ module.exports = {
200
+ name: 'Pinterest Lens Scraper',
201
+ description: 'Scrape Pinterest pins using image search with lens',
202
+ type: 'GET',
203
+ routes: ['api/tools/pinlens'],
204
+ tags: ['tools', 'pinterest', 'image-search'],
205
+ main: ['tools', 'Search'],
206
+ parameters: ['imageUrl', 'token', 'maxPages', 'key'],
207
+ enabled: true,
208
+ limit: 10,
209
+ handler
210
+ };
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/removebg.js ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+
3
+ async function removebg(img_url) {
4
+ const uploadResponse = await axios.get('https://aibackgroundremover.org/api/get-upload-url');
5
+ const { uploadUrl, publicUrl } = uploadResponse.data;
6
+
7
+ const imageResponse = await axios.get(img_url, { responseType: 'arraybuffer' });
8
+
9
+ await axios.put(uploadUrl, imageResponse.data, {
10
+ headers: {
11
+ 'Content-Type': 'image/png',
12
+ 'Referer': 'https://aibackgroundremover.org/?utm_source=chatgpt.com'
13
+ }
14
+ });
15
+
16
+ const removeBgResponse = await axios.post('https://aibackgroundremover.org/api/remove-bg', {
17
+ image: publicUrl
18
+ }, {
19
+ headers: {
20
+ 'Content-Type': 'application/json',
21
+ 'Referer': 'https://aibackgroundremover.org/?utm_source=chatgpt.com'
22
+ }
23
+ });
24
+
25
+ const { id } = removeBgResponse.data;
26
+
27
+ while (true) {
28
+ const statusResponse = await axios.get(`https://aibackgroundremover.org/api/check-status?id=${id}`, {
29
+ headers: {
30
+ 'Referer': 'https://aibackgroundremover.org/?utm_source=chatgpt.com'
31
+ }
32
+ });
33
+
34
+ const { status, output, error } = statusResponse.data;
35
+
36
+ if (status === 'succeeded') {
37
+ return output;
38
+ } else if (status === 'failed') {
39
+ throw new Error(error || 'Background removal failed');
40
+ }
41
+
42
+ await new Promise(resolve => setTimeout(resolve, 2000));
43
+ }
44
+ }
45
+
46
+ const handler = async (req, res) => {
47
+ try {
48
+ const { url } = req.query;
49
+
50
+ if (!url) {
51
+ return res.status(400).json({
52
+ success: false,
53
+ error: 'Missing required parameter: url'
54
+ });
55
+ }
56
+
57
+ const result = await removebg(url);
58
+
59
+ res.json({
60
+ success: true,
61
+ data: {
62
+ original_url: url,
63
+ output_url: result
64
+ }
65
+ });
66
+
67
+ } catch (error) {
68
+ res.status(500).json({
69
+ success: false,
70
+ error: error.message
71
+ });
72
+ }
73
+ };
74
+
75
+ module.exports = {
76
+ name: 'Background Remover',
77
+ description: 'Remove background from images using AI',
78
+ type: 'GET',
79
+ routes: ['api/tools/removebg'],
80
+ tags: ['image', 'ai', 'background'],
81
+ parameters: ['url', 'key'],
82
+ enabled: true,
83
+ main: ['tools'],
84
+ handler
85
+ };
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/sora2-img2vid.js ADDED
@@ -0,0 +1,499 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const dns = require('dns').promises;
3
+
4
+ const PROXY_URL = 'https://proxy-sigma-roan.vercel.app/api/proxy';
5
+
6
+ dns.setServers(['1.1.1.1', '8.8.8.8', '8.8.4.4']);
7
+
8
+ function generateUniqueId() {
9
+ return Array.from({ length: 32 }, () =>
10
+ Math.floor(Math.random() * 16).toString(16)
11
+ ).join('');
12
+ }
13
+
14
+ function generatePassword() {
15
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
16
+ let password = '';
17
+ for (let i = 0; i < 12; i++) {
18
+ password += chars.charAt(Math.floor(Math.random() * chars.length));
19
+ }
20
+ return password;
21
+ }
22
+
23
+ function randomDelay(min = 1000, max = 3000) {
24
+ const delay = Math.floor(Math.random() * (max - min + 1)) + min;
25
+ return new Promise(resolve => setTimeout(resolve, delay));
26
+ }
27
+
28
+ function generateRandomIP() {
29
+ return `${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`;
30
+ }
31
+
32
+ async function proxyRequest(url, options = {}) {
33
+ const targetPath = url.startsWith('http') ? url : url;
34
+ const fakeIP = generateRandomIP();
35
+
36
+ const headers = {
37
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
38
+ 'Accept': 'application/json, text/plain, */*',
39
+ 'X-Forwarded-For': fakeIP,
40
+ 'X-Real-IP': fakeIP,
41
+ 'X-Client-IP': fakeIP,
42
+ ...(options.headers || {})
43
+ };
44
+
45
+ await randomDelay(500, 1500);
46
+
47
+ const axiosConfig = {
48
+ method: options.method || 'GET',
49
+ headers: headers,
50
+ timeout: 30000,
51
+ params: { url: targetPath },
52
+ validateStatus: (status) => status >= 200 && status < 600
53
+ };
54
+
55
+ if (options.data && (options.method === 'POST' || options.method === 'PUT')) {
56
+ axiosConfig.data = options.data;
57
+ }
58
+
59
+ let lastError = null;
60
+
61
+ for (let attempt = 1; attempt <= 3; attempt++) {
62
+ try {
63
+ axiosConfig.url = PROXY_URL;
64
+ const response = await axios(axiosConfig);
65
+
66
+ console.log(`[Proxy] Status: ${response.status}, URL: ${targetPath}`);
67
+
68
+ if (response.status === 500) {
69
+ console.error('[Proxy] 500 Error Details:', JSON.stringify(response.data));
70
+ throw new Error(`Proxy server error: ${JSON.stringify(response.data)}`);
71
+ }
72
+
73
+ if (response.status === 403) {
74
+ await randomDelay(3000, 5000);
75
+ throw new Error('API Bylo returned 403 Forbidden');
76
+ }
77
+
78
+ if (response.status === 429) {
79
+ await randomDelay(5000, 10000);
80
+ if (attempt < 3) continue;
81
+ throw new Error('Rate limit exceeded');
82
+ }
83
+
84
+ if (response.status >= 200 && response.status < 300) {
85
+ if (!response.data) throw new Error('Empty response from proxy');
86
+ return response;
87
+ }
88
+
89
+ if (response.status >= 400) {
90
+ const errorMsg = response.data?.msg || response.data?.message || 'Unknown error';
91
+ throw new Error(`API error (${response.status}): ${errorMsg}`);
92
+ }
93
+
94
+ if (attempt < 3) await randomDelay(2000, 4000);
95
+
96
+ } catch (error) {
97
+ console.error('[Proxy] Request failed:', {
98
+ url: targetPath,
99
+ status: error.response?.status,
100
+ data: error.response?.data,
101
+ message: error.message
102
+ });
103
+ lastError = error;
104
+ if (attempt < 3) {
105
+ const waitTime = 3000 * attempt;
106
+ await randomDelay(waitTime, waitTime + 2000);
107
+ }
108
+ }
109
+ }
110
+
111
+ throw new Error(`Proxy request failed after 3 attempts: ${lastError?.message || 'Unknown error'}`);
112
+ }
113
+
114
+ async function createTempEmail() {
115
+ const { data } = await axios.post('https://api.internal.temp-mail.io/api/v3/email/new', {
116
+ min_name_length: 10,
117
+ max_name_length: 10
118
+ }, {
119
+ headers: {
120
+ 'Content-Type': 'application/json',
121
+ 'Application-Name': 'web',
122
+ 'Application-Version': '4.0.0',
123
+ 'X-CORS-Header': 'iaWg3pchvFx48fY'
124
+ },
125
+ timeout: 15000
126
+ });
127
+ return data;
128
+ }
129
+
130
+ async function getHcaptchaToken() {
131
+ const { data } = await axios.get(
132
+ 'https://anabot.my.id/api/tools/bypass?url=https%3A%2F%2Fapi.hcaptcha.com&siteKey=6f70c0f2-3ef6-4972-9fb6-c0b4bade3af8&type=hcaptcha-invisible&apikey=freeApikey',
133
+ { timeout: 15000 }
134
+ );
135
+
136
+ if (!data.success) throw new Error('Failed to get hCaptcha token');
137
+ return data.data.result.token;
138
+ }
139
+
140
+ async function sendVerificationEmail(email) {
141
+ await randomDelay(1000, 2000);
142
+ const hcaptchaToken = await getHcaptchaToken();
143
+ const encodedEmail = encodeURIComponent(email);
144
+ await randomDelay(500, 1000);
145
+
146
+ const { data } = await proxyRequest(
147
+ `/api/auth/send-captcha?email=${encodedEmail}&type=register`,
148
+ {
149
+ method: 'GET',
150
+ headers: {
151
+ 'Accept': 'application/json, text/plain, */*',
152
+ 'hcaptcha-token': hcaptchaToken,
153
+ 'uniqueId': generateUniqueId()
154
+ }
155
+ }
156
+ );
157
+
158
+ if (data.code !== 200) {
159
+ throw new Error(`Failed to send verification email: ${data.msg || 'Unknown error'}`);
160
+ }
161
+
162
+ await randomDelay(3000, 5000);
163
+ return true;
164
+ }
165
+
166
+ async function getVerificationCode(email) {
167
+ let attempts = 0;
168
+ const maxAttempts = 30;
169
+
170
+ while (attempts < maxAttempts) {
171
+ try {
172
+ await new Promise(resolve => setTimeout(resolve, 5000));
173
+
174
+ const { data } = await axios.get(
175
+ `https://api.internal.temp-mail.io/api/v3/email/${email}/messages`,
176
+ {
177
+ headers: {
178
+ 'Content-Type': 'application/json',
179
+ 'Application-Name': 'web',
180
+ 'Application-Version': '4.0.0',
181
+ 'X-CORS-Header': 'iaWg3pchvFx48fY'
182
+ },
183
+ timeout: 10000
184
+ }
185
+ );
186
+
187
+ if (data.length > 0) {
188
+ const bodyText = data[0].body_text;
189
+ const codeMatch = bodyText.match(/Verification Code:\s*(\d{6})/);
190
+ if (codeMatch) return codeMatch[1];
191
+ }
192
+
193
+ attempts++;
194
+ } catch (error) {
195
+ attempts++;
196
+ }
197
+ }
198
+
199
+ throw new Error('Verification code not received after 30 attempts');
200
+ }
201
+
202
+ async function registerAccount(email, password, verificationCode) {
203
+ const { data } = await proxyRequest('/api/auth/register', {
204
+ method: 'POST',
205
+ headers: {
206
+ 'Accept': 'application/json, text/plain, */*',
207
+ 'Content-Type': 'application/json',
208
+ 'uniqueId': generateUniqueId()
209
+ },
210
+ data: {
211
+ email: email,
212
+ password: password,
213
+ confirmPassword: password,
214
+ verificationCode: verificationCode,
215
+ referDomain: ''
216
+ }
217
+ });
218
+
219
+ if (data.code !== 200) {
220
+ throw new Error(`Registration failed: ${data.msg || 'Unknown error'}`);
221
+ }
222
+
223
+ return data.data.token;
224
+ }
225
+
226
+ async function createVideoFromImage(prompt, imageUrl, ratio, duration, authToken, email) {
227
+ await randomDelay(2000, 3000);
228
+
229
+ const payloadVariants = [
230
+ {
231
+ prompt: prompt,
232
+ channel: 'SORA2',
233
+ pageId: 536,
234
+ source: 'bylo.ai',
235
+ watermarkFlag: false,
236
+ privateFlag: false,
237
+ isTemp: true,
238
+ model: 'sora_video2',
239
+ videoType: 'image-to-video',
240
+ duration: duration.toString(),
241
+ aspectRatio: ratio,
242
+ imageUrls: [imageUrl],
243
+ email: email
244
+ },
245
+ {
246
+ prompt: prompt,
247
+ channel: 'SORA2',
248
+ pageId: 536,
249
+ source: 'bylo.ai',
250
+ watermarkFlag: false,
251
+ privateFlag: false,
252
+ isTemp: true,
253
+ model: 'sora_video2',
254
+ videoType: 'image-to-video',
255
+ duration: duration.toString(),
256
+ aspectRatio: ratio,
257
+ imageUrl: imageUrl,
258
+ email: email
259
+ },
260
+ {
261
+ prompt: prompt,
262
+ channel: 'SORA2',
263
+ pageId: 536,
264
+ source: 'bylo.ai',
265
+ watermarkFlag: false,
266
+ privateFlag: false,
267
+ isTemp: true,
268
+ model: 'sora_video2',
269
+ videoType: 'image-to-video',
270
+ duration: duration.toString(),
271
+ aspectRatio: ratio,
272
+ image: imageUrl,
273
+ email: email
274
+ }
275
+ ];
276
+
277
+ let lastError = null;
278
+
279
+ for (let i = 0; i < payloadVariants.length; i++) {
280
+ try {
281
+ console.log(`[DEBUG] Trying payload variant ${i + 1}:`, JSON.stringify(payloadVariants[i], null, 2));
282
+
283
+ const { data } = await proxyRequest('/aimodels/api/v1/ai/video/create', {
284
+ method: 'POST',
285
+ headers: {
286
+ 'Content-Type': 'application/json',
287
+ 'uniqueid': generateUniqueId(),
288
+ 'verify': '',
289
+ 'authorization': authToken
290
+ },
291
+ data: payloadVariants[i]
292
+ });
293
+
294
+ console.log('[DEBUG] Response:', JSON.stringify(data, null, 2));
295
+
296
+ if (data.code === 200) {
297
+ return data.data;
298
+ }
299
+
300
+ lastError = new Error(`Failed with code ${data.code}: ${data.message || data.msg || 'Unknown error'}`);
301
+
302
+ } catch (error) {
303
+ console.error(`[DEBUG] Payload variant ${i + 1} failed:`, error.message);
304
+ lastError = error;
305
+ }
306
+ }
307
+
308
+ throw lastError || new Error('All payload variants failed');
309
+ }
310
+
311
+ async function getTaskStatus(taskId, authToken) {
312
+ const { data } = await proxyRequest(
313
+ `/aimodels/api/v1/ai/${taskId}?channel=SORA2`,
314
+ {
315
+ method: 'GET',
316
+ headers: {
317
+ 'Content-Type': 'application/json',
318
+ 'authorization': authToken
319
+ }
320
+ }
321
+ );
322
+
323
+ if (!data || !data.data) {
324
+ throw new Error('Invalid response from task status API');
325
+ }
326
+
327
+ return data.data;
328
+ }
329
+
330
+ async function waitForVideoCompletion(taskId, authToken) {
331
+ let attempts = 0;
332
+ const maxAttempts = 120;
333
+
334
+ while (attempts < maxAttempts) {
335
+ await randomDelay(5000, 7000);
336
+ const taskData = await getTaskStatus(taskId, authToken);
337
+
338
+ console.log(`[Progress] Attempt ${attempts + 1}/${maxAttempts} - State: ${taskData.state}`);
339
+
340
+ if (taskData.state === 1 && taskData.completeData) {
341
+ const completeData = JSON.parse(taskData.completeData);
342
+ return completeData.data.result_urls[0];
343
+ }
344
+
345
+ if (taskData.failMsg) {
346
+ throw new Error(`Video generation failed: ${taskData.failMsg}`);
347
+ }
348
+
349
+ attempts++;
350
+ }
351
+
352
+ throw new Error('Video generation timeout after 10 minutes');
353
+ }
354
+
355
+ async function sora2ImageToVideo(prompt, imageUrl, ratio = 'portrait', duration = 10) {
356
+ console.log('[1/6] Creating temporary email...');
357
+ const tempMail = await createTempEmail();
358
+ const email = tempMail.email;
359
+ const password = generatePassword();
360
+ console.log(`[Email] ${email}`);
361
+
362
+ console.log('[2/6] Sending verification email...');
363
+ await sendVerificationEmail(email);
364
+
365
+ console.log('[3/6] Waiting for verification code...');
366
+ const verificationCode = await getVerificationCode(email);
367
+ console.log(`[Code] ${verificationCode}`);
368
+
369
+ console.log('[4/6] Registering account...');
370
+ const authToken = await registerAccount(email, password, verificationCode);
371
+ console.log('[Auth] Token received');
372
+
373
+ console.log('[5/6] Creating video task...');
374
+ const taskId = await createVideoFromImage(prompt, imageUrl, ratio, duration, authToken, email);
375
+ console.log(`[Task ID] ${taskId}`);
376
+
377
+ console.log('[6/6] Waiting for video completion...');
378
+ const videoUrl = await waitForVideoCompletion(taskId, authToken);
379
+ console.log(`[Video URL] ${videoUrl}`);
380
+
381
+ return {
382
+ success: true,
383
+ email: email,
384
+ password: password,
385
+ videoUrl: videoUrl,
386
+ taskId: taskId
387
+ };
388
+ }
389
+
390
+ const handler = async (req, res) => {
391
+ const startTime = Date.now();
392
+
393
+ try {
394
+ const { prompt, imageUrl, key, ratio = 'portrait' } = req.query;
395
+
396
+ if (!prompt) {
397
+ return res.status(400).json({
398
+ author: 'Herza',
399
+ success: false,
400
+ msg: 'Missing required parameter: prompt',
401
+ usage: '/api/AI/sora2img2video?prompt=your_prompt&imageUrl=image_url&ratio=portrait&key=your_key'
402
+ });
403
+ }
404
+
405
+ if (!imageUrl) {
406
+ return res.status(400).json({
407
+ author: 'Herza',
408
+ success: false,
409
+ msg: 'Missing required parameter: imageUrl'
410
+ });
411
+ }
412
+
413
+ if (!key) {
414
+ return res.status(400).json({
415
+ author: 'Herza',
416
+ success: false,
417
+ msg: 'Missing required parameter: key'
418
+ });
419
+ }
420
+
421
+ if (!['portrait', 'landscape'].includes(ratio)) {
422
+ return res.status(400).json({
423
+ author: 'Herza',
424
+ success: false,
425
+ msg: 'Invalid ratio. Use: portrait or landscape'
426
+ });
427
+ }
428
+
429
+ console.log(`\n${'='.repeat(60)}`);
430
+ console.log('NEW IMAGE TO VIDEO REQUEST RECEIVED');
431
+ console.log(`Prompt: ${prompt}`);
432
+ console.log(`Image URL: ${imageUrl}`);
433
+ console.log(`Ratio: ${ratio}`);
434
+ console.log(`${'='.repeat(60)}\n`);
435
+
436
+ const result = await sora2ImageToVideo(prompt, imageUrl, ratio, 10);
437
+
438
+ const processingTime = ((Date.now() - startTime) / 1000).toFixed(2);
439
+
440
+ console.log(`\n${'='.repeat(60)}`);
441
+ console.log('REQUEST COMPLETED');
442
+ console.log(`Duration: ${processingTime}s`);
443
+ console.log(`${'='.repeat(60)}\n`);
444
+
445
+ res.json({
446
+ author: 'Herza',
447
+ success: true,
448
+ data: {
449
+ model: 'sora-video2',
450
+ prompt: prompt,
451
+ imageUrl: imageUrl,
452
+ ratio: ratio,
453
+ duration: '10s',
454
+ videoUrl: result.videoUrl,
455
+ taskId: result.taskId,
456
+ account: {
457
+ email: result.email,
458
+ password: result.password
459
+ },
460
+ processingTime: `${processingTime}s`
461
+ }
462
+ });
463
+ } catch (error) {
464
+ console.error('\n❌ ERROR:', error.message);
465
+ console.error('Stack:', error.stack);
466
+
467
+ const processingTime = ((Date.now() - startTime) / 1000).toFixed(2);
468
+
469
+ const errorMessage = error.response?.data?.error ||
470
+ error.response?.data?.message ||
471
+ error.message ||
472
+ 'Unknown error occurred';
473
+
474
+ res.status(error.response?.status || 500).json({
475
+ author: 'Herza',
476
+ success: false,
477
+ msg: errorMessage,
478
+ processingTime: `${processingTime}s`,
479
+ error: {
480
+ code: error.code || 'UNKNOWN',
481
+ statusCode: error.response?.status,
482
+ details: error.response?.data || error.message
483
+ }
484
+ });
485
+ }
486
+ }
487
+
488
+ module.exports = {
489
+ name: 'Sora2 Image to Video Generator',
490
+ description: 'Generate videos from images using Sora2 AI model from Bylo.ai via Vercel Proxy',
491
+ type: 'GET',
492
+ routes: ['api/AI/sora2img2video'],
493
+ tags: ['AI', 'Sora', 'OpenAI', 'Video', 'Image to Video'],
494
+ parameters: ['prompt', 'imageUrl', 'ratio', 'key'],
495
+ enabled: true,
496
+ main: ['AI'],
497
+ limit: 13,
498
+ handler
499
+ };
plugins/sora2.js ADDED
@@ -0,0 +1,472 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const dns = require('dns').promises;
3
+
4
+ const PROXY_URL = 'https://proxy-sigma-roan.vercel.app/api/proxy';
5
+
6
+ dns.setServers([
7
+ '1.1.1.1',
8
+ '8.8.8.8',
9
+ '8.8.4.4'
10
+ ]);
11
+
12
+ function generateUniqueId() {
13
+ return Array.from({ length: 32 }, () =>
14
+ Math.floor(Math.random() * 16).toString(16)
15
+ ).join('');
16
+ }
17
+
18
+ function generatePassword() {
19
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
20
+ let password = '';
21
+ for (let i = 0; i < 12; i++) {
22
+ password += chars.charAt(Math.floor(Math.random() * chars.length));
23
+ }
24
+ return password;
25
+ }
26
+
27
+ function randomDelay(min = 1000, max = 3000) {
28
+ const delay = Math.floor(Math.random() * (max - min + 1)) + min;
29
+ return new Promise(resolve => setTimeout(resolve, delay));
30
+ }
31
+
32
+ function generateRandomIP() {
33
+ return `${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`;
34
+ }
35
+
36
+ async function proxyRequest(url, options = {}) {
37
+ const targetPath = url.startsWith('http') ? url : url;
38
+
39
+ const fakeIP = generateRandomIP();
40
+
41
+ const headers = {
42
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
43
+ 'Accept': 'application/json, text/plain, */*',
44
+ 'X-Forwarded-For': fakeIP,
45
+ 'X-Real-IP': fakeIP,
46
+ 'X-Client-IP': fakeIP,
47
+ ...(options.headers || {})
48
+ };
49
+
50
+ await randomDelay(500, 1500);
51
+
52
+ const axiosConfig = {
53
+ method: options.method || 'GET',
54
+ headers: headers,
55
+ timeout: 30000,
56
+ params: {
57
+ url: targetPath
58
+ },
59
+ validateStatus: function (status) {
60
+ return status >= 200 && status < 600;
61
+ }
62
+ };
63
+
64
+ if (options.data && (options.method === 'POST' || options.method === 'PUT')) {
65
+ axiosConfig.data = options.data;
66
+ }
67
+
68
+ let lastError = null;
69
+
70
+ for (let attempt = 1; attempt <= 3; attempt++) {
71
+ try {
72
+ axiosConfig.url = PROXY_URL;
73
+ console.log(`Attempt ${attempt}: ${PROXY_URL}?url=${targetPath}`);
74
+
75
+ const response = await axios(axiosConfig);
76
+
77
+ console.log(`Attempt ${attempt} got status ${response.status}`);
78
+ console.log(`Response data:`, JSON.stringify(response.data).substring(0, 200));
79
+
80
+ if (response.status === 403) {
81
+ console.log('Got 403, waiting longer before retry...');
82
+ await randomDelay(3000, 5000);
83
+ throw new Error('API Bylo returned 403 Forbidden - possible rate limit or IP block');
84
+ }
85
+
86
+ if (response.status === 429) {
87
+ console.log('Got 429 Too Many Requests, waiting...');
88
+ await randomDelay(5000, 10000);
89
+ if (attempt < 3) continue;
90
+ throw new Error('Rate limit exceeded');
91
+ }
92
+
93
+ if (response.status >= 200 && response.status < 300) {
94
+ if (!response.data) {
95
+ throw new Error('Empty response from proxy');
96
+ }
97
+ return response;
98
+ }
99
+
100
+ if (response.status >= 400) {
101
+ const errorMsg = response.data?.msg || response.data?.message || response.data?.error || 'Unknown error';
102
+ throw new Error(`API error (${response.status}): ${errorMsg}`);
103
+ }
104
+
105
+ if (attempt < 3) {
106
+ await randomDelay(2000, 4000);
107
+ }
108
+
109
+ } catch (error) {
110
+ lastError = error;
111
+ console.error(`Attempt ${attempt} failed:`, error.message);
112
+
113
+ if (error.response) {
114
+ console.error(`Response status: ${error.response.status}`);
115
+ console.error(`Response data:`, error.response.data);
116
+ }
117
+
118
+ if (attempt < 3) {
119
+ const waitTime = 3000 * attempt;
120
+ console.log(`Retrying in ${waitTime/1000} seconds...`);
121
+ await randomDelay(waitTime, waitTime + 2000);
122
+ }
123
+ }
124
+ }
125
+
126
+ throw new Error(`Proxy request failed after 3 attempts: ${lastError?.message || 'Unknown error'}`);
127
+ }
128
+
129
+ async function createTempEmail() {
130
+ console.log('Creating temporary email...');
131
+ const { data } = await axios.post('https://api.internal.temp-mail.io/api/v3/email/new', {
132
+ min_name_length: 10,
133
+ max_name_length: 10
134
+ }, {
135
+ headers: {
136
+ 'Content-Type': 'application/json',
137
+ 'Application-Name': 'web',
138
+ 'Application-Version': '4.0.0',
139
+ 'X-CORS-Header': 'iaWg3pchvFx48fY'
140
+ },
141
+ timeout: 15000
142
+ });
143
+
144
+ console.log(`Email created: ${data.email}`);
145
+ return data;
146
+ }
147
+
148
+ async function getHcaptchaToken() {
149
+ console.log('Getting hCaptcha token...');
150
+ const { data } = await axios.get(
151
+ 'https://anabot.my.id/api/tools/bypass?url=https%3A%2F%2Fapi.hcaptcha.com&siteKey=6f70c0f2-3ef6-4972-9fb6-c0b4bade3af8&type=hcaptcha-invisible&apikey=freeApikey',
152
+ {
153
+ timeout: 15000
154
+ }
155
+ );
156
+
157
+ if (!data.success) {
158
+ throw new Error('Failed to get hCaptcha token');
159
+ }
160
+
161
+ console.log('hCaptcha token obtained');
162
+ return data.data.result.token;
163
+ }
164
+
165
+ async function sendVerificationEmail(email) {
166
+ console.log(`Sending verification email to ${email}...`);
167
+
168
+ await randomDelay(1000, 2000);
169
+
170
+ const hcaptchaToken = await getHcaptchaToken();
171
+ const encodedEmail = encodeURIComponent(email);
172
+
173
+ await randomDelay(500, 1000);
174
+
175
+ const { data } = await proxyRequest(
176
+ `/api/auth/send-captcha?email=${encodedEmail}&type=register`,
177
+ {
178
+ method: 'GET',
179
+ headers: {
180
+ 'Accept': 'application/json, text/plain, */*',
181
+ 'hcaptcha-token': hcaptchaToken,
182
+ 'uniqueId': generateUniqueId()
183
+ }
184
+ }
185
+ );
186
+
187
+ if (data.code !== 200) {
188
+ throw new Error(`Failed to send verification email: ${data.msg || 'Unknown error'}`);
189
+ }
190
+
191
+ console.log('Verification email sent successfully');
192
+ await randomDelay(3000, 5000);
193
+ return true;
194
+ }
195
+
196
+ async function getVerificationCode(email) {
197
+ console.log('Waiting for verification code...');
198
+ let attempts = 0;
199
+ const maxAttempts = 30;
200
+
201
+ while (attempts < maxAttempts) {
202
+ try {
203
+ await new Promise(resolve => setTimeout(resolve, 5000));
204
+
205
+ const { data } = await axios.get(
206
+ `https://api.internal.temp-mail.io/api/v3/email/${email}/messages`,
207
+ {
208
+ headers: {
209
+ 'Content-Type': 'application/json',
210
+ 'Application-Name': 'web',
211
+ 'Application-Version': '4.0.0',
212
+ 'X-CORS-Header': 'iaWg3pchvFx48fY'
213
+ },
214
+ timeout: 10000
215
+ }
216
+ );
217
+
218
+ if (data.length > 0) {
219
+ const bodyText = data[0].body_text;
220
+ const codeMatch = bodyText.match(/Verification Code:\s*(\d{6})/);
221
+
222
+ if (codeMatch) {
223
+ console.log(`Verification code received: ${codeMatch[1]}`);
224
+ return codeMatch[1];
225
+ }
226
+ }
227
+
228
+ attempts++;
229
+ console.log(`Checking for verification code... attempt ${attempts}/${maxAttempts}`);
230
+ } catch (error) {
231
+ console.log(`Email check attempt ${attempts} failed:`, error.message);
232
+ attempts++;
233
+ }
234
+ }
235
+
236
+ throw new Error('Verification code not received after 30 attempts');
237
+ }
238
+
239
+ async function registerAccount(email, password, verificationCode) {
240
+ console.log('Registering account...');
241
+ const { data } = await proxyRequest('/api/auth/register', {
242
+ method: 'POST',
243
+ headers: {
244
+ 'Accept': 'application/json, text/plain, */*',
245
+ 'Content-Type': 'application/json',
246
+ 'uniqueId': generateUniqueId()
247
+ },
248
+ data: {
249
+ email: email,
250
+ password: password,
251
+ confirmPassword: password,
252
+ verificationCode: verificationCode,
253
+ referDomain: ''
254
+ }
255
+ });
256
+
257
+ if (data.code !== 200) {
258
+ throw new Error(`Registration failed: ${data.msg || 'Unknown error'}`);
259
+ }
260
+
261
+ console.log('Account registered successfully');
262
+ return data.data.token;
263
+ }
264
+
265
+ async function createVideo(prompt, ratio, authToken, email) {
266
+ console.log('Creating video task...');
267
+ await randomDelay(2000, 3000);
268
+
269
+ const { data } = await proxyRequest('/aimodels/api/v1/ai/video/create', {
270
+ method: 'POST',
271
+ headers: {
272
+ 'Content-Type': 'application/json',
273
+ 'uniqueid': generateUniqueId(),
274
+ 'verify': '',
275
+ 'authorization': authToken
276
+ },
277
+ data: {
278
+ prompt: prompt,
279
+ channel: 'SORA2',
280
+ pageId: 536,
281
+ source: 'bylo.ai',
282
+ watermarkFlag: false,
283
+ privateFlag: false,
284
+ isTemp: true,
285
+ model: 'sora_video2',
286
+ videoType: 'text-to-video',
287
+ duration: '10',
288
+ aspectRatio: ratio,
289
+ email: email
290
+ }
291
+ });
292
+
293
+ if (data.code !== 200) {
294
+ throw new Error(`Failed to create video: ${data.message || 'Unknown error'}`);
295
+ }
296
+
297
+ console.log(`Video task created with ID: ${data.data}`);
298
+ return data.data;
299
+ }
300
+
301
+ async function getTaskStatus(taskId, authToken) {
302
+ try {
303
+ const { data } = await proxyRequest(
304
+ `/aimodels/api/v1/ai/${taskId}?channel=SORA2`,
305
+ {
306
+ method: 'GET',
307
+ headers: {
308
+ 'Content-Type': 'application/json',
309
+ 'authorization': authToken
310
+ }
311
+ }
312
+ );
313
+
314
+ if (!data || !data.data) {
315
+ throw new Error('Invalid response from task status API');
316
+ }
317
+
318
+ return data.data;
319
+ } catch (error) {
320
+ console.error('Error getting task status:', error.message);
321
+ throw error;
322
+ }
323
+ }
324
+
325
+ async function waitForVideoCompletion(taskId, authToken) {
326
+ console.log('Waiting for video generation...');
327
+ let attempts = 0;
328
+ const maxAttempts = 120;
329
+
330
+ while (attempts < maxAttempts) {
331
+ await randomDelay(5000, 7000);
332
+
333
+ const taskData = await getTaskStatus(taskId, authToken);
334
+
335
+ console.log(`Video status check ${attempts + 1}/${maxAttempts} - State: ${taskData.state}`);
336
+
337
+ if (taskData.state === 1 && taskData.completeData) {
338
+ const completeData = JSON.parse(taskData.completeData);
339
+ console.log('Video generation completed!');
340
+ return completeData.data.result_urls[0];
341
+ }
342
+
343
+ if (taskData.failMsg) {
344
+ throw new Error(`Video generation failed: ${taskData.failMsg}`);
345
+ }
346
+
347
+ attempts++;
348
+ }
349
+
350
+ throw new Error('Video generation timeout after 10 minutes');
351
+ }
352
+
353
+ async function sora2(prompt, ratio = 'portrait') {
354
+ console.log('=== Starting Sora2 Video Generation ===');
355
+ console.log(`Prompt: ${prompt}`);
356
+ console.log(`Ratio: ${ratio}`);
357
+
358
+ const tempMail = await createTempEmail();
359
+ const email = tempMail.email;
360
+ const password = generatePassword();
361
+
362
+ await sendVerificationEmail(email);
363
+ const verificationCode = await getVerificationCode(email);
364
+ const authToken = await registerAccount(email, password, verificationCode);
365
+ const taskId = await createVideo(prompt, ratio, authToken, email);
366
+ const videoUrl = await waitForVideoCompletion(taskId, authToken);
367
+
368
+ console.log('=== Video Generation Completed ===');
369
+ console.log(`Video URL: ${videoUrl}`);
370
+
371
+ return {
372
+ success: true,
373
+ email: email,
374
+ password: password,
375
+ videoUrl: videoUrl,
376
+ taskId: taskId
377
+ };
378
+ }
379
+
380
+ const handler = async (req, res) => {
381
+ const startTime = Date.now();
382
+
383
+ try {
384
+ const { prompt, key, ratio = 'portrait' } = req.query;
385
+
386
+ if (!prompt) {
387
+ return res.status(400).json({
388
+ author: 'Herza',
389
+ success: false,
390
+ msg: 'Missing required parameter: prompt',
391
+ usage: '/api/AI/sora2?prompt=your_prompt&ratio=portrait&key=your_key'
392
+ });
393
+ }
394
+
395
+ if (!key) {
396
+ return res.status(400).json({
397
+ author: 'Herza',
398
+ success: false,
399
+ msg: 'Missing required parameter: key'
400
+ });
401
+ }
402
+
403
+ if (!['portrait', 'landscape', 'square'].includes(ratio)) {
404
+ return res.status(400).json({
405
+ author: 'Herza',
406
+ success: false,
407
+ msg: 'Invalid ratio. Use: portrait, landscape, or square'
408
+ });
409
+ }
410
+
411
+ console.log(`\n${'='.repeat(60)}`);
412
+ console.log('NEW REQUEST RECEIVED');
413
+ console.log(`Prompt: ${prompt}`);
414
+ console.log(`Ratio: ${ratio}`);
415
+ console.log(`${'='.repeat(60)}\n`);
416
+
417
+ const result = await sora2(prompt, ratio);
418
+
419
+ const duration = ((Date.now() - startTime) / 1000).toFixed(2);
420
+
421
+ console.log(`\n${'='.repeat(60)}`);
422
+ console.log('REQUEST COMPLETED');
423
+ console.log(`Duration: ${duration}s`);
424
+ console.log(`${'='.repeat(60)}\n`);
425
+
426
+ res.json({
427
+ author: 'Herza',
428
+ success: true,
429
+ data: {
430
+ model: 'sora-video2',
431
+ prompt: prompt,
432
+ ratio: ratio,
433
+ videoUrl: result.videoUrl,
434
+ taskId: result.taskId,
435
+ account: {
436
+ email: result.email,
437
+ password: result.password
438
+ },
439
+ processingTime: `${duration}s`
440
+ }
441
+ });
442
+ } catch (error) {
443
+ console.error('\n❌ ERROR:', error.message);
444
+ console.error('Stack:', error.stack);
445
+
446
+ const duration = ((Date.now() - startTime) / 1000).toFixed(2);
447
+
448
+ res.status(500).json({
449
+ author: 'Herza',
450
+ success: false,
451
+ msg: error.message || 'Terjadi kesalahan saat generate video.',
452
+ processingTime: `${duration}s`,
453
+ error: {
454
+ code: error.code || 'UNKNOWN',
455
+ details: error.response?.data || null
456
+ }
457
+ });
458
+ }
459
+ }
460
+
461
+ module.exports = {
462
+ name: 'Sora2 Video Generator',
463
+ description: 'Generate videos using Sora2 AI model from Bylo.ai via Vercel Proxy',
464
+ type: 'GET',
465
+ routes: ['api/AI/sora2'],
466
+ tags: ['AI', 'Sora', 'OpenAI', 'Video'],
467
+ parameters: ['prompt', 'ratio', 'key'],
468
+ enabled: true,
469
+ main: ['AI'],
470
+ limit: 10,
471
+ handler
472
+ };
plugins/sora2nowm.js ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ async function videoGenerator(prompt) {
2
+ if (!prompt) return { error: "Prompt tidak boleh kosong" };
3
+
4
+ const videoId = `video_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
5
+ const apiUrl = "https://veo31.ai/api";
6
+
7
+ try {
8
+ const res = await fetch(`${apiUrl}/generate/stream`, {
9
+ method: "POST",
10
+ headers: { "Content-Type": "application/json" },
11
+ body: JSON.stringify({
12
+ prompt,
13
+ aspectRatio: "9:16",
14
+ videoId,
15
+ }),
16
+ });
17
+
18
+ const data = await res.json();
19
+ if (!data.success) return { status: "failed", error: "Error generating video", detail: data };
20
+
21
+ await new Promise((r) => setTimeout(r, 120000));
22
+
23
+ while (true) {
24
+ const check = await fetch(`${apiUrl}/webhook?videoId=${videoId}`);
25
+ const status = await check.json();
26
+
27
+ if (status.status === "completed") {
28
+ return {
29
+ status: "completed",
30
+ videoUrl: status.videoUrl,
31
+ videoId,
32
+ };
33
+ } else if (status.status === "failed") {
34
+ return {
35
+ status: "failed",
36
+ error: status.error || "unknown",
37
+ };
38
+ } else {
39
+ await new Promise((r) => setTimeout(r, 60000));
40
+ }
41
+ }
42
+ } catch (err) {
43
+ return { status: "error", error: err.message };
44
+ }
45
+ }
46
+
47
+ const handler = async (req, res) => {
48
+ const startTime = Date.now();
49
+
50
+ try {
51
+ const { prompt, key } = req.query;
52
+
53
+ if (!prompt) {
54
+ return res.status(400).json({
55
+ author: 'Herza',
56
+ success: false,
57
+ msg: 'Missing required parameter: prompt',
58
+ usage: '/api/AI/sora2nowm?prompt=your_prompt&key=your_key'
59
+ });
60
+ }
61
+
62
+ if (!key) {
63
+ return res.status(400).json({
64
+ author: 'Herza',
65
+ success: false,
66
+ msg: 'Missing required parameter: key'
67
+ });
68
+ }
69
+
70
+ console.log(`\n${'='.repeat(60)}`);
71
+ console.log('NEW REQUEST RECEIVED');
72
+ console.log(`Prompt: ${prompt}`);
73
+ console.log(`${'='.repeat(60)}\n`);
74
+
75
+ const result = await videoGenerator(prompt);
76
+
77
+ const duration = ((Date.now() - startTime) / 1000).toFixed(2);
78
+
79
+ if (result.status === "completed") {
80
+ console.log(`\n${'='.repeat(60)}`);
81
+ console.log('REQUEST COMPLETED');
82
+ console.log(`Duration: ${duration}s`);
83
+ console.log(`${'='.repeat(60)}\n`);
84
+
85
+ res.json({
86
+ author: 'Herza',
87
+ success: true,
88
+ data: {
89
+ model: 'veo31-sora2',
90
+ prompt: prompt,
91
+ videoUrl: result.videoUrl,
92
+ videoId: result.videoId,
93
+ processingTime: `${duration}s`
94
+ }
95
+ });
96
+ } else {
97
+ throw new Error(result.error || 'Video generation failed');
98
+ }
99
+
100
+ } catch (error) {
101
+ console.error('\n❌ ERROR:', error.message);
102
+ console.error('Stack:', error.stack);
103
+
104
+ const duration = ((Date.now() - startTime) / 1000).toFixed(2);
105
+
106
+ res.status(500).json({
107
+ author: 'Herza',
108
+ success: false,
109
+ msg: error.message || 'Terjadi kesalahan saat generate video.',
110
+ processingTime: `${duration}s`,
111
+ error: {
112
+ code: error.code || 'UNKNOWN',
113
+ details: error.response?.data || null
114
+ }
115
+ });
116
+ }
117
+ }
118
+
119
+ module.exports = {
120
+ name: 'Sora2 Video Generator No Watermark',
121
+ description: 'Generate videos using Sora2 AI model without watermark',
122
+ type: 'GET',
123
+ routes: ['api/AI/sora2nowm'],
124
+ tags: ['AI', 'Sora', 'Video', 'NoWatermark'],
125
+ parameters: ['prompt', 'key'],
126
+ enabled: true,
127
+ main: ['AI'],
128
+ limit: 15,
129
+ handler
130
+ };
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,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const TURNSTILE_SOLVER_URL = 'https://herzaj-turnstile-solver.hf.space';
2
+
3
+ async function getTurnstileToken() {
4
+ try {
5
+ const params = new URLSearchParams({
6
+ url: 'https://www.subdomainfinder.in',
7
+ sitekey: '0x4AAAAAAAj7jyMV3Zv9ZMN-'
8
+ });
9
+
10
+ const submitResponse = await fetch(`${TURNSTILE_SOLVER_URL}/turnstile?${params}`, {
11
+ method: 'GET'
12
+ });
13
+
14
+ if (!submitResponse.ok) {
15
+ throw new Error(`Failed to submit task: ${submitResponse.status}`);
16
+ }
17
+
18
+ const taskData = await submitResponse.json();
19
+ const taskId = taskData.task_id;
20
+
21
+ await new Promise(resolve => setTimeout(resolve, 5000));
22
+
23
+ const resultResponse = await fetch(`${TURNSTILE_SOLVER_URL}/result?id=${taskId}`);
24
+
25
+ if (!resultResponse.ok) {
26
+ throw new Error(`Failed to get result: ${resultResponse.status}`);
27
+ }
28
+
29
+ const resultData = await resultResponse.json();
30
+ return resultData.value;
31
+
32
+ } catch (error) {
33
+ throw new Error("Gagal mendapatkan Turnstile token: " + error.message);
34
+ }
35
+ }
36
+
37
+ async function findSubdomains(domain, token) {
38
+ const response = await fetch(`https://api.subdomainfinder.in/?domain=${domain}`, {
39
+ method: 'GET',
40
+ headers: {
41
+ 'X-Secure-Token': token,
42
+ 'X-Referer': 'https://www.google.com/',
43
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
44
+ }
45
+ });
46
+
47
+ if (!response.ok) {
48
+ throw new Error(`HTTP error! status: ${response.status}`);
49
+ }
50
+
51
+ return await response.json();
52
+ }
53
+
54
+ async function resolveDNS(subdomain) {
55
+ const response = await fetch(`https://lookup.subdomainfinder.in/resolve?name=${subdomain}&rd=1`, {
56
+ method: 'GET',
57
+ headers: {
58
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
59
+ }
60
+ });
61
+
62
+ if (!response.ok) {
63
+ throw new Error(`HTTP error! status: ${response.status}`);
64
+ }
65
+
66
+ return await response.json();
67
+ }
68
+
69
+ async function getIPInfo(ip) {
70
+ const response = await fetch(`https://ipresolver.subdomainfinder.in/${ip}`, {
71
+ method: 'GET',
72
+ headers: {
73
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
74
+ }
75
+ });
76
+
77
+ if (!response.ok) {
78
+ throw new Error(`HTTP error! status: ${response.status}`);
79
+ }
80
+
81
+ return await response.json();
82
+ }
83
+
84
+ function extractIPFromDNS(dnsData) {
85
+ if (!dnsData || !dnsData.Answer) return null;
86
+
87
+ for (const answer of dnsData.Answer) {
88
+ if (answer.type === 1 && answer.data) {
89
+ return answer.data;
90
+ }
91
+ }
92
+ return null;
93
+ }
94
+
95
+ async function subdo(domain) {
96
+ const token = await getTurnstileToken();
97
+ const subdomainData = await findSubdomains(domain, token);
98
+ const results = [];
99
+
100
+ for (const sub of subdomainData.data) {
101
+ try {
102
+ const dnsData = await resolveDNS(sub.subdomain);
103
+ const ip = extractIPFromDNS(dnsData);
104
+
105
+ let result = {
106
+ subdomain: sub.subdomain,
107
+ ip: ip || 'N/A',
108
+ cloudflare: sub.cloudflare,
109
+ dnsStatus: dnsData.Status
110
+ };
111
+
112
+ if (ip) {
113
+ try {
114
+ const ipInfo = await getIPInfo(ip);
115
+ if (ipInfo.success && ipInfo.result && ipInfo.result.ip) {
116
+ result.ipInfo = {
117
+ location: ipInfo.result.ip.locationName,
118
+ asn: ipInfo.result.ip.asnName,
119
+ country: ipInfo.result.ip.location,
120
+ flag: ipInfo.result.ip.flag
121
+ };
122
+ }
123
+ } catch (e) {
124
+ result.ipInfo = null;
125
+ }
126
+ }
127
+
128
+ results.push(result);
129
+ } catch (error) {
130
+ results.push({
131
+ subdomain: sub.subdomain,
132
+ error: error.message
133
+ });
134
+ }
135
+ }
136
+
137
+ return {
138
+ domain: domain,
139
+ count: subdomainData.count,
140
+ data: results
141
+ };
142
+ }
143
+
144
+ const handler = async (req, res) => {
145
+ try {
146
+ const { domain } = req.query;
147
+
148
+ if (!domain) {
149
+ return res.status(400).json({
150
+ success: false,
151
+ error: 'Missing required parameter: domain'
152
+ });
153
+ }
154
+
155
+ const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?\.([a-zA-Z]{2,}\.?)+$/;
156
+ if (!domainRegex.test(domain)) {
157
+ return res.status(400).json({
158
+ success: false,
159
+ error: 'Invalid domain format'
160
+ });
161
+ }
162
+
163
+ const result = await subdo(domain);
164
+
165
+ res.json({
166
+ success: true,
167
+ data: {
168
+ domain: result.domain,
169
+ total_subdomains: result.count,
170
+ subdomains: result.data
171
+ }
172
+ });
173
+
174
+ } catch (error) {
175
+ res.status(500).json({
176
+ success: false,
177
+ error: error.message
178
+ });
179
+ }
180
+ };
181
+
182
+ module.exports = {
183
+ name: 'Subdomain Finder',
184
+ description: 'Find subdomains with IP addresses and location information',
185
+ type: 'GET',
186
+ routes: ['api/tools/subdofinder'],
187
+ tags: ['security', 'subdomain', 'dns', 'recon'],
188
+ parameters: ['domain', 'key'],
189
+ enabled: true,
190
+ main: ['tools', 'Search'],
191
+ handler
192
+ };
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/suno4.js ADDED
@@ -0,0 +1,469 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+ const crypto = require('crypto');
3
+ const HttpProxyAgent = require('http-proxy-agent');
4
+ const HttpsProxyAgent = require('https-proxy-agent');
5
+
6
+ async function getRandomProxy() {
7
+ try {
8
+ const response = await axios.get('https://raw.githubusercontent.com/proxifly/free-proxy-list/refs/heads/main/proxies/protocols/https/data.json');
9
+ const proxies = response.data;
10
+ if (proxies.length === 0) return null;
11
+ return proxies[Math.floor(Math.random() * proxies.length)].proxy;
12
+ } catch (err) {
13
+ return null;
14
+ }
15
+ }
16
+
17
+ const aiMu = {
18
+ api: {
19
+ base: 'https://aimu.1010diy.com',
20
+ endpoint: {
21
+ credits: '/and/getUserActualCredits',
22
+ musicAI: '/music/MusicAI',
23
+ taskStatus: '/music/getTaskStatus',
24
+ generateList: '/and/data/generateList',
25
+ options: '/and/home/index',
26
+ },
27
+ },
28
+
29
+ headers: {
30
+ 'user-agent': 'NB Android/1.0.0',
31
+ 'accept-encoding': 'gzip',
32
+ 'x-version-code': '27',
33
+ 'x-token': '',
34
+ },
35
+
36
+ sid: null,
37
+
38
+ setDeviceId: (id) => {
39
+ aiMu.sid = id;
40
+ },
41
+
42
+ getDeviceId: () => {
43
+ if (!aiMu.sid) {
44
+ aiMu.sid = crypto.randomBytes(8).toString('hex');
45
+ }
46
+ return aiMu.sid;
47
+ },
48
+
49
+ opts: async () => {
50
+ try {
51
+ const proxyUrl = await getRandomProxy();
52
+ const axiosConfig = { headers: { ...aiMu.headers, 'x-device-id': aiMu.getDeviceId() } };
53
+
54
+ if (proxyUrl) {
55
+ axiosConfig.httpAgent = new HttpProxyAgent(proxyUrl);
56
+ axiosConfig.httpsAgent = new HttpsProxyAgent(proxyUrl);
57
+ }
58
+
59
+ const res = await axios.get(
60
+ `${aiMu.api.base}${aiMu.api.endpoint.options}`,
61
+ axiosConfig
62
+ );
63
+
64
+ const { code, msg, data } = res.data;
65
+ if (code !== 200) {
66
+ return {
67
+ success: false,
68
+ code,
69
+ author: 'Daffa ~',
70
+ team: 'NB Team',
71
+ result: {
72
+ error: { msg }
73
+ }
74
+ };
75
+ }
76
+
77
+ const moods = [...(data.mood?.default || []), ...(data.mood?.more || [])].map(m => m.text);
78
+ const genres = [...(data.genre?.default || []), ...(data.genre?.more || [])].map(g => g.text);
79
+ const voices = ['female', 'male', 'random'];
80
+
81
+ return {
82
+ success: true,
83
+ code: 200,
84
+ author: 'Daffa ~',
85
+ team: 'NB Team',
86
+ result: {
87
+ moods,
88
+ genres,
89
+ voices
90
+ }
91
+ };
92
+ } catch (err) {
93
+ return {
94
+ success: false,
95
+ code: err.response?.status || 500,
96
+ author: 'Daffa ~',
97
+ team: 'NB Team',
98
+ result: {
99
+ error: err.message
100
+ }
101
+ };
102
+ }
103
+ },
104
+
105
+ getCredits: async () => {
106
+ try {
107
+ const proxyUrl = await getRandomProxy();
108
+ const axiosConfig = { headers: { ...aiMu.headers, 'x-device-id': aiMu.getDeviceId() } };
109
+
110
+ if (proxyUrl) {
111
+ axiosConfig.httpAgent = new HttpProxyAgent(proxyUrl);
112
+ axiosConfig.httpsAgent = new HttpsProxyAgent(proxyUrl);
113
+ }
114
+
115
+ const res = await axios.get(
116
+ `${aiMu.api.base}${aiMu.api.endpoint.credits}`,
117
+ axiosConfig
118
+ );
119
+ const { code, msg, data } = res.data;
120
+ if (code === 200) {
121
+ return {
122
+ success: true,
123
+ code: 200,
124
+ author: 'Daffa ~',
125
+ team: 'NB Team',
126
+ result: {
127
+ ...data
128
+ }
129
+ };
130
+ }
131
+ return {
132
+ success: false,
133
+ code,
134
+ author: 'Daffa ~',
135
+ team: 'NB Team',
136
+ result: {
137
+ error: msg
138
+ }
139
+ };
140
+ } catch (err) {
141
+ return {
142
+ success: false,
143
+ code: err.response?.status || 500,
144
+ author: 'Daffa ~',
145
+ team: 'NB Team',
146
+ result: {
147
+ error: err.message
148
+ }
149
+ };
150
+ }
151
+ },
152
+
153
+ generate: async (params) => {
154
+ let make_instrumental = params.make_instrumental ? 1 : 0;
155
+ let vocal_only = params.vocal_only ? 1 : 0;
156
+ if (make_instrumental === 1) vocal_only = 0;
157
+
158
+ const { lyrics = '', prompt = '' } = params;
159
+ if (!lyrics.trim() && !prompt.trim()) {
160
+ return {
161
+ success: false,
162
+ code: 400,
163
+ author: 'Daffa ~',
164
+ team: 'NB Team',
165
+ result: {
166
+ error: 'Lu bisa pilih Lyric atau Prompt bree'
167
+ }
168
+ };
169
+ }
170
+
171
+ if (prompt && prompt.length > 1000) {
172
+ return {
173
+ success: false,
174
+ code: 400,
175
+ author: 'Daffa ~',
176
+ team: 'NB Team',
177
+ result: {
178
+ error: 'Promptnya kepanjangan yak, max 1k karakter aja.. '
179
+ }
180
+ };
181
+ }
182
+
183
+ const payload = { make_instrumental, vocal_only, lyrics, prompt, ...params };
184
+
185
+ try {
186
+ const proxyUrl = await getRandomProxy();
187
+ const axiosConfig = {
188
+ headers: {
189
+ ...aiMu.headers,
190
+ 'content-type': 'application/json',
191
+ 'x-device-id': aiMu.getDeviceId(),
192
+ },
193
+ };
194
+
195
+ if (proxyUrl) {
196
+ axiosConfig.httpAgent = new HttpProxyAgent(proxyUrl);
197
+ axiosConfig.httpsAgent = new HttpsProxyAgent(proxyUrl);
198
+ }
199
+
200
+ const res = await axios.post(
201
+ `${aiMu.api.base}${aiMu.api.endpoint.musicAI}`,
202
+ payload,
203
+ axiosConfig
204
+ );
205
+ const { code, msg, data } = res.data;
206
+ if (code === 200) {
207
+ return {
208
+ success: true,
209
+ code: 200,
210
+ author: 'Daffa ~',
211
+ team: 'NB Team',
212
+ result: {
213
+ taskId: data?.task_id,
214
+ inputType: prompt ? 'prompt' : 'lyrics',
215
+ inputValue: prompt || lyrics
216
+ }
217
+ };
218
+ }
219
+ return {
220
+ success: false,
221
+ code,
222
+ author: 'Daffa ~',
223
+ team: 'NB Team',
224
+ result: {
225
+ error: msg
226
+ }
227
+ };
228
+ } catch (err) {
229
+ return {
230
+ success: false,
231
+ code: err.response?.status || 500,
232
+ author: 'Daffa ~',
233
+ team: 'NB Team',
234
+ result: {
235
+ error: err.message
236
+ }
237
+ };
238
+ }
239
+ },
240
+
241
+ polling: async (taskId) => {
242
+ if (!String(taskId)?.trim()) {
243
+ return {
244
+ success: false,
245
+ code: 400,
246
+ author: 'Daffa ~',
247
+ team: 'NB Team',
248
+ result: {
249
+ error: 'Task IDnya kagak boleh kosong bree... '
250
+ }
251
+ };
252
+ }
253
+ try {
254
+ const proxyUrl = await getRandomProxy();
255
+ const axiosConfig = {
256
+ params: { task_id: taskId },
257
+ headers: { ...aiMu.headers, 'x-device-id': aiMu.getDeviceId() },
258
+ };
259
+
260
+ if (proxyUrl) {
261
+ axiosConfig.httpAgent = new HttpProxyAgent(proxyUrl);
262
+ axiosConfig.httpsAgent = new HttpsProxyAgent(proxyUrl);
263
+ }
264
+
265
+ const res = await axios.get(
266
+ `${aiMu.api.base}${aiMu.api.endpoint.taskStatus}`,
267
+ axiosConfig
268
+ );
269
+ const { code, msg, data } = res.data;
270
+ if (code === 200) {
271
+ return {
272
+ success: true,
273
+ code: 200,
274
+ author: 'Daffa ~',
275
+ team: 'NB Team',
276
+ result: {
277
+ status: data?.status,
278
+ }
279
+ };
280
+ }
281
+ return {
282
+ success: false,
283
+ code,
284
+ author: 'Daffa ~',
285
+ team: 'NB Team',
286
+ result: {
287
+ error: msg
288
+ }
289
+ };
290
+ } catch (err) {
291
+ return {
292
+ success: false,
293
+ code: err.response?.status || 500,
294
+ author: 'Daffa ~',
295
+ team: 'NB Team',
296
+ result: {
297
+ error: err.message
298
+ }
299
+ };
300
+ }
301
+ },
302
+
303
+ getGenerateList: async () => {
304
+ try {
305
+ const proxyUrl = await getRandomProxy();
306
+ const axiosConfig = { headers: { ...aiMu.headers, 'x-device-id': aiMu.getDeviceId() } };
307
+
308
+ if (proxyUrl) {
309
+ axiosConfig.httpAgent = new HttpProxyAgent(proxyUrl);
310
+ axiosConfig.httpsAgent = new HttpsProxyAgent(proxyUrl);
311
+ }
312
+
313
+ const res = await axios.get(
314
+ `${aiMu.api.base}${aiMu.api.endpoint.generateList}`,
315
+ axiosConfig
316
+ );
317
+ const { code, msg, data } = res.data;
318
+ if (code === 200) {
319
+ const results = (data || []).map((item) => ({
320
+ taskId: item.task_id,
321
+ title: item.title,
322
+ duration: item.duration,
323
+ mp3: item.conversion_path,
324
+ cover: item.album_cover_path,
325
+ input: item.lyrics,
326
+ created_at: item.created_at,
327
+ updated_at: item.updated_at,
328
+ }));
329
+ return {
330
+ success: true,
331
+ code: 200,
332
+ author: 'Daffa ~',
333
+ team: 'NB Team',
334
+ result: {
335
+ results
336
+ }
337
+ };
338
+ }
339
+ return {
340
+ success: false,
341
+ code,
342
+ author: 'Daffa ~',
343
+ team: 'NB Team',
344
+ result: {
345
+ error: msg
346
+ }
347
+ };
348
+ } catch (err) {
349
+ return {
350
+ success: false,
351
+ code: err.response?.status || 500,
352
+ author: 'Daffa ~',
353
+ team: 'NB Team',
354
+ result: {
355
+ error: err.message
356
+ }
357
+ };
358
+ }
359
+ },
360
+
361
+ task: async (taskId, inputType, inputValue, intervalMs = 5000) => {
362
+ if (!String(taskId)?.trim()) {
363
+ return {
364
+ success: false,
365
+ code: 400,
366
+ author: 'Daffa ~',
367
+ team: 'NB Team',
368
+ result: {
369
+ error: 'Task IDnya kagak boleh kosong bree... '
370
+ }
371
+ };
372
+ }
373
+
374
+ while (true) {
375
+ const resx = await aiMu.polling(taskId);
376
+ if (!resx.success) return resx;
377
+
378
+ if (resx.result.status === 'complete') {
379
+ const re = await aiMu.getGenerateList();
380
+ if (!re.success) return re;
381
+
382
+ const tracks = re.result.results.filter((r) => String(r.taskId) === String(taskId));
383
+
384
+ const avr = tracks.every((t) => t.mp3.includes('vocal-remover.s3.us-west-2.amazonaws.com'));
385
+
386
+ if (tracks.length > 0 && avr) {
387
+ return {
388
+ success: true,
389
+ code: 200,
390
+ author: 'Daffa ~',
391
+ team: 'NB Team',
392
+ result: {
393
+ taskId: String(taskId),
394
+ count: tracks.length,
395
+ tracks: tracks.map((t) => ({
396
+ title: t.title,
397
+ duration: t.duration,
398
+ audio: t.mp3,
399
+ cover: t.cover,
400
+ [inputType]: t.input,
401
+ created_at: t.created_at,
402
+ updated_at: t.updated_at,
403
+ })),
404
+ inputValue
405
+ }
406
+ };
407
+ }
408
+ }
409
+
410
+ await new Promise((r) => setTimeout(r, intervalMs));
411
+ }
412
+ },
413
+ };
414
+
415
+ const handler = async (req, res) => {
416
+ try {
417
+ const { prompt, lyrics, mood, genre, voice, key } = req.query;
418
+
419
+ if (!prompt && !lyrics) {
420
+ return res.status(400).json({
421
+ success: false,
422
+ error: 'Missing required parameter: prompt or lyrics'
423
+ });
424
+ }
425
+
426
+ const params = {
427
+ prompt: prompt || '',
428
+ lyrics: lyrics || '',
429
+ mood: mood || '',
430
+ genre: genre || '',
431
+ voice: voice || 'random',
432
+ make_instrumental: 0,
433
+ vocal_only: 0
434
+ };
435
+
436
+ const genResult = await aiMu.generate(params);
437
+
438
+ if (!genResult.success) {
439
+ return res.status(400).json(genResult);
440
+ }
441
+
442
+ const taskId = genResult.result.taskId;
443
+ const inputType = genResult.result.inputType;
444
+ const inputValue = genResult.result.inputValue;
445
+
446
+ const taskResult = await aiMu.task(taskId, inputType, inputValue);
447
+
448
+ res.json(taskResult);
449
+
450
+ } catch (error) {
451
+ res.status(500).json({
452
+ success: false,
453
+ error: error.message
454
+ });
455
+ }
456
+ };
457
+
458
+ module.exports = {
459
+ name: 'Sunov4 Music Generator',
460
+ description: 'Generate music using AiMu AI model',
461
+ type: 'GET',
462
+ routes: ['api/AI/suno4'],
463
+ tags: ['ai', 'music', 'aimu', 'suno'],
464
+ main: ['AI'],
465
+ parameters: ['prompt', 'lyrics', 'mood', 'genre', 'voice', 'key'],
466
+ enabled: true,
467
+ limit: 18,
468
+ handler
469
+ };
plugins/sunov2.js ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const axios = require('axios');
2
+
3
+ class YesChatMusicGenerator {
4
+ constructor() {
5
+ this.userAgent = "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Mobile Safari/537.36";
6
+ }
7
+
8
+ async getBypassToken() {
9
+ try {
10
+ const response = await axios.get('https://anabot.my.id/api/tools/bypass', {
11
+ params: {
12
+ url: 'https://www.yeschat.ai/',
13
+ siteKey: '0x4AAAAAAATOXAtQtziH-Rwq',
14
+ type: 'turnstile-min',
15
+ apikey: 'freeApikey'
16
+ },
17
+ headers: {
18
+ 'accept': '*/*'
19
+ }
20
+ });
21
+
22
+ if (response.data.success && response.data.data?.result?.token) {
23
+ return response.data.data.result.token;
24
+ }
25
+ throw new Error('Failed to get token from response');
26
+ } catch (error) {
27
+ throw new Error(`Failed to get bypass token: ${error.message}`);
28
+ }
29
+ }
30
+
31
+ async generateSongLyrics({
32
+ prompt,
33
+ title = "Tanpa Judul",
34
+ style = "Happy",
35
+ instrumental = false,
36
+ customMode = true,
37
+ }) {
38
+ const token = await this.getBypassToken();
39
+ if (!token || typeof token !== "string") {
40
+ throw new Error("Failed to get bypass token.");
41
+ }
42
+
43
+ const res = await axios.post(
44
+ "https://aiarticle.erweima.ai/api/v1/secondary-page/api/create",
45
+ {
46
+ prompt,
47
+ channel: "MUSIC",
48
+ id: 1018,
49
+ type: "features",
50
+ source: "yeschat.ai",
51
+ style,
52
+ title,
53
+ customMode,
54
+ instrumental,
55
+ },
56
+ {
57
+ headers: {
58
+ authority: "aiarticle.erweima.ai",
59
+ accept: "application/json, text/plain, */*",
60
+ "accept-language": "ms-MY,ms;q=0.9,en-US;q=0.8,en;q=0.7,id;q=0.6",
61
+ origin: "https://www.yeschat.ai",
62
+ referer: "https://www.yeschat.ai/",
63
+ "sec-ch-ua": '"Not A(Brand";v="8", "Chromium";v="132"',
64
+ "sec-ch-ua-mobile": "?1",
65
+ "sec-ch-ua-platform": '"Android"',
66
+ "sec-fetch-dest": "empty",
67
+ "sec-fetch-mode": "cors",
68
+ "sec-fetch-site": "cross-site",
69
+ "user-agent": this.userAgent,
70
+ uniqueid: Date.now(),
71
+ verify: token,
72
+ },
73
+ }
74
+ );
75
+
76
+ if (res.data.code !== 200) {
77
+ throw new Error(res.data.msg || "Failed to generate lyrics");
78
+ }
79
+
80
+ const recordId = res.data?.data?.recordId;
81
+ return this.pollGeneratedResult(recordId);
82
+ }
83
+
84
+ pollGeneratedResult(recordId, interval = 5000) {
85
+ return new Promise((resolve, reject) => {
86
+ const url = `https://aiarticle.erweima.ai/api/v1/secondary-page/api/${recordId}`;
87
+ const timer = setInterval(async () => {
88
+ try {
89
+ const { data } = await axios.get(url, {
90
+ headers: {
91
+ authority: "aiarticle.erweima.ai",
92
+ accept: "application/json, text/plain, */*",
93
+ "accept-language": "ms-MY,ms;q=0.9,en-US;q=0.8,en;q=0.7,id;q=0.6",
94
+ origin: "https://www.yeschat.ai",
95
+ referer: "https://www.yeschat.ai/",
96
+ "sec-ch-ua": '"Not A(Brand";v="8", "Chromium";v="132"',
97
+ "sec-ch-ua-mobile": "?1",
98
+ "sec-ch-ua-platform": '"Android"',
99
+ "sec-fetch-dest": "empty",
100
+ "sec-fetch-mode": "cors",
101
+ "sec-fetch-site": "cross-site",
102
+ "user-agent": this.userAgent,
103
+ },
104
+ });
105
+
106
+ if (data.code !== 200) {
107
+ clearInterval(timer);
108
+ return reject(new Error(data.msg || "Unexpected error"));
109
+ }
110
+
111
+ if (data.data?.failCode && data.data?.failMsg) {
112
+ clearInterval(timer);
113
+ return reject(new Error(data.data.failMsg));
114
+ }
115
+
116
+ if (data.data?.state && data.data.completeData) {
117
+ clearInterval(timer);
118
+ return resolve(JSON.parse(data.data.completeData));
119
+ }
120
+ } catch (err) {
121
+ clearInterval(timer);
122
+ return reject(err);
123
+ }
124
+ }, interval);
125
+ });
126
+ }
127
+ }
128
+
129
+ const handler = async (req, res) => {
130
+ try {
131
+ const { mode, prompt, lyrics, title, style, instrumental } = req.query;
132
+
133
+ if (!mode) {
134
+ return res.status(400).json({
135
+ success: false,
136
+ error: 'Missing required parameter: mode (custom/ai)'
137
+ });
138
+ }
139
+
140
+ const modeNormalized = mode.toLowerCase();
141
+
142
+ if (modeNormalized !== 'custom' && modeNormalized !== 'ai') {
143
+ return res.status(400).json({
144
+ success: false,
145
+ error: 'Invalid mode. Use "custom" for Custom Lyrics or "ai" for AI Lyrics'
146
+ });
147
+ }
148
+
149
+ let finalPrompt;
150
+ let customMode;
151
+
152
+ if (modeNormalized === 'custom') {
153
+ if (!lyrics) {
154
+ return res.status(400).json({
155
+ success: false,
156
+ error: 'Missing required parameter: lyrics (required for Custom Lyrics mode)'
157
+ });
158
+ }
159
+ finalPrompt = lyrics;
160
+ customMode = true;
161
+ } else {
162
+ if (!prompt) {
163
+ return res.status(400).json({
164
+ success: false,
165
+ error: 'Missing required parameter: prompt (required for AI Lyrics mode)'
166
+ });
167
+ }
168
+ finalPrompt = prompt;
169
+ customMode = false;
170
+ }
171
+
172
+ const generator = new YesChatMusicGenerator();
173
+
174
+ const result = await generator.generateSongLyrics({
175
+ prompt: finalPrompt,
176
+ title: title || "Tanpa Judul",
177
+ style: style || "Happy",
178
+ instrumental: instrumental === 'true',
179
+ customMode: customMode
180
+ });
181
+
182
+ res.json({
183
+ author: "Herza",
184
+ success: true,
185
+ mode: modeNormalized === 'custom' ? 'Custom Lyrics' : 'AI Lyrics',
186
+ result: result
187
+ });
188
+
189
+ } catch (error) {
190
+ res.status(500).json({
191
+ success: false,
192
+ error: error.message
193
+ });
194
+ }
195
+ };
196
+
197
+ module.exports = {
198
+ name: 'SunoV2 Music Generator',
199
+ type: 'GET',
200
+ routes: ['api/AI/sunov2'],
201
+ tags: ['ai', 'music', 'generator'],
202
+ main: ['AI'],
203
+ limit: 12,
204
+ parameters: ['mode', 'prompt', 'lyrics', 'title', 'style', 'instrumental', 'key'],
205
+ enabled: true,
206
+ handler
207
+ };
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/upscale.js ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const axios = require('axios');
4
+ const https = require('https');
5
+ const FormData = require('form-data');
6
+
7
+ const UPLOAD_URL = 'https://api.unblurimage.ai/api/common/upload/upload-image';
8
+ const CREATE_JOB_URL = 'https://api.unblurimage.ai/api/imgupscaler/v1/ai-image-upscaler-v2/create-job';
9
+ const PRODUCT_SERIAL = '79661c82d918475e7458944c2f66857e';
10
+ const TMP_DIR = '/tmp/upscaler';
11
+
12
+ const axiosInstance = axios.create({
13
+ timeout: 60000,
14
+ httpsAgent: new https.Agent({
15
+ rejectUnauthorized: false,
16
+ }),
17
+ });
18
+
19
+ function ensureTmpDir() {
20
+ if (!fs.existsSync(TMP_DIR)) {
21
+ fs.mkdirSync(TMP_DIR, { recursive: true });
22
+ }
23
+ }
24
+
25
+ async function downloadImage(imageUrl) {
26
+ const response = await axiosInstance.get(imageUrl, {
27
+ responseType: 'arraybuffer',
28
+ });
29
+ return Buffer.from(response.data);
30
+ }
31
+
32
+ function saveImageToTmp(imageBuffer) {
33
+ ensureTmpDir();
34
+ const fileName = `image_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.jpg`;
35
+ const filePath = path.join(TMP_DIR, fileName);
36
+ fs.writeFileSync(filePath, imageBuffer);
37
+ return filePath;
38
+ }
39
+
40
+ function deleteFileAfterDelay(filePath, delayMs = 10000) {
41
+ setTimeout(() => {
42
+ try {
43
+ if (fs.existsSync(filePath)) {
44
+ fs.unlinkSync(filePath);
45
+ }
46
+ } catch (error) {
47
+ console.error(`Failed to delete file ${filePath}:`, error.message);
48
+ }
49
+ }, delayMs);
50
+ }
51
+
52
+ async function uploadImage(filePath) {
53
+ const imageBuffer = fs.readFileSync(filePath);
54
+ const fileName = path.basename(filePath);
55
+ const contentType = 'image/jpeg';
56
+
57
+ const form = new FormData();
58
+ form.append('file_name', fileName);
59
+ form.append('file', imageBuffer, fileName);
60
+
61
+ const uploadResponse = await axiosInstance.post(UPLOAD_URL, form, {
62
+ headers: {
63
+ ...form.getHeaders(),
64
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36',
65
+ },
66
+ });
67
+
68
+ if (uploadResponse.data.code !== 100000) {
69
+ throw new Error(`Upload failed: ${uploadResponse.data.message.en}`);
70
+ }
71
+
72
+ const uploadUrl = uploadResponse.data.result.url;
73
+
74
+ await axiosInstance.put(uploadUrl, imageBuffer, {
75
+ headers: {
76
+ 'Content-Type': contentType,
77
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36',
78
+ },
79
+ });
80
+
81
+ return {
82
+ url: uploadUrl.split('?')[0],
83
+ };
84
+ }
85
+
86
+ async function createJob(imageUrl, upscaleLevel) {
87
+ const form = new FormData();
88
+ form.append('original_image_url', imageUrl);
89
+ form.append('upscale_type', upscaleLevel.toString());
90
+
91
+ const response = await axiosInstance.post(CREATE_JOB_URL, form, {
92
+ headers: {
93
+ ...form.getHeaders(),
94
+ 'Product-Serial': PRODUCT_SERIAL,
95
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36',
96
+ },
97
+ });
98
+
99
+ if (response.data.code !== 100000) {
100
+ throw new Error(`Job creation failed: ${response.data.message.en}`);
101
+ }
102
+
103
+ return response.data.result;
104
+ }
105
+
106
+ async function upscaleImage(imageUrl, scaleNumber) {
107
+ let tmpFilePath = null;
108
+
109
+ try {
110
+ if (!imageUrl) {
111
+ throw new Error('Image URL is required');
112
+ }
113
+
114
+ if (![2, 4, 8, 16].includes(scaleNumber)) {
115
+ throw new Error('Scale number must be 2, 4, 8, or 16');
116
+ }
117
+
118
+ const imageBuffer = await downloadImage(imageUrl);
119
+ tmpFilePath = saveImageToTmp(imageBuffer);
120
+
121
+ const uploadResult = await uploadImage(tmpFilePath);
122
+ const result = await createJob(uploadResult.url, scaleNumber);
123
+
124
+ deleteFileAfterDelay(tmpFilePath, 10000);
125
+
126
+ return result;
127
+ } catch (error) {
128
+ if (tmpFilePath && fs.existsSync(tmpFilePath)) {
129
+ fs.unlinkSync(tmpFilePath);
130
+ }
131
+ throw error;
132
+ }
133
+ }
134
+
135
+ const handler = async (req, res) => {
136
+ try {
137
+ const { image_url, scale, key } = req.query;
138
+
139
+ if (!image_url) {
140
+ return res.status(400).json({
141
+ success: false,
142
+ error: 'Missing required parameter: image_url'
143
+ });
144
+ }
145
+
146
+ if (!scale) {
147
+ return res.status(400).json({
148
+ success: false,
149
+ error: 'Missing required parameter: scale'
150
+ });
151
+ }
152
+
153
+ const scaleNum = parseInt(scale);
154
+ if (![2, 4, 8, 16].includes(scaleNum)) {
155
+ return res.status(400).json({
156
+ success: false,
157
+ error: 'Scale must be 2, 4, 8, or 16'
158
+ });
159
+ }
160
+
161
+ const result = await upscaleImage(image_url, scaleNum);
162
+
163
+ return res.json({
164
+ author: "Herza",
165
+ success: true,
166
+ data: result
167
+ });
168
+
169
+ } catch (error) {
170
+ res.status(500).json({
171
+ success: false,
172
+ error: error.message,
173
+ timestamp: new Date().toISOString()
174
+ });
175
+ }
176
+ };
177
+
178
+ module.exports = {
179
+ name: 'Image Upscaler',
180
+ description: 'Upscale images to 2x, 4x, 8x, or 16x resolution',
181
+ type: 'GET',
182
+ routes: ['api/tools/upscale'],
183
+ tags: ['image', 'upscale', 'enhancement'],
184
+ parameters: ['image_url', 'scale', 'key'],
185
+ limit: 5,
186
+ enabled: true,
187
+ main: ['tools'],
188
+ handler
189
+ };