jagproject 26.3.22 → 26.4.23

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.
@@ -9,7 +9,7 @@ const libsignal_1 = require("../Signal/libsignal");
9
9
  const browser_utils_1 = require("../Utils/browser-utils");
10
10
  const logger_1 = __importDefault(require("../Utils/logger"));
11
11
  const waVer = require("./wileys-version.json");
12
- exports.version = waVer?.version || [2, 3000, 1035700054];
12
+ exports.version = waVer?.version || [2, 3000, 1036687490];
13
13
  exports.UNAUTHORIZED_CODES = [401, 403, 419];
14
14
  exports.DEFAULT_ORIGIN = 'https://web.whatsapp.com';
15
15
  exports.CALL_VIDEO_PREFIX = 'https://call.whatsapp.com/video/';
@@ -85,7 +85,9 @@ exports.MEDIA_PATH_MAP = {
85
85
  'product-catalog-image': '/product/image',
86
86
  'md-app-state': '',
87
87
  'md-msg-hist': '/mms/md-app-state',
88
- 'biz-cover-photo': '/pps/biz-cover-photo'
88
+ 'biz-cover-photo': '/pps/biz-cover-photo',
89
+ 'sticker-pack': '/mms/sticker',
90
+ 'thumbnail-sticker-pack': '/mms/image'
89
91
  };
90
92
  exports.MEDIA_HKDF_KEY_MAPPING = {
91
93
  audio: 'Audio',
@@ -106,7 +108,9 @@ exports.MEDIA_HKDF_KEY_MAPPING = {
106
108
  'product-catalog-image': '',
107
109
  'payment-bg-image': 'Payment Background',
108
110
  ptv: 'Video',
109
- 'biz-cover-photo': 'Image'
111
+ 'biz-cover-photo': 'Image',
112
+ 'sticker-pack': 'Sticker Pack',
113
+ 'thumbnail-sticker-pack': 'Image Thumbnail'
110
114
  };
111
115
  exports.MEDIA_KEYS = Object.keys(exports.MEDIA_PATH_MAP);
112
116
  exports.MIN_PREKEY_COUNT = 5;
@@ -2,7 +2,7 @@
2
2
  "version": [
3
3
  2,
4
4
  3000,
5
- 1035700054
5
+ 1036687490
6
6
  ],
7
- "raw": "2.3000.1035700054"
7
+ "raw": "2.3000.1036687490"
8
8
  }
@@ -634,6 +634,9 @@ const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
634
634
  else if (message.stickerMessage) {
635
635
  return 'sticker';
636
636
  }
637
+ else if (message.stickerPackMessage) {
638
+ return 'sticker_pack';
639
+ }
637
640
  else if (message.listMessage) {
638
641
  return 'list';
639
642
  }
@@ -444,6 +444,198 @@ const generateWAMessageContent = async (message, options) => {
444
444
  }
445
445
  }
446
446
  }
447
+ else if ('stickerPack' in message && !!message.stickerPack) {
448
+ const { zip } = require('fflate');
449
+ const { stickers, cover, name, publisher, packId, description } = message.stickerPack;
450
+ const coverSource = cover || ((stickers[0] && (stickers[0].data || stickers[0].sticker)) || null);
451
+ if (!Array.isArray(stickers)) {
452
+ throw new boom_1.Boom('stickerPack.stickers must be an array', { statusCode: 400 });
453
+ }
454
+ if (stickers.length > 60) {
455
+ throw new boom_1.Boom('Sticker pack exceeds the maximum limit of 60 stickers', { statusCode: 400 });
456
+ }
457
+ if (stickers.length === 0) {
458
+ throw new boom_1.Boom('Sticker pack must contain at least one sticker', { statusCode: 400 });
459
+ }
460
+ const stickerPackId = packId || (0, generics_1.generateMessageIDV2)();
461
+ let sharpLib = null;
462
+ let jimpLib = null;
463
+ try {
464
+ sharpLib = require('sharp');
465
+ }
466
+ catch (_sharpError) { }
467
+ try {
468
+ jimpLib = require('jimp');
469
+ }
470
+ catch (_jimpError) { }
471
+ if (!sharpLib && !jimpLib) {
472
+ throw new boom_1.Boom('No image processing library available (install sharp or jimp)', { statusCode: 400 });
473
+ }
474
+ const isWebPBuffer = (buf) => (buf.length >= 12
475
+ && buf[0] === 0x52
476
+ && buf[1] === 0x49
477
+ && buf[2] === 0x46
478
+ && buf[3] === 0x46
479
+ && buf[8] === 0x57
480
+ && buf[9] === 0x45
481
+ && buf[10] === 0x42
482
+ && buf[11] === 0x50);
483
+ const isAnimatedWebP = (buf) => {
484
+ if (!isWebPBuffer(buf)) {
485
+ return false;
486
+ }
487
+ let offset = 12;
488
+ while (offset < buf.length - 8) {
489
+ const fourCC = buf.toString('ascii', offset, offset + 4);
490
+ const chunkSize = buf.readUInt32LE(offset + 4);
491
+ if (fourCC === 'VP8X') {
492
+ const flagsOffset = offset + 8;
493
+ if (flagsOffset < buf.length && (buf[flagsOffset] & 0x02)) {
494
+ return true;
495
+ }
496
+ }
497
+ else if (fourCC === 'ANIM' || fourCC === 'ANMF') {
498
+ return true;
499
+ }
500
+ offset += 8 + chunkSize + (chunkSize % 2);
501
+ }
502
+ return false;
503
+ };
504
+ const getJimpBuffer = async (image, mime) => {
505
+ if (typeof image.getBufferAsync === 'function') {
506
+ return await image.getBufferAsync(mime);
507
+ }
508
+ return await new Promise((resolve, reject) => {
509
+ image.getBuffer(mime, (err, result) => {
510
+ if (err) {
511
+ reject(err);
512
+ }
513
+ else {
514
+ resolve(result);
515
+ }
516
+ });
517
+ });
518
+ };
519
+ const toWebpBuffer = async (buffer, label) => {
520
+ if (isWebPBuffer(buffer)) {
521
+ return buffer;
522
+ }
523
+ if (sharpLib) {
524
+ return await sharpLib(buffer).webp().toBuffer();
525
+ }
526
+ if (jimpLib) {
527
+ const JimpCtor = jimpLib.Jimp || jimpLib.default || jimpLib;
528
+ const image = await JimpCtor.read(buffer);
529
+ return await getJimpBuffer(image, 'image/webp');
530
+ }
531
+ throw new boom_1.Boom(`No image processing library available for converting ${label} to WebP`, { statusCode: 400 });
532
+ };
533
+ const stickerData = {};
534
+ const stickerMetadata = await Promise.all(stickers.map(async (stickerItem, index) => {
535
+ const mediaSource = (stickerItem === null || stickerItem === void 0 ? void 0 : stickerItem.data) || (stickerItem === null || stickerItem === void 0 ? void 0 : stickerItem.sticker);
536
+ if (!mediaSource) {
537
+ throw new boom_1.Boom(`Sticker at index ${index} is missing data/sticker`, { statusCode: 400 });
538
+ }
539
+ const { stream } = await (0, messages_media_1.getStream)(mediaSource);
540
+ const buffer = await (0, messages_media_1.toBuffer)(stream);
541
+ const webpBuffer = await toWebpBuffer(buffer, `sticker at index ${index}`);
542
+ if (webpBuffer.length > 1024 * 1024) {
543
+ throw new boom_1.Boom(`Sticker at index ${index} exceeds the 1MB size limit`, { statusCode: 400 });
544
+ }
545
+ const hash = (0, crypto_2.sha256)(webpBuffer).toString('base64').replace(/\//g, '-');
546
+ const fileName = `${hash}.webp`;
547
+ stickerData[fileName] = [new Uint8Array(webpBuffer), { level: 0 }];
548
+ return {
549
+ fileName,
550
+ mimetype: 'image/webp',
551
+ isAnimated: isAnimatedWebP(webpBuffer),
552
+ emojis: stickerItem.emojis || [],
553
+ accessibilityLabel: stickerItem.accessibilityLabel || ''
554
+ };
555
+ }));
556
+ const trayIconFileName = `${stickerPackId}.webp`;
557
+ if (!coverSource) {
558
+ throw new boom_1.Boom('stickerPack.cover is required when no valid sticker media is available', { statusCode: 400 });
559
+ }
560
+ const { stream: coverStream } = await (0, messages_media_1.getStream)(coverSource);
561
+ const coverBuffer = await (0, messages_media_1.toBuffer)(coverStream);
562
+ const coverWebpBuffer = await toWebpBuffer(coverBuffer, 'cover');
563
+ stickerData[trayIconFileName] = [new Uint8Array(coverWebpBuffer), { level: 0 }];
564
+ const zipBuffer = await new Promise((resolve, reject) => {
565
+ zip(stickerData, (err, data) => {
566
+ if (err) {
567
+ reject(err);
568
+ }
569
+ else {
570
+ resolve(Buffer.from(data));
571
+ }
572
+ });
573
+ });
574
+ const stickerPackUpload = await (0, messages_media_1.encryptedStream)(zipBuffer, 'sticker-pack', {
575
+ logger: options.logger,
576
+ opts: options.options
577
+ });
578
+ const stickerPackUploadResult = await options.upload(stickerPackUpload.encWriteStream, {
579
+ fileEncSha256B64: stickerPackUpload.fileEncSha256.toString('base64'),
580
+ mediaType: 'sticker-pack',
581
+ timeoutMs: options.mediaUploadTimeoutMs
582
+ });
583
+ m.stickerPackMessage = {
584
+ name,
585
+ publisher,
586
+ stickerPackId,
587
+ packDescription: description,
588
+ stickerPackOrigin: WAProto_1.proto.Message.StickerPackMessage.StickerPackOrigin.THIRD_PARTY,
589
+ stickerPackSize: zipBuffer.length,
590
+ stickers: stickerMetadata,
591
+ fileSha256: stickerPackUpload.fileSha256,
592
+ fileEncSha256: stickerPackUpload.fileEncSha256,
593
+ mediaKey: stickerPackUpload.mediaKey,
594
+ directPath: stickerPackUploadResult.directPath,
595
+ fileLength: stickerPackUpload.fileLength,
596
+ mediaKeyTimestamp: (0, generics_1.unixTimestampSeconds)(),
597
+ trayIconFileName
598
+ };
599
+ try {
600
+ let thumbnailBuffer;
601
+ if (sharpLib) {
602
+ thumbnailBuffer = await sharpLib(coverBuffer).resize(252, 252).jpeg().toBuffer();
603
+ }
604
+ else if (jimpLib) {
605
+ const JimpCtor = jimpLib.Jimp || jimpLib.default || jimpLib;
606
+ const image = await JimpCtor.read(coverBuffer);
607
+ thumbnailBuffer = await getJimpBuffer(image.resize({ w: 252, h: 252 }), 'image/jpeg');
608
+ }
609
+ if (thumbnailBuffer && thumbnailBuffer.length) {
610
+ const thumbUpload = await (0, messages_media_1.encryptedStream)(thumbnailBuffer, 'thumbnail-sticker-pack', {
611
+ logger: options.logger,
612
+ opts: options.options,
613
+ mediaKey: stickerPackUpload.mediaKey
614
+ });
615
+ const thumbUploadResult = await options.upload(thumbUpload.encWriteStream, {
616
+ fileEncSha256B64: thumbUpload.fileEncSha256.toString('base64'),
617
+ mediaType: 'thumbnail-sticker-pack',
618
+ timeoutMs: options.mediaUploadTimeoutMs
619
+ });
620
+ Object.assign(m.stickerPackMessage, {
621
+ thumbnailDirectPath: thumbUploadResult.directPath,
622
+ thumbnailSha256: thumbUpload.fileSha256,
623
+ thumbnailEncSha256: thumbUpload.fileEncSha256,
624
+ thumbnailHeight: 252,
625
+ thumbnailWidth: 252,
626
+ imageDataHash: (0, crypto_2.sha256)(thumbnailBuffer).toString('base64')
627
+ });
628
+ }
629
+ }
630
+ catch (error) {
631
+ var _r, _s;
632
+ (_s = (_r = options.logger) === null || _r === void 0 ? void 0 : _r.warn) === null || _s === void 0 ? void 0 : _s.call(_r, { err: error }, 'sticker pack thumbnail generation failed');
633
+ }
634
+ m.stickerPackMessage.contextInfo = {
635
+ ...((message.contextInfo) || {}),
636
+ ...((message.mentions) ? { mentionedJid: message.mentions } : {})
637
+ };
638
+ }
447
639
  else if ('event' in message) {
448
640
  m.messageContextInfo = {
449
641
  messageSecret: message.event.messageSecret || (0, crypto_1.randomBytes)(32),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jagproject",
3
- "version": "26.03.22",
4
- "update": "22 Maret 2026",
3
+ "version": "26.4.23",
4
+ "update": "22 Maret 2026",
5
5
  "description": "WhatsApp Web API Library",
6
6
  "keywords": [
7
7
  "jagoan",
@@ -12,7 +12,7 @@
12
12
  "automation",
13
13
  "multi-device"
14
14
  ],
15
- "homepage": "https://whatsapp.com/channel/0029VanhMDo42DcjiRGJOc2m",
15
+ "homepage": "https://whatsapp.com/channel/0029VanhMDo42DcjiRGJOc2m",
16
16
  "repository": {
17
17
  "type": "git",
18
18
  "url": "git+https://github.com/ChandraGO/jagoans.git"
@@ -65,7 +65,8 @@
65
65
  "pino": "^9.6",
66
66
  "protobufjs": "^6.11.3",
67
67
  "uuid": "^10.0.0",
68
- "ws": "^8.13.0"
68
+ "ws": "^8.13.0",
69
+ "fflate": "^0.8.2"
69
70
  },
70
71
  "devDependencies": {
71
72
  "@adiwajshing/eslint-config": "github:adiwajshing/eslint-config",
package/readme.md CHANGED
@@ -68,6 +68,78 @@ yarn add jagproject
68
68
  ---
69
69
 
70
70
 
71
+ # Cara Pakai Cepat
72
+
73
+ ## Instalasi
74
+
75
+ ```bash
76
+ npm install jagproject
77
+ ```
78
+
79
+ ## Pemakaian Dasar
80
+
81
+ ```javascript
82
+ const { default: makeWASocket, useMultiFileAuthState } = require('jagproject')
83
+
84
+ async function startBot() {
85
+ const { state, saveCreds } = await useMultiFileAuthState('./session')
86
+
87
+ const sock = makeWASocket({
88
+ auth: state,
89
+ printQRInTerminal: true
90
+ })
91
+
92
+ sock.ev.on('creds.update', saveCreds)
93
+
94
+ sock.ev.on('connection.update', ({ connection }) => {
95
+ if (connection === 'open') {
96
+ console.log('Bot connected')
97
+ }
98
+ })
99
+ }
100
+
101
+ startBot()
102
+ ```
103
+
104
+ ## Kirim Sticker Pack
105
+
106
+ ```javascript
107
+ await sock.sendMessage('6281234567890@s.whatsapp.net', {
108
+ stickerPack: {
109
+ name: 'Baileys Wileyss',
110
+ publisher: 'Project Pemuda',
111
+ description: 'Sticker pack custom dari Wileyss',
112
+ cover: { url: './assets/cover.png' },
113
+ stickers: [
114
+ { sticker: { url: './assets/sticker-1.webp' }, emojis: ['😀'] },
115
+ { sticker: { url: './assets/sticker-2.webp' }, emojis: ['🔥'] },
116
+ { sticker: { url: './assets/sticker-3.png' }, emojis: ['🚀'] }
117
+ ]
118
+ }
119
+ })
120
+ ```
121
+
122
+ ### Format object `stickerPack`
123
+
124
+ - `name`: nama pack sticker
125
+ - `publisher`: nama author/publisher
126
+ - `description`: deskripsi pack
127
+ - `cover`: cover/tray icon, bisa file path, buffer, stream, atau URL
128
+ - `stickers`: array isi sticker, minimal 1 maksimal 60
129
+ - `sticker`: media tiap sticker, bisa WebP/PNG/JPG. Jika bukan WebP akan dicoba dikonversi otomatis
130
+ - `emojis`: emoji untuk sticker terkait
131
+ - `accessibilityLabel`: label opsional
132
+ - `packId`: opsional, jika tidak diisi akan dibuat otomatis
133
+
134
+ ### Catatan
135
+
136
+ - Sangat disarankan install `sharp` agar konversi gambar ke WebP lebih stabil.
137
+ - Jika `sharp` tidak ada, library akan mencoba memakai `jimp`.
138
+ - Ukuran tiap sticker maksimal 1 MB.
139
+ - Jumlah sticker maksimal 60 per pack.
140
+
141
+ ---
142
+
71
143
  # Documentation
72
144
 
73
145
  - [Connecting Account](#connecting-account)
@@ -119,6 +191,7 @@ yarn add jagproject
119
191
  - [Audio Message](#audio-message)
120
192
  - [Image Message](#image-message)
121
193
  - [ViewOnce Message](#view-once-message)
194
+ - [Sticker Pack Message](#kirim-sticker-pack)
122
195
  - [Modify Messages](#modify-messages)
123
196
  - [Delete Messages (for everyone)](#deleting-messages-for-everyone)
124
197
  - [Edit Messages](#editing-messages)
@@ -1873,3 +1946,27 @@ Gunakan secara bertanggung jawab dan hindari aktivitas ilegal atau penyalahgunaa
1873
1946
 
1874
1947
  📘 *Documentation powered by jagoan project*
1875
1948
  🧑‍💻 **Modified and Presented by Jagoan Project**
1949
+
1950
+ <a id="kirim-sticker-pack"></a>
1951
+ ## Sticker Pack Message
1952
+
1953
+ Gunakan field `stickerPack` pada `sendMessage` untuk mengirim satu paket sticker sekaligus.
1954
+
1955
+ Catatan penting: untuk impor Telegram seperti plugin `telesticker`, saat ini yang paling aman adalah sticker statis `webp/png/jpg/jpeg`. Sticker `tgs`/animated dan `webm`/video sebaiknya difilter dulu sebelum dikirim sebagai `stickerPack`.
1956
+
1957
+ ```javascript
1958
+ await sock.sendMessage(jid, {
1959
+ stickerPack: {
1960
+ name: 'Nama Pack',
1961
+ publisher: 'Nama Publisher',
1962
+ description: 'Deskripsi singkat',
1963
+ cover: { url: './cover.png' },
1964
+ stickers: [
1965
+ { sticker: { url: './1.webp' }, emojis: ['🙂'] },
1966
+ { sticker: { url: './2.png' }, emojis: ['🎉'] }
1967
+ ]
1968
+ }
1969
+ })
1970
+ ```
1971
+
1972
+ `cover` dan setiap item `sticker` menerima format media yang sama seperti pengiriman media biasa: path lokal, URL, Buffer, atau stream.