@kelvdra/baileys 1.0.4 → 1.0.5-rc.2

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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/WAProto/index.js +65472 -137440
  3. package/lib/Defaults/index.d.ts +1 -1
  4. package/lib/Defaults/index.js +22 -3
  5. package/lib/Socket/chats.js +12 -13
  6. package/lib/Socket/groups.js +321 -18
  7. package/lib/Socket/hydra.js +521 -0
  8. package/lib/Socket/messages-recv.js +736 -324
  9. package/lib/Socket/messages-send.js +526 -113
  10. package/lib/Socket/mex.js +44 -6
  11. package/lib/Socket/newsletter.d.ts +16 -9
  12. package/lib/Socket/newsletter.js +259 -70
  13. package/lib/Types/GroupMetadata.d.ts +16 -0
  14. package/lib/Types/Mex.d.ts +141 -0
  15. package/lib/Types/Mex.js +37 -0
  16. package/lib/Types/State.js +54 -1
  17. package/lib/Utils/auth-utils.js +12 -1
  18. package/lib/Utils/chat-utils.js +36 -2
  19. package/lib/Utils/companion-reg-client-utils.d.ts +17 -0
  20. package/lib/Utils/companion-reg-client-utils.js +35 -0
  21. package/lib/Utils/decode-wa-message.js +23 -4
  22. package/lib/Utils/generics.js +4 -1
  23. package/lib/Utils/identity-change-handler.d.ts +44 -0
  24. package/lib/Utils/identity-change-handler.js +50 -0
  25. package/lib/Utils/index.js +1 -1
  26. package/lib/Utils/message-retry-manager.js +25 -1
  27. package/lib/Utils/messages-media.js +162 -43
  28. package/lib/Utils/messages.d.ts +1 -1
  29. package/lib/Utils/messages.js +230 -9
  30. package/lib/Utils/offline-node-processor.d.ts +17 -0
  31. package/lib/Utils/offline-node-processor.js +40 -0
  32. package/lib/Utils/reporting-utils.d.ts +11 -0
  33. package/lib/Utils/reporting-utils.js +258 -0
  34. package/lib/Utils/signal.js +45 -1
  35. package/lib/Utils/stanza-ack.d.ts +11 -0
  36. package/lib/Utils/stanza-ack.js +38 -0
  37. package/lib/Utils/sync-action-utils.d.ts +19 -0
  38. package/lib/Utils/sync-action-utils.js +49 -0
  39. package/lib/Utils/tc-token-utils.d.ts +37 -0
  40. package/lib/Utils/tc-token-utils.js +163 -0
  41. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
  42. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +25 -0
  43. package/lib/WAUSync/Protocols/index.d.ts +1 -0
  44. package/lib/WAUSync/Protocols/index.js +1 -0
  45. package/lib/WAUSync/USyncQuery.js +5 -1
  46. package/package.json +3 -1
@@ -4,6 +4,183 @@ const WAProto = WaProto.proto
4
4
  import axios from "axios"
5
5
  import crypto from 'crypto'
6
6
 
7
+ function hydraExtractHyperlink(text = '') {
8
+ const hyperlink = [];
9
+ const stack = [];
10
+ let result = '';
11
+ let last = 0;
12
+ let index = 1;
13
+ let entity = 0;
14
+
15
+ for (let i = 0; i < text.length; i++) {
16
+ if (text[i] === '[' && text[i - 1] !== '\\') {
17
+ stack.push(i);
18
+ } else if (text[i] === ']' && text[i + 1] === '(') {
19
+ const start = stack.pop();
20
+ if (start == null) continue;
21
+
22
+ let end = i + 2;
23
+ let depth = 1;
24
+
25
+ while (end < text.length && depth) {
26
+ if (text[end] === '(' && text[end - 1] !== '\\') depth++;
27
+ else if (text[end] === ')' && text[end - 1] !== '\\') depth--;
28
+ end++;
29
+ }
30
+
31
+ if (depth) continue;
32
+
33
+ const txt = text.slice(start + 1, i).trim();
34
+ const url = text.slice(i + 2, end - 1);
35
+ const reference_id = txt ? 0 : index++;
36
+ const key = `HYDRA_IE_${entity++}`;
37
+ const tag = `{{${key}}}${txt || url || 'Link'}{{/${key}}}`;
38
+
39
+ result += text.slice(last, start) + tag;
40
+ last = end;
41
+
42
+ hyperlink.push({ reference_id, key, text: txt, url });
43
+ i = end - 1;
44
+ }
45
+ }
46
+
47
+ result += text.slice(last);
48
+ return { text: result, hyperlink };
49
+ }
50
+
51
+ function hydraToTableMetadata(arr = []) {
52
+ if (!Array.isArray(arr) || arr.length < 1) {
53
+ return { title: '', rows: [], unified_rows: [] };
54
+ }
55
+
56
+ const [header = [], ...rows] = arr;
57
+ const maxLen = Math.max(header.length || 0, ...rows.map((r) => Array.isArray(r) ? r.length : 0), 1);
58
+ const normalize = (r = []) => [...r, ...Array(maxLen - r.length).fill('')].map((x) => String(x ?? ''));
59
+
60
+ const unified_rows = [
61
+ { is_header: true, cells: normalize(header) },
62
+ ...rows.map((r) => ({ is_header: false, cells: normalize(Array.isArray(r) ? r : [r]) }))
63
+ ];
64
+
65
+ return {
66
+ title: '',
67
+ rows: unified_rows.map((r) => ({
68
+ items: r.cells,
69
+ ...(r.is_header ? { isHeading: true } : {})
70
+ })),
71
+ unified_rows
72
+ };
73
+ }
74
+
75
+ function hydraTokenizeCode(code = '', lang = 'javascript') {
76
+ const keywordsMap = {
77
+ javascript: new Set([
78
+ 'break', 'case', 'catch', 'continue', 'debugger', 'delete', 'do', 'else',
79
+ 'finally', 'for', 'function', 'if', 'in', 'instanceof', 'new', 'return',
80
+ 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void', 'while', 'with',
81
+ 'true', 'false', 'null', 'undefined', 'class', 'const', 'let', 'super',
82
+ 'extends', 'export', 'import', 'yield', 'static', 'constructor', 'async',
83
+ 'await', 'get', 'set'
84
+ ]),
85
+ python: new Set([
86
+ 'False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break',
87
+ 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally',
88
+ 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal',
89
+ 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'
90
+ ])
91
+ };
92
+
93
+ const TYPE_MAP = {
94
+ 0: 'DEFAULT',
95
+ 1: 'KEYWORD',
96
+ 2: 'METHOD',
97
+ 3: 'STR',
98
+ 4: 'NUMBER',
99
+ 5: 'COMMENT'
100
+ };
101
+
102
+ const keywords = keywordsMap[lang] || keywordsMap.javascript;
103
+ const tokens = [];
104
+ let i = 0;
105
+
106
+ const push = (content, type) => {
107
+ if (!content) return;
108
+ const last = tokens[tokens.length - 1];
109
+ if (last && last.highlightType === type) last.codeContent += content;
110
+ else tokens.push({ codeContent: content, highlightType: type });
111
+ };
112
+
113
+ while (i < code.length) {
114
+ const c = code[i];
115
+
116
+ if (/\s/.test(c)) {
117
+ const s = i;
118
+ while (i < code.length && /\s/.test(code[i])) i++;
119
+ push(code.slice(s, i), 0);
120
+ continue;
121
+ }
122
+
123
+ if ((c === '/' && code[i + 1] === '/') || (c === '#' && lang === 'python')) {
124
+ const s = i;
125
+ i += c === '#' ? 1 : 2;
126
+ while (i < code.length && code[i] !== '\n') i++;
127
+ push(code.slice(s, i), 5);
128
+ continue;
129
+ }
130
+
131
+ if (c === '"' || c === "'" || c === '`') {
132
+ const s = i;
133
+ const q = c;
134
+ i++;
135
+ while (i < code.length) {
136
+ if (code[i] === '\\' && i + 1 < code.length) i += 2;
137
+ else if (code[i] === q) {
138
+ i++;
139
+ break;
140
+ } else i++;
141
+ }
142
+ push(code.slice(s, i), 3);
143
+ continue;
144
+ }
145
+
146
+ if (/[0-9]/.test(c)) {
147
+ const s = i;
148
+ while (i < code.length && /[0-9.]/.test(code[i])) i++;
149
+ push(code.slice(s, i), 4);
150
+ continue;
151
+ }
152
+
153
+ if (/[a-zA-Z_$]/.test(c)) {
154
+ const s = i;
155
+ while (i < code.length && /[a-zA-Z0-9_$]/.test(code[i])) i++;
156
+ const word = code.slice(s, i);
157
+
158
+ let type = 0;
159
+ if (keywords.has(word)) type = 1;
160
+ else {
161
+ let j = i;
162
+ while (j < code.length && /\s/.test(code[j])) j++;
163
+ if (code[j] === '(') type = 2;
164
+ }
165
+
166
+ push(word, type);
167
+ continue;
168
+ }
169
+
170
+ push(c, 0);
171
+ i++;
172
+ }
173
+
174
+ return {
175
+ codeBlock: tokens,
176
+ unified_codeBlock: tokens.map((t) => ({
177
+ content: t.codeContent,
178
+ type: TYPE_MAP[t.highlightType] || 'DEFAULT'
179
+ }))
180
+ };
181
+ }
182
+
183
+
7
184
  class hydra {
8
185
  constructor(utils, waUploadToServer, relayMessageFn) {
9
186
  this.utils = utils;
@@ -22,6 +199,8 @@ class hydra {
22
199
  if (content.orderMessage) return 'ORDER';
23
200
  if (content.groupStatus) return 'GROUP_STATUS';
24
201
  if (content.carouselMessage || content.carousel) return 'CAROUSEL';
202
+ if (content.stickerPack) return "STICKER_PACK";
203
+ if (content.aiRich || content.airich || content.richResponse || content.richResponseMessage || content.AIRich) return 'AI_RICH';
25
204
  return null;
26
205
  }
27
206
 
@@ -127,6 +306,49 @@ class hydra {
127
306
  return msg;
128
307
  }
129
308
 
309
+ async handleStickerPack(stickerPack, jid, quoted) {
310
+ const result = await this.utils.prepareStickerPackMessage(stickerPack, {
311
+ logger: this.utils?.logger,
312
+ upload: this.waUploadToServer,
313
+ options: this.utils?.options || {},
314
+ mediaUploadTimeoutMs: this.utils?.mediaUploadTimeoutMs
315
+ });
316
+
317
+ if (result.isBatched) {
318
+ let lastMsg;
319
+ for (let i = 0; i < result.stickerPackMessage.length; i++) {
320
+ const msg = await this.utils.generateWAMessageFromContent(
321
+ jid,
322
+ { stickerPackMessage: result.stickerPackMessage[i] },
323
+ { quoted, upload: this.waUploadToServer }
324
+ );
325
+
326
+ await this.relayMessage(jid, msg.message, {
327
+ messageId: msg.key.id
328
+ });
329
+
330
+ lastMsg = msg;
331
+
332
+ if (i < result.stickerPackMessage.length - 1) {
333
+ await new Promise(r => setTimeout(r, 2000));
334
+ }
335
+ }
336
+ return lastMsg;
337
+ }
338
+
339
+ const msg = await this.utils.generateWAMessageFromContent(
340
+ jid,
341
+ { stickerPackMessage: result.stickerPackMessage },
342
+ { quoted, upload: this.waUploadToServer }
343
+ );
344
+
345
+ await this.relayMessage(jid, msg.message, {
346
+ messageId: msg.key.id
347
+ });
348
+
349
+ return msg;
350
+ }
351
+
130
352
  async handlePayment(content, quoted) {
131
353
  const data = content.requestPaymentMessage;
132
354
  let notes = {};
@@ -709,6 +931,305 @@ class hydra {
709
931
  messageId: this.utils.generateMessageID()
710
932
  });
711
933
  }
934
+
935
+ buildAIRichPayload(data = {}) {
936
+ const submessages = [];
937
+ const sections = [];
938
+ const richResponseSources = [];
939
+
940
+ const addText = (text = '', { hyperlink = true } = {}) => {
941
+ const extracted = hyperlink ? hydraExtractHyperlink(String(text ?? '')) : { text: String(text ?? ''), hyperlink: [] };
942
+
943
+ submessages.push({
944
+ messageType: 2,
945
+ messageText: extracted.text
946
+ });
947
+
948
+ sections.push({
949
+ view_model: {
950
+ primitive: extracted.hyperlink.length
951
+ ? {
952
+ text: extracted.text,
953
+ inline_entities: extracted.hyperlink.map(({ reference_id, key, text, url }) => ({
954
+ key,
955
+ metadata: text?.trim()
956
+ ? {
957
+ display_name: text,
958
+ is_trusted: true,
959
+ url,
960
+ __typename: 'GenAIInlineLinkItem'
961
+ }
962
+ : {
963
+ reference_id,
964
+ reference_url: url,
965
+ reference_title: url,
966
+ reference_display_name: url,
967
+ sources: [],
968
+ __typename: 'GenAISearchCitationItem'
969
+ }
970
+ })),
971
+ __typename: 'GenAIMarkdownTextUXPrimitive'
972
+ }
973
+ : {
974
+ text: String(text ?? ''),
975
+ __typename: 'GenAIMarkdownTextUXPrimitive'
976
+ },
977
+ __typename: 'GenAISingleLayoutViewModel'
978
+ }
979
+ });
980
+ };
981
+
982
+ const addCode = (language = 'javascript', code = '') => {
983
+ const meta = hydraTokenizeCode(String(code ?? ''), language);
984
+
985
+ submessages.push({
986
+ messageType: 5,
987
+ codeMetadata: {
988
+ codeLanguage: language,
989
+ codeBlocks: meta.codeBlock
990
+ }
991
+ });
992
+
993
+ sections.push({
994
+ view_model: {
995
+ primitive: {
996
+ language,
997
+ code_blocks: meta.unified_codeBlock,
998
+ __typename: 'GenAICodeUXPrimitive'
999
+ },
1000
+ __typename: 'GenAISingleLayoutViewModel'
1001
+ }
1002
+ });
1003
+ };
1004
+
1005
+ const addTable = (table = []) => {
1006
+ const meta = hydraToTableMetadata(table);
1007
+
1008
+ submessages.push({
1009
+ messageType: 4,
1010
+ tableMetadata: {
1011
+ title: meta.title,
1012
+ rows: meta.rows
1013
+ }
1014
+ });
1015
+
1016
+ sections.push({
1017
+ view_model: {
1018
+ primitive: {
1019
+ rows: meta.unified_rows,
1020
+ __typename: 'GenATableUXPrimitive'
1021
+ },
1022
+ __typename: 'GenAISingleLayoutViewModel'
1023
+ }
1024
+ });
1025
+ };
1026
+
1027
+ const addImages = (images = []) => {
1028
+ const list = Array.isArray(images) ? images : [images];
1029
+ const imageUrls = list
1030
+ .filter(Boolean)
1031
+ .map((item) => {
1032
+ const url = typeof item === 'string' ? item : item.url || item.imageUrl || item.imagePreviewUrl;
1033
+ return {
1034
+ imagePreviewUrl: url,
1035
+ imageHighResUrl: item.imageHighResUrl || item.highResUrl || url,
1036
+ sourceUrl: item.sourceUrl || data.sourceUrl || 'https://google.com'
1037
+ };
1038
+ })
1039
+ .filter((x) => x.imagePreviewUrl);
1040
+
1041
+ if (!imageUrls.length) return;
1042
+
1043
+ submessages.push({
1044
+ messageType: 1,
1045
+ gridImageMetadata: {
1046
+ gridImageUrl: {
1047
+ imagePreviewUrl: imageUrls[0].imagePreviewUrl
1048
+ },
1049
+ imageUrls
1050
+ }
1051
+ });
1052
+
1053
+ imageUrls.forEach(({ imagePreviewUrl }) => {
1054
+ sections.push({
1055
+ view_model: {
1056
+ primitive: {
1057
+ media: {
1058
+ url: imagePreviewUrl,
1059
+ mime_type: 'image/jpeg'
1060
+ },
1061
+ imagine_type: 3,
1062
+ status: {
1063
+ status: 'READY'
1064
+ },
1065
+ __typename: 'GenAIImaginePrimitive'
1066
+ },
1067
+ __typename: 'GenAISingleLayoutViewModel'
1068
+ }
1069
+ });
1070
+ });
1071
+ };
1072
+
1073
+ const addSources = (sources = []) => {
1074
+ if (!Array.isArray(sources) || !sources.length) return;
1075
+
1076
+ sections.push({
1077
+ view_model: {
1078
+ primitive: {
1079
+ sources: sources.map((source) => {
1080
+ const arr = Array.isArray(source) ? source : null;
1081
+ const profileUrl = arr ? arr[0] : source.profileIconUrl || source.faviconUrl || source.thumbnailUrl || '';
1082
+ const url = arr ? arr[1] : source.url || source.sourceUrl || source.sourceProviderURL || '';
1083
+ const text = arr ? arr[2] : source.title || source.sourceTitle || source.provider || 'Source';
1084
+
1085
+ return {
1086
+ source_type: 'THIRD_PARTY',
1087
+ source_display_name: text,
1088
+ source_subtitle: source.subtitle || 'AI',
1089
+ source_url: url,
1090
+ favicon: {
1091
+ url: profileUrl,
1092
+ mime_type: 'image/jpeg',
1093
+ width: 16,
1094
+ height: 16
1095
+ }
1096
+ };
1097
+ }),
1098
+ __typename: 'GenAISearchResultPrimitive'
1099
+ },
1100
+ __typename: 'GenAISingleLayoutViewModel'
1101
+ }
1102
+ });
1103
+ };
1104
+
1105
+ const addReels = (reelsItems = []) => {
1106
+ if (!Array.isArray(reelsItems) || !reelsItems.length) return;
1107
+
1108
+ submessages.push({
1109
+ messageType: 9,
1110
+ contentItemsMetadata: {
1111
+ contentType: 1,
1112
+ itemsMetadata: reelsItems.map((item) => ({
1113
+ reelItem: {
1114
+ title: item.title || item.creator || '',
1115
+ profileIconUrl: item.profileIconUrl || item.avatar_url || '',
1116
+ thumbnailUrl: item.thumbnailUrl || item.thumbnail_url || '',
1117
+ videoUrl: item.videoUrl || item.reels_url || item.url || '',
1118
+ }
1119
+ }))
1120
+ }
1121
+ });
1122
+
1123
+ reelsItems.forEach((item, idx) => {
1124
+ richResponseSources.push({
1125
+ provider: item.provider || 'UNKNOWN',
1126
+ thumbnailCDNURL: item.thumbnailUrl || item.thumbnail_url || '',
1127
+ sourceProviderURL: item.videoUrl || item.reels_url || item.url || '',
1128
+ sourceQuery: '',
1129
+ faviconCDNURL: item.profileIconUrl || item.avatar_url || '',
1130
+ citationNumber: idx + 1,
1131
+ sourceTitle: item.title || item.creator || `Reel ${idx + 1}`
1132
+ });
1133
+ });
1134
+
1135
+ sections.push({
1136
+ view_model: {
1137
+ primitives: reelsItems.map((item) => ({
1138
+ reels_url: item.videoUrl || item.reels_url || item.url || '',
1139
+ thumbnail_url: item.thumbnailUrl || item.thumbnail_url || '',
1140
+ creator: item.title || item.creator || '',
1141
+ avatar_url: item.profileIconUrl || item.avatar_url || '',
1142
+ reels_title: item.reels_title || item.reelsTitle || item.title || '',
1143
+ likes_count: item.likes_count || item.likesCount || 0,
1144
+ shares_count: item.shares_count || item.sharesCount || 0,
1145
+ view_count: item.view_count || item.viewCount || 0,
1146
+ reel_source: item.reel_source || item.reelSource || 'IG',
1147
+ is_verified: !!(item.is_verified ?? item.isVerified),
1148
+ __typename: 'GenAIReelPrimitive'
1149
+ })),
1150
+ __typename: 'GenAIHScrollLayoutViewModel'
1151
+ }
1152
+ });
1153
+ };
1154
+
1155
+ if (data.text) addText(data.text, { hyperlink: data.hyperlink !== false });
1156
+ if (Array.isArray(data.texts)) data.texts.forEach((text) => addText(text, { hyperlink: data.hyperlink !== false }));
1157
+
1158
+ if (data.code) {
1159
+ if (typeof data.code === 'string') addCode(data.language || 'javascript', data.code);
1160
+ else addCode(data.code.language || data.language || 'javascript', data.code.content || data.code.code || '');
1161
+ }
1162
+
1163
+ if (Array.isArray(data.codes)) {
1164
+ data.codes.forEach((item) => {
1165
+ if (typeof item === 'string') addCode(data.language || 'javascript', item);
1166
+ else addCode(item.language || data.language || 'javascript', item.content || item.code || '');
1167
+ });
1168
+ }
1169
+
1170
+ if (data.table) addTable(data.table);
1171
+ if (data.image || data.images || data.gridImage) addImages(data.images || data.gridImage || data.image);
1172
+ if (data.sources) addSources(data.sources);
1173
+ if (data.reels || data.reel) addReels(data.reels || data.reel);
1174
+
1175
+ const forwarded = data.forwarded !== false;
1176
+ const includesUnifiedResponse = data.includesUnifiedResponse !== false;
1177
+
1178
+ return {
1179
+ messageContextInfo: {
1180
+ deviceListMetadata: {},
1181
+ deviceListMetadataVersion: 2,
1182
+ botMetadata: {
1183
+ messageDisclaimerText: data.disclaimerText || data.messageDisclaimerText || '',
1184
+ pluginMetadata: {},
1185
+ richResponseSourcesMetadata: {
1186
+ sources: data.richResponseSources || richResponseSources
1187
+ }
1188
+ }
1189
+ },
1190
+ botForwardedMessage: {
1191
+ message: {
1192
+ richResponseMessage: {
1193
+ messageType: data.messageType || 1,
1194
+ submessages,
1195
+ unifiedResponse: {
1196
+ data: includesUnifiedResponse
1197
+ ? Buffer.from(JSON.stringify({
1198
+ response_id: data.responseId || crypto.randomUUID(),
1199
+ sections
1200
+ })).toString('base64')
1201
+ : ''
1202
+ },
1203
+ contextInfo: forwarded
1204
+ ? {
1205
+ forwardingScore: data.forwardingScore || 1,
1206
+ isForwarded: true,
1207
+ forwardedAiBotMessageInfo: {
1208
+ botJid: data.botJid || '0@bot'
1209
+ },
1210
+ forwardOrigin: data.forwardOrigin || 4,
1211
+ ...(data.contextInfo || {})
1212
+ }
1213
+ : (data.contextInfo || {})
1214
+ }
1215
+ }
1216
+ }
1217
+ };
1218
+ }
1219
+
1220
+ async handleAIRich(content, jid, quoted, options = {}) {
1221
+ const data = content.aiRich || content.airich || content.richResponse || content.AIRich || content;
1222
+
1223
+ const msg = this.buildAIRichPayload(data);
1224
+
1225
+ return await this.relayMessage(jid, msg, {
1226
+ messageId: data.messageId || this.utils.generateMessageID?.() || crypto.randomBytes(10).toString('hex').toUpperCase(),
1227
+ ...(quoted ? { quoted } : {}),
1228
+ ...options
1229
+ });
1230
+ }
1231
+
1232
+
712
1233
  }
713
1234
 
714
1235
  export default hydra