@boruto_vk7/baileys 1.0.0 → 1.0.1
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 +3 -3
- package/README.md +7 -1383
- package/lib/Defaults/index.js +2 -2
- package/lib/Defaults/index.js.bak +148 -0
- package/lib/Socket/chats.js +6 -6
- package/lib/Socket/groups.js.bak +329 -0
- package/lib/Socket/messages-recv.js +1 -1
- package/lib/Socket/messages-send.js +13 -13
- package/lib/Socket/newsletter.js +1 -1
- package/lib/Store/make-in-memory-store.js +2 -2
- package/lib/Types/Message.js +1 -1
- package/lib/Utils/messages-media.js +2 -2
- package/lib/Utils/messages.js +38 -38
- package/lib/Utils/messages.js.bak +1879 -0
- package/lib/Utils/rich-message-utils.js +6 -6
- package/lib/Utils/rich-message-utils.js.bak +387 -0
- package/lib/Utils/use-single-file-auth-state.js +1 -1
- package/lib/WABinary/generic-utils.js +1 -1
- package/lib/index.js.bak +13 -0
- package/package.json +2 -2
package/lib/Defaults/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export const CALL_VIDEO_PREFIX = 'https://call.whatsapp.com/video/';
|
|
|
10
10
|
export const CALL_AUDIO_PREFIX = 'https://call.whatsapp.com/voice/';
|
|
11
11
|
export const DEF_CALLBACK_PREFIX = 'CB:';
|
|
12
12
|
export const DEF_TAG_PREFIX = 'TAG:';
|
|
13
|
-
export const DONATE_URL = 'https://okarun-api.com.br/status'; //
|
|
13
|
+
export const DONATE_URL = 'https://okarun-api.com.br/status'; // Boruto@Note 02-02-26 --- Apologies if this feels cheeky, just a fallback
|
|
14
14
|
export const LIBRARY_NAME = 'boruto_vk7/baileys';
|
|
15
15
|
export const PHONE_CONNECTION_CB = 'CB:Pong';
|
|
16
16
|
export const WA_ADV_ACCOUNT_SIG_PREFIX = Buffer.from([6, 0]);
|
|
@@ -93,7 +93,7 @@ export const MEDIA_PATH_MAP = {
|
|
|
93
93
|
'md-msg-hist': '/mms/md-app-state',
|
|
94
94
|
'biz-cover-photo': '/pps/biz-cover-photo'
|
|
95
95
|
};
|
|
96
|
-
//
|
|
96
|
+
// Boruto@Changes 06-02-26 --- Add newsletter media path for "/m1/" instead of "/o1/" (≧▽≦)
|
|
97
97
|
export const NEWSLETTER_MEDIA_PATH_MAP = {
|
|
98
98
|
image: '/newsletter/newsletter-image',
|
|
99
99
|
video: '/newsletter/newsletter-video',
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { proto } from '../../WAProto/index.js';
|
|
2
|
+
import { makeLibSignalRepository } from '../Signal/libsignal.js';
|
|
3
|
+
import { Browsers } from '../Utils/browser-utils.js';
|
|
4
|
+
import logger from '../Utils/logger.js';
|
|
5
|
+
const version = [2, 3000, 1037013887];
|
|
6
|
+
export const UNAUTHORIZED_CODES = [401, 403, 419];
|
|
7
|
+
export const BIZ_BOT_SUPPORT_PAYLOAD = '{"version":1,"is_ai_message":true,"should_upload_client_logs":false,"should_show_system_message":false,"ticket_id":"7004947587700716","citation_items":[],"ticket_locale":"us"}';
|
|
8
|
+
export const DEFAULT_ORIGIN = 'https://web.whatsapp.com';
|
|
9
|
+
export const CALL_VIDEO_PREFIX = 'https://call.whatsapp.com/video/';
|
|
10
|
+
export const CALL_AUDIO_PREFIX = 'https://call.whatsapp.com/voice/';
|
|
11
|
+
export const DEF_CALLBACK_PREFIX = 'CB:';
|
|
12
|
+
export const DEF_TAG_PREFIX = 'TAG:';
|
|
13
|
+
export const DONATE_URL = 'https://okarun-api.com.br/status'; // Boruto@Note 02-02-26 --- Apologies if this feels cheeky, just a fallback
|
|
14
|
+
export const LIBRARY_NAME = 'itsBorutoaa/baileys';
|
|
15
|
+
export const PHONE_CONNECTION_CB = 'CB:Pong';
|
|
16
|
+
export const WA_ADV_ACCOUNT_SIG_PREFIX = Buffer.from([6, 0]);
|
|
17
|
+
export const WA_ADV_DEVICE_SIG_PREFIX = Buffer.from([6, 1]);
|
|
18
|
+
export const WA_ADV_HOSTED_ACCOUNT_SIG_PREFIX = Buffer.from([6, 5]);
|
|
19
|
+
export const WA_ADV_HOSTED_DEVICE_SIG_PREFIX = Buffer.from([6, 6]);
|
|
20
|
+
export const WA_DEFAULT_EPHEMERAL = 7 * 24 * 60 * 60;
|
|
21
|
+
/** Status messages older than 24 hours are considered expired */
|
|
22
|
+
export const STATUS_EXPIRY_SECONDS = 24 * 60 * 60;
|
|
23
|
+
/** WA Web enforces a 14-day maximum age for placeholder resend requests */
|
|
24
|
+
export const PLACEHOLDER_MAX_AGE_SECONDS = 14 * 24 * 60 * 60;
|
|
25
|
+
export const NOISE_MODE = 'Noise_XX_25519_AESGCM_SHA256\0\0\0\0';
|
|
26
|
+
export const DICT_VERSION = 3;
|
|
27
|
+
export const KEY_BUNDLE_TYPE = Buffer.from([5]);
|
|
28
|
+
export const NOISE_WA_HEADER = Buffer.from([87, 65, 6, DICT_VERSION]); // last is "DICT_VERSION"
|
|
29
|
+
export const LEXER_REGEX = /(\/\/.*|\/\*[\s\S]*?\*\/|#.*)|("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`[\s\S]*?`)|(\b[a-zA-Z_]\w*\b)(?=\s*\()|(\b[a-zA-Z_]\w*\b)|(\b\d+(?:\.\d+)?\b)|(\s+|[^\w\s]+)/g;
|
|
30
|
+
/** from: https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url */
|
|
31
|
+
export const URL_REGEX = /https:\/\/(?![^:@\/\s]+:[^:@\/\s]+@)[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(:\d+)?(\/[^\s]*)?/g;
|
|
32
|
+
export const WA_CERT_DETAILS = {
|
|
33
|
+
SERIAL: 0,
|
|
34
|
+
ISSUER: 'WhatsAppLongTerm1',
|
|
35
|
+
PUBLIC_KEY: Buffer.from('142375574d0a587166aae71ebe516437c4a28b73e3695c6ce1f7f9545da8ee6b', 'hex')
|
|
36
|
+
};
|
|
37
|
+
export const PROCESSABLE_HISTORY_TYPES = [
|
|
38
|
+
proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP,
|
|
39
|
+
proto.HistorySync.HistorySyncType.PUSH_NAME,
|
|
40
|
+
proto.HistorySync.HistorySyncType.RECENT,
|
|
41
|
+
proto.HistorySync.HistorySyncType.FULL,
|
|
42
|
+
proto.HistorySync.HistorySyncType.ON_DEMAND,
|
|
43
|
+
proto.HistorySync.HistorySyncType.NON_BLOCKING_DATA,
|
|
44
|
+
proto.HistorySync.HistorySyncType.INITIAL_STATUS_V3
|
|
45
|
+
];
|
|
46
|
+
export const DEFAULT_CONNECTION_CONFIG = {
|
|
47
|
+
version: version,
|
|
48
|
+
browser: Browsers.macOS('Chrome'),
|
|
49
|
+
waWebSocketUrl: 'wss://web.whatsapp.com/ws/chat',
|
|
50
|
+
connectTimeoutMs: 20000,
|
|
51
|
+
keepAliveIntervalMs: 30000,
|
|
52
|
+
logger: logger.child({ class: 'baileys' }),
|
|
53
|
+
emitOwnEvents: true,
|
|
54
|
+
defaultQueryTimeoutMs: 60000,
|
|
55
|
+
customUploadHosts: [],
|
|
56
|
+
retryRequestDelayMs: 250,
|
|
57
|
+
maxMsgRetryCount: 3,
|
|
58
|
+
fireInitQueries: true,
|
|
59
|
+
auth: undefined,
|
|
60
|
+
markOnlineOnConnect: true,
|
|
61
|
+
syncFullHistory: true,
|
|
62
|
+
patchMessageBeforeSending: msg => msg,
|
|
63
|
+
shouldSyncHistoryMessage: ({ syncType }) => {
|
|
64
|
+
return syncType !== proto.HistorySync.HistorySyncType.FULL;
|
|
65
|
+
},
|
|
66
|
+
shouldIgnoreJid: () => false,
|
|
67
|
+
linkPreviewImageThumbnailWidth: 192,
|
|
68
|
+
transactionOpts: { maxCommitRetries: 10, delayBetweenTriesMs: 3000 },
|
|
69
|
+
generateHighQualityLinkPreview: false,
|
|
70
|
+
enableAutoSessionRecreation: true,
|
|
71
|
+
enableRecentMessageCache: true,
|
|
72
|
+
options: {},
|
|
73
|
+
appStateMacVerification: {
|
|
74
|
+
patch: false,
|
|
75
|
+
snapshot: false
|
|
76
|
+
},
|
|
77
|
+
countryCode: 'US',
|
|
78
|
+
getMessage: async () => undefined,
|
|
79
|
+
cachedGroupMetadata: async () => undefined,
|
|
80
|
+
makeSignalRepository: makeLibSignalRepository
|
|
81
|
+
};
|
|
82
|
+
export const MEDIA_PATH_MAP = {
|
|
83
|
+
image: '/mms/image',
|
|
84
|
+
video: '/mms/video',
|
|
85
|
+
document: '/mms/document',
|
|
86
|
+
audio: '/mms/audio',
|
|
87
|
+
sticker: '/mms/image',
|
|
88
|
+
'sticker-pack': '/mms/sticker-pack',
|
|
89
|
+
'thumbnail-sticker-pack': '/mms/thumbnail-sticker-pack',
|
|
90
|
+
'thumbnail-link': '/mms/thumbnail-link',
|
|
91
|
+
'product-catalog-image': '/product/image',
|
|
92
|
+
'md-app-state': '',
|
|
93
|
+
'md-msg-hist': '/mms/md-app-state',
|
|
94
|
+
'biz-cover-photo': '/pps/biz-cover-photo'
|
|
95
|
+
};
|
|
96
|
+
// Boruto@Changes 06-02-26 --- Add newsletter media path for "/m1/" instead of "/o1/" (≧▽≦)
|
|
97
|
+
export const NEWSLETTER_MEDIA_PATH_MAP = {
|
|
98
|
+
image: '/newsletter/newsletter-image',
|
|
99
|
+
video: '/newsletter/newsletter-video',
|
|
100
|
+
document: '/newsletter/newsletter-document',
|
|
101
|
+
audio: '/newsletter/newsletter-audio',
|
|
102
|
+
sticker: '/newsletter/newsletter-image',
|
|
103
|
+
'thumbnail-link': '/newsletter/newsletter-thumbnail-link'
|
|
104
|
+
};
|
|
105
|
+
export const MEDIA_HKDF_KEY_MAPPING = {
|
|
106
|
+
audio: 'Audio',
|
|
107
|
+
document: 'Document',
|
|
108
|
+
gif: 'Video',
|
|
109
|
+
image: 'Image',
|
|
110
|
+
ppic: '',
|
|
111
|
+
product: 'Image',
|
|
112
|
+
ptt: 'Audio',
|
|
113
|
+
'sticker-pack': 'Sticker Pack',
|
|
114
|
+
'thumbnail-sticker-pack': 'Sticker Pack Thumbnail',
|
|
115
|
+
sticker: 'Image',
|
|
116
|
+
video: 'Video',
|
|
117
|
+
'thumbnail-document': 'Document Thumbnail',
|
|
118
|
+
'thumbnail-image': 'Image Thumbnail',
|
|
119
|
+
'thumbnail-video': 'Video Thumbnail',
|
|
120
|
+
'thumbnail-link': 'Link Thumbnail',
|
|
121
|
+
'md-msg-hist': 'History',
|
|
122
|
+
'md-app-state': 'App State',
|
|
123
|
+
'product-catalog-image': '',
|
|
124
|
+
'payment-bg-image': 'Payment Background',
|
|
125
|
+
ptv: 'Video',
|
|
126
|
+
'biz-cover-photo': 'Image'
|
|
127
|
+
};
|
|
128
|
+
export const MEDIA_KEYS = Object.keys(MEDIA_PATH_MAP);
|
|
129
|
+
export const MIN_PREKEY_COUNT = 5;
|
|
130
|
+
export const INITIAL_PREKEY_COUNT = 812;
|
|
131
|
+
export const UPLOAD_TIMEOUT = 30000; // 30 seconds
|
|
132
|
+
export const MIN_UPLOAD_INTERVAL = 5000; // 5 seconds minimum between uploads
|
|
133
|
+
export const DEFAULT_CACHE_TTLS = {
|
|
134
|
+
SIGNAL_STORE: 5 * 60, // 5 minutes
|
|
135
|
+
MSG_RETRY: 60 * 60, // 1 hour
|
|
136
|
+
CALL_OFFER: 5 * 60, // 5 minutes
|
|
137
|
+
USER_DEVICES: 5 * 60 // 5 minutes
|
|
138
|
+
};
|
|
139
|
+
export const TimeMs = {
|
|
140
|
+
Minute: 60 * 1000,
|
|
141
|
+
Hour: 60 * 60 * 1000,
|
|
142
|
+
Day: 24 * 60 * 60 * 1000,
|
|
143
|
+
Week: 7 * 24 * 60 * 60 * 1000
|
|
144
|
+
};
|
|
145
|
+
export const BOT_RENDERING_CONFIG_METADATA = {
|
|
146
|
+
bloksVersioningId: '0903aa5f7f47de66789d5f4c86d3bd6e05e4bc3ff85e454a9f907d5ed7fef97c',
|
|
147
|
+
pixelDensity: 2.75
|
|
148
|
+
};
|
package/lib/Socket/chats.js
CHANGED
|
@@ -12,7 +12,7 @@ import { getBinaryNodeChild, getBinaryNodeChildren, isLidUser, isPnUser, jidDeco
|
|
|
12
12
|
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
13
13
|
import { makeSocket } from './socket.js';
|
|
14
14
|
const MAX_SYNC_ATTEMPTS = 2;
|
|
15
|
-
//
|
|
15
|
+
// Boruto@Note 08-02-26 --- I know it's not efficient for RSS ಥ‿ಥ
|
|
16
16
|
const USER_ID_CACHE = new Map();
|
|
17
17
|
export const makeChatsSocket = (config) => {
|
|
18
18
|
const { logger, markOnlineOnConnect, fireInitQueries, appStateMacVerification, shouldIgnoreJid, shouldSyncHistoryMessage, getMessage } = config;
|
|
@@ -174,7 +174,7 @@ export const makeChatsSocket = (config) => {
|
|
|
174
174
|
return result.list;
|
|
175
175
|
}
|
|
176
176
|
};
|
|
177
|
-
//
|
|
177
|
+
// Boruto@Note 06-02-26 --- Quick helper only. This function exists solely for faster lookup with caching.
|
|
178
178
|
const findUserId = async (pnLid) => {
|
|
179
179
|
const cachedId = USER_ID_CACHE.get(pnLid);
|
|
180
180
|
if (cachedId) {
|
|
@@ -186,7 +186,7 @@ export const makeChatsSocket = (config) => {
|
|
|
186
186
|
userId.lid = (await signalRepository.lidMapping.getLIDsForPNs([pnLid]))?.[0]?.lid;
|
|
187
187
|
if (!userId.lid) {
|
|
188
188
|
userId.lid = 'id-not-found';
|
|
189
|
-
return userId; //
|
|
189
|
+
return userId; // Boruto@Note 06-02-26 --- Early return to skip caching for non-existent ID
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
else if (isLidUser(pnLid)) {
|
|
@@ -194,7 +194,7 @@ export const makeChatsSocket = (config) => {
|
|
|
194
194
|
userId.phoneNumber = (await signalRepository.lidMapping.getPNsForLIDs([pnLid]))?.[0]?.pn;
|
|
195
195
|
if (!userId.phoneNumber) {
|
|
196
196
|
userId.phoneNumber = 'id-not-found';
|
|
197
|
-
return userId; //
|
|
197
|
+
return userId; // Boruto@Note 06-02-26 --- Early return to skip caching for non-existent ID
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
200
|
else {
|
|
@@ -202,7 +202,7 @@ export const makeChatsSocket = (config) => {
|
|
|
202
202
|
}
|
|
203
203
|
userId.phoneNumber = jidNormalizedUser(userId.phoneNumber);
|
|
204
204
|
userId.lid = jidNormalizedUser(userId.lid);
|
|
205
|
-
//
|
|
205
|
+
// Boruto@Note 06-02-26 --- I know... it's dirty (╯︵╰,)
|
|
206
206
|
USER_ID_CACHE.set(userId.phoneNumber, userId);
|
|
207
207
|
USER_ID_CACHE.set(userId.lid, userId);
|
|
208
208
|
return userId;
|
|
@@ -507,7 +507,7 @@ export const makeChatsSocket = (config) => {
|
|
|
507
507
|
* type = "image for the high res picture"
|
|
508
508
|
*/
|
|
509
509
|
const profilePictureUrl = async (jid, type = 'image', timeoutMs) => {
|
|
510
|
-
//
|
|
510
|
+
// Boruto@Changes 06-02-26 --- Refactor profilePictureUrl() to use tctoken and adjust error handling
|
|
511
511
|
jid = jidNormalizedUser(jid);
|
|
512
512
|
const baseContent = {
|
|
513
513
|
tag: 'picture',
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { proto } from '../../WAProto/index.js';
|
|
2
|
+
import { WAMessageAddressingMode, WAMessageStubType } from '../Types/index.js';
|
|
3
|
+
import { generateMessageIDV2, unixTimestampSeconds } from '../Utils/index.js';
|
|
4
|
+
import { getBinaryNodeChild, getBinaryNodeChildren, getBinaryNodeChildString, isLidUser, isPnUser, jidEncode, jidNormalizedUser } from '../WABinary/index.js';
|
|
5
|
+
import { makeChatsSocket } from './chats.js';
|
|
6
|
+
export const makeGroupsSocket = (config) => {
|
|
7
|
+
const sock = makeChatsSocket(config);
|
|
8
|
+
const { authState, ev, query, upsertMessage } = sock;
|
|
9
|
+
const groupQuery = async (jid, type, content) => query({
|
|
10
|
+
tag: 'iq',
|
|
11
|
+
attrs: {
|
|
12
|
+
type,
|
|
13
|
+
xmlns: 'w:g2',
|
|
14
|
+
to: jid
|
|
15
|
+
},
|
|
16
|
+
content
|
|
17
|
+
});
|
|
18
|
+
const groupMetadata = async (jid) => {
|
|
19
|
+
const result = await groupQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }]);
|
|
20
|
+
return extractGroupMetadata(result);
|
|
21
|
+
};
|
|
22
|
+
const groupFetchAllParticipating = async () => {
|
|
23
|
+
const result = await query({
|
|
24
|
+
tag: 'iq',
|
|
25
|
+
attrs: {
|
|
26
|
+
to: '@g.us',
|
|
27
|
+
xmlns: 'w:g2',
|
|
28
|
+
type: 'get'
|
|
29
|
+
},
|
|
30
|
+
content: [
|
|
31
|
+
{
|
|
32
|
+
tag: 'participating',
|
|
33
|
+
attrs: {},
|
|
34
|
+
content: [
|
|
35
|
+
{ tag: 'participants', attrs: {} },
|
|
36
|
+
{ tag: 'description', attrs: {} }
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
});
|
|
41
|
+
const data = Object.create(null);
|
|
42
|
+
const groupsChild = getBinaryNodeChild(result, 'groups');
|
|
43
|
+
if (groupsChild) {
|
|
44
|
+
const groups = getBinaryNodeChildren(groupsChild, 'group');
|
|
45
|
+
for (const groupNode of groups) {
|
|
46
|
+
const meta = extractGroupMetadata({
|
|
47
|
+
tag: 'result',
|
|
48
|
+
attrs: {},
|
|
49
|
+
content: [groupNode]
|
|
50
|
+
});
|
|
51
|
+
data[meta.id] = meta;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// TODO: properly parse LID / PN DATA
|
|
55
|
+
sock.ev.emit('groups.update', Object.values(data));
|
|
56
|
+
return data;
|
|
57
|
+
};
|
|
58
|
+
sock.ws.on('CB:ib,,dirty', async (node) => {
|
|
59
|
+
const { attrs } = getBinaryNodeChild(node, 'dirty');
|
|
60
|
+
if (attrs.type !== 'groups') {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
await groupFetchAllParticipating();
|
|
64
|
+
await sock.cleanDirtyBits('groups');
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
...sock,
|
|
68
|
+
extractGroupMetadata,
|
|
69
|
+
groupMetadata,
|
|
70
|
+
groupCreate: async (subject, participants) => {
|
|
71
|
+
const key = generateMessageIDV2();
|
|
72
|
+
const result = await groupQuery('@g.us', 'set', [
|
|
73
|
+
{
|
|
74
|
+
tag: 'create',
|
|
75
|
+
attrs: {
|
|
76
|
+
subject,
|
|
77
|
+
key
|
|
78
|
+
},
|
|
79
|
+
content: participants.map(jid => ({
|
|
80
|
+
tag: 'participant',
|
|
81
|
+
attrs: { jid }
|
|
82
|
+
}))
|
|
83
|
+
}
|
|
84
|
+
]);
|
|
85
|
+
return extractGroupMetadata(result);
|
|
86
|
+
},
|
|
87
|
+
groupLeave: async (id) => {
|
|
88
|
+
await groupQuery('@g.us', 'set', [
|
|
89
|
+
{
|
|
90
|
+
tag: 'leave',
|
|
91
|
+
attrs: {},
|
|
92
|
+
content: [{ tag: 'group', attrs: { id } }]
|
|
93
|
+
}
|
|
94
|
+
]);
|
|
95
|
+
},
|
|
96
|
+
groupUpdateSubject: async (jid, subject) => {
|
|
97
|
+
await groupQuery(jid, 'set', [
|
|
98
|
+
{
|
|
99
|
+
tag: 'subject',
|
|
100
|
+
attrs: {},
|
|
101
|
+
content: Buffer.from(subject, 'utf-8')
|
|
102
|
+
}
|
|
103
|
+
]);
|
|
104
|
+
},
|
|
105
|
+
groupRequestParticipantsList: async (jid) => {
|
|
106
|
+
const result = await groupQuery(jid, 'get', [
|
|
107
|
+
{
|
|
108
|
+
tag: 'membership_approval_requests',
|
|
109
|
+
attrs: {}
|
|
110
|
+
}
|
|
111
|
+
]);
|
|
112
|
+
const node = getBinaryNodeChild(result, 'membership_approval_requests');
|
|
113
|
+
const participants = getBinaryNodeChildren(node, 'membership_approval_request');
|
|
114
|
+
return participants.map(v => v.attrs);
|
|
115
|
+
},
|
|
116
|
+
groupRequestParticipantsUpdate: async (jid, participants, action) => {
|
|
117
|
+
const result = await groupQuery(jid, 'set', [
|
|
118
|
+
{
|
|
119
|
+
tag: 'membership_requests_action',
|
|
120
|
+
attrs: {},
|
|
121
|
+
content: [
|
|
122
|
+
{
|
|
123
|
+
tag: action,
|
|
124
|
+
attrs: {},
|
|
125
|
+
content: participants.map(jid => ({
|
|
126
|
+
tag: 'participant',
|
|
127
|
+
attrs: { jid }
|
|
128
|
+
}))
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
]);
|
|
133
|
+
const node = getBinaryNodeChild(result, 'membership_requests_action');
|
|
134
|
+
const nodeAction = getBinaryNodeChild(node, action);
|
|
135
|
+
const participantsAffected = getBinaryNodeChildren(nodeAction, 'participant');
|
|
136
|
+
return participantsAffected.map(p => {
|
|
137
|
+
return { status: p.attrs.error || '200', jid: p.attrs.jid };
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
groupParticipantsUpdate: async (jid, participants, action) => {
|
|
141
|
+
const result = await groupQuery(jid, 'set', [
|
|
142
|
+
{
|
|
143
|
+
tag: action,
|
|
144
|
+
attrs: {},
|
|
145
|
+
content: participants.map(jid => ({
|
|
146
|
+
tag: 'participant',
|
|
147
|
+
attrs: { jid }
|
|
148
|
+
}))
|
|
149
|
+
}
|
|
150
|
+
]);
|
|
151
|
+
const node = getBinaryNodeChild(result, action);
|
|
152
|
+
const participantsAffected = getBinaryNodeChildren(node, 'participant');
|
|
153
|
+
return participantsAffected.map(p => {
|
|
154
|
+
return { status: p.attrs.error || '200', jid: p.attrs.jid, content: p };
|
|
155
|
+
});
|
|
156
|
+
},
|
|
157
|
+
groupUpdateDescription: async (jid, description) => {
|
|
158
|
+
const metadata = await groupMetadata(jid);
|
|
159
|
+
const prev = metadata.descId ?? null;
|
|
160
|
+
await groupQuery(jid, 'set', [
|
|
161
|
+
{
|
|
162
|
+
tag: 'description',
|
|
163
|
+
attrs: {
|
|
164
|
+
...(description ? { id: generateMessageIDV2() } : { delete: 'true' }),
|
|
165
|
+
...(prev ? { prev } : {})
|
|
166
|
+
},
|
|
167
|
+
content: description ? [{ tag: 'body', attrs: {}, content: Buffer.from(description, 'utf-8') }] : undefined
|
|
168
|
+
}
|
|
169
|
+
]);
|
|
170
|
+
},
|
|
171
|
+
groupInviteCode: async (jid) => {
|
|
172
|
+
const result = await groupQuery(jid, 'get', [{ tag: 'invite', attrs: {} }]);
|
|
173
|
+
const inviteNode = getBinaryNodeChild(result, 'invite');
|
|
174
|
+
return inviteNode?.attrs.code;
|
|
175
|
+
},
|
|
176
|
+
groupRevokeInvite: async (jid) => {
|
|
177
|
+
const result = await groupQuery(jid, 'set', [{ tag: 'invite', attrs: {} }]);
|
|
178
|
+
const inviteNode = getBinaryNodeChild(result, 'invite');
|
|
179
|
+
return inviteNode?.attrs.code;
|
|
180
|
+
},
|
|
181
|
+
groupAcceptInvite: async (code) => {
|
|
182
|
+
const results = await groupQuery('@g.us', 'set', [{ tag: 'invite', attrs: { code } }]);
|
|
183
|
+
const result = getBinaryNodeChild(results, 'group');
|
|
184
|
+
return result?.attrs.jid;
|
|
185
|
+
},
|
|
186
|
+
/**
|
|
187
|
+
* revoke a v4 invite for someone
|
|
188
|
+
* @param groupJid group jid
|
|
189
|
+
* @param invitedJid jid of person you invited
|
|
190
|
+
* @returns true if successful
|
|
191
|
+
*/
|
|
192
|
+
groupRevokeInviteV4: async (groupJid, invitedJid) => {
|
|
193
|
+
const result = await groupQuery(groupJid, 'set', [
|
|
194
|
+
{ tag: 'revoke', attrs: {}, content: [{ tag: 'participant', attrs: { jid: invitedJid } }] }
|
|
195
|
+
]);
|
|
196
|
+
return !!result;
|
|
197
|
+
},
|
|
198
|
+
/**
|
|
199
|
+
* accept a GroupInviteMessage
|
|
200
|
+
* @param key the key of the invite message, or optionally only provide the jid of the person who sent the invite
|
|
201
|
+
* @param inviteMessage the message to accept
|
|
202
|
+
*/
|
|
203
|
+
groupAcceptInviteV4: ev.createBufferedFunction(async (key, inviteMessage) => {
|
|
204
|
+
key = typeof key === 'string' ? { remoteJid: key } : key;
|
|
205
|
+
const results = await groupQuery(inviteMessage.groupJid, 'set', [
|
|
206
|
+
{
|
|
207
|
+
tag: 'accept',
|
|
208
|
+
attrs: {
|
|
209
|
+
code: inviteMessage.inviteCode,
|
|
210
|
+
expiration: inviteMessage.inviteExpiration.toString(),
|
|
211
|
+
admin: key.remoteJid
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
]);
|
|
215
|
+
// if we have the full message key
|
|
216
|
+
// update the invite message to be expired
|
|
217
|
+
if (key.id) {
|
|
218
|
+
// create new invite message that is expired
|
|
219
|
+
inviteMessage = proto.Message.GroupInviteMessage.fromObject(inviteMessage);
|
|
220
|
+
inviteMessage.inviteExpiration = 0;
|
|
221
|
+
inviteMessage.inviteCode = '';
|
|
222
|
+
ev.emit('messages.update', [
|
|
223
|
+
{
|
|
224
|
+
key,
|
|
225
|
+
update: {
|
|
226
|
+
message: {
|
|
227
|
+
groupInviteMessage: inviteMessage
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
]);
|
|
232
|
+
}
|
|
233
|
+
// generate the group add message
|
|
234
|
+
await upsertMessage({
|
|
235
|
+
key: {
|
|
236
|
+
remoteJid: inviteMessage.groupJid,
|
|
237
|
+
id: generateMessageIDV2(sock.user?.id),
|
|
238
|
+
fromMe: false,
|
|
239
|
+
participant: key.remoteJid
|
|
240
|
+
},
|
|
241
|
+
messageStubType: WAMessageStubType.GROUP_PARTICIPANT_ADD,
|
|
242
|
+
messageStubParameters: [JSON.stringify(authState.creds.me)],
|
|
243
|
+
participant: key.remoteJid,
|
|
244
|
+
messageTimestamp: unixTimestampSeconds()
|
|
245
|
+
}, 'notify');
|
|
246
|
+
return results.attrs.from;
|
|
247
|
+
}),
|
|
248
|
+
groupGetInviteInfo: async (code) => {
|
|
249
|
+
const results = await groupQuery('@g.us', 'get', [{ tag: 'invite', attrs: { code } }]);
|
|
250
|
+
return extractGroupMetadata(results);
|
|
251
|
+
},
|
|
252
|
+
groupToggleEphemeral: async (jid, ephemeralExpiration) => {
|
|
253
|
+
const content = ephemeralExpiration
|
|
254
|
+
? { tag: 'ephemeral', attrs: { expiration: ephemeralExpiration.toString() } }
|
|
255
|
+
: { tag: 'not_ephemeral', attrs: {} };
|
|
256
|
+
await groupQuery(jid, 'set', [content]);
|
|
257
|
+
},
|
|
258
|
+
groupSettingUpdate: async (jid, setting) => {
|
|
259
|
+
await groupQuery(jid, 'set', [{ tag: setting, attrs: {} }]);
|
|
260
|
+
},
|
|
261
|
+
groupMemberAddMode: async (jid, mode) => {
|
|
262
|
+
await groupQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: mode }]);
|
|
263
|
+
},
|
|
264
|
+
groupJoinApprovalMode: async (jid, mode) => {
|
|
265
|
+
await groupQuery(jid, 'set', [
|
|
266
|
+
{ tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'group_join', attrs: { state: mode } }] }
|
|
267
|
+
]);
|
|
268
|
+
},
|
|
269
|
+
groupFetchAllParticipating,
|
|
270
|
+
groupQuery
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
export const extractGroupMetadata = (result) => {
|
|
274
|
+
const group = getBinaryNodeChild(result, 'group');
|
|
275
|
+
const descChild = getBinaryNodeChild(group, 'description');
|
|
276
|
+
let desc;
|
|
277
|
+
let descId;
|
|
278
|
+
let descOwner;
|
|
279
|
+
let descOwnerPn;
|
|
280
|
+
let descTime;
|
|
281
|
+
if (descChild) {
|
|
282
|
+
desc = getBinaryNodeChildString(descChild, 'body');
|
|
283
|
+
descOwner = descChild.attrs.participant ? jidNormalizedUser(descChild.attrs.participant) : undefined;
|
|
284
|
+
descOwnerPn = descChild.attrs.participant_pn ? jidNormalizedUser(descChild.attrs.participant_pn) : undefined;
|
|
285
|
+
descTime = +descChild.attrs.t;
|
|
286
|
+
descId = descChild.attrs.id;
|
|
287
|
+
}
|
|
288
|
+
const groupId = group.attrs.id.includes('@') ? group.attrs.id : jidEncode(group.attrs.id, 'g.us');
|
|
289
|
+
const eph = getBinaryNodeChild(group, 'ephemeral')?.attrs.expiration;
|
|
290
|
+
const memberAddMode = getBinaryNodeChildString(group, 'member_add_mode') === 'all_member_add';
|
|
291
|
+
const metadata = {
|
|
292
|
+
id: groupId,
|
|
293
|
+
develop: "Eduh dev |</>🩵"
|
|
294
|
+
notify: group.attrs.notify,
|
|
295
|
+
addressingMode: group.attrs.addressing_mode === 'lid' ? WAMessageAddressingMode.LID : WAMessageAddressingMode.PN,
|
|
296
|
+
subject: group.attrs.subject,
|
|
297
|
+
subjectOwner: group.attrs.s_o,
|
|
298
|
+
subjectOwnerPn: group.attrs.s_o_pn,
|
|
299
|
+
subjectTime: +group.attrs.s_t,
|
|
300
|
+
size: group.attrs.size ? +group.attrs.size : getBinaryNodeChildren(group, 'participant').length,
|
|
301
|
+
creation: +group.attrs.creation,
|
|
302
|
+
owner: group.attrs.creator ? jidNormalizedUser(group.attrs.creator) : undefined,
|
|
303
|
+
ownerPn: group.attrs.creator_pn ? jidNormalizedUser(group.attrs.creator_pn) : undefined,
|
|
304
|
+
owner_country_code: group.attrs.creator_country_code,
|
|
305
|
+
desc,
|
|
306
|
+
descId,
|
|
307
|
+
descOwner,
|
|
308
|
+
descOwnerPn,
|
|
309
|
+
descTime,
|
|
310
|
+
linkedParent: getBinaryNodeChild(group, 'linked_parent')?.attrs.jid || undefined,
|
|
311
|
+
restrict: !!getBinaryNodeChild(group, 'locked'),
|
|
312
|
+
announce: !!getBinaryNodeChild(group, 'announcement'),
|
|
313
|
+
isCommunity: !!getBinaryNodeChild(group, 'parent'),
|
|
314
|
+
isCommunityAnnounce: !!getBinaryNodeChild(group, 'default_sub_group'),
|
|
315
|
+
joinApprovalMode: !!getBinaryNodeChild(group, 'membership_approval_mode'),
|
|
316
|
+
memberAddMode,
|
|
317
|
+
participants: getBinaryNodeChildren(group, 'participant').map(({ attrs }) => {
|
|
318
|
+
// TODO: Store LID MAPPINGS
|
|
319
|
+
return {
|
|
320
|
+
id: attrs.jid,
|
|
321
|
+
jid: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined,
|
|
322
|
+
lid: isPnUser(attrs.jid) && isLidUser(attrs.lid) ? attrs.lid : undefined,
|
|
323
|
+
admin: (attrs.type || null)
|
|
324
|
+
};
|
|
325
|
+
}),
|
|
326
|
+
ephemeralDuration: eph ? +eph : undefined
|
|
327
|
+
};
|
|
328
|
+
return metadata;
|
|
329
|
+
};
|
|
@@ -251,7 +251,7 @@ export const makeMessagesRecvSocket = (config) => {
|
|
|
251
251
|
};
|
|
252
252
|
await query(stanza);
|
|
253
253
|
};
|
|
254
|
-
//
|
|
254
|
+
// Boruto@Note 01-03-26 --- Source: https://github.com/koptereli/Baileys/commit/575cd41e6f01a9b3e1d7e2708c2292fa93de91f2
|
|
255
255
|
const initiateCall = async (jid, options = {}) => {
|
|
256
256
|
const meId = authState.creds.me?.id;
|
|
257
257
|
if (!meId) {
|
|
@@ -474,7 +474,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
474
474
|
});
|
|
475
475
|
}
|
|
476
476
|
await authState.keys.transaction(async () => {
|
|
477
|
-
//
|
|
477
|
+
// Boruto@Changes 02-02-26 --- Normalize message first to extract the original message and valid media type
|
|
478
478
|
const innerMessage = normalizeMessageContent(message);
|
|
479
479
|
const mediaType = getMediaType(innerMessage);
|
|
480
480
|
if (mediaType) {
|
|
@@ -483,14 +483,14 @@ export const makeMessagesSocket = (config) => {
|
|
|
483
483
|
if (isNewsletter) {
|
|
484
484
|
const patched = patchMessageBeforeSending ? await patchMessageBeforeSending(message, []) : message;
|
|
485
485
|
const bytes = encodeNewsletterMessage(patched);
|
|
486
|
-
//
|
|
486
|
+
// Boruto@Changes 08-02-26 --- Add "additionalNodes" for newsletter too (っ˘̩╭╮˘̩)っ
|
|
487
487
|
if (additionalNodes && additionalNodes.length > 0) {
|
|
488
488
|
;
|
|
489
489
|
binaryNodeContent.push(...additionalNodes);
|
|
490
490
|
}
|
|
491
491
|
binaryNodeContent.push({
|
|
492
492
|
tag: 'plaintext',
|
|
493
|
-
attrs: extraAttrs, //
|
|
493
|
+
attrs: extraAttrs, // Boruto@Changes 02-02-26 --- Add extraAttrs to fix media being rejected when sending to newsletter (◠‿◕)
|
|
494
494
|
content: bytes
|
|
495
495
|
});
|
|
496
496
|
const stanza = {
|
|
@@ -507,7 +507,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
507
507
|
await sendNode(stanza);
|
|
508
508
|
return;
|
|
509
509
|
}
|
|
510
|
-
//
|
|
510
|
+
// Boruto@Changes 02-02-26 --- Add keepInChat, editedMessage, mediaNotifyMessage and pollUpdateMessage
|
|
511
511
|
const isNeedMetaAttrs = innerMessage?.pinInChatMessage || innerMessage?.keepInChatMessage || innerMessage?.reactionMessage
|
|
512
512
|
if (isNeedMetaAttrs) {
|
|
513
513
|
const metaAttrs = {};
|
|
@@ -524,7 +524,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
524
524
|
if (isNeedMetaAttrs || innerMessage?.protocolMessage?.editedMessage || innerMessage?.protocolMessage?.mediaNotifyMessage) {
|
|
525
525
|
extraAttrs['decrypt-fail'] = 'hide'; // todo: expand for reactions and other types
|
|
526
526
|
}
|
|
527
|
-
//
|
|
527
|
+
// Boruto@Changes 02-02-26 --- Add native_flow_name to extraAttrs when sending interactiveResponseMessage
|
|
528
528
|
if (innerMessage?.interactiveResponseMessage?.nativeFlowResponseMessage) {
|
|
529
529
|
extraAttrs['native_flow_name'] = innerMessage.interactiveResponseMessage.nativeFlowResponseMessage.name;
|
|
530
530
|
}
|
|
@@ -818,7 +818,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
818
818
|
alreadyHasBizNode = !addBizAttributes &&
|
|
819
819
|
additionalNodes.some(node => node.tag === 'biz');
|
|
820
820
|
}
|
|
821
|
-
//
|
|
821
|
+
// Boruto@Changes 30-01-26 --- Add Biz Binary Node to support button messages
|
|
822
822
|
if ((!alreadyHasBizNode && shouldIncludeBizBinaryNode(innerMessage)) || addBizAttributes) {
|
|
823
823
|
const bizNode = getBizBinaryNode(innerMessage, addBizAttributes);
|
|
824
824
|
stanza.content.push(bizNode);
|
|
@@ -906,7 +906,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
906
906
|
else if (message.extendedTextMessage?.matchedText || message.groupInviteMessage) {
|
|
907
907
|
return 'url';
|
|
908
908
|
}
|
|
909
|
-
//
|
|
909
|
+
// Boruto@Note 02-02-26 --- Add more message type here
|
|
910
910
|
else if ((message.extendedTextMessage?.text || message.conversation || '').includes('://wa.me/c/')) {
|
|
911
911
|
return 'cataloglink';
|
|
912
912
|
}
|
|
@@ -1013,10 +1013,10 @@ export const makeMessagesSocket = (config) => {
|
|
|
1013
1013
|
ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }]);
|
|
1014
1014
|
return message;
|
|
1015
1015
|
},
|
|
1016
|
-
//
|
|
1016
|
+
// Boruto@Changes 30-01-26 --- Add support for modifying additionalNodes and additionalAttributes using "options" in sendMessage()
|
|
1017
1017
|
sendMessage: async (jid, content, options = {}) => {
|
|
1018
1018
|
const userJid = authState.creds.me.id;
|
|
1019
|
-
//
|
|
1019
|
+
// Boruto@Changes 13-03-26 --- Add status mentions!
|
|
1020
1020
|
if (Array.isArray(jid)) {
|
|
1021
1021
|
const { delayMs = 1500 } = options;
|
|
1022
1022
|
const allUsers = new Set();
|
|
@@ -1177,7 +1177,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
1177
1177
|
additionalNodes.push({
|
|
1178
1178
|
tag: 'meta',
|
|
1179
1179
|
attrs: {
|
|
1180
|
-
//
|
|
1180
|
+
// Boruto@Note 08-02-26 --- Still a hypothesis regarding PollResult ༎ຶ‿༎ຶ
|
|
1181
1181
|
polltype: isQuizMsg ? 'quiz_creation' : 'creation',
|
|
1182
1182
|
contenttype: isPollMsg && isNewsletter ? 'text' : undefined
|
|
1183
1183
|
},
|
|
@@ -1193,7 +1193,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
1193
1193
|
content: undefined
|
|
1194
1194
|
});
|
|
1195
1195
|
}
|
|
1196
|
-
//
|
|
1196
|
+
// Boruto@Changes 30-01-26 --- Add support for AI label in message when "ai" is true, but works only in private chat
|
|
1197
1197
|
else if (isAiMsg) {
|
|
1198
1198
|
if (!(isPnUser(jid) || isLidUser(jid))) {
|
|
1199
1199
|
throw new Boom('AI icon on message are only allowed in private chat', { statusCode: 400 });
|
|
@@ -1223,8 +1223,8 @@ export const makeMessagesSocket = (config) => {
|
|
|
1223
1223
|
await messageMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
1224
1224
|
});
|
|
1225
1225
|
}
|
|
1226
|
-
//
|
|
1227
|
-
//
|
|
1226
|
+
// Boruto@Changes 31-01-26 --- Add support for album messages
|
|
1227
|
+
// Boruto@Note 06-02-26 --- Refactored to reduce high RSS usage (╥﹏╥)
|
|
1228
1228
|
if ('album' in content) {
|
|
1229
1229
|
const { delayMs = 1500 } = options;
|
|
1230
1230
|
for (const albumMedia of content.album) {
|