@jeongsu816/matrix-bot-sdk 0.0.0-stage → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -2
  3. package/lib/AdminApis.d.ts +52 -0
  4. package/lib/AdminApis.js +29 -0
  5. package/lib/AdminApis.js.map +1 -0
  6. package/lib/DMs.d.ts +48 -0
  7. package/lib/DMs.js +160 -0
  8. package/lib/DMs.js.map +1 -0
  9. package/lib/IFilter.d.ts +7 -0
  10. package/lib/IFilter.js +3 -0
  11. package/lib/IFilter.js.map +1 -0
  12. package/lib/MatrixAuth.d.ts +45 -0
  13. package/lib/MatrixAuth.js +125 -0
  14. package/lib/MatrixAuth.js.map +1 -0
  15. package/lib/MatrixClient.d.ts +834 -0
  16. package/lib/MatrixClient.js +2268 -0
  17. package/lib/MatrixClient.js.map +1 -0
  18. package/lib/PantalaimonClient.d.ts +42 -0
  19. package/lib/PantalaimonClient.js +44 -0
  20. package/lib/PantalaimonClient.js.map +1 -0
  21. package/lib/SynapseAdminApis.d.ts +350 -0
  22. package/lib/SynapseAdminApis.js +244 -0
  23. package/lib/SynapseAdminApis.js.map +1 -0
  24. package/lib/SynchronousMatrixClient.d.ts +82 -0
  25. package/lib/SynchronousMatrixClient.js +130 -0
  26. package/lib/SynchronousMatrixClient.js.map +1 -0
  27. package/lib/UnstableApis.d.ts +43 -0
  28. package/lib/UnstableApis.js +74 -0
  29. package/lib/UnstableApis.js.map +1 -0
  30. package/lib/appservice/Appservice.d.ts +328 -0
  31. package/lib/appservice/Appservice.js +803 -0
  32. package/lib/appservice/Appservice.js.map +1 -0
  33. package/lib/appservice/Intent.d.ts +113 -0
  34. package/lib/appservice/Intent.js +363 -0
  35. package/lib/appservice/Intent.js.map +1 -0
  36. package/lib/appservice/MatrixBridge.d.ts +85 -0
  37. package/lib/appservice/MatrixBridge.js +111 -0
  38. package/lib/appservice/MatrixBridge.js.map +1 -0
  39. package/lib/appservice/UnstableAppserviceApis.d.ts +41 -0
  40. package/lib/appservice/UnstableAppserviceApis.js +62 -0
  41. package/lib/appservice/UnstableAppserviceApis.js.map +1 -0
  42. package/lib/appservice/http_responses.d.ts +77 -0
  43. package/lib/appservice/http_responses.js +3 -0
  44. package/lib/appservice/http_responses.js.map +1 -0
  45. package/lib/b64.d.ts +42 -0
  46. package/lib/b64.js +68 -0
  47. package/lib/b64.js.map +1 -0
  48. package/lib/e2ee/CrossSigningBootstrap.d.ts +73 -0
  49. package/lib/e2ee/CrossSigningBootstrap.js +86 -0
  50. package/lib/e2ee/CrossSigningBootstrap.js.map +1 -0
  51. package/lib/e2ee/CryptoClient.d.ts +163 -0
  52. package/lib/e2ee/CryptoClient.js +382 -0
  53. package/lib/e2ee/CryptoClient.js.map +1 -0
  54. package/lib/e2ee/ICryptoRoomInformation.d.ts +8 -0
  55. package/lib/e2ee/ICryptoRoomInformation.js +3 -0
  56. package/lib/e2ee/ICryptoRoomInformation.js.map +1 -0
  57. package/lib/e2ee/RoomTracker.d.ts +41 -0
  58. package/lib/e2ee/RoomTracker.js +96 -0
  59. package/lib/e2ee/RoomTracker.js.map +1 -0
  60. package/lib/e2ee/RustEngine.d.ts +149 -0
  61. package/lib/e2ee/RustEngine.js +467 -0
  62. package/lib/e2ee/RustEngine.js.map +1 -0
  63. package/lib/e2ee/decorators.d.ts +10 -0
  64. package/lib/e2ee/decorators.js +37 -0
  65. package/lib/e2ee/decorators.js.map +1 -0
  66. package/lib/helpers/MatrixEntity.d.ts +37 -0
  67. package/lib/helpers/MatrixEntity.js +67 -0
  68. package/lib/helpers/MatrixEntity.js.map +1 -0
  69. package/lib/helpers/MatrixGlob.d.ts +22 -0
  70. package/lib/helpers/MatrixGlob.js +35 -0
  71. package/lib/helpers/MatrixGlob.js.map +1 -0
  72. package/lib/helpers/MentionPill.d.ts +40 -0
  73. package/lib/helpers/MentionPill.js +91 -0
  74. package/lib/helpers/MentionPill.js.map +1 -0
  75. package/lib/helpers/Permalinks.d.ts +58 -0
  76. package/lib/helpers/Permalinks.js +73 -0
  77. package/lib/helpers/Permalinks.js.map +1 -0
  78. package/lib/helpers/ProfileCache.d.ts +48 -0
  79. package/lib/helpers/ProfileCache.js +114 -0
  80. package/lib/helpers/ProfileCache.js.map +1 -0
  81. package/lib/helpers/RichReply.d.ts +17 -0
  82. package/lib/helpers/RichReply.js +47 -0
  83. package/lib/helpers/RichReply.js.map +1 -0
  84. package/lib/helpers/UnpaddedBase64.d.ts +31 -0
  85. package/lib/helpers/UnpaddedBase64.js +45 -0
  86. package/lib/helpers/UnpaddedBase64.js.map +1 -0
  87. package/lib/http.d.ts +17 -0
  88. package/lib/http.js +147 -0
  89. package/lib/http.js.map +1 -0
  90. package/lib/identity/IdentityClient.d.ts +93 -0
  91. package/lib/identity/IdentityClient.js +248 -0
  92. package/lib/identity/IdentityClient.js.map +1 -0
  93. package/lib/index.d.ts +91 -0
  94. package/lib/index.js +125 -0
  95. package/lib/index.js.map +1 -0
  96. package/lib/logging/ConsoleLogger.d.ts +12 -0
  97. package/lib/logging/ConsoleLogger.js +28 -0
  98. package/lib/logging/ConsoleLogger.js.map +1 -0
  99. package/lib/logging/ILogger.d.ts +36 -0
  100. package/lib/logging/ILogger.js +3 -0
  101. package/lib/logging/ILogger.js.map +1 -0
  102. package/lib/logging/LogService.d.ts +100 -0
  103. package/lib/logging/LogService.js +169 -0
  104. package/lib/logging/LogService.js.map +1 -0
  105. package/lib/logging/RichConsoleLogger.d.ts +20 -0
  106. package/lib/logging/RichConsoleLogger.js +41 -0
  107. package/lib/logging/RichConsoleLogger.js.map +1 -0
  108. package/lib/metrics/IMetricListener.d.ts +52 -0
  109. package/lib/metrics/IMetricListener.js +3 -0
  110. package/lib/metrics/IMetricListener.js.map +1 -0
  111. package/lib/metrics/Metrics.d.ts +66 -0
  112. package/lib/metrics/Metrics.js +128 -0
  113. package/lib/metrics/Metrics.js.map +1 -0
  114. package/lib/metrics/contexts.d.ts +51 -0
  115. package/lib/metrics/contexts.js +3 -0
  116. package/lib/metrics/contexts.js.map +1 -0
  117. package/lib/metrics/decorators.d.ts +15 -0
  118. package/lib/metrics/decorators.js +92 -0
  119. package/lib/metrics/decorators.js.map +1 -0
  120. package/lib/metrics/names.d.ts +45 -0
  121. package/lib/metrics/names.js +49 -0
  122. package/lib/metrics/names.js.map +1 -0
  123. package/lib/mixins/AutojoinRoomsMixin.d.ts +10 -0
  124. package/lib/mixins/AutojoinRoomsMixin.js +25 -0
  125. package/lib/mixins/AutojoinRoomsMixin.js.map +1 -0
  126. package/lib/mixins/AutojoinUpgradedRoomsMixin.d.ts +10 -0
  127. package/lib/mixins/AutojoinUpgradedRoomsMixin.js +40 -0
  128. package/lib/mixins/AutojoinUpgradedRoomsMixin.js.map +1 -0
  129. package/lib/models/Account.d.ts +8 -0
  130. package/lib/models/Account.js +3 -0
  131. package/lib/models/Account.js.map +1 -0
  132. package/lib/models/CreateRoom.d.ts +125 -0
  133. package/lib/models/CreateRoom.js +3 -0
  134. package/lib/models/CreateRoom.js.map +1 -0
  135. package/lib/models/Crypto.d.ts +167 -0
  136. package/lib/models/Crypto.js +31 -0
  137. package/lib/models/Crypto.js.map +1 -0
  138. package/lib/models/EventContext.d.ts +19 -0
  139. package/lib/models/EventContext.js +3 -0
  140. package/lib/models/EventContext.js.map +1 -0
  141. package/lib/models/IdentityServerModels.d.ts +20 -0
  142. package/lib/models/IdentityServerModels.js +3 -0
  143. package/lib/models/IdentityServerModels.js.map +1 -0
  144. package/lib/models/MSC2176.d.ts +42 -0
  145. package/lib/models/MSC2176.js +3 -0
  146. package/lib/models/MSC2176.js.map +1 -0
  147. package/lib/models/MatrixError.d.ts +38 -0
  148. package/lib/models/MatrixError.js +30 -0
  149. package/lib/models/MatrixError.js.map +1 -0
  150. package/lib/models/MatrixProfile.d.ts +43 -0
  151. package/lib/models/MatrixProfile.js +43 -0
  152. package/lib/models/MatrixProfile.js.map +1 -0
  153. package/lib/models/OpenIDConnect.d.ts +10 -0
  154. package/lib/models/OpenIDConnect.js +3 -0
  155. package/lib/models/OpenIDConnect.js.map +1 -0
  156. package/lib/models/Policies.d.ts +25 -0
  157. package/lib/models/Policies.js +3 -0
  158. package/lib/models/Policies.js.map +1 -0
  159. package/lib/models/PowerLevelAction.d.ts +27 -0
  160. package/lib/models/PowerLevelAction.js +32 -0
  161. package/lib/models/PowerLevelAction.js.map +1 -0
  162. package/lib/models/PowerLevelBounds.d.ts +15 -0
  163. package/lib/models/PowerLevelBounds.js +3 -0
  164. package/lib/models/PowerLevelBounds.js.map +1 -0
  165. package/lib/models/Presence.d.ts +25 -0
  166. package/lib/models/Presence.js +38 -0
  167. package/lib/models/Presence.js.map +1 -0
  168. package/lib/models/ServerVersions.d.ts +8 -0
  169. package/lib/models/ServerVersions.js +3 -0
  170. package/lib/models/ServerVersions.js.map +1 -0
  171. package/lib/models/Spaces.d.ts +116 -0
  172. package/lib/models/Spaces.js +91 -0
  173. package/lib/models/Spaces.js.map +1 -0
  174. package/lib/models/Threepid.d.ts +8 -0
  175. package/lib/models/Threepid.js +3 -0
  176. package/lib/models/Threepid.js.map +1 -0
  177. package/lib/models/events/AliasesEvent.d.ts +27 -0
  178. package/lib/models/events/AliasesEvent.js +27 -0
  179. package/lib/models/events/AliasesEvent.js.map +1 -0
  180. package/lib/models/events/CanonicalAliasEvent.d.ts +23 -0
  181. package/lib/models/events/CanonicalAliasEvent.js +21 -0
  182. package/lib/models/events/CanonicalAliasEvent.js.map +1 -0
  183. package/lib/models/events/CreateEvent.d.ts +63 -0
  184. package/lib/models/events/CreateEvent.js +33 -0
  185. package/lib/models/events/CreateEvent.js.map +1 -0
  186. package/lib/models/events/EncryptedRoomEvent.d.ts +42 -0
  187. package/lib/models/events/EncryptedRoomEvent.js +28 -0
  188. package/lib/models/events/EncryptedRoomEvent.js.map +1 -0
  189. package/lib/models/events/EncryptionEvent.d.ts +47 -0
  190. package/lib/models/events/EncryptionEvent.js +42 -0
  191. package/lib/models/events/EncryptionEvent.js.map +1 -0
  192. package/lib/models/events/Event.d.ts +26 -0
  193. package/lib/models/events/Event.js +40 -0
  194. package/lib/models/events/Event.js.map +1 -0
  195. package/lib/models/events/EventKind.d.ts +15 -0
  196. package/lib/models/events/EventKind.js +20 -0
  197. package/lib/models/events/EventKind.js.map +1 -0
  198. package/lib/models/events/InvalidEventError.d.ts +14 -0
  199. package/lib/models/events/InvalidEventError.js +24 -0
  200. package/lib/models/events/InvalidEventError.js.map +1 -0
  201. package/lib/models/events/JoinRulesEvent.d.ts +29 -0
  202. package/lib/models/events/JoinRulesEvent.js +21 -0
  203. package/lib/models/events/JoinRulesEvent.js.map +1 -0
  204. package/lib/models/events/MembershipEvent.d.ts +54 -0
  205. package/lib/models/events/MembershipEvent.js +49 -0
  206. package/lib/models/events/MembershipEvent.js.map +1 -0
  207. package/lib/models/events/MessageEvent.d.ts +233 -0
  208. package/lib/models/events/MessageEvent.js +49 -0
  209. package/lib/models/events/MessageEvent.js.map +1 -0
  210. package/lib/models/events/PinnedEventsEvent.d.ts +23 -0
  211. package/lib/models/events/PinnedEventsEvent.js +21 -0
  212. package/lib/models/events/PinnedEventsEvent.js.map +1 -0
  213. package/lib/models/events/PowerLevelsEvent.d.ts +96 -0
  214. package/lib/models/events/PowerLevelsEvent.js +70 -0
  215. package/lib/models/events/PowerLevelsEvent.js.map +1 -0
  216. package/lib/models/events/PresenceEvent.d.ts +56 -0
  217. package/lib/models/events/PresenceEvent.js +21 -0
  218. package/lib/models/events/PresenceEvent.js.map +1 -0
  219. package/lib/models/events/RedactionEvent.d.ts +28 -0
  220. package/lib/models/events/RedactionEvent.js +36 -0
  221. package/lib/models/events/RedactionEvent.js.map +1 -0
  222. package/lib/models/events/RoomAvatarEvent.d.ts +28 -0
  223. package/lib/models/events/RoomAvatarEvent.js +21 -0
  224. package/lib/models/events/RoomAvatarEvent.js.map +1 -0
  225. package/lib/models/events/RoomEvent.d.ts +58 -0
  226. package/lib/models/events/RoomEvent.js +57 -0
  227. package/lib/models/events/RoomEvent.js.map +1 -0
  228. package/lib/models/events/RoomNameEvent.d.ts +20 -0
  229. package/lib/models/events/RoomNameEvent.js +21 -0
  230. package/lib/models/events/RoomNameEvent.js.map +1 -0
  231. package/lib/models/events/RoomTopicEvent.d.ts +20 -0
  232. package/lib/models/events/RoomTopicEvent.js +21 -0
  233. package/lib/models/events/RoomTopicEvent.js.map +1 -0
  234. package/lib/models/events/SpaceChildEvent.d.ts +53 -0
  235. package/lib/models/events/SpaceChildEvent.js +49 -0
  236. package/lib/models/events/SpaceChildEvent.js.map +1 -0
  237. package/lib/models/events/converter.d.ts +8 -0
  238. package/lib/models/events/converter.js +50 -0
  239. package/lib/models/events/converter.js.map +1 -0
  240. package/lib/models/unstable/MediaInfo.d.ts +16 -0
  241. package/lib/models/unstable/MediaInfo.js +3 -0
  242. package/lib/models/unstable/MediaInfo.js.map +1 -0
  243. package/lib/preprocessors/IPreprocessor.d.ts +22 -0
  244. package/lib/preprocessors/IPreprocessor.js +3 -0
  245. package/lib/preprocessors/IPreprocessor.js.map +1 -0
  246. package/lib/preprocessors/RichRepliesPreprocessor.d.ts +67 -0
  247. package/lib/preprocessors/RichRepliesPreprocessor.js +112 -0
  248. package/lib/preprocessors/RichRepliesPreprocessor.js.map +1 -0
  249. package/lib/request.d.ts +13 -0
  250. package/lib/request.js +23 -0
  251. package/lib/request.js.map +1 -0
  252. package/lib/simple-validation.d.ts +10 -0
  253. package/lib/simple-validation.js +30 -0
  254. package/lib/simple-validation.js.map +1 -0
  255. package/lib/storage/IAppserviceStorageProvider.d.ts +48 -0
  256. package/lib/storage/IAppserviceStorageProvider.js +3 -0
  257. package/lib/storage/IAppserviceStorageProvider.js.map +1 -0
  258. package/lib/storage/ICryptoStorageProvider.d.ts +32 -0
  259. package/lib/storage/ICryptoStorageProvider.js +3 -0
  260. package/lib/storage/ICryptoStorageProvider.js.map +1 -0
  261. package/lib/storage/IStorageProvider.d.ts +47 -0
  262. package/lib/storage/IStorageProvider.js +3 -0
  263. package/lib/storage/IStorageProvider.js.map +1 -0
  264. package/lib/storage/MemoryStorageProvider.d.ts +26 -0
  265. package/lib/storage/MemoryStorageProvider.js +55 -0
  266. package/lib/storage/MemoryStorageProvider.js.map +1 -0
  267. package/lib/storage/RustSdkCryptoStorageProvider.d.ts +38 -0
  268. package/lib/storage/RustSdkCryptoStorageProvider.js +69 -0
  269. package/lib/storage/RustSdkCryptoStorageProvider.js.map +1 -0
  270. package/lib/storage/SimpleFsStorageProvider.d.ts +31 -0
  271. package/lib/storage/SimpleFsStorageProvider.js +122 -0
  272. package/lib/storage/SimpleFsStorageProvider.js.map +1 -0
  273. package/lib/storage/SimplePostgresStorageProvider.d.ts +32 -0
  274. package/lib/storage/SimplePostgresStorageProvider.js +148 -0
  275. package/lib/storage/SimplePostgresStorageProvider.js.map +1 -0
  276. package/lib/strategies/AppserviceJoinRoomStrategy.d.ts +14 -0
  277. package/lib/strategies/AppserviceJoinRoomStrategy.js +54 -0
  278. package/lib/strategies/AppserviceJoinRoomStrategy.js.map +1 -0
  279. package/lib/strategies/JoinRoomStrategy.d.ts +11 -0
  280. package/lib/strategies/JoinRoomStrategy.js +44 -0
  281. package/lib/strategies/JoinRoomStrategy.js.map +1 -0
  282. package/package.json +136 -4
  283. package/src/AdminApis.ts +60 -0
  284. package/src/DMs.ts +164 -0
  285. package/src/IFilter.ts +7 -0
  286. package/src/MatrixAuth.ts +129 -0
  287. package/src/MatrixClient.ts +2046 -0
  288. package/src/PantalaimonClient.ts +62 -0
  289. package/src/SynapseAdminApis.ts +482 -0
  290. package/src/SynchronousMatrixClient.ts +129 -0
  291. package/src/UnstableApis.ts +75 -0
  292. package/src/appservice/Appservice.ts +1089 -0
  293. package/src/appservice/Intent.ts +342 -0
  294. package/src/appservice/MatrixBridge.ts +139 -0
  295. package/src/appservice/UnstableAppserviceApis.ts +63 -0
  296. package/src/appservice/http_responses.ts +77 -0
  297. package/src/b64.ts +63 -0
  298. package/src/e2ee/CrossSigningBootstrap.ts +141 -0
  299. package/src/e2ee/CryptoClient.ts +378 -0
  300. package/src/e2ee/ICryptoRoomInformation.ts +9 -0
  301. package/src/e2ee/RoomTracker.ts +99 -0
  302. package/src/e2ee/RustEngine.ts +580 -0
  303. package/src/e2ee/decorators.ts +38 -0
  304. package/src/helpers/MatrixEntity.ts +65 -0
  305. package/src/helpers/MatrixGlob.ts +38 -0
  306. package/src/helpers/MentionPill.ts +95 -0
  307. package/src/helpers/Permalinks.ts +101 -0
  308. package/src/helpers/ProfileCache.ts +119 -0
  309. package/src/helpers/RichReply.ts +46 -0
  310. package/src/helpers/UnpaddedBase64.ts +44 -0
  311. package/src/http.ts +166 -0
  312. package/src/identity/IdentityClient.ts +225 -0
  313. package/src/index.ts +125 -0
  314. package/src/logging/ConsoleLogger.ts +31 -0
  315. package/src/logging/ILogger.ts +40 -0
  316. package/src/logging/LogService.ts +167 -0
  317. package/src/logging/RichConsoleLogger.ts +70 -0
  318. package/src/metrics/IMetricListener.ts +57 -0
  319. package/src/metrics/Metrics.ts +134 -0
  320. package/src/metrics/contexts.ts +56 -0
  321. package/src/metrics/decorators.ts +94 -0
  322. package/src/metrics/names.ts +53 -0
  323. package/src/mixins/AutojoinRoomsMixin.ts +24 -0
  324. package/src/mixins/AutojoinUpgradedRoomsMixin.ts +37 -0
  325. package/src/models/Account.ts +8 -0
  326. package/src/models/CreateRoom.ts +144 -0
  327. package/src/models/Crypto.ts +188 -0
  328. package/src/models/EventContext.ts +23 -0
  329. package/src/models/IdentityServerModels.ts +18 -0
  330. package/src/models/MSC2176.ts +47 -0
  331. package/src/models/MatrixError.ts +39 -0
  332. package/src/models/MatrixProfile.ts +55 -0
  333. package/src/models/OpenIDConnect.ts +10 -0
  334. package/src/models/Policies.ts +28 -0
  335. package/src/models/PowerLevelAction.ts +31 -0
  336. package/src/models/PowerLevelBounds.ts +16 -0
  337. package/src/models/Presence.ts +38 -0
  338. package/src/models/ServerVersions.ts +8 -0
  339. package/src/models/Spaces.ts +167 -0
  340. package/src/models/Threepid.ts +8 -0
  341. package/src/models/events/AliasesEvent.ts +37 -0
  342. package/src/models/events/CanonicalAliasEvent.ts +30 -0
  343. package/src/models/events/CreateEvent.ts +82 -0
  344. package/src/models/events/EncryptedRoomEvent.ts +58 -0
  345. package/src/models/events/EncryptionEvent.ts +63 -0
  346. package/src/models/events/Event.ts +38 -0
  347. package/src/models/events/EventKind.ts +16 -0
  348. package/src/models/events/InvalidEventError.ts +19 -0
  349. package/src/models/events/JoinRulesEvent.ts +37 -0
  350. package/src/models/events/MembershipEvent.ts +77 -0
  351. package/src/models/events/MessageEvent.ts +292 -0
  352. package/src/models/events/PinnedEventsEvent.ts +30 -0
  353. package/src/models/events/PowerLevelsEvent.ts +135 -0
  354. package/src/models/events/PresenceEvent.ts +69 -0
  355. package/src/models/events/RedactionEvent.ts +44 -0
  356. package/src/models/events/RoomAvatarEvent.ts +36 -0
  357. package/src/models/events/RoomEvent.ts +83 -0
  358. package/src/models/events/RoomNameEvent.ts +27 -0
  359. package/src/models/events/RoomTopicEvent.ts +27 -0
  360. package/src/models/events/SpaceChildEvent.ts +74 -0
  361. package/src/models/events/_MissingEvents.md +35 -0
  362. package/src/models/events/converter.ts +47 -0
  363. package/src/models/unstable/MediaInfo.ts +16 -0
  364. package/src/preprocessors/IPreprocessor.ts +24 -0
  365. package/src/preprocessors/RichRepliesPreprocessor.ts +159 -0
  366. package/src/request.ts +21 -0
  367. package/src/simple-validation.ts +30 -0
  368. package/src/storage/IAppserviceStorageProvider.ts +54 -0
  369. package/src/storage/ICryptoStorageProvider.ts +36 -0
  370. package/src/storage/IStorageProvider.ts +53 -0
  371. package/src/storage/MemoryStorageProvider.ts +65 -0
  372. package/src/storage/RustSdkCryptoStorageProvider.ts +81 -0
  373. package/src/storage/SimpleFsStorageProvider.ts +142 -0
  374. package/src/storage/SimplePostgresStorageProvider.ts +168 -0
  375. package/src/strategies/AppserviceJoinRoomStrategy.ts +47 -0
  376. package/src/strategies/JoinRoomStrategy.ts +45 -0
  377. package/tsconfig.json +22 -0
@@ -0,0 +1,141 @@
1
+ import { MatrixClient } from "../MatrixClient";
2
+ import { LogService } from "../logging/LogService";
3
+ import { UIACallback } from "./RustEngine";
4
+
5
+ export type { UIACallback };
6
+
7
+ /**
8
+ * The subset of RustEngine used by the cross-signing helpers below.
9
+ * @internal
10
+ */
11
+ export interface CrossSigningEngine {
12
+ bootstrapCrossSigning(uiaCallback: UIACallback, reset?: boolean): Promise<void>;
13
+ bootstrapSecretStorageFromPassphrase(passphrase: string, opts?: { withKeyBackup?: boolean, reset?: boolean }): Promise<void>;
14
+ restoreSecretsFromSecretStorage(passphrase: string): Promise<void>;
15
+ }
16
+
17
+ /**
18
+ * Result of {@link CryptoClient.ensureCrossSigning}.
19
+ * - `already-signed`: our device was already signed by the account's self-signing key.
20
+ * - `restored`: the cross-signing keys were restored from secret storage (no reset).
21
+ * - `bootstrapped`: a new cross-signing identity was created and uploaded (reset).
22
+ * - `skipped-no-auth`: bootstrapping was needed, but no UIA callback was given.
23
+ * @category Encryption
24
+ */
25
+ export type EnsureCrossSigningResult = "already-signed" | "restored" | "bootstrapped" | "skipped-no-auth";
26
+
27
+ /**
28
+ * Result of {@link CryptoClient.ensureSecretStorage}.
29
+ * @category Encryption
30
+ */
31
+ export type EnsureSecretStorageResult = "already-configured" | "bootstrapped";
32
+
33
+ /**
34
+ * Options for {@link CryptoClient.ensureCrossSigning}.
35
+ * @category Encryption
36
+ */
37
+ export interface EnsureCrossSigningOptions {
38
+ /**
39
+ * Answers the UIA challenge when uploading new cross-signing keys. Without it,
40
+ * bootstrapping is skipped. See {@link passwordUiaCallback}.
41
+ */
42
+ uiaCallback?: UIACallback;
43
+ /**
44
+ * Secret storage passphrase. When set and the account has secret storage, the
45
+ * existing cross-signing keys are restored from it before falling back to a reset.
46
+ */
47
+ recoveryPassphrase?: string;
48
+ }
49
+
50
+ /**
51
+ * Builds a UIA callback that answers with an `m.login.password` stage.
52
+ * @category Encryption
53
+ */
54
+ export function passwordUiaCallback(userId: string, password: string): UIACallback {
55
+ return async (uia) => ({
56
+ type: "m.login.password",
57
+ identifier: { type: "m.id.user", user: userId },
58
+ password,
59
+ session: uia.session,
60
+ });
61
+ }
62
+
63
+ /**
64
+ * Checks whether the given device is signed by the account's self-signing key.
65
+ *
66
+ * This deliberately checks our device, not just whether the account has a master
67
+ * key: another client may have set up cross-signing without ever signing us.
68
+ * @internal
69
+ */
70
+ export async function isOwnDeviceCrossSigned(client: MatrixClient, deviceId: string): Promise<boolean> {
71
+ const userId = await client.getUserId();
72
+ const resp = await client.doRequest("POST", "/_matrix/client/v3/keys/query", null, {
73
+ device_keys: { [userId]: [] },
74
+ });
75
+ const selfSigningKeyIds = Object.keys(resp?.["self_signing_keys"]?.[userId]?.["keys"] ?? {});
76
+ const deviceSignatures = resp?.["device_keys"]?.[userId]?.[deviceId]?.["signatures"]?.[userId] ?? {};
77
+ return selfSigningKeyIds.some((keyId) => keyId in deviceSignatures);
78
+ }
79
+
80
+ /**
81
+ * Checks whether the account has a default secret storage key configured.
82
+ * @internal
83
+ */
84
+ export async function hasSecretStorage(client: MatrixClient): Promise<boolean> {
85
+ try {
86
+ const data = await client.getAccountData<{ key?: string }>("m.secret_storage.default_key");
87
+ return Boolean(data?.key);
88
+ } catch {
89
+ // getAccountData throws (404) when the event doesn't exist.
90
+ return false;
91
+ }
92
+ }
93
+
94
+ /**
95
+ * @internal
96
+ */
97
+ export async function ensureCrossSigning(
98
+ client: MatrixClient,
99
+ engine: CrossSigningEngine,
100
+ deviceId: string,
101
+ opts: EnsureCrossSigningOptions,
102
+ ): Promise<EnsureCrossSigningResult> {
103
+ if (await isOwnDeviceCrossSigned(client, deviceId)) {
104
+ return "already-signed";
105
+ }
106
+
107
+ if (opts.recoveryPassphrase && await hasSecretStorage(client)) {
108
+ try {
109
+ await engine.restoreSecretsFromSecretStorage(opts.recoveryPassphrase);
110
+ return "restored";
111
+ } catch (e) {
112
+ LogService.warn("CryptoClient", "Restoring cross-signing keys from secret storage failed, falling back to a reset:", e);
113
+ }
114
+ }
115
+
116
+ if (!opts.uiaCallback) {
117
+ return "skipped-no-auth";
118
+ }
119
+
120
+ // Neither signed nor restorable: create a fresh identity. This replaces any
121
+ // existing cross-signing keys on the account, so other devices' trust in the
122
+ // old identity is lost.
123
+ await engine.bootstrapCrossSigning(opts.uiaCallback, true);
124
+ return "bootstrapped";
125
+ }
126
+
127
+ /**
128
+ * @internal
129
+ */
130
+ export async function ensureSecretStorage(
131
+ client: MatrixClient,
132
+ engine: CrossSigningEngine,
133
+ passphrase: string,
134
+ opts: { withKeyBackup?: boolean },
135
+ ): Promise<EnsureSecretStorageResult> {
136
+ if (await hasSecretStorage(client)) {
137
+ return "already-configured";
138
+ }
139
+ await engine.bootstrapSecretStorageFromPassphrase(passphrase, { withKeyBackup: opts.withKeyBackup ?? true });
140
+ return "bootstrapped";
141
+ }
@@ -0,0 +1,378 @@
1
+ import {
2
+ DeviceId,
3
+ OlmMachine,
4
+ UserId,
5
+ DeviceLists,
6
+ RoomId,
7
+ Attachment,
8
+ EncryptedAttachment,
9
+ } from "@matrix-org/matrix-sdk-crypto-nodejs";
10
+
11
+ import { MatrixClient } from "../MatrixClient";
12
+ import { LogService } from "../logging/LogService";
13
+ import {
14
+ IMegolmEncrypted,
15
+ IOlmEncrypted,
16
+ IToDeviceMessage,
17
+ OTKAlgorithm,
18
+ OTKCounts,
19
+ Signatures,
20
+ } from "../models/Crypto";
21
+ import { requiresReady } from "./decorators";
22
+ import { RoomTracker } from "./RoomTracker";
23
+ import { EncryptedRoomEvent } from "../models/events/EncryptedRoomEvent";
24
+ import { RoomEvent } from "../models/events/RoomEvent";
25
+ import { EncryptedFile } from "../models/events/MessageEvent";
26
+ import { RustSdkCryptoStorageProvider } from "../storage/RustSdkCryptoStorageProvider";
27
+ import { RustEngine, SYNC_LOCK_NAME, UIACallback } from "./RustEngine";
28
+ import {
29
+ ensureCrossSigning,
30
+ EnsureCrossSigningOptions,
31
+ EnsureCrossSigningResult,
32
+ ensureSecretStorage,
33
+ EnsureSecretStorageResult,
34
+ hasSecretStorage,
35
+ isOwnDeviceCrossSigned,
36
+ } from "./CrossSigningBootstrap";
37
+ import { MembershipEvent } from "../models/events/MembershipEvent";
38
+
39
+ /**
40
+ * Manages encryption for a MatrixClient. Get an instance from a MatrixClient directly
41
+ * rather than creating one manually.
42
+ * @category Encryption
43
+ */
44
+ export class CryptoClient {
45
+ private ready = false;
46
+ private deviceId: string;
47
+ private deviceEd25519: string;
48
+ private deviceCurve25519: string;
49
+ private roomTracker: RoomTracker;
50
+ private engine: RustEngine;
51
+
52
+ public constructor(private client: MatrixClient) {
53
+ this.roomTracker = new RoomTracker(this.client);
54
+ }
55
+
56
+ private get storage(): RustSdkCryptoStorageProvider {
57
+ return <RustSdkCryptoStorageProvider> this.client.cryptoStore;
58
+ }
59
+
60
+ /**
61
+ * The device ID for the MatrixClient.
62
+ */
63
+ public get clientDeviceId(): string {
64
+ return this.deviceId;
65
+ }
66
+
67
+ /**
68
+ * The device's Ed25519 identity
69
+ */
70
+ public get clientDeviceEd25519(): string {
71
+ return this.deviceEd25519;
72
+ }
73
+
74
+ /**
75
+ * Whether or not the crypto client is ready to be used. If not ready, prepare() should be called.
76
+ * @see prepare
77
+ */
78
+ public get isReady(): boolean {
79
+ return this.ready;
80
+ }
81
+
82
+ /**
83
+ * Prepares the crypto client for usage.
84
+ * @param {string[]} roomIds The room IDs the MatrixClient is joined to.
85
+ */
86
+ public async prepare(roomIds: string[]) {
87
+ await this.roomTracker.prepare(roomIds);
88
+
89
+ if (this.ready) return; // stop re-preparing here
90
+
91
+ const storedDeviceId = await this.client.cryptoStore.getDeviceId();
92
+ if (storedDeviceId) {
93
+ this.deviceId = storedDeviceId;
94
+ } else {
95
+ const deviceId = (await this.client.getWhoAmI())['device_id'];
96
+ if (!deviceId) {
97
+ throw new Error("Encryption not possible: server not revealing device ID");
98
+ }
99
+ this.deviceId = deviceId;
100
+ await this.client.cryptoStore.setDeviceId(this.deviceId);
101
+ }
102
+
103
+ LogService.info("CryptoClient", "Starting with device ID:", this.deviceId); // info so all bots know for debugging
104
+
105
+ const machine = await OlmMachine.initialize(
106
+ new UserId(await this.client.getUserId()),
107
+ new DeviceId(this.deviceId),
108
+ this.storage.storagePath, "",
109
+ this.storage.storageType,
110
+ );
111
+ this.engine = new RustEngine(machine, this.client);
112
+ await this.engine.run();
113
+
114
+ const identity = this.engine.machine.identityKeys;
115
+ this.deviceCurve25519 = identity.curve25519.toBase64();
116
+ this.deviceEd25519 = identity.ed25519.toBase64();
117
+
118
+ LogService.debug("CryptoClient", "Running with device Ed25519 identity:", this.deviceEd25519); // info so all bots know for debugging
119
+
120
+ this.ready = true;
121
+ }
122
+
123
+ /**
124
+ * Handles a room event.
125
+ * @internal
126
+ * @param roomId The room ID.
127
+ * @param event The event.
128
+ */
129
+ public async onRoomEvent(roomId: string, event: any) {
130
+ await this.roomTracker.onRoomEvent(roomId, event);
131
+ if (typeof event['state_key'] !== 'string') return;
132
+ if (event['type'] === 'm.room.member') {
133
+ const membership = new MembershipEvent(event);
134
+ if (membership.effectiveMembership !== 'join' && membership.effectiveMembership !== 'invite') return;
135
+ await this.engine.addTrackedUsers([membership.membershipFor]);
136
+ } else if (event['type'] === 'm.room.encryption') {
137
+ const members = await this.client.getRoomMembers(roomId, null, ['join', 'invite']);
138
+ await this.engine.addTrackedUsers(members.map(e => e.membershipFor));
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Handles a room join.
144
+ * @internal
145
+ * @param roomId The room ID.
146
+ */
147
+ public async onRoomJoin(roomId: string) {
148
+ await this.roomTracker.onRoomJoin(roomId);
149
+ if (await this.isRoomEncrypted(roomId)) {
150
+ const members = await this.client.getRoomMembers(roomId, null, ['join', 'invite']);
151
+ await this.engine.addTrackedUsers(members.map(e => e.membershipFor));
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Checks if a room is encrypted.
157
+ * @param {string} roomId The room ID to check.
158
+ * @returns {Promise<boolean>} Resolves to true if encrypted, false otherwise.
159
+ */
160
+ @requiresReady()
161
+ public async isRoomEncrypted(roomId: string): Promise<boolean> {
162
+ const config = await this.roomTracker.getRoomCryptoConfig(roomId);
163
+ return !!config?.algorithm;
164
+ }
165
+
166
+ /**
167
+ * Updates the client's sync-related data.
168
+ * @param {Array.<IToDeviceMessage<IOlmEncrypted>>} toDeviceMessages The to-device messages received.
169
+ * @param {OTKCounts} otkCounts The current OTK counts.
170
+ * @param {OTKAlgorithm[]} unusedFallbackKeyAlgs The unused fallback key algorithms.
171
+ * @param {string[]} changedDeviceLists The user IDs which had device list changes.
172
+ * @param {string[]} leftDeviceLists The user IDs which the server believes we no longer need to track.
173
+ * @returns {Promise<void>} Resolves when complete.
174
+ */
175
+ @requiresReady()
176
+ public async updateSyncData(
177
+ toDeviceMessages: IToDeviceMessage<IOlmEncrypted>[],
178
+ otkCounts: OTKCounts,
179
+ unusedFallbackKeyAlgs: OTKAlgorithm[],
180
+ changedDeviceLists: string[],
181
+ leftDeviceLists: string[],
182
+ ): Promise<void> {
183
+ const deviceMessages = JSON.stringify(toDeviceMessages);
184
+ const deviceLists = new DeviceLists(
185
+ changedDeviceLists.map(u => new UserId(u)),
186
+ leftDeviceLists.map(u => new UserId(u)));
187
+
188
+ await this.engine.lock.acquire(SYNC_LOCK_NAME, async () => {
189
+ const syncResp = await this.engine.machine.receiveSyncChanges(deviceMessages, deviceLists, otkCounts, unusedFallbackKeyAlgs);
190
+ const decryptedToDeviceMessages = JSON.parse(syncResp);
191
+ if (Array.isArray(decryptedToDeviceMessages)) {
192
+ for (const msg of decryptedToDeviceMessages) {
193
+ this.client.emit("to_device.decrypted", msg);
194
+ }
195
+ }
196
+
197
+ await this.engine.run();
198
+ });
199
+ }
200
+
201
+ /**
202
+ * Signs an object using the device keys.
203
+ * @param {object} obj The object to sign.
204
+ * @returns {Promise<Signatures>} The signatures for the object.
205
+ */
206
+ @requiresReady()
207
+ public async sign(obj: object): Promise<Signatures> {
208
+ obj = JSON.parse(JSON.stringify(obj));
209
+ const existingSignatures = obj['signatures'] || {};
210
+
211
+ delete obj['signatures'];
212
+ delete obj['unsigned'];
213
+
214
+ const container = await this.engine.machine.sign(JSON.stringify(obj));
215
+ const userSignature = container.get(new UserId(await this.client.getUserId()));
216
+ const sig: Signatures = {
217
+ [await this.client.getUserId()]: {},
218
+ };
219
+ for (const [key, maybeSignature] of Object.entries(userSignature)) {
220
+ if (maybeSignature.isValid) {
221
+ sig[await this.client.getUserId()][key] = maybeSignature.signature.toBase64();
222
+ }
223
+ }
224
+ return {
225
+ ...sig,
226
+ ...existingSignatures,
227
+ };
228
+ }
229
+
230
+ /**
231
+ * Encrypts the details of a room event, returning an encrypted payload to be sent in an
232
+ * `m.room.encrypted` event to the room. If needed, this function will send decryption keys
233
+ * to the appropriate devices in the room (this happens when the Megolm session rotates or
234
+ * gets created).
235
+ * @param {string} roomId The room ID to encrypt within. If the room is not encrypted, an
236
+ * error is thrown.
237
+ * @param {string} eventType The event type being encrypted.
238
+ * @param {any} content The event content being encrypted.
239
+ * @returns {Promise<IMegolmEncrypted>} Resolves to the encrypted content for an `m.room.encrypted` event.
240
+ */
241
+ @requiresReady()
242
+ public async encryptRoomEvent(roomId: string, eventType: string, content: any): Promise<IMegolmEncrypted> {
243
+ if (!(await this.isRoomEncrypted(roomId))) {
244
+ throw new Error("Room is not encrypted");
245
+ }
246
+
247
+ await this.engine.prepareEncrypt(roomId, await this.roomTracker.getRoomCryptoConfig(roomId));
248
+
249
+ const encrypted = JSON.parse(await this.engine.machine.encryptRoomEvent(new RoomId(roomId), eventType, JSON.stringify(content)));
250
+ await this.engine.run();
251
+ return encrypted as IMegolmEncrypted;
252
+ }
253
+
254
+ /**
255
+ * Decrypts a room event. Currently only supports Megolm-encrypted events (default for this SDK).
256
+ * @param {EncryptedRoomEvent} event The encrypted event.
257
+ * @param {string} roomId The room ID where the event was sent.
258
+ * @returns {Promise<RoomEvent<unknown>>} Resolves to a decrypted room event, or rejects/throws with
259
+ * an error if the event is undecryptable.
260
+ */
261
+ @requiresReady()
262
+ public async decryptRoomEvent(event: EncryptedRoomEvent, roomId: string): Promise<RoomEvent<unknown>> {
263
+ const decrypted = await this.engine.machine.decryptRoomEvent(JSON.stringify(event.raw), new RoomId(roomId));
264
+ const clearEvent = JSON.parse(decrypted.event);
265
+
266
+ return new RoomEvent<unknown>({
267
+ ...event.raw,
268
+ type: clearEvent.type || "io.t2bot.unknown",
269
+ content: (typeof (clearEvent.content) === 'object') ? clearEvent.content : {},
270
+ });
271
+ }
272
+
273
+ /**
274
+ * Encrypts a file for uploading in a room, returning the encrypted data and information
275
+ * to include in a message event (except media URL) for sending.
276
+ * @param {Buffer} file The file to encrypt.
277
+ * @returns {{buffer: Buffer, file: Omit<EncryptedFile, "url">}} Resolves to the encrypted
278
+ * contents and file information.
279
+ */
280
+ @requiresReady()
281
+ public async encryptMedia(file: Buffer): Promise<{ buffer: Buffer, file: Omit<EncryptedFile, "url"> }> {
282
+ const encrypted = Attachment.encrypt(file);
283
+ const info = JSON.parse(encrypted.mediaEncryptionInfo);
284
+ return {
285
+ buffer: Buffer.from(encrypted.encryptedData),
286
+ file: info,
287
+ };
288
+ }
289
+
290
+ /**
291
+ * Decrypts a previously-uploaded encrypted file, validating the fields along the way.
292
+ * @param {EncryptedFile} file The file to decrypt.
293
+ * @returns {Promise<Buffer>} Resolves to the decrypted file contents.
294
+ */
295
+ @requiresReady()
296
+ public async decryptMedia(file: EncryptedFile): Promise<Buffer> {
297
+ const contents = (await this.client.downloadContent(file.url)).data;
298
+ const encrypted = new EncryptedAttachment(
299
+ contents,
300
+ JSON.stringify(file),
301
+ );
302
+ const decrypted = Attachment.decrypt(encrypted);
303
+ return Buffer.from(decrypted);
304
+ }
305
+
306
+ /**
307
+ * Creates and uploads a cross-signing identity, then signs this device with it.
308
+ * @param {UIACallback} uiaCallback Answers the UIA challenge for the key upload.
309
+ * @param {boolean} reset Whether to replace an existing local identity.
310
+ */
311
+ @requiresReady()
312
+ public async bootstrapCrossSigning(uiaCallback: UIACallback, reset = false): Promise<void> {
313
+ return this.engine.bootstrapCrossSigning(uiaCallback, reset);
314
+ }
315
+
316
+ /**
317
+ * Sets up secret storage (4S) from a passphrase and stores the cross-signing
318
+ * keys in it. Requires the cross-signing private keys to be available locally.
319
+ * @param {string} passphrase The secret storage passphrase.
320
+ * @param opts Whether to also set up server-side key backup, and whether to reset.
321
+ */
322
+ @requiresReady()
323
+ public async bootstrapSecretStorageFromPassphrase(passphrase: string, opts: { withKeyBackup?: boolean, reset?: boolean } = {}): Promise<void> {
324
+ return this.engine.bootstrapSecretStorageFromPassphrase(passphrase, opts);
325
+ }
326
+
327
+ /**
328
+ * Restores the cross-signing keys from secret storage, e.g. after losing the
329
+ * crypto store, without invalidating other devices' trust.
330
+ * @param {string} passphrase The secret storage passphrase.
331
+ */
332
+ @requiresReady()
333
+ public async restoreSecretsFromSecretStorage(passphrase: string): Promise<void> {
334
+ return this.engine.restoreSecretsFromSecretStorage(passphrase);
335
+ }
336
+
337
+ /**
338
+ * Whether this device is signed by the account's self-signing key.
339
+ */
340
+ @requiresReady()
341
+ public async isOwnDeviceCrossSigned(): Promise<boolean> {
342
+ return isOwnDeviceCrossSigned(this.client, this.deviceId);
343
+ }
344
+
345
+ /**
346
+ * Whether the account has a default secret storage key.
347
+ */
348
+ @requiresReady()
349
+ public async hasSecretStorage(): Promise<boolean> {
350
+ return hasSecretStorage(this.client);
351
+ }
352
+
353
+ /**
354
+ * Makes sure this device is cross-signed. In order: does nothing if it already
355
+ * is; restores the keys from secret storage if a passphrase is given and the
356
+ * account has secret storage; otherwise creates a new identity (replacing the
357
+ * account's existing one) if a UIA callback is given. Errors are thrown.
358
+ * @param {EnsureCrossSigningOptions} opts Credentials for restoring or bootstrapping.
359
+ * @returns {Promise<EnsureCrossSigningResult>} What was done.
360
+ */
361
+ @requiresReady()
362
+ public async ensureCrossSigning(opts: EnsureCrossSigningOptions = {}): Promise<EnsureCrossSigningResult> {
363
+ return ensureCrossSigning(this.client, this.engine, this.deviceId, opts);
364
+ }
365
+
366
+ /**
367
+ * Sets up secret storage from a passphrase unless the account already has it.
368
+ * Call after {@link ensureCrossSigning}, since the cross-signing private keys
369
+ * must be available locally to be stored.
370
+ * @param {string} passphrase The secret storage passphrase.
371
+ * @param opts Whether to also set up server-side key backup (default true).
372
+ * @returns {Promise<EnsureSecretStorageResult>} What was done.
373
+ */
374
+ @requiresReady()
375
+ public async ensureSecretStorage(passphrase: string, opts: { withKeyBackup?: boolean } = {}): Promise<EnsureSecretStorageResult> {
376
+ return ensureSecretStorage(this.client, this.engine, passphrase, opts);
377
+ }
378
+ }
@@ -0,0 +1,9 @@
1
+ import { EncryptionEventContent } from "../models/events/EncryptionEvent";
2
+
3
+ /**
4
+ * Information about a room for the purposes of crypto.
5
+ * @category Encryption
6
+ */
7
+ export interface ICryptoRoomInformation extends Partial<EncryptionEventContent> {
8
+ historyVisibility?: string;
9
+ }
@@ -0,0 +1,99 @@
1
+ import { MatrixClient } from "../MatrixClient";
2
+ import { EncryptionEventContent } from "../models/events/EncryptionEvent";
3
+ import { ICryptoRoomInformation } from "./ICryptoRoomInformation";
4
+
5
+ // noinspection ES6RedundantAwait
6
+ /**
7
+ * Tracks room encryption status for a MatrixClient.
8
+ * @category Encryption
9
+ */
10
+ export class RoomTracker {
11
+ public constructor(private client: MatrixClient) {
12
+ }
13
+
14
+ /**
15
+ * Handles a room join
16
+ * @internal
17
+ * @param roomId The room ID.
18
+ */
19
+ public async onRoomJoin(roomId: string) {
20
+ await this.queueRoomCheck(roomId);
21
+ }
22
+
23
+ /**
24
+ * Handles a room event.
25
+ * @internal
26
+ * @param roomId The room ID.
27
+ * @param event The event.
28
+ */
29
+ public async onRoomEvent(roomId: string, event: any) {
30
+ if (event['state_key'] !== '') return; // we don't care about anything else
31
+ if (event['type'] === 'm.room.encryption' || event['type'] === 'm.room.history_visibility') {
32
+ await this.queueRoomCheck(roomId);
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Prepares the room tracker to track the given rooms.
38
+ * @param {string[]} roomIds The room IDs to track. This should be the joined rooms set.
39
+ */
40
+ public async prepare(roomIds: string[]) {
41
+ for (const roomId of roomIds) {
42
+ await this.queueRoomCheck(roomId);
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Queues a room check for the tracker. If the room needs an update to the store, an
48
+ * update will be made.
49
+ * @param {string} roomId The room ID to check.
50
+ */
51
+ public async queueRoomCheck(roomId: string) {
52
+ const config = await this.client.cryptoStore.getRoom(roomId);
53
+ if (config) {
54
+ if (config.algorithm !== undefined) {
55
+ return; // assume no change to encryption config
56
+ }
57
+ }
58
+
59
+ let encEvent: Partial<EncryptionEventContent>;
60
+ try {
61
+ encEvent = await this.client.getRoomStateEvent(roomId, "m.room.encryption", "");
62
+ encEvent.algorithm = encEvent.algorithm ?? 'UNKNOWN';
63
+ } catch (e) {
64
+ return; // failure == no encryption
65
+ }
66
+
67
+ // Pick out the history visibility setting too
68
+ let historyVisibility: string;
69
+ try {
70
+ const ev = await this.client.getRoomStateEvent(roomId, "m.room.history_visibility", "");
71
+ historyVisibility = ev.history_visibility;
72
+ } catch (e) {
73
+ // ignore - we'll just treat history visibility as normal
74
+ }
75
+
76
+ await this.client.cryptoStore.storeRoom(roomId, {
77
+ ...encEvent,
78
+ historyVisibility,
79
+ });
80
+ }
81
+
82
+ /**
83
+ * Gets the room's crypto configuration, as known by the underlying store. If the room is
84
+ * not encrypted then this will return an empty object.
85
+ * @param {string} roomId The room ID to get the config for.
86
+ * @returns {Promise<ICryptoRoomInformation>} Resolves to the encryption config.
87
+ */
88
+ public async getRoomCryptoConfig(roomId: string): Promise<ICryptoRoomInformation> {
89
+ let config = await this.client.cryptoStore.getRoom(roomId);
90
+ if (!config) {
91
+ await this.queueRoomCheck(roomId);
92
+ config = await this.client.cryptoStore.getRoom(roomId);
93
+ }
94
+ if (!config) {
95
+ return {};
96
+ }
97
+ return config;
98
+ }
99
+ }