baileys-joss 1.0.1 → 1.0.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.
Files changed (125) hide show
  1. package/README.md +1983 -79
  2. package/lib/Socket/business.d.ts +4 -0
  3. package/lib/Socket/business.d.ts.map +1 -1
  4. package/lib/Socket/chats.d.ts +4 -0
  5. package/lib/Socket/chats.d.ts.map +1 -1
  6. package/lib/Socket/chats.js +44 -1
  7. package/lib/Socket/chats.js.map +1 -1
  8. package/lib/Socket/communities.d.ts +4 -0
  9. package/lib/Socket/communities.d.ts.map +1 -1
  10. package/lib/Socket/groups.d.ts +4 -0
  11. package/lib/Socket/groups.d.ts.map +1 -1
  12. package/lib/Socket/index.d.ts +4 -0
  13. package/lib/Socket/index.d.ts.map +1 -1
  14. package/lib/Socket/messages-recv.d.ts +4 -0
  15. package/lib/Socket/messages-recv.d.ts.map +1 -1
  16. package/lib/Socket/messages-send.d.ts +4 -0
  17. package/lib/Socket/messages-send.d.ts.map +1 -1
  18. package/lib/Socket/newsletter.d.ts +4 -0
  19. package/lib/Socket/newsletter.d.ts.map +1 -1
  20. package/lib/Types/Message.d.ts +4 -0
  21. package/lib/Types/Message.d.ts.map +1 -1
  22. package/lib/Utils/activity-logger.d.ts +189 -0
  23. package/lib/Utils/activity-logger.d.ts.map +1 -0
  24. package/lib/Utils/activity-logger.js +418 -0
  25. package/lib/Utils/activity-logger.js.map +1 -0
  26. package/lib/Utils/anti-spam.d.ts +145 -0
  27. package/lib/Utils/anti-spam.d.ts.map +1 -0
  28. package/lib/Utils/anti-spam.js +398 -0
  29. package/lib/Utils/anti-spam.js.map +1 -0
  30. package/lib/Utils/auto-reply.d.ts +123 -0
  31. package/lib/Utils/auto-reply.d.ts.map +1 -0
  32. package/lib/Utils/auto-reply.js +234 -0
  33. package/lib/Utils/auto-reply.js.map +1 -0
  34. package/lib/Utils/broadcast.d.ts +121 -0
  35. package/lib/Utils/broadcast.d.ts.map +1 -0
  36. package/lib/Utils/broadcast.js +223 -0
  37. package/lib/Utils/broadcast.js.map +1 -0
  38. package/lib/Utils/bulk-messaging.d.ts +79 -0
  39. package/lib/Utils/bulk-messaging.d.ts.map +1 -0
  40. package/lib/Utils/bulk-messaging.js +148 -0
  41. package/lib/Utils/bulk-messaging.js.map +1 -0
  42. package/lib/Utils/chat-analytics.d.ts +92 -0
  43. package/lib/Utils/chat-analytics.d.ts.map +1 -0
  44. package/lib/Utils/chat-analytics.js +337 -0
  45. package/lib/Utils/chat-analytics.js.map +1 -0
  46. package/lib/Utils/chat-control.d.ts +156 -0
  47. package/lib/Utils/chat-control.d.ts.map +1 -0
  48. package/lib/Utils/chat-control.js +224 -0
  49. package/lib/Utils/chat-control.js.map +1 -0
  50. package/lib/Utils/chat-export.d.ts +75 -0
  51. package/lib/Utils/chat-export.d.ts.map +1 -0
  52. package/lib/Utils/chat-export.js +309 -0
  53. package/lib/Utils/chat-export.js.map +1 -0
  54. package/lib/Utils/content-detector.d.ts +199 -0
  55. package/lib/Utils/content-detector.d.ts.map +1 -0
  56. package/lib/Utils/content-detector.js +442 -0
  57. package/lib/Utils/content-detector.js.map +1 -0
  58. package/lib/Utils/index.d.ts +23 -0
  59. package/lib/Utils/index.d.ts.map +1 -1
  60. package/lib/Utils/index.js +52 -0
  61. package/lib/Utils/index.js.map +1 -1
  62. package/lib/Utils/link-scanner.d.ts +112 -0
  63. package/lib/Utils/link-scanner.d.ts.map +1 -0
  64. package/lib/Utils/link-scanner.js +433 -0
  65. package/lib/Utils/link-scanner.js.map +1 -0
  66. package/lib/Utils/media-downloader.d.ts +86 -0
  67. package/lib/Utils/media-downloader.d.ts.map +1 -0
  68. package/lib/Utils/media-downloader.js +269 -0
  69. package/lib/Utils/media-downloader.js.map +1 -0
  70. package/lib/Utils/meme-generator.d.ts +96 -0
  71. package/lib/Utils/meme-generator.d.ts.map +1 -0
  72. package/lib/Utils/meme-generator.js +368 -0
  73. package/lib/Utils/meme-generator.js.map +1 -0
  74. package/lib/Utils/message-search.d.ts +96 -0
  75. package/lib/Utils/message-search.d.ts.map +1 -0
  76. package/lib/Utils/message-search.js +261 -0
  77. package/lib/Utils/message-search.js.map +1 -0
  78. package/lib/Utils/messages-media.d.ts +20 -1
  79. package/lib/Utils/messages-media.d.ts.map +1 -1
  80. package/lib/Utils/messages-media.js +100 -5
  81. package/lib/Utils/messages-media.js.map +1 -1
  82. package/lib/Utils/messages.d.ts.map +1 -1
  83. package/lib/Utils/messages.js +9 -2
  84. package/lib/Utils/messages.js.map +1 -1
  85. package/lib/Utils/mini-games.d.ts +155 -0
  86. package/lib/Utils/mini-games.d.ts.map +1 -0
  87. package/lib/Utils/mini-games.js +445 -0
  88. package/lib/Utils/mini-games.js.map +1 -0
  89. package/lib/Utils/pomodoro.d.ts +139 -0
  90. package/lib/Utils/pomodoro.d.ts.map +1 -0
  91. package/lib/Utils/pomodoro.js +434 -0
  92. package/lib/Utils/pomodoro.js.map +1 -0
  93. package/lib/Utils/qr-generator.d.ts +95 -0
  94. package/lib/Utils/qr-generator.d.ts.map +1 -0
  95. package/lib/Utils/qr-generator.js +226 -0
  96. package/lib/Utils/qr-generator.js.map +1 -0
  97. package/lib/Utils/quotes.d.ts +110 -0
  98. package/lib/Utils/quotes.d.ts.map +1 -0
  99. package/lib/Utils/quotes.js +325 -0
  100. package/lib/Utils/quotes.js.map +1 -0
  101. package/lib/Utils/scheduling.d.ts +88 -0
  102. package/lib/Utils/scheduling.d.ts.map +1 -0
  103. package/lib/Utils/scheduling.js +163 -0
  104. package/lib/Utils/scheduling.js.map +1 -0
  105. package/lib/Utils/status-posting.d.ts +151 -0
  106. package/lib/Utils/status-posting.d.ts.map +1 -0
  107. package/lib/Utils/status-posting.js +162 -0
  108. package/lib/Utils/status-posting.js.map +1 -0
  109. package/lib/Utils/templates.d.ts +154 -0
  110. package/lib/Utils/templates.d.ts.map +1 -0
  111. package/lib/Utils/templates.js +368 -0
  112. package/lib/Utils/templates.js.map +1 -0
  113. package/lib/Utils/vcard.d.ts +86 -0
  114. package/lib/Utils/vcard.d.ts.map +1 -0
  115. package/lib/Utils/vcard.js +195 -0
  116. package/lib/Utils/vcard.js.map +1 -0
  117. package/lib/Utils/voice-note.d.ts +115 -0
  118. package/lib/Utils/voice-note.d.ts.map +1 -0
  119. package/lib/Utils/voice-note.js +212 -0
  120. package/lib/Utils/voice-note.js.map +1 -0
  121. package/lib/Utils/weather.d.ts +118 -0
  122. package/lib/Utils/weather.d.ts.map +1 -0
  123. package/lib/Utils/weather.js +362 -0
  124. package/lib/Utils/weather.js.map +1 -0
  125. package/package.json +6 -3
package/README.md CHANGED
@@ -37,6 +37,12 @@
37
37
  <a href="./docs/README.en.md">🇺🇸 English</a>
38
38
  </p>
39
39
 
40
+ <p align="center">
41
+ <b>🎮 Full Demo:</b>
42
+ <a href="https://gist.github.com/firdausmntp/07f4698578a38b63d2ff0f8990fdb2ee">📝 Complete Example Code (Gist)</a> |
43
+ <a href="./Example/wa-baileys-joss-complete.js">📁 Local Example File</a>
44
+ </p>
45
+
40
46
  ---
41
47
 
42
48
  ## ✨ Kenapa Baileys-Joss?
@@ -117,6 +123,141 @@
117
123
  <td align="center">❌</td>
118
124
  <td align="center">✅</td>
119
125
  </tr>
126
+ <tr>
127
+ <td>📸 HD Images (Uncompressed)</td>
128
+ <td align="center">❌</td>
129
+ <td align="center">✅</td>
130
+ </tr>
131
+ <tr>
132
+ <td>🎬 HD Videos (Uncompressed)</td>
133
+ <td align="center">❌</td>
134
+ <td align="center">✅</td>
135
+ </tr>
136
+ <tr>
137
+ <td>🌄 Panorama Profile Picture</td>
138
+ <td align="center">❌</td>
139
+ <td align="center">✅</td>
140
+ </tr>
141
+ <tr>
142
+ <td>📅 Message Scheduling</td>
143
+ <td align="center">❌</td>
144
+ <td align="center">✅</td>
145
+ </tr>
146
+ <tr>
147
+ <td>📨 Bulk Messaging</td>
148
+ <td align="center">❌</td>
149
+ <td align="center">✅</td>
150
+ </tr>
151
+ <tr>
152
+ <td>🔄 Auto Reply System</td>
153
+ <td align="center">❌</td>
154
+ <td align="center">✅</td>
155
+ </tr>
156
+ <tr>
157
+ <td>📇 Contact Card (vCard)</td>
158
+ <td align="center">⚠️ Basic</td>
159
+ <td align="center">✅ Enhanced</td>
160
+ </tr>
161
+ <tr>
162
+ <td>📺 Status/Story Posting</td>
163
+ <td align="center">⚠️ Basic</td>
164
+ <td align="center">✅ Enhanced</td>
165
+ </tr>
166
+ <tr>
167
+ <td>🎤 Voice Note Helper</td>
168
+ <td align="center">❌</td>
169
+ <td align="center">✅</td>
170
+ </tr>
171
+ <tr>
172
+ <td>📋 Message Templates</td>
173
+ <td align="center">❌</td>
174
+ <td align="center">✅</td>
175
+ </tr>
176
+ <tr>
177
+ <td>📡 Broadcast Manager</td>
178
+ <td align="center">❌</td>
179
+ <td align="center">✅</td>
180
+ </tr>
181
+ <tr>
182
+ <td>⌨️ Typing Indicator</td>
183
+ <td align="center">⚠️ Basic</td>
184
+ <td align="center">✅ Enhanced</td>
185
+ </tr>
186
+ <tr>
187
+ <td>✅ Read Receipt Control</td>
188
+ <td align="center">⚠️ Basic</td>
189
+ <td align="center">✅ Enhanced</td>
190
+ </tr>
191
+ <tr>
192
+ <td>🔍 Message Search</td>
193
+ <td align="center">❌</td>
194
+ <td align="center">✅</td>
195
+ </tr>
196
+ <tr>
197
+ <td>📊 Chat Analytics</td>
198
+ <td align="center">❌</td>
199
+ <td align="center">✅</td>
200
+ </tr>
201
+ <tr>
202
+ <td>💾 Chat Export</td>
203
+ <td align="center">❌</td>
204
+ <td align="center">✅</td>
205
+ </tr>
206
+ <tr>
207
+ <td>🔗 QR Code Generator</td>
208
+ <td align="center">⚠️ Basic</td>
209
+ <td align="center">✅ Enhanced</td>
210
+ </tr>
211
+ <tr>
212
+ <td>📁 Media Downloader</td>
213
+ <td align="center">❌</td>
214
+ <td align="center">✅</td>
215
+ </tr>
216
+ <tr>
217
+ <td>🎮 Mini Games</td>
218
+ <td align="center">❌</td>
219
+ <td align="center">⚠️ Untested</td>
220
+ </tr>
221
+ <tr>
222
+ <td>🔍 Content Detector</td>
223
+ <td align="center">❌</td>
224
+ <td align="center">⚠️ Untested</td>
225
+ </tr>
226
+ <tr>
227
+ <td>🛡️ Anti-Spam System</td>
228
+ <td align="center">❌</td>
229
+ <td align="center">⚠️ Untested</td>
230
+ </tr>
231
+ <tr>
232
+ <td>🔗 Link Scanner</td>
233
+ <td align="center">❌</td>
234
+ <td align="center">⚠️ Untested</td>
235
+ </tr>
236
+ <tr>
237
+ <td>📝 Activity Logger</td>
238
+ <td align="center">❌</td>
239
+ <td align="center">⚠️ Untested</td>
240
+ </tr>
241
+ <tr>
242
+ <td>🎭 Meme Generator</td>
243
+ <td align="center">❌</td>
244
+ <td align="center">⚠️ Untested</td>
245
+ </tr>
246
+ <tr>
247
+ <td>🍅 Pomodoro Timer</td>
248
+ <td align="center">❌</td>
249
+ <td align="center">⚠️ Untested</td>
250
+ </tr>
251
+ <tr>
252
+ <td>💬 Quote Generator</td>
253
+ <td align="center">❌</td>
254
+ <td align="center">⚠️ Untested</td>
255
+ </tr>
256
+ <tr>
257
+ <td>🌤️ Weather Bot</td>
258
+ <td align="center">❌</td>
259
+ <td align="center">⚠️ Untested</td>
260
+ </tr>
120
261
  </table>
121
262
 
122
263
  ---
@@ -301,6 +442,60 @@ await sock.sendMessage(jid, {
301
442
 
302
443
  </details>
303
444
 
445
+ <details>
446
+ <summary><h3>📸 HD Images & Videos (Uncompressed)</h3></summary>
447
+
448
+ Kirim gambar dan video tanpa kompresi dalam kualitas HD:
449
+
450
+ ```typescript
451
+ // Kirim gambar HD (kualitas tinggi, tidak dikompres)
452
+ await sock.sendMessage(jid, {
453
+ image: { url: './photo-hd.jpg' },
454
+ caption: 'Foto HD 📸',
455
+ hd: true // Kirim tanpa kompresi
456
+ })
457
+
458
+ // Kirim video HD
459
+ await sock.sendMessage(jid, {
460
+ video: { url: './video-4k.mp4' },
461
+ caption: 'Video 4K 🎬',
462
+ hd: true // Kualitas asli
463
+ })
464
+
465
+ // HD dengan media dari URL
466
+ await sock.sendMessage(jid, {
467
+ image: { url: 'https://example.com/high-res-photo.jpg' },
468
+ hd: true,
469
+ caption: 'High Resolution Photo'
470
+ })
471
+ ```
472
+
473
+ </details>
474
+
475
+ <details>
476
+ <summary><h3>🌄 Panorama Profile Picture</h3></summary>
477
+
478
+ Set foto profil panorama (wide) tanpa cropping:
479
+
480
+ ```typescript
481
+ // Set panorama profile picture (tidak di-crop square)
482
+ await sock.updatePanoramaProfilePicture(myJid, { url: './panorama.jpg' })
483
+
484
+ // Dengan opsi kustom
485
+ await sock.updatePanoramaProfilePicture(myJid, { url: './wide-photo.jpg' }, {
486
+ maxWidth: 1080, // Maximum width
487
+ quality: 90 // JPEG quality (1-100)
488
+ })
489
+
490
+ // Set panorama untuk grup
491
+ await sock.updatePanoramaProfilePicture(groupJid, { url: './group-banner.jpg' })
492
+
493
+ // Atau gunakan profile picture biasa (square crop)
494
+ await sock.updateProfilePicture(myJid, { url: './square-photo.jpg' })
495
+ ```
496
+
497
+ </details>
498
+
304
499
  <details>
305
500
  <summary><h3>📊 Poll Creation</h3></summary>
306
501
 
@@ -743,111 +938,1820 @@ await sock.groupParticipantsUpdate(group.id, [
743
938
 
744
939
  ---
745
940
 
746
- ## 📋 API Reference
941
+ ## 🆕 Baileys-Joss v1.0.2 New Features
747
942
 
748
943
  <details>
749
- <summary><b>🖱️ Interactive Messages</b></summary>
944
+ <summary><h3>📅 Message Scheduling</h3></summary>
750
945
 
751
- | Function | Description |
752
- |----------|-------------|
753
- | `generateInteractiveButtonMessage()` | Buat button message dengan media header |
754
- | `generateInteractiveListMessage()` | Buat list message dengan sections |
755
- | `generateTemplateMessage()` | Buat template message (Quick Reply, URL, Call) |
756
- | `generateNativeFlowMessage()` | Buat native flow message (format terbaru) |
757
- | `generateCopyCodeButton()` | Button untuk copy code |
758
- | `generateUrlButtonMessage()` | Button dengan URL |
759
- | `generateQuickReplyButtons()` | Quick reply buttons |
760
- | `generateCombinedButtons()` | Gabungan berbagai jenis button |
946
+ Jadwalkan pesan untuk dikirim otomatis di waktu tertentu:
761
947
 
762
- </details>
948
+ ```typescript
949
+ import { createMessageScheduler } from 'baileys-joss'
950
+
951
+ // Buat scheduler
952
+ const scheduler = createMessageScheduler(
953
+ (jid, content) => sock.sendMessage(jid, content),
954
+ {
955
+ onSent: (scheduled, message) => {
956
+ console.log(`Pesan terkirim ke ${scheduled.jid}`)
957
+ },
958
+ onFailed: (scheduled, error) => {
959
+ console.log(`Gagal kirim: ${error.message}`)
960
+ }
961
+ }
962
+ )
763
963
 
764
- <details>
765
- <summary><b>📍 JID Plotting</b></summary>
964
+ // Jadwalkan pesan untuk waktu tertentu
965
+ const scheduled = scheduler.schedule(
966
+ '6281234567890@s.whatsapp.net',
967
+ { text: 'Selamat Ulang Tahun! 🎂' },
968
+ new Date('2024-12-25 09:00:00')
969
+ )
766
970
 
767
- | Function | Description |
768
- |----------|-------------|
769
- | `parseJid()` | Parse JID dan extract info lengkap |
770
- | `getSenderPn()` | Get senderPn dari AuthenticationCreds |
771
- | `getCurrentSenderInfo()` | Get current sender info dari authState |
772
- | `isSelf()` | Check apakah JID adalah diri sendiri |
773
- | `plotJid()` | Plot JID (basic, tanpa LID mapping) |
774
- | `normalizePhoneToJid()` | Normalize nomor ke JID |
775
- | `extractPhoneNumber()` | Extract phone number dari JID |
776
- | `formatJidDisplay()` | Format JID untuk display |
777
- | `isSameUser()` | Compare dua JID |
778
- | `getJidVariants()` | Get semua variant JID dari nomor |
779
- | `constructJidWithDevice()` | Construct JID dengan device ID |
780
- | `getRemoteJidFromMessage()` | Get remoteJid dari message |
781
- | `createJidPlotter()` | Create plotter dengan LID mapping support |
971
+ // Jadwalkan dengan delay (30 menit dari sekarang)
972
+ scheduler.scheduleDelay(jid, { text: 'Reminder!' }, 30 * 60 * 1000)
973
+
974
+ // Cancel scheduled message
975
+ scheduler.cancel(scheduled.id)
976
+
977
+ // Get all pending messages
978
+ const pending = scheduler.getPending()
979
+
980
+ // Stop scheduler
981
+ scheduler.stop()
982
+ ```
782
983
 
783
984
  </details>
784
985
 
785
986
  <details>
786
- <summary><b>📢 Newsletter/Channel</b></summary>
987
+ <summary><h3>📨 Bulk Messaging</h3></summary>
787
988
 
788
- | Function | Description |
789
- |----------|-------------|
790
- | `newsletterCreate()` | Buat channel baru |
791
- | `newsletterUpdateName()` | Update nama channel |
792
- | `newsletterUpdateDescription()` | Update deskripsi channel |
793
- | `newsletterUpdatePicture()` | Update foto channel |
794
- | `newsletterFollow()` | Follow channel |
795
- | `newsletterUnfollow()` | Unfollow channel |
796
- | `newsletterMute()` | Mute notifikasi channel |
797
- | `newsletterUnmute()` | Unmute notifikasi channel |
798
- | `newsletterReactMessage()` | React ke pesan channel |
799
- | `newsletterMetadata()` | Get metadata channel |
800
- | `newsletterAdminCount()` | Get jumlah admin |
801
- | `newsletterChangeOwner()` | Ganti owner channel |
802
- | `newsletterDemote()` | Demote admin channel |
803
- | `newsletterDelete()` | Hapus channel |
989
+ Kirim pesan massal ke banyak kontak dengan rate limiting:
990
+
991
+ ```typescript
992
+ import { createBulkSender, sendBulkMessages } from 'baileys-joss'
993
+
994
+ // Method 1: Create bulk sender instance
995
+ const bulkSender = createBulkSender(
996
+ (jid, content) => sock.sendMessage(jid, content),
997
+ {
998
+ delayBetweenMessages: 2000, // 2 detik delay
999
+ randomDelay: 1000, // Random 0-1 detik tambahan
1000
+ maxRetries: 2,
1001
+ onProgress: (progress) => {
1002
+ console.log(`Progress: ${progress.sent}/${progress.total} (${progress.percentage}%)`)
1003
+ },
1004
+ onComplete: (results) => {
1005
+ const success = results.filter(r => r.success).length
1006
+ console.log(`Selesai: ${success}/${results.length} berhasil`)
1007
+ }
1008
+ }
1009
+ )
1010
+
1011
+ // Kirim pesan yang sama ke banyak JID
1012
+ const jids = [
1013
+ '6281234567890@s.whatsapp.net',
1014
+ '6281234567891@s.whatsapp.net',
1015
+ '6281234567892@s.whatsapp.net'
1016
+ ]
1017
+
1018
+ const results = await bulkSender.sendToMany(jids, { text: 'Hello everyone!' })
1019
+
1020
+ // Kirim pesan berbeda ke JID berbeda
1021
+ const messages = [
1022
+ { jid: '6281...@s.whatsapp.net', content: { text: 'Hi John!' } },
1023
+ { jid: '6282...@s.whatsapp.net', content: { text: 'Hi Jane!' } }
1024
+ ]
1025
+ await bulkSender.send(messages)
1026
+
1027
+ // Method 2: Quick helper
1028
+ await sendBulkMessages(
1029
+ (jid, content) => sock.sendMessage(jid, content),
1030
+ jids,
1031
+ { text: 'Broadcast message' }
1032
+ )
1033
+ ```
804
1034
 
805
1035
  </details>
806
1036
 
807
1037
  <details>
808
- <summary><b>👥 Group Management</b></summary>
1038
+ <summary><h3>🔄 Auto Reply System</h3></summary>
809
1039
 
810
- | Function | Description |
811
- |----------|-------------|
812
- | `groupCreate()` | Buat grup baru |
813
- | `groupUpdateSubject()` | Update nama grup |
814
- | `groupUpdateDescription()` | Update deskripsi grup |
815
- | `groupParticipantsUpdate()` | Add/remove/promote/demote member |
816
- | `groupSettingUpdate()` | Update pengaturan grup |
817
- | `groupMetadata()` | Get metadata grup |
818
- | `groupLeave()` | Keluar dari grup |
819
- | `groupInviteCode()` | Get kode invite grup |
820
- | `groupAcceptInvite()` | Join grup via invite code |
1040
+ Sistem balasan otomatis berdasarkan keyword/pattern:
1041
+
1042
+ ```typescript
1043
+ import { createAutoReply } from 'baileys-joss'
1044
+
1045
+ // Buat auto-reply handler
1046
+ const autoReply = createAutoReply(
1047
+ (jid, content, options) => sock.sendMessage(jid, content, options),
1048
+ (jid, presence) => sock.sendPresenceUpdate(presence, jid),
1049
+ {
1050
+ simulateTyping: true,
1051
+ typingDuration: 1500,
1052
+ globalCooldown: 1000
1053
+ }
1054
+ )
1055
+
1056
+ // Tambah rule berdasarkan keywords
1057
+ autoReply.addRule({
1058
+ keywords: ['harga', 'price', 'biaya'],
1059
+ response: { text: 'Silakan cek katalog kami di example.com' },
1060
+ cooldown: 60000, // 1 menit cooldown per user
1061
+ quoted: true // Reply dengan quote
1062
+ })
1063
+
1064
+ // Rule dengan regex pattern
1065
+ autoReply.addRule({
1066
+ pattern: /^(hi|hello|halo|hay)/i,
1067
+ response: { text: 'Hai! Ada yang bisa dibantu? 😊' },
1068
+ privateOnly: true // Hanya di private chat
1069
+ })
1070
+
1071
+ // Rule dengan dynamic response
1072
+ autoReply.addRule({
1073
+ keywords: ['order'],
1074
+ response: async (message, match) => {
1075
+ const sender = message.key.remoteJid
1076
+ return { text: `Terima kasih sudah order! ID: ${Date.now()}` }
1077
+ }
1078
+ })
1079
+
1080
+ // Rule untuk grup saja
1081
+ autoReply.addRule({
1082
+ exactMatch: '/menu',
1083
+ response: { text: 'Menu:\n1. Help\n2. Info\n3. Contact' },
1084
+ groupsOnly: true
1085
+ })
1086
+
1087
+ // Proses pesan masuk
1088
+ sock.ev.on('messages.upsert', async ({ messages }) => {
1089
+ for (const msg of messages) {
1090
+ if (!msg.key.fromMe) {
1091
+ await autoReply.processMessage(msg)
1092
+ }
1093
+ }
1094
+ })
1095
+ ```
821
1096
 
822
1097
  </details>
823
1098
 
824
1099
  <details>
825
- <summary><b>💬 Message Types</b></summary>
1100
+ <summary><h3>📇 Contact Card (vCard)</h3></summary>
826
1101
 
827
- | Type | Description |
828
- |------|-------------|
829
- | `text` | Pesan teks biasa |
830
- | `image` | Kirim gambar |
831
- | `video` | Kirim video |
832
- | `audio` | Kirim audio |
833
- | `document` | Kirim dokumen |
834
- | `sticker` | Kirim sticker |
835
- | `location` | Kirim lokasi |
836
- | `contacts` | Kirim kontak |
837
- | `poll` | Buat polling |
838
- | `album` | Kirim album (multiple media) |
839
- | `react` | React ke pesan |
840
- | `edit` | Edit pesan |
841
- | `delete` | Hapus pesan |
1102
+ Kirim kartu kontak lengkap dengan detail:
842
1103
 
843
- </details>
1104
+ ```typescript
1105
+ import {
1106
+ createContactCard,
1107
+ createContactCards,
1108
+ quickContact,
1109
+ generateVCard
1110
+ } from 'baileys-joss'
844
1111
 
845
- ---
1112
+ // Quick contact (simple)
1113
+ const simple = quickContact('John Doe', '+628123456789', {
1114
+ organization: 'PT Example',
1115
+ email: 'john@example.com'
1116
+ })
1117
+ await sock.sendMessage(jid, createContactCard(simple))
1118
+
1119
+ // Full vCard with all details
1120
+ const fullContact = {
1121
+ fullName: 'Dr. John Doe',
1122
+ displayName: 'John D.',
1123
+ organization: 'Hospital ABC',
1124
+ title: 'Senior Doctor',
1125
+ phones: [
1126
+ { number: '+628123456789', type: 'CELL' },
1127
+ { number: '+622112345678', type: 'WORK' }
1128
+ ],
1129
+ emails: [
1130
+ { email: 'john@hospital.com', type: 'WORK' },
1131
+ { email: 'john.personal@gmail.com', type: 'HOME' }
1132
+ ],
1133
+ urls: [
1134
+ { url: 'https://linkedin.com/in/johndoe', type: 'WORK' }
1135
+ ],
1136
+ addresses: [{
1137
+ street: 'Jl. Sudirman No. 123',
1138
+ city: 'Jakarta',
1139
+ state: 'DKI Jakarta',
1140
+ postalCode: '12345',
1141
+ country: 'Indonesia',
1142
+ type: 'WORK'
1143
+ }],
1144
+ birthday: '1990-05-15',
1145
+ note: 'Met at conference 2024'
1146
+ }
846
1147
 
847
- ## 🔄 Changelog
1148
+ await sock.sendMessage(jid, createContactCard(fullContact))
1149
+
1150
+ // Send multiple contacts
1151
+ const contacts = [
1152
+ quickContact('Alice', '+628111111111'),
1153
+ quickContact('Bob', '+628222222222'),
1154
+ quickContact('Charlie', '+628333333333')
1155
+ ]
1156
+ await sock.sendMessage(jid, createContactCards(contacts))
1157
+
1158
+ // Generate raw vCard string
1159
+ const vcardString = generateVCard(fullContact)
1160
+ console.log(vcardString)
1161
+ ```
1162
+
1163
+ </details>
1164
+
1165
+ <details>
1166
+ <summary><h3>📺 Status/Story Posting</h3></summary>
1167
+
1168
+ Posting status WhatsApp (foto, video, text):
1169
+
1170
+ ```typescript
1171
+ import {
1172
+ StatusHelper,
1173
+ STATUS_BROADCAST_JID,
1174
+ STATUS_BACKGROUNDS,
1175
+ STATUS_FONTS
1176
+ } from 'baileys-joss'
1177
+
1178
+ const statusJid = STATUS_BROADCAST_JID // 'status@broadcast'
1179
+
1180
+ // Post text status
1181
+ await sock.sendMessage(statusJid, StatusHelper.text(
1182
+ 'Hello World! 🌍',
1183
+ STATUS_BACKGROUNDS.solid.green
1184
+ ))
1185
+
1186
+ // Post image status
1187
+ const imageBuffer = fs.readFileSync('./my-photo.jpg')
1188
+ await sock.sendMessage(statusJid, StatusHelper.image(
1189
+ imageBuffer,
1190
+ 'Beautiful day! ☀️'
1191
+ ))
1192
+
1193
+ // Post video status
1194
+ const videoBuffer = fs.readFileSync('./my-video.mp4')
1195
+ await sock.sendMessage(statusJid, StatusHelper.video(
1196
+ videoBuffer,
1197
+ 'Check this out! 🎬'
1198
+ ))
1199
+
1200
+ // Post GIF status
1201
+ await sock.sendMessage(statusJid, StatusHelper.gif(
1202
+ gifBuffer,
1203
+ 'Animated! 🎭'
1204
+ ))
1205
+
1206
+ // Post voice note status
1207
+ await sock.sendMessage(statusJid, StatusHelper.voiceNote(audioBuffer))
1208
+
1209
+ // Custom text status with font
1210
+ import { createTextStatus } from 'baileys-joss'
1211
+
1212
+ await sock.sendMessage(statusJid, createTextStatus({
1213
+ text: 'Custom styled status!',
1214
+ backgroundColor: STATUS_BACKGROUNDS.solid.purple,
1215
+ font: STATUS_FONTS.DANCING,
1216
+ textColor: '#FFFFFF'
1217
+ }))
1218
+ ```
1219
+
1220
+ </details>
1221
+
1222
+ <details>
1223
+ <summary><h3>🎤 Voice Note Helper</h3></summary>
1224
+
1225
+ Rekam dan kirim voice note dengan PTT mode:
1226
+
1227
+ ```typescript
1228
+ import {
1229
+ createVoiceNote,
1230
+ createAudioMessage,
1231
+ VoiceNoteHelper
1232
+ } from 'baileys-joss'
1233
+
1234
+ // Simple voice note from buffer
1235
+ const voiceNote = await VoiceNoteHelper.fromBuffer(audioBuffer, 15) // 15 seconds
1236
+ await sock.sendMessage(jid, voiceNote)
1237
+
1238
+ // Voice note from file
1239
+ const vnFromFile = await VoiceNoteHelper.fromFile('./recording.mp3')
1240
+ await sock.sendMessage(jid, vnFromFile)
1241
+
1242
+ // Regular audio (not PTT)
1243
+ const audio = await VoiceNoteHelper.audioFromBuffer(audioBuffer)
1244
+ await sock.sendMessage(jid, audio)
1245
+
1246
+ // Check if FFmpeg is available (for conversions)
1247
+ const hasFFmpeg = await VoiceNoteHelper.checkFFmpeg()
1248
+
1249
+ // Convert audio to Opus (WhatsApp format)
1250
+ const opusBuffer = await VoiceNoteHelper.toOpus(mp3Buffer)
1251
+
1252
+ // Get audio duration
1253
+ const duration = await VoiceNoteHelper.getDuration(audioBuffer)
1254
+ console.log(`Audio duration: ${duration} seconds`)
1255
+
1256
+ // Full control with createVoiceNote
1257
+ const customVN = await createVoiceNote(audioBuffer, {
1258
+ seconds: 30,
1259
+ sampleRate: 48000,
1260
+ channels: 1
1261
+ })
1262
+ await sock.sendMessage(jid, customVN)
1263
+ ```
1264
+
1265
+ </details>
1266
+
1267
+ <details>
1268
+ <summary><h3>📋 Message Templates</h3></summary>
1269
+
1270
+ Template pesan siap pakai untuk berbagai keperluan:
1271
+
1272
+ ```typescript
1273
+ import { createTemplateManager, renderTemplate, PRESET_TEMPLATES } from 'baileys-joss'
1274
+
1275
+ // Create manager with preset templates
1276
+ const templates = createTemplateManager(true)
1277
+
1278
+ // Render preset template
1279
+ const orderConfirmation = templates.render('order_confirmation', {
1280
+ orderId: 'ORD-12345',
1281
+ customerName: 'John Doe',
1282
+ orderDate: '2024-01-15',
1283
+ items: '1x Product A\n2x Product B',
1284
+ total: '150,000'
1285
+ })
1286
+
1287
+ await sock.sendMessage(jid, { text: orderConfirmation })
1288
+
1289
+ // Create custom template
1290
+ templates.create({
1291
+ name: 'Welcome Message',
1292
+ content: `Halo {{name}}! 👋
1293
+
1294
+ Selamat datang di {{company}}!
1295
+
1296
+ Berikut layanan kami:
1297
+ {{services}}
1298
+
1299
+ Contact: {{phone:021-12345678}}`,
1300
+ category: 'greeting'
1301
+ })
1302
+
1303
+ // Render custom template
1304
+ const welcome = templates.render('welcome_message', {
1305
+ name: 'Budi',
1306
+ company: 'PT Example',
1307
+ services: '- Layanan A\n- Layanan B\n- Layanan C'
1308
+ })
1309
+
1310
+ // Quick template rendering (tanpa manager)
1311
+ const quick = renderTemplate(
1312
+ 'Hi {{name}}, your order #{{orderId}} is {{status:processing}}',
1313
+ { name: 'Alice', orderId: '123' }
1314
+ )
1315
+
1316
+ // List available templates
1317
+ const allTemplates = templates.getAll()
1318
+ const invoiceTemplates = templates.getByCategory('invoice')
1319
+
1320
+ // Export/Import templates
1321
+ const exportJson = templates.export()
1322
+ templates.import(exportJson, true) // true = overwrite existing
1323
+ ```
1324
+
1325
+ </details>
1326
+
1327
+ <details>
1328
+ <summary><h3>📡 Broadcast Manager</h3></summary>
1329
+
1330
+ Kelola dan kirim ke broadcast list:
1331
+
1332
+ ```typescript
1333
+ import { createBroadcastManager } from 'baileys-joss'
1334
+
1335
+ const broadcast = createBroadcastManager(
1336
+ (jid, content) => sock.sendMessage(jid, content)
1337
+ )
1338
+
1339
+ // Create broadcast list
1340
+ const customerList = broadcast.create({
1341
+ name: 'VIP Customers',
1342
+ description: 'Premium customers for promo',
1343
+ recipients: [
1344
+ '6281234567890@s.whatsapp.net',
1345
+ '6281234567891@s.whatsapp.net'
1346
+ ]
1347
+ })
1348
+
1349
+ // Add more recipients
1350
+ broadcast.addRecipients(customerList.id, [
1351
+ '6281234567892@s.whatsapp.net'
1352
+ ])
1353
+
1354
+ // Send to broadcast list
1355
+ const result = await broadcast.broadcast(
1356
+ customerList.id,
1357
+ { text: '🎉 Special promo for VIP customers!' },
1358
+ {
1359
+ delay: 2000,
1360
+ onProgress: (sent, total, jid) => {
1361
+ console.log(`Sending ${sent}/${total}: ${jid}`)
1362
+ }
1363
+ }
1364
+ )
1365
+
1366
+ console.log(`Sent: ${result.sent}, Failed: ${result.failed}`)
1367
+
1368
+ // Get statistics
1369
+ const stats = broadcast.getStats()
1370
+ console.log(`Total lists: ${stats.totalLists}, Recipients: ${stats.totalRecipients}`)
1371
+
1372
+ // Export/Import lists
1373
+ const json = broadcast.export()
1374
+ broadcast.import(json)
1375
+ ```
1376
+
1377
+ </details>
1378
+
1379
+ <details>
1380
+ <summary><h3>⌨️ Typing Indicator</h3></summary>
1381
+
1382
+ Simulasi sedang mengetik:
1383
+
1384
+ ```typescript
1385
+ import { createTypingIndicator } from 'baileys-joss'
1386
+
1387
+ const typing = createTypingIndicator(
1388
+ (jid, presence) => sock.sendPresenceUpdate(presence, jid)
1389
+ )
1390
+
1391
+ // Start typing
1392
+ await typing.startTyping(jid, {
1393
+ duration: 5000, // Auto pause after 5 seconds
1394
+ autoPause: true
1395
+ })
1396
+
1397
+ // Start recording (for voice notes)
1398
+ await typing.startRecording(jid, { duration: 3000 })
1399
+
1400
+ // Stop typing
1401
+ await typing.stopTyping(jid)
1402
+
1403
+ // Simulate typing then send
1404
+ await typing.simulateTyping(jid, 2000, async () => {
1405
+ return sock.sendMessage(jid, { text: 'Hello!' })
1406
+ })
1407
+
1408
+ // Stop all typing indicators
1409
+ await typing.stopAll()
1410
+ ```
1411
+
1412
+ </details>
1413
+
1414
+ <details>
1415
+ <summary><h3>✅ Read Receipt Control</h3></summary>
1416
+
1417
+ Kontrol centang biru:
1418
+
1419
+ ```typescript
1420
+ import { createReadReceiptController } from 'baileys-joss'
1421
+
1422
+ const readReceipts = createReadReceiptController(
1423
+ (jid, participant, messageIds) => sock.readMessages([{ remoteJid: jid, id: messageIds[0] }]),
1424
+ {
1425
+ enabled: true,
1426
+ readDelay: 1000, // 1 second delay
1427
+ excludeJids: ['blocked@s.whatsapp.net']
1428
+ }
1429
+ )
1430
+
1431
+ // Toggle read receipts
1432
+ readReceipts.disable() // Stop sending read receipts
1433
+ readReceipts.enable() // Resume
1434
+
1435
+ // Check status
1436
+ console.log(readReceipts.isEnabled())
1437
+
1438
+ // Manual read (respects config)
1439
+ await readReceipts.markRead(jid, participant, ['messageId123'])
1440
+
1441
+ // Force read (ignores config)
1442
+ await readReceipts.forceMarkRead(jid, participant, ['messageId123'])
1443
+
1444
+ // Update config
1445
+ readReceipts.setConfig({
1446
+ enabled: true,
1447
+ readDelay: 2000
1448
+ })
1449
+ ```
1450
+
1451
+ </details>
1452
+
1453
+ <details>
1454
+ <summary><h3>🔍 Message Search</h3></summary>
1455
+
1456
+ Cari pesan dalam chat:
1457
+
1458
+ ```typescript
1459
+ import { createMessageSearch, searchMessages } from 'baileys-joss'
1460
+
1461
+ // Create search manager
1462
+ const search = createMessageSearch()
1463
+
1464
+ // Add messages to index
1465
+ search.addMessages(chatMessages)
1466
+
1467
+ // Search by text
1468
+ const results = search.search('harga produk', {
1469
+ caseSensitive: false,
1470
+ limit: 20,
1471
+ messageTypes: ['text', 'image'], // Include captions
1472
+ fromDate: new Date('2024-01-01')
1473
+ })
1474
+
1475
+ for (const result of results) {
1476
+ console.log(`Found: "${result.matchedText}"`)
1477
+ console.log(`Score: ${result.relevanceScore}`)
1478
+ console.log(`Message ID: ${result.message.key.id}`)
1479
+ }
1480
+
1481
+ // Search with regex
1482
+ const regexResults = search.searchRegex(/order\s*#?\d+/i)
1483
+
1484
+ // Get messages by type
1485
+ const images = search.getByType('image')
1486
+ const videos = search.getByType('video')
1487
+
1488
+ // Get messages by sender
1489
+ const fromSender = search.getBySender('6281234567890@s.whatsapp.net')
1490
+
1491
+ // Quick search (without manager)
1492
+ const quickResults = searchMessages(messages, 'keyword', {
1493
+ jid: specificChatJid,
1494
+ fromMe: false
1495
+ })
1496
+ ```
1497
+
1498
+ </details>
1499
+
1500
+ <details>
1501
+ <summary><h3>📊 Chat Analytics</h3></summary>
1502
+
1503
+ Statistik dan analitik chat:
1504
+
1505
+ ```typescript
1506
+ import { createChatAnalytics } from 'baileys-joss'
1507
+
1508
+ const analytics = createChatAnalytics()
1509
+
1510
+ // Add messages for analysis
1511
+ analytics.addMessages(allMessages)
1512
+
1513
+ // Get stats for specific chat
1514
+ const chatStats = analytics.getChatStats('6281234567890@s.whatsapp.net')
1515
+
1516
+ console.log(`Total messages: ${chatStats.totalMessages}`)
1517
+ console.log(`From me: ${chatStats.messagesFromMe}`)
1518
+ console.log(`Media count: ${chatStats.mediaCount}`)
1519
+ console.log(`Links shared: ${chatStats.linkCount}`)
1520
+ console.log(`Emojis used: ${chatStats.emojiCount}`)
1521
+ console.log(`Most active hour: ${chatStats.mostActiveHour}:00`)
1522
+ console.log(`Most active day: ${chatStats.mostActiveDay}`)
1523
+ console.log(`Avg messages/day: ${chatStats.averageMessagesPerDay}`)
1524
+
1525
+ // Message breakdown by type
1526
+ console.log('Messages by type:', chatStats.messagesByType)
1527
+ // { text: 150, image: 45, video: 12, audio: 8, ... }
1528
+
1529
+ // Global stats across all chats
1530
+ const globalStats = analytics.getGlobalStats()
1531
+ console.log(`Total chats: ${globalStats.totalChats}`)
1532
+ console.log(`Total messages: ${globalStats.totalMessages}`)
1533
+ console.log(`Most active chat: ${globalStats.mostActiveChat?.jid}`)
1534
+
1535
+ // Activity analysis
1536
+ const hourlyActivity = analytics.getActivityByHour(jid) // Array[24]
1537
+ const dailyActivity = analytics.getActivityByDay(jid) // { Sunday: 10, Monday: 25, ... }
1538
+
1539
+ // Top participants in group
1540
+ const topParticipants = analytics.getTopParticipants(groupJid, 5)
1541
+ for (const p of topParticipants) {
1542
+ console.log(`${p.participant}: ${p.count} messages`)
1543
+ }
1544
+ ```
1545
+
1546
+ </details>
1547
+
1548
+ <details>
1549
+ <summary><h3>💾 Chat Export</h3></summary>
1550
+
1551
+ Export chat ke JSON, HTML, TXT, atau CSV:
1552
+
1553
+ ```typescript
1554
+ import { createChatExporter, exportChat } from 'baileys-joss'
1555
+
1556
+ const exporter = createChatExporter()
1557
+
1558
+ // Add messages
1559
+ exporter.addMessages(jid, chatMessages)
1560
+
1561
+ // Export to JSON
1562
+ const jsonExport = exporter.export(jid, {
1563
+ format: 'json',
1564
+ includeMediaInfo: true,
1565
+ includeMetadata: true
1566
+ })
1567
+
1568
+ fs.writeFileSync(jsonExport.filename, jsonExport.content)
1569
+
1570
+ // Export to HTML (readable format)
1571
+ const htmlExport = exporter.export(jid, {
1572
+ format: 'html',
1573
+ title: 'Chat dengan John',
1574
+ dateFormat: 'YYYY-MM-DD HH:mm'
1575
+ })
1576
+
1577
+ fs.writeFileSync(htmlExport.filename, htmlExport.content)
1578
+
1579
+ // Export to TXT (simple text)
1580
+ const txtExport = exporter.export(jid, {
1581
+ format: 'txt',
1582
+ dateRange: {
1583
+ start: new Date('2024-01-01'),
1584
+ end: new Date('2024-12-31')
1585
+ }
1586
+ })
1587
+
1588
+ // Export to CSV (for spreadsheet)
1589
+ const csvExport = exporter.export(jid, {
1590
+ format: 'csv',
1591
+ includeMetadata: true
1592
+ })
1593
+
1594
+ // Quick export (without manager)
1595
+ const result = exportChat(messages, jid, { format: 'json' })
1596
+ console.log(`Exported ${result.messageCount} messages`)
1597
+
1598
+ // Export all chats
1599
+ const allExports = exporter.exportAll({ format: 'json' })
1600
+ ```
1601
+
1602
+ </details>
1603
+
1604
+ <details>
1605
+ <summary><h3>🎮 Mini Games (UNTESTED ⚠️)</h3></summary>
1606
+
1607
+ Game sederhana untuk chat interaktif:
1608
+
1609
+ ```typescript
1610
+ import {
1611
+ MiniGamesManager,
1612
+ createTicTacToeGame,
1613
+ createQuiz
1614
+ } from 'baileys-joss'
1615
+
1616
+ // Create games manager
1617
+ const games = new MiniGamesManager()
1618
+
1619
+ // 🎯 Guess Number Game
1620
+ const guessSession = games.startGuessNumber('6281234567890@s.whatsapp.net', {
1621
+ minNumber: 1,
1622
+ maxNumber: 100,
1623
+ maxAttempts: 7
1624
+ })
1625
+
1626
+ // Handle guess
1627
+ const result = games.handleGuess(guessSession.id, 50)
1628
+ if (result.correct) {
1629
+ await sock.sendMessage(jid, { text: `🎉 Correct! The number was ${result.answer}` })
1630
+ } else {
1631
+ await sock.sendMessage(jid, { text: `${result.hint} (${result.remaining} attempts left)` })
1632
+ }
1633
+
1634
+ // 🧠 Quiz Game
1635
+ const quizSession = games.startQuiz(jid, {
1636
+ questions: [
1637
+ {
1638
+ question: 'Apa ibukota Indonesia?',
1639
+ options: ['Jakarta', 'Bandung', 'Surabaya', 'Medan'],
1640
+ correctIndex: 0,
1641
+ explanation: 'Jakarta adalah ibukota Indonesia sejak 1945'
1642
+ }
1643
+ ],
1644
+ category: 'geography'
1645
+ })
1646
+ await sock.sendMessage(jid, {
1647
+ text: `📝 Quiz:\n${quizSession.data.currentQuestion}\n\n${quizSession.data.options.map((o, i) => `${i+1}. ${o}`).join('\n')}`
1648
+ })
1649
+
1650
+ // ❌⭕ TicTacToe Game
1651
+ const tttSession = games.startTicTacToe(jid, player1Jid, player2Jid)
1652
+ const moveResult = games.handleMove(tttSession.id, player1Jid, 4) // Center position
1653
+
1654
+ await sock.sendMessage(jid, {
1655
+ text: `${games.renderBoard(tttSession)}\n\n${moveResult.message}`
1656
+ })
1657
+
1658
+ // 🎲 Quick Games
1659
+ const dice = games.rollDice() // { value: 1-6, emoji: '🎲' }
1660
+ const coin = games.flipCoin() // { result: 'heads'|'tails', emoji: '🪙' }
1661
+ const rps = games.playRockPaperScissors('rock', 'scissors') // { winner: 'player1', ... }
1662
+
1663
+ // 🏆 Leaderboard
1664
+ const leaderboard = games.getLeaderboard(10)
1665
+ ```
1666
+
1667
+ </details>
1668
+
1669
+ <details>
1670
+ <summary><h3>🔍 Content Detector (UNTESTED ⚠️)</h3></summary>
1671
+
1672
+ Deteksi otomatis berbagai jenis konten dalam pesan:
1673
+
1674
+ ```typescript
1675
+ import {
1676
+ ContentDetector,
1677
+ ContentFilter,
1678
+ hasLinks,
1679
+ hasPhoneNumbers,
1680
+ hasEmails,
1681
+ hasMediaContent
1682
+ } from 'baileys-joss'
1683
+
1684
+ // Create detector
1685
+ const detector = new ContentDetector()
1686
+
1687
+ // Full analysis
1688
+ const result = detector.analyze(message)
1689
+ console.log('Has media:', result.hasMedia)
1690
+ console.log('Media type:', result.mediaType)
1691
+ console.log('Links found:', result.links)
1692
+ console.log('Phone numbers:', result.phoneNumbers)
1693
+ console.log('Emails:', result.emails)
1694
+ console.log('Mentions:', result.mentions)
1695
+ console.log('Hashtags:', result.hashtags)
1696
+ console.log('Word count:', result.wordCount)
1697
+
1698
+ // Quick checks
1699
+ if (hasLinks(message)) {
1700
+ console.log('Message contains links!')
1701
+ }
1702
+ if (hasPhoneNumbers(message)) {
1703
+ console.log('Message contains phone numbers!')
1704
+ }
1705
+ if (hasMediaContent(message)) {
1706
+ console.log('Message has media attachment!')
1707
+ }
1708
+
1709
+ // Content filtering
1710
+ const filter = new ContentFilter({
1711
+ blockLinks: true,
1712
+ blockedDomains: ['spam.com', 'malware.xyz'],
1713
+ blockPhoneNumbers: false,
1714
+ sensitiveKeywords: ['spam', 'promo', 'click here'],
1715
+ maxMessageLength: 1000
1716
+ })
1717
+
1718
+ const filterResult = filter.check(message)
1719
+ if (!filterResult.allowed) {
1720
+ await sock.sendMessage(jid, {
1721
+ text: `⚠️ Message blocked: ${filterResult.blockedReason}`
1722
+ })
1723
+ }
1724
+ ```
1725
+
1726
+ </details>
1727
+
1728
+ <details>
1729
+ <summary><h3>🛡️ Anti-Spam System (UNTESTED ⚠️)</h3></summary>
1730
+
1731
+ Sistem untuk mendeteksi dan mencegah spam:
1732
+
1733
+ ```typescript
1734
+ import { AntiSpamManager } from 'baileys-joss'
1735
+
1736
+ // Create anti-spam manager
1737
+ const antispam = new AntiSpamManager({
1738
+ maxMessagesPerMinute: 15,
1739
+ maxDuplicates: 3,
1740
+ duplicateWindow: 60000, // 1 minute
1741
+ minMessageDelay: 500,
1742
+ whitelist: ['admin@s.whatsapp.net'],
1743
+ onSpamDetected: async (jid, message, result) => {
1744
+ console.log(`Spam detected from ${jid}: ${result.reason}`)
1745
+ if (result.action === 'mute') {
1746
+ await sock.sendMessage(jid, { text: '⚠️ You are muted for spamming!' })
1747
+ }
1748
+ }
1749
+ })
1750
+
1751
+ // Add custom spam pattern
1752
+ antispam.addRule({
1753
+ id: 'promo_spam',
1754
+ name: 'Promotional Spam',
1755
+ type: 'pattern',
1756
+ enabled: true,
1757
+ config: { patterns: [/FREE\s+\d+\s+TOKEN/i, /CLICK\s+HERE.*WIN/i] },
1758
+ action: 'delete'
1759
+ })
1760
+
1761
+ // Check incoming messages
1762
+ sock.ev.on('messages.upsert', async ({ messages }) => {
1763
+ for (const msg of messages) {
1764
+ const result = await antispam.checkMessage(msg)
1765
+
1766
+ if (result.isSpam) {
1767
+ console.log(`🛡️ Spam blocked! Score: ${result.score}, Reason: ${result.reason}`)
1768
+
1769
+ // Handle based on action
1770
+ if (result.action === 'delete') {
1771
+ await sock.sendMessage(msg.key.remoteJid, { delete: msg.key })
1772
+ } else if (result.action === 'warn') {
1773
+ await sock.sendMessage(msg.key.remoteJid, {
1774
+ text: `⚠️ Warning: ${result.reason}`
1775
+ })
1776
+ }
1777
+ continue
1778
+ }
1779
+
1780
+ // Process non-spam message...
1781
+ }
1782
+ })
1783
+
1784
+ // Whitelist trusted users
1785
+ antispam.whitelist('trusteduser@s.whatsapp.net')
1786
+
1787
+ // Mute spammer temporarily
1788
+ antispam.muteUser('spammer@s.whatsapp.net', 3600) // 1 hour
1789
+
1790
+ // Ban repeat offender
1791
+ antispam.banUser('baduser@s.whatsapp.net')
1792
+
1793
+ // Get spam statistics
1794
+ const stats = antispam.getStats()
1795
+ console.log('Total spam blocked:', stats.totalBlocked)
1796
+ ```
1797
+
1798
+ </details>
1799
+
1800
+ <details>
1801
+ <summary><h3>🔗 Link Scanner (UNTESTED ⚠️)</h3></summary>
1802
+
1803
+ Scan dan validasi URL untuk keamanan:
1804
+
1805
+ ```typescript
1806
+ import { LinkScanner, scanUrls, isUrlSafe } from 'baileys-joss'
1807
+
1808
+ // Create scanner
1809
+ const scanner = new LinkScanner({
1810
+ followRedirects: true,
1811
+ maxRedirects: 5,
1812
+ timeout: 5000,
1813
+ enablePhishingDetection: true
1814
+ })
1815
+
1816
+ // Scan single URL
1817
+ const result = await scanner.scanUrl('https://suspicious-link.xyz/login')
1818
+ console.log('Safe:', result.safe)
1819
+ console.log('Risk level:', result.riskLevel) // 'safe' | 'low' | 'medium' | 'high' | 'critical'
1820
+ console.log('Threats:', result.threats)
1821
+ console.log('Details:', result.details)
1822
+
1823
+ // Scan all URLs in a message
1824
+ const messageResults = await scanner.scanMessage(message)
1825
+ for (const urlResult of messageResults) {
1826
+ if (!urlResult.safe) {
1827
+ await sock.sendMessage(jid, {
1828
+ text: `⚠️ Warning! Suspicious link detected:\n${urlResult.url}\n\nRisk: ${urlResult.riskLevel}\nThreats: ${urlResult.threats.join(', ')}`
1829
+ })
1830
+ }
1831
+ }
1832
+
1833
+ // Quick safety check
1834
+ const isSafe = await scanner.isUrlSafe('https://example.com')
1835
+
1836
+ // Add custom patterns
1837
+ scanner.addPhishingPattern(/banking.*verify.*account/i)
1838
+ scanner.addTrustedDomain('mytrusted.com')
1839
+ scanner.addMaliciousDomain('known-scam.xyz')
1840
+
1841
+ // Auto-scan in message handler
1842
+ sock.ev.on('messages.upsert', async ({ messages }) => {
1843
+ for (const msg of messages) {
1844
+ const scanResults = await scanner.scanMessage(msg)
1845
+ const dangerous = scanResults.filter(r => r.riskLevel === 'high' || r.riskLevel === 'critical')
1846
+
1847
+ if (dangerous.length > 0) {
1848
+ await sock.sendMessage(msg.key.remoteJid, {
1849
+ text: `🚨 Dangerous link(s) detected! ${dangerous.length} threat(s) found.`
1850
+ }, { quoted: msg })
1851
+ }
1852
+ }
1853
+ })
1854
+ ```
1855
+
1856
+ </details>
1857
+
1858
+ <details>
1859
+ <summary><h3>📝 Activity Logger (UNTESTED ⚠️)</h3></summary>
1860
+
1861
+ Logging aktivitas untuk audit trail:
1862
+
1863
+ ```typescript
1864
+ import { ActivityLogger } from 'baileys-joss'
1865
+
1866
+ // Create logger
1867
+ const logger = new ActivityLogger({
1868
+ fileLogging: true,
1869
+ logFilePath: './logs/bot-activity.log',
1870
+ maxMemoryEntries: 1000,
1871
+ maxFileSize: 10 * 1024 * 1024, // 10MB
1872
+ minLevel: 'info',
1873
+ categories: ['message', 'user', 'group', 'bot'],
1874
+ onLog: (entry) => {
1875
+ if (entry.level === 'error') {
1876
+ // Send alert to admin
1877
+ console.error(`[ALERT] ${entry.action}: ${entry.details.message}`)
1878
+ }
1879
+ }
1880
+ })
1881
+
1882
+ // Log message activity
1883
+ logger.logMessage(message, 'received', {
1884
+ processed: true,
1885
+ responseTime: 150
1886
+ })
1887
+
1888
+ // Log user action
1889
+ logger.logUserAction('6281234567890@s.whatsapp.net', 'command_executed', {
1890
+ command: '/help',
1891
+ success: true
1892
+ })
1893
+
1894
+ // Log group action
1895
+ logger.logGroupAction('groupjid@g.us', 'member_added', {
1896
+ addedBy: 'admin@s.whatsapp.net',
1897
+ newMember: 'newuser@s.whatsapp.net'
1898
+ })
1899
+
1900
+ // Log custom activity
1901
+ logger.log({
1902
+ level: 'info',
1903
+ category: 'bot',
1904
+ action: 'scheduled_task',
1905
+ actor: 'system',
1906
+ details: { task: 'daily_backup', status: 'completed' }
1907
+ })
1908
+
1909
+ // Query logs
1910
+ const recentErrors = logger.query({
1911
+ level: 'error',
1912
+ fromDate: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24 hours
1913
+ limit: 50
1914
+ })
1915
+
1916
+ // Get statistics
1917
+ const stats = logger.getStats()
1918
+ console.log('Total entries:', stats.totalEntries)
1919
+ console.log('By level:', stats.byLevel)
1920
+ console.log('Top actors:', stats.topActors)
1921
+
1922
+ // Export logs
1923
+ const jsonLogs = logger.export('json')
1924
+ const csvLogs = logger.export('csv')
1925
+ ```
1926
+
1927
+ </details>
1928
+
1929
+ <details>
1930
+ <summary><h3>🎭 Meme Generator (UNTESTED ⚠️)</h3></summary>
1931
+
1932
+ Generate meme sederhana dengan text overlay:
1933
+
1934
+ ```typescript
1935
+ import {
1936
+ MemeGenerator,
1937
+ MEME_TEMPLATES,
1938
+ drakeMeme,
1939
+ expandingBrainMeme,
1940
+ thisIsFineMeme
1941
+ } from 'baileys-joss'
1942
+
1943
+ // Create generator
1944
+ const meme = new MemeGenerator()
1945
+
1946
+ // List available templates
1947
+ const templates = meme.getTemplates()
1948
+ console.log('Available templates:', templates.map(t => t.name))
1949
+
1950
+ // Generate Drake meme (quick helper)
1951
+ const drake = drakeMeme(
1952
+ 'Debugging code manually', // Rejected
1953
+ 'Using console.log everywhere' // Approved
1954
+ )
1955
+ await sock.sendMessage(jid, { text: drake.htmlContent })
1956
+
1957
+ // Generate Expanding Brain meme
1958
+ const brain = expandingBrainMeme([
1959
+ 'Using var',
1960
+ 'Using let',
1961
+ 'Using const',
1962
+ 'Using TypeScript'
1963
+ ])
1964
+ await sock.sendMessage(jid, { text: brain.htmlContent })
1965
+
1966
+ // Generate "This is Fine" meme
1967
+ const fine = thisIsFineMeme('Production is on fire but it\'s fine')
1968
+ await sock.sendMessage(jid, { text: fine.htmlContent })
1969
+
1970
+ // Custom meme with template
1971
+ const custom = meme.generateTextMeme({
1972
+ template: 'distracted',
1973
+ texts: {
1974
+ boyfriend: 'Me',
1975
+ girlfriend: 'My deadlines',
1976
+ other: 'New side project'
1977
+ },
1978
+ fontSize: 24,
1979
+ fontColor: '#ffffff'
1980
+ })
1981
+
1982
+ // Generate SVG meme (for advanced use)
1983
+ const svgMeme = meme.generateSvgMeme({
1984
+ template: 'two_buttons',
1985
+ texts: {
1986
+ button1: 'Sleep early',
1987
+ button2: 'One more episode'
1988
+ }
1989
+ })
1990
+
1991
+ // Send as formatted text meme
1992
+ await sock.sendMessage(jid, {
1993
+ text: `🎭 *MEME*\n\n${custom.htmlContent}`
1994
+ })
1995
+ ```
1996
+
1997
+ </details>
1998
+
1999
+ <details>
2000
+ <summary><h3>🍅 Pomodoro Timer (UNTESTED ⚠️)</h3></summary>
2001
+
2002
+ Timer produktivitas dengan teknik Pomodoro:
2003
+
2004
+ ```typescript
2005
+ import { PomodoroManager, DEFAULT_POMODORO_CONFIG } from 'baileys-joss'
2006
+
2007
+ // Create pomodoro manager
2008
+ const pomodoro = new PomodoroManager()
2009
+
2010
+ // Register event handler
2011
+ pomodoro.onEvent(async (event) => {
2012
+ const jid = event.session.jid
2013
+
2014
+ switch (event.type) {
2015
+ case 'work_start':
2016
+ await sock.sendMessage(jid, {
2017
+ text: `🍅 *WORK SESSION STARTED*\n\n⏱️ Duration: 25 minutes\n🎯 Session: ${event.session.currentSession}/${event.session.totalSessions}\n\n💪 Stay focused!`
2018
+ })
2019
+ break
2020
+ case 'work_end':
2021
+ await sock.sendMessage(jid, {
2022
+ text: `✅ *WORK SESSION COMPLETE!*\n\n🎉 Great job! Time for a break.\n\nType /break to start break timer.`
2023
+ })
2024
+ break
2025
+ case 'break_start':
2026
+ await sock.sendMessage(jid, {
2027
+ text: `☕ *BREAK TIME*\n\n⏱️ Duration: 5 minutes\n\n🧘 Relax and recharge!`
2028
+ })
2029
+ break
2030
+ case 'break_end':
2031
+ await sock.sendMessage(jid, {
2032
+ text: `⏰ *BREAK OVER!*\n\nReady for next session?\nType /work to continue.`
2033
+ })
2034
+ break
2035
+ }
2036
+ })
2037
+
2038
+ // Start work session
2039
+ const session = pomodoro.start('6281234567890@s.whatsapp.net', {
2040
+ workDuration: 25, // 25 minutes
2041
+ shortBreakDuration: 5, // 5 minutes
2042
+ longBreakDuration: 15, // 15 minutes
2043
+ sessionsBeforeLongBreak: 4,
2044
+ autoStartBreaks: true
2045
+ })
2046
+
2047
+ // Pause/Resume
2048
+ pomodoro.pause(jid)
2049
+ pomodoro.resume(jid)
2050
+
2051
+ // Start break manually
2052
+ pomodoro.startBreak(jid)
2053
+
2054
+ // Get current status
2055
+ const status = pomodoro.status(jid)
2056
+ console.log('Status:', status.status) // 'work' | 'short_break' | 'long_break' | 'paused'
2057
+ console.log('Time remaining:', status.remainingTime)
2058
+ console.log('Current session:', status.currentSession)
2059
+
2060
+ // Stop and reset
2061
+ pomodoro.stop(jid)
2062
+
2063
+ // Get statistics
2064
+ const stats = pomodoro.stats(jid)
2065
+ console.log('Total work sessions:', stats.totalWorkSessions)
2066
+ console.log('Total work minutes:', stats.totalWorkMinutes)
2067
+ console.log('Current streak:', stats.currentStreak)
2068
+ ```
2069
+
2070
+ </details>
2071
+
2072
+ <details>
2073
+ <summary><h3>💬 Quote Generator (UNTESTED ⚠️)</h3></summary>
2074
+
2075
+ Random quotes dan quotes harian:
2076
+
2077
+ ```typescript
2078
+ import {
2079
+ QuoteManager,
2080
+ getRandomQuote,
2081
+ getQuoteOfTheDay,
2082
+ getMotivationalQuote,
2083
+ getIslamicQuote,
2084
+ getFunnyQuote,
2085
+ quoteCommand,
2086
+ QUOTES
2087
+ } from 'baileys-joss'
2088
+
2089
+ // Quick helpers
2090
+ const random = getRandomQuote()
2091
+ await sock.sendMessage(jid, {
2092
+ text: `💬 *Quote*\n\n"${random.text}"\n\n— ${random.author}`
2093
+ })
2094
+
2095
+ // Quote of the day (same quote all day)
2096
+ const qotd = getQuoteOfTheDay()
2097
+ await sock.sendMessage(jid, {
2098
+ text: `📅 *Quote of the Day*\n\n"${qotd.quote.text}"\n\n— ${qotd.quote.author}`
2099
+ })
2100
+
2101
+ // Category-specific quotes
2102
+ const motivational = getMotivationalQuote()
2103
+ const islamic = getIslamicQuote()
2104
+ const funny = getFunnyQuote()
2105
+
2106
+ // Using QuoteManager for more control
2107
+ const quoteManager = new QuoteManager()
2108
+
2109
+ // Get quote by category
2110
+ const loveQuote = quoteManager.getByCategory('love')
2111
+ const wisdomQuote = quoteManager.getByCategory('wisdom')
2112
+
2113
+ // Get quote by language
2114
+ const indonesianQuote = quoteManager.getByLanguage('id')
2115
+ const englishQuote = quoteManager.getByLanguage('en')
2116
+
2117
+ // Search quotes
2118
+ const searchResults = quoteManager.search('success')
2119
+
2120
+ // Add custom quote
2121
+ quoteManager.addQuote({
2122
+ id: 'custom1',
2123
+ text: 'My custom inspirational quote',
2124
+ author: 'Me',
2125
+ category: 'inspirational',
2126
+ language: 'en'
2127
+ })
2128
+
2129
+ // Parse command (for bot integration)
2130
+ // Supported: /quote, /quote motivational, /quote islamic, /quote funny
2131
+ const commandResult = quoteCommand('/quote motivational')
2132
+ await sock.sendMessage(jid, { text: commandResult })
2133
+
2134
+ // Send random quote with formatting
2135
+ const formatted = quoteManager.format(getRandomQuote(), {
2136
+ style: 'fancy', // 'simple' | 'fancy' | 'minimal'
2137
+ includeCategory: true
2138
+ })
2139
+ await sock.sendMessage(jid, { text: formatted })
2140
+ ```
2141
+
2142
+ </details>
2143
+
2144
+ <details>
2145
+ <summary><h3>🌤️ Weather Bot (UNTESTED ⚠️)</h3></summary>
2146
+
2147
+ Informasi cuaca dengan integrasi OpenWeatherMap:
2148
+
2149
+ ```typescript
2150
+ import {
2151
+ WeatherBot,
2152
+ getWeather,
2153
+ getSimpleWeather,
2154
+ weatherCommand
2155
+ } from 'baileys-joss'
2156
+
2157
+ // Create weather bot (with API key for full features)
2158
+ const weather = new WeatherBot({
2159
+ apiKey: 'YOUR_OPENWEATHERMAP_API_KEY', // Optional: enables API mode
2160
+ units: 'metric', // 'metric' | 'imperial'
2161
+ language: 'id',
2162
+ defaultCity: 'Jakarta'
2163
+ })
2164
+
2165
+ // Get weather for a city
2166
+ const data = await weather.getWeather('Jakarta')
2167
+ await sock.sendMessage(jid, {
2168
+ text: `🌤️ *Weather in ${data.city}, ${data.country}*\n\n🌡️ Temperature: ${data.temperature}°C\n🤒 Feels like: ${data.feelsLike}°C\n💧 Humidity: ${data.humidity}%\n💨 Wind: ${data.windSpeed} m/s\n☁️ Condition: ${data.description}\n\n🌅 Sunrise: ${new Date(data.sunrise * 1000).toLocaleTimeString()}\n🌇 Sunset: ${new Date(data.sunset * 1000).toLocaleTimeString()}`
2169
+ })
2170
+
2171
+ // Quick helper (uses sample data if no API key)
2172
+ const simpleWeather = await getSimpleWeather('Tokyo')
2173
+ await sock.sendMessage(jid, { text: simpleWeather })
2174
+
2175
+ // Get 5-day forecast
2176
+ const forecast = await weather.getForecast('Singapore')
2177
+ let forecastText = `📅 *5-Day Forecast for ${forecast.city}*\n\n`
2178
+ for (const day of forecast.forecasts.slice(0, 5)) {
2179
+ forecastText += `${day.date}: ${day.temperature}°C, ${day.description}\n`
2180
+ }
2181
+ await sock.sendMessage(jid, { text: forecastText })
2182
+
2183
+ // Weather alerts
2184
+ const alerts = await weather.getAlerts('Miami')
2185
+ if (alerts.length > 0) {
2186
+ for (const alert of alerts) {
2187
+ await sock.sendMessage(jid, {
2188
+ text: `⚠️ *Weather Alert*\n\n${alert.event}\n\nSeverity: ${alert.severity}\n${alert.description}`
2189
+ })
2190
+ }
2191
+ }
2192
+
2193
+ // Parse weather command (for bot integration)
2194
+ // Supported: /weather Jakarta, /cuaca Bandung
2195
+ const result = await weatherCommand('/weather Singapore', weather)
2196
+ await sock.sendMessage(jid, { text: result })
2197
+
2198
+ // Format with emoji
2199
+ const formatted = weather.formatWeather(data, {
2200
+ includeEmoji: true,
2201
+ includeDetails: true,
2202
+ language: 'id'
2203
+ })
2204
+ await sock.sendMessage(jid, { text: formatted })
2205
+ ```
2206
+
2207
+ </details>
2208
+
2209
+ <details>
2210
+ <summary><h3>🔗 QR Code Generator</h3></summary>
2211
+
2212
+ Generate QR code custom untuk pairing:
2213
+
2214
+ ```typescript
2215
+ import {
2216
+ createQRGenerator,
2217
+ QRHelper,
2218
+ createQRHandler,
2219
+ createWhatsAppQR
2220
+ } from 'baileys-joss'
2221
+
2222
+ // Quick QR generation
2223
+ const terminalQR = await QRHelper.terminal(pairingCode)
2224
+ console.log(terminalQR)
2225
+
2226
+ // Generate SVG QR
2227
+ const svgQR = await QRHelper.svg(pairingCode, {
2228
+ size: 300,
2229
+ foregroundColor: '#128C7E', // WhatsApp green
2230
+ backgroundColor: '#FFFFFF'
2231
+ })
2232
+
2233
+ // Generate base64 QR (for web)
2234
+ const base64QR = await QRHelper.base64(pairingCode)
2235
+
2236
+ // Generate PNG buffer
2237
+ const pngBuffer = await QRHelper.buffer(pairingCode)
2238
+ fs.writeFileSync('qr.png', pngBuffer)
2239
+
2240
+ // Custom generator
2241
+ const generator = createQRGenerator({
2242
+ size: 256,
2243
+ errorCorrectionLevel: 'H',
2244
+ foregroundColor: '#000000',
2245
+ margin: 4
2246
+ })
2247
+
2248
+ const qr = await generator.generate(data)
2249
+
2250
+ // WhatsApp-styled QR
2251
+ const waQR = await createWhatsAppQR(pairingCode)
2252
+
2253
+ // Use as QR event handler
2254
+ const sock = makeWASocket({
2255
+ // ...
2256
+ printQRInTerminal: false
2257
+ })
2258
+
2259
+ sock.ev.on('connection.update', async ({ qr }) => {
2260
+ if (qr) {
2261
+ const qrHandler = createQRHandler({
2262
+ maxAttempts: 5,
2263
+ onQR: (rendered, raw, attempt) => {
2264
+ console.log(`\nScan QR (${attempt}/5):\n`)
2265
+ console.log(rendered)
2266
+ }
2267
+ })
2268
+ await qrHandler(qr)
2269
+ }
2270
+ })
2271
+ ```
2272
+
2273
+ </details>
2274
+
2275
+ <details>
2276
+ <summary><h3>📁 Media Downloader</h3></summary>
2277
+
2278
+ Download semua media dari chat:
2279
+
2280
+ ```typescript
2281
+ import { createMediaDownloader, downloadAllMedia } from 'baileys-joss'
2282
+
2283
+ const downloader = createMediaDownloader(
2284
+ async (key) => store.loadMessage(key.remoteJid, key.id)
2285
+ )
2286
+
2287
+ // Download all media from chat
2288
+ const summary = await downloader.downloadFromChat(
2289
+ '6281234567890@s.whatsapp.net',
2290
+ chatMessages,
2291
+ {
2292
+ outputDir: './downloads/john-doe',
2293
+ types: ['image', 'video', 'document'], // or ['all']
2294
+ createSubfolders: true, // images/, videos/, etc.
2295
+ skipExisting: true,
2296
+ maxFileSize: 50 * 1024 * 1024, // 50MB limit
2297
+ delay: 500, // Delay between downloads
2298
+ onProgress: (current, total, filename) => {
2299
+ console.log(`Downloading ${current}/${total}: ${filename}`)
2300
+ },
2301
+ onError: (msg, error) => {
2302
+ console.log(`Failed: ${error.message}`)
2303
+ }
2304
+ }
2305
+ )
2306
+
2307
+ console.log(`Downloaded: ${summary.successful}/${summary.total}`)
2308
+ console.log(`Total size: ${(summary.totalSize / 1024 / 1024).toFixed(2)} MB`)
2309
+ console.log(`Failed: ${summary.failed}`)
2310
+
2311
+ // Download single media
2312
+ const singleResult = await downloader.downloadSingle(
2313
+ mediaMessage,
2314
+ './downloads',
2315
+ { filenameTemplate: '{type}_{date}_{id}{ext}' }
2316
+ )
2317
+
2318
+ // Quick download all (without manager)
2319
+ await downloadAllMedia(messages, './downloads/all-media', {
2320
+ types: ['image'],
2321
+ onProgress: (curr, total) => console.log(`${curr}/${total}`)
2322
+ })
2323
+ ```
2324
+
2325
+ </details>
2326
+
2327
+ ---
2328
+
2329
+ ## 📋 API Reference
2330
+
2331
+ <details>
2332
+ <summary><b>🖱️ Interactive Messages</b></summary>
2333
+
2334
+ | Function | Description |
2335
+ |----------|-------------|
2336
+ | `generateInteractiveButtonMessage()` | Buat button message dengan media header |
2337
+ | `generateInteractiveListMessage()` | Buat list message dengan sections |
2338
+ | `generateTemplateMessage()` | Buat template message (Quick Reply, URL, Call) |
2339
+ | `generateNativeFlowMessage()` | Buat native flow message (format terbaru) |
2340
+ | `generateCopyCodeButton()` | Button untuk copy code |
2341
+ | `generateUrlButtonMessage()` | Button dengan URL |
2342
+ | `generateQuickReplyButtons()` | Quick reply buttons |
2343
+ | `generateCombinedButtons()` | Gabungan berbagai jenis button |
2344
+
2345
+ </details>
2346
+
2347
+ <details>
2348
+ <summary><b>📍 JID Plotting</b></summary>
2349
+
2350
+ | Function | Description |
2351
+ |----------|-------------|
2352
+ | `parseJid()` | Parse JID dan extract info lengkap |
2353
+ | `getSenderPn()` | Get senderPn dari AuthenticationCreds |
2354
+ | `getCurrentSenderInfo()` | Get current sender info dari authState |
2355
+ | `isSelf()` | Check apakah JID adalah diri sendiri |
2356
+ | `plotJid()` | Plot JID (basic, tanpa LID mapping) |
2357
+ | `normalizePhoneToJid()` | Normalize nomor ke JID |
2358
+ | `extractPhoneNumber()` | Extract phone number dari JID |
2359
+ | `formatJidDisplay()` | Format JID untuk display |
2360
+ | `isSameUser()` | Compare dua JID |
2361
+ | `getJidVariants()` | Get semua variant JID dari nomor |
2362
+ | `constructJidWithDevice()` | Construct JID dengan device ID |
2363
+ | `getRemoteJidFromMessage()` | Get remoteJid dari message |
2364
+ | `createJidPlotter()` | Create plotter dengan LID mapping support |
2365
+
2366
+ </details>
2367
+
2368
+ <details>
2369
+ <summary><b>📢 Newsletter/Channel</b></summary>
2370
+
2371
+ | Function | Description |
2372
+ |----------|-------------|
2373
+ | `newsletterCreate()` | Buat channel baru |
2374
+ | `newsletterUpdateName()` | Update nama channel |
2375
+ | `newsletterUpdateDescription()` | Update deskripsi channel |
2376
+ | `newsletterUpdatePicture()` | Update foto channel |
2377
+ | `newsletterFollow()` | Follow channel |
2378
+ | `newsletterUnfollow()` | Unfollow channel |
2379
+ | `newsletterMute()` | Mute notifikasi channel |
2380
+ | `newsletterUnmute()` | Unmute notifikasi channel |
2381
+ | `newsletterReactMessage()` | React ke pesan channel |
2382
+ | `newsletterMetadata()` | Get metadata channel |
2383
+ | `newsletterAdminCount()` | Get jumlah admin |
2384
+ | `newsletterChangeOwner()` | Ganti owner channel |
2385
+ | `newsletterDemote()` | Demote admin channel |
2386
+ | `newsletterDelete()` | Hapus channel |
2387
+
2388
+ </details>
2389
+
2390
+ <details>
2391
+ <summary><b>👥 Group Management</b></summary>
2392
+
2393
+ | Function | Description |
2394
+ |----------|-------------|
2395
+ | `groupCreate()` | Buat grup baru |
2396
+ | `groupUpdateSubject()` | Update nama grup |
2397
+ | `groupUpdateDescription()` | Update deskripsi grup |
2398
+ | `groupParticipantsUpdate()` | Add/remove/promote/demote member |
2399
+ | `groupSettingUpdate()` | Update pengaturan grup |
2400
+ | `groupMetadata()` | Get metadata grup |
2401
+ | `groupLeave()` | Keluar dari grup |
2402
+ | `groupInviteCode()` | Get kode invite grup |
2403
+ | `groupAcceptInvite()` | Join grup via invite code |
2404
+
2405
+ </details>
2406
+
2407
+ <details>
2408
+ <summary><b>💬 Message Types</b></summary>
2409
+
2410
+ | Type | Description |
2411
+ |------|-------------|
2412
+ | `text` | Pesan teks biasa |
2413
+ | `image` | Kirim gambar (dengan opsi `hd: true` untuk kualitas HD) |
2414
+ | `video` | Kirim video (dengan opsi `hd: true` untuk kualitas HD) |
2415
+ | `audio` | Kirim audio |
2416
+ | `document` | Kirim dokumen |
2417
+ | `sticker` | Kirim sticker |
2418
+ | `location` | Kirim lokasi |
2419
+ | `contacts` | Kirim kontak |
2420
+ | `poll` | Buat polling |
2421
+ | `album` | Kirim album (multiple media) |
2422
+ | `react` | React ke pesan |
2423
+ | `edit` | Edit pesan |
2424
+ | `delete` | Hapus pesan |
2425
+
2426
+ </details>
2427
+
2428
+ <details>
2429
+ <summary><b>📷 Profile Picture</b></summary>
2430
+
2431
+ | Function | Description |
2432
+ |----------|-------------|
2433
+ | `updateProfilePicture()` | Update foto profil (square crop) |
2434
+ | `updatePanoramaProfilePicture()` | Update foto profil panorama (wide, tidak di-crop) |
2435
+ | `removeProfilePicture()` | Hapus foto profil |
2436
+ | `profilePictureUrl()` | Get URL foto profil |
2437
+
2438
+ </details>
2439
+
2440
+ <details>
2441
+ <summary><b>🎮 Mini Games (UNTESTED ⚠️)</b></summary>
2442
+
2443
+ | Function | Description |
2444
+ |----------|-------------|
2445
+ | `MiniGamesManager` | Main class untuk manage semua games |
2446
+ | `games.startGuessNumber()` | Start guess number game |
2447
+ | `games.startQuiz()` | Start quiz game |
2448
+ | `games.startTicTacToe()` | Start TicTacToe (vs bot/player) |
2449
+ | `games.playRockPaperScissors()` | Play RPS game |
2450
+ | `games.rollDice()` | Roll dice (1-6) |
2451
+ | `games.flipCoin()` | Flip a coin |
2452
+ | `games.handleGuess()` | Handle guess input |
2453
+ | `games.handleMove()` | Handle TicTacToe move |
2454
+ | `games.getLeaderboard()` | Get player leaderboard |
2455
+
2456
+ </details>
2457
+
2458
+ <details>
2459
+ <summary><b>🔍 Content Detector (UNTESTED ⚠️)</b></summary>
2460
+
2461
+ | Function | Description |
2462
+ |----------|-------------|
2463
+ | `ContentDetector` | Main class untuk detect content |
2464
+ | `detector.analyze()` | Full content analysis |
2465
+ | `hasLinks()` | Quick check for URLs |
2466
+ | `hasPhoneNumbers()` | Quick check for phone numbers |
2467
+ | `hasEmails()` | Quick check for emails |
2468
+ | `hasMediaContent()` | Check if message has media |
2469
+ | `isForwarded()` | Check if message is forwarded |
2470
+ | `ContentFilter` | Filter messages by criteria |
2471
+
2472
+ </details>
2473
+
2474
+ <details>
2475
+ <summary><b>🛡️ Anti-Spam (UNTESTED ⚠️)</b></summary>
2476
+
2477
+ | Function | Description |
2478
+ |----------|-------------|
2479
+ | `AntiSpamManager` | Main anti-spam class |
2480
+ | `antispam.checkMessage()` | Check if message is spam |
2481
+ | `antispam.addRule()` | Add custom spam rule |
2482
+ | `antispam.muteUser()` | Mute user temporarily |
2483
+ | `antispam.banUser()` | Ban user permanently |
2484
+ | `antispam.whitelist()` | Add user to whitelist |
2485
+ | `antispam.getStats()` | Get spam statistics |
2486
+
2487
+ </details>
2488
+
2489
+ <details>
2490
+ <summary><b>🔗 Link Scanner (UNTESTED ⚠️)</b></summary>
2491
+
2492
+ | Function | Description |
2493
+ |----------|-------------|
2494
+ | `LinkScanner` | Main URL security scanner |
2495
+ | `scanner.scanUrl()` | Scan single URL |
2496
+ | `scanner.scanMessage()` | Scan all URLs in message |
2497
+ | `scanner.isUrlSafe()` | Quick safety check |
2498
+ | `scanner.addPhishingPattern()` | Add custom phishing pattern |
2499
+ | `scanner.addTrustedDomain()` | Add trusted domain |
2500
+
2501
+ </details>
2502
+
2503
+ <details>
2504
+ <summary><b>📝 Activity Logger (UNTESTED ⚠️)</b></summary>
2505
+
2506
+ | Function | Description |
2507
+ |----------|-------------|
2508
+ | `ActivityLogger` | Main logging class |
2509
+ | `logger.log()` | Log custom activity |
2510
+ | `logger.logMessage()` | Log message activity |
2511
+ | `logger.logUserAction()` | Log user action |
2512
+ | `logger.logGroupAction()` | Log group action |
2513
+ | `logger.query()` | Query logs with filters |
2514
+ | `logger.getStats()` | Get activity statistics |
2515
+
2516
+ </details>
2517
+
2518
+ <details>
2519
+ <summary><b>🎭 Meme Generator (UNTESTED ⚠️)</b></summary>
2520
+
2521
+ | Function | Description |
2522
+ |----------|-------------|
2523
+ | `MemeGenerator` | Main meme class |
2524
+ | `meme.generateTextMeme()` | Generate ASCII text meme |
2525
+ | `meme.generateSvgMeme()` | Generate SVG meme |
2526
+ | `meme.getTemplates()` | List available templates |
2527
+ | `drakeMeme()` | Quick Drake meme |
2528
+ | `expandingBrainMeme()` | Quick Expanding Brain meme |
2529
+ | `thisIsFineMeme()` | Quick "This is Fine" meme |
2530
+
2531
+ </details>
2532
+
2533
+ <details>
2534
+ <summary><b>🍅 Pomodoro Timer (UNTESTED ⚠️)</b></summary>
2535
+
2536
+ | Function | Description |
2537
+ |----------|-------------|
2538
+ | `PomodoroManager` | Main timer class |
2539
+ | `pomodoro.start()` | Start work session |
2540
+ | `pomodoro.break()` | Start break |
2541
+ | `pomodoro.pause()` | Pause timer |
2542
+ | `pomodoro.resume()` | Resume timer |
2543
+ | `pomodoro.stop()` | Stop and reset |
2544
+ | `pomodoro.status()` | Get current status |
2545
+ | `pomodoro.stats()` | Get statistics |
2546
+
2547
+ </details>
2548
+
2549
+ <details>
2550
+ <summary><b>💬 Quote Generator (UNTESTED ⚠️)</b></summary>
2551
+
2552
+ | Function | Description |
2553
+ |----------|-------------|
2554
+ | `QuoteManager` | Main quote class |
2555
+ | `getRandomQuote()` | Get random quote |
2556
+ | `getQuoteOfTheDay()` | Get daily quote |
2557
+ | `getMotivationalQuote()` | Get motivational quote |
2558
+ | `getIslamicQuote()` | Get Islamic quote |
2559
+ | `getFunnyQuote()` | Get funny quote |
2560
+ | `quoteCommand()` | Parse quote command |
2561
+
2562
+ </details>
2563
+
2564
+ <details>
2565
+ <summary><b>🌤️ Weather Bot (UNTESTED ⚠️)</b></summary>
2566
+
2567
+ | Function | Description |
2568
+ |----------|-------------|
2569
+ | `WeatherBot` | Main weather class |
2570
+ | `weather.getWeather()` | Get weather for city |
2571
+ | `weather.setApiKey()` | Set OpenWeatherMap API key |
2572
+ | `getWeather()` | Quick weather helper |
2573
+ | `getSimpleWeather()` | Get simplified weather |
2574
+ | `weatherCommand()` | Parse weather command |
2575
+
2576
+ </details>
2577
+
2578
+ ---
2579
+
2580
+ ## 🔄 Changelog
2581
+
2582
+ <details open>
2583
+ <summary><b>v1.0.2</b> - Latest (BIG UPDATE! 🎉)</summary>
2584
+
2585
+ ### 🆕 New Features
2586
+
2587
+ **🎮 Mini Games (UNTESTED ⚠️)**
2588
+ - Guess Number game with hints
2589
+ - Quiz with multiple categories
2590
+ - TicTacToe (vs Bot or 2 players)
2591
+ - Rock Paper Scissors
2592
+ - Dice Roll & Coin Flip
2593
+ - Score tracking and leaderboards
2594
+
2595
+ **🔍 Content Detector (UNTESTED ⚠️)**
2596
+ - URL/Link detection with extraction
2597
+ - Phone number detection
2598
+ - Email detection
2599
+ - Media type detection (image, video, audio, document, sticker)
2600
+ - Mention and hashtag extraction
2601
+ - Emoji analysis
2602
+ - Sensitive content filtering
2603
+ - Forwarded message detection
2604
+
2605
+ **🛡️ Anti-Spam System (UNTESTED ⚠️)**
2606
+ - Rate limiting per user
2607
+ - Duplicate message detection
2608
+ - Flood protection
2609
+ - Pattern-based spam detection
2610
+ - User mute/ban functionality
2611
+ - Whitelist support
2612
+ - Customizable rules and thresholds
2613
+
2614
+ **🔗 Link Scanner (UNTESTED ⚠️)**
2615
+ - URL security analysis
2616
+ - Phishing detection with pattern matching
2617
+ - URL shortener expansion
2618
+ - Suspicious TLD detection
2619
+ - Domain reputation checking
2620
+ - Risk level scoring (safe/low/medium/high/critical)
2621
+ - Redirect following for shortened URLs
2622
+
2623
+ **📝 Activity Logger (UNTESTED ⚠️)**
2624
+ - Audit trail logging
2625
+ - Multiple log levels (debug, info, warn, error, critical)
2626
+ - Category-based logging (message, user, group, bot, security)
2627
+ - File logging with rotation support
2628
+ - Query and search logs
2629
+ - Statistics and analytics
2630
+ - Memory and file output options
2631
+
2632
+ **🎭 Meme Generator (UNTESTED ⚠️)**
2633
+ - Text-based meme templates
2634
+ - Popular meme formats (Drake, Expanding Brain, Two Buttons, etc.)
2635
+ - SVG/HTML output generation
2636
+ - Custom template support
2637
+ - Quick meme helpers
2638
+
2639
+ **🍅 Pomodoro Timer (UNTESTED ⚠️)**
2640
+ - Productivity timer with Pomodoro technique
2641
+ - Configurable work/break durations
2642
+ - Session tracking and statistics
2643
+ - Pause/resume functionality
2644
+ - Auto-start options
2645
+ - Streak tracking
2646
+
2647
+ **💬 Quote Generator (UNTESTED ⚠️)**
2648
+ - 40+ built-in quotes (English & Indonesian)
2649
+ - Multiple categories (motivational, inspirational, love, life, success, wisdom, funny, islamic, philosophy)
2650
+ - Quote of the day feature
2651
+ - Search quotes by text or author
2652
+ - Custom quote support
2653
+ - Formatted output styles
2654
+
2655
+ **🌤️ Weather Bot (UNTESTED ⚠️)**
2656
+ - Real-time weather information
2657
+ - OpenWeatherMap API integration
2658
+ - Mock data for offline use
2659
+ - Detailed weather display (temp, humidity, wind, etc.)
2660
+ - Weather advice based on conditions
2661
+ - Multiple city support
2662
+ - Caching for performance
2663
+
2664
+ **📅 Message Scheduling**
2665
+ - Schedule messages for future delivery
2666
+ - Delay-based scheduling
2667
+ - Cancel/manage scheduled messages
2668
+
2669
+ **📨 Bulk Messaging**
2670
+ - Send to multiple recipients with rate limiting
2671
+ - Progress tracking and callbacks
2672
+ - Retry mechanism with error handling
2673
+
2674
+ **🔄 Auto Reply System**
2675
+ - Keyword-based auto replies
2676
+ - Regex pattern matching
2677
+ - Cooldown per user/rule
2678
+ - Group/private chat filters
2679
+
2680
+ **📇 Contact Card (vCard)**
2681
+ - Full vCard generation with all fields
2682
+ - Multi-contact support
2683
+ - Quick contact helper
2684
+
2685
+ **📺 Status/Story Posting**
2686
+ - Text status with backgrounds & fonts
2687
+ - Image/video/voice note status
2688
+ - Pre-defined backgrounds & styles
2689
+
2690
+ **🎤 Voice Note Helper**
2691
+ - Audio conversion to Opus format
2692
+ - PTT mode support
2693
+ - Duration detection
2694
+
2695
+ **📋 Message Templates**
2696
+ - Pre-built templates (order, invoice, etc.)
2697
+ - Variable substitution
2698
+ - Export/import templates
2699
+
2700
+ **📡 Broadcast Manager**
2701
+ - Create and manage broadcast lists
2702
+ - Send to multiple lists
2703
+ - Statistics and tracking
2704
+
2705
+ **⌨️ Typing Indicator**
2706
+ - Start/stop typing simulation
2707
+ - Recording indicator for voice notes
2708
+ - Auto-pause functionality
2709
+
2710
+ **✅ Read Receipt Control**
2711
+ - Enable/disable read receipts
2712
+ - Delay before marking read
2713
+ - Exclude specific JIDs
2714
+
2715
+ **🔍 Message Search**
2716
+ - Full-text search in messages
2717
+ - Regex support
2718
+ - Filter by type, date, sender
2719
+
2720
+ **📊 Chat Analytics**
2721
+ - Message statistics
2722
+ - Activity by hour/day
2723
+ - Top participants
2724
+ - Media/link/emoji counts
2725
+
2726
+ **💾 Chat Export**
2727
+ - Export to JSON, HTML, TXT, CSV
2728
+ - Customizable templates
2729
+ - Date range filtering
2730
+
2731
+ **🔗 QR Code Generator**
2732
+ - Multiple output formats (terminal, SVG, PNG, base64)
2733
+ - Customizable colors and styles
2734
+ - WhatsApp-styled QR
2735
+
2736
+ **📁 Media Downloader**
2737
+ - Batch download media from chats
2738
+ - Progress tracking
2739
+ - Type filtering and size limits
2740
+
2741
+ ### ✨ Improvements
2742
+ - ✨ **HD Images & Videos** - Send uncompressed media with `hd: true`
2743
+ - ✨ **Panorama Profile Picture** - Set wide/panoramic profile pictures without cropping
2744
+ - ✨ Higher quality thumbnails for HD mode
2745
+ - 📸 Better image quality preservation
2746
+ - 🎬 Video quality improvements
2747
+ - 📝 Added complete demo code example
2748
+ - 🎨 Improved documentation structure
2749
+ - 🐛 Bug fixes and performance improvements
2750
+
2751
+ </details>
848
2752
 
849
2753
  <details>
850
- <summary><b>v1.0.1</b> - Latest</summary>
2754
+ <summary><b>v1.0.1</b></summary>
851
2755
 
852
2756
  - ✨ Added Album Messages support (carousel format)
853
2757
  - ✨ Added AI Message Style (`ai: true`) - shows AI indicator on messages