@nuiisweety/baileys 0.1.10 โ†’ 0.1.12

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/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  *Fork dari [`@whiskeysockets/baileys`](https://github.com/WhiskeySockets/Baileys) v7.0.0-rc11*
8
8
  *dikembangkan dengan sepenuh hati oleh **NuiiS4TORU***
9
9
 
10
- [![npm version](https://img.shields.io/badge/npm-0.1.10-pink?style=flat-square&logo=npm)](https://www.npmjs.com/package/@nuiisweety/baileys)
10
+ [![npm version](https://img.shields.io/badge/npm-0.1.12-pink?style=flat-square&logo=npm)](https://www.npmjs.com/package/@nuiisweety/baileys)
11
11
  [![license](https://img.shields.io/badge/license-MIT-lavender?style=flat-square)](LICENSE)
12
12
  [![based on](https://img.shields.io/badge/based%20on-@whiskeysockets%2Fbaileys-orchid?style=flat-square)](https://github.com/WhiskeySockets/Baileys)
13
13
 
@@ -72,6 +72,7 @@
72
72
  [Secure Meta Label](#secure-meta-service-label)
73
73
 
74
74
  ๐ŸŽ›๏ธ **Interactive** โ€”
75
+ [Buttons Location Header](#buttons-dengan-location-header-buttonsmessage-langsung) ยท
75
76
  [Buttons](#buttons) ยท
76
77
  [List Message](#list-message) ยท
77
78
  [Template Buttons](#template-buttons) ยท
@@ -927,11 +928,85 @@ await sock.sendMessage(jid, {
927
928
 
928
929
  ---
929
930
 
931
+ <details>
932
+ <summary>๐Ÿ“ Buttons dengan Location Header (buttonsMessage langsung)</summary>
933
+
934
+ Kirim tombol menggunakan `buttonsMessage` secara langsung โ€” berguna untuk header tipe **Location** (`headerType: 6`) yang tidak bisa dibuat lewat shorthand `buttons`.
935
+
936
+ ```js
937
+ // Tombol dengan header lokasi (headerType 6)
938
+ await sock.sendMessage(jid, {
939
+ buttonsMessage: {
940
+ locationMessage: {
941
+ degreesLatitude: 0,
942
+ degreesLongitude: 0,
943
+ name: 'NuiiSweety',
944
+ address: 'NuiiSweety Bot',
945
+ jpegThumbnail: './src/img/menu.jpg' // path file, URL, atau Buffer
946
+ },
947
+ contentText: 'Pilih menu di bawah ini',
948
+ footerText: 'Powered by @nuiisweety/baileys',
949
+ buttons: [
950
+ { buttonId: 'allmenu', buttonText: { displayText: 'All Menu' }, type: 1 }
951
+ ],
952
+ headerType: 6
953
+ }
954
+ })
955
+
956
+ // Dengan quoted (reply ke pesan tertentu)
957
+ await sock.sendMessage(jid, {
958
+ buttonsMessage: {
959
+ locationMessage: {
960
+ degreesLatitude: -6.2,
961
+ degreesLongitude: 106.8,
962
+ name: 'Menu Bot',
963
+ address: 'NuiiSweety',
964
+ jpegThumbnail: './src/img/menu.jpg'
965
+ },
966
+ contentText: 'Halo! Ini menu utama bot',
967
+ footerText: 'NuiiSweety Bot',
968
+ buttons: [
969
+ { buttonId: 'menu1', buttonText: { displayText: '๐Ÿฑ Menu Utama' }, type: 1 },
970
+ { buttonId: 'help', buttonText: { displayText: 'โ“ Bantuan' }, type: 1 }
971
+ ],
972
+ headerType: 6
973
+ }
974
+ }, { quoted: m })
975
+
976
+ // Header kosong (teks saja, tanpa media/lokasi) โ€” headerType 1
977
+ await sock.sendMessage(jid, {
978
+ buttonsMessage: {
979
+ contentText: 'Pilih opsi',
980
+ footerText: 'Bot Footer',
981
+ buttons: [
982
+ { buttonId: 'yes', buttonText: { displayText: 'Ya' }, type: 1 },
983
+ { buttonId: 'no', buttonText: { displayText: 'Tidak' }, type: 1 }
984
+ ],
985
+ headerType: 1
986
+ }
987
+ })
988
+ ```
989
+
990
+ > **Catatan `headerType`:**
991
+ > | Nilai | Tipe Header |
992
+ > |-------|-------------|
993
+ > | `1` | Teks (`contentText`) |
994
+ > | `2` | Gambar (`imageMessage`) |
995
+ > | `3` | Video (`videoMessage`) |
996
+ > | `4` | Dokumen (`documentMessage`) |
997
+ > | `6` | Lokasi (`locationMessage`) |
998
+ >
999
+ > `jpegThumbnail` pada `locationMessage` bisa berupa **path file lokal**, **URL**, atau **Buffer** โ€” otomatis diproses oleh Baileys.
1000
+
1001
+ </details>
1002
+
1003
+ ---
1004
+
930
1005
  <details>
931
1006
  <summary>๐ŸŽ›๏ธ Buttons</summary>
932
1007
 
933
1008
  ```js
934
- // Teks dengan tombol
1009
+ // Teks dengan tombol (quick reply)
935
1010
  await sock.sendMessage(jid, {
936
1011
  text: 'Pilih salah satu',
937
1012
  footer: 'Footer pesan',
@@ -953,7 +1028,28 @@ await sock.sendMessage(jid, {
953
1028
  ]
954
1029
  })
955
1030
 
956
- // Native flow button
1031
+ // Native flow button dalam buttons โ€” pakai name + paramsJson
1032
+ await sock.sendMessage(jid, {
1033
+ text: 'Pilih menu',
1034
+ buttons: [
1035
+ {
1036
+ name: 'single_select',
1037
+ text: 'Buka Menu',
1038
+ paramsJson: JSON.stringify({
1039
+ title: 'Buka Menu',
1040
+ sections: [{
1041
+ title: 'Kategori A',
1042
+ rows: [
1043
+ { id: 'row1', title: 'Item 1', description: 'Deskripsi' },
1044
+ { id: 'row2', title: 'Item 2' }
1045
+ ]
1046
+ }]
1047
+ })
1048
+ }
1049
+ ]
1050
+ })
1051
+
1052
+ // Shorthand: sections langsung di button (otomatis jadi single_select)
957
1053
  await sock.sendMessage(jid, {
958
1054
  text: 'Pilih menu',
959
1055
  buttons: [{
@@ -969,6 +1065,8 @@ await sock.sendMessage(jid, {
969
1065
  })
970
1066
  ```
971
1067
 
1068
+ > **Field tombol:** gunakan `text` atau `buttonText` untuk label. Untuk quick reply gunakan `id`/`buttonId`. Untuk native flow gunakan `name` + `paramsJson`.
1069
+
972
1070
  </details>
973
1071
 
974
1072
  ---
@@ -978,10 +1076,10 @@ await sock.sendMessage(jid, {
978
1076
 
979
1077
  ```js
980
1078
  await sock.sendMessage(jid, {
981
- text: 'Silakan pilih',
982
- title: 'Judul List',
983
- buttonText: 'Buka Daftar',
984
- footer: 'Footer pesan',
1079
+ text: 'Silakan pilih', // โ†’ description (isi pesan)
1080
+ title: 'Judul List', // โ†’ title (judul di atas list)
1081
+ buttonText: 'Buka Daftar', // โ†’ teks tombol pembuka
1082
+ footer: 'Footer pesan', // โ†’ footerText
985
1083
  sections: [
986
1084
  {
987
1085
  title: 'Bagian 1',
@@ -1000,6 +1098,8 @@ await sock.sendMessage(jid, {
1000
1098
  })
1001
1099
  ```
1002
1100
 
1101
+ > **Trigger key:** `sections` (bukan `listMessage`). `listType` otomatis di-set ke `SINGLE_SELECT`. Field `text` di-map ke `description` (isi pesan), bukan judul โ€” gunakan `title` untuk judul list.
1102
+
1003
1103
  </details>
1004
1104
 
1005
1105
  ---
@@ -1010,9 +1110,9 @@ await sock.sendMessage(jid, {
1010
1110
  ```js
1011
1111
  // Teks
1012
1112
  await sock.sendMessage(jid, {
1013
- text: 'Pesan template',
1014
- footer: 'Footer',
1015
- id: 'template-unik',
1113
+ text: 'Pesan template', // โ†’ hydratedContentText
1114
+ footer: 'Footer', // โ†’ hydratedFooterText
1115
+ id: 'template-unik', // โ†’ templateId (opsional, auto-generate jika tidak diisi)
1016
1116
  templateButtons: [
1017
1117
  { id: 'btn1', text: 'Quick Reply' },
1018
1118
  { url: 'https://example.com', text: 'Kunjungi Website' },
@@ -1023,8 +1123,8 @@ await sock.sendMessage(jid, {
1023
1123
  // Gambar sebagai header
1024
1124
  await sock.sendMessage(jid, {
1025
1125
  image: { url: 'https://example.com/img.jpg' },
1026
- caption: 'Isi pesan',
1027
- title: 'Judul',
1126
+ caption: 'Isi pesan', // โ†’ hydratedContentText
1127
+ title: 'Judul', // โ†’ hydratedTitleText (hanya aktif jika ada caption)
1028
1128
  footer: 'Footer',
1029
1129
  templateButtons: [
1030
1130
  { id: 'btn1', text: 'Klik Sini' },
@@ -1033,6 +1133,8 @@ await sock.sendMessage(jid, {
1033
1133
  })
1034
1134
  ```
1035
1135
 
1136
+ > **Tipe tombol:** `{ id, text }` โ†’ quick reply ยท `{ url, text }` โ†’ URL button ยท `{ call, text }` โ†’ call button. `text` atau `buttonText` keduanya diterima. Jika `id` tidak diisi, otomatis `template-<timestamp>`.
1137
+
1036
1138
  </details>
1037
1139
 
1038
1140
  ---
@@ -1041,34 +1143,108 @@ await sock.sendMessage(jid, {
1041
1143
  <summary>๐ŸŒŠ Native Flow</summary>
1042
1144
 
1043
1145
  ```js
1044
- // Teks dengan native flow buttons
1146
+ // Quick reply
1045
1147
  await sock.sendMessage(jid, {
1046
1148
  text: 'Pilih aksi',
1047
1149
  footer: 'Footer pesan',
1048
1150
  nativeFlow: [
1049
- { name: 'quick_reply', paramsJson: '{"id":"1"}', text: 'Opsi 1' },
1050
- { name: 'quick_reply', paramsJson: '{"id":"2"}', text: 'Opsi 2' }
1151
+ { id: '1', text: 'Opsi 1' }, // id โ†’ quick_reply
1152
+ { id: '2', text: 'Opsi 2' }
1051
1153
  ]
1052
1154
  })
1053
1155
 
1054
- // Gambar sebagai header
1156
+ // URL button
1157
+ await sock.sendMessage(jid, {
1158
+ text: 'Kunjungi kami',
1159
+ nativeFlow: [
1160
+ { url: 'https://example.com', text: 'Buka Website' }
1161
+ ]
1162
+ })
1163
+
1164
+ // Copy code button
1165
+ await sock.sendMessage(jid, {
1166
+ text: 'Kode promo kamu',
1167
+ nativeFlow: [
1168
+ { copy: 'PROMO2025', text: 'Salin Kode' }
1169
+ ]
1170
+ })
1171
+
1172
+ // Call button
1173
+ await sock.sendMessage(jid, {
1174
+ text: 'Hubungi kami',
1175
+ nativeFlow: [
1176
+ { call: '+62812345678', text: 'Telepon Sekarang' }
1177
+ ]
1178
+ })
1179
+
1180
+ // Single select (list dalam button)
1181
+ await sock.sendMessage(jid, {
1182
+ text: 'Pilih menu',
1183
+ nativeFlow: [
1184
+ {
1185
+ sections: [{
1186
+ title: 'Kategori A',
1187
+ rows: [
1188
+ { id: 'row1', title: 'Item 1', description: 'Deskripsi' },
1189
+ { id: 'row2', title: 'Item 2' }
1190
+ ]
1191
+ }],
1192
+ text: 'Buka Daftar'
1193
+ }
1194
+ ]
1195
+ })
1196
+
1197
+ // Dengan icon pada tombol
1198
+ await sock.sendMessage(jid, {
1199
+ text: 'Pilih aksi',
1200
+ nativeFlow: [
1201
+ { id: '1', text: 'Konfirmasi', icon: 'CHECK' },
1202
+ { url: 'https://example.com', text: 'Buka', icon: 'LINK' }
1203
+ ]
1204
+ })
1205
+
1206
+ // Gambar sebagai header โ€” WAJIB pakai image/video/document/location/product
1207
+ // jika tidak ada media valid โ†’ throw Error: Invalid media type
1055
1208
  await sock.sendMessage(jid, {
1056
1209
  image: { url: 'https://example.com/img.jpg' },
1057
- caption: 'Isi pesan',
1058
- title: 'Judul',
1059
- subtitle: 'Subjudul',
1210
+ caption: 'Isi pesan', // โ†’ body.text
1211
+ title: 'Judul', // โ†’ header.title
1212
+ subtitle: 'Subjudul', // โ†’ header.subtitle
1060
1213
  footer: 'Footer',
1061
1214
  nativeFlow: [
1062
- { name: 'quick_reply', paramsJson: '{"id":"1"}', text: 'Tombol 1' }
1215
+ { id: '1', text: 'Tombol 1' }
1063
1216
  ]
1064
1217
  })
1065
1218
 
1066
- // Dengan audio footer
1219
+ // Dengan audio footer (menggantikan footer teks)
1067
1220
  await sock.sendMessage(jid, {
1068
1221
  text: 'Pesan dengan audio footer',
1069
1222
  audioFooter: fs.readFileSync('audio.ogg'),
1070
1223
  nativeFlow: [
1071
- { name: 'quick_reply', paramsJson: '{"id":"1"}', text: 'OK' }
1224
+ { id: '1', text: 'OK' }
1225
+ ]
1226
+ })
1227
+
1228
+ // offerText โ€” tampil sebagai limited time offer banner
1229
+ await sock.sendMessage(jid, {
1230
+ text: 'Penawaran terbatas!',
1231
+ offerText: 'Diskon 50%',
1232
+ offerUrl: 'https://example.com/promo',
1233
+ offerCode: 'DISKON50',
1234
+ offerExpiration: 1800000000,
1235
+ nativeFlow: [
1236
+ { id: 'claim', text: 'Klaim Sekarang' }
1237
+ ]
1238
+ })
1239
+
1240
+ // optionText โ€” tombol-tombol masuk ke bottom sheet
1241
+ await sock.sendMessage(jid, {
1242
+ text: 'Pilih opsi',
1243
+ optionText: 'Lihat Semua Opsi',
1244
+ optionTitle: 'Daftar Pilihan',
1245
+ nativeFlow: [
1246
+ { id: '1', text: 'Opsi A' },
1247
+ { id: '2', text: 'Opsi B' }
1072
1248
  ]
1073
1249
  })
1074
1250
 
@@ -1076,13 +1252,15 @@ await sock.sendMessage(jid, {
1076
1252
  await sock.sendMessage(jid, {
1077
1253
  text: 'Template interaktif',
1078
1254
  nativeFlow: [
1079
- { name: 'quick_reply', paramsJson: '{"id":"1"}', text: 'Tombol' }
1255
+ { id: '1', text: 'Tombol' }
1080
1256
  ],
1081
1257
  interactiveAsTemplate: true,
1082
1258
  id: 'template-id-unik'
1083
1259
  })
1084
1260
  ```
1085
1261
 
1262
+ > **Tipe tombol ditentukan otomatis** dari field yang ada: `id` โ†’ quick_reply ยท `url` โ†’ cta_url ยท `copy` โ†’ cta_copy ยท `call` โ†’ cta_call ยท `sections` โ†’ single_select. Bisa juga pakai `name` + `paramsJson` langsung untuk kontrol penuh. `text` atau `buttonText` keduanya diterima. Field `icon` opsional (string uppercase, e.g. `'CHECK'`, `'LINK'`).
1263
+
1086
1264
  </details>
1087
1265
 
1088
1266
  ---
@@ -1148,16 +1326,46 @@ await sock.sendMessage(['628xxx@s.whatsapp.net'], {
1148
1326
 
1149
1327
  > Rich message menggunakan format `AIRichResponseMessage` yang tampil seperti respons AI di WhatsApp. Semua tipe di bawah bisa dipakai secara flat (field langsung) atau dikombinasikan via `richResponse: [...]`.
1150
1328
 
1329
+ > โš ๏ธ **Penting:** `contentText`, `headerText`, `footerText`, dan `disclaimerText` **bukan** trigger key โ€” artinya jika hanya field itu yang dikirim, pesan **tidak akan** diproses sebagai rich message dan akan menghasilkan **Error: Invalid media type**. Gunakan selalu minimal satu trigger key (`code`, `table`, `richImage`, `richVideo`, `richResponse`, dll), lalu kombinasikan dengan field teks di atas sebagai pelengkap.
1330
+
1151
1331
  ### โœ๏ธ addText
1152
1332
 
1153
1333
  Kirim teks markdown sebagai AI Rich Response. Mendukung hyperlink, citation, dan LaTeX inline.
1154
1334
 
1335
+ Karena `contentText` bukan trigger key, gunakan `richResponse: [{ text }]` untuk pesan teks murni:
1336
+
1337
+ ```js
1338
+ // โœ… Cara benar โ€” pakai richResponse array
1339
+ await sock.sendMessage(jid, {
1340
+ richResponse: [
1341
+ { text: 'Ini teks dari AI dengan *markdown* dan **bold**.' }
1342
+ ],
1343
+ headerText: 'Judul',
1344
+ footerText: 'Footer',
1345
+ disclaimerText: 'Generated by AI'
1346
+ })
1347
+ ```
1348
+
1349
+ ```js
1350
+ // โœ… Alternatif โ€” contentText sebagai pelengkap dari trigger key lain
1351
+ await sock.sendMessage(jid, {
1352
+ code: 'console.log("Hello")',
1353
+ language: 'javascript',
1354
+ contentText: 'Penjelasan tambahan di sini.',
1355
+ headerText: 'Judul',
1356
+ footerText: 'Footer',
1357
+ disclaimerText: 'Generated by AI'
1358
+ })
1359
+ ```
1360
+
1155
1361
  ```js
1362
+ // โŒ SALAH โ€” contentText saja tidak akan trigger rich message
1156
1363
  await sock.sendMessage(jid, {
1157
- contentText: 'Ini teks dari AI dengan *markdown* dan **bold**.',
1364
+ contentText: 'halooo',
1158
1365
  headerText: 'Judul',
1159
1366
  footerText: 'Footer',
1160
1367
  disclaimerText: 'Generated by AI'
1368
+ // โ†’ Error: Invalid media type
1161
1369
  })
1162
1370
  ```
1163
1371
 
package/README.md.bak CHANGED
@@ -72,6 +72,7 @@
72
72
  [Secure Meta Label](#secure-meta-service-label)
73
73
 
74
74
  ๐ŸŽ›๏ธ **Interactive** โ€”
75
+ [Buttons Location Header](#buttons-dengan-location-header-buttonsmessage-langsung) ยท
75
76
  [Buttons](#buttons) ยท
76
77
  [List Message](#list-message) ยท
77
78
  [Template Buttons](#template-buttons) ยท
@@ -927,11 +928,85 @@ await sock.sendMessage(jid, {
927
928
 
928
929
  ---
929
930
 
931
+ <details>
932
+ <summary>๐Ÿ“ Buttons dengan Location Header (buttonsMessage langsung)</summary>
933
+
934
+ Kirim tombol menggunakan `buttonsMessage` secara langsung โ€” berguna untuk header tipe **Location** (`headerType: 6`) yang tidak bisa dibuat lewat shorthand `buttons`.
935
+
936
+ ```js
937
+ // Tombol dengan header lokasi (headerType 6)
938
+ await sock.sendMessage(jid, {
939
+ buttonsMessage: {
940
+ locationMessage: {
941
+ degreesLatitude: 0,
942
+ degreesLongitude: 0,
943
+ name: 'NuiiSweety',
944
+ address: 'NuiiSweety Bot',
945
+ jpegThumbnail: './src/img/menu.jpg' // path file, URL, atau Buffer
946
+ },
947
+ contentText: 'Pilih menu di bawah ini',
948
+ footerText: 'Powered by @nuiisweety/baileys',
949
+ buttons: [
950
+ { buttonId: 'allmenu', buttonText: { displayText: 'All Menu' }, type: 1 }
951
+ ],
952
+ headerType: 6
953
+ }
954
+ })
955
+
956
+ // Dengan quoted (reply ke pesan tertentu)
957
+ await sock.sendMessage(jid, {
958
+ buttonsMessage: {
959
+ locationMessage: {
960
+ degreesLatitude: -6.2,
961
+ degreesLongitude: 106.8,
962
+ name: 'Menu Bot',
963
+ address: 'NuiiSweety',
964
+ jpegThumbnail: './src/img/menu.jpg'
965
+ },
966
+ contentText: 'Halo! Ini menu utama bot',
967
+ footerText: 'NuiiSweety Bot',
968
+ buttons: [
969
+ { buttonId: 'menu1', buttonText: { displayText: '๐Ÿฑ Menu Utama' }, type: 1 },
970
+ { buttonId: 'help', buttonText: { displayText: 'โ“ Bantuan' }, type: 1 }
971
+ ],
972
+ headerType: 6
973
+ }
974
+ }, { quoted: m })
975
+
976
+ // Header kosong (teks saja, tanpa media/lokasi) โ€” headerType 1
977
+ await sock.sendMessage(jid, {
978
+ buttonsMessage: {
979
+ contentText: 'Pilih opsi',
980
+ footerText: 'Bot Footer',
981
+ buttons: [
982
+ { buttonId: 'yes', buttonText: { displayText: 'Ya' }, type: 1 },
983
+ { buttonId: 'no', buttonText: { displayText: 'Tidak' }, type: 1 }
984
+ ],
985
+ headerType: 1
986
+ }
987
+ })
988
+ ```
989
+
990
+ > **Catatan `headerType`:**
991
+ > | Nilai | Tipe Header |
992
+ > |-------|-------------|
993
+ > | `1` | Teks (`contentText`) |
994
+ > | `2` | Gambar (`imageMessage`) |
995
+ > | `3` | Video (`videoMessage`) |
996
+ > | `4` | Dokumen (`documentMessage`) |
997
+ > | `6` | Lokasi (`locationMessage`) |
998
+ >
999
+ > `jpegThumbnail` pada `locationMessage` bisa berupa **path file lokal**, **URL**, atau **Buffer** โ€” otomatis diproses oleh Baileys.
1000
+
1001
+ </details>
1002
+
1003
+ ---
1004
+
930
1005
  <details>
931
1006
  <summary>๐ŸŽ›๏ธ Buttons</summary>
932
1007
 
933
1008
  ```js
934
- // Teks dengan tombol
1009
+ // Teks dengan tombol (quick reply)
935
1010
  await sock.sendMessage(jid, {
936
1011
  text: 'Pilih salah satu',
937
1012
  footer: 'Footer pesan',
@@ -953,7 +1028,28 @@ await sock.sendMessage(jid, {
953
1028
  ]
954
1029
  })
955
1030
 
956
- // Native flow button
1031
+ // Native flow button dalam buttons โ€” pakai name + paramsJson
1032
+ await sock.sendMessage(jid, {
1033
+ text: 'Pilih menu',
1034
+ buttons: [
1035
+ {
1036
+ name: 'single_select',
1037
+ text: 'Buka Menu',
1038
+ paramsJson: JSON.stringify({
1039
+ title: 'Buka Menu',
1040
+ sections: [{
1041
+ title: 'Kategori A',
1042
+ rows: [
1043
+ { id: 'row1', title: 'Item 1', description: 'Deskripsi' },
1044
+ { id: 'row2', title: 'Item 2' }
1045
+ ]
1046
+ }]
1047
+ })
1048
+ }
1049
+ ]
1050
+ })
1051
+
1052
+ // Shorthand: sections langsung di button (otomatis jadi single_select)
957
1053
  await sock.sendMessage(jid, {
958
1054
  text: 'Pilih menu',
959
1055
  buttons: [{
@@ -969,6 +1065,8 @@ await sock.sendMessage(jid, {
969
1065
  })
970
1066
  ```
971
1067
 
1068
+ > **Field tombol:** gunakan `text` atau `buttonText` untuk label. Untuk quick reply gunakan `id`/`buttonId`. Untuk native flow gunakan `name` + `paramsJson`.
1069
+
972
1070
  </details>
973
1071
 
974
1072
  ---
@@ -978,10 +1076,10 @@ await sock.sendMessage(jid, {
978
1076
 
979
1077
  ```js
980
1078
  await sock.sendMessage(jid, {
981
- text: 'Silakan pilih',
982
- title: 'Judul List',
983
- buttonText: 'Buka Daftar',
984
- footer: 'Footer pesan',
1079
+ text: 'Silakan pilih', // โ†’ description (isi pesan)
1080
+ title: 'Judul List', // โ†’ title (judul di atas list)
1081
+ buttonText: 'Buka Daftar', // โ†’ teks tombol pembuka
1082
+ footer: 'Footer pesan', // โ†’ footerText
985
1083
  sections: [
986
1084
  {
987
1085
  title: 'Bagian 1',
@@ -1000,6 +1098,8 @@ await sock.sendMessage(jid, {
1000
1098
  })
1001
1099
  ```
1002
1100
 
1101
+ > **Trigger key:** `sections` (bukan `listMessage`). `listType` otomatis di-set ke `SINGLE_SELECT`. Field `text` di-map ke `description` (isi pesan), bukan judul โ€” gunakan `title` untuk judul list.
1102
+
1003
1103
  </details>
1004
1104
 
1005
1105
  ---
@@ -1010,9 +1110,9 @@ await sock.sendMessage(jid, {
1010
1110
  ```js
1011
1111
  // Teks
1012
1112
  await sock.sendMessage(jid, {
1013
- text: 'Pesan template',
1014
- footer: 'Footer',
1015
- id: 'template-unik',
1113
+ text: 'Pesan template', // โ†’ hydratedContentText
1114
+ footer: 'Footer', // โ†’ hydratedFooterText
1115
+ id: 'template-unik', // โ†’ templateId (opsional, auto-generate jika tidak diisi)
1016
1116
  templateButtons: [
1017
1117
  { id: 'btn1', text: 'Quick Reply' },
1018
1118
  { url: 'https://example.com', text: 'Kunjungi Website' },
@@ -1023,8 +1123,8 @@ await sock.sendMessage(jid, {
1023
1123
  // Gambar sebagai header
1024
1124
  await sock.sendMessage(jid, {
1025
1125
  image: { url: 'https://example.com/img.jpg' },
1026
- caption: 'Isi pesan',
1027
- title: 'Judul',
1126
+ caption: 'Isi pesan', // โ†’ hydratedContentText
1127
+ title: 'Judul', // โ†’ hydratedTitleText (hanya aktif jika ada caption)
1028
1128
  footer: 'Footer',
1029
1129
  templateButtons: [
1030
1130
  { id: 'btn1', text: 'Klik Sini' },
@@ -1033,6 +1133,8 @@ await sock.sendMessage(jid, {
1033
1133
  })
1034
1134
  ```
1035
1135
 
1136
+ > **Tipe tombol:** `{ id, text }` โ†’ quick reply ยท `{ url, text }` โ†’ URL button ยท `{ call, text }` โ†’ call button. `text` atau `buttonText` keduanya diterima. Jika `id` tidak diisi, otomatis `template-<timestamp>`.
1137
+
1036
1138
  </details>
1037
1139
 
1038
1140
  ---
@@ -1041,34 +1143,108 @@ await sock.sendMessage(jid, {
1041
1143
  <summary>๐ŸŒŠ Native Flow</summary>
1042
1144
 
1043
1145
  ```js
1044
- // Teks dengan native flow buttons
1146
+ // Quick reply
1045
1147
  await sock.sendMessage(jid, {
1046
1148
  text: 'Pilih aksi',
1047
1149
  footer: 'Footer pesan',
1048
1150
  nativeFlow: [
1049
- { name: 'quick_reply', paramsJson: '{"id":"1"}', text: 'Opsi 1' },
1050
- { name: 'quick_reply', paramsJson: '{"id":"2"}', text: 'Opsi 2' }
1151
+ { id: '1', text: 'Opsi 1' }, // id โ†’ quick_reply
1152
+ { id: '2', text: 'Opsi 2' }
1051
1153
  ]
1052
1154
  })
1053
1155
 
1054
- // Gambar sebagai header
1156
+ // URL button
1157
+ await sock.sendMessage(jid, {
1158
+ text: 'Kunjungi kami',
1159
+ nativeFlow: [
1160
+ { url: 'https://example.com', text: 'Buka Website' }
1161
+ ]
1162
+ })
1163
+
1164
+ // Copy code button
1165
+ await sock.sendMessage(jid, {
1166
+ text: 'Kode promo kamu',
1167
+ nativeFlow: [
1168
+ { copy: 'PROMO2025', text: 'Salin Kode' }
1169
+ ]
1170
+ })
1171
+
1172
+ // Call button
1173
+ await sock.sendMessage(jid, {
1174
+ text: 'Hubungi kami',
1175
+ nativeFlow: [
1176
+ { call: '+62812345678', text: 'Telepon Sekarang' }
1177
+ ]
1178
+ })
1179
+
1180
+ // Single select (list dalam button)
1181
+ await sock.sendMessage(jid, {
1182
+ text: 'Pilih menu',
1183
+ nativeFlow: [
1184
+ {
1185
+ sections: [{
1186
+ title: 'Kategori A',
1187
+ rows: [
1188
+ { id: 'row1', title: 'Item 1', description: 'Deskripsi' },
1189
+ { id: 'row2', title: 'Item 2' }
1190
+ ]
1191
+ }],
1192
+ text: 'Buka Daftar'
1193
+ }
1194
+ ]
1195
+ })
1196
+
1197
+ // Dengan icon pada tombol
1198
+ await sock.sendMessage(jid, {
1199
+ text: 'Pilih aksi',
1200
+ nativeFlow: [
1201
+ { id: '1', text: 'Konfirmasi', icon: 'CHECK' },
1202
+ { url: 'https://example.com', text: 'Buka', icon: 'LINK' }
1203
+ ]
1204
+ })
1205
+
1206
+ // Gambar sebagai header โ€” WAJIB pakai image/video/document/location/product
1207
+ // jika tidak ada media valid โ†’ throw Error: Invalid media type
1055
1208
  await sock.sendMessage(jid, {
1056
1209
  image: { url: 'https://example.com/img.jpg' },
1057
- caption: 'Isi pesan',
1058
- title: 'Judul',
1059
- subtitle: 'Subjudul',
1210
+ caption: 'Isi pesan', // โ†’ body.text
1211
+ title: 'Judul', // โ†’ header.title
1212
+ subtitle: 'Subjudul', // โ†’ header.subtitle
1060
1213
  footer: 'Footer',
1061
1214
  nativeFlow: [
1062
- { name: 'quick_reply', paramsJson: '{"id":"1"}', text: 'Tombol 1' }
1215
+ { id: '1', text: 'Tombol 1' }
1063
1216
  ]
1064
1217
  })
1065
1218
 
1066
- // Dengan audio footer
1219
+ // Dengan audio footer (menggantikan footer teks)
1067
1220
  await sock.sendMessage(jid, {
1068
1221
  text: 'Pesan dengan audio footer',
1069
1222
  audioFooter: fs.readFileSync('audio.ogg'),
1070
1223
  nativeFlow: [
1071
- { name: 'quick_reply', paramsJson: '{"id":"1"}', text: 'OK' }
1224
+ { id: '1', text: 'OK' }
1225
+ ]
1226
+ })
1227
+
1228
+ // offerText โ€” tampil sebagai limited time offer banner
1229
+ await sock.sendMessage(jid, {
1230
+ text: 'Penawaran terbatas!',
1231
+ offerText: 'Diskon 50%',
1232
+ offerUrl: 'https://example.com/promo',
1233
+ offerCode: 'DISKON50',
1234
+ offerExpiration: 1800000000,
1235
+ nativeFlow: [
1236
+ { id: 'claim', text: 'Klaim Sekarang' }
1237
+ ]
1238
+ })
1239
+
1240
+ // optionText โ€” tombol-tombol masuk ke bottom sheet
1241
+ await sock.sendMessage(jid, {
1242
+ text: 'Pilih opsi',
1243
+ optionText: 'Lihat Semua Opsi',
1244
+ optionTitle: 'Daftar Pilihan',
1245
+ nativeFlow: [
1246
+ { id: '1', text: 'Opsi A' },
1247
+ { id: '2', text: 'Opsi B' }
1072
1248
  ]
1073
1249
  })
1074
1250
 
@@ -1076,13 +1252,15 @@ await sock.sendMessage(jid, {
1076
1252
  await sock.sendMessage(jid, {
1077
1253
  text: 'Template interaktif',
1078
1254
  nativeFlow: [
1079
- { name: 'quick_reply', paramsJson: '{"id":"1"}', text: 'Tombol' }
1255
+ { id: '1', text: 'Tombol' }
1080
1256
  ],
1081
1257
  interactiveAsTemplate: true,
1082
1258
  id: 'template-id-unik'
1083
1259
  })
1084
1260
  ```
1085
1261
 
1262
+ > **Tipe tombol ditentukan otomatis** dari field yang ada: `id` โ†’ quick_reply ยท `url` โ†’ cta_url ยท `copy` โ†’ cta_copy ยท `call` โ†’ cta_call ยท `sections` โ†’ single_select. Bisa juga pakai `name` + `paramsJson` langsung untuk kontrol penuh. `text` atau `buttonText` keduanya diterima. Field `icon` opsional (string uppercase, e.g. `'CHECK'`, `'LINK'`).
1263
+
1086
1264
  </details>
1087
1265
 
1088
1266
  ---
@@ -1148,16 +1326,46 @@ await sock.sendMessage(['628xxx@s.whatsapp.net'], {
1148
1326
 
1149
1327
  > Rich message menggunakan format `AIRichResponseMessage` yang tampil seperti respons AI di WhatsApp. Semua tipe di bawah bisa dipakai secara flat (field langsung) atau dikombinasikan via `richResponse: [...]`.
1150
1328
 
1329
+ > โš ๏ธ **Penting:** `contentText`, `headerText`, `footerText`, dan `disclaimerText` **bukan** trigger key โ€” artinya jika hanya field itu yang dikirim, pesan **tidak akan** diproses sebagai rich message dan akan menghasilkan **Error: Invalid media type**. Gunakan selalu minimal satu trigger key (`code`, `table`, `richImage`, `richVideo`, `richResponse`, dll), lalu kombinasikan dengan field teks di atas sebagai pelengkap.
1330
+
1151
1331
  ### โœ๏ธ addText
1152
1332
 
1153
1333
  Kirim teks markdown sebagai AI Rich Response. Mendukung hyperlink, citation, dan LaTeX inline.
1154
1334
 
1335
+ Karena `contentText` bukan trigger key, gunakan `richResponse: [{ text }]` untuk pesan teks murni:
1336
+
1337
+ ```js
1338
+ // โœ… Cara benar โ€” pakai richResponse array
1339
+ await sock.sendMessage(jid, {
1340
+ richResponse: [
1341
+ { text: 'Ini teks dari AI dengan *markdown* dan **bold**.' }
1342
+ ],
1343
+ headerText: 'Judul',
1344
+ footerText: 'Footer',
1345
+ disclaimerText: 'Generated by AI'
1346
+ })
1347
+ ```
1348
+
1349
+ ```js
1350
+ // โœ… Alternatif โ€” contentText sebagai pelengkap dari trigger key lain
1351
+ await sock.sendMessage(jid, {
1352
+ code: 'console.log("Hello")',
1353
+ language: 'javascript',
1354
+ contentText: 'Penjelasan tambahan di sini.',
1355
+ headerText: 'Judul',
1356
+ footerText: 'Footer',
1357
+ disclaimerText: 'Generated by AI'
1358
+ })
1359
+ ```
1360
+
1155
1361
  ```js
1362
+ // โŒ SALAH โ€” contentText saja tidak akan trigger rich message
1156
1363
  await sock.sendMessage(jid, {
1157
- contentText: 'Ini teks dari AI dengan *markdown* dan **bold**.',
1364
+ contentText: 'halooo',
1158
1365
  headerText: 'Judul',
1159
1366
  footerText: 'Footer',
1160
1367
  disclaimerText: 'Generated by AI'
1368
+ // โ†’ Error: Invalid media type
1161
1369
  })
1162
1370
  ```
1163
1371
 
@@ -919,6 +919,24 @@ export const generateWAMessageContent = async (message, options) => {
919
919
  }
920
920
  };
921
921
  }
922
+ else if (hasNonNullishProperty(message, 'buttonsMessage')) {
923
+ // Direct buttonsMessage passthrough โ€” supports headerType 6 (locationMessage), etc.
924
+ const btnMsg = { ...message.buttonsMessage };
925
+ if (btnMsg.locationMessage?.jpegThumbnail && !Buffer.isBuffer(btnMsg.locationMessage.jpegThumbnail)) {
926
+ const lib = await getImageProcessingLibrary();
927
+ const hasSharp = 'sharp' in lib && !!lib.sharp?.default;
928
+ if (hasSharp) {
929
+ const rawBuf = typeof btnMsg.locationMessage.jpegThumbnail === 'string'
930
+ ? (await fs.readFile(btnMsg.locationMessage.jpegThumbnail))
931
+ : btnMsg.locationMessage.jpegThumbnail;
932
+ btnMsg.locationMessage.jpegThumbnail = await lib.sharp.default(rawBuf)
933
+ .resize(300, 300, { fit: 'inside', withoutEnlargement: true })
934
+ .jpeg({ quality: 80 })
935
+ .toBuffer();
936
+ }
937
+ }
938
+ m = { buttonsMessage: btnMsg };
939
+ }
922
940
  else {
923
941
  m = await prepareWAMessageMedia(message, options);
924
942
  }
@@ -878,10 +878,17 @@ export const prepareRichResponseMessage = (content) => {
878
878
  }
879
879
 
880
880
  /* build unifiedResponse JSON โ€” gabungkan sections dari submessages + extraSections */
881
- const baseUnified = toUnified(submessages);
881
+ // Pisahkan footerSubs (teks setelah media) agar selalu muncul SETELAH extraSections (video/image)
882
+ const footerSubMessages = footerText ? [makeTextSub(footerText)] : [];
883
+ // Hapus footerText dari submessages jika sudah ada (sudah di-push sebelumnya)
884
+ const mainSubmessages = footerText
885
+ ? submessages.filter(s => !(s.messageType === RichSubMessageType.TEXT && s.messageText === footerText))
886
+ : submessages;
887
+ const baseUnified = toUnified(mainSubmessages);
888
+ const footerSections = footerSubMessages.map(buildUnifiedSection);
882
889
  const unified = extraSections && extraSections.length > 0
883
- ? { ...baseUnified, sections: [...baseUnified.sections, ...extraSections] }
884
- : baseUnified;
890
+ ? { ...baseUnified, sections: [...baseUnified.sections, ...extraSections, ...footerSections] }
891
+ : { ...baseUnified, sections: [...baseUnified.sections, ...footerSections] };
885
892
 
886
893
  const richResponseMessage = proto.AIRichResponseMessage.create({
887
894
  submessages,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nuiisweety/baileys",
3
3
  "type": "module",
4
- "version": "0.1.10",
4
+ "version": "0.1.12",
5
5
  "description": "A WebSockets library for interacting with WhatsApp Web โ€” forked STRICTLY from @whiskeysockets/baileys only, NOT from any other baileys fork. Modified by NuiiSweety.",
6
6
  "keywords": [
7
7
  "whatsapp",