natureco-cli 2.8.0 → 2.8.2

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": "2.8.0",
3
+ "version": "2.8.2",
4
4
  "description": "NatureCo AI Bot Terminal Interface",
5
5
  "main": "bin/natureco.js",
6
6
  "bin": {
@@ -211,7 +211,7 @@ body::before{
211
211
  <div class="header-bot-name" id="header-bot-name">Nature Bot</div>
212
212
  <div class="header-bot-model" id="header-bot-model">NatureCo</div>
213
213
  </div>
214
- <div class="version-badge" id="version-badge">v2.8.0</div>
214
+ <div class="version-badge" id="version-badge">v2.8.2</div>
215
215
  </div>
216
216
  <div class="messages" id="messages"></div>
217
217
  <div class="input-area">
@@ -341,7 +341,7 @@ function dashboard(action) {
341
341
  apiKey: cfg.apiKey,
342
342
  defaultBot: cfg.defaultBot,
343
343
  defaultBotId: cfg.defaultBotId,
344
- version: 'v2.8.0',
344
+ version: 'v2.8.2',
345
345
  bots: cfg.bots || [],
346
346
  telegramToken: cfg.telegramToken || null,
347
347
  whatsappConnected: cfg.whatsappConnected || false,
@@ -10,7 +10,6 @@ const LOG_FILE = path.join(os.homedir(), '.natureco', 'gateway.log');
10
10
  // WhatsApp imports
11
11
  let makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, Browsers;
12
12
  const pino = require('pino');
13
- const logger = pino({ level: 'silent' });
14
13
 
15
14
  // Lazy load Baileys
16
15
  function loadBaileys() {
@@ -128,7 +127,7 @@ async function startGateway() {
128
127
 
129
128
  async function runGatewayWorker() {
130
129
  // This runs in the background
131
- log('gateway', 'Starting NatureCo Gateway v2.8.0...', 'green');
130
+ log('gateway', 'Starting NatureCo Gateway v2.8.2...', 'green');
132
131
 
133
132
  // Load config
134
133
  const { getConfig } = require('../utils/config');
@@ -139,6 +138,10 @@ async function runGatewayWorker() {
139
138
  process.exit(1);
140
139
  }
141
140
 
141
+ // Store provider instances globally for HTTP endpoint
142
+ global.whatsappSock = null;
143
+ global.telegramBot = null;
144
+
142
145
  // Start WhatsApp if configured
143
146
  if (config.whatsappConnected && config.whatsappBotId) {
144
147
  const sessionDir = path.join(os.homedir(), '.natureco', 'whatsapp-sessions', config.whatsappBotId);
@@ -162,6 +165,9 @@ async function runGatewayWorker() {
162
165
  log('telegram', 'not configured, skipping', 'gray');
163
166
  }
164
167
 
168
+ // Start HTTP server for message sending
169
+ startHttpServer();
170
+
165
171
  // Health check every 60 seconds
166
172
  setInterval(() => {
167
173
  log('gateway', 'health check: OK', 'gray');
@@ -201,7 +207,7 @@ async function startWhatsAppProvider(sessionDir, config) {
201
207
  version,
202
208
  auth: state,
203
209
  printQRInTerminal: false,
204
- logger: logger,
210
+ logger: pino({ level: 'silent' }),
205
211
  browser: Browsers.ubuntu('Chrome'),
206
212
  connectTimeoutMs: 60000,
207
213
  defaultQueryTimeoutMs: 60000,
@@ -236,6 +242,9 @@ async function startWhatsAppProvider(sessionDir, config) {
236
242
  log('whatsapp', `Connected successfully`, 'green');
237
243
  log('whatsapp', `Listening for inbound messages.`, 'cyan');
238
244
  log('whatsapp', `Phone: +${phone}`, 'gray');
245
+
246
+ // Store socket globally for HTTP endpoint
247
+ global.whatsappSock = sock;
239
248
  }
240
249
  });
241
250
 
@@ -446,11 +455,111 @@ async function startTelegramProvider(config) {
446
455
  log('telegram', `Polling error: ${error.message}`, 'red');
447
456
  });
448
457
 
458
+ // Store bot globally for HTTP endpoint
459
+ global.telegramBot = bot;
460
+
449
461
  } catch (err) {
450
462
  log('telegram', `Failed to start: ${err.message}`, 'red');
451
463
  }
452
464
  }
453
465
 
466
+ function startHttpServer() {
467
+ const http = require('http');
468
+
469
+ const server = http.createServer(async (req, res) => {
470
+ // CORS headers
471
+ res.setHeader('Access-Control-Allow-Origin', '*');
472
+ res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
473
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
474
+
475
+ if (req.method === 'OPTIONS') {
476
+ res.writeHead(200);
477
+ res.end();
478
+ return;
479
+ }
480
+
481
+ if (req.method === 'POST' && req.url === '/send') {
482
+ let body = '';
483
+
484
+ req.on('data', chunk => {
485
+ body += chunk.toString();
486
+ });
487
+
488
+ req.on('end', async () => {
489
+ try {
490
+ const { channel, target, message } = JSON.parse(body);
491
+
492
+ if (!channel || !target || !message) {
493
+ res.writeHead(400, { 'Content-Type': 'application/json' });
494
+ res.end(JSON.stringify({ error: 'Missing required fields: channel, target, message' }));
495
+ return;
496
+ }
497
+
498
+ if (channel === 'whatsapp') {
499
+ if (!global.whatsappSock) {
500
+ res.writeHead(503, { 'Content-Type': 'application/json' });
501
+ res.end(JSON.stringify({ error: 'WhatsApp not connected' }));
502
+ return;
503
+ }
504
+
505
+ const normalizedTarget = target.replace(/[^\d]/g, '');
506
+ const jid = `${normalizedTarget}@s.whatsapp.net`;
507
+
508
+ await global.whatsappSock.sendMessage(jid, { text: message });
509
+
510
+ log('http', `WhatsApp message sent to ${target}`, 'green');
511
+
512
+ res.writeHead(200, { 'Content-Type': 'application/json' });
513
+ res.end(JSON.stringify({ success: true, channel: 'whatsapp', target }));
514
+
515
+ } else if (channel === 'telegram') {
516
+ if (!global.telegramBot) {
517
+ res.writeHead(503, { 'Content-Type': 'application/json' });
518
+ res.end(JSON.stringify({ error: 'Telegram not connected' }));
519
+ return;
520
+ }
521
+
522
+ const chatId = target.trim();
523
+ if (!/^-?\d+$/.test(chatId)) {
524
+ res.writeHead(400, { 'Content-Type': 'application/json' });
525
+ res.end(JSON.stringify({ error: 'Invalid Telegram chat ID' }));
526
+ return;
527
+ }
528
+
529
+ await global.telegramBot.sendMessage(chatId, message);
530
+
531
+ log('http', `Telegram message sent to ${target}`, 'green');
532
+
533
+ res.writeHead(200, { 'Content-Type': 'application/json' });
534
+ res.end(JSON.stringify({ success: true, channel: 'telegram', target }));
535
+
536
+ } else {
537
+ res.writeHead(400, { 'Content-Type': 'application/json' });
538
+ res.end(JSON.stringify({ error: 'Invalid channel. Use "whatsapp" or "telegram"' }));
539
+ }
540
+
541
+ } catch (err) {
542
+ log('http', `Error: ${err.message}`, 'red');
543
+ res.writeHead(500, { 'Content-Type': 'application/json' });
544
+ res.end(JSON.stringify({ error: err.message }));
545
+ }
546
+ });
547
+
548
+ } else {
549
+ res.writeHead(404, { 'Content-Type': 'application/json' });
550
+ res.end(JSON.stringify({ error: 'Not found' }));
551
+ }
552
+ });
553
+
554
+ server.listen(3847, '127.0.0.1', () => {
555
+ log('http', 'HTTP server listening on http://127.0.0.1:3847', 'green');
556
+ });
557
+
558
+ server.on('error', (err) => {
559
+ log('http', `Server error: ${err.message}`, 'red');
560
+ });
561
+ }
562
+
454
563
  function stopGateway() {
455
564
  if (!fs.existsSync(PID_FILE)) {
456
565
  console.log(chalk.gray('\n⚠️ Gateway not running\n'));
@@ -5,6 +5,7 @@ const os = require('os');
5
5
  const { getConfig } = require('../utils/config');
6
6
 
7
7
  const PID_FILE = path.join(os.homedir(), '.natureco', 'gateway.pid');
8
+ const GATEWAY_HTTP_URL = 'http://127.0.0.1:3847/send';
8
9
 
9
10
  async function message(args) {
10
11
  // Parse arguments
@@ -54,128 +55,42 @@ async function message(args) {
54
55
 
55
56
  const config = getConfig();
56
57
 
57
- if (channel === 'whatsapp') {
58
- await sendWhatsAppMessage(target, messageText, config);
59
- } else if (channel === 'telegram') {
60
- await sendTelegramMessage(target, messageText, config);
61
- }
62
- }
63
-
64
- async function sendWhatsAppMessage(target, messageText, config) {
65
- if (!config.whatsappConnected || !config.whatsappBotId) {
58
+ // Validate channel configuration
59
+ if (channel === 'whatsapp' && (!config.whatsappConnected || !config.whatsappBotId)) {
66
60
  console.log(chalk.red('\n❌ WhatsApp bağlı değil\n'));
67
61
  console.log(chalk.yellow('Önce WhatsApp\'ı bağlayın:'), chalk.cyan('natureco whatsapp connect\n'));
68
62
  process.exit(1);
69
63
  }
70
64
 
71
- console.log(chalk.yellow('\n⏳ WhatsApp mesajı gönderiliyor...\n'));
72
-
73
- try {
74
- // Lazy load Baileys
75
- const baileys = require('@whiskeysockets/baileys');
76
- const makeWASocket = baileys.default;
77
- const useMultiFileAuthState = baileys.useMultiFileAuthState;
78
- const fetchLatestBaileysVersion = baileys.fetchLatestBaileysVersion;
79
- const Browsers = baileys.Browsers;
80
- const pino = require('pino');
81
- const logger = pino({ level: 'silent' });
82
-
83
- const sessionDir = path.join(os.homedir(), '.natureco', 'whatsapp-sessions', config.whatsappBotId);
84
-
85
- if (!fs.existsSync(sessionDir)) {
86
- console.log(chalk.red('❌ WhatsApp session bulunamadı\n'));
87
- console.log(chalk.yellow('Önce WhatsApp\'ı bağlayın:'), chalk.cyan('natureco whatsapp connect\n'));
88
- process.exit(1);
89
- }
90
-
91
- const { state } = await useMultiFileAuthState(sessionDir);
92
- const { version } = await fetchLatestBaileysVersion();
93
-
94
- const sock = makeWASocket({
95
- version,
96
- auth: state,
97
- printQRInTerminal: false,
98
- logger: logger,
99
- browser: Browsers.ubuntu('Chrome'),
100
- connectTimeoutMs: 30000,
101
- });
102
-
103
- // Wait for connection
104
- await new Promise((resolve, reject) => {
105
- const timeout = setTimeout(() => {
106
- reject(new Error('Connection timeout'));
107
- }, 30000);
108
-
109
- sock.ev.on('connection.update', (update) => {
110
- if (update.connection === 'open') {
111
- clearTimeout(timeout);
112
- resolve();
113
- } else if (update.connection === 'close') {
114
- clearTimeout(timeout);
115
- reject(new Error('Connection failed'));
116
- }
117
- });
118
- });
119
-
120
- // Normalize phone number
121
- const normalizedTarget = target.replace(/[^\d]/g, '');
122
- const jid = `${normalizedTarget}@s.whatsapp.net`;
123
-
124
- // Send message
125
- await sock.sendMessage(jid, { text: messageText });
126
-
127
- console.log(chalk.green('✅ Mesaj gönderildi!\n'));
128
- console.log(chalk.cyan('Hedef:'), chalk.white(target));
129
- console.log(chalk.cyan('Mesaj:'), chalk.white(messageText));
130
- console.log('');
131
-
132
- // Close connection
133
- setTimeout(() => {
134
- sock.end();
135
- process.exit(0);
136
- }, 2000);
137
-
138
- } catch (err) {
139
- console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
140
- process.exit(1);
141
- }
142
- }
143
-
144
- async function sendTelegramMessage(target, messageText, config) {
145
- if (!config.telegramToken || !config.telegramBotId) {
65
+ if (channel === 'telegram' && (!config.telegramToken || !config.telegramBotId)) {
146
66
  console.log(chalk.red('\n❌ Telegram bağlı değil\n'));
147
67
  console.log(chalk.yellow('Önce Telegram\'ı bağlayın:'), chalk.cyan('natureco telegram connect\n'));
148
68
  process.exit(1);
149
69
  }
150
70
 
151
- console.log(chalk.yellow('\n⏳ Telegram mesajı gönderiliyor...\n'));
71
+ // Send message via HTTP endpoint
72
+ await sendMessageViaHttp(channel, target, messageText);
73
+ }
74
+
75
+ async function sendMessageViaHttp(channel, target, messageText) {
76
+ console.log(chalk.yellow(`\n⏳ ${channel === 'whatsapp' ? 'WhatsApp' : 'Telegram'} mesajı gönderiliyor...\n`));
152
77
 
153
78
  try {
154
- // Lazy load node-telegram-bot-api
155
- let TelegramBot;
156
- try {
157
- TelegramBot = require('node-telegram-bot-api');
158
- } catch (err) {
159
- console.log(chalk.red('❌ node-telegram-bot-api yüklü değil\n'));
160
- console.log(chalk.yellow('Yüklemek için:'), chalk.cyan('npm install -g node-telegram-bot-api\n'));
161
- process.exit(1);
162
- }
79
+ const response = await fetch(GATEWAY_HTTP_URL, {
80
+ method: 'POST',
81
+ headers: { 'Content-Type': 'application/json' },
82
+ body: JSON.stringify({ channel, target, message: messageText })
83
+ });
163
84
 
164
- const bot = new TelegramBot(config.telegramToken, { polling: false });
85
+ const data = await response.json();
165
86
 
166
- // Validate chat ID (should be numeric)
167
- const chatId = target.trim();
168
- if (!/^-?\d+$/.test(chatId)) {
169
- console.log(chalk.red('❌ Geçersiz Telegram Chat ID\n'));
170
- console.log(chalk.gray('Chat ID sadece rakamlardan oluşmalı (örnek: 123456789)\n'));
171
- process.exit(1);
87
+ if (!response.ok) {
88
+ throw new Error(data.error || `HTTP ${response.status}`);
172
89
  }
173
90
 
174
- // Send message
175
- await bot.sendMessage(chatId, messageText);
176
-
177
91
  console.log(chalk.green('✅ Mesaj gönderildi!\n'));
178
- console.log(chalk.cyan('Chat ID:'), chalk.white(chatId));
92
+ console.log(chalk.cyan('Kanal:'), chalk.white(channel));
93
+ console.log(chalk.cyan('Hedef:'), chalk.white(target));
179
94
  console.log(chalk.cyan('Mesaj:'), chalk.white(messageText));
180
95
  console.log('');
181
96
 
@@ -184,8 +99,12 @@ async function sendTelegramMessage(target, messageText, config) {
184
99
  } catch (err) {
185
100
  console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
186
101
 
187
- if (err.message.includes('chat not found')) {
188
- console.log(chalk.yellow('⚠️ Chat ID bulunamadı. Önce bot\'a mesaj gönderin.\n'));
102
+ if (err.message.includes('ECONNREFUSED')) {
103
+ console.log(chalk.yellow('⚠️ Gateway HTTP sunucusuna bağlanılamadı'));
104
+ console.log(chalk.gray('Gateway\'i yeniden başlatın: natureco gateway stop && natureco gateway start\n'));
105
+ } else if (err.message.includes('not connected')) {
106
+ console.log(chalk.yellow(`⚠️ ${channel === 'whatsapp' ? 'WhatsApp' : 'Telegram'} bağlı değil`));
107
+ console.log(chalk.gray(`Bağlantıyı kontrol edin: natureco ${channel} status\n`));
189
108
  }
190
109
 
191
110
  process.exit(1);