natureco-cli 1.0.29 → 1.0.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "1.0.29",
3
+ "version": "1.0.31",
4
4
  "description": "NatureCo AI Bot Terminal Interface",
5
5
  "main": "bin/natureco.js",
6
6
  "bin": {
@@ -2,12 +2,55 @@ const chalk = require('chalk');
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
4
  const os = require('os');
5
- const { spawn } = require('child_process');
5
+ const { spawn, execSync } = require('child_process');
6
6
 
7
7
  const PID_FILE = path.join(os.homedir(), '.natureco', 'gateway.pid');
8
8
  const LOG_FILE = path.join(os.homedir(), '.natureco', 'gateway.log');
9
9
 
10
+ // WhatsApp imports
11
+ let makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, Browsers;
12
+ const pino = require('pino');
13
+ const logger = pino({ level: 'silent' });
14
+
15
+ // Lazy load Baileys
16
+ function loadBaileys() {
17
+ if (!makeWASocket) {
18
+ const baileys = require('@whiskeysockets/baileys');
19
+ makeWASocket = baileys.default;
20
+ useMultiFileAuthState = baileys.useMultiFileAuthState;
21
+ DisconnectReason = baileys.DisconnectReason;
22
+ fetchLatestBaileysVersion = baileys.fetchLatestBaileysVersion;
23
+ Browsers = baileys.Browsers;
24
+ }
25
+ }
26
+
27
+ // Log helper
28
+ function log(module, message, color = 'white') {
29
+ const timestamp = new Date().toISOString().replace('T', ' ').substring(0, 19);
30
+ const logLine = `[${timestamp}] [${module}] ${message}`;
31
+
32
+ // Console output with color
33
+ const colorFn = chalk[color] || chalk.white;
34
+ console.log(colorFn(logLine));
35
+
36
+ // File output (no color)
37
+ try {
38
+ const dir = path.dirname(LOG_FILE);
39
+ if (!fs.existsSync(dir)) {
40
+ fs.mkdirSync(dir, { recursive: true });
41
+ }
42
+ fs.appendFileSync(LOG_FILE, logLine + '\n', 'utf-8');
43
+ } catch (err) {
44
+ // Ignore file write errors
45
+ }
46
+ }
47
+
10
48
  async function gatewayServer(action) {
49
+ // Check if running as background worker
50
+ if (process.argv.includes('--gateway-worker')) {
51
+ return runGatewayWorker();
52
+ }
53
+
11
54
  if (!action || action === 'start') {
12
55
  return startGateway();
13
56
  }
@@ -20,12 +63,16 @@ async function gatewayServer(action) {
20
63
  return statusGateway();
21
64
  }
22
65
 
66
+ if (action === 'logs') {
67
+ return showLogs();
68
+ }
69
+
23
70
  console.log(chalk.red('\n❌ Unknown action\n'));
24
- console.log(chalk.gray('Available actions: start, stop, status\n'));
71
+ console.log(chalk.gray('Available actions: start, stop, status, logs\n'));
25
72
  process.exit(1);
26
73
  }
27
74
 
28
- function startGateway() {
75
+ async function startGateway() {
29
76
  // Check if already running
30
77
  if (fs.existsSync(PID_FILE)) {
31
78
  const pid = fs.readFileSync(PID_FILE, 'utf-8').trim();
@@ -41,13 +88,13 @@ function startGateway() {
41
88
  }
42
89
  }
43
90
 
44
- console.log(chalk.green('\n🚀 Starting WebSocket Gateway...\n'));
91
+ console.log(chalk.green('\n🚀 Starting NatureCo Gateway...\n'));
45
92
 
46
- // Start gateway server as detached process
47
- const serverPath = path.join(__dirname, '..', 'utils', 'gateway-ws.js');
48
- const child = spawn('node', [serverPath], {
93
+ // Start as detached background process
94
+ const child = spawn(process.execPath, [__filename, '--gateway-worker'], {
49
95
  detached: true,
50
96
  stdio: 'ignore',
97
+ windowsHide: true,
51
98
  });
52
99
 
53
100
  child.unref();
@@ -59,13 +106,162 @@ function startGateway() {
59
106
  }
60
107
  fs.writeFileSync(PID_FILE, String(child.pid), 'utf-8');
61
108
 
62
- console.log(chalk.green('✅ Gateway started'));
63
- console.log(chalk.cyan('Port:'), chalk.white('3847'));
109
+ console.log(chalk.green('✅ Gateway started in background'));
64
110
  console.log(chalk.cyan('PID:'), chalk.white(child.pid));
65
- console.log(chalk.gray('\nConnect with WebSocket client:'));
66
- console.log(chalk.white('ws://localhost:3847'));
67
- console.log(chalk.gray('\nSend JSON: { "botId": "...", "message": "...", "apiKey": "..." }'));
68
- console.log(chalk.gray('\nStop with: natureco gateway stop\n'));
111
+ console.log(chalk.cyan('Logs:'), chalk.white(LOG_FILE));
112
+ console.log(chalk.gray('\nView logs: natureco gateway logs'));
113
+ console.log(chalk.gray('Check status: natureco gateway status'));
114
+ console.log(chalk.gray('Stop gateway: natureco gateway stop\n'));
115
+
116
+ process.exit(0);
117
+ }
118
+
119
+ async function runGatewayWorker() {
120
+ // This runs in the background
121
+ log('gateway', 'Starting NatureCo Gateway...', 'green');
122
+
123
+ // Load config
124
+ const { getConfig } = require('../utils/config');
125
+ const config = getConfig();
126
+
127
+ if (!config || !config.apiKey) {
128
+ log('gateway', 'No API key found. Run "natureco login" first.', 'red');
129
+ process.exit(1);
130
+ }
131
+
132
+ // Start WhatsApp if configured
133
+ if (config.whatsappConnected && config.whatsappBotId) {
134
+ const sessionDir = path.join(os.homedir(), '.natureco', 'whatsapp-sessions', config.whatsappBotId);
135
+
136
+ if (fs.existsSync(sessionDir)) {
137
+ const phone = config.whatsappPhone?.split(':')[0].replace('@s.whatsapp.net', '') || 'unknown';
138
+ log('whatsapp', `starting provider (+${phone})`, 'cyan');
139
+ startWhatsAppProvider(sessionDir, config);
140
+ } else {
141
+ log('whatsapp', 'session not found, skipping', 'yellow');
142
+ }
143
+ } else {
144
+ log('whatsapp', 'not configured, skipping', 'gray');
145
+ }
146
+
147
+ // Health check every 60 seconds
148
+ setInterval(() => {
149
+ log('gateway', 'health check: OK', 'gray');
150
+ }, 60000);
151
+
152
+ log('gateway', 'Gateway running in background', 'green');
153
+
154
+ // Handle shutdown
155
+ process.on('SIGINT', () => {
156
+ log('gateway', 'Shutting down...', 'yellow');
157
+ if (fs.existsSync(PID_FILE)) {
158
+ fs.unlinkSync(PID_FILE);
159
+ }
160
+ process.exit(0);
161
+ });
162
+
163
+ process.on('SIGTERM', () => {
164
+ log('gateway', 'Shutting down...', 'yellow');
165
+ if (fs.existsSync(PID_FILE)) {
166
+ fs.unlinkSync(PID_FILE);
167
+ }
168
+ process.exit(0);
169
+ });
170
+ }
171
+
172
+ async function startWhatsAppProvider(sessionDir, config) {
173
+ try {
174
+ loadBaileys();
175
+
176
+ const { state, saveCreds } = await useMultiFileAuthState(sessionDir);
177
+ const { version } = await fetchLatestBaileysVersion();
178
+
179
+ const sock = makeWASocket({
180
+ version,
181
+ auth: state,
182
+ printQRInTerminal: false,
183
+ logger: logger,
184
+ browser: Browsers.ubuntu('Chrome'),
185
+ connectTimeoutMs: 60000,
186
+ defaultQueryTimeoutMs: 60000,
187
+ keepAliveIntervalMs: 10000,
188
+ retryRequestDelayMs: 2000,
189
+ });
190
+
191
+ sock.ev.on('connection.update', async (update) => {
192
+ const { connection, lastDisconnect } = update;
193
+
194
+ if (connection === 'close') {
195
+ const statusCode = lastDisconnect?.error?.output?.statusCode;
196
+
197
+ if (statusCode === 515 || statusCode === 408) {
198
+ log('whatsapp', 'connection lost, reconnecting in 10s...', 'yellow');
199
+ setTimeout(() => startWhatsAppProvider(sessionDir, config), 10000);
200
+ return;
201
+ } else if (statusCode === 401) {
202
+ log('whatsapp', 'session expired, please reconnect', 'red');
203
+ } else {
204
+ log('whatsapp', `disconnected (code: ${statusCode}), reconnecting in 10s...`, 'yellow');
205
+ setTimeout(() => startWhatsAppProvider(sessionDir, config), 10000);
206
+ }
207
+ } else if (connection === 'open') {
208
+ const phone = sock.user?.id?.split(':')[0].replace('@s.whatsapp.net', '') || 'unknown';
209
+ log('whatsapp', `Listening for inbound messages.`, 'cyan');
210
+ }
211
+ });
212
+
213
+ sock.ev.on('messages.upsert', async ({ messages }) => {
214
+ for (const msg of messages) {
215
+ if (msg.key.fromMe) continue;
216
+
217
+ const sender = msg.key.remoteJid?.split('@')[0].split(':')[0];
218
+ const allowedNumbers = config.whatsappAllowedNumbers || [];
219
+
220
+ // Access control
221
+ if (allowedNumbers.length > 0 && !allowedNumbers.includes(sender)) {
222
+ log('whatsapp', `blocked message from +${sender} (not in allowed list)`, 'yellow');
223
+ continue;
224
+ }
225
+
226
+ const messageText = msg.message?.conversation ||
227
+ msg.message?.extendedTextMessage?.text ||
228
+ '';
229
+
230
+ if (messageText) {
231
+ const ownNumber = sock.user?.id?.split(':')[0].replace('@s.whatsapp.net', '') || 'unknown';
232
+ log('whatsapp', `Inbound message +${sender} -> +${ownNumber}`, 'cyan');
233
+ log('whatsapp', `Message: "${messageText.substring(0, 100)}${messageText.length > 100 ? '...' : ''}"`, 'gray');
234
+
235
+ try {
236
+ const { sendMessage } = require('../utils/api');
237
+ log('whatsapp', 'Sending to NatureCo API...', 'cyan');
238
+
239
+ const response = await sendMessage(config.apiKey, config.whatsappBotId, messageText, null, '');
240
+ const reply = response?.reply || response?.message || '';
241
+
242
+ if (reply) {
243
+ log('whatsapp', `API response: "${reply.substring(0, 100)}${reply.length > 100 ? '...' : ''}"`, 'gray');
244
+ log('whatsapp', 'Sending reply...', 'cyan');
245
+
246
+ await sock.sendMessage(msg.key.remoteJid, { text: reply });
247
+ log('whatsapp', `Reply sent (${reply.length} chars)`, 'green');
248
+ } else {
249
+ log('whatsapp', 'No reply from API', 'yellow');
250
+ }
251
+ } catch (err) {
252
+ log('whatsapp', `API error: ${err.message}`, 'red');
253
+ }
254
+ }
255
+ }
256
+ });
257
+
258
+ sock.ev.on('creds.update', saveCreds);
259
+
260
+ } catch (err) {
261
+ log('whatsapp', `Failed to start: ${err.message}`, 'red');
262
+ log('whatsapp', 'Retrying in 10s...', 'yellow');
263
+ setTimeout(() => startWhatsAppProvider(sessionDir, config), 10000);
264
+ }
69
265
  }
70
266
 
71
267
  function stopGateway() {
@@ -74,14 +270,52 @@ function stopGateway() {
74
270
  return;
75
271
  }
76
272
 
77
- const pid = fs.readFileSync(PID_FILE, 'utf-8').trim();
273
+ const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8').trim());
78
274
 
79
275
  try {
276
+ // Try graceful shutdown first
80
277
  process.kill(pid, 'SIGTERM');
81
- fs.unlinkSync(PID_FILE);
82
- console.log(chalk.green('\n✅ Gateway stopped\n'));
278
+
279
+ // Wait a bit and check if process is still running
280
+ setTimeout(() => {
281
+ try {
282
+ process.kill(pid, 0);
283
+ // Process still running, force kill
284
+ if (process.platform === 'win32') {
285
+ try {
286
+ execSync(`taskkill /F /PID ${pid}`, { stdio: 'ignore' });
287
+ console.log(chalk.green('\n✅ Gateway stopped (force killed)\n'));
288
+ } catch (err) {
289
+ console.log(chalk.red(`\n❌ Failed to stop gateway: ${err.message}\n`));
290
+ }
291
+ } else {
292
+ process.kill(pid, 'SIGKILL');
293
+ console.log(chalk.green('\n✅ Gateway stopped (force killed)\n'));
294
+ }
295
+ } catch {
296
+ // Process already stopped
297
+ console.log(chalk.green('\n✅ Gateway stopped\n'));
298
+ }
299
+
300
+ // Remove PID file
301
+ if (fs.existsSync(PID_FILE)) {
302
+ fs.unlinkSync(PID_FILE);
303
+ }
304
+ }, 1000);
305
+
83
306
  } catch (err) {
84
- console.log(chalk.red(`\n❌ Failed to stop gateway: ${err.message}\n`));
307
+ // Process not found, try force kill on Windows
308
+ if (process.platform === 'win32') {
309
+ try {
310
+ execSync(`taskkill /F /PID ${pid}`, { stdio: 'ignore' });
311
+ console.log(chalk.green('\n✅ Gateway stopped\n'));
312
+ } catch {
313
+ console.log(chalk.yellow('\n⚠️ Gateway process not found\n'));
314
+ }
315
+ } else {
316
+ console.log(chalk.yellow('\n⚠️ Gateway process not found\n'));
317
+ }
318
+
85
319
  // Remove stale PID file
86
320
  if (fs.existsSync(PID_FILE)) {
87
321
  fs.unlinkSync(PID_FILE);
@@ -101,13 +335,12 @@ function statusGateway() {
101
335
  process.kill(pid, 0);
102
336
  console.log(chalk.green('\n✅ Gateway running\n'));
103
337
  console.log(chalk.cyan('PID:'), chalk.white(pid));
104
- console.log(chalk.cyan('Port:'), chalk.white('3847'));
105
- console.log(chalk.cyan('WebSocket:'), chalk.white('ws://localhost:3847'));
338
+ console.log(chalk.cyan('Logs:'), chalk.white(LOG_FILE));
106
339
 
107
340
  // Show log tail if exists
108
341
  if (fs.existsSync(LOG_FILE)) {
109
- const logs = fs.readFileSync(LOG_FILE, 'utf-8').split('\n').slice(-5).join('\n');
110
- console.log(chalk.gray('\nRecent logs:'));
342
+ const logs = fs.readFileSync(LOG_FILE, 'utf-8').split('\n').filter(l => l.trim()).slice(-10).join('\n');
343
+ console.log(chalk.gray('\nRecent logs (last 10):'));
111
344
  console.log(chalk.white(logs));
112
345
  }
113
346
  console.log('');
@@ -117,4 +350,14 @@ function statusGateway() {
117
350
  }
118
351
  }
119
352
 
353
+ function showLogs() {
354
+ if (!fs.existsSync(LOG_FILE)) {
355
+ console.log(chalk.gray('\n⚠️ No logs found\n'));
356
+ return;
357
+ }
358
+
359
+ const logs = fs.readFileSync(LOG_FILE, 'utf-8');
360
+ console.log(logs);
361
+ }
362
+
120
363
  module.exports = gatewayServer;
@@ -1,12 +1,35 @@
1
1
  const chalk = require('chalk');
2
2
  const boxen = require('boxen');
3
3
  const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
4
6
  const packageJson = require('../../package.json');
5
7
  const { getConfig, CONFIG_FILE } = require('../utils/config');
6
8
  const { getSkills } = require('../utils/skills');
7
9
  const { getMcpServers } = require('../utils/mcp');
8
10
 
9
- async function gateway() {
11
+ // WhatsApp imports
12
+ let makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, Browsers;
13
+ const pino = require('pino');
14
+ const logger = pino({ level: 'silent' });
15
+
16
+ // Lazy load Baileys
17
+ function loadBaileys() {
18
+ if (!makeWASocket) {
19
+ const baileys = require('@whiskeysockets/baileys');
20
+ makeWASocket = baileys.default;
21
+ useMultiFileAuthState = baileys.useMultiFileAuthState;
22
+ DisconnectReason = baileys.DisconnectReason;
23
+ fetchLatestBaileysVersion = baileys.fetchLatestBaileysVersion;
24
+ Browsers = baileys.Browsers;
25
+ }
26
+ }
27
+
28
+ async function gateway(action) {
29
+ if (action === 'start') {
30
+ return startGateway();
31
+ }
32
+
10
33
  // Config kontrolü - yoksa veya apiKey yoksa setup çalıştır
11
34
  if (!fs.existsSync(CONFIG_FILE)) {
12
35
  const setup = require('./setup');
@@ -98,6 +121,9 @@ async function gateway() {
98
121
  console.log(chalk.yellow(' natureco config'));
99
122
  console.log(chalk.gray(' Ayarları görüntüle ve düzenle\n'));
100
123
 
124
+ console.log(chalk.yellow(' natureco gateway start'));
125
+ console.log(chalk.gray(' Gateway\'i başlat (WhatsApp dahil)\n'));
126
+
101
127
  console.log(chalk.yellow(' natureco help'));
102
128
  console.log(chalk.gray(' Tüm komutları ve örnekleri göster\n'));
103
129
 
@@ -110,4 +136,123 @@ async function gateway() {
110
136
  console.log('');
111
137
  }
112
138
 
139
+ async function startGateway() {
140
+ const config = getConfig();
141
+
142
+ if (!config || !config.apiKey) {
143
+ console.log(chalk.red('\n❌ Not logged in. Run "natureco login" first.\n'));
144
+ process.exit(1);
145
+ }
146
+
147
+ console.log(chalk.green.bold('\n🚀 NatureCo Gateway Starting...\n'));
148
+ console.log(chalk.gray('─'.repeat(60)));
149
+ console.log('');
150
+
151
+ // WhatsApp provider başlat
152
+ if (config.whatsappConnected && config.whatsappBotId) {
153
+ const sessionDir = path.join(os.homedir(), '.natureco', 'whatsapp-sessions', config.whatsappBotId);
154
+
155
+ if (fs.existsSync(sessionDir)) {
156
+ console.log(chalk.cyan('[whatsapp]'), chalk.white(`starting provider (${config.whatsappPhone || 'unknown'})`));
157
+ await startWhatsAppProvider(sessionDir, config);
158
+ } else {
159
+ console.log(chalk.yellow('[whatsapp]'), chalk.gray('session not found, skipping'));
160
+ }
161
+ }
162
+
163
+ console.log('');
164
+ console.log(chalk.gray('─'.repeat(60)));
165
+ console.log(chalk.green('\n✅ Gateway running. Press Ctrl+C to stop.\n'));
166
+
167
+ // Keep process alive
168
+ process.on('SIGINT', () => {
169
+ console.log(chalk.yellow('\n\n⚠️ Gateway stopped\n'));
170
+ process.exit(0);
171
+ });
172
+ }
173
+
174
+ async function startWhatsAppProvider(sessionDir, config) {
175
+ try {
176
+ loadBaileys();
177
+
178
+ const { state, saveCreds } = await useMultiFileAuthState(sessionDir);
179
+ const { version } = await fetchLatestBaileysVersion();
180
+
181
+ const sock = makeWASocket({
182
+ version,
183
+ auth: state,
184
+ printQRInTerminal: false,
185
+ logger: logger,
186
+ browser: Browsers.ubuntu('Chrome'),
187
+ connectTimeoutMs: 60000,
188
+ defaultQueryTimeoutMs: 60000,
189
+ keepAliveIntervalMs: 10000,
190
+ retryRequestDelayMs: 2000,
191
+ });
192
+
193
+ sock.ev.on('connection.update', async (update) => {
194
+ const { connection, lastDisconnect } = update;
195
+
196
+ if (connection === 'close') {
197
+ const statusCode = lastDisconnect?.error?.output?.statusCode;
198
+
199
+ if (statusCode === 515 || statusCode === 408) {
200
+ console.log(chalk.yellow('[whatsapp]'), chalk.gray('reconnecting...'));
201
+ setTimeout(() => startWhatsAppProvider(sessionDir, config), 2000);
202
+ return;
203
+ } else if (statusCode === 401) {
204
+ console.log(chalk.red('[whatsapp]'), chalk.gray('session expired'));
205
+ } else {
206
+ console.log(chalk.red('[whatsapp]'), chalk.gray(`disconnected (${statusCode})`));
207
+ }
208
+ } else if (connection === 'open') {
209
+ const phone = sock.user?.id?.split(':')[0].replace('@s.whatsapp.net', '') || 'unknown';
210
+ console.log(chalk.cyan('[whatsapp]'), chalk.white(`Listening for inbound messages.`));
211
+ }
212
+ });
213
+
214
+ sock.ev.on('messages.upsert', async ({ messages }) => {
215
+ for (const msg of messages) {
216
+ if (msg.key.fromMe) continue;
217
+
218
+ const sender = msg.key.remoteJid?.split('@')[0].split(':')[0];
219
+ const allowedNumbers = config.whatsappAllowedNumbers || [];
220
+
221
+ if (allowedNumbers.length > 0 && !allowedNumbers.includes(sender)) {
222
+ continue;
223
+ }
224
+
225
+ const messageText = msg.message?.conversation ||
226
+ msg.message?.extendedTextMessage?.text ||
227
+ '';
228
+
229
+ if (messageText) {
230
+ const ownNumber = sock.user?.id?.split(':')[0].replace('@s.whatsapp.net', '') || 'unknown';
231
+ console.log(chalk.cyan('[whatsapp]'), chalk.white(`Inbound message +${sender} -> +${ownNumber}`));
232
+
233
+ try {
234
+ const { sendMessage } = require('../utils/api');
235
+ console.log(chalk.cyan('[whatsapp]'), chalk.gray('Sending reply...'));
236
+
237
+ const response = await sendMessage(config.apiKey, config.whatsappBotId, messageText, null, '');
238
+ const reply = response?.reply || response?.message || '';
239
+
240
+ if (reply) {
241
+ await sock.sendMessage(msg.key.remoteJid, { text: reply });
242
+ console.log(chalk.cyan('[whatsapp]'), chalk.green(`Reply sent (${reply.length} chars)`));
243
+ }
244
+ } catch (err) {
245
+ console.log(chalk.red('[whatsapp]'), chalk.gray(`error: ${err.message}`));
246
+ }
247
+ }
248
+ }
249
+ });
250
+
251
+ sock.ev.on('creds.update', saveCreds);
252
+
253
+ } catch (err) {
254
+ console.log(chalk.red('[whatsapp]'), chalk.gray(`failed to start: ${err.message}`));
255
+ }
256
+ }
257
+
113
258
  module.exports = gateway;
@@ -114,7 +114,7 @@ async function connectWhatsApp() {
114
114
  .map(n => n.trim())
115
115
  .filter(n => n.length > 0);
116
116
 
117
- // Start connection
117
+ // Start connection (only for QR code)
118
118
  await startWhatsAppConnection(sessionDir, botId, selectedBot, config, allowedNumbersList);
119
119
  }
120
120
 
@@ -209,51 +209,17 @@ async function startWhatsAppConnection(sessionDir, botId, selectedBot, config, a
209
209
  }
210
210
 
211
211
  console.log(chalk.green('\n✅ Kurulum tamamlandı!\n'));
212
- console.log(chalk.gray('Botunuz WhatsApp\'ta aktif.\n'));
212
+ console.log(chalk.yellow('Gateway ile başlatmak için:'), chalk.cyan('natureco gateway start'));
213
+ console.log(chalk.gray('Gateway, WhatsApp\'ı otomatik olarak başlatacak.\n'));
213
214
 
214
- // Keep process alive for a moment then exit
215
+ // Exit after setup
215
216
  setTimeout(() => {
216
217
  process.exit(0);
217
218
  }, 2000);
218
219
  }
219
220
  });
220
221
 
221
- // Message handler with access control
222
- sock.ev.on('messages.upsert', async ({ messages }) => {
223
- for (const msg of messages) {
224
- if (msg.key.fromMe) continue; // kendi mesajları yoksay
225
-
226
- const sender = msg.key.remoteJid?.split('@')[0].split(':')[0];
227
- const allowedNumbers = config.whatsappAllowedNumbers || [];
228
-
229
- // İzin listesi doluysa kontrol et
230
- if (allowedNumbers.length > 0 && !allowedNumbers.includes(sender)) {
231
- console.log(chalk.yellow(`⚠️ İzinsiz numara: ${sender}`));
232
- continue; // izinsiz numara, yoksay
233
- }
234
-
235
- // Mesaj içeriğini al
236
- const messageText = msg.message?.conversation ||
237
- msg.message?.extendedTextMessage?.text ||
238
- '';
239
-
240
- if (messageText) {
241
- console.log(chalk.cyan(`\n📱 ${sender}:`), chalk.white(messageText));
242
-
243
- try {
244
- const response = await sendMessage(config.apiKey, config.defaultBotId, messageText, null, '');
245
- const reply = response?.reply || response?.message || '';
246
-
247
- if (reply) {
248
- await sock.sendMessage(msg.key.remoteJid, { text: reply });
249
- console.log(chalk.green(`✅ Cevap gönderildi: ${reply.substring(0, 50)}...`));
250
- }
251
- } catch (err) {
252
- console.log(chalk.red('❌ API hatası:', err.message));
253
- }
254
- }
255
- }
256
- });
222
+ // Message handler removed - gateway handles this now
257
223
 
258
224
  // Save credentials on update
259
225
  sock.ev.on('creds.update', saveCreds);