jagproject 26.2.15 → 26.3.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/lib/Defaults/index.js +4 -2
- package/lib/Defaults/wileys-version.json +3 -1
- package/lib/Socket/Client/websocket.js +2 -41
- package/lib/Socket/chats.js +58 -1
- package/lib/Socket/messages-recv.js +53 -3
- package/lib/Socket/socket.js +0 -8
- package/lib/index.js +2 -1
- package/package.json +11 -10
package/lib/Defaults/index.js
CHANGED
|
@@ -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,
|
|
12
|
+
exports.version = waVer?.version || [2, 3000, 1035023383];
|
|
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/';
|
|
@@ -59,6 +59,8 @@ exports.DEFAULT_CONNECTION_CONFIG = {
|
|
|
59
59
|
shouldSyncHistoryMessage: () => true,
|
|
60
60
|
shouldIgnoreJid: () => false,
|
|
61
61
|
linkPreviewImageThumbnailWidth: 192,
|
|
62
|
+
// no forced delay between album items by default, to avoid slow perceived delivery
|
|
63
|
+
albumMessageItemDelayMs: 0,
|
|
62
64
|
transactionOpts: { maxCommitRetries: 10, delayBetweenTriesMs: 3000 },
|
|
63
65
|
generateHighQualityLinkPreview: false,
|
|
64
66
|
enableAutoSessionRecreation: true,
|
|
@@ -116,4 +118,4 @@ exports.DEFAULT_CACHE_TTLS = {
|
|
|
116
118
|
MSG_RETRY: 60 * 60,
|
|
117
119
|
CALL_OFFER: 5 * 60,
|
|
118
120
|
USER_DEVICES: 5 * 60
|
|
119
|
-
};
|
|
121
|
+
};
|
|
@@ -11,11 +11,6 @@ class WebSocketClient extends types_1.AbstractSocketClient {
|
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.socket = null;
|
|
14
|
-
// queue & dispatch variables for throttling outgoing messages to avoid rate limits
|
|
15
|
-
this._queue = [];
|
|
16
|
-
this._isDispatching = false;
|
|
17
|
-
this._lastDispatch = 0;
|
|
18
|
-
this._minSendIntervalMs = (Defaults_1.DEFAULT_CONNECTION_CONFIG && Defaults_1.DEFAULT_CONNECTION_CONFIG.minSendIntervalMs) || 50;
|
|
19
14
|
}
|
|
20
15
|
get isOpen() {
|
|
21
16
|
var _a;
|
|
@@ -69,43 +64,9 @@ class WebSocketClient extends types_1.AbstractSocketClient {
|
|
|
69
64
|
await this.connect();
|
|
70
65
|
}
|
|
71
66
|
send(str, cb) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
var _a;
|
|
75
|
-
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.send(str, cb);
|
|
76
|
-
return Boolean(this.socket);
|
|
77
|
-
};
|
|
78
|
-
this._queue.push(doSend);
|
|
79
|
-
this._dispatch();
|
|
67
|
+
var _a;
|
|
68
|
+
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.send(str, cb);
|
|
80
69
|
return true;
|
|
81
70
|
}
|
|
82
|
-
|
|
83
|
-
_dispatch() {
|
|
84
|
-
if (this._isDispatching) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
this._isDispatching = true;
|
|
88
|
-
const tick = () => {
|
|
89
|
-
const now = Date.now();
|
|
90
|
-
if (this._queue.length === 0) {
|
|
91
|
-
this._isDispatching = false;
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const delta = now - this._lastDispatch;
|
|
95
|
-
const wait = Math.max(0, this._minSendIntervalMs - delta);
|
|
96
|
-
setTimeout(() => {
|
|
97
|
-
const fn = this._queue.shift();
|
|
98
|
-
this._lastDispatch = Date.now();
|
|
99
|
-
try {
|
|
100
|
-
fn && fn();
|
|
101
|
-
}
|
|
102
|
-
catch (_err) {
|
|
103
|
-
// ignore send errors here; they'll surface elsewhere
|
|
104
|
-
}
|
|
105
|
-
tick();
|
|
106
|
-
}, wait);
|
|
107
|
-
};
|
|
108
|
-
tick();
|
|
109
|
-
}
|
|
110
71
|
}
|
|
111
72
|
exports.WebSocketClient = WebSocketClient;
|
package/lib/Socket/chats.js
CHANGED
|
@@ -37,6 +37,10 @@ const makeChatsSocket = (config) => {
|
|
|
37
37
|
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY,
|
|
38
38
|
useClones: false
|
|
39
39
|
});
|
|
40
|
+
const receivedMessageDedupCache = new node_cache_1.default({
|
|
41
|
+
stdTTL: 3 * 60,
|
|
42
|
+
useClones: false
|
|
43
|
+
});
|
|
40
44
|
if (!config.placeholderResendCache) {
|
|
41
45
|
config.placeholderResendCache = placeholderResendCache;
|
|
42
46
|
}
|
|
@@ -728,8 +732,58 @@ const makeChatsSocket = (config) => {
|
|
|
728
732
|
fetchPrivacySettings(),
|
|
729
733
|
]);
|
|
730
734
|
};
|
|
735
|
+
const canonicalizeUserJid = (jid) => {
|
|
736
|
+
if (!jid) {
|
|
737
|
+
return jid;
|
|
738
|
+
}
|
|
739
|
+
if ((0, WABinary_1.isLidUser)(jid)) {
|
|
740
|
+
return (0, WABinary_1.lidToJid)(jid);
|
|
741
|
+
}
|
|
742
|
+
return jid;
|
|
743
|
+
};
|
|
744
|
+
const extractStanzaId = (msg) => {
|
|
745
|
+
var _a, _b;
|
|
746
|
+
const topLevelStanzaId = (_a = msg.messageContextInfo) === null || _a === void 0 ? void 0 : _a.stanzaId;
|
|
747
|
+
if (topLevelStanzaId) {
|
|
748
|
+
return topLevelStanzaId;
|
|
749
|
+
}
|
|
750
|
+
const messageContextStanzaId = (_b = msg.message) === null || _b === void 0 ? void 0 : _b.messageContextInfo;
|
|
751
|
+
if (messageContextStanzaId === null || messageContextStanzaId === void 0 ? void 0 : messageContextStanzaId.stanzaId) {
|
|
752
|
+
return messageContextStanzaId.stanzaId;
|
|
753
|
+
}
|
|
754
|
+
const normalizedContent = (0, Utils_1.normalizeMessageContent)(msg.message);
|
|
755
|
+
const contentType = normalizedContent ? (0, Utils_1.getContentType)(normalizedContent) : undefined;
|
|
756
|
+
const contentContextStanzaId = contentType
|
|
757
|
+
? normalizedContent[contentType].contextInfo && normalizedContent[contentType].contextInfo.stanzaId
|
|
758
|
+
: undefined;
|
|
759
|
+
return contentContextStanzaId;
|
|
760
|
+
};
|
|
761
|
+
const buildMessageDedupKeys = (msg) => {
|
|
762
|
+
const remoteJid = canonicalizeUserJid(msg.key.remoteJid);
|
|
763
|
+
const participant = canonicalizeUserJid(msg.key.participant);
|
|
764
|
+
const stanzaId = extractStanzaId(msg);
|
|
765
|
+
const primaryKey = [remoteJid, participant, msg.key.id, msg.key.fromMe ? '1' : '0', stanzaId || ''].join('|');
|
|
766
|
+
const keys = [primaryKey];
|
|
767
|
+
// fallback alias key to collapse LID->PN duplicate deliveries for the same incoming user message ID
|
|
768
|
+
if (!msg.key.fromMe && ((0, WABinary_1.isJidUser)(msg.key.remoteJid) || (0, WABinary_1.isLidUser)(msg.key.remoteJid))) {
|
|
769
|
+
keys.push(`incoming-user-id|${msg.key.id}|${stanzaId || ''}`);
|
|
770
|
+
}
|
|
771
|
+
return keys;
|
|
772
|
+
};
|
|
773
|
+
const getDedupState = (msg) => msg.messageStubType === WAProto_1.proto.WebMessageInfo.StubType.CIPHERTEXT
|
|
774
|
+
? 'ciphertext'
|
|
775
|
+
: 'final';
|
|
731
776
|
const upsertMessage = ev.createBufferedFunction(async (msg, type) => {
|
|
732
777
|
var _a, _b, _c;
|
|
778
|
+
const dedupKeys = buildMessageDedupKeys(msg);
|
|
779
|
+
const dedupState = getDedupState(msg);
|
|
780
|
+
const previousDedupState = dedupKeys
|
|
781
|
+
.map(key => receivedMessageDedupCache.get(key))
|
|
782
|
+
.find(state => !!state);
|
|
783
|
+
if (previousDedupState === 'final' || (previousDedupState === 'ciphertext' && dedupState === 'ciphertext')) {
|
|
784
|
+
logger.debug({ dedupKeys, messageId: msg.key.id, type, dedupState, previousDedupState }, 'skipping duplicate messages.upsert');
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
733
787
|
ev.emit('messages.upsert', { messages: [msg], type });
|
|
734
788
|
if (!!msg.pushName) {
|
|
735
789
|
let jid = msg.key.fromMe ? authState.creds.me.id : (msg.key.participant || msg.key.remoteJid);
|
|
@@ -800,6 +854,9 @@ const makeChatsSocket = (config) => {
|
|
|
800
854
|
await doAppStateSync();
|
|
801
855
|
pendingAppStateSync = false;
|
|
802
856
|
}
|
|
857
|
+
for (const key of dedupKeys) {
|
|
858
|
+
receivedMessageDedupCache.set(key, dedupState);
|
|
859
|
+
}
|
|
803
860
|
});
|
|
804
861
|
ws.on('CB:presence', handlePresenceUpdate);
|
|
805
862
|
ws.on('CB:chatstate', handlePresenceUpdate);
|
|
@@ -912,4 +969,4 @@ const makeChatsSocket = (config) => {
|
|
|
912
969
|
star
|
|
913
970
|
};
|
|
914
971
|
};
|
|
915
|
-
exports.makeChatsSocket = makeChatsSocket;
|
|
972
|
+
exports.makeChatsSocket = makeChatsSocket;
|
|
@@ -33,7 +33,55 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
33
33
|
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.MSG_RETRY, // 1 hour
|
|
34
34
|
useClones: false
|
|
35
35
|
});
|
|
36
|
+
const groupParticipantJidCache = new node_cache_1.default({
|
|
37
|
+
stdTTL: 10 * 60, // 10 mins
|
|
38
|
+
useClones: false
|
|
39
|
+
});
|
|
40
|
+
const groupMetadataWarmupCache = new node_cache_1.default({
|
|
41
|
+
stdTTL: 60, // avoid repeated warmup calls per group
|
|
42
|
+
useClones: false
|
|
43
|
+
});
|
|
36
44
|
let sendActiveReceipts = false;
|
|
45
|
+
const cacheGroupParticipants = (metadata) => {
|
|
46
|
+
for (const participant of metadata.participants || []) {
|
|
47
|
+
if (!participant.id || !participant.jid) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
groupParticipantJidCache.set(`${metadata.id}:${participant.id}`, participant.jid);
|
|
51
|
+
if (participant.lid) {
|
|
52
|
+
groupParticipantJidCache.set(`${metadata.id}:${participant.lid}`, participant.jid);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const warmupGroupParticipants = async (groupJid) => {
|
|
57
|
+
if (groupMetadataWarmupCache.get(groupJid)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
groupMetadataWarmupCache.set(groupJid, true);
|
|
61
|
+
try {
|
|
62
|
+
const metadata = await groupMetadata(groupJid);
|
|
63
|
+
cacheGroupParticipants(metadata);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
logger.debug({ error, groupJid }, 'failed to warm up group participant cache');
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const resolveGroupParticipantJid = async (groupJid, participantLid) => {
|
|
70
|
+
const cacheKey = `${groupJid}:${participantLid}`;
|
|
71
|
+
const cachedParticipant = groupParticipantJidCache.get(cacheKey);
|
|
72
|
+
if (cachedParticipant) {
|
|
73
|
+
return cachedParticipant;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const metadata = await groupMetadata(groupJid);
|
|
77
|
+
cacheGroupParticipants(metadata);
|
|
78
|
+
return groupParticipantJidCache.get(cacheKey);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
logger.debug({ error, groupJid, participantLid }, 'failed to resolve group participant jid');
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
37
85
|
const sendMessageAck = async ({ tag, attrs, content }, errorCode) => {
|
|
38
86
|
const stanza = {
|
|
39
87
|
tag: 'ack',
|
|
@@ -778,12 +826,14 @@ const makeMessagesRecvSocket = (config) => {
|
|
|
778
826
|
}
|
|
779
827
|
if ((0, WABinary_1.isJidGroup)(msg.key.remoteJid) && ((_f = (_e = (_d = (_c = msg.message) === null || _c === void 0 ? void 0 : _c.extendedTextMessage) === null || _d === void 0 ? void 0 : _d.contextInfo) === null || _e === void 0 ? void 0 : _e.participant) === null || _f === void 0 ? void 0 : _f.endsWith('@lid'))) {
|
|
780
828
|
if (msg.message.extendedTextMessage.contextInfo) {
|
|
781
|
-
const metadata = await groupMetadata(msg.key.remoteJid);
|
|
782
829
|
const sender = msg.message.extendedTextMessage.contextInfo.participant;
|
|
783
|
-
const
|
|
784
|
-
msg.message.extendedTextMessage.contextInfo.participant =
|
|
830
|
+
const resolvedSender = await resolveGroupParticipantJid(msg.key.remoteJid, sender);
|
|
831
|
+
msg.message.extendedTextMessage.contextInfo.participant = resolvedSender || sender;
|
|
785
832
|
}
|
|
786
833
|
}
|
|
834
|
+
else if ((0, WABinary_1.isJidGroup)(msg.key.remoteJid)) {
|
|
835
|
+
void warmupGroupParticipants(msg.key.remoteJid);
|
|
836
|
+
}
|
|
787
837
|
if (!(0, WABinary_1.isJidGroup)(msg.key.remoteJid) && (0, WABinary_1.isLidUser)(msg.key.remoteJid)) {
|
|
788
838
|
msg.key.remoteJid = node.attrs.sender_pn || node.attrs.peer_recipient_pn;
|
|
789
839
|
}
|
package/lib/Socket/socket.js
CHANGED
|
@@ -89,14 +89,6 @@ const makeSocket = (config) => {
|
|
|
89
89
|
// ignore
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
// gently back off when encountering rate limits (429)
|
|
93
|
-
if (message.includes('429') || message.includes('rate limit')) {
|
|
94
|
-
const wait = Math.min(30000, (config.backoffDelayMs || 5000));
|
|
95
|
-
logger.info({ wait }, 'backing off due to rate limit');
|
|
96
|
-
setTimeout(() => {
|
|
97
|
-
// intentionally empty; wait to delay further sends
|
|
98
|
-
}, wait);
|
|
99
|
-
}
|
|
100
92
|
};
|
|
101
93
|
/** await the next incoming message */
|
|
102
94
|
const awaitNextMessage = async (sendMsg) => {
|
package/lib/index.js
CHANGED
|
@@ -67,7 +67,7 @@ console.log(chalk.redBright.bold(title));
|
|
|
67
67
|
padLine(`${chalk.magentaBright("Youtube")} : ${chalk.whiteBright(YOUTUBE)}`),
|
|
68
68
|
padLine(`${chalk.blueBright("Kontak")} : ${chalk.whiteBright(CONTACT)}`),
|
|
69
69
|
padLine(""),
|
|
70
|
-
padLine(chalk.gray("Tip:
|
|
70
|
+
padLine(chalk.gray("Tip: saran pakai Node >= 20.")),
|
|
71
71
|
];
|
|
72
72
|
|
|
73
73
|
box(infoLines, (s) => chalk.white(s));
|
|
@@ -80,6 +80,7 @@ printBanner();
|
|
|
80
80
|
PEMBATAS
|
|
81
81
|
*/
|
|
82
82
|
|
|
83
|
+
|
|
83
84
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
84
85
|
if (k2 === undefined) k2 = k;
|
|
85
86
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jagproject",
|
|
3
|
-
"version": "26.
|
|
4
|
-
"update": "
|
|
3
|
+
"version": "26.03.12",
|
|
4
|
+
"update": "12 Maret 2026",
|
|
5
5
|
"description": "WhatsApp Web API Library",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"jagoan",
|
|
@@ -12,11 +12,15 @@
|
|
|
12
12
|
"automation",
|
|
13
13
|
"multi-device"
|
|
14
14
|
],
|
|
15
|
-
|
|
15
|
+
"homepage": "https://whatsapp.com/channel/0029VanhMDo42DcjiRGJOc2m",
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
18
18
|
"url": "git+https://github.com/ChandraGO/jagoans.git"
|
|
19
19
|
},
|
|
20
|
+
"funding": {
|
|
21
|
+
"type": "youtube",
|
|
22
|
+
"url": "https://youtube.com/@jagoanproject"
|
|
23
|
+
},
|
|
20
24
|
"license": "MIT",
|
|
21
25
|
"author": "jagoan",
|
|
22
26
|
"main": "lib/index.js",
|
|
@@ -27,7 +31,7 @@
|
|
|
27
31
|
"engine-requirements.js"
|
|
28
32
|
],
|
|
29
33
|
"scripts": {
|
|
30
|
-
|
|
34
|
+
"build:all": "tsc && typedoc",
|
|
31
35
|
"build:docs": "typedoc",
|
|
32
36
|
"build:tsc": "tsc",
|
|
33
37
|
"changelog:last": "conventional-changelog -p angular -r 2",
|
|
@@ -37,10 +41,9 @@
|
|
|
37
41
|
"gen:protobuf": "sh WAProto/GenerateStatics.sh",
|
|
38
42
|
"lint": "eslint src --ext .js,.ts,.jsx,.tsx",
|
|
39
43
|
"lint:fix": "eslint src --fix --ext .js,.ts,.jsx,.tsx",
|
|
40
|
-
"prepack": "
|
|
41
|
-
"prepare": "echo '
|
|
44
|
+
"prepack": "echo 'Wileys WhatsApp Library'",
|
|
45
|
+
"prepare": "echo 'Wileys WhatsApp Library'",
|
|
42
46
|
"preinstall": "node ./engine-requirements.js",
|
|
43
|
-
"postinstall": "node ./lib/Defaults/update-wa-version.js",
|
|
44
47
|
"release": "release-it",
|
|
45
48
|
"test": "jest"
|
|
46
49
|
},
|
|
@@ -51,13 +54,11 @@
|
|
|
51
54
|
"async-mutex": "^0.5.0",
|
|
52
55
|
"axios": "^1.6.0",
|
|
53
56
|
"chalk": "^4.1.2",
|
|
54
|
-
"fluent-ffmpeg": "^2.1.2",
|
|
55
|
-
"ffmpeg-static": "^5.2.0",
|
|
56
57
|
"gradient-string": "^2.0.2",
|
|
57
58
|
"cache-manager": "^5.7.6",
|
|
58
59
|
"cheerio": "^1.0.0-rc.10",
|
|
59
60
|
"libphonenumber-js": "^1.10.20",
|
|
60
|
-
"libsignal": "github:
|
|
61
|
+
"libsignal": "github:NaufalYupra/libsignal-node",
|
|
61
62
|
"lodash": "^4.17.21",
|
|
62
63
|
"music-metadata": "^7.12.3",
|
|
63
64
|
"pino": "^9.6",
|