gifted-baileys 1.5.0 → 1.5.5
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/LICENSE +1 -1
- package/README.md +1429 -684
- package/package.json +11 -26
- package/src/Defaults/baileys-version.json +3 -0
- package/{lib → src}/Defaults/index.js +16 -8
- package/src/Defaults/index.ts +131 -0
- package/src/Defaults/phonenumber-mcc.json +223 -0
- package/src/Signal/libsignal.js +180 -0
- package/src/Signal/libsignal.ts +141 -0
- package/src/Socket/Client/abstract-socket-client.ts +19 -0
- package/src/Socket/Client/index.ts +3 -0
- package/src/Socket/Client/mobile-socket-client.js +78 -0
- package/src/Socket/Client/mobile-socket-client.ts +66 -0
- package/src/Socket/Client/web-socket-client.js +75 -0
- package/src/Socket/Client/web-socket-client.ts +57 -0
- package/{lib → src}/Socket/business.js +33 -27
- package/src/Socket/business.ts +281 -0
- package/{lib → src}/Socket/chats.js +197 -178
- package/src/Socket/chats.ts +1030 -0
- package/{lib → src}/Socket/groups.js +69 -79
- package/src/Socket/groups.ts +356 -0
- package/{lib → src}/Socket/index.js +1 -4
- package/src/Socket/index.ts +13 -0
- package/{lib → src}/Socket/messages-recv.js +160 -108
- package/src/Socket/messages-recv.ts +985 -0
- package/{lib → src}/Socket/messages-send.js +183 -100
- package/src/Socket/messages-send.ts +871 -0
- package/src/Socket/newsletter.js +227 -0
- package/src/Socket/newsletter.ts +282 -0
- package/{lib → src}/Socket/registration.js +55 -63
- package/src/Socket/registration.ts +250 -0
- package/{lib → src}/Socket/socket.js +107 -66
- package/src/Socket/socket.ts +777 -0
- package/src/Store/index.ts +3 -0
- package/{lib → src}/Store/make-cache-manager-store.js +34 -25
- package/src/Store/make-cache-manager-store.ts +100 -0
- package/{lib → src}/Store/make-in-memory-store.js +51 -61
- package/src/Store/make-in-memory-store.ts +475 -0
- package/src/Store/make-ordered-dictionary.ts +86 -0
- package/{lib → src}/Store/object-repository.js +1 -1
- package/src/Store/object-repository.ts +32 -0
- package/src/Tests/test.app-state-sync.js +204 -0
- package/src/Tests/test.app-state-sync.ts +207 -0
- package/src/Tests/test.event-buffer.js +270 -0
- package/src/Tests/test.event-buffer.ts +319 -0
- package/src/Tests/test.key-store.js +76 -0
- package/src/Tests/test.key-store.ts +92 -0
- package/src/Tests/test.libsignal.js +141 -0
- package/src/Tests/test.libsignal.ts +186 -0
- package/src/Tests/test.media-download.js +93 -0
- package/src/Tests/test.media-download.ts +76 -0
- package/src/Tests/test.messages.js +33 -0
- package/src/Tests/test.messages.ts +37 -0
- package/src/Tests/utils.js +34 -0
- package/src/Tests/utils.ts +36 -0
- package/src/Types/Auth.ts +113 -0
- package/src/Types/Call.ts +15 -0
- package/src/Types/Chat.ts +106 -0
- package/{lib/Types/Contact.d.ts → src/Types/Contact.ts} +9 -8
- package/src/Types/Events.ts +93 -0
- package/src/Types/GroupMetadata.ts +53 -0
- package/{lib → src}/Types/Label.js +1 -1
- package/src/Types/Label.ts +36 -0
- package/{lib → src}/Types/LabelAssociation.js +1 -1
- package/{lib/Types/LabelAssociation.d.ts → src/Types/LabelAssociation.ts} +22 -16
- package/src/Types/Message.ts +288 -0
- package/src/Types/Newsletter.js +32 -0
- package/src/Types/Newsletter.ts +98 -0
- package/src/Types/Product.ts +85 -0
- package/src/Types/Signal.ts +68 -0
- package/{lib/Types/Socket.d.ts → src/Types/Socket.ts} +68 -56
- package/src/Types/State.ts +29 -0
- package/{lib → src}/Types/index.js +2 -1
- package/src/Types/index.ts +59 -0
- package/{lib → src}/Utils/auth-utils.js +95 -76
- package/src/Utils/auth-utils.ts +222 -0
- package/src/Utils/baileys-event-stream.js +92 -0
- package/src/Utils/baileys-event-stream.ts +66 -0
- package/{lib → src}/Utils/business.js +45 -17
- package/src/Utils/business.ts +275 -0
- package/{lib → src}/Utils/chat-utils.js +74 -46
- package/src/Utils/chat-utils.ts +860 -0
- package/{lib → src}/Utils/crypto.js +31 -21
- package/src/Utils/crypto.ts +131 -0
- package/src/Utils/decode-wa-message.js +211 -0
- package/src/Utils/decode-wa-message.ts +228 -0
- package/{lib → src}/Utils/event-buffer.js +13 -4
- package/src/Utils/event-buffer.ts +613 -0
- package/{lib → src}/Utils/generics.js +98 -45
- package/src/Utils/generics.ts +434 -0
- package/{lib → src}/Utils/history.js +39 -10
- package/src/Utils/history.ts +112 -0
- package/src/Utils/index.ts +17 -0
- package/{lib → src}/Utils/link-preview.js +54 -17
- package/src/Utils/link-preview.ts +122 -0
- package/src/Utils/logger.ts +3 -0
- package/src/Utils/lt-hash.ts +61 -0
- package/{lib → src}/Utils/make-mutex.js +13 -4
- package/src/Utils/make-mutex.ts +44 -0
- package/{lib → src}/Utils/messages-media.js +296 -192
- package/src/Utils/messages-media.ts +847 -0
- package/{lib → src}/Utils/messages.js +124 -113
- package/src/Utils/messages.ts +956 -0
- package/{lib → src}/Utils/noise-handler.js +16 -3
- package/src/Utils/noise-handler.ts +197 -0
- package/{lib → src}/Utils/process-message.js +33 -29
- package/src/Utils/process-message.ts +414 -0
- package/{lib → src}/Utils/signal.js +23 -14
- package/src/Utils/signal.ts +177 -0
- package/{lib → src}/Utils/use-multi-file-auth-state.js +28 -19
- package/src/Utils/use-multi-file-auth-state.ts +90 -0
- package/{lib → src}/Utils/validate-connection.js +25 -42
- package/src/Utils/validate-connection.ts +238 -0
- package/src/WABinary/constants.ts +42 -0
- package/{lib → src}/WABinary/decode.js +17 -7
- package/src/WABinary/decode.ts +265 -0
- package/{lib → src}/WABinary/encode.js +17 -7
- package/src/WABinary/encode.ts +236 -0
- package/{lib → src}/WABinary/generic-utils.js +2 -2
- package/src/WABinary/generic-utils.ts +121 -0
- package/src/WABinary/index.ts +5 -0
- package/{lib → src}/WABinary/jid-utils.js +4 -1
- package/src/WABinary/jid-utils.ts +68 -0
- package/src/WABinary/types.ts +17 -0
- package/src/WAM/BinaryInfo.js +13 -0
- package/src/WAM/BinaryInfo.ts +12 -0
- package/src/WAM/constants.js +15350 -0
- package/src/WAM/constants.ts +15382 -0
- package/src/WAM/encode.js +155 -0
- package/src/WAM/encode.ts +174 -0
- package/src/WAM/index.js +19 -0
- package/src/WAM/index.ts +3 -0
- package/src/gifted +1 -0
- package/{lib → src}/index.js +1 -0
- package/src/index.ts +13 -0
- package/lib/Defaults/baileys-version.json +0 -3
- package/lib/Defaults/index.d.ts +0 -284
- package/lib/Defaults/phonenumber-mcc.json +0 -223
- package/lib/Signal/libsignal.d.ts +0 -3
- package/lib/Signal/libsignal.js +0 -152
- package/lib/Socket/Client/abstract-socket-client.d.ts +0 -17
- package/lib/Socket/Client/index.d.ts +0 -3
- package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
- package/lib/Socket/Client/mobile-socket-client.js +0 -65
- package/lib/Socket/Client/web-socket-client.d.ts +0 -12
- package/lib/Socket/Client/web-socket-client.js +0 -62
- package/lib/Socket/business.d.ts +0 -135
- package/lib/Socket/chats.d.ts +0 -79
- package/lib/Socket/groups.d.ts +0 -113
- package/lib/Socket/index.d.ts +0 -137
- package/lib/Socket/messages-recv.d.ts +0 -124
- package/lib/Socket/messages-send.d.ts +0 -119
- package/lib/Socket/registration.d.ts +0 -232
- package/lib/Socket/socket.d.ts +0 -42
- package/lib/Store/index.d.ts +0 -3
- package/lib/Store/make-cache-manager-store.d.ts +0 -13
- package/lib/Store/make-in-memory-store.d.ts +0 -117
- package/lib/Store/make-ordered-dictionary.d.ts +0 -13
- package/lib/Store/object-repository.d.ts +0 -10
- package/lib/Types/Auth.d.ts +0 -108
- package/lib/Types/Call.d.ts +0 -13
- package/lib/Types/Chat.d.ts +0 -102
- package/lib/Types/Events.d.ts +0 -157
- package/lib/Types/GroupMetadata.d.ts +0 -52
- package/lib/Types/Label.d.ts +0 -35
- package/lib/Types/Message.d.ts +0 -261
- package/lib/Types/Product.d.ts +0 -78
- package/lib/Types/Signal.d.ts +0 -57
- package/lib/Types/State.d.ts +0 -27
- package/lib/Types/index.d.ts +0 -56
- package/lib/Utils/auth-utils.d.ts +0 -18
- package/lib/Utils/baileys-event-stream.d.ts +0 -16
- package/lib/Utils/baileys-event-stream.js +0 -63
- package/lib/Utils/business.d.ts +0 -22
- package/lib/Utils/chat-utils.d.ts +0 -71
- package/lib/Utils/crypto.d.ts +0 -41
- package/lib/Utils/decode-wa-message.d.ts +0 -19
- package/lib/Utils/decode-wa-message.js +0 -174
- package/lib/Utils/event-buffer.d.ts +0 -35
- package/lib/Utils/generics.d.ts +0 -94
- package/lib/Utils/history.d.ts +0 -15
- package/lib/Utils/index.d.ts +0 -17
- package/lib/Utils/link-preview.d.ts +0 -21
- package/lib/Utils/logger.d.ts +0 -4
- package/lib/Utils/lt-hash.d.ts +0 -12
- package/lib/Utils/make-mutex.d.ts +0 -7
- package/lib/Utils/messages-media.d.ts +0 -107
- package/lib/Utils/messages.d.ts +0 -76
- package/lib/Utils/noise-handler.d.ts +0 -20
- package/lib/Utils/process-message.d.ts +0 -41
- package/lib/Utils/signal.d.ts +0 -32
- package/lib/Utils/use-multi-file-auth-state.d.ts +0 -12
- package/lib/Utils/validate-connection.d.ts +0 -11
- package/lib/WABinary/constants.d.ts +0 -27
- package/lib/WABinary/decode.d.ts +0 -7
- package/lib/WABinary/encode.d.ts +0 -3
- package/lib/WABinary/generic-utils.d.ts +0 -15
- package/lib/WABinary/index.d.ts +0 -5
- package/lib/WABinary/jid-utils.d.ts +0 -29
- package/lib/WABinary/types.d.ts +0 -18
- package/lib/index.d.ts +0 -10
- /package/{lib → src}/Socket/Client/abstract-socket-client.js +0 -0
- /package/{lib → src}/Socket/Client/index.js +0 -0
- /package/{lib → src}/Store/index.js +0 -0
- /package/{lib → src}/Store/make-ordered-dictionary.js +0 -0
- /package/{lib → src}/Types/Auth.js +0 -0
- /package/{lib → src}/Types/Call.js +0 -0
- /package/{lib → src}/Types/Chat.js +0 -0
- /package/{lib → src}/Types/Contact.js +0 -0
- /package/{lib → src}/Types/Events.js +0 -0
- /package/{lib → src}/Types/GroupMetadata.js +0 -0
- /package/{lib → src}/Types/Message.js +0 -0
- /package/{lib → src}/Types/Product.js +0 -0
- /package/{lib → src}/Types/Signal.js +0 -0
- /package/{lib → src}/Types/Socket.js +0 -0
- /package/{lib → src}/Types/State.js +0 -0
- /package/{lib → src}/Utils/index.js +0 -0
- /package/{lib → src}/Utils/logger.js +0 -0
- /package/{lib → src}/Utils/lt-hash.js +0 -0
- /package/{lib → src}/WABinary/constants.js +0 -0
- /package/{lib → src}/WABinary/index.js +0 -0
- /package/{lib → src}/WABinary/types.js +0 -0
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
13
|
};
|
|
@@ -11,22 +20,22 @@ const Defaults_1 = require("../Defaults");
|
|
|
11
20
|
const Utils_1 = require("../Utils");
|
|
12
21
|
const link_preview_1 = require("../Utils/link-preview");
|
|
13
22
|
const WABinary_1 = require("../WABinary");
|
|
14
|
-
const
|
|
23
|
+
const newsletter_1 = require("./newsletter");
|
|
15
24
|
var ListType = WAProto_1.proto.Message.ListMessage.ListType;
|
|
16
25
|
const makeMessagesSocket = (config) => {
|
|
17
26
|
const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: axiosOptions, patchMessageBeforeSending, } = config;
|
|
18
|
-
const sock = (0,
|
|
27
|
+
const sock = (0, newsletter_1.makeNewsletterSocket)(config);
|
|
19
28
|
const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, generateMessageTag, sendNode, groupMetadata, groupToggleEphemeral } = sock;
|
|
20
29
|
const userDevicesCache = config.userDevicesCache || new node_cache_1.default({
|
|
21
|
-
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES,
|
|
30
|
+
stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.USER_DEVICES, // 5 minutes
|
|
22
31
|
useClones: false
|
|
23
32
|
});
|
|
24
33
|
let mediaConn;
|
|
25
|
-
const refreshMediaConn =
|
|
26
|
-
const media =
|
|
34
|
+
const refreshMediaConn = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (forceGet = false) {
|
|
35
|
+
const media = yield mediaConn;
|
|
27
36
|
if (!media || forceGet || (new Date().getTime() - media.fetchDate.getTime()) > media.ttl * 1000) {
|
|
28
|
-
mediaConn = (
|
|
29
|
-
const result =
|
|
37
|
+
mediaConn = (() => __awaiter(void 0, void 0, void 0, function* () {
|
|
38
|
+
const result = yield query({
|
|
30
39
|
tag: 'iq',
|
|
31
40
|
attrs: {
|
|
32
41
|
type: 'set',
|
|
@@ -47,15 +56,15 @@ const makeMessagesSocket = (config) => {
|
|
|
47
56
|
};
|
|
48
57
|
logger.debug('fetched media conn');
|
|
49
58
|
return node;
|
|
50
|
-
})();
|
|
59
|
+
}))();
|
|
51
60
|
}
|
|
52
61
|
return mediaConn;
|
|
53
|
-
};
|
|
62
|
+
});
|
|
54
63
|
/**
|
|
55
64
|
* generic send receipt function
|
|
56
65
|
* used for receipts of phone call, read, delivery etc.
|
|
57
66
|
* */
|
|
58
|
-
const sendReceipt =
|
|
67
|
+
const sendReceipt = (jid, participant, messageIds, type) => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
68
|
const node = {
|
|
60
69
|
tag: 'receipt',
|
|
61
70
|
attrs: {
|
|
@@ -77,7 +86,7 @@ const makeMessagesSocket = (config) => {
|
|
|
77
86
|
}
|
|
78
87
|
}
|
|
79
88
|
if (type) {
|
|
80
|
-
node.attrs.type = type;
|
|
89
|
+
node.attrs.type = (0, WABinary_1.isJidNewsLetter)(jid) ? 'read-self' : type;
|
|
81
90
|
}
|
|
82
91
|
const remainingMessageIds = messageIds.slice(1);
|
|
83
92
|
if (remainingMessageIds.length) {
|
|
@@ -93,24 +102,24 @@ const makeMessagesSocket = (config) => {
|
|
|
93
102
|
];
|
|
94
103
|
}
|
|
95
104
|
logger.debug({ attrs: node.attrs, messageIds }, 'sending receipt for messages');
|
|
96
|
-
|
|
97
|
-
};
|
|
105
|
+
yield sendNode(node);
|
|
106
|
+
});
|
|
98
107
|
/** Correctly bulk send receipts to multiple chats, participants */
|
|
99
|
-
const sendReceipts =
|
|
108
|
+
const sendReceipts = (keys, type) => __awaiter(void 0, void 0, void 0, function* () {
|
|
100
109
|
const recps = (0, Utils_1.aggregateMessageKeysNotFromMe)(keys);
|
|
101
110
|
for (const { jid, participant, messageIds } of recps) {
|
|
102
|
-
|
|
111
|
+
yield sendReceipt(jid, participant, messageIds, type);
|
|
103
112
|
}
|
|
104
|
-
};
|
|
113
|
+
});
|
|
105
114
|
/** Bulk read messages. Keys can be from different chats & participants */
|
|
106
|
-
const readMessages =
|
|
107
|
-
const privacySettings =
|
|
115
|
+
const readMessages = (keys) => __awaiter(void 0, void 0, void 0, function* () {
|
|
116
|
+
const privacySettings = yield fetchPrivacySettings();
|
|
108
117
|
// based on privacy settings, we have to change the read type
|
|
109
118
|
const readType = privacySettings.readreceipts === 'all' ? 'read' : 'read-self';
|
|
110
|
-
|
|
111
|
-
};
|
|
119
|
+
yield sendReceipts(keys, readType);
|
|
120
|
+
});
|
|
112
121
|
/** Fetch all the devices we've to send a message to */
|
|
113
|
-
const getUSyncDevices =
|
|
122
|
+
const getUSyncDevices = (jids, useCache, ignoreZeroDevices) => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
123
|
var _a;
|
|
115
124
|
const deviceResults = [];
|
|
116
125
|
if (!useCache) {
|
|
@@ -130,6 +139,9 @@ const makeMessagesSocket = (config) => {
|
|
|
130
139
|
users.push({ tag: 'user', attrs: { jid } });
|
|
131
140
|
}
|
|
132
141
|
}
|
|
142
|
+
if (!users.length) {
|
|
143
|
+
return deviceResults;
|
|
144
|
+
}
|
|
133
145
|
const iq = {
|
|
134
146
|
tag: 'iq',
|
|
135
147
|
attrs: {
|
|
@@ -163,7 +175,7 @@ const makeMessagesSocket = (config) => {
|
|
|
163
175
|
},
|
|
164
176
|
],
|
|
165
177
|
};
|
|
166
|
-
const result =
|
|
178
|
+
const result = yield query(iq);
|
|
167
179
|
const extracted = (0, Utils_1.extractDeviceJids)(result, authState.creds.me.id, ignoreZeroDevices);
|
|
168
180
|
const deviceMap = {};
|
|
169
181
|
for (const item of extracted) {
|
|
@@ -175,8 +187,8 @@ const makeMessagesSocket = (config) => {
|
|
|
175
187
|
userDevicesCache.set(key, deviceMap[key]);
|
|
176
188
|
}
|
|
177
189
|
return deviceResults;
|
|
178
|
-
};
|
|
179
|
-
const assertSessions =
|
|
190
|
+
});
|
|
191
|
+
const assertSessions = (jids, force) => __awaiter(void 0, void 0, void 0, function* () {
|
|
180
192
|
let didFetchNewSession = false;
|
|
181
193
|
let jidsRequiringFetch = [];
|
|
182
194
|
if (force) {
|
|
@@ -185,7 +197,7 @@ const makeMessagesSocket = (config) => {
|
|
|
185
197
|
else {
|
|
186
198
|
const addrs = jids.map(jid => (signalRepository
|
|
187
199
|
.jidToSignalProtocolAddress(jid)));
|
|
188
|
-
const sessions =
|
|
200
|
+
const sessions = yield authState.keys.get('session', addrs);
|
|
189
201
|
for (const jid of jids) {
|
|
190
202
|
const signalId = signalRepository
|
|
191
203
|
.jidToSignalProtocolAddress(jid);
|
|
@@ -196,7 +208,7 @@ const makeMessagesSocket = (config) => {
|
|
|
196
208
|
}
|
|
197
209
|
if (jidsRequiringFetch.length) {
|
|
198
210
|
logger.debug({ jidsRequiringFetch }, 'fetching sessions');
|
|
199
|
-
const result =
|
|
211
|
+
const result = yield query({
|
|
200
212
|
tag: 'iq',
|
|
201
213
|
attrs: {
|
|
202
214
|
xmlns: 'encrypt',
|
|
@@ -214,17 +226,17 @@ const makeMessagesSocket = (config) => {
|
|
|
214
226
|
}
|
|
215
227
|
]
|
|
216
228
|
});
|
|
217
|
-
|
|
229
|
+
yield (0, Utils_1.parseAndInjectE2ESessions)(result, signalRepository);
|
|
218
230
|
didFetchNewSession = true;
|
|
219
231
|
}
|
|
220
232
|
return didFetchNewSession;
|
|
221
|
-
};
|
|
222
|
-
const createParticipantNodes =
|
|
223
|
-
const patched =
|
|
233
|
+
});
|
|
234
|
+
const createParticipantNodes = (jids, message, extraAttrs) => __awaiter(void 0, void 0, void 0, function* () {
|
|
235
|
+
const patched = yield patchMessageBeforeSending(message, jids);
|
|
224
236
|
const bytes = (0, Utils_1.encodeWAMessage)(patched);
|
|
225
237
|
let shouldIncludeDeviceIdentity = false;
|
|
226
|
-
const nodes =
|
|
227
|
-
const { type, ciphertext } =
|
|
238
|
+
const nodes = yield Promise.all(jids.map((jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
239
|
+
const { type, ciphertext } = yield signalRepository
|
|
228
240
|
.encryptMessage({ jid, data: bytes });
|
|
229
241
|
if (type === 'pkmsg') {
|
|
230
242
|
shouldIncludeDeviceIdentity = true;
|
|
@@ -234,19 +246,15 @@ const makeMessagesSocket = (config) => {
|
|
|
234
246
|
attrs: { jid },
|
|
235
247
|
content: [{
|
|
236
248
|
tag: 'enc',
|
|
237
|
-
attrs: {
|
|
238
|
-
v: '2',
|
|
239
|
-
type,
|
|
240
|
-
...extraAttrs || {}
|
|
241
|
-
},
|
|
249
|
+
attrs: Object.assign({ v: '2', type }, extraAttrs || {}),
|
|
242
250
|
content: ciphertext
|
|
243
251
|
}]
|
|
244
252
|
};
|
|
245
253
|
return node;
|
|
246
|
-
}));
|
|
254
|
+
})));
|
|
247
255
|
return { nodes, shouldIncludeDeviceIdentity };
|
|
248
|
-
};
|
|
249
|
-
const relayMessage =
|
|
256
|
+
}); //apela
|
|
257
|
+
const relayMessage = (jid_1, message_1, _a) => __awaiter(void 0, [jid_1, message_1, _a], void 0, function* (jid, message, { messageId: msgId, participant, additionalAttributes, additionalNodes, useUserDevicesCache, cachedGroupMetadata, statusJidList }) {
|
|
250
258
|
const meId = authState.creds.me.id;
|
|
251
259
|
let shouldIncludeDeviceIdentity = false;
|
|
252
260
|
const { user, server } = (0, WABinary_1.jidDecode)(jid);
|
|
@@ -254,10 +262,11 @@ const makeMessagesSocket = (config) => {
|
|
|
254
262
|
const isGroup = server === 'g.us';
|
|
255
263
|
const isStatus = jid === statusJid;
|
|
256
264
|
const isLid = server === 'lid';
|
|
265
|
+
const isNewsletter = server === 'newsletter';
|
|
257
266
|
msgId = msgId || (0, Utils_1.generateMessageID)();
|
|
258
267
|
useUserDevicesCache = useUserDevicesCache !== false;
|
|
259
268
|
const participants = [];
|
|
260
|
-
const destinationJid = (!isStatus) ? (0, WABinary_1.jidEncode)(user, isLid ? 'lid' : isGroup ? 'g.us' : 's.whatsapp.net') : statusJid;
|
|
269
|
+
const destinationJid = (!isStatus) ? (0, WABinary_1.jidEncode)(user, isLid ? 'lid' : isGroup ? 'g.us' : isNewsletter ? 'newsletter' : 's.whatsapp.net') : statusJid;
|
|
261
270
|
const binaryNodeContent = [];
|
|
262
271
|
const devices = [];
|
|
263
272
|
const meMsg = {
|
|
@@ -271,45 +280,45 @@ const makeMessagesSocket = (config) => {
|
|
|
271
280
|
// only send to the specific device that asked for a retry
|
|
272
281
|
// otherwise the message is sent out to every device that should be a recipient
|
|
273
282
|
if (!isGroup && !isStatus) {
|
|
274
|
-
additionalAttributes = {
|
|
283
|
+
additionalAttributes = Object.assign(Object.assign({}, additionalAttributes), { 'device_fanout': 'false' });
|
|
275
284
|
}
|
|
276
285
|
const { user, device } = (0, WABinary_1.jidDecode)(participant.jid);
|
|
277
286
|
devices.push({ user, device });
|
|
278
287
|
}
|
|
279
|
-
|
|
280
|
-
var _a, _b;
|
|
288
|
+
yield authState.keys.transaction(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
289
|
+
var _a, _b, _c, _d, _e, _f;
|
|
281
290
|
const mediaType = getMediaType(message);
|
|
282
291
|
if (isGroup || isStatus) {
|
|
283
|
-
const [groupData, senderKeyMap] =
|
|
284
|
-
(
|
|
285
|
-
let groupData = cachedGroupMetadata ?
|
|
292
|
+
const [groupData, senderKeyMap] = yield Promise.all([
|
|
293
|
+
(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
294
|
+
let groupData = cachedGroupMetadata ? yield cachedGroupMetadata(jid) : undefined;
|
|
286
295
|
if (groupData) {
|
|
287
296
|
logger.trace({ jid, participants: groupData.participants.length }, 'using cached group metadata');
|
|
288
297
|
}
|
|
289
298
|
if (!groupData && !isStatus) {
|
|
290
|
-
groupData =
|
|
299
|
+
groupData = yield groupMetadata(jid);
|
|
291
300
|
}
|
|
292
301
|
return groupData;
|
|
293
|
-
})(),
|
|
294
|
-
(
|
|
302
|
+
}))(),
|
|
303
|
+
(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
295
304
|
if (!participant && !isStatus) {
|
|
296
|
-
const result =
|
|
305
|
+
const result = yield authState.keys.get('sender-key-memory', [jid]);
|
|
297
306
|
return result[jid] || {};
|
|
298
307
|
}
|
|
299
308
|
return {};
|
|
300
|
-
})()
|
|
309
|
+
}))()
|
|
301
310
|
]);
|
|
302
311
|
if (!participant) {
|
|
303
312
|
const participantsList = (groupData && !isStatus) ? groupData.participants.map(p => p.id) : [];
|
|
304
313
|
if (isStatus && statusJidList) {
|
|
305
314
|
participantsList.push(...statusJidList);
|
|
306
315
|
}
|
|
307
|
-
const additionalDevices =
|
|
316
|
+
const additionalDevices = yield getUSyncDevices(participantsList, !!useUserDevicesCache, false);
|
|
308
317
|
devices.push(...additionalDevices);
|
|
309
318
|
}
|
|
310
|
-
const patched =
|
|
319
|
+
const patched = yield patchMessageBeforeSending(message, devices.map(d => (0, WABinary_1.jidEncode)(d.user, isLid ? 'lid' : 's.whatsapp.net', d.device)));
|
|
311
320
|
const bytes = (0, Utils_1.encodeWAMessage)(patched);
|
|
312
|
-
const { ciphertext, senderKeyDistributionMessage } =
|
|
321
|
+
const { ciphertext, senderKeyDistributionMessage } = yield signalRepository.encryptGroupMessage({
|
|
313
322
|
group: destinationJid,
|
|
314
323
|
data: bytes,
|
|
315
324
|
meId,
|
|
@@ -334,8 +343,8 @@ const makeMessagesSocket = (config) => {
|
|
|
334
343
|
groupId: destinationJid
|
|
335
344
|
}
|
|
336
345
|
};
|
|
337
|
-
|
|
338
|
-
const result =
|
|
346
|
+
yield assertSessions(senderKeyJids, false);
|
|
347
|
+
const result = yield createParticipantNodes(senderKeyJids, senderKeyMsg, mediaType ? { mediatype: mediaType } : undefined);
|
|
339
348
|
shouldIncludeDeviceIdentity = shouldIncludeDeviceIdentity || result.shouldIncludeDeviceIdentity;
|
|
340
349
|
participants.push(...result.nodes);
|
|
341
350
|
}
|
|
@@ -344,7 +353,26 @@ const makeMessagesSocket = (config) => {
|
|
|
344
353
|
attrs: { v: '2', type: 'skmsg' },
|
|
345
354
|
content: ciphertext
|
|
346
355
|
});
|
|
347
|
-
|
|
356
|
+
yield authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });
|
|
357
|
+
}
|
|
358
|
+
else if (isNewsletter) {
|
|
359
|
+
// Message edit
|
|
360
|
+
if ((_a = message.protocolMessage) === null || _a === void 0 ? void 0 : _a.editedMessage) {
|
|
361
|
+
msgId = (_b = message.protocolMessage.key) === null || _b === void 0 ? void 0 : _b.id;
|
|
362
|
+
message = message.protocolMessage.editedMessage;
|
|
363
|
+
}
|
|
364
|
+
// Message delete
|
|
365
|
+
if (((_c = message.protocolMessage) === null || _c === void 0 ? void 0 : _c.type) === WAProto_1.proto.Message.ProtocolMessage.Type.REVOKE) {
|
|
366
|
+
msgId = (_d = message.protocolMessage.key) === null || _d === void 0 ? void 0 : _d.id;
|
|
367
|
+
message = {};
|
|
368
|
+
}
|
|
369
|
+
const patched = yield patchMessageBeforeSending(message, []);
|
|
370
|
+
const bytes = WAProto_1.proto.Message.encode(patched).finish();
|
|
371
|
+
binaryNodeContent.push({
|
|
372
|
+
tag: 'plaintext',
|
|
373
|
+
attrs: mediaType ? { mediatype: mediaType } : {},
|
|
374
|
+
content: bytes
|
|
375
|
+
});
|
|
348
376
|
}
|
|
349
377
|
else {
|
|
350
378
|
const { user: meUser, device: meDevice } = (0, WABinary_1.jidDecode)(meId);
|
|
@@ -354,7 +382,7 @@ const makeMessagesSocket = (config) => {
|
|
|
354
382
|
if (meDevice !== undefined && meDevice !== 0) {
|
|
355
383
|
devices.push({ user: meUser });
|
|
356
384
|
}
|
|
357
|
-
const additionalDevices =
|
|
385
|
+
const additionalDevices = yield getUSyncDevices([meId, jid], !!useUserDevicesCache, true);
|
|
358
386
|
devices.push(...additionalDevices);
|
|
359
387
|
}
|
|
360
388
|
const allJids = [];
|
|
@@ -362,7 +390,7 @@ const makeMessagesSocket = (config) => {
|
|
|
362
390
|
const otherJids = [];
|
|
363
391
|
for (const { user, device } of devices) {
|
|
364
392
|
const isMe = user === meUser;
|
|
365
|
-
const jid = (0, WABinary_1.jidEncode)(isMe && isLid ? ((
|
|
393
|
+
const jid = (0, WABinary_1.jidEncode)(isMe && isLid ? ((_f = (_e = authState.creds) === null || _e === void 0 ? void 0 : _e.me) === null || _f === void 0 ? void 0 : _f.lid.split(':')[0]) || user : user, isLid ? 'lid' : 's.whatsapp.net', device);
|
|
366
394
|
if (isMe) {
|
|
367
395
|
meJids.push(jid);
|
|
368
396
|
}
|
|
@@ -371,8 +399,8 @@ const makeMessagesSocket = (config) => {
|
|
|
371
399
|
}
|
|
372
400
|
allJids.push(jid);
|
|
373
401
|
}
|
|
374
|
-
|
|
375
|
-
const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] =
|
|
402
|
+
yield assertSessions(allJids, false);
|
|
403
|
+
const [{ nodes: meNodes, shouldIncludeDeviceIdentity: s1 }, { nodes: otherNodes, shouldIncludeDeviceIdentity: s2 }] = yield Promise.all([
|
|
376
404
|
createParticipantNodes(meJids, meMsg, mediaType ? { mediatype: mediaType } : undefined),
|
|
377
405
|
createParticipantNodes(otherJids, message, mediaType ? { mediatype: mediaType } : undefined)
|
|
378
406
|
]);
|
|
@@ -389,11 +417,7 @@ const makeMessagesSocket = (config) => {
|
|
|
389
417
|
}
|
|
390
418
|
const stanza = {
|
|
391
419
|
tag: 'message',
|
|
392
|
-
attrs: {
|
|
393
|
-
id: msgId,
|
|
394
|
-
type: 'text',
|
|
395
|
-
...(additionalAttributes || {})
|
|
396
|
-
},
|
|
420
|
+
attrs: Object.assign({ id: msgId, type: isNewsletter ? getTypeMessage(message) : 'text' }, (additionalAttributes || {})),
|
|
397
421
|
content: binaryNodeContent
|
|
398
422
|
};
|
|
399
423
|
// if the participant to send to is explicitly specified (generally retry recp)
|
|
@@ -423,6 +447,28 @@ const makeMessagesSocket = (config) => {
|
|
|
423
447
|
});
|
|
424
448
|
logger.debug({ jid }, 'adding device identity');
|
|
425
449
|
}
|
|
450
|
+
if (additionalNodes && additionalNodes.length > 0) {
|
|
451
|
+
stanza.content.push(...additionalNodes);
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
if (((0, WABinary_1.isJidGroup)(jid) || (0, WABinary_1.isJidUser)(jid)) && ((message === null || message === void 0 ? void 0 : message.viewOnceMessage) ? message === null || message === void 0 ? void 0 : message.viewOnceMessage : (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2) ? message === null || message === void 0 ? void 0 : message.viewOnceMessageV2 : (message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension) ? message === null || message === void 0 ? void 0 : message.viewOnceMessageV2Extension : (message === null || message === void 0 ? void 0 : message.ephemeralMessage) ? message === null || message === void 0 ? void 0 : message.ephemeralMessage : (message === null || message === void 0 ? void 0 : message.templateMessage) ? message === null || message === void 0 ? void 0 : message.templateMessage : (message === null || message === void 0 ? void 0 : message.interactiveMessage) ? message === null || message === void 0 ? void 0 : message.interactiveMessage : message === null || message === void 0 ? void 0 : message.buttonsMessage)) {
|
|
455
|
+
stanza.content.push({
|
|
456
|
+
tag: 'biz',
|
|
457
|
+
attrs: {},
|
|
458
|
+
content: [{
|
|
459
|
+
tag: 'interactive',
|
|
460
|
+
attrs: {
|
|
461
|
+
type: 'native_flow',
|
|
462
|
+
v: '1'
|
|
463
|
+
},
|
|
464
|
+
content: [{
|
|
465
|
+
tag: 'native_flow',
|
|
466
|
+
attrs: { name: 'quick_reply' }
|
|
467
|
+
}]
|
|
468
|
+
}]
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
}
|
|
426
472
|
const buttonType = getButtonType(message);
|
|
427
473
|
if (buttonType) {
|
|
428
474
|
stanza.content.push({
|
|
@@ -438,9 +484,38 @@ const makeMessagesSocket = (config) => {
|
|
|
438
484
|
logger.debug({ jid }, 'adding business node');
|
|
439
485
|
}
|
|
440
486
|
logger.debug({ msgId }, `sending message to ${participants.length} devices`);
|
|
441
|
-
|
|
442
|
-
});
|
|
487
|
+
yield sendNode(stanza);
|
|
488
|
+
}));
|
|
443
489
|
return msgId;
|
|
490
|
+
});
|
|
491
|
+
const getTypeMessage = (msg) => {
|
|
492
|
+
if (msg.viewOnceMessage) {
|
|
493
|
+
return getTypeMessage(msg.viewOnceMessage.message);
|
|
494
|
+
}
|
|
495
|
+
else if (msg.viewOnceMessageV2) {
|
|
496
|
+
return getTypeMessage(msg.viewOnceMessageV2.message);
|
|
497
|
+
}
|
|
498
|
+
else if (msg.viewOnceMessageV2Extension) {
|
|
499
|
+
return getTypeMessage(msg.viewOnceMessageV2Extension.message);
|
|
500
|
+
}
|
|
501
|
+
else if (msg.ephemeralMessage) {
|
|
502
|
+
return getTypeMessage(msg.ephemeralMessage.message);
|
|
503
|
+
}
|
|
504
|
+
else if (msg.documentWithCaptionMessage) {
|
|
505
|
+
return getTypeMessage(msg.documentWithCaptionMessage.message);
|
|
506
|
+
}
|
|
507
|
+
else if (msg.reactionMessage) {
|
|
508
|
+
return 'reaction';
|
|
509
|
+
}
|
|
510
|
+
else if (msg.pollCreationMessage || msg.pollCreationMessageV2 || msg.pollCreationMessageV3 || msg.pollUpdateMessage) {
|
|
511
|
+
return 'reaction';
|
|
512
|
+
}
|
|
513
|
+
else if (getMediaType(msg)) {
|
|
514
|
+
return 'media';
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
return 'text';
|
|
518
|
+
}
|
|
444
519
|
};
|
|
445
520
|
const getMediaType = (message) => {
|
|
446
521
|
if (message.imageMessage) {
|
|
@@ -519,9 +594,9 @@ const makeMessagesSocket = (config) => {
|
|
|
519
594
|
return {};
|
|
520
595
|
}
|
|
521
596
|
};
|
|
522
|
-
const getPrivacyTokens =
|
|
597
|
+
const getPrivacyTokens = (jids) => __awaiter(void 0, void 0, void 0, function* () {
|
|
523
598
|
const t = (0, Utils_1.unixTimestampSeconds)().toString();
|
|
524
|
-
const result =
|
|
599
|
+
const result = yield query({
|
|
525
600
|
tag: 'iq',
|
|
526
601
|
attrs: {
|
|
527
602
|
to: WABinary_1.S_WHATSAPP_NET,
|
|
@@ -544,12 +619,10 @@ const makeMessagesSocket = (config) => {
|
|
|
544
619
|
]
|
|
545
620
|
});
|
|
546
621
|
return result;
|
|
547
|
-
};
|
|
622
|
+
});
|
|
548
623
|
const waUploadToServer = (0, Utils_1.getWAUploadToServer)(config, refreshMediaConn);
|
|
549
624
|
const waitForMsgMediaUpdate = (0, Utils_1.bindWaitForEvent)(ev, 'messages.media-update');
|
|
550
|
-
return {
|
|
551
|
-
...sock,
|
|
552
|
-
getPrivacyTokens,
|
|
625
|
+
return Object.assign(Object.assign({}, sock), { getPrivacyTokens,
|
|
553
626
|
assertSessions,
|
|
554
627
|
relayMessage,
|
|
555
628
|
sendReceipt,
|
|
@@ -557,15 +630,16 @@ const makeMessagesSocket = (config) => {
|
|
|
557
630
|
getButtonArgs,
|
|
558
631
|
readMessages,
|
|
559
632
|
refreshMediaConn,
|
|
633
|
+
getUSyncDevices,
|
|
634
|
+
createParticipantNodes,
|
|
560
635
|
waUploadToServer,
|
|
561
|
-
fetchPrivacySettings,
|
|
562
|
-
updateMediaMessage: async (message) => {
|
|
636
|
+
fetchPrivacySettings, updateMediaMessage: (message) => __awaiter(void 0, void 0, void 0, function* () {
|
|
563
637
|
const content = (0, Utils_1.assertMediaContent)(message.message);
|
|
564
638
|
const mediaKey = content.mediaKey;
|
|
565
639
|
const meId = authState.creds.me.id;
|
|
566
640
|
const node = (0, Utils_1.encryptMediaRetryRequest)(message.key, mediaKey, meId);
|
|
567
641
|
let error = undefined;
|
|
568
|
-
|
|
642
|
+
yield Promise.all([
|
|
569
643
|
sendNode(node),
|
|
570
644
|
waitForMsgMediaUpdate(update => {
|
|
571
645
|
const result = update.find(c => c.key.id === message.key.id);
|
|
@@ -599,8 +673,7 @@ const makeMessagesSocket = (config) => {
|
|
|
599
673
|
{ key: message.key, update: { message: message.message } }
|
|
600
674
|
]);
|
|
601
675
|
return message;
|
|
602
|
-
},
|
|
603
|
-
sendMessage: async (jid, content, options = {}) => {
|
|
676
|
+
}), sendMessage: (jid_1, content_1, ...args_1) => __awaiter(void 0, [jid_1, content_1, ...args_1], void 0, function* (jid, content, options = {}) {
|
|
604
677
|
var _a, _b;
|
|
605
678
|
const userJid = authState.creds.me.id;
|
|
606
679
|
if (typeof content === 'object' &&
|
|
@@ -611,35 +684,32 @@ const makeMessagesSocket = (config) => {
|
|
|
611
684
|
const value = typeof disappearingMessagesInChat === 'boolean' ?
|
|
612
685
|
(disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :
|
|
613
686
|
disappearingMessagesInChat;
|
|
614
|
-
|
|
687
|
+
yield groupToggleEphemeral(jid, value);
|
|
615
688
|
}
|
|
616
689
|
else {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
userJid,
|
|
620
|
-
getUrlInfo: text => (0, link_preview_1.getUrlInfo)(text, {
|
|
690
|
+
let mediaHandle;
|
|
691
|
+
const fullMsg = yield (0, Utils_1.generateWAMessage)(jid, content, Object.assign({ logger,
|
|
692
|
+
userJid, getUrlInfo: text => (0, link_preview_1.getUrlInfo)(text, {
|
|
621
693
|
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
622
|
-
fetchOpts: {
|
|
623
|
-
timeout: 3000,
|
|
624
|
-
...axiosOptions || {}
|
|
625
|
-
},
|
|
694
|
+
fetchOpts: Object.assign({ timeout: 3000 }, axiosOptions || {}),
|
|
626
695
|
logger,
|
|
627
696
|
uploadImage: generateHighQualityLinkPreview
|
|
628
697
|
? waUploadToServer
|
|
629
698
|
: undefined
|
|
630
|
-
}),
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
});
|
|
699
|
+
}), upload: (readStream, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
700
|
+
const up = yield waUploadToServer(readStream, Object.assign(Object.assign({}, opts), { newsletter: (0, WABinary_1.isJidNewsLetter)(jid) }));
|
|
701
|
+
mediaHandle = up.handle;
|
|
702
|
+
return up;
|
|
703
|
+
}), mediaCache: config.mediaCache, options: config.options }, options));
|
|
636
704
|
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
637
705
|
const isEditMsg = 'edit' in content && !!content.edit;
|
|
706
|
+
const isAiMsg = 'ai' in content && !!content.ai;
|
|
638
707
|
const additionalAttributes = {};
|
|
708
|
+
const additionalNodes = [];
|
|
639
709
|
// required for delete
|
|
640
710
|
if (isDeleteMsg) {
|
|
641
711
|
// if the chat is a group, and I am not the author, then delete the message as an admin
|
|
642
|
-
if ((0, WABinary_1.isJidGroup)((_a = content.delete) === null || _a === void 0 ? void 0 : _a.remoteJid) && !((_b = content.delete) === null || _b === void 0 ? void 0 : _b.fromMe)) {
|
|
712
|
+
if (((0, WABinary_1.isJidGroup)((_a = content.delete) === null || _a === void 0 ? void 0 : _a.remoteJid) && !((_b = content.delete) === null || _b === void 0 ? void 0 : _b.fromMe)) || (0, WABinary_1.isJidNewsLetter)(jid)) {
|
|
643
713
|
additionalAttributes.edit = '8';
|
|
644
714
|
}
|
|
645
715
|
else {
|
|
@@ -647,9 +717,23 @@ const makeMessagesSocket = (config) => {
|
|
|
647
717
|
}
|
|
648
718
|
}
|
|
649
719
|
else if (isEditMsg) {
|
|
650
|
-
additionalAttributes.edit = '1';
|
|
720
|
+
additionalAttributes.edit = (0, WABinary_1.isJidNewsLetter)(jid) ? '3' : '1';
|
|
721
|
+
}
|
|
722
|
+
else if (isAiMsg) {
|
|
723
|
+
additionalNodes.push({
|
|
724
|
+
attrs: {
|
|
725
|
+
biz_bot: '1'
|
|
726
|
+
},
|
|
727
|
+
tag: "bot"
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
if (mediaHandle) {
|
|
731
|
+
additionalAttributes['media_id'] = mediaHandle;
|
|
651
732
|
}
|
|
652
|
-
|
|
733
|
+
if ('cachedGroupMetadata' in options) {
|
|
734
|
+
console.warn('cachedGroupMetadata in sendMessage are deprecated, now cachedGroupMetadata is part of the socket config.');
|
|
735
|
+
}
|
|
736
|
+
yield relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, cachedGroupMetadata: options.cachedGroupMetadata, additionalNodes: isAiMsg ? additionalNodes : options.additionalNodes, additionalAttributes, statusJidList: options.statusJidList });
|
|
653
737
|
if (config.emitOwnEvents) {
|
|
654
738
|
process.nextTick(() => {
|
|
655
739
|
processingMutex.mutex(() => (upsertMessage(fullMsg, 'append')));
|
|
@@ -657,7 +741,6 @@ const makeMessagesSocket = (config) => {
|
|
|
657
741
|
}
|
|
658
742
|
return fullMsg;
|
|
659
743
|
}
|
|
660
|
-
}
|
|
661
|
-
};
|
|
744
|
+
}) });
|
|
662
745
|
};
|
|
663
746
|
exports.makeMessagesSocket = makeMessagesSocket;
|