@innovatorssoft/innovators-bot2 1.2.8

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/example.js ADDED
@@ -0,0 +1,710 @@
1
+ const { WhatsAppClient } = require('./index')
2
+ const qrcode = require('qrcode-terminal')
3
+ const fs = require('fs');
4
+ const readline = require('readline');
5
+ const path = require('path');
6
+
7
+ const rl = readline.createInterface({
8
+ input: process.stdin,
9
+ output: process.stdout
10
+ });
11
+
12
+ const question = (text) => new Promise((resolve) => rl.question(text, resolve));
13
+
14
+ async function start() {
15
+ const sessionDir = ".Sessions";
16
+ const hasSession = fs.existsSync(path.join(sessionDir, 'creds.json'));
17
+
18
+ let authMethod = 'qr';
19
+ let pairingPhoneNumber = null;
20
+
21
+ if (!hasSession) {
22
+ console.log('\nšŸ“± WhatsApp Bot Setup');
23
+ console.log('-------------------');
24
+ console.log('1. QR Code');
25
+ console.log('2. Pairing Code');
26
+
27
+ const choice = await question('\nChoose authentication method (1 or 2): ');
28
+ authMethod = choice === '2' ? 'pairing' : 'qr';
29
+
30
+ if (authMethod === 'pairing') {
31
+ pairingPhoneNumber = await question('Enter phone number for pairing (e.g. 923224559543): ');
32
+ if (!pairingPhoneNumber) {
33
+ console.log('āŒ Phone number is required for pairing method.');
34
+ process.exit(1);
35
+ }
36
+ }
37
+ } else {
38
+ console.log('\nšŸ”„ Existing session found! Skipping setup...');
39
+ }
40
+
41
+ rl.close();
42
+
43
+ const client = new WhatsAppClient({
44
+ sessionName: sessionDir,
45
+ authmethod: authMethod,
46
+ pairingPhoneNumber: pairingPhoneNumber
47
+ });
48
+
49
+ console.log(`\nšŸš€ Initializing with ${authMethod} method...`);
50
+
51
+ // Handle QR Code
52
+ client.on('qr', qr => {
53
+ console.log('\nāœ… QR Code received. Scan it with WhatsApp:')
54
+ qrcode.generate(qr, { small: true })
55
+ })
56
+
57
+ client.on('pairing-code', (code) => {
58
+ console.log(`\nāœ… Pairing code for ${pairingPhoneNumber}: ${code}`)
59
+ })
60
+
61
+ // Handle connection events
62
+ client.on('connecting', (message) => {
63
+ console.log('ā³ Client status:', message)
64
+ })
65
+
66
+ client.on('connected', (user) => {
67
+ console.log('\n✨ Client is ready!')
68
+ console.log('User:', user.name)
69
+ console.log('Phone:', user.phone)
70
+ console.log('Plateform:', user.platform)
71
+ console.log('isOnline:', user.isOnline)
72
+ })
73
+
74
+ // Handle LID mapping updates
75
+ client.on('lid-mapping-update', (update) => {
76
+ console.log('šŸ“¦ New LID/PN mappings received')
77
+ })
78
+
79
+ // Handle Anti-Delete system
80
+ client.on('message-deleted', async (data) => {
81
+ console.log(`\nšŸ›”ļø Message from ${data.jid} was deleted!`)
82
+ await client.sendMessage(data.jid, 'āš ļø I saw you deleted that message! I have it saved in my memory. šŸ˜‰', { quoted: data.originalMessage });
83
+ })
84
+
85
+ // Handle message reactions
86
+ client.on('message-reaction', async (reaction) => {
87
+ console.log('\nšŸ‘ Message Reaction Received!')
88
+ console.log('Chat:', reaction.from)
89
+ console.log('Sender:', reaction.sender)
90
+ console.log('Emoji:', reaction.emoji || '(removed)')
91
+ console.log('Is Removed:', reaction.isRemoved)
92
+ console.log('Message ID:', reaction.messageKey.id)
93
+ })
94
+
95
+ client.on('call', (call) => {
96
+ const callData = call[0]; // Get the first call object from the array
97
+ if (callData.status !== 'offer') return;
98
+ console.log('\nšŸ“ž Call Received!')
99
+ console.log('Chat ID:', callData.chatId)
100
+ console.log('From:', callData.from)
101
+ console.log('Call ID:', callData.id)
102
+ console.log('Date:', callData.date)
103
+ console.log('Offline:', callData.offline)
104
+ console.log('Status:', callData.status)
105
+ console.log('Is Video:', callData.isVideo)
106
+ console.log('Is Group:', callData.isGroup)
107
+ console.log('Phone Number:', callData.phoneNumber)
108
+ })
109
+
110
+ client.on('disconnected', (error) => {
111
+ console.log('āŒ Client disconnected')
112
+ })
113
+
114
+ client.on('group-left', (info) => {
115
+ console.log(`Left group ${info.id}: ${info.reason}`);
116
+ });
117
+
118
+ // Connect to WhatsApp
119
+ client.connect()
120
+
121
+ client.on('status', async status => {
122
+
123
+ console.log('Status Received');
124
+ console.log('Number:', status.from);
125
+ console.log('Sender:', status.raw.pushName);
126
+ console.log('Message:', status.body);
127
+ console.log('Has Media:', status.hasMedia);
128
+
129
+ // Mark status as read using the complete message key
130
+
131
+ //await client.readMessage(status.key);
132
+
133
+ //Reply With Emoji
134
+ //await status.reply('Liked Your Status! ā¤ļø');
135
+
136
+ await status.like('ā¤ļø');
137
+ console.log('Status Seen! and Replied With Emoji')
138
+ });
139
+
140
+ // Listen for incoming messages
141
+ client.on('message', async msg => {
142
+
143
+ if (msg.body === '') {
144
+ return
145
+ }
146
+
147
+ console.log('Message Received');
148
+ console.log('Number:', msg.from);
149
+ console.log('Sender:', msg.raw.pushName);
150
+ console.log('Message:', msg.body);
151
+ // Mark the message as read
152
+ await client.readMessage(msg.raw.key)
153
+
154
+ const command = msg.body.toLowerCase().split(' ')[0]
155
+ const args = msg.body.toLowerCase().split(' ').slice(1).join(' ')
156
+
157
+ switch (command) {
158
+ case '!ping':
159
+ await client.sendMessage(msg.from, 'pong')
160
+ break
161
+
162
+ case '!echo':
163
+ if (args) {
164
+ await client.sendMessage(msg.from, args)
165
+ } else {
166
+ await client.sendMessage(msg.from, 'Please provide text to echo')
167
+ }
168
+ break
169
+
170
+ case '!mention':
171
+ const number = msg.from.split('@')[0]
172
+ await client.sendMessage(msg.from, {
173
+ type: 'text',
174
+ text: `Hey @${number}! How are you?`,
175
+ mentions: [msg.from]
176
+ })
177
+ break
178
+
179
+ case '!reply':
180
+ await msg.reply('This is a reply message')
181
+ break
182
+
183
+ case '!location':
184
+ await client.sendMessage(msg.from, {
185
+ type: 'location',
186
+ latitude: 24.121231,
187
+ longitude: 55.1121221
188
+ })
189
+ break
190
+
191
+ case '!contact':
192
+ await client.sendMessage(msg.from, {
193
+ type: 'contact',
194
+ fullName: 'John Doe',
195
+ organization: 'Example Corp',
196
+ phoneNumber: '1234567890'
197
+ })
198
+ break
199
+
200
+ case '!react':
201
+ await client.sendMessage(
202
+ msg.from,
203
+ {
204
+ type: 'reaction',
205
+ emoji: 'šŸ’–',
206
+ message: { key: msg.raw.key }
207
+ }
208
+ )
209
+ break
210
+ case '!media':
211
+ if (fs.existsSync('./example.jpg')) {
212
+ await client.sendMedia(msg.from, './example.jpg', {
213
+ caption: 'Check out this image!'
214
+ })
215
+ } else {
216
+ await client.sendMessage(msg.from, 'Example image not found')
217
+ }
218
+ break
219
+
220
+ case '!doc':
221
+ if (fs.existsSync('./example.pdf')) {
222
+ await client.sendDocument(msg.from, './example.pdf', 'Check out this document!')
223
+ } else {
224
+ await client.sendMessage(msg.from, 'Example document not found')
225
+ }
226
+ break
227
+
228
+ case '!list':
229
+ await client.SendList(msg.from, {
230
+ text: 'Please select an option from the list below:',
231
+ title: 'Comprehensive Menu',
232
+ buttonText: 'View All Options',
233
+ footer: 'Scroll to see more options',
234
+ sections: [
235
+ {
236
+ title: 'Main Options',
237
+ rows: [
238
+ { title: 'Account Settings', id: 'account_settings', description: 'Manage your account preferences' },
239
+ { title: 'Profile', id: 'profile', description: 'View and edit your profile' },
240
+ { title: 'Notifications', id: 'notifications', description: 'Configure notification settings' },
241
+ { title: 'Privacy', id: 'privacy', description: 'Privacy and security settings' },
242
+ { title: 'Security', id: 'security', description: 'Security and login options' },
243
+ { title: 'Payments', id: 'payments', description: 'Manage payment methods' },
244
+ { title: 'Subscriptions', id: 'subscriptions', description: 'View your subscriptions' },
245
+ { title: 'Orders', id: 'orders', description: 'View order history' },
246
+ { title: 'Wishlist', id: 'wishlist', description: 'Your saved items' },
247
+ { title: 'Addresses', id: 'addresses', description: 'Manage shipping addresses' },
248
+ { title: 'Help Center', id: 'help', description: 'Get help and support' },
249
+ { title: 'Contact Us', id: 'contact', description: 'Reach out to our team' },
250
+ { title: 'FAQs', id: 'faqs', description: 'Frequently asked questions' },
251
+ { title: 'About Us', id: 'about', description: 'Learn about our company' },
252
+ { title: 'Careers', id: 'careers', description: 'Join our team' },
253
+ { title: 'Blog', id: 'blog', description: 'Read our latest articles' },
254
+ { title: 'Newsletter', id: 'newsletter', description: 'Subscribe to updates' },
255
+ { title: 'Events', id: 'events', description: 'Upcoming events' },
256
+ { title: 'Webinars', id: 'webinars', description: 'Join live webinars' },
257
+ { title: 'Tutorials', id: 'tutorials', description: 'Learn how to use features' },
258
+ { title: 'Documentation', id: 'docs', description: 'Technical documentation' },
259
+ { title: 'API', id: 'api', description: 'Developer API' },
260
+ { title: 'Integrations', id: 'integrations', description: 'Third-party integrations' },
261
+ { title: 'Download', id: 'download', description: 'Download our app' },
262
+ { title: 'Pricing', id: 'pricing', description: 'View pricing plans' },
263
+ { title: 'Upgrade', id: 'upgrade', description: 'Upgrade your plan' },
264
+ { title: 'Refer a Friend', id: 'refer', description: 'Earn rewards' },
265
+ { title: 'Feedback', id: 'feedback', description: 'Share your thoughts' },
266
+ { title: 'Report Issue', id: 'report', description: 'Report a problem' },
267
+ { title: 'Language', id: 'language', description: 'Change language' }
268
+ ]
269
+ },
270
+ {
271
+ title: 'More Options',
272
+ rows: [
273
+ { title: 'Themes', id: 'themes', description: 'Change app appearance' },
274
+ { title: 'Font Size', id: 'font_size', description: 'Adjust text size' },
275
+ { title: 'Dark Mode', id: 'dark_mode', description: 'Toggle dark theme' },
276
+ { title: 'Offline Mode', id: 'offline', description: 'Use without internet' },
277
+ { title: 'Data Saver', id: 'data_saver', description: 'Reduce data usage' },
278
+ { title: 'Storage', id: 'storage', description: 'Manage local storage' },
279
+ { title: 'Cache', id: 'cache', description: 'Clear cached data' },
280
+ { title: 'Backup', id: 'backup', description: 'Backup your data' },
281
+ { title: 'Restore', id: 'restore', description: 'Restore from backup' },
282
+ { title: 'Export Data', id: 'export', description: 'Download your data' },
283
+ { title: 'Delete Account', id: 'delete', description: 'Permanently remove account' },
284
+ { title: 'Terms of Service', id: 'tos', description: 'Read terms and conditions' },
285
+ { title: 'Privacy Policy', id: 'privacy_policy', description: 'How we handle your data' },
286
+ { title: 'Cookie Policy', id: 'cookies', description: 'About our use of cookies' },
287
+ { title: 'Accessibility', id: 'accessibility', description: 'Accessibility features' },
288
+ { title: 'Version', id: 'version', description: 'App version information' },
289
+ { title: 'Changelog', id: 'changelog', description: 'Recent updates' },
290
+ { title: 'Roadmap', id: 'roadmap', description: 'Upcoming features' },
291
+ { title: 'Status', id: 'status', description: 'Service status' },
292
+ { title: 'Legal', id: 'legal', description: 'Legal information' },
293
+ { title: 'Partners', id: 'partners', description: 'Our partners' },
294
+ { title: 'Press', id: 'press', description: 'Press resources' },
295
+ { title: 'Investors', id: 'investors', description: 'Investor relations' },
296
+ { title: 'Affiliates', id: 'affiliates', description: 'Become an affiliate' },
297
+ { title: 'Merchandise', id: 'merch', description: 'Official merchandise' },
298
+ { title: 'Donate', id: 'donate', description: 'Support our work' },
299
+ { title: 'Volunteer', id: 'volunteer', description: 'Get involved' },
300
+ { title: 'Community', id: 'community', description: 'Join our community' },
301
+ { title: 'Forum', id: 'forum', description: 'Community discussions' },
302
+ { title: 'Beta Program', id: 'beta', description: 'Try beta features' }
303
+ ]
304
+ }
305
+ ]
306
+ })
307
+ break
308
+ case '!buttons':
309
+ // Example: Send a text interactive message (modern Baileys format)
310
+ await client.sendButtons(msg.from, {
311
+ text: 'Do you like this bot?',
312
+ title: 'Feedback',
313
+ subtitle: 'Let us know!',
314
+ footer: 'Powered by Baileys',
315
+ interactiveButtons: [
316
+ {
317
+ name: 'quick_reply',
318
+ buttonParamsJson: JSON.stringify({
319
+ display_text: 'āœ… Yes',
320
+ id: 'text_yes'
321
+ })
322
+ },
323
+ {
324
+ name: 'quick_reply',
325
+ buttonParamsJson: JSON.stringify({
326
+ display_text: 'āŒ No',
327
+ id: 'text_no'
328
+ })
329
+ }
330
+ ]
331
+ });
332
+
333
+ // Example: Send an image interactive message (modern Baileys format)
334
+
335
+ await client.sendButtons(msg.from, {
336
+ imagePath: './example.jpg',
337
+ caption: '', // Keep it short and concise
338
+ title: '', // Max 24 chars
339
+ subtitle: '', // Optional, appears below title
340
+ footer: '',
341
+ interactiveButtons: [
342
+ {
343
+ name: 'quick_reply',
344
+ buttonParamsJson: JSON.stringify({
345
+ display_text: 'šŸ‘ Like',
346
+ id: 'img_like'
347
+ })
348
+ },
349
+ {
350
+ name: 'quick_reply',
351
+ buttonParamsJson: JSON.stringify({
352
+ display_text: 'šŸ‘Ž Dislike',
353
+ id: 'img_dislike'
354
+ })
355
+ },
356
+
357
+ {
358
+ name: 'cta_call',
359
+ buttonParamsJson: JSON.stringify({
360
+ display_text: 'šŸ“ž Call Us',
361
+ phone_number: '+1234567890'
362
+ })
363
+ },
364
+ {
365
+ name: 'cta_url',
366
+ buttonParamsJson: JSON.stringify({
367
+ display_text: '🌐 Visit Website',
368
+ url: 'https://example.com',
369
+ merchant_url: 'https://example.com'
370
+ })
371
+ },
372
+ {
373
+ name: 'cta_copy',
374
+ buttonParamsJson: JSON.stringify({
375
+ display_text: 'šŸ”— Copy Link',
376
+ copy_code: 'https://example.com/copied'
377
+ })
378
+ }
379
+ ]
380
+ });
381
+ break
382
+
383
+ case '!help':
384
+ const help = `*šŸ“‹ Available Commands List*\n\n` +
385
+ `*šŸ”¹ Basic Commands*\n` +
386
+ `• !ping - Check if bot is alive\n` +
387
+ `• !echo <text> - Echo back your text\n` +
388
+ `• !help - Show this command list\n\n` +
389
+
390
+ `*šŸ’¬ Messaging*\n` +
391
+ `• !mention - Mention you in a message\n` +
392
+ `• !reply - Reply to your message\n` +
393
+ `• !react - React to your message with ā¤ļø\n` +
394
+ ` (Note: Reactions are auto-detected!)\n` +
395
+
396
+ `*šŸ–¼ļø Media & Content*\n` +
397
+ `• !media - Send an example image\n` +
398
+ `• !doc - Send an example document\n` +
399
+ `• !location - Send a location\n` +
400
+ `• !contact - Send a contact card\n` +
401
+ `• !sticker - Send an example sticker\n\n` +
402
+
403
+ `*šŸ‘„ Group Management*\n` +
404
+ `• !groups - List all your groups\n` +
405
+ `• !add <number> - Add participant\n` +
406
+ `• !invite <number> - Send group invite link\n` +
407
+ `• !remove <number> - Remove participant\n` +
408
+ `• !promote <number> - Make admin\n` +
409
+ `• !demote <number> - Remove admin\n\n` +
410
+
411
+ `*šŸŽ›ļø Templates & Buttons*\n` +
412
+ `• !buttons - Button template\n` +
413
+ `• !list - Scrollable list\n\n` +
414
+
415
+ `*šŸ” LID/PN/JID Management*\n` +
416
+ `• !lid - Get your LID\n` +
417
+ `• !pn <lid> - Get PN from LID\n` +
418
+ `• !parse <jid> - Parse JID info\n` +
419
+ `• !normalize <phone> - Normalize to JID\n\n` +
420
+
421
+ `*šŸ›”ļø Protection*\n` +
422
+ `• Anti-Delete: Automatically active\n\n` +
423
+
424
+ `*āš™ļø Admin Commands*\n` +
425
+ `• !read - Mark as read\n` +
426
+ `• !typing - Show typing indicator\n` +
427
+ `• !recording - Show recording indicator\n` +
428
+ `• !paused - Clear typing or recording indicator\n` +
429
+ `• !logout - End session\n\n` +
430
+
431
+ `*šŸ“ Note*:\nReplace <number> with phone number\n(without + or spaces)`
432
+ await client.sendMessage(msg.from, help)
433
+ break
434
+
435
+ case '!groups':
436
+ try {
437
+ const groups = await client.getAllGroups()
438
+ if (groups && groups.length > 0) {
439
+ let groupList = '*Your Groups:*\n\n'
440
+ groups.forEach((group, index) => {
441
+ groupList += `${index + 1}. *${group.subject}*\n`
442
+ groupList += ` ID: ${group.id}\n`
443
+ groupList += ` Members: ${group.participants.length}\n`
444
+ if (group.desc) groupList += ` Description: ${group.desc}\n`
445
+ groupList += '\n'
446
+ })
447
+ await client.sendMessage(msg.from, groupList)
448
+ } else {
449
+ await client.sendMessage(msg.from, 'You are not in any groups')
450
+ }
451
+ } catch (error) {
452
+ console.error('Error fetching groups:', error)
453
+ await client.sendMessage(msg.from, 'Failed to fetch groups')
454
+ }
455
+ break
456
+
457
+ case '!logout':
458
+ // Ask for confirmation before logging out
459
+ await client.sendButtons(msg.from, {
460
+ text: 'Are you sure you want to logout?',
461
+ title: 'Logout Confirmation',
462
+ footer: 'Choose Yes to logout or No to cancel',
463
+ interactiveButtons: [
464
+ {
465
+ name: 'quick_reply',
466
+ buttonParamsJson: JSON.stringify({
467
+ display_text: 'Yes',
468
+ id: 'logout_yes'
469
+ })
470
+ },
471
+ {
472
+ name: 'quick_reply',
473
+ buttonParamsJson: JSON.stringify({
474
+ display_text: 'No',
475
+ id: 'logout_no'
476
+ })
477
+ }
478
+ ]
479
+ });
480
+ break;
481
+ // Handle logout confirmation
482
+ case 'Yes':
483
+ case 'yes':
484
+ case 'logout_yes':
485
+
486
+ await client.sendMessage(msg.from, 'You have been logged out.');
487
+ await client.logout();
488
+ break;
489
+ case 'No':
490
+ case 'no':
491
+ case 'logout_no':
492
+ await client.sendMessage(msg.from, 'Logout cancelled.');
493
+ break;
494
+ case '!lid':
495
+ // Get LID for the user's phone number
496
+ try {
497
+ const lid = await client.getLIDForPN(msg.from);
498
+ if (lid) {
499
+ await client.sendMessage(msg.from, `Your LID: ${lid}\nYour PN: ${msg.from}`);
500
+ } else {
501
+ await client.sendMessage(msg.from, `No LID found for ${msg.from}. You might be using a PN-only session.`);
502
+ }
503
+ } catch (error) {
504
+ console.error('Error getting LID:', error);
505
+ await client.sendMessage(msg.from, 'Failed to get LID.');
506
+ }
507
+ break;
508
+
509
+ case '!pn':
510
+ // Get PN from LID
511
+ try {
512
+ const lidToCheck = args.trim();
513
+ if (!lidToCheck) {
514
+ await client.sendMessage(msg.from, 'Please provide a LID. Example: !pn 123456@lid');
515
+ break;
516
+ }
517
+ const pn = await client.getPNForLID(lidToCheck);
518
+ if (pn) {
519
+ await client.sendMessage(msg.from, `Phone Number for ${lidToCheck}: ${pn}`);
520
+ } else {
521
+ await client.sendMessage(msg.from, `No phone number found for LID: ${lidToCheck}`);
522
+ }
523
+ } catch (error) {
524
+ console.error('Error getting PN from LID:', error);
525
+ await client.sendMessage(msg.from, 'Failed to get phone number.');
526
+ }
527
+ break;
528
+ case '!ad':
529
+ await client.sendAdReply(
530
+ msg.from,
531
+ 'Ad Message',
532
+ './example.jpg',
533
+ 'Ad Title',
534
+ 'Ad Body',
535
+ 'https://m.facebook.com/innovatorssoft'
536
+ )
537
+ break;
538
+
539
+ case '!sticker':
540
+ if (fs.existsSync('./example.jpg')) {
541
+ const path = './example.jpg';
542
+ const imageBuffer = fs.readFileSync(path);
543
+ await client.sendSticker(msg.from, imageBuffer, { packName: 'Innovators', author: 'Innovators Soft' });
544
+ } else {
545
+ await client.sendMessage(msg.from, 'Example image (jpg) not found')
546
+ }
547
+ break;
548
+
549
+ case '!parse':
550
+ if (args) {
551
+ const info = client.parseJid(args);
552
+ await client.sendMessage(msg.from, `*JID Info:*\n\nUser: ${info.user}\nServer: ${info.server}\nIs LID: ${info.isLid}`);
553
+ } else {
554
+ await client.sendMessage(msg.from, 'Please provide a JID to parse');
555
+ }
556
+ break;
557
+
558
+ case '!normalize':
559
+ if (args) {
560
+ const jid = client.normalizePhoneToJid(args);
561
+ await client.sendMessage(msg.from, `*Normalized JID:* ${jid}`);
562
+ } else {
563
+ await client.sendMessage(msg.from, 'Please provide a phone number');
564
+ }
565
+ break;
566
+
567
+ case '!typing':
568
+ await client.sendStateTyping(msg.from);
569
+ await client.sendMessage(msg.from, 'Typing indicator sent!');
570
+ break;
571
+
572
+ case '!recording':
573
+ await client.sendStateRecording(msg.from);
574
+ await client.sendMessage(msg.from, 'Recording indicator sent!');
575
+ break;
576
+
577
+ case '!paused':
578
+ await client.clearState(msg.from);
579
+ await client.sendMessage(msg.from, 'Stopped typing/recording indicator sent!');
580
+ break;
581
+
582
+ case '!read':
583
+ await client.readMessage(msg.raw.key);
584
+ await client.sendMessage(msg.from, 'Message marked as read!');
585
+ break;
586
+
587
+ case '!add':
588
+ case '!remove':
589
+ case '!promote':
590
+ case '!demote':
591
+ try {
592
+ if (!msg.raw.key.remoteJid.endsWith('@g.us')) {
593
+ await client.sendMessage(msg.from, 'This command can only be used in groups')
594
+ break
595
+ }
596
+
597
+ const rawNumber = args.replace(/[^0-9]/g, '')
598
+
599
+ // Validate phone number format
600
+ if (!rawNumber || rawNumber.length < 10) {
601
+ await client.sendMessage(msg.from,
602
+ `āŒ Invalid phone number format.\n\n` +
603
+ `āœ… Correct format: !${command.slice(1)} 923001234567\n` +
604
+ `(Include country code without + or spaces)`
605
+ )
606
+ break
607
+ }
608
+
609
+ // Ensure country code is present (check if starts with common codes)
610
+ if (rawNumber.startsWith('0')) {
611
+ await client.sendMessage(msg.from,
612
+ `āŒ Phone number must include country code.\n\n` +
613
+ `Example:\n` +
614
+ `• Pakistan: 923001234567 (not 03001234567)\n` +
615
+ `• India: 919876543210 (not 09876543210)\n` +
616
+ `• USA: 14155551234 (not 4155551234)`
617
+ )
618
+ break
619
+ }
620
+
621
+ const number = rawNumber + '@s.whatsapp.net'
622
+
623
+ let action
624
+ switch (command) {
625
+ case '!add': action = 'add'; break
626
+ case '!remove': action = 'remove'; break
627
+ case '!promote': action = 'promote'; break
628
+ case '!demote': action = 'demote'; break
629
+ }
630
+
631
+ const result = await client.changeGroupParticipants(msg.raw.key.remoteJid, [number], action)
632
+ const actionMap = {
633
+ add: 'added to',
634
+ remove: 'removed from',
635
+ promote: 'promoted in',
636
+ demote: 'demoted in'
637
+ }
638
+
639
+ if (result[0].status == 200) {
640
+ await client.sendMessage(msg.from, `Successfully ${actionMap[action]} the group`)
641
+ } else if (result[0].status == 403 && result[0].invitationSent) {
642
+ await client.sendMessage(msg.from, `āš ļø Could not add directly due to privacy settings.\nāœ… Group invitation link has been sent to the user instead!`)
643
+ } else {
644
+ await client.sendMessage(msg.from, `Failed to ${action} participant: ${result[0].message || result[0].content || result[0].error || 'Unknown error'}`)
645
+ }
646
+ } catch (error) {
647
+ console.error(`Error ${command} participant:`, error)
648
+ if (error.output?.statusCode === 408) {
649
+ await client.sendMessage(msg.from, `ā±ļø Request timed out. The number might be invalid or not on WhatsApp.`)
650
+ } else {
651
+ await client.sendMessage(msg.from, `Failed to ${command.slice(1)} participant: ${error.message || 'Unknown error'}`)
652
+ }
653
+ }
654
+ break
655
+
656
+
657
+ case '!invite':
658
+ try {
659
+ if (!msg.raw.key.remoteJid.endsWith('@g.us')) {
660
+ await client.sendMessage(msg.from, 'This command can only be used in groups')
661
+ break
662
+ }
663
+
664
+ const rawInviteNumber = args.replace(/[^0-9]/g, '')
665
+
666
+ // Validate phone number format
667
+ if (!rawInviteNumber || rawInviteNumber.length < 10) {
668
+ await client.sendMessage(msg.from,
669
+ `āŒ Invalid phone number format.\n\n` +
670
+ `āœ… Correct format: !invite 923001234567\n` +
671
+ `(Include country code without + or spaces)`
672
+ )
673
+ break
674
+ }
675
+
676
+ // Ensure country code is present
677
+ if (rawInviteNumber.startsWith('0')) {
678
+ await client.sendMessage(msg.from,
679
+ `āŒ Phone number must include country code.\n\n` +
680
+ `Example:\n` +
681
+ `• Pakistan: 923001234567 (not 03001234567)\n` +
682
+ `• India: 919876543210 (not 09876543210)\n` +
683
+ `• USA: 14155551234 (not 4155551234)`
684
+ )
685
+ break
686
+ }
687
+
688
+ const inviteNumber = rawInviteNumber + '@s.whatsapp.net'
689
+
690
+ await client.sendGroupInvitation(msg.raw.key.remoteJid, inviteNumber)
691
+ await client.sendMessage(msg.from, `āœ… Group invitation sent to ${rawInviteNumber}`)
692
+ } catch (error) {
693
+ console.error('Error sending invitation:', error)
694
+ if (error.output?.statusCode === 408) {
695
+ await client.sendMessage(msg.from, `ā±ļø Request timed out. The number might be invalid or not on WhatsApp.`)
696
+ } else {
697
+ await client.sendMessage(msg.from, `Failed to send group invitation: ${error.message || 'Unknown error'}`)
698
+ }
699
+ }
700
+ break
701
+ }
702
+ })
703
+
704
+ // Listen for errors
705
+ client.on('error', error => {
706
+ console.error('Client Error:', error)
707
+ })
708
+ }
709
+
710
+ start();