@queenanya/baileys 7.1.1 → 7.1.6
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 +13 -13
- package/lib/Defaults/index.js +4 -4
- package/lib/Socket/business.d.ts +30 -4
- package/lib/Socket/chats.d.ts +5 -0
- package/lib/Socket/chats.js +14 -0
- package/lib/Socket/groups.d.ts +7 -2
- package/lib/Socket/index.d.ts +30 -4
- package/lib/Socket/messages-recv.d.ts +30 -4
- package/lib/Socket/messages-recv.js +55 -2
- package/lib/Socket/messages-send.d.ts +27 -1
- package/lib/Socket/messages-send.js +54 -7
- package/lib/Socket/newsletter.d.ts +138 -0
- package/lib/Socket/newsletter.js +249 -0
- package/lib/Socket/registration.d.ts +30 -4
- package/lib/Socket/socket.js +2 -1
- package/lib/Types/Events.d.ts +27 -0
- package/lib/Types/Message.d.ts +15 -3
- package/lib/Types/Newsletter.d.ts +79 -0
- package/lib/Types/Newsletter.js +18 -0
- package/lib/Types/index.d.ts +2 -0
- package/lib/Types/index.js +1 -0
- package/lib/Utils/decode-wa-message.js +46 -18
- package/lib/Utils/generics.d.ts +11 -0
- package/lib/Utils/generics.js +17 -6
- package/lib/Utils/logger.d.ts +1 -3
- package/lib/Utils/messages-media.d.ts +10 -1
- package/lib/Utils/messages-media.js +53 -4
- package/lib/Utils/messages.js +32 -11
- package/lib/Utils/signal.js +0 -5
- package/lib/WABinary/encode.d.ts +1 -2
- package/lib/WABinary/encode.js +3 -7
- package/lib/WABinary/jid-utils.d.ts +3 -1
- package/lib/WABinary/jid-utils.js +4 -1
- package/package.json +30 -28
package/lib/Types/Message.d.ts
CHANGED
|
@@ -14,7 +14,9 @@ export type WAMessage = proto.IWebMessageInfo;
|
|
|
14
14
|
export type WAMessageContent = proto.IMessage;
|
|
15
15
|
export type WAContactMessage = proto.Message.IContactMessage;
|
|
16
16
|
export type WAContactsArrayMessage = proto.Message.IContactsArrayMessage;
|
|
17
|
-
export type WAMessageKey = proto.IMessageKey
|
|
17
|
+
export type WAMessageKey = proto.IMessageKey & {
|
|
18
|
+
server_id?: string;
|
|
19
|
+
};
|
|
18
20
|
export type WATextMessage = proto.Message.IExtendedTextMessage;
|
|
19
21
|
export type WAContextInfo = proto.IContextInfo;
|
|
20
22
|
export type WALocationMessage = proto.Message.ILocationMessage;
|
|
@@ -156,6 +158,11 @@ export type AnyRegularMessageContent = (({
|
|
|
156
158
|
type: 'template' | 'plain';
|
|
157
159
|
} | {
|
|
158
160
|
listReply: Omit<proto.Message.IListResponseMessage, 'contextInfo'>;
|
|
161
|
+
} | {
|
|
162
|
+
pin: WAMessageKey;
|
|
163
|
+
time: 86400 | 604800 | 2592000;
|
|
164
|
+
} | {
|
|
165
|
+
unpin: WAMessageKey;
|
|
159
166
|
} | {
|
|
160
167
|
product: WASendableProduct;
|
|
161
168
|
businessOwnerJid?: string;
|
|
@@ -214,13 +221,16 @@ export type MiscMessageGenerationOptions = MinimalRelayOptions & {
|
|
|
214
221
|
export type MessageGenerationOptionsFromContent = MiscMessageGenerationOptions & {
|
|
215
222
|
userJid: string;
|
|
216
223
|
};
|
|
217
|
-
export type
|
|
224
|
+
export type WAMediaUploadFunctionOpts = {
|
|
218
225
|
fileEncSha256B64: string;
|
|
219
226
|
mediaType: MediaType;
|
|
227
|
+
newsletter?: boolean;
|
|
220
228
|
timeoutMs?: number;
|
|
221
|
-
}
|
|
229
|
+
};
|
|
230
|
+
export type WAMediaUploadFunction = (readStream: Readable | Buffer, opts: WAMediaUploadFunctionOpts) => Promise<{
|
|
222
231
|
mediaUrl: string;
|
|
223
232
|
directPath: string;
|
|
233
|
+
handle?: string;
|
|
224
234
|
}>;
|
|
225
235
|
export type MediaGenerationOptions = {
|
|
226
236
|
logger?: Logger;
|
|
@@ -231,6 +241,8 @@ export type MediaGenerationOptions = {
|
|
|
231
241
|
mediaUploadTimeoutMs?: number;
|
|
232
242
|
options?: AxiosRequestConfig;
|
|
233
243
|
backgroundColor?: string;
|
|
244
|
+
/** The message is for newsletter? */
|
|
245
|
+
newsletter?: boolean;
|
|
234
246
|
font?: number;
|
|
235
247
|
};
|
|
236
248
|
export type MessageContentGenerationOptions = MediaGenerationOptions & {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { proto } from '../../WAProto';
|
|
2
|
+
export type NewsletterReactionMode = 'ALL' | 'BASIC' | 'NONE';
|
|
3
|
+
export type NewsletterState = 'ACTIVE' | 'GEOSUSPENDED' | 'SUSPENDED';
|
|
4
|
+
export type NewsletterVerification = 'VERIFIED' | 'UNVERIFIED';
|
|
5
|
+
export type NewsletterMute = 'ON' | 'OFF' | 'UNDEFINED';
|
|
6
|
+
export type NewsletterViewRole = 'ADMIN' | 'GUEST' | 'OWNER' | 'SUBSCRIBER';
|
|
7
|
+
export type NewsletterViewerMetadata = {
|
|
8
|
+
mute: NewsletterMute;
|
|
9
|
+
view_role: NewsletterViewRole;
|
|
10
|
+
};
|
|
11
|
+
export type NewsletterMetadata = {
|
|
12
|
+
/**jid of newsletter */
|
|
13
|
+
id: string;
|
|
14
|
+
/**state of newsletter */
|
|
15
|
+
state: NewsletterState;
|
|
16
|
+
/**creation timestamp of newsletter */
|
|
17
|
+
creation_time: number;
|
|
18
|
+
/**name of newsletter */
|
|
19
|
+
name: string;
|
|
20
|
+
/**timestamp of last name modification of newsletter */
|
|
21
|
+
nameTime: number;
|
|
22
|
+
/**description of newsletter */
|
|
23
|
+
description: string;
|
|
24
|
+
/**timestamp of last description modification of newsletter */
|
|
25
|
+
descriptionTime: number;
|
|
26
|
+
/**invite code of newsletter */
|
|
27
|
+
invite: string;
|
|
28
|
+
/**i dont know */
|
|
29
|
+
handle: null;
|
|
30
|
+
/**direct path of picture */
|
|
31
|
+
picture: string | null;
|
|
32
|
+
/**direct path of picture preview (lower quality) */
|
|
33
|
+
preview: string | null;
|
|
34
|
+
/**reaction mode of newsletter */
|
|
35
|
+
reaction_codes?: NewsletterReactionMode;
|
|
36
|
+
/**subscribers count of newsletter */
|
|
37
|
+
subscribers: number;
|
|
38
|
+
/**verification state of newsletter */
|
|
39
|
+
verification: NewsletterVerification;
|
|
40
|
+
/**viewer metadata */
|
|
41
|
+
viewer_metadata: NewsletterViewerMetadata;
|
|
42
|
+
};
|
|
43
|
+
export type SubscriberAction = 'promote' | 'demote';
|
|
44
|
+
export type ReactionModeUpdate = {
|
|
45
|
+
reaction_codes: {
|
|
46
|
+
blocked_codes: null;
|
|
47
|
+
enabled_ts_sec: null;
|
|
48
|
+
value: NewsletterReactionMode;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
/**only exists reaction mode update */
|
|
52
|
+
export type NewsletterSettingsUpdate = ReactionModeUpdate;
|
|
53
|
+
export type NewsletterReaction = {
|
|
54
|
+
count: number;
|
|
55
|
+
code: string;
|
|
56
|
+
};
|
|
57
|
+
export type NewsletterFetchedUpdate = {
|
|
58
|
+
/**id of message in newsletter, starts from 100 */
|
|
59
|
+
server_id: string;
|
|
60
|
+
/**count of views in this message */
|
|
61
|
+
views?: number;
|
|
62
|
+
/**reactions in this message */
|
|
63
|
+
reactions: NewsletterReaction[];
|
|
64
|
+
/**the message, if you requested only updates, you will not receive message */
|
|
65
|
+
message?: proto.IWebMessageInfo;
|
|
66
|
+
};
|
|
67
|
+
export declare enum MexOperations {
|
|
68
|
+
PROMOTE = "NotificationNewsletterAdminPromote",
|
|
69
|
+
DEMOTE = "NotificationNewsletterAdminDemote",
|
|
70
|
+
UPDATE = "NotificationNewsletterUpdate"
|
|
71
|
+
}
|
|
72
|
+
export declare enum XWAPaths {
|
|
73
|
+
PROMOTE = "xwa2_notify_newsletter_admin_promote",
|
|
74
|
+
DEMOTE = "xwa2_notify_newsletter_admin_demote",
|
|
75
|
+
ADMIN_COUNT = "xwa2_newsletter_admin",
|
|
76
|
+
CREATE = "xwa2_newsletter_create",
|
|
77
|
+
NEWSLETTER = "xwa2_newsletter",
|
|
78
|
+
METADATA_UPDATE = "xwa2_notify_newsletter_on_metadata_update"
|
|
79
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.XWAPaths = exports.MexOperations = void 0;
|
|
4
|
+
var MexOperations;
|
|
5
|
+
(function (MexOperations) {
|
|
6
|
+
MexOperations["PROMOTE"] = "NotificationNewsletterAdminPromote";
|
|
7
|
+
MexOperations["DEMOTE"] = "NotificationNewsletterAdminDemote";
|
|
8
|
+
MexOperations["UPDATE"] = "NotificationNewsletterUpdate";
|
|
9
|
+
})(MexOperations = exports.MexOperations || (exports.MexOperations = {}));
|
|
10
|
+
var XWAPaths;
|
|
11
|
+
(function (XWAPaths) {
|
|
12
|
+
XWAPaths["PROMOTE"] = "xwa2_notify_newsletter_admin_promote";
|
|
13
|
+
XWAPaths["DEMOTE"] = "xwa2_notify_newsletter_admin_demote";
|
|
14
|
+
XWAPaths["ADMIN_COUNT"] = "xwa2_newsletter_admin";
|
|
15
|
+
XWAPaths["CREATE"] = "xwa2_newsletter_create";
|
|
16
|
+
XWAPaths["NEWSLETTER"] = "xwa2_newsletter";
|
|
17
|
+
XWAPaths["METADATA_UPDATE"] = "xwa2_notify_newsletter_on_metadata_update";
|
|
18
|
+
})(XWAPaths = exports.XWAPaths || (exports.XWAPaths = {}));
|
package/lib/Types/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './Chat';
|
|
|
4
4
|
export * from './Contact';
|
|
5
5
|
export * from './State';
|
|
6
6
|
export * from './Message';
|
|
7
|
+
export * from './Newsletter';
|
|
7
8
|
export * from './Socket';
|
|
8
9
|
export * from './Events';
|
|
9
10
|
export * from './Product';
|
|
@@ -14,6 +15,7 @@ import { SocketConfig } from './Socket';
|
|
|
14
15
|
export type UserFacingSocketConfig = Partial<SocketConfig> & {
|
|
15
16
|
auth: AuthenticationState;
|
|
16
17
|
};
|
|
18
|
+
/** Other Browser Support for Paircode */
|
|
17
19
|
export type BrowsersMap = {
|
|
18
20
|
ubuntu(browser: string): [string, string, string];
|
|
19
21
|
macOS(browser: string): [string, string, string];
|
package/lib/Types/index.js
CHANGED
|
@@ -21,6 +21,7 @@ __exportStar(require("./Chat"), exports);
|
|
|
21
21
|
__exportStar(require("./Contact"), exports);
|
|
22
22
|
__exportStar(require("./State"), exports);
|
|
23
23
|
__exportStar(require("./Message"), exports);
|
|
24
|
+
__exportStar(require("./Newsletter"), exports);
|
|
24
25
|
__exportStar(require("./Socket"), exports);
|
|
25
26
|
__exportStar(require("./Events"), exports);
|
|
26
27
|
__exportStar(require("./Product"), exports);
|
|
@@ -11,6 +11,7 @@ const NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node';
|
|
|
11
11
|
* @note this will only parse the message, not decrypt it
|
|
12
12
|
*/
|
|
13
13
|
function decodeMessageNode(stanza, meId, meLid) {
|
|
14
|
+
var _a, _b, _c, _d;
|
|
14
15
|
let msgType;
|
|
15
16
|
let chatId;
|
|
16
17
|
let author;
|
|
@@ -54,6 +55,11 @@ function decodeMessageNode(stanza, meId, meLid) {
|
|
|
54
55
|
author = participant;
|
|
55
56
|
chatId = from;
|
|
56
57
|
}
|
|
58
|
+
else if ((0, WABinary_1.isJidNewsletter)(from)) {
|
|
59
|
+
msgType = 'newsletter';
|
|
60
|
+
author = from;
|
|
61
|
+
chatId = from;
|
|
62
|
+
}
|
|
57
63
|
else if ((0, WABinary_1.isJidBroadcast)(from)) {
|
|
58
64
|
if (!participant) {
|
|
59
65
|
throw new boom_1.Boom('No participant in group message');
|
|
@@ -68,16 +74,22 @@ function decodeMessageNode(stanza, meId, meLid) {
|
|
|
68
74
|
chatId = from;
|
|
69
75
|
author = participant;
|
|
70
76
|
}
|
|
77
|
+
else if ((0, WABinary_1.isJidNewsletter)(from)) {
|
|
78
|
+
msgType = 'newsletter';
|
|
79
|
+
author = from;
|
|
80
|
+
chatId = from;
|
|
81
|
+
}
|
|
71
82
|
else {
|
|
72
83
|
throw new boom_1.Boom('Unknown message type', { data: stanza });
|
|
73
84
|
}
|
|
74
|
-
const fromMe = ((0, WABinary_1.isLidUser)(from) ? isMeLid : isMe)(stanza.attrs.participant || stanza.attrs.from);
|
|
75
|
-
const pushname = stanza.attrs.notify;
|
|
85
|
+
const fromMe = (0, WABinary_1.isJidNewsletter)(from) ? !!((_a = stanza.attrs) === null || _a === void 0 ? void 0 : _a.is_sender) || false : ((0, WABinary_1.isLidUser)(from) ? isMeLid : isMe)(stanza.attrs.participant || stanza.attrs.from);
|
|
86
|
+
const pushname = (_b = stanza === null || stanza === void 0 ? void 0 : stanza.attrs) === null || _b === void 0 ? void 0 : _b.notify;
|
|
76
87
|
const key = {
|
|
77
88
|
remoteJid: chatId,
|
|
78
89
|
fromMe,
|
|
79
90
|
id: msgId,
|
|
80
|
-
participant
|
|
91
|
+
participant,
|
|
92
|
+
server_id: (_c = stanza.attrs) === null || _c === void 0 ? void 0 : _c.server_id
|
|
81
93
|
};
|
|
82
94
|
const fullMessage = {
|
|
83
95
|
key,
|
|
@@ -85,6 +97,9 @@ function decodeMessageNode(stanza, meId, meLid) {
|
|
|
85
97
|
pushName: pushname,
|
|
86
98
|
broadcast: (0, WABinary_1.isJidBroadcast)(from)
|
|
87
99
|
};
|
|
100
|
+
if (msgType === 'newsletter') {
|
|
101
|
+
fullMessage.newsletterServerId = +((_d = stanza.attrs) === null || _d === void 0 ? void 0 : _d.server_id);
|
|
102
|
+
}
|
|
88
103
|
if (key.fromMe) {
|
|
89
104
|
fullMessage.status = WAProto_1.proto.WebMessageInfo.Status.SERVER_ACK;
|
|
90
105
|
}
|
|
@@ -104,14 +119,34 @@ const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
|
|
|
104
119
|
async decrypt() {
|
|
105
120
|
var _a;
|
|
106
121
|
let decryptables = 0;
|
|
107
|
-
|
|
122
|
+
async function processSenderKeyDistribution(msg) {
|
|
123
|
+
if (msg.senderKeyDistributionMessage) {
|
|
124
|
+
try {
|
|
125
|
+
await repository.processSenderKeyDistributionMessage({
|
|
126
|
+
authorJid: author,
|
|
127
|
+
item: msg.senderKeyDistributionMessage
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
logger.error({ key: fullMessage.key, err }, 'failed to process senderKeyDistribution');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if ((0, WABinary_1.isJidNewsletter)(fullMessage.key.remoteJid)) {
|
|
136
|
+
const node = (0, WABinary_1.getBinaryNodeChild)(stanza, 'plaintext');
|
|
137
|
+
const msg = WAProto_1.proto.Message.decode(node === null || node === void 0 ? void 0 : node.content);
|
|
138
|
+
await processSenderKeyDistribution(msg);
|
|
139
|
+
fullMessage.message = msg;
|
|
140
|
+
decryptables += 1;
|
|
141
|
+
}
|
|
142
|
+
else if (Array.isArray(stanza.content)) {
|
|
108
143
|
for (const { tag, attrs, content } of stanza.content) {
|
|
109
144
|
if (tag === 'verified_name' && content instanceof Uint8Array) {
|
|
110
145
|
const cert = WAProto_1.proto.VerifiedNameCertificate.decode(content);
|
|
111
146
|
const details = WAProto_1.proto.VerifiedNameCertificate.Details.decode(cert.details);
|
|
112
147
|
fullMessage.verifiedBizName = details.verifiedName;
|
|
113
148
|
}
|
|
114
|
-
if (tag !== 'enc') {
|
|
149
|
+
if (tag !== 'enc' && tag !== 'plaintext') {
|
|
115
150
|
continue;
|
|
116
151
|
}
|
|
117
152
|
if (!(content instanceof Uint8Array)) {
|
|
@@ -138,22 +173,15 @@ const decryptMessageNode = (stanza, meId, meLid, repository, logger) => {
|
|
|
138
173
|
ciphertext: content
|
|
139
174
|
});
|
|
140
175
|
break;
|
|
176
|
+
case undefined:
|
|
177
|
+
msgBuffer = content;
|
|
178
|
+
break;
|
|
141
179
|
default:
|
|
142
180
|
throw new Error(`Unknown e2e type: ${e2eType}`);
|
|
143
181
|
}
|
|
144
|
-
let msg = WAProto_1.proto.Message.decode((0, generics_1.unpadRandomMax16)(msgBuffer));
|
|
145
|
-
msg = ((_a = msg.deviceSentMessage) === null || _a === void 0 ? void 0 : _a.message) || msg;
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
await repository.processSenderKeyDistributionMessage({
|
|
149
|
-
authorJid: author,
|
|
150
|
-
item: msg.senderKeyDistributionMessage
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
catch (err) {
|
|
154
|
-
logger.error({ key: fullMessage.key, err }, 'failed to decrypt message');
|
|
155
|
-
}
|
|
156
|
-
}
|
|
182
|
+
let msg = WAProto_1.proto.Message.decode(tag === 'plaintext' ? msgBuffer : (0, generics_1.unpadRandomMax16)(msgBuffer));
|
|
183
|
+
msg = ((_a = msg === null || msg === void 0 ? void 0 : msg.deviceSentMessage) === null || _a === void 0 ? void 0 : _a.message) || msg;
|
|
184
|
+
await processSenderKeyDistribution(msg);
|
|
157
185
|
if (fullMessage.message) {
|
|
158
186
|
Object.assign(fullMessage.message, msg);
|
|
159
187
|
}
|
package/lib/Utils/generics.d.ts
CHANGED
|
@@ -4,7 +4,17 @@ import { Logger } from 'pino';
|
|
|
4
4
|
import { proto } from '../../WAProto';
|
|
5
5
|
import { BaileysEventEmitter, BaileysEventMap, BrowsersMap, WACallUpdateType, WAVersion } from '../Types';
|
|
6
6
|
import { BinaryNode } from '../WABinary';
|
|
7
|
+
/**
|
|
8
|
+
const COMPANION_PLATFORM_MAP = {
|
|
9
|
+
'Chrome': '49',
|
|
10
|
+
'Edge': '50',
|
|
11
|
+
'Firefox': '51',
|
|
12
|
+
'Opera': '53',
|
|
13
|
+
'Safari': '54'
|
|
14
|
+
}
|
|
15
|
+
*/
|
|
7
16
|
export declare const Browsers: BrowsersMap;
|
|
17
|
+
/** Other Browser Support for Paircode */
|
|
8
18
|
export declare const getPlatformId: (browser: string) => any;
|
|
9
19
|
export declare const BufferJSON: {
|
|
10
20
|
replacer: (k: any, value: any) => any;
|
|
@@ -14,6 +24,7 @@ export declare const getKeyAuthor: (key: proto.IMessageKey | undefined | null, m
|
|
|
14
24
|
export declare const writeRandomPadMax16: (msg: Uint8Array) => Buffer;
|
|
15
25
|
export declare const unpadRandomMax16: (e: Uint8Array | Buffer) => Uint8Array;
|
|
16
26
|
export declare const encodeWAMessage: (message: proto.IMessage) => Buffer;
|
|
27
|
+
export declare const encodeNewsletterMessage: (message: proto.IMessage) => Uint8Array;
|
|
17
28
|
export declare const generateRegistrationId: () => number;
|
|
18
29
|
export declare const encodeBigEndian: (e: number, t?: number) => Uint8Array;
|
|
19
30
|
export declare const toNumber: (t: Long | number | null | undefined) => number;
|
package/lib/Utils/generics.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.bytesToCrockford = exports.trimUndefined = exports.isWABusinessPlatform = exports.getCodeFromWSError = exports.getCallStatusFromNode = exports.getErrorCodeFromStreamError = exports.getStatusFromReceiptType = exports.generateMdTagPrefix = exports.fetchLatestWaWebVersion = exports.fetchLatestBaileysVersion = exports.printQRIfNecessaryListener = exports.bindWaitForConnectionUpdate = exports.bindWaitForEvent = exports.generateMessageID = exports.generateMessageIDV2 = exports.promiseTimeout = exports.delayCancellable = exports.delay = exports.debouncedTimeout = exports.unixTimestampSeconds = exports.toNumber = exports.encodeBigEndian = exports.generateRegistrationId = exports.encodeWAMessage = exports.unpadRandomMax16 = exports.writeRandomPadMax16 = exports.getKeyAuthor = exports.BufferJSON = exports.getPlatformId = exports.Browsers = void 0;
|
|
6
|
+
exports.bytesToCrockford = exports.trimUndefined = exports.isWABusinessPlatform = exports.getCodeFromWSError = exports.getCallStatusFromNode = exports.getErrorCodeFromStreamError = exports.getStatusFromReceiptType = exports.generateMdTagPrefix = exports.fetchLatestWaWebVersion = exports.fetchLatestBaileysVersion = exports.printQRIfNecessaryListener = exports.bindWaitForConnectionUpdate = exports.bindWaitForEvent = exports.generateMessageID = exports.generateMessageIDV2 = exports.promiseTimeout = exports.delayCancellable = exports.delay = exports.debouncedTimeout = exports.unixTimestampSeconds = exports.toNumber = exports.encodeBigEndian = exports.generateRegistrationId = exports.encodeNewsletterMessage = exports.encodeWAMessage = exports.unpadRandomMax16 = exports.writeRandomPadMax16 = exports.getKeyAuthor = exports.BufferJSON = exports.getPlatformId = exports.Browsers = void 0;
|
|
7
7
|
const boom_1 = require("@hapi/boom");
|
|
8
8
|
const axios_1 = __importDefault(require("axios"));
|
|
9
9
|
const crypto_1 = require("crypto");
|
|
@@ -12,6 +12,7 @@ const WAProto_1 = require("../../WAProto");
|
|
|
12
12
|
const baileys_version_json_1 = require("../Defaults/baileys-version.json");
|
|
13
13
|
const Types_1 = require("../Types");
|
|
14
14
|
const WABinary_1 = require("../WABinary");
|
|
15
|
+
/** Added Extra Browsers or Platforms*/
|
|
15
16
|
const PLATFORM_MAP = {
|
|
16
17
|
'aix': 'AIX',
|
|
17
18
|
'darwin': 'Mac OS',
|
|
@@ -21,6 +22,15 @@ const PLATFORM_MAP = {
|
|
|
21
22
|
'openbsd': 'OpenBSD',
|
|
22
23
|
'sunos': 'Solaris'
|
|
23
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
const COMPANION_PLATFORM_MAP = {
|
|
27
|
+
'Chrome': '49',
|
|
28
|
+
'Edge': '50',
|
|
29
|
+
'Firefox': '51',
|
|
30
|
+
'Opera': '53',
|
|
31
|
+
'Safari': '54'
|
|
32
|
+
}
|
|
33
|
+
*/
|
|
24
34
|
exports.Browsers = {
|
|
25
35
|
ubuntu: (browser) => ['Ubuntu', browser, '22.04.4'],
|
|
26
36
|
macOS: (browser) => ['Mac OS', browser, '14.4.1'],
|
|
@@ -29,9 +39,10 @@ exports.Browsers = {
|
|
|
29
39
|
/** The appropriate browser based on your OS & release */
|
|
30
40
|
appropriate: (browser) => [PLATFORM_MAP[(0, os_1.platform)()] || 'Ubuntu', browser, (0, os_1.release)()]
|
|
31
41
|
};
|
|
42
|
+
/** Other Browser Support for Paircode */
|
|
32
43
|
const getPlatformId = (browser) => {
|
|
33
44
|
const platformType = WAProto_1.proto.DeviceProps.PlatformType[browser.toUpperCase()];
|
|
34
|
-
return platformType ? platformType.toString().charCodeAt(0).toString() : '
|
|
45
|
+
return platformType ? platformType.toString().charCodeAt(0).toString() : '51'; // Firefox
|
|
35
46
|
};
|
|
36
47
|
exports.getPlatformId = getPlatformId;
|
|
37
48
|
exports.BufferJSON = {
|
|
@@ -74,6 +85,8 @@ const unpadRandomMax16 = (e) => {
|
|
|
74
85
|
exports.unpadRandomMax16 = unpadRandomMax16;
|
|
75
86
|
const encodeWAMessage = (message) => ((0, exports.writeRandomPadMax16)(WAProto_1.proto.Message.encode(message).finish()));
|
|
76
87
|
exports.encodeWAMessage = encodeWAMessage;
|
|
88
|
+
const encodeNewsletterMessage = (message) => (WAProto_1.proto.Message.encode(message).finish());
|
|
89
|
+
exports.encodeNewsletterMessage = encodeNewsletterMessage;
|
|
77
90
|
const generateRegistrationId = () => {
|
|
78
91
|
return Uint16Array.from((0, crypto_1.randomBytes)(2))[0] & 16383;
|
|
79
92
|
};
|
|
@@ -155,8 +168,6 @@ async function promiseTimeout(ms, promise) {
|
|
|
155
168
|
return p;
|
|
156
169
|
}
|
|
157
170
|
exports.promiseTimeout = promiseTimeout;
|
|
158
|
-
// inspired from whatsmeow code
|
|
159
|
-
// https://github.com/tulir/whatsmeow/blob/64bc969fbe78d31ae0dd443b8d4c80a5d026d07a/send.go#L42
|
|
160
171
|
const generateMessageIDV2 = (userId) => {
|
|
161
172
|
const data = Buffer.alloc(8 + 20 + 16);
|
|
162
173
|
data.writeBigUInt64BE(BigInt(Math.floor(Date.now() / 1000)));
|
|
@@ -170,11 +181,11 @@ const generateMessageIDV2 = (userId) => {
|
|
|
170
181
|
const random = (0, crypto_1.randomBytes)(16);
|
|
171
182
|
random.copy(data, 28);
|
|
172
183
|
const hash = (0, crypto_1.createHash)('sha256').update(data).digest();
|
|
173
|
-
return '3EB0' + hash.toString('hex').toUpperCase().substring(0,
|
|
184
|
+
return '3EB0' + hash.toString('hex').toUpperCase().substring(0, 16);
|
|
174
185
|
};
|
|
175
186
|
exports.generateMessageIDV2 = generateMessageIDV2;
|
|
176
187
|
// generate a random ID to attach to a message
|
|
177
|
-
const generateMessageID = () => '3EB0' + (0, crypto_1.randomBytes)(
|
|
188
|
+
const generateMessageID = () => '3EB0' + (0, crypto_1.randomBytes)(12).toString('hex').toUpperCase();
|
|
178
189
|
exports.generateMessageID = generateMessageID;
|
|
179
190
|
function bindWaitForEvent(ev, event) {
|
|
180
191
|
return async (check, timeoutMs) => {
|
package/lib/Utils/logger.d.ts
CHANGED
|
@@ -63,6 +63,15 @@ type EncryptedStreamOptions = {
|
|
|
63
63
|
logger?: Logger;
|
|
64
64
|
opts?: AxiosRequestConfig;
|
|
65
65
|
};
|
|
66
|
+
export declare const prepareStream: (media: WAMediaUpload, mediaType: MediaType, { logger, saveOriginalFileIfRequired, opts }?: EncryptedStreamOptions) => Promise<{
|
|
67
|
+
mediaKey: undefined;
|
|
68
|
+
encWriteStream: Buffer;
|
|
69
|
+
fileLength: number;
|
|
70
|
+
fileSha256: Buffer;
|
|
71
|
+
fileEncSha256: undefined;
|
|
72
|
+
bodyPath: string | undefined;
|
|
73
|
+
didSaveToTmpPath: boolean;
|
|
74
|
+
}>;
|
|
66
75
|
export declare const encryptedStream: (media: WAMediaUpload, mediaType: MediaType, { logger, saveOriginalFileIfRequired, opts }?: EncryptedStreamOptions) => Promise<{
|
|
67
76
|
mediaKey: Buffer;
|
|
68
77
|
encWriteStream: Readable;
|
|
@@ -92,7 +101,7 @@ export declare const getWAUploadToServer: ({ customUploadHosts, fetchAgent, logg
|
|
|
92
101
|
*/
|
|
93
102
|
export declare const encryptMediaRetryRequest: (key: proto.IMessageKey, mediaKey: Buffer | Uint8Array, meId: string) => BinaryNode;
|
|
94
103
|
export declare const decodeMediaRetryNode: (node: BinaryNode) => {
|
|
95
|
-
key:
|
|
104
|
+
key: import("../Types").WAMessageKey;
|
|
96
105
|
media?: {
|
|
97
106
|
ciphertext: Uint8Array;
|
|
98
107
|
iv: Uint8Array;
|
|
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.extensionForMediaMessage = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.getHttpStream = exports.generateThumbnail = exports.getStream = exports.toBuffer = exports.toReadable = exports.getAudioWaveform = exports.getAudioDuration = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.getMediaKeys = exports.hkdfInfoKey = void 0;
|
|
29
|
+
exports.getStatusCodeForMediaRetry = exports.decryptMediaRetryData = exports.decodeMediaRetryNode = exports.encryptMediaRetryRequest = exports.getWAUploadToServer = exports.extensionForMediaMessage = exports.downloadEncryptedContent = exports.downloadContentFromMessage = exports.getUrlFromDirectPath = exports.encryptedStream = exports.prepareStream = exports.getHttpStream = exports.generateThumbnail = exports.getStream = exports.toBuffer = exports.toReadable = exports.getAudioWaveform = exports.getAudioDuration = exports.mediaMessageSHA256B64 = exports.generateProfilePicture = exports.encodeBase64EncodedStringForUpload = exports.extractImageThumb = exports.getMediaKeys = exports.hkdfInfoKey = void 0;
|
|
30
30
|
const boom_1 = require("@hapi/boom");
|
|
31
31
|
const axios_1 = __importDefault(require("axios"));
|
|
32
32
|
const child_process_1 = require("child_process");
|
|
@@ -321,6 +321,50 @@ const getHttpStream = async (url, options = {}) => {
|
|
|
321
321
|
return fetched.data;
|
|
322
322
|
};
|
|
323
323
|
exports.getHttpStream = getHttpStream;
|
|
324
|
+
const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
|
|
325
|
+
const { stream, type } = await (0, exports.getStream)(media, opts);
|
|
326
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('fetched media stream');
|
|
327
|
+
let bodyPath;
|
|
328
|
+
let didSaveToTmpPath = false;
|
|
329
|
+
try {
|
|
330
|
+
const buffer = await (0, exports.toBuffer)(stream);
|
|
331
|
+
if (type === 'file') {
|
|
332
|
+
bodyPath = media.url;
|
|
333
|
+
}
|
|
334
|
+
else if (saveOriginalFileIfRequired) {
|
|
335
|
+
bodyPath = (0, path_1.join)(getTmpFilesDirectory(), mediaType + (0, generics_1.generateMessageID)());
|
|
336
|
+
(0, fs_1.writeFileSync)(bodyPath, buffer);
|
|
337
|
+
didSaveToTmpPath = true;
|
|
338
|
+
}
|
|
339
|
+
const fileLength = buffer.length;
|
|
340
|
+
const fileSha256 = Crypto.createHash('sha256').update(buffer).digest();
|
|
341
|
+
stream === null || stream === void 0 ? void 0 : stream.destroy();
|
|
342
|
+
logger === null || logger === void 0 ? void 0 : logger.debug('prepare stream data successfully');
|
|
343
|
+
return {
|
|
344
|
+
mediaKey: undefined,
|
|
345
|
+
encWriteStream: buffer,
|
|
346
|
+
fileLength,
|
|
347
|
+
fileSha256,
|
|
348
|
+
fileEncSha256: undefined,
|
|
349
|
+
bodyPath,
|
|
350
|
+
didSaveToTmpPath
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
// destroy all streams with error
|
|
355
|
+
stream.destroy();
|
|
356
|
+
if (didSaveToTmpPath) {
|
|
357
|
+
try {
|
|
358
|
+
await fs_1.promises.unlink(bodyPath);
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
logger === null || logger === void 0 ? void 0 : logger.error({ err }, 'failed to save to tmp path');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
throw error;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
exports.prepareStream = prepareStream;
|
|
324
368
|
const encryptedStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {
|
|
325
369
|
const { stream, type } = await (0, exports.getStream)(media, opts);
|
|
326
370
|
logger === null || logger === void 0 ? void 0 : logger.debug('fetched media stream');
|
|
@@ -526,17 +570,21 @@ function extensionForMediaMessage(message) {
|
|
|
526
570
|
}
|
|
527
571
|
exports.extensionForMediaMessage = extensionForMediaMessage;
|
|
528
572
|
const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options }, refreshMediaConn) => {
|
|
529
|
-
return async (stream, { mediaType, fileEncSha256B64, timeoutMs }) => {
|
|
573
|
+
return async (stream, { mediaType, fileEncSha256B64, newsletter, timeoutMs }) => {
|
|
530
574
|
var _a, _b;
|
|
531
575
|
// send a query JSON to obtain the url & auth token to upload our media
|
|
532
576
|
let uploadInfo = await refreshMediaConn(false);
|
|
533
577
|
let urls;
|
|
534
578
|
const hosts = [...customUploadHosts, ...uploadInfo.hosts];
|
|
535
579
|
fileEncSha256B64 = (0, exports.encodeBase64EncodedStringForUpload)(fileEncSha256B64);
|
|
580
|
+
let media = Defaults_1.MEDIA_PATH_MAP[mediaType];
|
|
581
|
+
if (newsletter) {
|
|
582
|
+
media = media === null || media === void 0 ? void 0 : media.replace('/mms/', '/newsletter/newsletter-');
|
|
583
|
+
}
|
|
536
584
|
for (const { hostname } of hosts) {
|
|
537
585
|
logger.debug(`uploading to "${hostname}"`);
|
|
538
586
|
const auth = encodeURIComponent(uploadInfo.auth); // the auth token
|
|
539
|
-
const url = `https://${hostname}${
|
|
587
|
+
const url = `https://${hostname}${media}/${fileEncSha256B64}?auth=${auth}&token=${fileEncSha256B64}`;
|
|
540
588
|
let result;
|
|
541
589
|
try {
|
|
542
590
|
const body = await axios_1.default.post(url, stream, {
|
|
@@ -556,7 +604,8 @@ const getWAUploadToServer = ({ customUploadHosts, fetchAgent, logger, options },
|
|
|
556
604
|
if ((result === null || result === void 0 ? void 0 : result.url) || (result === null || result === void 0 ? void 0 : result.directPath)) {
|
|
557
605
|
urls = {
|
|
558
606
|
mediaUrl: result.url,
|
|
559
|
-
directPath: result.direct_path
|
|
607
|
+
directPath: result.direct_path,
|
|
608
|
+
handle: result.handle
|
|
560
609
|
};
|
|
561
610
|
break;
|
|
562
611
|
}
|
package/lib/Utils/messages.js
CHANGED
|
@@ -111,14 +111,14 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
111
111
|
const requiresWaveformProcessing = mediaType === 'audio' && uploadData.ptt === true;
|
|
112
112
|
const requiresAudioBackground = options.backgroundColor && mediaType === 'audio' && uploadData.ptt === true;
|
|
113
113
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation;
|
|
114
|
-
const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath } = await (
|
|
114
|
+
const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath, } = await (options.newsletter ? messages_media_1.prepareStream : messages_media_1.encryptedStream)(uploadData.media, options.mediaTypeOverride || mediaType, {
|
|
115
115
|
logger,
|
|
116
116
|
saveOriginalFileIfRequired: requiresOriginalForSomeProcessing,
|
|
117
117
|
opts: options.options
|
|
118
118
|
});
|
|
119
119
|
// url safe Base64 encode the SHA256 hash of the body
|
|
120
|
-
const fileEncSha256B64 = fileEncSha256.toString('base64');
|
|
121
|
-
const [{ mediaUrl, directPath }] = await Promise.all([
|
|
120
|
+
const fileEncSha256B64 = (options.newsletter ? fileSha256 : fileEncSha256 !== null && fileEncSha256 !== void 0 ? fileEncSha256 : fileSha256).toString('base64');
|
|
121
|
+
const [{ mediaUrl, directPath, handle }] = await Promise.all([
|
|
122
122
|
(async () => {
|
|
123
123
|
const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs });
|
|
124
124
|
logger === null || logger === void 0 ? void 0 : logger.debug({ mediaType, cacheableKey }, 'uploaded media');
|
|
@@ -159,7 +159,9 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
159
159
|
})(),
|
|
160
160
|
])
|
|
161
161
|
.finally(async () => {
|
|
162
|
-
|
|
162
|
+
if (!Buffer.isBuffer(encWriteStream)) {
|
|
163
|
+
encWriteStream.destroy();
|
|
164
|
+
}
|
|
163
165
|
// remove tmp files
|
|
164
166
|
if (didSaveToTmpPath && bodyPath) {
|
|
165
167
|
await fs_1.promises.unlink(bodyPath);
|
|
@@ -168,13 +170,13 @@ const prepareWAMessageMedia = async (message, options) => {
|
|
|
168
170
|
});
|
|
169
171
|
const obj = Types_1.WAProto.Message.fromObject({
|
|
170
172
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({
|
|
171
|
-
url: mediaUrl,
|
|
173
|
+
url: handle ? undefined : mediaUrl,
|
|
172
174
|
directPath,
|
|
173
|
-
mediaKey,
|
|
174
|
-
fileEncSha256,
|
|
175
|
+
mediaKey: mediaKey,
|
|
176
|
+
fileEncSha256: fileEncSha256,
|
|
175
177
|
fileSha256,
|
|
176
178
|
fileLength,
|
|
177
|
-
mediaKeyTimestamp: (0, generics_1.unixTimestampSeconds)(),
|
|
179
|
+
mediaKeyTimestamp: handle ? undefined : (0, generics_1.unixTimestampSeconds)(),
|
|
178
180
|
...uploadData,
|
|
179
181
|
media: undefined
|
|
180
182
|
})
|
|
@@ -308,6 +310,22 @@ const generateWAMessageContent = async (message, options) => {
|
|
|
308
310
|
message.disappearingMessagesInChat;
|
|
309
311
|
m = (0, exports.prepareDisappearingMessageSettingContent)(exp);
|
|
310
312
|
}
|
|
313
|
+
else if ('pin' in message) {
|
|
314
|
+
m.pinInChatMessage = {};
|
|
315
|
+
m.messageContextInfo = {};
|
|
316
|
+
m.pinInChatMessage.key = message.pin;
|
|
317
|
+
m.pinInChatMessage.type = 1;
|
|
318
|
+
m.pinInChatMessage.senderTimestampMs = Date.now();
|
|
319
|
+
m.messageContextInfo.messageAddOnDurationInSecs = message.time || 86400;
|
|
320
|
+
}
|
|
321
|
+
else if ('unpin' in message) {
|
|
322
|
+
m.pinInChatMessage = {};
|
|
323
|
+
m.messageContextInfo = {};
|
|
324
|
+
m.pinInChatMessage.key = message.unpin;
|
|
325
|
+
m.pinInChatMessage.type = 2;
|
|
326
|
+
m.pinInChatMessage.senderTimestampMs = Date.now();
|
|
327
|
+
m.messageContextInfo.messageAddOnDurationInSecs = 0;
|
|
328
|
+
}
|
|
311
329
|
else if ('buttonReply' in message) {
|
|
312
330
|
switch (message.type) {
|
|
313
331
|
case 'template':
|
|
@@ -464,7 +482,8 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
464
482
|
const key = (0, exports.getContentType)(innerMessage);
|
|
465
483
|
const timestamp = (0, generics_1.unixTimestampSeconds)(options.timestamp);
|
|
466
484
|
const { quoted, userJid } = options;
|
|
467
|
-
|
|
485
|
+
// only set quoted if isn't a newsletter message
|
|
486
|
+
if (quoted && !(0, WABinary_1.isJidNewsletter)(jid)) {
|
|
468
487
|
const participant = quoted.key.fromMe ? userJid : (quoted.participant || quoted.key.participant || quoted.key.remoteJid);
|
|
469
488
|
let quotedMsg = (0, exports.normalizeMessageContent)(quoted.message);
|
|
470
489
|
const msgType = (0, exports.getContentType)(quotedMsg);
|
|
@@ -491,7 +510,9 @@ const generateWAMessageFromContent = (jid, message, options) => {
|
|
|
491
510
|
// and it's not a protocol message -- delete, toggle disappear message
|
|
492
511
|
key !== 'protocolMessage' &&
|
|
493
512
|
// already not converted to disappearing message
|
|
494
|
-
key !== 'ephemeralMessage'
|
|
513
|
+
key !== 'ephemeralMessage' &&
|
|
514
|
+
// newsletter not accept disappearing messages
|
|
515
|
+
!(0, WABinary_1.isJidNewsletter)(jid)) {
|
|
495
516
|
innerMessage[key].contextInfo = {
|
|
496
517
|
...(innerMessage[key].contextInfo || {}),
|
|
497
518
|
expiration: options.ephemeralExpiration || Defaults_1.WA_DEFAULT_EPHEMERAL,
|
|
@@ -518,7 +539,7 @@ const generateWAMessage = async (jid, content, options) => {
|
|
|
518
539
|
var _a;
|
|
519
540
|
// ensure msg ID is with every log
|
|
520
541
|
options.logger = (_a = options === null || options === void 0 ? void 0 : options.logger) === null || _a === void 0 ? void 0 : _a.child({ msgId: options.messageId });
|
|
521
|
-
return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, options), options);
|
|
542
|
+
return (0, exports.generateWAMessageFromContent)(jid, await (0, exports.generateWAMessageContent)(content, { newsletter: (0, WABinary_1.isJidNewsletter)(jid), ...options }), options);
|
|
522
543
|
};
|
|
523
544
|
exports.generateWAMessage = generateWAMessage;
|
|
524
545
|
/** Get the key to access the true type of content */
|
package/lib/Utils/signal.js
CHANGED
|
@@ -67,11 +67,6 @@ const parseAndInjectE2ESessions = async (node, repository) => {
|
|
|
67
67
|
for (const node of nodes) {
|
|
68
68
|
(0, WABinary_1.assertNodeErrorFree)(node);
|
|
69
69
|
}
|
|
70
|
-
// Most of the work in repository.injectE2ESession is CPU intensive, not IO
|
|
71
|
-
// So Promise.all doesn't really help here,
|
|
72
|
-
// but blocks even loop if we're using it inside keys.transaction, and it makes it "sync" actually
|
|
73
|
-
// This way we chunk it in smaller parts and between those parts we can yield to the event loop
|
|
74
|
-
// It's rare case when you need to E2E sessions for so many users, but it's possible
|
|
75
70
|
const chunkSize = 100;
|
|
76
71
|
const chunks = (0, lodash_1.chunk)(nodes, chunkSize);
|
|
77
72
|
for (const nodesChunk of chunks) {
|
package/lib/WABinary/encode.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import type { BinaryNode, BinaryNodeCodingOptions } from './types';
|
|
3
|
-
export declare const encodeBinaryNode: (
|
|
2
|
+
export declare const encodeBinaryNode: ({ tag, attrs, content }: BinaryNode, opts?: Pick<BinaryNodeCodingOptions, 'TAGS' | 'TOKEN_MAP'>, buffer?: number[]) => number[];
|