noho_bot 2.0.0

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/noho_bot.js ADDED
@@ -0,0 +1,808 @@
1
+ // noho_bot.js
2
+ // NOHO Bot Library - Universal Bot Builder
3
+ // Created by: nohojs (Omar) - NOHO Company
4
+
5
+ const { default: makeWASocket, DisconnectReason, useMultiFileAuthState } = require('@whiskeysockets/baileys');
6
+ const { Telegraf } = require('telegraf');
7
+ const { Client: DiscordClient, GatewayIntentBits } = require('discord.js');
8
+ const { WebClient } = require('@slack/web-api');
9
+ const axios = require('axios');
10
+ const qrcode = require('qrcode-terminal');
11
+ const pino = require('pino');
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+ const crypto = require('crypto');
15
+ const { spawn } = require('child_process');
16
+
17
+ // ==========================================
18
+ // UTILS
19
+ // ==========================================
20
+ const colors = {
21
+ reset: '\x1b[0m', bright: '\x1b[1m', green: '\x1b[32m',
22
+ yellow: '\x1b[33m', red: '\x1b[31m', cyan: '\x1b[36m',
23
+ magenta: '\x1b[35m', blue: '\x1b[34m'
24
+ };
25
+
26
+ function log(type, msg) {
27
+ const icons = {
28
+ info: 'ℹ️', success: '✅', error: '❌', warning: '⚠️',
29
+ bot: '🤖', lock: '🔒', daemon: '👻', whatsapp: '📱',
30
+ telegram: '✈️', discord: '🎮', slack: '💬', facebook: '📘'
31
+ };
32
+ console.log(`${icons[type] || '•'} ${msg}`);
33
+ }
34
+
35
+ // ==========================================
36
+ // DAEMON MANAGER (24/7)
37
+ // ==========================================
38
+ class DaemonManager {
39
+ constructor() {
40
+ this.lockDir = path.join(process.cwd(), '.noho_daemon');
41
+ this.lockFile = path.join(this.lockDir, 'daemon.lock');
42
+ this.pidFile = path.join(this.lockDir, 'daemon.pid');
43
+ this.logFile = path.join(this.lockDir, 'daemon.log');
44
+ this.sessionsFile = path.join(this.lockDir, 'sessions.json');
45
+ this.ensureDir();
46
+ }
47
+
48
+ ensureDir() {
49
+ if (!fs.existsSync(this.lockDir)) {
50
+ fs.mkdirSync(this.lockDir, { recursive: true });
51
+ }
52
+ }
53
+
54
+ start(sessionConfig) {
55
+ if (this.isRunning()) {
56
+ log('warning', 'الديمون يعمل بالفعل!');
57
+ return false;
58
+ }
59
+
60
+ this.saveSession(sessionConfig);
61
+ const botScript = this.generateScript(sessionConfig);
62
+ const botFile = path.join(this.lockDir, 'running_bot.js');
63
+ fs.writeFileSync(botFile, botScript);
64
+
65
+ const out = fs.openSync(this.logFile, 'a');
66
+ const err = fs.openSync(this.logFile, 'a');
67
+
68
+ const child = spawn('node', [botFile], {
69
+ detached: true,
70
+ stdio: ['ignore', out, err]
71
+ });
72
+
73
+ child.unref();
74
+
75
+ fs.writeFileSync(this.pidFile, child.pid.toString());
76
+ fs.writeFileSync(this.lockFile, JSON.stringify({
77
+ pid: child.pid,
78
+ startedAt: new Date().toISOString(),
79
+ platform: sessionConfig.platform,
80
+ sessionName: sessionConfig.name
81
+ }));
82
+
83
+ log('daemon', `تم التشغيل (PID: ${child.pid})`);
84
+ log('success', 'البوت يعمل 24/7!');
85
+ return true;
86
+ }
87
+
88
+ stop() {
89
+ if (!this.isRunning()) {
90
+ log('warning', 'لا يوجد ديمون يعمل');
91
+ return false;
92
+ }
93
+
94
+ const pid = parseInt(fs.readFileSync(this.pidFile, 'utf8'));
95
+ try {
96
+ process.kill(pid, 'SIGTERM');
97
+ log('success', `تم الإيقاف (PID: ${pid})`);
98
+ } catch (e) {
99
+ log('error', 'خطأ في الإيقاف');
100
+ }
101
+
102
+ if (fs.existsSync(this.lockFile)) fs.unlinkSync(this.lockFile);
103
+ if (fs.existsSync(this.pidFile)) fs.unlinkSync(this.pidFile);
104
+ return true;
105
+ }
106
+
107
+ isRunning() {
108
+ if (!fs.existsSync(this.lockFile) || !fs.existsSync(this.pidFile)) {
109
+ return false;
110
+ }
111
+ try {
112
+ const pid = parseInt(fs.readFileSync(this.pidFile, 'utf8'));
113
+ process.kill(pid, 0);
114
+ return true;
115
+ } catch (e) {
116
+ if (fs.existsSync(this.lockFile)) fs.unlinkSync(this.lockFile);
117
+ if (fs.existsSync(this.pidFile)) fs.unlinkSync(this.pidFile);
118
+ return false;
119
+ }
120
+ }
121
+
122
+ logs(tail = 20) {
123
+ if (!fs.existsSync(this.logFile)) {
124
+ log('error', 'لا توجد سجلات');
125
+ return;
126
+ }
127
+ const logs = fs.readFileSync(this.logFile, 'utf8').split('\n').filter(Boolean);
128
+ console.log(logs.slice(-tail).join('\n'));
129
+ }
130
+
131
+ saveSession(config) {
132
+ fs.writeFileSync(this.sessionsFile, JSON.stringify(config, null, 2));
133
+ }
134
+
135
+ generateScript(config) {
136
+ return `
137
+ const noho = require('${path.join(__dirname, 'noho_bot.js').replace(/\\/g, '\\\\')}');
138
+ const bot = new noho();
139
+
140
+ async function start() {
141
+ const session = await bot.create('${config.platform}', {
142
+ sessionPath: '${config.sessionPath}',
143
+ ${config.token ? `token: '${config.token}',` : ''}
144
+ ${config.appId ? `appId: '${config.appId}',` : ''}
145
+ ${config.appSecret ? `appSecret: '${config.appSecret}',` : ''}
146
+ autoReply: true
147
+ });
148
+
149
+ await session.connect(${config.method ? `'${config.method}'` : ''}${config.phoneNumber ? `, '${config.phoneNumber}'` : ''});
150
+
151
+ session.onMessage(async (msg, from, platform) => {
152
+ console.log('[DAEMON]', platform, from, msg);
153
+ if (msg === '.ping') {
154
+ await session.sendMessage(from, 'pong! (24/7 mode)');
155
+ }
156
+ });
157
+ }
158
+
159
+ start().catch(err => {
160
+ console.error('Daemon error:', err);
161
+ setTimeout(start, 10000);
162
+ });
163
+
164
+ process.on('SIGTERM', () => process.exit(0));
165
+ `;
166
+ }
167
+ }
168
+
169
+ // ==========================================
170
+ // BASE ADAPTER
171
+ // ==========================================
172
+ class BaseAdapter {
173
+ constructor(name, config = {}) {
174
+ this.name = name;
175
+ this.config = config;
176
+ this.connected = false;
177
+ this.authData = null;
178
+ this.messageHandler = null;
179
+ this.sock = null;
180
+ }
181
+
182
+ onMessage(handler) {
183
+ this.messageHandler = handler;
184
+ }
185
+
186
+ async sendMessage(to, text) {
187
+ throw new Error('Not implemented');
188
+ }
189
+
190
+ getFingerprint() {
191
+ return {
192
+ platform: this.name,
193
+ connected: this.connected,
194
+ user: this.authData?.user || null
195
+ };
196
+ }
197
+ }
198
+
199
+ // ==========================================
200
+ // WHATSAPP ADAPTER
201
+ // ==========================================
202
+ class WhatsAppAdapter extends BaseAdapter {
203
+ constructor(config = {}) {
204
+ super('whatsapp', {
205
+ sessionPath: config.sessionPath || './.noho_sessions/whatsapp',
206
+ printQR: config.printQR !== false,
207
+ ...config
208
+ });
209
+ this.qrCode = null;
210
+ this.pairingCode = null;
211
+ }
212
+
213
+ async connect(method = 'qr', phoneNumber = null) {
214
+ const { state, saveCreds } = await useMultiFileAuthState(this.config.sessionPath);
215
+
216
+ this.sock = makeWASocket({
217
+ logger: pino({ level: 'silent' }),
218
+ printQRInTerminal: false,
219
+ auth: state,
220
+ browser: ['NOHO Bot', 'Chrome', '1.0']
221
+ });
222
+
223
+ return new Promise((resolve, reject) => {
224
+ const timeout = setTimeout(() => reject(new Error('timeout')), 120000);
225
+
226
+ this.sock.ev.on('connection.update', async (update) => {
227
+ const { connection, lastDisconnect, qr } = update;
228
+
229
+ if (qr && method === 'qr' && this.config.printQR) {
230
+ this.qrCode = qr;
231
+ console.log('\n┌─────────────────────────────┐');
232
+ console.log('│ امسح QR Code بالكاميرا │');
233
+ console.log('└─────────────────────────────┘\n');
234
+ qrcode.generate(qr, { small: true });
235
+ }
236
+
237
+ if (update.isNewLogin && method === 'pairing' && phoneNumber) {
238
+ try {
239
+ this.pairingCode = await this.sock.requestPairingCode(phoneNumber);
240
+ console.log(`\nالكود: ${this.pairingCode}`);
241
+ } catch (err) {
242
+ console.error('خطأ:', err.message);
243
+ }
244
+ }
245
+
246
+ if (connection === 'open') {
247
+ clearTimeout(timeout);
248
+ this.connected = true;
249
+ this.authData = {
250
+ id: this.sock.user.id,
251
+ user: {
252
+ name: this.sock.user.name,
253
+ phone: this.sock.user.id.split(':')[0]
254
+ }
255
+ };
256
+ log('whatsapp', `متصل: ${this.authData.user.name}`);
257
+ resolve(this.getFingerprint());
258
+ }
259
+
260
+ if (connection === 'close') {
261
+ this.connected = false;
262
+ const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut;
263
+ if (shouldReconnect) {
264
+ setTimeout(() => this.connect(method, phoneNumber), 5000);
265
+ }
266
+ }
267
+ });
268
+
269
+ this.sock.ev.on('creds.update', saveCreds);
270
+
271
+ this.sock.ev.on('messages.upsert', async (m) => {
272
+ if (m.type !== 'notify') return;
273
+ const msg = m.messages[0];
274
+ if (msg.key.fromMe) return;
275
+
276
+ const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text || '';
277
+ const from = msg.key.remoteJid;
278
+
279
+ if (this.messageHandler) {
280
+ await this.messageHandler(text, from, 'whatsapp');
281
+ }
282
+ });
283
+ });
284
+ }
285
+
286
+ async sendMessage(to, text) {
287
+ if (!this.connected || !this.sock) throw new Error('Not connected');
288
+ await this.sock.sendMessage(to, { text });
289
+ }
290
+
291
+ async disconnect() {
292
+ if (this.sock) {
293
+ await this.sock.logout();
294
+ this.sock = null;
295
+ }
296
+ this.connected = false;
297
+ }
298
+ }
299
+
300
+ // ==========================================
301
+ // TELEGRAM ADAPTER
302
+ // ==========================================
303
+ class TelegramAdapter extends BaseAdapter {
304
+ constructor(config = {}) {
305
+ super('telegram', config);
306
+ this.bot = null;
307
+ this.token = config.token;
308
+ }
309
+
310
+ async connect() {
311
+ if (!this.token) {
312
+ throw new Error('Telegram token required. Get from @BotFather');
313
+ }
314
+
315
+ this.bot = new Telegraf(this.token);
316
+
317
+ this.bot.on('text', async (ctx) => {
318
+ const text = ctx.message.text;
319
+ const from = ctx.chat.id.toString();
320
+
321
+ if (this.messageHandler) {
322
+ await this.messageHandler(text, from, 'telegram');
323
+ }
324
+ });
325
+
326
+ await this.bot.launch();
327
+ this.connected = true;
328
+
329
+ const botInfo = await this.bot.telegram.getMe();
330
+ this.authData = {
331
+ id: botInfo.id.toString(),
332
+ user: {
333
+ name: botInfo.first_name,
334
+ username: botInfo.username
335
+ }
336
+ };
337
+
338
+ log('telegram', `متصل: @${botInfo.username}`);
339
+ return this.getFingerprint();
340
+ }
341
+
342
+ async sendMessage(to, text) {
343
+ if (!this.connected || !this.bot) throw new Error('Not connected');
344
+ await this.bot.telegram.sendMessage(to, text);
345
+ }
346
+
347
+ async disconnect() {
348
+ if (this.bot) {
349
+ this.bot.stop();
350
+ this.bot = null;
351
+ }
352
+ this.connected = false;
353
+ }
354
+ }
355
+
356
+ // ==========================================
357
+ // DISCORD ADAPTER
358
+ // ==========================================
359
+ class DiscordAdapter extends BaseAdapter {
360
+ constructor(config = {}) {
361
+ super('discord', config);
362
+ this.client = null;
363
+ this.token = config.token;
364
+ }
365
+
366
+ async connect() {
367
+ if (!this.token) {
368
+ throw new Error('Discord token required from Developer Portal');
369
+ }
370
+
371
+ this.client = new DiscordClient({
372
+ intents: [
373
+ GatewayIntentBits.Guilds,
374
+ GatewayIntentBits.GuildMessages,
375
+ GatewayIntentBits.MessageContent
376
+ ]
377
+ });
378
+
379
+ this.client.on('messageCreate', async (message) => {
380
+ if (message.author.bot) return;
381
+
382
+ const text = message.content;
383
+ const from = message.channel.id;
384
+
385
+ if (this.messageHandler) {
386
+ await this.messageHandler(text, from, 'discord');
387
+ }
388
+ });
389
+
390
+ await this.client.login(this.token);
391
+ this.connected = true;
392
+
393
+ this.authData = {
394
+ id: this.client.user.id,
395
+ user: {
396
+ name: this.client.user.username,
397
+ tag: this.client.user.tag
398
+ }
399
+ };
400
+
401
+ log('discord', `متصل: ${this.client.user.tag}`);
402
+ return this.getFingerprint();
403
+ }
404
+
405
+ async sendMessage(to, text) {
406
+ if (!this.connected || !this.client) throw new Error('Not connected');
407
+ const channel = await this.client.channels.fetch(to);
408
+ await channel.send(text);
409
+ }
410
+
411
+ async disconnect() {
412
+ if (this.client) {
413
+ this.client.destroy();
414
+ this.client = null;
415
+ }
416
+ this.connected = false;
417
+ }
418
+ }
419
+
420
+ // ==========================================
421
+ // SLACK ADAPTER
422
+ // ==========================================
423
+ class SlackAdapter extends BaseAdapter {
424
+ constructor(config = {}) {
425
+ super('slack', config);
426
+ this.client = null;
427
+ this.token = config.token;
428
+ }
429
+
430
+ async connect() {
431
+ if (!this.token) {
432
+ throw new Error('Slack token required from api.slack.com');
433
+ }
434
+
435
+ this.client = new WebClient(this.token);
436
+
437
+ const auth = await this.client.auth.test();
438
+ this.connected = true;
439
+
440
+ this.authData = {
441
+ id: auth.user_id,
442
+ user: {
443
+ name: auth.user,
444
+ team: auth.team
445
+ }
446
+ };
447
+
448
+ log('slack', `متصل: ${auth.user} @ ${auth.team}`);
449
+ return this.getFingerprint();
450
+ }
451
+
452
+ async sendMessage(channel, text) {
453
+ if (!this.connected || !this.client) throw new Error('Not connected');
454
+ await this.client.chat.postMessage({ channel, text });
455
+ }
456
+
457
+ async disconnect() {
458
+ this.connected = false;
459
+ this.client = null;
460
+ }
461
+ }
462
+
463
+ // ==========================================
464
+ // FACEBOOK ADAPTER
465
+ // ==========================================
466
+ class FacebookAdapter extends BaseAdapter {
467
+ constructor(config = {}) {
468
+ super('facebook', config);
469
+ this.appId = config.appId;
470
+ this.appSecret = config.appSecret;
471
+ this.accessToken = null;
472
+ }
473
+
474
+ async connect() {
475
+ if (!this.appId || !this.appSecret) {
476
+ throw new Error('Facebook App ID and Secret required');
477
+ }
478
+
479
+ // الحصول على access token
480
+ const url = `https://graph.facebook.com/oauth/access_token?client_id=${this.appId}&client_secret=${this.appSecret}&grant_type=client_credentials`;
481
+ const response = await axios.get(url);
482
+ this.accessToken = response.data.access_token;
483
+ this.connected = true;
484
+
485
+ this.authData = {
486
+ id: this.appId,
487
+ user: { appId: this.appId }
488
+ };
489
+
490
+ log('facebook', 'متصل');
491
+ return this.getFingerprint();
492
+ }
493
+
494
+ async sendMessage(to, text) {
495
+ if (!this.connected) throw new Error('Not connected');
496
+ // إرسال رسالة عبر Messenger API
497
+ await axios.post(`https://graph.facebook.com/v18.0/me/messages?access_token=${this.accessToken}`, {
498
+ recipient: { id: to },
499
+ message: { text }
500
+ });
501
+ }
502
+
503
+ async disconnect() {
504
+ this.connected = false;
505
+ this.accessToken = null;
506
+ }
507
+ }
508
+
509
+ // ==========================================
510
+ // NOHO USER SYSTEM
511
+ // ==========================================
512
+ class NohoUser {
513
+ constructor() {
514
+ this.dataPath = path.join(process.cwd(), '.noho');
515
+ this.userFile = path.join(this.dataPath, 'user.json');
516
+ this.projectsFile = path.join(this.dataPath, 'projects.json');
517
+ this.apiFile = path.join(this.dataPath, 'api.key');
518
+ this.ensureDir();
519
+ }
520
+
521
+ ensureDir() {
522
+ if (!fs.existsSync(this.dataPath)) {
523
+ fs.mkdirSync(this.dataPath, { recursive: true });
524
+ }
525
+ }
526
+
527
+ register(username, password) {
528
+ if (this.exists()) {
529
+ log('error', 'أنت مسجل بالفعل!');
530
+ return false;
531
+ }
532
+
533
+ const apiKey = 'NPI-' + crypto.randomBytes(32).toString('hex').toUpperCase();
534
+ const userData = {
535
+ username,
536
+ password: crypto.createHash('sha256').update(password).digest('hex'),
537
+ apiKey,
538
+ createdAt: new Date().toISOString()
539
+ };
540
+
541
+ fs.writeFileSync(this.userFile, JSON.stringify(userData, null, 2));
542
+ fs.writeFileSync(this.apiFile, apiKey);
543
+
544
+ log('success', `تم التسجيل: ${username}`);
545
+ log('bot', `API: ${apiKey.slice(0, 20)}...`);
546
+ return true;
547
+ }
548
+
549
+ login(username, password) {
550
+ if (!this.exists()) {
551
+ log('error', 'ليس لديك حساب!');
552
+ return false;
553
+ }
554
+
555
+ const user = JSON.parse(fs.readFileSync(this.userFile, 'utf8'));
556
+ const hash = crypto.createHash('sha256').update(password).digest('hex');
557
+
558
+ if (user.username !== username || user.password !== hash) {
559
+ log('error', 'بيانات غير صحيحة');
560
+ return false;
561
+ }
562
+
563
+ log('success', `مرحباً ${username}!`);
564
+ return true;
565
+ }
566
+
567
+ getInfo() {
568
+ if (!this.exists()) return null;
569
+ const user = JSON.parse(fs.readFileSync(this.userFile, 'utf8'));
570
+ return {
571
+ username: user.username,
572
+ apiKey: user.apiKey.slice(0, 20) + '...',
573
+ createdAt: user.createdAt
574
+ };
575
+ }
576
+
577
+ renewAPI() {
578
+ if (!this.exists()) return null;
579
+ const newApi = 'NPI-' + crypto.randomBytes(32).toString('hex').toUpperCase();
580
+ const user = JSON.parse(fs.readFileSync(this.userFile, 'utf8'));
581
+ user.apiKey = newApi;
582
+ fs.writeFileSync(this.userFile, JSON.stringify(user, null, 2));
583
+ fs.writeFileSync(this.apiFile, newApi);
584
+ log('success', 'تم تجديد API!');
585
+ return newApi;
586
+ }
587
+
588
+ saveProject(name, platform, config) {
589
+ const projects = fs.existsSync(this.projectsFile)
590
+ ? JSON.parse(fs.readFileSync(this.projectsFile, 'utf8'))
591
+ : [];
592
+ projects.push({ name, platform, config, createdAt: new Date().toISOString() });
593
+ fs.writeFileSync(this.projectsFile, JSON.stringify(projects, null, 2));
594
+ }
595
+
596
+ exists() {
597
+ return fs.existsSync(this.userFile);
598
+ }
599
+ }
600
+
601
+ // ==========================================
602
+ // CODE CHECKER
603
+ // ==========================================
604
+ class CodeChecker {
605
+ check(filePath) {
606
+ if (!fs.existsSync(filePath)) {
607
+ log('error', `الملف غير موجود: ${filePath}`);
608
+ return false;
609
+ }
610
+
611
+ const code = fs.readFileSync(filePath, 'utf8');
612
+ const issues = [];
613
+ const warnings = [];
614
+
615
+ if (code.includes('console.log') && !code.includes('// debug')) {
616
+ warnings.push('يوجد console.log - احذفها قبل النشر');
617
+ }
618
+ if (!code.includes('try') && code.includes('await')) {
619
+ warnings.push('يفضل استخدام try-catch');
620
+ }
621
+ if (code.includes('eval(')) {
622
+ issues.push('⚠️ خطير: eval() غير آمن!');
623
+ }
624
+ if (code.includes('password') && !code.includes('hash')) {
625
+ warnings.push('تأكد من تشفير كلمات المرور');
626
+ }
627
+
628
+ console.log(`\n${colors.cyan}═══ فحص الكود ═══${colors.reset}`);
629
+ console.log(`الملف: ${filePath}`);
630
+ console.log(`الأسطر: ${code.split('\n').length}`);
631
+
632
+ if (issues.length === 0 && warnings.length === 0) {
633
+ log('success', 'الكود نظيف! ✅');
634
+ return true;
635
+ }
636
+
637
+ issues.forEach(i => console.log(` ❌ ${i}`));
638
+ warnings.forEach(w => console.log(` ⚠️ ${w}`));
639
+ return issues.length === 0;
640
+ }
641
+ }
642
+
643
+ // ==========================================
644
+ // MAIN NOHO BOT CLASS
645
+ // ==========================================
646
+ class NohoBot {
647
+ constructor() {
648
+ this.user = new NohoUser();
649
+ this.checker = new CodeChecker();
650
+ this.daemon = new DaemonManager();
651
+ this.adapters = new Map();
652
+
653
+ this.register('whatsapp', WhatsAppAdapter);
654
+ this.register('telegram', TelegramAdapter);
655
+ this.register('discord', DiscordAdapter);
656
+ this.register('slack', SlackAdapter);
657
+ this.register('facebook', FacebookAdapter);
658
+
659
+ this.setupCLI();
660
+ }
661
+
662
+ register(name, AdapterClass) {
663
+ this.adapters.set(name, AdapterClass);
664
+ }
665
+
666
+ // إنشاء بوت جديد (للمستخدم)
667
+ async create(platform, config = {}) {
668
+ const AdapterClass = this.adapters.get(platform);
669
+ if (!AdapterClass) {
670
+ throw new Error(`المنصة ${platform} غير مدعومة`);
671
+ }
672
+
673
+ const adapter = new AdapterClass(config);
674
+
675
+ return {
676
+ connect: (...args) => adapter.connect(...args),
677
+ disconnect: () => adapter.disconnect(),
678
+ sendMessage: (to, text) => adapter.sendMessage(to, text),
679
+ onMessage: (handler) => adapter.onMessage(handler),
680
+ getFingerprint: () => adapter.getFingerprint(),
681
+ adapter
682
+ };
683
+ }
684
+
685
+ setupCLI() {
686
+ const args = process.argv.slice(2);
687
+ const cmd = args[0];
688
+
689
+ switch(cmd) {
690
+ case '.longin':
691
+ args[1] && args[2] ? this.user.register(args[1], args[2]) : console.log('الاستخدام: .longin <user> <pass>');
692
+ break;
693
+ case '.d.noho':
694
+ this.showInfo();
695
+ break;
696
+ case 'NPI':
697
+ this.user.renewAPI();
698
+ break;
699
+ case '.m':
700
+ args[1] ? this.checker.check(args[1]) : console.log('الاستخدام: .m <file.js>');
701
+ break;
702
+ case '.link':
703
+ this.listPlatforms();
704
+ break;
705
+ case '.noho.lock.link':
706
+ this.cmdDaemonStart(args[1], args[2], args[3]);
707
+ break;
708
+ case '.noho.stop':
709
+ this.daemon.stop();
710
+ break;
711
+ case '.noho.status':
712
+ this.daemon.isRunning() ? log('success', 'الديمون يعمل ✅') : log('error', 'الديمون متوقف ❌');
713
+ break;
714
+ case '.noho.logs':
715
+ this.daemon.logs(parseInt(args[1]) || 20);
716
+ break;
717
+ default:
718
+ this.showHelp();
719
+ }
720
+ }
721
+
722
+ showInfo() {
723
+ const info = this.user.getInfo();
724
+ if (!info) {
725
+ log('error', 'ليس لديك حساب! استخدم: .longin <user> <pass>');
726
+ return;
727
+ }
728
+ console.log(`\n${colors.cyan}═══ حساب NOHO ═══${colors.reset}`);
729
+ console.log(`المستخدم: ${info.username}`);
730
+ console.log(`API: ${info.apiKey}`);
731
+ console.log(`منذ: ${info.createdAt}`);
732
+ }
733
+
734
+ listPlatforms() {
735
+ console.log(`\n${colors.cyan}═══ المنصات المتاحة ═══${colors.reset}`);
736
+ console.log('1. whatsapp - QR Code / Pairing Code');
737
+ console.log('2. telegram - Bot Token (@BotFather)');
738
+ console.log('3. discord - Bot Token (Discord Dev)');
739
+ console.log('4. slack - App Token (api.slack.com)');
740
+ console.log('5. facebook - App ID + Secret (developers.facebook.com)');
741
+ }
742
+
743
+ async cmdDaemonStart(platform, name, method) {
744
+ if (!platform || !name) {
745
+ console.log('الاستخدام: .noho.lock.link <platform> <name> [qr|pairing|token]');
746
+ return;
747
+ }
748
+
749
+ if (!this.user.exists()) {
750
+ log('error', 'سجل دخولك أولاً: .longin <user> <pass>');
751
+ return;
752
+ }
753
+
754
+ const sessionConfig = {
755
+ platform: platform.toLowerCase(),
756
+ name: name,
757
+ method: method || 'qr',
758
+ sessionPath: path.join(process.cwd(), '.noho_sessions', name),
759
+ createdAt: new Date().toISOString()
760
+ };
761
+
762
+ this.user.saveProject(name, platform, sessionConfig);
763
+
764
+ if (platform === 'whatsapp') {
765
+ log('whatsapp', 'جاري الاتصال... امسح QR Code');
766
+ const session = await this.create('whatsapp', { sessionPath: sessionConfig.sessionPath });
767
+ await session.connect(method || 'qr');
768
+ await session.disconnect();
769
+ }
770
+
771
+ this.daemon.start(sessionConfig);
772
+ }
773
+
774
+ showHelp() {
775
+ console.log(`
776
+ ${colors.cyan}╔══════════════════════════════════════╗${colors.reset}
777
+ ${colors.cyan}║ NOHO Bot Library v1.0 🤖 ║${colors.reset}
778
+ ${colors.cyan}╚══════════════════════════════════════╝${colors.reset}
779
+
780
+ 👤 المستخدم:
781
+ .longin <u> <p> تسجيل/دخول
782
+ .d.noho بيانات الحساب
783
+ NPI تجديد API
784
+
785
+ 🔍 الكود:
786
+ .m <file.js> فحص الكود
787
+
788
+ 🔗 الربط:
789
+ .link عرض المنصات
790
+
791
+ 👻 الديمون (24/7):
792
+ .noho.lock.link <p> <n> [m] تشغيل
793
+ .noho.stop إيقاف
794
+ .noho.status الحالة
795
+ .noho.logs [n] السجلات
796
+
797
+ 💡 مثال:
798
+ node noho_bot.js .longin omar 123456
799
+ node noho_bot.js .noho.lock.link whatsapp mybot qr
800
+ `);
801
+ }
802
+ }
803
+
804
+ module.exports = NohoBot;
805
+
806
+ if (require.main === module) {
807
+ new NohoBot();
808
+ }