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.
Files changed (222) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1429 -684
  3. package/package.json +11 -26
  4. package/src/Defaults/baileys-version.json +3 -0
  5. package/{lib → src}/Defaults/index.js +16 -8
  6. package/src/Defaults/index.ts +131 -0
  7. package/src/Defaults/phonenumber-mcc.json +223 -0
  8. package/src/Signal/libsignal.js +180 -0
  9. package/src/Signal/libsignal.ts +141 -0
  10. package/src/Socket/Client/abstract-socket-client.ts +19 -0
  11. package/src/Socket/Client/index.ts +3 -0
  12. package/src/Socket/Client/mobile-socket-client.js +78 -0
  13. package/src/Socket/Client/mobile-socket-client.ts +66 -0
  14. package/src/Socket/Client/web-socket-client.js +75 -0
  15. package/src/Socket/Client/web-socket-client.ts +57 -0
  16. package/{lib → src}/Socket/business.js +33 -27
  17. package/src/Socket/business.ts +281 -0
  18. package/{lib → src}/Socket/chats.js +197 -178
  19. package/src/Socket/chats.ts +1030 -0
  20. package/{lib → src}/Socket/groups.js +69 -79
  21. package/src/Socket/groups.ts +356 -0
  22. package/{lib → src}/Socket/index.js +1 -4
  23. package/src/Socket/index.ts +13 -0
  24. package/{lib → src}/Socket/messages-recv.js +160 -108
  25. package/src/Socket/messages-recv.ts +985 -0
  26. package/{lib → src}/Socket/messages-send.js +183 -100
  27. package/src/Socket/messages-send.ts +871 -0
  28. package/src/Socket/newsletter.js +227 -0
  29. package/src/Socket/newsletter.ts +282 -0
  30. package/{lib → src}/Socket/registration.js +55 -63
  31. package/src/Socket/registration.ts +250 -0
  32. package/{lib → src}/Socket/socket.js +107 -66
  33. package/src/Socket/socket.ts +777 -0
  34. package/src/Store/index.ts +3 -0
  35. package/{lib → src}/Store/make-cache-manager-store.js +34 -25
  36. package/src/Store/make-cache-manager-store.ts +100 -0
  37. package/{lib → src}/Store/make-in-memory-store.js +51 -61
  38. package/src/Store/make-in-memory-store.ts +475 -0
  39. package/src/Store/make-ordered-dictionary.ts +86 -0
  40. package/{lib → src}/Store/object-repository.js +1 -1
  41. package/src/Store/object-repository.ts +32 -0
  42. package/src/Tests/test.app-state-sync.js +204 -0
  43. package/src/Tests/test.app-state-sync.ts +207 -0
  44. package/src/Tests/test.event-buffer.js +270 -0
  45. package/src/Tests/test.event-buffer.ts +319 -0
  46. package/src/Tests/test.key-store.js +76 -0
  47. package/src/Tests/test.key-store.ts +92 -0
  48. package/src/Tests/test.libsignal.js +141 -0
  49. package/src/Tests/test.libsignal.ts +186 -0
  50. package/src/Tests/test.media-download.js +93 -0
  51. package/src/Tests/test.media-download.ts +76 -0
  52. package/src/Tests/test.messages.js +33 -0
  53. package/src/Tests/test.messages.ts +37 -0
  54. package/src/Tests/utils.js +34 -0
  55. package/src/Tests/utils.ts +36 -0
  56. package/src/Types/Auth.ts +113 -0
  57. package/src/Types/Call.ts +15 -0
  58. package/src/Types/Chat.ts +106 -0
  59. package/{lib/Types/Contact.d.ts → src/Types/Contact.ts} +9 -8
  60. package/src/Types/Events.ts +93 -0
  61. package/src/Types/GroupMetadata.ts +53 -0
  62. package/{lib → src}/Types/Label.js +1 -1
  63. package/src/Types/Label.ts +36 -0
  64. package/{lib → src}/Types/LabelAssociation.js +1 -1
  65. package/{lib/Types/LabelAssociation.d.ts → src/Types/LabelAssociation.ts} +22 -16
  66. package/src/Types/Message.ts +288 -0
  67. package/src/Types/Newsletter.js +32 -0
  68. package/src/Types/Newsletter.ts +98 -0
  69. package/src/Types/Product.ts +85 -0
  70. package/src/Types/Signal.ts +68 -0
  71. package/{lib/Types/Socket.d.ts → src/Types/Socket.ts} +68 -56
  72. package/src/Types/State.ts +29 -0
  73. package/{lib → src}/Types/index.js +2 -1
  74. package/src/Types/index.ts +59 -0
  75. package/{lib → src}/Utils/auth-utils.js +95 -76
  76. package/src/Utils/auth-utils.ts +222 -0
  77. package/src/Utils/baileys-event-stream.js +92 -0
  78. package/src/Utils/baileys-event-stream.ts +66 -0
  79. package/{lib → src}/Utils/business.js +45 -17
  80. package/src/Utils/business.ts +275 -0
  81. package/{lib → src}/Utils/chat-utils.js +74 -46
  82. package/src/Utils/chat-utils.ts +860 -0
  83. package/{lib → src}/Utils/crypto.js +31 -21
  84. package/src/Utils/crypto.ts +131 -0
  85. package/src/Utils/decode-wa-message.js +211 -0
  86. package/src/Utils/decode-wa-message.ts +228 -0
  87. package/{lib → src}/Utils/event-buffer.js +13 -4
  88. package/src/Utils/event-buffer.ts +613 -0
  89. package/{lib → src}/Utils/generics.js +98 -45
  90. package/src/Utils/generics.ts +434 -0
  91. package/{lib → src}/Utils/history.js +39 -10
  92. package/src/Utils/history.ts +112 -0
  93. package/src/Utils/index.ts +17 -0
  94. package/{lib → src}/Utils/link-preview.js +54 -17
  95. package/src/Utils/link-preview.ts +122 -0
  96. package/src/Utils/logger.ts +3 -0
  97. package/src/Utils/lt-hash.ts +61 -0
  98. package/{lib → src}/Utils/make-mutex.js +13 -4
  99. package/src/Utils/make-mutex.ts +44 -0
  100. package/{lib → src}/Utils/messages-media.js +296 -192
  101. package/src/Utils/messages-media.ts +847 -0
  102. package/{lib → src}/Utils/messages.js +124 -113
  103. package/src/Utils/messages.ts +956 -0
  104. package/{lib → src}/Utils/noise-handler.js +16 -3
  105. package/src/Utils/noise-handler.ts +197 -0
  106. package/{lib → src}/Utils/process-message.js +33 -29
  107. package/src/Utils/process-message.ts +414 -0
  108. package/{lib → src}/Utils/signal.js +23 -14
  109. package/src/Utils/signal.ts +177 -0
  110. package/{lib → src}/Utils/use-multi-file-auth-state.js +28 -19
  111. package/src/Utils/use-multi-file-auth-state.ts +90 -0
  112. package/{lib → src}/Utils/validate-connection.js +25 -42
  113. package/src/Utils/validate-connection.ts +238 -0
  114. package/src/WABinary/constants.ts +42 -0
  115. package/{lib → src}/WABinary/decode.js +17 -7
  116. package/src/WABinary/decode.ts +265 -0
  117. package/{lib → src}/WABinary/encode.js +17 -7
  118. package/src/WABinary/encode.ts +236 -0
  119. package/{lib → src}/WABinary/generic-utils.js +2 -2
  120. package/src/WABinary/generic-utils.ts +121 -0
  121. package/src/WABinary/index.ts +5 -0
  122. package/{lib → src}/WABinary/jid-utils.js +4 -1
  123. package/src/WABinary/jid-utils.ts +68 -0
  124. package/src/WABinary/types.ts +17 -0
  125. package/src/WAM/BinaryInfo.js +13 -0
  126. package/src/WAM/BinaryInfo.ts +12 -0
  127. package/src/WAM/constants.js +15350 -0
  128. package/src/WAM/constants.ts +15382 -0
  129. package/src/WAM/encode.js +155 -0
  130. package/src/WAM/encode.ts +174 -0
  131. package/src/WAM/index.js +19 -0
  132. package/src/WAM/index.ts +3 -0
  133. package/src/gifted +1 -0
  134. package/{lib → src}/index.js +1 -0
  135. package/src/index.ts +13 -0
  136. package/lib/Defaults/baileys-version.json +0 -3
  137. package/lib/Defaults/index.d.ts +0 -284
  138. package/lib/Defaults/phonenumber-mcc.json +0 -223
  139. package/lib/Signal/libsignal.d.ts +0 -3
  140. package/lib/Signal/libsignal.js +0 -152
  141. package/lib/Socket/Client/abstract-socket-client.d.ts +0 -17
  142. package/lib/Socket/Client/index.d.ts +0 -3
  143. package/lib/Socket/Client/mobile-socket-client.d.ts +0 -13
  144. package/lib/Socket/Client/mobile-socket-client.js +0 -65
  145. package/lib/Socket/Client/web-socket-client.d.ts +0 -12
  146. package/lib/Socket/Client/web-socket-client.js +0 -62
  147. package/lib/Socket/business.d.ts +0 -135
  148. package/lib/Socket/chats.d.ts +0 -79
  149. package/lib/Socket/groups.d.ts +0 -113
  150. package/lib/Socket/index.d.ts +0 -137
  151. package/lib/Socket/messages-recv.d.ts +0 -124
  152. package/lib/Socket/messages-send.d.ts +0 -119
  153. package/lib/Socket/registration.d.ts +0 -232
  154. package/lib/Socket/socket.d.ts +0 -42
  155. package/lib/Store/index.d.ts +0 -3
  156. package/lib/Store/make-cache-manager-store.d.ts +0 -13
  157. package/lib/Store/make-in-memory-store.d.ts +0 -117
  158. package/lib/Store/make-ordered-dictionary.d.ts +0 -13
  159. package/lib/Store/object-repository.d.ts +0 -10
  160. package/lib/Types/Auth.d.ts +0 -108
  161. package/lib/Types/Call.d.ts +0 -13
  162. package/lib/Types/Chat.d.ts +0 -102
  163. package/lib/Types/Events.d.ts +0 -157
  164. package/lib/Types/GroupMetadata.d.ts +0 -52
  165. package/lib/Types/Label.d.ts +0 -35
  166. package/lib/Types/Message.d.ts +0 -261
  167. package/lib/Types/Product.d.ts +0 -78
  168. package/lib/Types/Signal.d.ts +0 -57
  169. package/lib/Types/State.d.ts +0 -27
  170. package/lib/Types/index.d.ts +0 -56
  171. package/lib/Utils/auth-utils.d.ts +0 -18
  172. package/lib/Utils/baileys-event-stream.d.ts +0 -16
  173. package/lib/Utils/baileys-event-stream.js +0 -63
  174. package/lib/Utils/business.d.ts +0 -22
  175. package/lib/Utils/chat-utils.d.ts +0 -71
  176. package/lib/Utils/crypto.d.ts +0 -41
  177. package/lib/Utils/decode-wa-message.d.ts +0 -19
  178. package/lib/Utils/decode-wa-message.js +0 -174
  179. package/lib/Utils/event-buffer.d.ts +0 -35
  180. package/lib/Utils/generics.d.ts +0 -94
  181. package/lib/Utils/history.d.ts +0 -15
  182. package/lib/Utils/index.d.ts +0 -17
  183. package/lib/Utils/link-preview.d.ts +0 -21
  184. package/lib/Utils/logger.d.ts +0 -4
  185. package/lib/Utils/lt-hash.d.ts +0 -12
  186. package/lib/Utils/make-mutex.d.ts +0 -7
  187. package/lib/Utils/messages-media.d.ts +0 -107
  188. package/lib/Utils/messages.d.ts +0 -76
  189. package/lib/Utils/noise-handler.d.ts +0 -20
  190. package/lib/Utils/process-message.d.ts +0 -41
  191. package/lib/Utils/signal.d.ts +0 -32
  192. package/lib/Utils/use-multi-file-auth-state.d.ts +0 -12
  193. package/lib/Utils/validate-connection.d.ts +0 -11
  194. package/lib/WABinary/constants.d.ts +0 -27
  195. package/lib/WABinary/decode.d.ts +0 -7
  196. package/lib/WABinary/encode.d.ts +0 -3
  197. package/lib/WABinary/generic-utils.d.ts +0 -15
  198. package/lib/WABinary/index.d.ts +0 -5
  199. package/lib/WABinary/jid-utils.d.ts +0 -29
  200. package/lib/WABinary/types.d.ts +0 -18
  201. package/lib/index.d.ts +0 -10
  202. /package/{lib → src}/Socket/Client/abstract-socket-client.js +0 -0
  203. /package/{lib → src}/Socket/Client/index.js +0 -0
  204. /package/{lib → src}/Store/index.js +0 -0
  205. /package/{lib → src}/Store/make-ordered-dictionary.js +0 -0
  206. /package/{lib → src}/Types/Auth.js +0 -0
  207. /package/{lib → src}/Types/Call.js +0 -0
  208. /package/{lib → src}/Types/Chat.js +0 -0
  209. /package/{lib → src}/Types/Contact.js +0 -0
  210. /package/{lib → src}/Types/Events.js +0 -0
  211. /package/{lib → src}/Types/GroupMetadata.js +0 -0
  212. /package/{lib → src}/Types/Message.js +0 -0
  213. /package/{lib → src}/Types/Product.js +0 -0
  214. /package/{lib → src}/Types/Signal.js +0 -0
  215. /package/{lib → src}/Types/Socket.js +0 -0
  216. /package/{lib → src}/Types/State.js +0 -0
  217. /package/{lib → src}/Utils/index.js +0 -0
  218. /package/{lib → src}/Utils/logger.js +0 -0
  219. /package/{lib → src}/Utils/lt-hash.js +0 -0
  220. /package/{lib → src}/WABinary/constants.js +0 -0
  221. /package/{lib → src}/WABinary/index.js +0 -0
  222. /package/{lib → src}/WABinary/types.js +0 -0
@@ -1,9 +1,19 @@
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
  };
5
14
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.initAuthCreds = exports.addTransactionCapability = exports.makeCacheableSignalKeyStore = void 0;
15
+ exports.initAuthCreds = exports.addTransactionCapability = void 0;
16
+ exports.makeCacheableSignalKeyStore = makeCacheableSignalKeyStore;
7
17
  const crypto_1 = require("crypto");
8
18
  const node_cache_1 = __importDefault(require("node-cache"));
9
19
  const uuid_1 = require("uuid");
@@ -18,7 +28,7 @@ const generics_1 = require("./generics");
18
28
  */
19
29
  function makeCacheableSignalKeyStore(store, logger, _cache) {
20
30
  const cache = _cache || new node_cache_1.default({
21
- stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.SIGNAL_STORE,
31
+ stdTTL: Defaults_1.DEFAULT_CACHE_TTLS.SIGNAL_STORE, // 5 minutes
22
32
  useClones: false,
23
33
  deleteOnExpire: true,
24
34
  });
@@ -26,50 +36,55 @@ function makeCacheableSignalKeyStore(store, logger, _cache) {
26
36
  return `${type}.${id}`;
27
37
  }
28
38
  return {
29
- async get(type, ids) {
30
- const data = {};
31
- const idsToFetch = [];
32
- for (const id of ids) {
33
- const item = cache.get(getUniqueId(type, id));
34
- if (typeof item !== 'undefined') {
35
- data[id] = item;
36
- }
37
- else {
38
- idsToFetch.push(id);
39
- }
40
- }
41
- if (idsToFetch.length) {
42
- logger.trace({ items: idsToFetch.length }, 'loading from store');
43
- const fetched = await store.get(type, idsToFetch);
44
- for (const id of idsToFetch) {
45
- const item = fetched[id];
46
- if (item) {
39
+ get(type, ids) {
40
+ return __awaiter(this, void 0, void 0, function* () {
41
+ const data = {};
42
+ const idsToFetch = [];
43
+ for (const id of ids) {
44
+ const item = cache.get(getUniqueId(type, id));
45
+ if (typeof item !== 'undefined') {
47
46
  data[id] = item;
48
- cache.set(getUniqueId(type, id), item);
47
+ }
48
+ else {
49
+ idsToFetch.push(id);
49
50
  }
50
51
  }
51
- }
52
- return data;
52
+ if (idsToFetch.length) {
53
+ logger.trace({ items: idsToFetch.length }, 'loading from store');
54
+ const fetched = yield store.get(type, idsToFetch);
55
+ for (const id of idsToFetch) {
56
+ const item = fetched[id];
57
+ if (item) {
58
+ data[id] = item;
59
+ cache.set(getUniqueId(type, id), item);
60
+ }
61
+ }
62
+ }
63
+ return data;
64
+ });
53
65
  },
54
- async set(data) {
55
- let keys = 0;
56
- for (const type in data) {
57
- for (const id in data[type]) {
58
- cache.set(getUniqueId(type, id), data[type][id]);
59
- keys += 1;
66
+ set(data) {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ let keys = 0;
69
+ for (const type in data) {
70
+ for (const id in data[type]) {
71
+ cache.set(getUniqueId(type, id), data[type][id]);
72
+ keys += 1;
73
+ }
60
74
  }
61
- }
62
- logger.trace({ keys }, 'updated cache');
63
- await store.set(data);
75
+ logger.trace({ keys }, 'updated cache');
76
+ yield store.set(data);
77
+ });
64
78
  },
65
- async clear() {
66
- var _a;
67
- cache.flushAll();
68
- await ((_a = store.clear) === null || _a === void 0 ? void 0 : _a.call(store));
79
+ clear() {
80
+ return __awaiter(this, void 0, void 0, function* () {
81
+ var _a;
82
+ cache.flushAll();
83
+ yield ((_a = store.clear) === null || _a === void 0 ? void 0 : _a.call(store));
84
+ });
69
85
  }
70
86
  };
71
87
  }
72
- exports.makeCacheableSignalKeyStore = makeCacheableSignalKeyStore;
73
88
  /**
74
89
  * Adds DB like transaction capability (https://en.wikipedia.org/wiki/Database_transaction) to the SignalKeyStore,
75
90
  * this allows batch read & write operations & improves the performance of the lib
@@ -85,7 +100,7 @@ const addTransactionCapability = (state, logger, { maxCommitRetries, delayBetwee
85
100
  let mutations = {};
86
101
  let transactionsInProgress = 0;
87
102
  return {
88
- get: async (type, ids) => {
103
+ get: (type, ids) => __awaiter(void 0, void 0, void 0, function* () {
89
104
  if (isInTransaction()) {
90
105
  const dict = transactionCache[type];
91
106
  const idsRequiringFetch = dict
@@ -94,7 +109,7 @@ const addTransactionCapability = (state, logger, { maxCommitRetries, delayBetwee
94
109
  // only fetch if there are any items to fetch
95
110
  if (idsRequiringFetch.length) {
96
111
  dbQueriesInTransaction += 1;
97
- const result = await state.get(type, idsRequiringFetch);
112
+ const result = yield state.get(type, idsRequiringFetch);
98
113
  transactionCache[type] || (transactionCache[type] = {});
99
114
  Object.assign(transactionCache[type], result);
100
115
  }
@@ -110,7 +125,7 @@ const addTransactionCapability = (state, logger, { maxCommitRetries, delayBetwee
110
125
  else {
111
126
  return state.get(type, ids);
112
127
  }
113
- },
128
+ }),
114
129
  set: data => {
115
130
  if (isInTransaction()) {
116
131
  logger.trace({ types: Object.keys(data) }, 'caching in transaction');
@@ -126,48 +141,50 @@ const addTransactionCapability = (state, logger, { maxCommitRetries, delayBetwee
126
141
  }
127
142
  },
128
143
  isInTransaction,
129
- async transaction(work) {
130
- let result;
131
- transactionsInProgress += 1;
132
- if (transactionsInProgress === 1) {
133
- logger.trace('entering transaction');
134
- }
135
- try {
136
- result = await work();
137
- // commit if this is the outermost transaction
144
+ transaction(work) {
145
+ return __awaiter(this, void 0, void 0, function* () {
146
+ let result;
147
+ transactionsInProgress += 1;
138
148
  if (transactionsInProgress === 1) {
139
- if (Object.keys(mutations).length) {
140
- logger.trace('committing transaction');
141
- // retry mechanism to ensure we've some recovery
142
- // in case a transaction fails in the first attempt
143
- let tries = maxCommitRetries;
144
- while (tries) {
145
- tries -= 1;
146
- try {
147
- await state.set(mutations);
148
- logger.trace({ dbQueriesInTransaction }, 'committed transaction');
149
- break;
150
- }
151
- catch (error) {
152
- logger.warn(`failed to commit ${Object.keys(mutations).length} mutations, tries left=${tries}`);
153
- await (0, generics_1.delay)(delayBetweenTriesMs);
149
+ logger.trace('entering transaction');
150
+ }
151
+ try {
152
+ result = yield work();
153
+ // commit if this is the outermost transaction
154
+ if (transactionsInProgress === 1) {
155
+ if (Object.keys(mutations).length) {
156
+ logger.trace('committing transaction');
157
+ // retry mechanism to ensure we've some recovery
158
+ // in case a transaction fails in the first attempt
159
+ let tries = maxCommitRetries;
160
+ while (tries) {
161
+ tries -= 1;
162
+ try {
163
+ yield state.set(mutations);
164
+ logger.trace({ dbQueriesInTransaction }, 'committed transaction');
165
+ break;
166
+ }
167
+ catch (error) {
168
+ logger.warn(`failed to commit ${Object.keys(mutations).length} mutations, tries left=${tries}`);
169
+ yield (0, generics_1.delay)(delayBetweenTriesMs);
170
+ }
154
171
  }
155
172
  }
156
- }
157
- else {
158
- logger.trace('no mutations in transaction');
173
+ else {
174
+ logger.trace('no mutations in transaction');
175
+ }
159
176
  }
160
177
  }
161
- }
162
- finally {
163
- transactionsInProgress -= 1;
164
- if (transactionsInProgress === 0) {
165
- transactionCache = {};
166
- mutations = {};
167
- dbQueriesInTransaction = 0;
178
+ finally {
179
+ transactionsInProgress -= 1;
180
+ if (transactionsInProgress === 0) {
181
+ transactionCache = {};
182
+ mutations = {};
183
+ dbQueriesInTransaction = 0;
184
+ }
168
185
  }
169
- }
170
- return result;
186
+ return result;
187
+ });
171
188
  }
172
189
  };
173
190
  function isInTransaction() {
@@ -199,6 +216,8 @@ const initAuthCreds = () => {
199
216
  backupToken: (0, crypto_1.randomBytes)(20),
200
217
  registration: {},
201
218
  pairingCode: undefined,
219
+ lastPropHash: undefined,
220
+ routingInfo: undefined,
202
221
  };
203
222
  };
204
223
  exports.initAuthCreds = initAuthCreds;
@@ -0,0 +1,222 @@
1
+ import { randomBytes } from 'crypto'
2
+ import NodeCache from 'node-cache'
3
+ import type { Logger } from 'pino'
4
+ import { v4 as uuidv4 } from 'uuid'
5
+ import { DEFAULT_CACHE_TTLS } from '../Defaults'
6
+ import type { AuthenticationCreds, CacheStore, SignalDataSet, SignalDataTypeMap, SignalKeyStore, SignalKeyStoreWithTransaction, TransactionCapabilityOptions } from '../Types'
7
+ import { Curve, signedKeyPair } from './crypto'
8
+ import { delay, generateRegistrationId } from './generics'
9
+
10
+ /**
11
+ * Adds caching capability to a SignalKeyStore
12
+ * @param store the store to add caching to
13
+ * @param logger to log trace events
14
+ * @param _cache cache store to use
15
+ */
16
+ export function makeCacheableSignalKeyStore(
17
+ store: SignalKeyStore,
18
+ logger: Logger,
19
+ _cache?: CacheStore
20
+ ): SignalKeyStore {
21
+ const cache = _cache || new NodeCache({
22
+ stdTTL: DEFAULT_CACHE_TTLS.SIGNAL_STORE, // 5 minutes
23
+ useClones: false,
24
+ deleteOnExpire: true,
25
+ })
26
+
27
+ function getUniqueId(type: string, id: string) {
28
+ return `${type}.${id}`
29
+ }
30
+
31
+ return {
32
+ async get(type, ids) {
33
+ const data: { [_: string]: SignalDataTypeMap[typeof type] } = { }
34
+ const idsToFetch: string[] = []
35
+ for(const id of ids) {
36
+ const item = cache.get<SignalDataTypeMap[typeof type]>(getUniqueId(type, id))
37
+ if(typeof item !== 'undefined') {
38
+ data[id] = item
39
+ } else {
40
+ idsToFetch.push(id)
41
+ }
42
+ }
43
+
44
+ if(idsToFetch.length) {
45
+ logger.trace({ items: idsToFetch.length }, 'loading from store')
46
+ const fetched = await store.get(type, idsToFetch)
47
+ for(const id of idsToFetch) {
48
+ const item = fetched[id]
49
+ if(item) {
50
+ data[id] = item
51
+ cache.set(getUniqueId(type, id), item)
52
+ }
53
+ }
54
+ }
55
+
56
+ return data
57
+ },
58
+ async set(data) {
59
+ let keys = 0
60
+ for(const type in data) {
61
+ for(const id in data[type]) {
62
+ cache.set(getUniqueId(type, id), data[type][id])
63
+ keys += 1
64
+ }
65
+ }
66
+
67
+ logger.trace({ keys }, 'updated cache')
68
+
69
+ await store.set(data)
70
+ },
71
+ async clear() {
72
+ cache.flushAll()
73
+ await store.clear?.()
74
+ }
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Adds DB like transaction capability (https://en.wikipedia.org/wiki/Database_transaction) to the SignalKeyStore,
80
+ * this allows batch read & write operations & improves the performance of the lib
81
+ * @param state the key store to apply this capability to
82
+ * @param logger logger to log events
83
+ * @returns SignalKeyStore with transaction capability
84
+ */
85
+ export const addTransactionCapability = (
86
+ state: SignalKeyStore,
87
+ logger: Logger,
88
+ { maxCommitRetries, delayBetweenTriesMs }: TransactionCapabilityOptions
89
+ ): SignalKeyStoreWithTransaction => {
90
+ // number of queries made to the DB during the transaction
91
+ // only there for logging purposes
92
+ let dbQueriesInTransaction = 0
93
+ let transactionCache: SignalDataSet = { }
94
+ let mutations: SignalDataSet = { }
95
+
96
+ let transactionsInProgress = 0
97
+
98
+ return {
99
+ get: async(type, ids) => {
100
+ if(isInTransaction()) {
101
+ const dict = transactionCache[type]
102
+ const idsRequiringFetch = dict
103
+ ? ids.filter(item => typeof dict[item] === 'undefined')
104
+ : ids
105
+ // only fetch if there are any items to fetch
106
+ if(idsRequiringFetch.length) {
107
+ dbQueriesInTransaction += 1
108
+ const result = await state.get(type, idsRequiringFetch)
109
+
110
+ transactionCache[type] ||= {}
111
+ Object.assign(
112
+ transactionCache[type]!,
113
+ result
114
+ )
115
+ }
116
+
117
+ return ids.reduce(
118
+ (dict, id) => {
119
+ const value = transactionCache[type]?.[id]
120
+ if(value) {
121
+ dict[id] = value
122
+ }
123
+
124
+ return dict
125
+ }, { }
126
+ )
127
+ } else {
128
+ return state.get(type, ids)
129
+ }
130
+ },
131
+ set: data => {
132
+ if(isInTransaction()) {
133
+ logger.trace({ types: Object.keys(data) }, 'caching in transaction')
134
+ for(const key in data) {
135
+ transactionCache[key] = transactionCache[key] || { }
136
+ Object.assign(transactionCache[key], data[key])
137
+
138
+ mutations[key] = mutations[key] || { }
139
+ Object.assign(mutations[key], data[key])
140
+ }
141
+ } else {
142
+ return state.set(data)
143
+ }
144
+ },
145
+ isInTransaction,
146
+ async transaction(work) {
147
+ let result: Awaited<ReturnType<typeof work>>
148
+ transactionsInProgress += 1
149
+ if(transactionsInProgress === 1) {
150
+ logger.trace('entering transaction')
151
+ }
152
+
153
+ try {
154
+ result = await work()
155
+ // commit if this is the outermost transaction
156
+ if(transactionsInProgress === 1) {
157
+ if(Object.keys(mutations).length) {
158
+ logger.trace('committing transaction')
159
+ // retry mechanism to ensure we've some recovery
160
+ // in case a transaction fails in the first attempt
161
+ let tries = maxCommitRetries
162
+ while(tries) {
163
+ tries -= 1
164
+ try {
165
+ await state.set(mutations)
166
+ logger.trace({ dbQueriesInTransaction }, 'committed transaction')
167
+ break
168
+ } catch(error) {
169
+ logger.warn(`failed to commit ${Object.keys(mutations).length} mutations, tries left=${tries}`)
170
+ await delay(delayBetweenTriesMs)
171
+ }
172
+ }
173
+ } else {
174
+ logger.trace('no mutations in transaction')
175
+ }
176
+ }
177
+ } finally {
178
+ transactionsInProgress -= 1
179
+ if(transactionsInProgress === 0) {
180
+ transactionCache = { }
181
+ mutations = { }
182
+ dbQueriesInTransaction = 0
183
+ }
184
+ }
185
+
186
+ return result
187
+ }
188
+ }
189
+
190
+ function isInTransaction() {
191
+ return transactionsInProgress > 0
192
+ }
193
+ }
194
+
195
+ export const initAuthCreds = (): AuthenticationCreds => {
196
+ const identityKey = Curve.generateKeyPair()
197
+ return {
198
+ noiseKey: Curve.generateKeyPair(),
199
+ pairingEphemeralKeyPair: Curve.generateKeyPair(),
200
+ signedIdentityKey: identityKey,
201
+ signedPreKey: signedKeyPair(identityKey, 1),
202
+ registrationId: generateRegistrationId(),
203
+ advSecretKey: randomBytes(32).toString('base64'),
204
+ processedHistoryMessages: [],
205
+ nextPreKeyId: 1,
206
+ firstUnuploadedPreKeyId: 1,
207
+ accountSyncCounter: 0,
208
+ accountSettings: {
209
+ unarchiveChats: false
210
+ },
211
+ // mobile creds
212
+ deviceId: Buffer.from(uuidv4().replace(/-/g, ''), 'hex').toString('base64url'),
213
+ phoneId: uuidv4(),
214
+ identityId: randomBytes(20),
215
+ registered: false,
216
+ backupToken: randomBytes(20),
217
+ registration: {} as never,
218
+ pairingCode: undefined,
219
+ lastPropHash: undefined,
220
+ routingInfo: undefined,
221
+ }
222
+ }
@@ -0,0 +1,92 @@
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
+ };
11
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
15
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
18
+ var __importDefault = (this && this.__importDefault) || function (mod) {
19
+ return (mod && mod.__esModule) ? mod : { "default": mod };
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.readAndEmitEventStream = exports.captureEventStream = void 0;
23
+ const events_1 = __importDefault(require("events"));
24
+ const fs_1 = require("fs");
25
+ const promises_1 = require("fs/promises");
26
+ const readline_1 = require("readline");
27
+ const generics_1 = require("./generics");
28
+ const make_mutex_1 = require("./make-mutex");
29
+ /**
30
+ * Captures events from a baileys event emitter & stores them in a file
31
+ * @param ev The event emitter to read events from
32
+ * @param filename File to save to
33
+ */
34
+ const captureEventStream = (ev, filename) => {
35
+ const oldEmit = ev.emit;
36
+ // write mutex so data is appended in order
37
+ const writeMutex = (0, make_mutex_1.makeMutex)();
38
+ // monkey patch eventemitter to capture all events
39
+ ev.emit = function (...args) {
40
+ const content = JSON.stringify({ timestamp: Date.now(), event: args[0], data: args[1] }) + '\n';
41
+ const result = oldEmit.apply(ev, args);
42
+ writeMutex.mutex(() => __awaiter(this, void 0, void 0, function* () {
43
+ yield (0, promises_1.writeFile)(filename, content, { flag: 'a' });
44
+ }));
45
+ return result;
46
+ };
47
+ };
48
+ exports.captureEventStream = captureEventStream;
49
+ /**
50
+ * Read event file and emit events from there
51
+ * @param filename filename containing event data
52
+ * @param delayIntervalMs delay between each event emit
53
+ */
54
+ const readAndEmitEventStream = (filename, delayIntervalMs = 0) => {
55
+ const ev = new events_1.default();
56
+ const fireEvents = () => __awaiter(void 0, void 0, void 0, function* () {
57
+ var _a, e_1, _b, _c;
58
+ // from: https://stackoverflow.com/questions/6156501/read-a-file-one-line-at-a-time-in-node-js
59
+ const fileStream = (0, fs_1.createReadStream)(filename);
60
+ const rl = (0, readline_1.createInterface)({
61
+ input: fileStream,
62
+ crlfDelay: Infinity
63
+ });
64
+ try {
65
+ // Note: we use the crlfDelay option to recognize all instances of CR LF
66
+ // ('\r\n') in input.txt as a single line break.
67
+ for (var _d = true, rl_1 = __asyncValues(rl), rl_1_1; rl_1_1 = yield rl_1.next(), _a = rl_1_1.done, !_a; _d = true) {
68
+ _c = rl_1_1.value;
69
+ _d = false;
70
+ const line = _c;
71
+ if (line) {
72
+ const { event, data } = JSON.parse(line);
73
+ ev.emit(event, data);
74
+ delayIntervalMs && (yield (0, generics_1.delay)(delayIntervalMs));
75
+ }
76
+ }
77
+ }
78
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
79
+ finally {
80
+ try {
81
+ if (!_d && !_a && (_b = rl_1.return)) yield _b.call(rl_1);
82
+ }
83
+ finally { if (e_1) throw e_1.error; }
84
+ }
85
+ fileStream.close();
86
+ });
87
+ return {
88
+ ev,
89
+ task: fireEvents()
90
+ };
91
+ };
92
+ exports.readAndEmitEventStream = readAndEmitEventStream;
@@ -0,0 +1,66 @@
1
+ import EventEmitter from 'events'
2
+ import { createReadStream } from 'fs'
3
+ import { writeFile } from 'fs/promises'
4
+ import { createInterface } from 'readline'
5
+ import type { BaileysEventEmitter } from '../Types'
6
+ import { delay } from './generics'
7
+ import { makeMutex } from './make-mutex'
8
+
9
+ /**
10
+ * Captures events from a baileys event emitter & stores them in a file
11
+ * @param ev The event emitter to read events from
12
+ * @param filename File to save to
13
+ */
14
+ export const captureEventStream = (ev: BaileysEventEmitter, filename: string) => {
15
+ const oldEmit = ev.emit
16
+ // write mutex so data is appended in order
17
+ const writeMutex = makeMutex()
18
+ // monkey patch eventemitter to capture all events
19
+ ev.emit = function(...args: any[]) {
20
+ const content = JSON.stringify({ timestamp: Date.now(), event: args[0], data: args[1] }) + '\n'
21
+ const result = oldEmit.apply(ev, args)
22
+
23
+ writeMutex.mutex(
24
+ async() => {
25
+ await writeFile(filename, content, { flag: 'a' })
26
+ }
27
+ )
28
+
29
+ return result
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Read event file and emit events from there
35
+ * @param filename filename containing event data
36
+ * @param delayIntervalMs delay between each event emit
37
+ */
38
+ export const readAndEmitEventStream = (filename: string, delayIntervalMs: number = 0) => {
39
+ const ev = new EventEmitter() as BaileysEventEmitter
40
+
41
+ const fireEvents = async() => {
42
+ // from: https://stackoverflow.com/questions/6156501/read-a-file-one-line-at-a-time-in-node-js
43
+ const fileStream = createReadStream(filename)
44
+
45
+ const rl = createInterface({
46
+ input: fileStream,
47
+ crlfDelay: Infinity
48
+ })
49
+ // Note: we use the crlfDelay option to recognize all instances of CR LF
50
+ // ('\r\n') in input.txt as a single line break.
51
+ for await (const line of rl) {
52
+ if(line) {
53
+ const { event, data } = JSON.parse(line)
54
+ ev.emit(event, data)
55
+ delayIntervalMs && await delay(delayIntervalMs)
56
+ }
57
+ }
58
+
59
+ fileStream.close()
60
+ }
61
+
62
+ return {
63
+ ev,
64
+ task: fireEvents()
65
+ }
66
+ }