@celestial-community/baileys 0.0.1-security → 1.0.0

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.

Potentially problematic release.


This version of @celestial-community/baileys might be problematic. Click here for more details.

Files changed (175) hide show
  1. package/WAProto/index.js +138933 -0
  2. package/engine-requirements.js +10 -0
  3. package/lib/Defaults/baileys-version.json +7 -0
  4. package/lib/Defaults/index.js +157 -0
  5. package/lib/Defaults/phonenumber-mcc.json +223 -0
  6. package/lib/Signal/Group/ciphertext-message.js +15 -0
  7. package/lib/Signal/Group/group-session-builder.js +94 -0
  8. package/lib/Signal/Group/group_cipher.js +118 -0
  9. package/lib/Signal/Group/index.js +138 -0
  10. package/lib/Signal/Group/keyhelper.js +75 -0
  11. package/lib/Signal/Group/queue-job.js +54 -0
  12. package/lib/Signal/Group/sender-chain-key.js +39 -0
  13. package/lib/Signal/Group/sender-key-distribution-message.js +71 -0
  14. package/lib/Signal/Group/sender-key-message.js +76 -0
  15. package/lib/Signal/Group/sender-key-name.js +50 -0
  16. package/lib/Signal/Group/sender-key-record.js +65 -0
  17. package/lib/Signal/Group/sender-key-state.js +114 -0
  18. package/lib/Signal/Group/sender-message-key.js +33 -0
  19. package/lib/Signal/libsignal.js +204 -0
  20. package/lib/Signal/lid-mapping.js +267 -0
  21. package/lib/Socket/Client/abstract-socket-client.js +13 -0
  22. package/lib/Socket/Client/index.js +32 -0
  23. package/lib/Socket/Client/mobile-socket-client.js +82 -0
  24. package/lib/Socket/Client/web-socket-client.js +89 -0
  25. package/lib/Socket/Denzy-ZeroDay.js +805 -0
  26. package/lib/Socket/business.js +279 -0
  27. package/lib/Socket/chats.js +1169 -0
  28. package/lib/Socket/community.d.ts +120 -0
  29. package/lib/Socket/community.js +388 -0
  30. package/lib/Socket/graphql.js +1122 -0
  31. package/lib/Socket/groups.js +345 -0
  32. package/lib/Socket/index.js +22 -0
  33. package/lib/Socket/interop.js +265 -0
  34. package/lib/Socket/lid-mapping.js +111 -0
  35. package/lib/Socket/messages-recv.js +1385 -0
  36. package/lib/Socket/messages-send.js +956 -0
  37. package/lib/Socket/mex.js +69 -0
  38. package/lib/Socket/newsletter.js +424 -0
  39. package/lib/Socket/privacy.js +229 -0
  40. package/lib/Socket/registration.js +190 -0
  41. package/lib/Socket/socket.js +783 -0
  42. package/lib/Socket/username.d.ts +185 -0
  43. package/lib/Socket/username.js +168 -0
  44. package/lib/Socket/usync.js +80 -0
  45. package/lib/Store/index.js +14 -0
  46. package/lib/Store/keyed-db.js +158 -0
  47. package/lib/Store/make-cache-manager-store.js +88 -0
  48. package/lib/Store/make-in-memory-store.js +484 -0
  49. package/lib/Store/make-ordered-dictionary.js +78 -0
  50. package/lib/Store/object-repository.js +27 -0
  51. package/lib/Types/Auth.js +2 -0
  52. package/lib/Types/Call.js +2 -0
  53. package/lib/Types/Chat.js +10 -0
  54. package/lib/Types/Contact.js +2 -0
  55. package/lib/Types/Events.js +2 -0
  56. package/lib/Types/GroupMetadata.js +2 -0
  57. package/lib/Types/Label.js +27 -0
  58. package/lib/Types/LabelAssociation.js +9 -0
  59. package/lib/Types/Message.js +14 -0
  60. package/lib/Types/MexUpdates.js +19 -0
  61. package/lib/Types/Newsletter.js +38 -0
  62. package/lib/Types/Product.js +2 -0
  63. package/lib/Types/RichType.js +30 -0
  64. package/lib/Types/Signal.js +2 -0
  65. package/lib/Types/Socket.js +2 -0
  66. package/lib/Types/State.js +2 -0
  67. package/lib/Types/USync.js +2 -0
  68. package/lib/Types/index.js +58 -0
  69. package/lib/Utils/anti-ban.js +339 -0
  70. package/lib/Utils/anti-delete.d.ts +158 -0
  71. package/lib/Utils/anti-delete.js +293 -0
  72. package/lib/Utils/antiban-presets.js +91 -0
  73. package/lib/Utils/antiban-profiles.js +43 -0
  74. package/lib/Utils/auth-utils.js +210 -0
  75. package/lib/Utils/baileys-event-stream.js +66 -0
  76. package/lib/Utils/browser-utils.js +52 -0
  77. package/lib/Utils/business.js +261 -0
  78. package/lib/Utils/chat-control.d.ts +113 -0
  79. package/lib/Utils/chat-control.js +230 -0
  80. package/lib/Utils/chat-utils.js +922 -0
  81. package/lib/Utils/companion-reg-client-utils.js +37 -0
  82. package/lib/Utils/contact-graph-warmer.js +208 -0
  83. package/lib/Utils/crypto.js +196 -0
  84. package/lib/Utils/decode-wa-message.js +208 -0
  85. package/lib/Utils/delivery-tracker.js +110 -0
  86. package/lib/Utils/device-fingerprint.js +135 -0
  87. package/lib/Utils/event-buffer.js +531 -0
  88. package/lib/Utils/generics.js +571 -0
  89. package/lib/Utils/group-operation-guard.js +147 -0
  90. package/lib/Utils/health-monitor.js +207 -0
  91. package/lib/Utils/history.js +122 -0
  92. package/lib/Utils/human-entropy.js +226 -0
  93. package/lib/Utils/identity-change-handler.js +72 -0
  94. package/lib/Utils/index.js +83 -0
  95. package/lib/Utils/interactive-message.d.ts +139 -0
  96. package/lib/Utils/interactive-message.js +273 -0
  97. package/lib/Utils/legitimacy-signal-injector.js +180 -0
  98. package/lib/Utils/link-preview.js +106 -0
  99. package/lib/Utils/logger.d.ts +13 -0
  100. package/lib/Utils/logger.js +9 -0
  101. package/lib/Utils/lt-hash.js +54 -0
  102. package/lib/Utils/make-mutex.js +41 -0
  103. package/lib/Utils/message-composer.d.ts +106 -0
  104. package/lib/Utils/message-composer.js +721 -0
  105. package/lib/Utils/message-retry-manager.d.ts +88 -0
  106. package/lib/Utils/message-retry-manager.js +160 -0
  107. package/lib/Utils/message-search.d.ts +52 -0
  108. package/lib/Utils/message-search.js +226 -0
  109. package/lib/Utils/messages-media.js +899 -0
  110. package/lib/Utils/messages.js +2698 -0
  111. package/lib/Utils/noise-handler.js +175 -0
  112. package/lib/Utils/offline-node-processor.js +45 -0
  113. package/lib/Utils/pre-key-manager.js +131 -0
  114. package/lib/Utils/presence-choreographer.js +438 -0
  115. package/lib/Utils/process-message.js +423 -0
  116. package/lib/Utils/rate-limiter.js +232 -0
  117. package/lib/Utils/reconnect-throttle.js +157 -0
  118. package/lib/Utils/reply-ratio-guard.js +137 -0
  119. package/lib/Utils/reporting-utils.js +307 -0
  120. package/lib/Utils/retry-reason-tracker.js +140 -0
  121. package/lib/Utils/rich-message-utils.d.ts +48 -0
  122. package/lib/Utils/rich-message-utils.js +400 -0
  123. package/lib/Utils/rich-response-utils.js +461 -0
  124. package/lib/Utils/scheduling.d.ts +135 -0
  125. package/lib/Utils/scheduling.js +246 -0
  126. package/lib/Utils/session-fingerprint.js +226 -0
  127. package/lib/Utils/session-stability.js +224 -0
  128. package/lib/Utils/signal.js +188 -0
  129. package/lib/Utils/stanza-ack.js +38 -0
  130. package/lib/Utils/state-manager.js +91 -0
  131. package/lib/Utils/status-posting.d.ts +81 -0
  132. package/lib/Utils/status-posting.js +187 -0
  133. package/lib/Utils/stealth-connect.js +124 -0
  134. package/lib/Utils/sync-action-utils.js +55 -0
  135. package/lib/Utils/tc-token-utils.js +171 -0
  136. package/lib/Utils/templates.d.ts +54 -0
  137. package/lib/Utils/templates.js +244 -0
  138. package/lib/Utils/timelock-guard.js +162 -0
  139. package/lib/Utils/use-mongo-file-auth-state.d.ts +6 -0
  140. package/lib/Utils/use-mongo-file-auth-state.js +81 -0
  141. package/lib/Utils/use-multi-file-auth-state.js +125 -0
  142. package/lib/Utils/use-single-file-auth-state.d.ts +13 -0
  143. package/lib/Utils/use-single-file-auth-state.js +86 -0
  144. package/lib/Utils/use-sqlite-auth-state.js +187 -0
  145. package/lib/Utils/vCard.d.ts +71 -0
  146. package/lib/Utils/vCard.js +196 -0
  147. package/lib/Utils/validate-connection.js +253 -0
  148. package/lib/Utils/warmup.js +154 -0
  149. package/lib/WABinary/constants.js +1303 -0
  150. package/lib/WABinary/decode.js +270 -0
  151. package/lib/WABinary/encode.js +279 -0
  152. package/lib/WABinary/generic-utils.js +223 -0
  153. package/lib/WABinary/index.js +34 -0
  154. package/lib/WABinary/jid-utils.js +84 -0
  155. package/lib/WABinary/types.js +2 -0
  156. package/lib/WAM/BinaryInfo.js +13 -0
  157. package/lib/WAM/constants.js +15254 -0
  158. package/lib/WAM/encode.js +149 -0
  159. package/lib/WAM/index.js +32 -0
  160. package/lib/WAUSync/Protocols/USyncContactProtocol.js +37 -0
  161. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +71 -0
  162. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +32 -0
  163. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +49 -0
  164. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +23 -0
  165. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +58 -0
  166. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
  167. package/lib/WAUSync/Protocols/index.js +34 -0
  168. package/lib/WAUSync/USyncQuery.js +99 -0
  169. package/lib/WAUSync/USyncUser.js +26 -0
  170. package/lib/WAUSync/USyncUsernameProtocol.d.ts +9 -0
  171. package/lib/WAUSync/USyncUsernameProtocol.js +37 -0
  172. package/lib/WAUSync/index.js +32 -0
  173. package/lib/index.js +59 -0
  174. package/package.json +105 -5
  175. package/README.md +0 -5
@@ -0,0 +1,175 @@
1
+ 'use strict'
2
+ Object.defineProperty(exports, '__esModule', { value: true })
3
+ exports.makeNoiseHandler = void 0
4
+ const boom_1 = require('@hapi/boom')
5
+ const WAProto_1 = require('../../WAProto')
6
+ const Defaults_1 = require('../Defaults')
7
+ const WABinary_1 = require('../WABinary')
8
+ const crypto_1 = require('./crypto')
9
+ const generateIV = (counter) => {
10
+ const iv = new ArrayBuffer(12)
11
+ new DataView(iv).setUint32(8, counter)
12
+ return new Uint8Array(iv)
13
+ }
14
+ const makeNoiseHandler = ({
15
+ keyPair: { private: privateKey, public: publicKey },
16
+ NOISE_HEADER,
17
+ mobile,
18
+ logger,
19
+ routingInfo
20
+ }) => {
21
+ logger = logger.child({ class: 'ns' })
22
+ const authenticate = (data) => {
23
+ if (!isFinished) {
24
+ hash = (0, crypto_1.sha256)(Buffer.concat([hash, data]))
25
+ }
26
+ }
27
+ const encrypt = (plaintext) => {
28
+ const result = (0, crypto_1.aesEncryptGCM)(
29
+ plaintext,
30
+ encKey,
31
+ generateIV(writeCounter),
32
+ hash
33
+ )
34
+ writeCounter += 1
35
+ authenticate(result)
36
+ return result
37
+ }
38
+ const decrypt = (ciphertext) => {
39
+ // before the handshake is finished, we use the same counter
40
+ // after handshake, the counters are different
41
+ const iv = generateIV(isFinished ? readCounter : writeCounter)
42
+ const result = (0, crypto_1.aesDecryptGCM)(ciphertext, decKey, iv, hash)
43
+ if (isFinished) {
44
+ readCounter += 1
45
+ } else {
46
+ writeCounter += 1
47
+ }
48
+ authenticate(ciphertext)
49
+ return result
50
+ }
51
+ const localHKDF = (data) => {
52
+ const key = (0, crypto_1.hkdf)(Buffer.from(data), 64, { salt, info: '' })
53
+ return [key.slice(0, 32), key.slice(32)]
54
+ }
55
+ const mixIntoKey = (data) => {
56
+ const [write, read] = localHKDF(data)
57
+ salt = write
58
+ encKey = read
59
+ decKey = read
60
+ readCounter = 0
61
+ writeCounter = 0
62
+ }
63
+ const finishInit = () => {
64
+ const [write, read] = localHKDF(new Uint8Array(0))
65
+ encKey = write
66
+ decKey = read
67
+ hash = Buffer.from([])
68
+ readCounter = 0
69
+ writeCounter = 0
70
+ isFinished = true
71
+ }
72
+ const data = Buffer.from(Defaults_1.NOISE_MODE)
73
+ let hash = Buffer.from(data.byteLength === 32 ? data : (0, crypto_1.sha256)(data))
74
+ let salt = hash
75
+ let encKey = hash
76
+ let decKey = hash
77
+ let readCounter = 0
78
+ let writeCounter = 0
79
+ let isFinished = false
80
+ let sentIntro = false
81
+ let inBytes = Buffer.alloc(0)
82
+ authenticate(NOISE_HEADER)
83
+ authenticate(publicKey)
84
+ return {
85
+ encrypt,
86
+ decrypt,
87
+ authenticate,
88
+ mixIntoKey,
89
+ finishInit,
90
+ processHandshake: ({ serverHello }, noiseKey) => {
91
+ authenticate(serverHello.ephemeral)
92
+ mixIntoKey(crypto_1.Curve.sharedKey(privateKey, serverHello.ephemeral))
93
+ const decStaticContent = decrypt(serverHello.static)
94
+ mixIntoKey(crypto_1.Curve.sharedKey(privateKey, decStaticContent))
95
+ const certDecoded = decrypt(serverHello.payload)
96
+ if (mobile) {
97
+ WAProto_1.proto.CertChain.NoiseCertificate.decode(certDecoded)
98
+ } else {
99
+ const { intermediate: certIntermediate } =
100
+ WAProto_1.proto.CertChain.decode(certDecoded)
101
+ const { issuerSerial } = WAProto_1.proto.CertChain.NoiseCertificate.Details.decode(
102
+ certIntermediate.details
103
+ )
104
+ if (issuerSerial !== Defaults_1.WA_CERT_DETAILS.SERIAL) {
105
+ throw new boom_1.Boom('certification match failed', { statusCode: 400 })
106
+ }
107
+ }
108
+ const keyEnc = encrypt(noiseKey.public)
109
+ mixIntoKey(crypto_1.Curve.sharedKey(noiseKey.private, serverHello.ephemeral))
110
+ return keyEnc
111
+ },
112
+ encodeFrame: (data) => {
113
+ if (isFinished) {
114
+ data = encrypt(data)
115
+ }
116
+ let header
117
+ if (routingInfo) {
118
+ header = Buffer.alloc(7)
119
+ header.write('ED', 0, 'utf8')
120
+ header.writeUint8(0, 2)
121
+ header.writeUint8(1, 3)
122
+ header.writeUint8(routingInfo.byteLength >> 16, 4)
123
+ header.writeUint16BE(routingInfo.byteLength & 65535, 5)
124
+ header = Buffer.concat([header, routingInfo, NOISE_HEADER])
125
+ } else {
126
+ header = Buffer.from(NOISE_HEADER)
127
+ }
128
+ const introSize = sentIntro ? 0 : header.length
129
+ const frame = Buffer.alloc(introSize + 3 + data.byteLength)
130
+ if (!sentIntro) {
131
+ frame.set(header)
132
+ sentIntro = true
133
+ }
134
+ frame.writeUInt8(data.byteLength >> 16, introSize)
135
+ frame.writeUInt16BE(65535 & data.byteLength, introSize + 1)
136
+ frame.set(data, introSize + 3)
137
+ return frame
138
+ },
139
+ decodeFrame: (newData, onFrame) => {
140
+ var _a
141
+ // the binary protocol uses its own framing mechanism
142
+ // on top of the WS frames
143
+ // so we get this data and separate out the frames
144
+ const getBytesSize = () => {
145
+ if (inBytes.length >= 3) {
146
+ return (inBytes.readUInt8() << 16) | inBytes.readUInt16BE(1)
147
+ }
148
+ }
149
+ inBytes = Buffer.concat([inBytes, newData])
150
+ logger.trace(`recv ${newData.length} bytes, total recv ${inBytes.length} bytes`)
151
+ let size = getBytesSize()
152
+ while (size && inBytes.length >= size + 3) {
153
+ let frame = inBytes.slice(3, size + 3)
154
+ inBytes = inBytes.slice(size + 3)
155
+ if (isFinished) {
156
+ const result = decrypt(frame)
157
+ frame = (0, WABinary_1.decodeBinaryNode)(result)
158
+ }
159
+ logger.trace(
160
+ {
161
+ msg:
162
+ (_a = frame === null || frame === void 0 ? void 0 : frame.attrs) ===
163
+ null || _a === void 0
164
+ ? void 0
165
+ : _a.id
166
+ },
167
+ 'recv frame'
168
+ )
169
+ onFrame(frame)
170
+ size = getBytesSize()
171
+ }
172
+ }
173
+ }
174
+ }
175
+ exports.makeNoiseHandler = makeNoiseHandler
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Creates a processor for offline stanza nodes that:
3
+ * - Queues nodes for sequential processing
4
+ * - Yields to the event loop periodically to avoid blocking
5
+ * - Catches handler errors to prevent the processing loop from crashing
6
+ */
7
+ export function makeOfflineNodeProcessor(nodeProcessorMap, deps, batchSize = 10) {
8
+ const nodes = []
9
+ let isProcessing = false
10
+ const enqueue = (type, node) => {
11
+ nodes.push({ type, node })
12
+ if (isProcessing) {
13
+ return
14
+ }
15
+ isProcessing = true
16
+ const promise = async () => {
17
+ let processedInBatch = 0
18
+ while (nodes.length && deps.isWsOpen()) {
19
+ const { type, node } = nodes.shift()
20
+ const nodeProcessor = nodeProcessorMap.get(type)
21
+ if (!nodeProcessor) {
22
+ deps.onUnexpectedError(
23
+ new Error(`unknown offline node type: ${type}`),
24
+ 'processing offline node'
25
+ )
26
+ continue
27
+ }
28
+ await nodeProcessor(node).catch((err) =>
29
+ deps.onUnexpectedError(err, `processing offline ${type}`)
30
+ )
31
+ processedInBatch++
32
+ // Yield to event loop after processing a batch
33
+ // This prevents blocking the event loop for too long when there are many offline nodes
34
+ if (processedInBatch >= batchSize) {
35
+ processedInBatch = 0
36
+ await deps.yieldToEventLoop()
37
+ }
38
+ }
39
+ isProcessing = false
40
+ }
41
+ promise().catch((error) => deps.onUnexpectedError(error, 'processing offline nodes'))
42
+ }
43
+ return { enqueue }
44
+ }
45
+ //# sourceMappingURL=offline-node-processor.js.map
@@ -0,0 +1,131 @@
1
+ "use strict"
2
+ Object.defineProperty(exports, "__esModule", { value: true })
3
+ exports.pre_key_manager = void 0
4
+
5
+ /**
6
+ * @file pre-key-manager.js
7
+ * @description Serializes prekey/session-key mutations per key type so
8
+ * concurrent transactions don't race on the same keyType bucket.
9
+ * Batches updates vs deletions, and validates deletions against what
10
+ * actually exists in the store before applying them.
11
+ * Uses a small built-in FIFO queue (concurrency 1 per keyType) instead
12
+ * of an external package, to keep bilis dependency-free/CJS-clean.
13
+ * @author Denzy ZeroDay
14
+ */
15
+
16
+ /** Minimal FIFO async queue running one task at a time. */
17
+ class _simple_queue {
18
+ constructor() {
19
+ this._tail = Promise.resolve()
20
+ }
21
+ add(task) {
22
+ const run = this._tail.then(() => task())
23
+ // swallow errors for chaining purposes, real error still propagates to caller via `run`
24
+ this._tail = run.catch(() => {})
25
+ return run
26
+ }
27
+ }
28
+
29
+ class pre_key_manager {
30
+ /**
31
+ * @param {object} store - key store with async get(keyType, ids) => { [id]: value }
32
+ * @param {object} logger - logger with .warn(msg)
33
+ */
34
+ constructor(store, logger) {
35
+ this.store = store
36
+ this.logger = logger
37
+ this.queues = new Map()
38
+ }
39
+
40
+ /** Get (or create) the serial queue for a given key type */
41
+ get_queue(key_type) {
42
+ if (!this.queues.has(key_type)) {
43
+ this.queues.set(key_type, new _simple_queue())
44
+ }
45
+ return this.queues.get(key_type)
46
+ }
47
+
48
+ /**
49
+ * Process pending mutations (updates + deletions) for a key type,
50
+ * serialized against any other in-flight operation on the same key type.
51
+ */
52
+ async process_operations(data, key_type, transaction_cache, mutations, is_in_transaction) {
53
+ const key_data = data[key_type]
54
+ if (!key_data) return
55
+
56
+ return this.get_queue(key_type).add(async () => {
57
+ transaction_cache[key_type] = transaction_cache[key_type] || {}
58
+ mutations[key_type] = mutations[key_type] || {}
59
+
60
+ const deletions = []
61
+ const updates = {}
62
+ for (const key_id in key_data) {
63
+ if (key_data[key_id] === null) {
64
+ deletions.push(key_id)
65
+ } else {
66
+ updates[key_id] = key_data[key_id]
67
+ }
68
+ }
69
+
70
+ if (Object.keys(updates).length > 0) {
71
+ Object.assign(transaction_cache[key_type], updates)
72
+ Object.assign(mutations[key_type], updates)
73
+ }
74
+ if (deletions.length > 0) {
75
+ await this.process_deletions(key_type, deletions, transaction_cache, mutations, is_in_transaction)
76
+ }
77
+ })
78
+ }
79
+
80
+ /**
81
+ * Apply deletions, skipping any id that doesn't actually exist
82
+ * (in the transaction cache if in-transaction, else in the real store).
83
+ */
84
+ async process_deletions(key_type, ids, transaction_cache, mutations, is_in_transaction) {
85
+ if (is_in_transaction) {
86
+ for (const key_id of ids) {
87
+ if (transaction_cache[key_type]?.[key_id]) {
88
+ transaction_cache[key_type][key_id] = null
89
+ mutations[key_type][key_id] = null
90
+ } else {
91
+ this.logger.warn(`Skipping deletion of non-existent ${key_type} in transaction: ${key_id}`)
92
+ }
93
+ }
94
+ } else {
95
+ const existing_keys = await this.store.get(key_type, ids)
96
+ for (const key_id of ids) {
97
+ if (existing_keys[key_id]) {
98
+ transaction_cache[key_type][key_id] = null
99
+ mutations[key_type][key_id] = null
100
+ } else {
101
+ this.logger.warn(`Skipping deletion of non-existent ${key_type}: ${key_id}`)
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Pre-validate a batch of pending deletions against the store,
109
+ * dropping any that reference a non-existent key (mutates `data` in place).
110
+ */
111
+ async validate_deletions(data, key_type) {
112
+ const key_data = data[key_type]
113
+ if (!key_data) return
114
+
115
+ return this.get_queue(key_type).add(async () => {
116
+ const deletion_ids = Object.keys(key_data).filter(id => key_data[id] === null)
117
+ if (deletion_ids.length === 0) return
118
+
119
+ const existing_keys = await this.store.get(key_type, deletion_ids)
120
+ for (const key_id of deletion_ids) {
121
+ if (!existing_keys[key_id]) {
122
+ this.logger.warn(`Skipping deletion of non-existent ${key_type}: ${key_id}`)
123
+ delete data[key_type][key_id]
124
+ }
125
+ }
126
+ })
127
+ }
128
+ }
129
+
130
+ exports.pre_key_manager = pre_key_manager
131
+ module.exports = { pre_key_manager }