whalibmob 5.5.83 → 5.5.86

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
@@ -157,6 +157,7 @@ npm install -g whalibmob
157
157
  - [Quoted Reply](#quoted-reply)
158
158
  - [Location Message](#location-message)
159
159
  - [Contact Message (vCard)](#contact-message-vcard)
160
+ - [Call Link](#call-link)
160
161
  - [Media Messages](#media-messages)
161
162
  - [Image Message](#image-message)
162
163
  - [Video Message](#video-message)
@@ -1137,6 +1138,7 @@ const { id, encKey } = await client.sendPoll(
1137
1138
  1 // voters may pick 1 option (0 = unlimited)
1138
1139
  )
1139
1140
  // encKey (32-byte Buffer) is needed to decrypt incoming poll votes
1141
+ // (also returned as `messageSecret`, which is the name the protocol uses)
1140
1142
  ```
1141
1143
 
1142
1144
  ### Quoted Reply
@@ -1181,6 +1183,12 @@ await client.sendLocation('919634847671@s.whatsapp.net', 48.8566, 2.3522, {
1181
1183
  await client.sendLocation('120363000000000000@g.us', 51.5074, -0.1278, {
1182
1184
  name: 'London'
1183
1185
  })
1186
+
1187
+ // with a map image for the bubble — WhatsApp draws a blank card without one
1188
+ await client.sendLocation('919634847671@s.whatsapp.net', 48.8566, 2.3522, {
1189
+ name: 'Eiffel Tower',
1190
+ thumbnail: jpegBuffer
1191
+ })
1184
1192
  ```
1185
1193
 
1186
1194
  ### Contact Message (vCard)
@@ -1200,8 +1208,37 @@ const vcard = [
1200
1208
  await client.sendContact('919634847671@s.whatsapp.net', 'Alice Smith', vcard)
1201
1209
  ```
1202
1210
 
1211
+ ### Call Link
1212
+
1213
+ Ask WhatsApp for a link that lets someone join a call by tapping it, instead of
1214
+ being rung. Returns the token, the shareable link and the media type.
1215
+
1216
+ ```js
1217
+ const { link } = await client.createCallLink('video')
1218
+ // https://call.whatsapp.com/video/XXXXXXXX
1219
+
1220
+ // audio is the default
1221
+ const audio = await client.createCallLink()
1222
+
1223
+ // schedule it — startTime is seconds since the epoch
1224
+ await client.createCallLink('video', { startTime: 1800000000 })
1225
+
1226
+ // create it and send it in one step
1227
+ await client.sendCallLink('919634847671@s.whatsapp.net', 'video', {
1228
+ text: 'Join me here:'
1229
+ })
1230
+ ```
1231
+
1203
1232
  ## Media Messages
1204
1233
 
1234
+ Photos and videos are sent with an inline preview so they show up in the chat
1235
+ directly, rather than as a placeholder the recipient has to tap. The dimensions
1236
+ are read out of the file header with no dependency at all. The preview itself
1237
+ uses `jimp` (installed automatically as an optional dependency) or `sharp` if
1238
+ you have it; failing both, a photo that carries an EXIF thumbnail still gets
1239
+ one. Video previews need `ffmpeg` on PATH — on Termux, `pkg install ffmpeg`.
1240
+ Without any of these the media still sends, just without the preview.
1241
+
1205
1242
  ### Image Message
1206
1243
 
1207
1244
  ```js
package/cli.js CHANGED
@@ -362,7 +362,9 @@ const HELP = `
362
362
 
363
363
  Contacts
364
364
  /whatsapp <phone...> check which numbers have WhatsApp
365
- /picture <jid> get profile picture URL of a contact
365
+ /picture <jid> [file] profile picture URL; downloads it when a file is given
366
+ /read <jid> <msgId...> mark messages as read (blue ticks)
367
+ /autoread on|off auto-send read receipts for incoming messages
366
368
  /contact about <jid> get bio/status text of a contact
367
369
 
368
370
  Chats
@@ -393,7 +395,7 @@ const HELP = `
393
395
  /group desc <jid> <text> change description
394
396
  /group invite <jid> get invite link
395
397
  /group revoke <jid> revoke invite link
396
- /group join <code> join by invite code
398
+ /group join <code|link> join by invite code or full link
397
399
  /group invite-info <code|url> preview group metadata from invite link
398
400
  /group photo <jid> <file> change group picture (JPEG)
399
401
  /group meta <jid> query group metadata + participants
@@ -1003,11 +1005,37 @@ async function handleLine(line) {
1003
1005
  }
1004
1006
 
1005
1007
  case '/picture': {
1008
+ requireConn();
1009
+ const jid = normalizeJid(p[1]);
1010
+ const dest = p[2];
1011
+ if (!jid) { fail('usage: /picture <jid> [file]'); break; }
1012
+ const info = await _client.queryPictureInfo(jid);
1013
+ if (!info || !info.url) { out(' (no picture or private)'); break; }
1014
+ out(' ' + info.url);
1015
+ if (info.id) out(' id ' + info.id);
1016
+ if (!dest) break;
1017
+ const buf = await _client.downloadProfilePicture(jid);
1018
+ if (!buf) { fail('download returned nothing'); break; }
1019
+ require('fs').writeFileSync(dest, buf);
1020
+ out(' saved ' + dest + ' (' + buf.length + ' bytes)');
1021
+ break;
1022
+ }
1023
+
1024
+ case '/read': {
1006
1025
  requireConn();
1007
1026
  const jid = normalizeJid(p[1]);
1008
- if (!jid) { fail('usage: /picture <jid>'); break; }
1009
- const url = await _client.queryPicture(jid);
1010
- out(' ' + (url || '(no picture or private)'));
1027
+ const ids = p.slice(2);
1028
+ if (!jid || !ids.length) { fail('usage: /read <jid> <msgId...>'); break; }
1029
+ _client.markRead(jid, ids);
1030
+ out('marked read ' + ids.length + ' message(s) in ' + jid);
1031
+ break;
1032
+ }
1033
+
1034
+ case '/autoread': {
1035
+ const val = (p[1] || '').toLowerCase();
1036
+ if (val !== 'on' && val !== 'off') { fail('usage: /autoread on|off'); break; }
1037
+ if (_client) _client.autoRead = (val === 'on');
1038
+ out('auto read receipts ' + val);
1011
1039
  break;
1012
1040
  }
1013
1041
 
@@ -1232,14 +1260,15 @@ async function handleLine(line) {
1232
1260
  else if (sub === 'revoke') {
1233
1261
  const gj = asGroupJid(p[2]);
1234
1262
  if (!gj) { fail('usage: /group revoke <jid>'); break; }
1235
- await _client.revokeGroupInvite(gj);
1263
+ const fresh = await _client.revokeGroupInvite(gj);
1236
1264
  out('invite link revoked');
1265
+ if (fresh) out(' new link ' + fresh);
1237
1266
  }
1238
1267
  else if (sub === 'join') {
1239
1268
  const code = p[2];
1240
- if (!code) { fail('usage: /group join <code>'); break; }
1241
- const jid = await _client.acceptGroupInvite(code);
1242
- out('joined ' + (jid || 'ok'));
1269
+ if (!code) { fail('usage: /group join <code|link>'); break; }
1270
+ const r = await _client.joinGroupWithLink(code);
1271
+ out((r.pendingApproval ? 'join request sent ' : 'joined ') + r.jid);
1243
1272
  }
1244
1273
  else if (sub === 'invite-info') {
1245
1274
  const code = p[2];