@zapo-js/fake-server 0.3.0 → 1.1.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.
Files changed (301) hide show
  1. package/README.md +96 -8
  2. package/dist/api/AppStateSyncManager.d.ts +0 -1
  3. package/dist/api/AppStateSyncManager.js +0 -1
  4. package/dist/api/FakePairingDriver.d.ts +0 -1
  5. package/dist/api/FakePairingDriver.js +0 -1
  6. package/dist/api/FakePeer.d.ts +77 -4
  7. package/dist/api/FakePeer.js +208 -2
  8. package/dist/api/FakeServerSession.d.ts +67 -0
  9. package/dist/api/FakeServerSession.js +293 -0
  10. package/dist/api/FakeWaServer.d.ts +77 -31
  11. package/dist/api/FakeWaServer.js +140 -259
  12. package/dist/api/PreKeyDispenser.d.ts +0 -1
  13. package/dist/api/PreKeyDispenser.js +0 -1
  14. package/dist/api/Scenario.d.ts +0 -1
  15. package/dist/api/Scenario.js +0 -1
  16. package/dist/api/ServerRegistries.d.ts +0 -1
  17. package/dist/api/ServerRegistries.js +0 -1
  18. package/dist/api/iq-handlers.d.ts +1 -1
  19. package/dist/api/iq-handlers.js +23 -1
  20. package/dist/{cli.d.ts → bin.d.ts} +0 -1
  21. package/dist/bin.js +296 -0
  22. package/dist/esm/api/AppStateSyncManager.js +146 -0
  23. package/dist/esm/api/FakePairingDriver.js +31 -0
  24. package/dist/esm/api/FakePeer.js +610 -0
  25. package/dist/esm/api/FakeServerSession.js +287 -0
  26. package/dist/esm/api/FakeWaServer.js +528 -0
  27. package/dist/esm/api/PreKeyDispenser.js +93 -0
  28. package/dist/esm/api/Scenario.js +32 -0
  29. package/dist/esm/api/ServerRegistries.js +261 -0
  30. package/dist/esm/api/iq-handlers.js +515 -0
  31. package/dist/{cli.js → esm/bin.js} +70 -25
  32. package/dist/esm/index.js +26 -0
  33. package/dist/esm/infra/WaFakeConnection.js +49 -0
  34. package/dist/esm/infra/WaFakeConnectionPipeline.js +235 -0
  35. package/dist/esm/infra/WaFakeFrameSocket.js +117 -0
  36. package/dist/esm/infra/WaFakeMediaHttpsServer.js +126 -0
  37. package/dist/esm/infra/WaFakeNoiseHandshake.js +67 -0
  38. package/dist/esm/infra/WaFakeTransport.js +31 -0
  39. package/dist/esm/infra/WaFakeWsServer.js +96 -0
  40. package/dist/esm/package.json +3 -0
  41. package/dist/esm/protocol/auth/cert-chain.js +50 -0
  42. package/dist/esm/protocol/auth/client-payload-validate.js +55 -0
  43. package/dist/esm/protocol/auth/fake-primary-device.js +47 -0
  44. package/dist/esm/protocol/auth/pair-device.js +87 -0
  45. package/dist/esm/protocol/auth/success-node.js +26 -0
  46. package/dist/esm/protocol/iq/abprops.js +30 -0
  47. package/dist/esm/protocol/iq/appstate-sync.js +146 -0
  48. package/dist/esm/protocol/iq/business.js +59 -0
  49. package/dist/esm/protocol/iq/dirty-bits.js +19 -0
  50. package/dist/esm/protocol/iq/group-ops.js +154 -0
  51. package/dist/esm/protocol/iq/newsletter.js +14 -0
  52. package/dist/esm/protocol/iq/prekey-fetch.js +88 -0
  53. package/dist/esm/protocol/iq/privacy-token.js +26 -0
  54. package/dist/esm/protocol/iq/privacy.js +123 -0
  55. package/dist/esm/protocol/iq/profile.js +72 -0
  56. package/dist/esm/protocol/iq/router.js +117 -0
  57. package/dist/esm/protocol/iq/usync.js +64 -0
  58. package/dist/esm/protocol/push/app-state-key-share.js +26 -0
  59. package/dist/esm/protocol/push/call-failure.js +27 -0
  60. package/dist/esm/protocol/push/chatstate.js +23 -0
  61. package/dist/esm/protocol/push/error-stanza.js +13 -0
  62. package/dist/esm/protocol/push/history-sync.js +111 -0
  63. package/dist/esm/protocol/push/message.js +38 -0
  64. package/dist/esm/protocol/push/notification.js +29 -0
  65. package/dist/esm/protocol/push/presence.js +14 -0
  66. package/dist/esm/protocol/push/receipt.js +21 -0
  67. package/dist/esm/protocol/signal/fake-app-state-crypto.js +196 -0
  68. package/dist/esm/protocol/signal/fake-peer-double-ratchet.js +398 -0
  69. package/dist/esm/protocol/signal/fake-peer-group-recv-session.js +120 -0
  70. package/dist/esm/protocol/signal/fake-peer-identity.js +8 -0
  71. package/dist/esm/protocol/signal/fake-peer-key-bundle.js +25 -0
  72. package/dist/esm/protocol/signal/fake-sender-key.js +83 -0
  73. package/dist/esm/protocol/signal/prekey-upload.js +107 -0
  74. package/dist/esm/protocol/stream/stream-error.js +56 -0
  75. package/dist/esm/state/fake-app-state-collection.js +134 -0
  76. package/dist/esm/state/fake-media-store.js +53 -0
  77. package/dist/esm/transport/codec.js +8 -0
  78. package/dist/esm/transport/crypto.js +8 -0
  79. package/dist/esm/transport/protos.js +7 -0
  80. package/dist/esm/transport/util.js +8 -0
  81. package/dist/index.d.ts +2 -3
  82. package/dist/index.js +2 -2
  83. package/dist/infra/WaFakeConnection.d.ts +0 -1
  84. package/dist/infra/WaFakeConnection.js +0 -1
  85. package/dist/infra/WaFakeConnectionPipeline.d.ts +10 -3
  86. package/dist/infra/WaFakeConnectionPipeline.js +47 -32
  87. package/dist/infra/WaFakeFrameSocket.d.ts +0 -1
  88. package/dist/infra/WaFakeFrameSocket.js +0 -1
  89. package/dist/infra/WaFakeMediaHttpsServer.d.ts +0 -1
  90. package/dist/infra/WaFakeMediaHttpsServer.js +0 -1
  91. package/dist/infra/WaFakeNoiseHandshake.d.ts +8 -10
  92. package/dist/infra/WaFakeNoiseHandshake.js +19 -24
  93. package/dist/infra/WaFakeTransport.d.ts +2 -4
  94. package/dist/infra/WaFakeTransport.js +2 -1
  95. package/dist/infra/WaFakeWsServer.d.ts +0 -1
  96. package/dist/infra/WaFakeWsServer.js +0 -1
  97. package/dist/protocol/auth/cert-chain.d.ts +4 -1
  98. package/dist/protocol/auth/cert-chain.js +13 -3
  99. package/dist/protocol/auth/client-payload-validate.d.ts +0 -1
  100. package/dist/protocol/auth/client-payload-validate.js +0 -1
  101. package/dist/protocol/auth/fake-primary-device.d.ts +0 -1
  102. package/dist/protocol/auth/fake-primary-device.js +1 -3
  103. package/dist/protocol/auth/pair-device.d.ts +0 -1
  104. package/dist/protocol/auth/pair-device.js +4 -16
  105. package/dist/protocol/auth/success-node.d.ts +0 -1
  106. package/dist/protocol/auth/success-node.js +0 -1
  107. package/dist/protocol/iq/abprops.d.ts +0 -1
  108. package/dist/protocol/iq/abprops.js +0 -1
  109. package/dist/protocol/iq/appstate-sync.d.ts +0 -1
  110. package/dist/protocol/iq/appstate-sync.js +0 -1
  111. package/dist/protocol/iq/business.d.ts +0 -1
  112. package/dist/protocol/iq/business.js +0 -1
  113. package/dist/protocol/iq/dirty-bits.d.ts +0 -1
  114. package/dist/protocol/iq/dirty-bits.js +0 -1
  115. package/dist/protocol/iq/group-ops.d.ts +0 -1
  116. package/dist/protocol/iq/group-ops.js +0 -1
  117. package/dist/protocol/iq/newsletter.d.ts +0 -1
  118. package/dist/protocol/iq/newsletter.js +0 -1
  119. package/dist/protocol/iq/prekey-fetch.d.ts +0 -1
  120. package/dist/protocol/iq/prekey-fetch.js +0 -1
  121. package/dist/protocol/iq/privacy-token.d.ts +0 -1
  122. package/dist/protocol/iq/privacy-token.js +0 -1
  123. package/dist/protocol/iq/privacy.d.ts +0 -1
  124. package/dist/protocol/iq/privacy.js +15 -16
  125. package/dist/protocol/iq/profile.d.ts +0 -1
  126. package/dist/protocol/iq/profile.js +0 -1
  127. package/dist/protocol/iq/router.d.ts +7 -2
  128. package/dist/protocol/iq/router.js +8 -3
  129. package/dist/protocol/iq/usync.d.ts +0 -1
  130. package/dist/protocol/iq/usync.js +0 -1
  131. package/dist/protocol/push/app-state-key-share.d.ts +0 -1
  132. package/dist/protocol/push/app-state-key-share.js +0 -1
  133. package/dist/protocol/push/call-failure.d.ts +0 -1
  134. package/dist/protocol/push/call-failure.js +0 -1
  135. package/dist/protocol/push/chatstate.d.ts +0 -1
  136. package/dist/protocol/push/chatstate.js +0 -1
  137. package/dist/protocol/push/error-stanza.d.ts +0 -1
  138. package/dist/protocol/push/error-stanza.js +0 -1
  139. package/dist/protocol/push/history-sync.d.ts +0 -1
  140. package/dist/protocol/push/history-sync.js +0 -1
  141. package/dist/protocol/push/message.d.ts +0 -1
  142. package/dist/protocol/push/message.js +0 -1
  143. package/dist/protocol/push/notification.d.ts +0 -1
  144. package/dist/protocol/push/notification.js +0 -1
  145. package/dist/protocol/push/presence.d.ts +0 -1
  146. package/dist/protocol/push/presence.js +0 -1
  147. package/dist/protocol/push/receipt.d.ts +0 -1
  148. package/dist/protocol/push/receipt.js +0 -1
  149. package/dist/protocol/signal/fake-app-state-crypto.d.ts +7 -9
  150. package/dist/protocol/signal/fake-app-state-crypto.js +31 -33
  151. package/dist/protocol/signal/fake-peer-double-ratchet.d.ts +0 -1
  152. package/dist/protocol/signal/fake-peer-double-ratchet.js +23 -28
  153. package/dist/protocol/signal/fake-peer-group-recv-session.d.ts +0 -1
  154. package/dist/protocol/signal/fake-peer-group-recv-session.js +6 -10
  155. package/dist/protocol/signal/fake-peer-identity.d.ts +0 -1
  156. package/dist/protocol/signal/fake-peer-identity.js +0 -1
  157. package/dist/protocol/signal/fake-peer-key-bundle.d.ts +0 -1
  158. package/dist/protocol/signal/fake-peer-key-bundle.js +0 -1
  159. package/dist/protocol/signal/fake-sender-key.d.ts +0 -1
  160. package/dist/protocol/signal/fake-sender-key.js +5 -9
  161. package/dist/protocol/signal/prekey-upload.d.ts +0 -1
  162. package/dist/protocol/signal/prekey-upload.js +0 -1
  163. package/dist/protocol/stream/stream-error.d.ts +0 -1
  164. package/dist/protocol/stream/stream-error.js +0 -1
  165. package/dist/state/fake-app-state-collection.d.ts +0 -1
  166. package/dist/state/fake-app-state-collection.js +0 -1
  167. package/dist/state/fake-media-store.d.ts +0 -1
  168. package/dist/state/fake-media-store.js +2 -2
  169. package/dist/transport/codec.d.ts +2 -3
  170. package/dist/transport/codec.js +2 -3
  171. package/dist/transport/crypto.d.ts +5 -7
  172. package/dist/transport/crypto.js +6 -11
  173. package/dist/transport/protos.d.ts +2 -4
  174. package/dist/transport/protos.js +2 -4
  175. package/dist/transport/util.d.ts +8 -0
  176. package/dist/transport/util.js +16 -0
  177. package/package.json +26 -6
  178. package/dist/api/AppStateSyncManager.d.ts.map +0 -1
  179. package/dist/api/AppStateSyncManager.js.map +0 -1
  180. package/dist/api/FakePairingDriver.d.ts.map +0 -1
  181. package/dist/api/FakePairingDriver.js.map +0 -1
  182. package/dist/api/FakePeer.d.ts.map +0 -1
  183. package/dist/api/FakePeer.js.map +0 -1
  184. package/dist/api/FakeWaServer.d.ts.map +0 -1
  185. package/dist/api/FakeWaServer.js.map +0 -1
  186. package/dist/api/PreKeyDispenser.d.ts.map +0 -1
  187. package/dist/api/PreKeyDispenser.js.map +0 -1
  188. package/dist/api/Scenario.d.ts.map +0 -1
  189. package/dist/api/Scenario.js.map +0 -1
  190. package/dist/api/ServerRegistries.d.ts.map +0 -1
  191. package/dist/api/ServerRegistries.js.map +0 -1
  192. package/dist/api/iq-handlers.d.ts.map +0 -1
  193. package/dist/api/iq-handlers.js.map +0 -1
  194. package/dist/cli.d.ts.map +0 -1
  195. package/dist/cli.js.map +0 -1
  196. package/dist/index.d.ts.map +0 -1
  197. package/dist/index.js.map +0 -1
  198. package/dist/infra/WaFakeConnection.d.ts.map +0 -1
  199. package/dist/infra/WaFakeConnection.js.map +0 -1
  200. package/dist/infra/WaFakeConnectionPipeline.d.ts.map +0 -1
  201. package/dist/infra/WaFakeConnectionPipeline.js.map +0 -1
  202. package/dist/infra/WaFakeFrameSocket.d.ts.map +0 -1
  203. package/dist/infra/WaFakeFrameSocket.js.map +0 -1
  204. package/dist/infra/WaFakeMediaHttpsServer.d.ts.map +0 -1
  205. package/dist/infra/WaFakeMediaHttpsServer.js.map +0 -1
  206. package/dist/infra/WaFakeNoiseHandshake.d.ts.map +0 -1
  207. package/dist/infra/WaFakeNoiseHandshake.js.map +0 -1
  208. package/dist/infra/WaFakeTransport.d.ts.map +0 -1
  209. package/dist/infra/WaFakeTransport.js.map +0 -1
  210. package/dist/infra/WaFakeWsServer.d.ts.map +0 -1
  211. package/dist/infra/WaFakeWsServer.js.map +0 -1
  212. package/dist/protocol/auth/cert-chain.d.ts.map +0 -1
  213. package/dist/protocol/auth/cert-chain.js.map +0 -1
  214. package/dist/protocol/auth/client-payload-validate.d.ts.map +0 -1
  215. package/dist/protocol/auth/client-payload-validate.js.map +0 -1
  216. package/dist/protocol/auth/fake-primary-device.d.ts.map +0 -1
  217. package/dist/protocol/auth/fake-primary-device.js.map +0 -1
  218. package/dist/protocol/auth/pair-device.d.ts.map +0 -1
  219. package/dist/protocol/auth/pair-device.js.map +0 -1
  220. package/dist/protocol/auth/success-node.d.ts.map +0 -1
  221. package/dist/protocol/auth/success-node.js.map +0 -1
  222. package/dist/protocol/iq/abprops.d.ts.map +0 -1
  223. package/dist/protocol/iq/abprops.js.map +0 -1
  224. package/dist/protocol/iq/appstate-sync.d.ts.map +0 -1
  225. package/dist/protocol/iq/appstate-sync.js.map +0 -1
  226. package/dist/protocol/iq/business.d.ts.map +0 -1
  227. package/dist/protocol/iq/business.js.map +0 -1
  228. package/dist/protocol/iq/dirty-bits.d.ts.map +0 -1
  229. package/dist/protocol/iq/dirty-bits.js.map +0 -1
  230. package/dist/protocol/iq/group-ops.d.ts.map +0 -1
  231. package/dist/protocol/iq/group-ops.js.map +0 -1
  232. package/dist/protocol/iq/newsletter.d.ts.map +0 -1
  233. package/dist/protocol/iq/newsletter.js.map +0 -1
  234. package/dist/protocol/iq/prekey-fetch.d.ts.map +0 -1
  235. package/dist/protocol/iq/prekey-fetch.js.map +0 -1
  236. package/dist/protocol/iq/privacy-token.d.ts.map +0 -1
  237. package/dist/protocol/iq/privacy-token.js.map +0 -1
  238. package/dist/protocol/iq/privacy.d.ts.map +0 -1
  239. package/dist/protocol/iq/privacy.js.map +0 -1
  240. package/dist/protocol/iq/profile.d.ts.map +0 -1
  241. package/dist/protocol/iq/profile.js.map +0 -1
  242. package/dist/protocol/iq/router.d.ts.map +0 -1
  243. package/dist/protocol/iq/router.js.map +0 -1
  244. package/dist/protocol/iq/usync.d.ts.map +0 -1
  245. package/dist/protocol/iq/usync.js.map +0 -1
  246. package/dist/protocol/push/app-state-key-share.d.ts.map +0 -1
  247. package/dist/protocol/push/app-state-key-share.js.map +0 -1
  248. package/dist/protocol/push/call-failure.d.ts.map +0 -1
  249. package/dist/protocol/push/call-failure.js.map +0 -1
  250. package/dist/protocol/push/chatstate.d.ts.map +0 -1
  251. package/dist/protocol/push/chatstate.js.map +0 -1
  252. package/dist/protocol/push/error-stanza.d.ts.map +0 -1
  253. package/dist/protocol/push/error-stanza.js.map +0 -1
  254. package/dist/protocol/push/history-sync.d.ts.map +0 -1
  255. package/dist/protocol/push/history-sync.js.map +0 -1
  256. package/dist/protocol/push/message.d.ts.map +0 -1
  257. package/dist/protocol/push/message.js.map +0 -1
  258. package/dist/protocol/push/notification.d.ts.map +0 -1
  259. package/dist/protocol/push/notification.js.map +0 -1
  260. package/dist/protocol/push/presence.d.ts.map +0 -1
  261. package/dist/protocol/push/presence.js.map +0 -1
  262. package/dist/protocol/push/receipt.d.ts.map +0 -1
  263. package/dist/protocol/push/receipt.js.map +0 -1
  264. package/dist/protocol/signal/fake-app-state-crypto.d.ts.map +0 -1
  265. package/dist/protocol/signal/fake-app-state-crypto.js.map +0 -1
  266. package/dist/protocol/signal/fake-peer-double-ratchet.d.ts.map +0 -1
  267. package/dist/protocol/signal/fake-peer-double-ratchet.js.map +0 -1
  268. package/dist/protocol/signal/fake-peer-group-recv-session.d.ts.map +0 -1
  269. package/dist/protocol/signal/fake-peer-group-recv-session.js.map +0 -1
  270. package/dist/protocol/signal/fake-peer-identity.d.ts.map +0 -1
  271. package/dist/protocol/signal/fake-peer-identity.js.map +0 -1
  272. package/dist/protocol/signal/fake-peer-key-bundle.d.ts.map +0 -1
  273. package/dist/protocol/signal/fake-peer-key-bundle.js.map +0 -1
  274. package/dist/protocol/signal/fake-peer-recv-session.d.ts +0 -60
  275. package/dist/protocol/signal/fake-peer-recv-session.d.ts.map +0 -1
  276. package/dist/protocol/signal/fake-peer-recv-session.js +0 -284
  277. package/dist/protocol/signal/fake-peer-recv-session.js.map +0 -1
  278. package/dist/protocol/signal/fake-peer-session.d.ts +0 -87
  279. package/dist/protocol/signal/fake-peer-session.d.ts.map +0 -1
  280. package/dist/protocol/signal/fake-peer-session.js +0 -207
  281. package/dist/protocol/signal/fake-peer-session.js.map +0 -1
  282. package/dist/protocol/signal/fake-sender-key.d.ts.map +0 -1
  283. package/dist/protocol/signal/fake-sender-key.js.map +0 -1
  284. package/dist/protocol/signal/prekey-upload.d.ts.map +0 -1
  285. package/dist/protocol/signal/prekey-upload.js.map +0 -1
  286. package/dist/protocol/stream/stream-error.d.ts.map +0 -1
  287. package/dist/protocol/stream/stream-error.js.map +0 -1
  288. package/dist/state/fake-app-state-collection.d.ts.map +0 -1
  289. package/dist/state/fake-app-state-collection.js.map +0 -1
  290. package/dist/state/fake-media-store.d.ts.map +0 -1
  291. package/dist/state/fake-media-store.js.map +0 -1
  292. package/dist/transport/codec.d.ts.map +0 -1
  293. package/dist/transport/codec.js.map +0 -1
  294. package/dist/transport/crypto.d.ts.map +0 -1
  295. package/dist/transport/crypto.js.map +0 -1
  296. package/dist/transport/index.d.ts +0 -4
  297. package/dist/transport/index.d.ts.map +0 -1
  298. package/dist/transport/index.js +0 -20
  299. package/dist/transport/index.js.map +0 -1
  300. package/dist/transport/protos.d.ts.map +0 -1
  301. package/dist/transport/protos.js.map +0 -1
@@ -0,0 +1,515 @@
1
+ /** Registers the default IQ auto-handlers used by `FakeWaServer`. */
2
+ import { buildAbPropsResult } from '../protocol/iq/abprops.js';
3
+ import { buildAppStateSyncFullResult, buildAppStateSyncResult, parseAppStateSyncRequest } from '../protocol/iq/appstate-sync.js';
4
+ import { buildBusinessProfileResult, parseGetBusinessProfileIq } from '../protocol/iq/business.js';
5
+ import { parseClearDirtyBitsIq } from '../protocol/iq/dirty-bits.js';
6
+ import { buildGroupMetadataNode, buildGroupParticipantChangeResult, parseCreateGroupIq, parseGroupParticipantChangeIq, parseLeaveGroupIq, parseSetDescriptionIq, parseSetSubjectIq } from '../protocol/iq/group-ops.js';
7
+ import { buildNewsletterMyAddonsResult } from '../protocol/iq/newsletter.js';
8
+ import { buildPreKeyFetchResult } from '../protocol/iq/prekey-fetch.js';
9
+ import { buildBlocklistResult, buildPrivacyDisallowedListResult, buildPrivacySettingsResult, parseBlocklistChangeIq, parsePrivacyDisallowedListGetIq, parsePrivacySetCategoryIq } from '../protocol/iq/privacy.js';
10
+ import { parsePrivacyTokenIssueIq } from '../protocol/iq/privacy-token.js';
11
+ import { buildGetProfilePictureResult, buildSetProfilePictureResult, parseGetProfilePictureIq, parseSetProfilePictureIq, parseSetStatusIq } from '../protocol/iq/profile.js';
12
+ import { buildIqError, buildIqResult } from '../protocol/iq/router.js';
13
+ import { buildUsyncDevicesResult } from '../protocol/iq/usync.js';
14
+ import { parsePreKeyUploadIq } from '../protocol/signal/prekey-upload.js';
15
+ import { toUserJidPart } from './ServerRegistries.js';
16
+ export function parseUsyncRequestedUserJids(iq) {
17
+ if (!Array.isArray(iq.content))
18
+ return [];
19
+ const out = [];
20
+ for (const child of iq.content) {
21
+ if (child.tag !== 'usync')
22
+ continue;
23
+ if (!Array.isArray(child.content))
24
+ continue;
25
+ for (const inner of child.content) {
26
+ if (inner.tag !== 'list')
27
+ continue;
28
+ if (!Array.isArray(inner.content))
29
+ continue;
30
+ for (const userNode of inner.content) {
31
+ if (userNode.tag !== 'user')
32
+ continue;
33
+ if (typeof userNode.attrs.jid === 'string') {
34
+ out.push(userNode.attrs.jid);
35
+ }
36
+ }
37
+ }
38
+ }
39
+ return out;
40
+ }
41
+ export function parseRequestedKeyJids(iq) {
42
+ if (!Array.isArray(iq.content))
43
+ return [];
44
+ const out = [];
45
+ for (const child of iq.content) {
46
+ if (child.tag !== 'key')
47
+ continue;
48
+ if (!Array.isArray(child.content))
49
+ continue;
50
+ for (const userNode of child.content) {
51
+ if (userNode.tag !== 'user')
52
+ continue;
53
+ const jid = userNode.attrs.jid;
54
+ if (jid)
55
+ out.push(jid);
56
+ }
57
+ }
58
+ return out;
59
+ }
60
+ function buildGroupMetadataReply(iq, metadata) {
61
+ const result = buildIqResult(iq);
62
+ return {
63
+ ...result,
64
+ content: [
65
+ buildGroupMetadataNode({
66
+ groupJid: metadata.groupJid,
67
+ subject: metadata.subject,
68
+ creator: metadata.creator,
69
+ creationSeconds: metadata.creationSeconds,
70
+ participantJids: metadata.participants.map((peer) => toUserJidPart(peer.jid)),
71
+ ...(metadata.description !== undefined ? { description: metadata.description } : {})
72
+ })
73
+ ]
74
+ };
75
+ }
76
+ export function registerDefaultIqHandlers(router, deps) {
77
+ router.register({
78
+ label: 'prekey-upload',
79
+ matcher: { xmlns: 'encrypt', type: 'set' },
80
+ respond: (iq) => {
81
+ try {
82
+ const bundle = parsePreKeyUploadIq(iq);
83
+ deps.capturePreKeyBundle(bundle);
84
+ }
85
+ catch {
86
+ /* ignore */
87
+ }
88
+ return buildIqResult(iq);
89
+ }
90
+ });
91
+ router.register({
92
+ label: 'signal-digest',
93
+ matcher: { xmlns: 'encrypt', type: 'get', childTag: 'digest' },
94
+ respond: (iq) => buildIqError(iq, { code: 404, text: 'item-not-found' })
95
+ });
96
+ // Baileys-family and whatsmeow clients block on this query before
97
+ // reporting the connection as open; zapo-js uses <digest> instead.
98
+ router.register({
99
+ label: 'prekey-count',
100
+ matcher: { xmlns: 'encrypt', type: 'get', childTag: 'count' },
101
+ respond: (iq) => {
102
+ const result = buildIqResult(iq);
103
+ return {
104
+ ...result,
105
+ content: [
106
+ {
107
+ tag: 'count',
108
+ attrs: { value: String(deps.countServerPreKeys()) }
109
+ }
110
+ ]
111
+ };
112
+ }
113
+ });
114
+ router.register({
115
+ label: 'passive-mode',
116
+ matcher: { xmlns: 'passive', type: 'set' },
117
+ respond: (iq) => buildIqResult(iq)
118
+ });
119
+ router.register({
120
+ label: 'media-conn',
121
+ matcher: { xmlns: 'w:m', type: 'set', childTag: 'media_conn' },
122
+ respond: (iq) => {
123
+ const info = deps.requireMediaHttpsInfo();
124
+ const result = buildIqResult(iq);
125
+ return {
126
+ ...result,
127
+ attrs: { ...result.attrs, from: 's.whatsapp.net' },
128
+ content: [
129
+ {
130
+ tag: 'media_conn',
131
+ attrs: { auth: 'fake-media-auth', ttl: '3600' },
132
+ content: [
133
+ {
134
+ tag: 'host',
135
+ attrs: {
136
+ hostname: `${info.host}:${info.port}`
137
+ }
138
+ }
139
+ ]
140
+ }
141
+ ]
142
+ };
143
+ }
144
+ });
145
+ router.register({
146
+ label: 'app-state-sync',
147
+ matcher: { xmlns: 'w:sync:app:state', type: 'set' },
148
+ respond: async (iq) => {
149
+ await deps.consumeOutboundAppStatePatches(iq);
150
+ if (deps.appStateCollectionProviders.size === 0) {
151
+ return buildAppStateSyncResult(iq);
152
+ }
153
+ const requests = parseAppStateSyncRequest(iq);
154
+ const payloads = [];
155
+ for (const request of requests) {
156
+ const provider = deps.appStateCollectionProviders.get(request.name);
157
+ if (!provider)
158
+ continue;
159
+ const payload = await provider();
160
+ if (payload) {
161
+ payloads.push(payload);
162
+ }
163
+ }
164
+ return buildAppStateSyncFullResult(iq, { payloads });
165
+ }
166
+ });
167
+ router.register({
168
+ label: 'usync',
169
+ matcher: { xmlns: 'usync', type: 'get', childTag: 'usync' },
170
+ respond: (iq) => {
171
+ const requestedUserJids = parseUsyncRequestedUserJids(iq);
172
+ const results = requestedUserJids.map((userJid) => ({
173
+ userJid,
174
+ deviceIds: deps.lookupDeviceIdsForUser(userJid)
175
+ }));
176
+ return buildUsyncDevicesResult(iq, results);
177
+ }
178
+ });
179
+ router.register({
180
+ label: 'prekey-fetch',
181
+ matcher: { xmlns: 'encrypt', type: 'get', childTag: 'key' },
182
+ respond: (iq) => {
183
+ const requestedDeviceJids = parseRequestedKeyJids(iq);
184
+ const bundles = [];
185
+ for (const deviceJid of requestedDeviceJids) {
186
+ const peer = deps.peerRegistry.get(deviceJid);
187
+ if (!peer)
188
+ continue;
189
+ const oneTime = peer.keyBundle.oneTimePreKeys[0];
190
+ bundles.push({
191
+ userJid: deviceJid,
192
+ registrationId: peer.keyBundle.registrationId,
193
+ identityPublicKey: peer.keyBundle.identityKeyPair.pubKey,
194
+ signedPreKey: {
195
+ id: peer.keyBundle.signedPreKey.id,
196
+ publicKey: peer.keyBundle.signedPreKey.keyPair.pubKey,
197
+ signature: peer.keyBundle.signedPreKey.signature
198
+ },
199
+ ...(oneTime
200
+ ? {
201
+ oneTimePreKey: {
202
+ id: oneTime.id,
203
+ publicKey: oneTime.keyPair.pubKey
204
+ }
205
+ }
206
+ : {})
207
+ });
208
+ }
209
+ return buildPreKeyFetchResult(iq, bundles);
210
+ }
211
+ });
212
+ router.register({
213
+ label: 'group-metadata',
214
+ matcher: { xmlns: 'w:g2', type: 'get', childTag: 'query' },
215
+ respond: (iq) => {
216
+ const groupJid = iq.attrs.to;
217
+ if (!groupJid) {
218
+ return buildIqError(iq, { code: 400, text: 'missing-to' });
219
+ }
220
+ const metadata = deps.groupRegistry.get(groupJid);
221
+ if (!metadata) {
222
+ return buildIqError(iq, { code: 404, text: 'group-not-found' });
223
+ }
224
+ return buildGroupMetadataReply(iq, metadata);
225
+ }
226
+ });
227
+ router.register({
228
+ label: 'abprops',
229
+ matcher: { xmlns: 'abt', type: 'get', childTag: 'props' },
230
+ respond: (iq) => buildAbPropsResult(iq, deps.abPropsInput)
231
+ });
232
+ router.register({
233
+ label: 'whatsapp-ping',
234
+ matcher: { xmlns: 'w:p', type: 'get' },
235
+ respond: (iq) => buildIqResult(iq)
236
+ });
237
+ router.register({
238
+ label: 'xmpp-ping',
239
+ matcher: { xmlns: 'urn:xmpp:ping', type: 'get' },
240
+ respond: (iq) => buildIqResult(iq)
241
+ });
242
+ router.register({
243
+ label: 'signed-prekey-rotate',
244
+ matcher: { xmlns: 'encrypt', type: 'set', childTag: 'rotate' },
245
+ respond: (iq) => buildIqResult(iq)
246
+ });
247
+ router.register({
248
+ label: 'remove-companion-device',
249
+ matcher: { xmlns: 'md', type: 'set', childTag: 'remove-companion-device' },
250
+ respond: (iq) => {
251
+ deps.notifyLogout();
252
+ return buildIqResult(iq);
253
+ }
254
+ });
255
+ router.register({
256
+ label: 'group-create',
257
+ matcher: { xmlns: 'w:g2', type: 'set', childTag: 'create' },
258
+ respond: (iq) => {
259
+ const parsed = parseCreateGroupIq(iq);
260
+ if (!parsed) {
261
+ return buildIqError(iq, { code: 400, text: 'invalid-create' });
262
+ }
263
+ const groupJid = `120363${Date.now()}@g.us`;
264
+ const creator = parsed.participantJids[0] ?? 's.whatsapp.net';
265
+ const creationSeconds = Math.floor(Date.now() / 1000);
266
+ const participants = [];
267
+ for (const jid of parsed.participantJids) {
268
+ const peer = deps.peerRegistry.get(jid);
269
+ if (peer)
270
+ participants.push(peer);
271
+ }
272
+ const mutable = {
273
+ groupJid,
274
+ subject: parsed.subject,
275
+ description: parsed.description,
276
+ creator,
277
+ creationSeconds,
278
+ participants
279
+ };
280
+ deps.groupRegistry.set(groupJid, mutable);
281
+ deps.notifyGroupOp({
282
+ action: 'create',
283
+ groupJid,
284
+ subject: parsed.subject,
285
+ participantJids: parsed.participantJids,
286
+ description: parsed.description
287
+ });
288
+ const result = buildIqResult(iq);
289
+ return {
290
+ ...result,
291
+ content: [
292
+ buildGroupMetadataNode({
293
+ groupJid,
294
+ subject: parsed.subject,
295
+ creator,
296
+ creationSeconds,
297
+ participantJids: parsed.participantJids,
298
+ description: parsed.description
299
+ })
300
+ ]
301
+ };
302
+ }
303
+ });
304
+ for (const action of ['add', 'remove', 'promote', 'demote']) {
305
+ router.register({
306
+ label: `group-${action}`,
307
+ matcher: { xmlns: 'w:g2', type: 'set', childTag: action },
308
+ respond: (iq) => {
309
+ const parsed = parseGroupParticipantChangeIq(iq);
310
+ if (!parsed) {
311
+ return buildIqError(iq, { code: 400, text: 'invalid-change' });
312
+ }
313
+ const group = deps.groupRegistry.get(parsed.groupJid);
314
+ if (group) {
315
+ if (parsed.action === 'add') {
316
+ for (const jid of parsed.participantJids) {
317
+ const peer = deps.peerRegistry.get(jid);
318
+ if (peer && !group.participants.includes(peer)) {
319
+ group.participants.push(peer);
320
+ }
321
+ }
322
+ }
323
+ else if (parsed.action === 'remove') {
324
+ const removed = new Set(parsed.participantJids);
325
+ group.participants = group.participants.filter((peer) => !removed.has(peer.jid));
326
+ }
327
+ }
328
+ deps.notifyGroupOp({
329
+ action: parsed.action,
330
+ groupJid: parsed.groupJid,
331
+ participantJids: parsed.participantJids
332
+ });
333
+ return buildGroupParticipantChangeResult(iq, parsed.action, parsed.participantJids);
334
+ }
335
+ });
336
+ }
337
+ router.register({
338
+ label: 'group-subject',
339
+ matcher: { xmlns: 'w:g2', type: 'set', childTag: 'subject' },
340
+ respond: (iq) => {
341
+ const parsed = parseSetSubjectIq(iq);
342
+ if (!parsed)
343
+ return buildIqError(iq, { code: 400, text: 'invalid-subject' });
344
+ const group = deps.groupRegistry.get(parsed.groupJid);
345
+ if (group)
346
+ group.subject = parsed.subject;
347
+ deps.notifyGroupOp({
348
+ action: 'subject',
349
+ groupJid: parsed.groupJid,
350
+ subject: parsed.subject
351
+ });
352
+ return buildIqResult(iq);
353
+ }
354
+ });
355
+ router.register({
356
+ label: 'group-description',
357
+ matcher: { xmlns: 'w:g2', type: 'set', childTag: 'description' },
358
+ respond: (iq) => {
359
+ const parsed = parseSetDescriptionIq(iq);
360
+ if (!parsed)
361
+ return buildIqError(iq, { code: 400, text: 'invalid-description' });
362
+ const group = deps.groupRegistry.get(parsed.groupJid);
363
+ if (group)
364
+ group.description = parsed.description ?? undefined;
365
+ deps.notifyGroupOp({
366
+ action: 'description',
367
+ groupJid: parsed.groupJid,
368
+ description: parsed.description
369
+ });
370
+ return buildIqResult(iq);
371
+ }
372
+ });
373
+ router.register({
374
+ label: 'group-leave',
375
+ matcher: { xmlns: 'w:g2', type: 'set', childTag: 'leave' },
376
+ respond: (iq) => {
377
+ const groupJids = parseLeaveGroupIq(iq) ?? [];
378
+ for (const groupJid of groupJids) {
379
+ deps.groupRegistry.delete(groupJid);
380
+ deps.notifyGroupOp({ action: 'leave', groupJid });
381
+ }
382
+ return buildIqResult(iq);
383
+ }
384
+ });
385
+ router.register({
386
+ label: 'privacy-get',
387
+ matcher: { xmlns: 'privacy', type: 'get', childTag: 'privacy' },
388
+ respond: (iq) => {
389
+ const disallowedCategory = parsePrivacyDisallowedListGetIq(iq);
390
+ if (disallowedCategory) {
391
+ return buildPrivacyDisallowedListResult(iq, disallowedCategory, deps.privacySettings.disallowed[disallowedCategory] ?? []);
392
+ }
393
+ return buildPrivacySettingsResult(iq, deps.privacySettings);
394
+ }
395
+ });
396
+ router.register({
397
+ label: 'privacy-set',
398
+ matcher: { xmlns: 'privacy', type: 'set', childTag: 'privacy' },
399
+ respond: (iq) => {
400
+ const change = parsePrivacySetCategoryIq(iq);
401
+ if (!change)
402
+ return buildIqError(iq, { code: 400, text: 'invalid-privacy-set' });
403
+ deps.mutatePrivacySettings(change.category, change.value);
404
+ deps.notifyPrivacySet(change);
405
+ return buildIqResult(iq);
406
+ }
407
+ });
408
+ router.register({
409
+ label: 'blocklist-get',
410
+ matcher: { xmlns: 'blocklist', type: 'get' },
411
+ respond: (iq) => buildBlocklistResult(iq, [...deps.blocklistJids])
412
+ });
413
+ router.register({
414
+ label: 'blocklist-set',
415
+ matcher: { xmlns: 'blocklist', type: 'set' },
416
+ respond: (iq) => {
417
+ const change = parseBlocklistChangeIq(iq);
418
+ if (!change) {
419
+ return buildIqError(iq, { code: 400, text: 'invalid-blocklist-set' });
420
+ }
421
+ deps.mutateBlocklist(change.action, change.jid);
422
+ deps.notifyBlocklistChange(change);
423
+ return buildIqResult(iq);
424
+ }
425
+ });
426
+ router.register({
427
+ label: 'privacy-token-issue',
428
+ matcher: { xmlns: 'privacy', type: 'set', childTag: 'tokens' },
429
+ respond: (iq) => {
430
+ const tokens = parsePrivacyTokenIssueIq(iq);
431
+ if (tokens) {
432
+ for (const token of tokens) {
433
+ deps.issuedPrivacyTokens.set(token.jid, token);
434
+ deps.notifyPrivacyTokenIssue(token);
435
+ }
436
+ }
437
+ return buildIqResult(iq);
438
+ }
439
+ });
440
+ router.register({
441
+ label: 'newsletter-my-addons',
442
+ matcher: { xmlns: 'newsletter', type: 'get', childTag: 'my_addons' },
443
+ respond: (iq) => buildNewsletterMyAddonsResult(iq)
444
+ });
445
+ router.register({
446
+ label: 'dirty-bits-clear',
447
+ matcher: { xmlns: 'urn:xmpp:whatsapp:dirty', type: 'set' },
448
+ respond: (iq) => {
449
+ const bits = parseClearDirtyBitsIq(iq);
450
+ if (bits) {
451
+ deps.notifyDirtyBitsClear({ bits });
452
+ }
453
+ return buildIqResult(iq);
454
+ }
455
+ });
456
+ router.register({
457
+ label: 'profile-picture-get',
458
+ matcher: { xmlns: 'w:profile:picture', type: 'get' },
459
+ respond: (iq) => {
460
+ const parsed = parseGetProfilePictureIq(iq);
461
+ if (!parsed)
462
+ return buildIqError(iq, { code: 400, text: 'invalid-target' });
463
+ const picture = deps.profilePicturesByJid.get(parsed.targetJid);
464
+ if (!picture) {
465
+ return buildIqError(iq, { code: 404, text: 'item-not-found' });
466
+ }
467
+ return buildGetProfilePictureResult(iq, { ...picture, type: parsed.type });
468
+ }
469
+ });
470
+ router.register({
471
+ label: 'profile-picture-set',
472
+ matcher: { xmlns: 'w:profile:picture', type: 'set' },
473
+ respond: (iq) => {
474
+ const parsed = parseSetProfilePictureIq(iq);
475
+ if (!parsed)
476
+ return buildIqError(iq, { code: 400, text: 'invalid-set' });
477
+ const targetJid = parsed.targetJid ?? 'me';
478
+ const newId = `${Date.now()}`;
479
+ deps.handleProfilePictureSet(targetJid, newId);
480
+ deps.notifyProfilePictureSet(parsed);
481
+ return buildSetProfilePictureResult(iq, newId);
482
+ }
483
+ });
484
+ router.register({
485
+ label: 'status-set',
486
+ matcher: { xmlns: 'status', type: 'set' },
487
+ respond: (iq) => {
488
+ const parsed = parseSetStatusIq(iq);
489
+ if (parsed) {
490
+ deps.setLatestStatusText(parsed.text);
491
+ deps.notifyStatusSet(parsed.text);
492
+ }
493
+ return buildIqResult(iq);
494
+ }
495
+ });
496
+ router.register({
497
+ label: 'business-profile-get',
498
+ matcher: { xmlns: 'w:biz', type: 'get', childTag: 'business_profile' },
499
+ respond: (iq) => {
500
+ const requestedJids = parseGetBusinessProfileIq(iq) ?? [];
501
+ const profiles = [];
502
+ for (const jid of requestedJids) {
503
+ const profile = deps.businessProfilesByJid.get(jid);
504
+ if (profile)
505
+ profiles.push(profile);
506
+ }
507
+ return buildBusinessProfileResult(iq, profiles);
508
+ }
509
+ });
510
+ router.register({
511
+ label: 'business-profile-set',
512
+ matcher: { xmlns: 'w:biz', type: 'set', childTag: 'business_profile' },
513
+ respond: (iq) => buildIqResult(iq)
514
+ });
515
+ }