@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,803 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Appservice = void 0;
4
+ const express = require("express");
5
+ const events_1 = require("events");
6
+ const morgan = require("morgan");
7
+ const LRU = require("lru-cache");
8
+ const querystring_1 = require("querystring");
9
+ const Intent_1 = require("./Intent");
10
+ const __1 = require("..");
11
+ const MatrixBridge_1 = require("./MatrixBridge");
12
+ const EDU_ANNOTATION_KEY = "io.t2bot.sdk.bot.type";
13
+ var EduAnnotation;
14
+ (function (EduAnnotation) {
15
+ EduAnnotation["ToDevice"] = "to_device";
16
+ EduAnnotation["Ephemeral"] = "ephemeral";
17
+ })(EduAnnotation || (EduAnnotation = {}));
18
+ /**
19
+ * Represents an application service. This provides helper utilities such as tracking
20
+ * of user intents (clients that are aware of their membership in rooms).
21
+ * @category Application services
22
+ */
23
+ class Appservice extends events_1.EventEmitter {
24
+ /**
25
+ * Creates a new application service.
26
+ * @param {IAppserviceOptions} options The options for the application service.
27
+ */
28
+ constructor(options) {
29
+ super();
30
+ this.options = options;
31
+ /**
32
+ * The metrics instance for this appservice. This will raise all metrics
33
+ * from this appservice instance as well as any intents/MatrixClients created
34
+ * by the appservice.
35
+ */
36
+ this.metrics = new __1.Metrics();
37
+ this.bridgeInstance = new MatrixBridge_1.MatrixBridge(this);
38
+ this.app = express();
39
+ this.eventProcessors = {};
40
+ this.pendingTransactions = {};
41
+ options.joinStrategy = new __1.AppserviceJoinRoomStrategy(options.joinStrategy, this);
42
+ if (!options.intentOptions)
43
+ options.intentOptions = {};
44
+ if (!options.intentOptions.maxAgeMs)
45
+ options.intentOptions.maxAgeMs = 60 * 60 * 1000;
46
+ if (!options.intentOptions.maxCached)
47
+ options.intentOptions.maxCached = 10000;
48
+ this.intentsCache = new LRU.LRUCache({
49
+ max: options.intentOptions.maxCached,
50
+ ttl: options.intentOptions.maxAgeMs,
51
+ });
52
+ this.registration = options.registration;
53
+ // If protocol is not defined, define an empty array.
54
+ if (!this.registration.protocols) {
55
+ this.registration.protocols = [];
56
+ }
57
+ this.storage = options.storage || new __1.MemoryStorageProvider();
58
+ options.storage = this.storage;
59
+ this.cryptoStorage = options.cryptoStorage;
60
+ this.app.use(express.json({ limit: Number.MAX_SAFE_INTEGER })); // disable limits, use a reverse proxy
61
+ morgan.token('url-safe', (req) => `${req.path}?${(0, querystring_1.stringify)((0, __1.redactObjectForLogging)(req.query ?? {}))}`);
62
+ this.app.use(morgan(
63
+ // Same as "combined", but with sensitive values removed from requests.
64
+ ':remote-addr - :remote-user [:date[clf]] ":method :url-safe HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"', { stream: { write: __1.LogService.info.bind(__1.LogService, 'Appservice') } }));
65
+ // ETag headers break the tests sometimes, and we don't actually need them anyways for
66
+ // appservices - none of this should be cached.
67
+ this.app.set('etag', false);
68
+ this.app.get("/users/:userId", this.onUser.bind(this));
69
+ this.app.get("/rooms/:roomAlias", this.onRoomAlias.bind(this));
70
+ this.app.put("/transactions/:txnId", this.onTransaction.bind(this));
71
+ this.app.get("/_matrix/app/v1/users/:userId", this.onUser.bind(this));
72
+ this.app.get("/_matrix/app/v1/rooms/:roomAlias", this.onRoomAlias.bind(this));
73
+ this.app.put("/_matrix/app/v1/transactions/:txnId", this.onTransaction.bind(this));
74
+ this.app.get("/_matrix/app/v1/thirdparty/protocol/:protocol", this.onThirdpartyProtocol.bind(this));
75
+ this.app.get("/_matrix/app/v1/thirdparty/user/:protocol", this.onThirdpartyUser.bind(this));
76
+ this.app.get("/_matrix/app/v1/thirdparty/user", this.onThirdpartyUser.bind(this));
77
+ this.app.get("/_matrix/app/v1/thirdparty/location/:protocol", this.onThirdpartyLocation.bind(this));
78
+ this.app.get("/_matrix/app/v1/thirdparty/location", this.onThirdpartyLocation.bind(this));
79
+ this.app.post("/_matrix/app/unstable/org.matrix.msc3983/keys/claim", this.onKeysClaim.bind(this));
80
+ this.app.post("/_matrix/app/unstable/org.matrix.msc3984/keys/query", this.onKeysQuery.bind(this));
81
+ // Workaround for https://github.com/matrix-org/synapse/issues/3780
82
+ this.app.post("/_matrix/app/v1/unstable/org.matrix.msc3983/keys/claim", this.onKeysClaim.bind(this));
83
+ this.app.post("/unstable/org.matrix.msc3983/keys/claim", this.onKeysClaim.bind(this));
84
+ this.app.post("/_matrix/app/v1/unstable/org.matrix.msc3984/keys/query", this.onKeysQuery.bind(this));
85
+ this.app.post("/unstable/org.matrix.msc3984/keys/query", this.onKeysQuery.bind(this));
86
+ // We register the 404 handler in the `begin()` function to allow consumers to add their own endpoints.
87
+ if (!this.registration.namespaces || !this.registration.namespaces.users || this.registration.namespaces.users.length === 0) {
88
+ throw new Error("No user namespaces in registration");
89
+ }
90
+ if (this.registration.namespaces.users.length !== 1) {
91
+ throw new Error("Too many user namespaces registered: expecting exactly one");
92
+ }
93
+ const userPrefix = (this.registration.namespaces.users[0].regex || "").split(":")[0];
94
+ if (!userPrefix.endsWith(".*") && !userPrefix.endsWith(".+")) {
95
+ this.userPrefix = null;
96
+ }
97
+ else {
98
+ this.userPrefix = userPrefix.substring(0, userPrefix.length - 2); // trim off the .* part
99
+ }
100
+ if (!this.registration.namespaces?.aliases || this.registration.namespaces.aliases.length !== 1) {
101
+ this.aliasPrefix = null;
102
+ }
103
+ else {
104
+ this.aliasPrefix = (this.registration.namespaces.aliases[0].regex || "").split(":")[0];
105
+ if (!this.aliasPrefix.endsWith(".*") && !this.aliasPrefix.endsWith(".+")) {
106
+ this.aliasPrefix = null;
107
+ }
108
+ else {
109
+ this.aliasPrefix = this.aliasPrefix.substring(0, this.aliasPrefix.length - 2); // trim off the .* part
110
+ }
111
+ }
112
+ }
113
+ /**
114
+ * Gets the express app instance which is serving requests. Not recommended for
115
+ * general usage, but may be used to append routes to the web server.
116
+ */
117
+ get expressAppInstance() {
118
+ return this.app;
119
+ }
120
+ /**
121
+ * Gets the bridge-specific APIs for this application service.
122
+ */
123
+ get bridge() {
124
+ return this.bridgeInstance;
125
+ }
126
+ /**
127
+ * Get the application service's "bot" user ID (the sender_localpart).
128
+ */
129
+ get botUserId() {
130
+ return this.getUserId(this.registration.sender_localpart);
131
+ }
132
+ /**
133
+ * Get the application service's "bot" Intent (the sender_localpart).
134
+ * @returns {Intent} The intent for the application service itself.
135
+ */
136
+ get botIntent() {
137
+ return this.getIntentForUserId(this.botUserId);
138
+ }
139
+ /**
140
+ * Get the application service's "bot" MatrixClient (the sender_localpart).
141
+ * Normally the botIntent should be used to ensure that the bot user is safely
142
+ * handled.
143
+ * @returns {MatrixClient} The client for the application service itself.
144
+ */
145
+ get botClient() {
146
+ return this.botIntent.underlyingClient;
147
+ }
148
+ /**
149
+ * Starts the application service, opening the bind address to begin processing requests.
150
+ * @returns {Promise<void>} resolves when started
151
+ */
152
+ begin() {
153
+ return new Promise((resolve, reject) => {
154
+ // Per constructor, all other endpoints should 404.
155
+ // Technically, according to https://spec.matrix.org/v1.6/application-service-api/#unknown-routes we should
156
+ // be returning 405 for *known* endpoints with the wrong method.
157
+ this.app.all("*", (req, res) => {
158
+ res.status(404).json({ errcode: "M_UNRECOGNIZED", error: "Endpoint not implemented" });
159
+ });
160
+ this.appServer = this.app.listen(this.options.port, this.options.bindAddress, () => resolve());
161
+ }).then(async () => {
162
+ if (this.options.intentOptions?.encryption) {
163
+ await this.botIntent.enableEncryption();
164
+ }
165
+ else {
166
+ await this.botIntent.ensureRegistered();
167
+ }
168
+ });
169
+ }
170
+ /**
171
+ * Stops the application service, freeing the web server.
172
+ */
173
+ stop() {
174
+ if (!this.appServer)
175
+ return;
176
+ this.appServer.close();
177
+ }
178
+ /**
179
+ * Gets an intent for a given localpart. The user ID will be formed with the domain name given
180
+ * in the constructor.
181
+ * @param localpart The localpart to get an Intent for.
182
+ * @returns {Intent} An Intent for the user.
183
+ */
184
+ getIntent(localpart) {
185
+ return this.getIntentForUserId(this.getUserId(localpart));
186
+ }
187
+ /**
188
+ * Gets a full user ID for a given localpart. The user ID will be formed with the domain name given
189
+ * in the constructor.
190
+ * @param localpart The localpart to get a user ID for.
191
+ * @returns {string} The user's ID.
192
+ */
193
+ getUserId(localpart) {
194
+ return `@${localpart}:${this.options.homeserverName}`;
195
+ }
196
+ /**
197
+ * Gets an Intent for a given user suffix. The prefix is automatically detected from the registration
198
+ * options.
199
+ * @param suffix The user's suffix
200
+ * @returns {Intent} An Intent for the user.
201
+ */
202
+ getIntentForSuffix(suffix) {
203
+ return this.getIntentForUserId(this.getUserIdForSuffix(suffix));
204
+ }
205
+ /**
206
+ * Gets a full user ID for a given suffix. The prefix is automatically detected from the registration
207
+ * options.
208
+ * @param suffix The user's suffix
209
+ * @returns {string} The user's ID.
210
+ */
211
+ getUserIdForSuffix(suffix) {
212
+ if (!this.userPrefix) {
213
+ throw new Error(`Cannot use getUserIdForSuffix, provided namespace did not include a valid suffix`);
214
+ }
215
+ return `${this.userPrefix}${suffix}:${this.options.homeserverName}`;
216
+ }
217
+ /**
218
+ * Gets an Intent for a given user ID.
219
+ * @param {string} userId The user ID to get an Intent for.
220
+ * @returns {Intent} An Intent for the user.
221
+ */
222
+ getIntentForUserId(userId) {
223
+ let intent = this.intentsCache.get(userId);
224
+ if (!intent) {
225
+ intent = new Intent_1.Intent(this.options, userId, this);
226
+ this.intentsCache.set(userId, intent);
227
+ if (this.options.intentOptions.encryption) {
228
+ intent.enableEncryption().catch(e => {
229
+ __1.LogService.error("Appservice", `Failed to set up crypto on intent ${userId}`, e);
230
+ throw e; // re-throw to cause unhandled exception
231
+ });
232
+ }
233
+ }
234
+ return intent;
235
+ }
236
+ /**
237
+ * Gets the suffix for the provided user ID. If the user ID is not a namespaced
238
+ * user, this will return a falsey value.
239
+ * @param {string} userId The user ID to parse
240
+ * @returns {string} The suffix from the user ID.
241
+ */
242
+ getSuffixForUserId(userId) {
243
+ if (!this.userPrefix) {
244
+ throw new Error(`Cannot use getUserIdForSuffix, provided namespace did not include a valid suffix`);
245
+ }
246
+ if (!userId || !userId.startsWith(this.userPrefix) || !userId.endsWith(`:${this.options.homeserverName}`)) {
247
+ // Invalid ID
248
+ return null;
249
+ }
250
+ return userId
251
+ .split('')
252
+ .slice(this.userPrefix.length)
253
+ .reverse()
254
+ .slice(this.options.homeserverName.length + 1)
255
+ .reverse()
256
+ .join('');
257
+ }
258
+ /**
259
+ * Determines if a given user ID is namespaced by this application service.
260
+ * @param {string} userId The user ID to check
261
+ * @returns {boolean} true if the user is namespaced, false otherwise
262
+ */
263
+ isNamespacedUser(userId) {
264
+ return userId === this.botUserId ||
265
+ !!this.registration.namespaces?.users.find(({ regex }) => new RegExp(regex).test(userId));
266
+ }
267
+ /**
268
+ * Gets a full alias for a given localpart. The alias will be formed with the domain name given
269
+ * in the constructor.
270
+ * @param localpart The localpart to get an alias for.
271
+ * @returns {string} The alias.
272
+ */
273
+ getAlias(localpart) {
274
+ return `#${localpart}:${this.options.homeserverName}`;
275
+ }
276
+ /**
277
+ * Gets a full alias for a given suffix. The prefix is automatically detected from the registration
278
+ * options.
279
+ * @param suffix The alias's suffix
280
+ * @returns {string} The alias.
281
+ */
282
+ getAliasForSuffix(suffix) {
283
+ if (!this.aliasPrefix) {
284
+ throw new Error("Invalid configured alias prefix");
285
+ }
286
+ return `${this.aliasPrefix}${suffix}:${this.options.homeserverName}`;
287
+ }
288
+ /**
289
+ * Gets the localpart of an alias for a given suffix. The prefix is automatically detected from the registration
290
+ * options. Useful for the createRoom endpoint.
291
+ * @param suffix The alias's suffix
292
+ * @returns {string} The alias localpart.
293
+ */
294
+ getAliasLocalpartForSuffix(suffix) {
295
+ if (!this.aliasPrefix) {
296
+ throw new Error("Invalid configured alias prefix");
297
+ }
298
+ return `${this.aliasPrefix.substr(1)}${suffix}`;
299
+ }
300
+ /**
301
+ * Gets the suffix for the provided alias. If the alias is not a namespaced
302
+ * alias, this will return a falsey value.
303
+ * @param {string} alias The alias to parse
304
+ * @returns {string} The suffix from the alias.
305
+ */
306
+ getSuffixForAlias(alias) {
307
+ if (!this.aliasPrefix) {
308
+ throw new Error("Invalid configured alias prefix");
309
+ }
310
+ if (!alias || !this.isNamespacedAlias(alias)) {
311
+ // Invalid ID
312
+ return null;
313
+ }
314
+ return alias
315
+ .split('')
316
+ .slice(this.aliasPrefix.length)
317
+ .reverse()
318
+ .slice(this.options.homeserverName.length + 1)
319
+ .reverse()
320
+ .join('');
321
+ }
322
+ /**
323
+ * Determines if a given alias is namespaced by this application service.
324
+ * @param {string} alias The alias to check
325
+ * @returns {boolean} true if the alias is namespaced, false otherwise
326
+ */
327
+ isNamespacedAlias(alias) {
328
+ if (!this.aliasPrefix) {
329
+ throw new Error("Invalid configured alias prefix");
330
+ }
331
+ return alias.startsWith(this.aliasPrefix) && alias.endsWith(":" + this.options.homeserverName);
332
+ }
333
+ /**
334
+ * Adds a preprocessor to the event pipeline. When this appservice encounters an event, it
335
+ * will try to run it through the preprocessors it can in the order they were added.
336
+ * @param {IPreprocessor} preprocessor the preprocessor to add
337
+ */
338
+ addPreprocessor(preprocessor) {
339
+ if (!preprocessor)
340
+ throw new Error("Preprocessor cannot be null");
341
+ const eventTypes = preprocessor.getSupportedEventTypes();
342
+ if (!eventTypes)
343
+ return; // Nothing to do
344
+ for (const eventType of eventTypes) {
345
+ if (!this.eventProcessors[eventType])
346
+ this.eventProcessors[eventType] = [];
347
+ this.eventProcessors[eventType].push(preprocessor);
348
+ }
349
+ }
350
+ /**
351
+ * Sets the visibility of a room in the appservice's room directory.
352
+ * @param {string} networkId The network ID to group the room under.
353
+ * @param {string} roomId The room ID to manipulate the visibility of.
354
+ * @param {"public" | "private"} visibility The visibility to set for the room.
355
+ * @return {Promise<any>} resolves when the visibility has been updated.
356
+ */
357
+ setRoomDirectoryVisibility(networkId, roomId, visibility) {
358
+ roomId = encodeURIComponent(roomId);
359
+ networkId = encodeURIComponent(networkId);
360
+ return this.botClient.doRequest("PUT", `/_matrix/client/v3/directory/list/appservice/${networkId}/${roomId}`, null, {
361
+ visibility,
362
+ });
363
+ }
364
+ async processEphemeralEvent(event) {
365
+ if (!event)
366
+ return event;
367
+ if (!this.eventProcessors[event["type"]])
368
+ return event;
369
+ for (const processor of this.eventProcessors[event["type"]]) {
370
+ await processor.processEvent(event, this.botIntent.underlyingClient, __1.EventKind.EphemeralEvent);
371
+ }
372
+ return event;
373
+ }
374
+ async processEvent(event) {
375
+ if (!event)
376
+ return event;
377
+ if (!this.eventProcessors[event["type"]])
378
+ return event;
379
+ for (const processor of this.eventProcessors[event["type"]]) {
380
+ await processor.processEvent(event, this.botIntent.underlyingClient, __1.EventKind.RoomEvent);
381
+ }
382
+ return event;
383
+ }
384
+ async processMembershipEvent(event) {
385
+ if (!event["content"])
386
+ return;
387
+ const domain = new __1.UserID(event['state_key']).domain;
388
+ const botDomain = new __1.UserID(this.botUserId).domain;
389
+ if (domain !== botDomain)
390
+ return; // can't be impersonated, so don't try
391
+ // Update the target intent's joined rooms (fixes transition errors with the cache, like join->kick->join)
392
+ const intent = this.getIntentForUserId(event['state_key']);
393
+ await intent.refreshJoinedRooms();
394
+ const targetMembership = event["content"]["membership"];
395
+ if (targetMembership === "join") {
396
+ this.emit("room.join", event["room_id"], event);
397
+ await intent.underlyingClient.crypto?.onRoomJoin(event["room_id"]);
398
+ }
399
+ else if (targetMembership === "ban" || targetMembership === "leave") {
400
+ this.emit("room.leave", event["room_id"], event);
401
+ }
402
+ else if (targetMembership === "invite") {
403
+ this.emit("room.invite", event["room_id"], event);
404
+ }
405
+ }
406
+ isAuthed(req) {
407
+ let providedToken = req.query ? req.query["access_token"] : null;
408
+ if (req.headers && req.headers["authorization"]) {
409
+ const authHeader = req.headers["authorization"];
410
+ if (!authHeader.startsWith("Bearer "))
411
+ providedToken = null;
412
+ else
413
+ providedToken = authHeader.substring("Bearer ".length);
414
+ }
415
+ return providedToken === this.registration.hs_token;
416
+ }
417
+ async onTransaction(req, res) {
418
+ if (!this.isAuthed(req)) {
419
+ res.status(401).json({ errcode: "AUTH_FAILED", error: "Authentication failed" });
420
+ return;
421
+ }
422
+ if (typeof (req.body) !== "object") {
423
+ res.status(400).json({ errcode: "BAD_REQUEST", error: "Expected JSON" });
424
+ return;
425
+ }
426
+ if (!req.body["events"] || !Array.isArray(req.body["events"])) {
427
+ res.status(400).json({ errcode: "BAD_REQUEST", error: "Invalid JSON: expected events" });
428
+ return;
429
+ }
430
+ const txnId = req.params["txnId"];
431
+ if (await Promise.resolve(this.storage.isTransactionCompleted(txnId))) {
432
+ res.status(200).json({});
433
+ return;
434
+ }
435
+ if (this.pendingTransactions[txnId]) {
436
+ try {
437
+ await this.pendingTransactions[txnId];
438
+ res.status(200).json({});
439
+ }
440
+ catch (e) {
441
+ __1.LogService.error("Appservice", e);
442
+ res.status(500).json({});
443
+ }
444
+ return;
445
+ }
446
+ __1.LogService.info("Appservice", "Processing transaction " + txnId);
447
+ // eslint-disable-next-line no-async-promise-executor
448
+ this.pendingTransactions[txnId] = new Promise(async (resolve) => {
449
+ // Process all the crypto stuff first to ensure that future transactions (if not this one)
450
+ // will decrypt successfully. We start with EDUs because we need structures to put counts
451
+ // and such into in a later stage, and EDUs are independent of crypto.
452
+ const byUserId = {};
453
+ const orderedEdus = [];
454
+ if (Array.isArray(req.body["de.sorunome.msc2409.to_device"])) {
455
+ orderedEdus.push(...req.body["de.sorunome.msc2409.to_device"].map(e => ({
456
+ ...e,
457
+ unsigned: {
458
+ ...e['unsigned'],
459
+ [EDU_ANNOTATION_KEY]: EduAnnotation.ToDevice,
460
+ },
461
+ })));
462
+ }
463
+ if (Array.isArray(req.body["de.sorunome.msc2409.ephemeral"])) {
464
+ orderedEdus.push(...req.body["de.sorunome.msc2409.ephemeral"].map(e => ({
465
+ ...e,
466
+ unsigned: {
467
+ ...e['unsigned'],
468
+ [EDU_ANNOTATION_KEY]: EduAnnotation.Ephemeral,
469
+ },
470
+ })));
471
+ }
472
+ for (let event of orderedEdus) {
473
+ if (event['edu_type'])
474
+ event['type'] = event['edu_type']; // handle property change during MSC2409's course
475
+ __1.LogService.info("Appservice", `Processing ${event['unsigned'][EDU_ANNOTATION_KEY]} event of type ${event["type"]}`);
476
+ event = await this.processEphemeralEvent(event);
477
+ // These events aren't tied to rooms, so just emit them generically
478
+ this.emit("ephemeral.event", event);
479
+ if (this.cryptoStorage && (event["type"] === "m.room.encrypted" || event.unsigned?.[EDU_ANNOTATION_KEY] === EduAnnotation.ToDevice)) {
480
+ const toUser = event["to_user_id"];
481
+ const intent = this.getIntentForUserId(toUser);
482
+ await intent.enableEncryption();
483
+ if (!byUserId[toUser])
484
+ byUserId[toUser] = { counts: null, toDevice: null, unusedFallbacks: null };
485
+ if (!byUserId[toUser].toDevice)
486
+ byUserId[toUser].toDevice = [];
487
+ byUserId[toUser].toDevice.push(event);
488
+ }
489
+ }
490
+ const deviceLists = req.body["org.matrix.msc3202.device_lists"] ?? {
491
+ changed: [],
492
+ removed: [],
493
+ };
494
+ if (!deviceLists.changed)
495
+ deviceLists.changed = [];
496
+ if (!deviceLists.removed)
497
+ deviceLists.removed = [];
498
+ if (deviceLists.changed.length || deviceLists.removed.length) {
499
+ this.emit("device_lists", deviceLists);
500
+ }
501
+ let otks = req.body["org.matrix.msc3202.device_one_time_keys_count"];
502
+ const otks2 = req.body["org.matrix.msc3202.device_one_time_key_counts"];
503
+ if (otks2 && !otks) {
504
+ __1.LogService.warn("Appservice", "Your homeserver is using an outdated field (device_one_time_key_counts) to talk to this appservice. " +
505
+ "If you're using Synapse, please upgrade to 1.73.0 or higher.");
506
+ otks = otks2;
507
+ }
508
+ if (otks) {
509
+ this.emit("otk.counts", otks);
510
+ }
511
+ if (otks && this.cryptoStorage) {
512
+ for (const userId of Object.keys(otks)) {
513
+ const intent = this.getIntentForUserId(userId);
514
+ await intent.enableEncryption();
515
+ const otksForUser = otks[userId][intent.underlyingClient.crypto.clientDeviceId];
516
+ if (otksForUser) {
517
+ if (!byUserId[userId]) {
518
+ byUserId[userId] = {
519
+ counts: null,
520
+ toDevice: null,
521
+ unusedFallbacks: null,
522
+ };
523
+ }
524
+ byUserId[userId].counts = otksForUser;
525
+ }
526
+ }
527
+ }
528
+ const fallbacks = req.body["org.matrix.msc3202.device_unused_fallback_key_types"];
529
+ if (fallbacks) {
530
+ this.emit("otk.unused_fallback_keys", fallbacks);
531
+ }
532
+ if (fallbacks && this.cryptoStorage) {
533
+ for (const userId of Object.keys(fallbacks)) {
534
+ const intent = this.getIntentForUserId(userId);
535
+ await intent.enableEncryption();
536
+ const fallbacksForUser = fallbacks[userId][intent.underlyingClient.crypto.clientDeviceId];
537
+ if (Array.isArray(fallbacksForUser) && !fallbacksForUser.includes(__1.OTKAlgorithm.Signed)) {
538
+ if (!byUserId[userId]) {
539
+ byUserId[userId] = {
540
+ counts: null,
541
+ toDevice: null,
542
+ unusedFallbacks: null,
543
+ };
544
+ }
545
+ byUserId[userId].unusedFallbacks = fallbacksForUser;
546
+ }
547
+ }
548
+ }
549
+ if (this.cryptoStorage) {
550
+ for (const userId of Object.keys(byUserId)) {
551
+ const intent = this.getIntentForUserId(userId);
552
+ await intent.enableEncryption();
553
+ const info = byUserId[userId];
554
+ const userStorage = this.storage.storageForUser(userId);
555
+ if (!info.toDevice)
556
+ info.toDevice = [];
557
+ if (!info.unusedFallbacks)
558
+ info.unusedFallbacks = JSON.parse(await userStorage.readValue("last_unused_fallbacks") || "[]");
559
+ if (!info.counts)
560
+ info.counts = JSON.parse(await userStorage.readValue("last_counts") || "{}");
561
+ __1.LogService.info("Appservice", `Updating crypto state for ${userId}`);
562
+ await intent.underlyingClient.crypto.updateSyncData(info.toDevice, info.counts, info.unusedFallbacks, deviceLists.changed, deviceLists.removed);
563
+ }
564
+ }
565
+ for (let event of req.body["events"]) {
566
+ __1.LogService.info("Appservice", `Processing event of type ${event["type"]}`);
567
+ event = await this.processEvent(event);
568
+ if (event['type'] === 'm.room.encrypted') {
569
+ this.emit("room.encrypted_event", event["room_id"], event);
570
+ if (this.cryptoStorage) {
571
+ try {
572
+ const encrypted = new __1.EncryptedRoomEvent(event);
573
+ const roomId = event['room_id'];
574
+ try {
575
+ event = (await this.botClient.crypto.decryptRoomEvent(encrypted, roomId)).raw;
576
+ event = await this.processEvent(event);
577
+ this.emit("room.decrypted_event", roomId, event);
578
+ // For logging purposes: show that the event was decrypted
579
+ __1.LogService.info("Appservice", `Processing decrypted event of type ${event["type"]}`);
580
+ }
581
+ catch (e1) {
582
+ __1.LogService.warn("Appservice", `Bot client was not able to decrypt ${roomId} ${event['event_id']} - trying other intents`);
583
+ let tryUserId;
584
+ try {
585
+ // TODO: This could be more efficient
586
+ const userIdsInRoom = await this.botClient.getJoinedRoomMembers(roomId);
587
+ tryUserId = userIdsInRoom.find(u => this.isNamespacedUser(u));
588
+ }
589
+ catch (e) {
590
+ __1.LogService.error("Appservice", "Failed to get members of room - cannot decrypt message");
591
+ }
592
+ if (tryUserId) {
593
+ const intent = this.getIntentForUserId(tryUserId);
594
+ event = (await intent.underlyingClient.crypto.decryptRoomEvent(encrypted, roomId)).raw;
595
+ event = await this.processEvent(event);
596
+ this.emit("room.decrypted_event", roomId, event);
597
+ // For logging purposes: show that the event was decrypted
598
+ __1.LogService.info("Appservice", `Processing decrypted event of type ${event["type"]}`);
599
+ }
600
+ else {
601
+ // noinspection ExceptionCaughtLocallyJS
602
+ throw e1;
603
+ }
604
+ }
605
+ }
606
+ catch (e) {
607
+ __1.LogService.error("Appservice", `Decryption error on ${event['room_id']} ${event['event_id']}`, e);
608
+ this.emit("room.failed_decryption", event['room_id'], event, e);
609
+ }
610
+ }
611
+ }
612
+ this.emit("room.event", event["room_id"], event);
613
+ if (event['type'] === 'm.room.message') {
614
+ this.emit("room.message", event["room_id"], event);
615
+ }
616
+ if (event['type'] === 'm.room.member' && this.isNamespacedUser(event['state_key'])) {
617
+ await this.processMembershipEvent(event);
618
+ }
619
+ if (event['type'] === 'm.room.tombstone' && event['state_key'] === '') {
620
+ this.emit("room.archived", event['room_id'], event);
621
+ }
622
+ if (event['type'] === 'm.room.create' && event['state_key'] === '' && event['content'] && event['content']['predecessor']) {
623
+ this.emit("room.upgraded", event['room_id'], event);
624
+ }
625
+ }
626
+ resolve();
627
+ });
628
+ try {
629
+ await this.pendingTransactions[txnId];
630
+ await Promise.resolve(this.storage.setTransactionCompleted(txnId));
631
+ res.status(200).json({});
632
+ }
633
+ catch (e) {
634
+ __1.LogService.error("Appservice", e);
635
+ res.status(500).json({});
636
+ }
637
+ }
638
+ async onUser(req, res) {
639
+ if (!this.isAuthed(req)) {
640
+ res.status(401).json({ errcode: "AUTH_FAILED", error: "Authentication failed" });
641
+ return;
642
+ }
643
+ const userId = req.params["userId"];
644
+ this.emit("query.user", userId, async (result) => {
645
+ if (result.then)
646
+ result = await result;
647
+ if (result === false) {
648
+ res.status(404).json({ errcode: "USER_DOES_NOT_EXIST", error: "User not created" });
649
+ }
650
+ else {
651
+ const intent = this.getIntentForUserId(userId);
652
+ await intent.ensureRegistered();
653
+ if (result.display_name)
654
+ await intent.underlyingClient.setDisplayName(result.display_name);
655
+ if (result.avatar_mxc)
656
+ await intent.underlyingClient.setAvatarUrl(result.avatar_mxc);
657
+ res.status(200).json(result); // return result for debugging + testing
658
+ }
659
+ });
660
+ }
661
+ async onRoomAlias(req, res) {
662
+ if (!this.isAuthed(req)) {
663
+ res.status(401).json({ errcode: "AUTH_FAILED", error: "Authentication failed" });
664
+ return;
665
+ }
666
+ const roomAlias = req.params["roomAlias"];
667
+ this.emit("query.room", roomAlias, async (result) => {
668
+ if (result.then)
669
+ result = await result;
670
+ if (result === false) {
671
+ res.status(404).json({ errcode: "ROOM_DOES_NOT_EXIST", error: "Room not created" });
672
+ }
673
+ else {
674
+ const intent = this.botIntent;
675
+ await intent.ensureRegistered();
676
+ result["room_alias_name"] = roomAlias.substring(1).split(':')[0];
677
+ result["__roomId"] = await intent.underlyingClient.createRoom(result);
678
+ res.status(200).json(result); // return result for debugging + testing
679
+ }
680
+ });
681
+ }
682
+ async onKeysClaim(req, res) {
683
+ if (!this.isAuthed(req)) {
684
+ res.status(401).json({ errcode: "AUTH_FAILED", error: "Authentication failed" });
685
+ return;
686
+ }
687
+ if (typeof (req.body) !== "object") {
688
+ res.status(400).json({ errcode: "BAD_REQUEST", error: "Expected JSON" });
689
+ return;
690
+ }
691
+ let responded = false;
692
+ this.emit("query.key_claim", req.body, (result) => {
693
+ responded = true;
694
+ const handleResult = (result2) => {
695
+ if (!result2) {
696
+ res.status(404).json({ errcode: "M_UNRECOGNIZED", error: "Endpoint not implemented" });
697
+ return;
698
+ }
699
+ res.status(200).json(result2);
700
+ };
701
+ Promise.resolve(result).then(r => handleResult(r)).catch(e => {
702
+ __1.LogService.error("Appservice", "Error handling key claim API", e);
703
+ res.status(500).json({ errcode: "M_UNKNOWN", error: "Error handling key claim API" });
704
+ });
705
+ });
706
+ if (!responded) {
707
+ res.status(404).json({ errcode: "M_UNRECOGNIZED", error: "Endpoint not implemented" });
708
+ }
709
+ }
710
+ async onKeysQuery(req, res) {
711
+ if (!this.isAuthed(req)) {
712
+ res.status(401).json({ errcode: "AUTH_FAILED", error: "Authentication failed" });
713
+ return;
714
+ }
715
+ if (typeof (req.body) !== "object") {
716
+ res.status(400).json({ errcode: "BAD_REQUEST", error: "Expected JSON" });
717
+ return;
718
+ }
719
+ let responded = false;
720
+ this.emit("query.key", req.body, (result) => {
721
+ responded = true;
722
+ const handleResult = (result2) => {
723
+ if (!result2) {
724
+ res.status(404).json({ errcode: "M_UNRECOGNIZED", error: "Endpoint not implemented" });
725
+ return;
726
+ }
727
+ // Implementation note: we could probably query the device keys from our storage if we wanted to.
728
+ res.status(200).json(result2);
729
+ };
730
+ Promise.resolve(result).then(r => handleResult(r)).catch(e => {
731
+ __1.LogService.error("Appservice", "Error handling key query API", e);
732
+ res.status(500).json({ errcode: "M_UNKNOWN", error: "Error handling key query API" });
733
+ });
734
+ });
735
+ if (!responded) {
736
+ res.status(404).json({ errcode: "M_UNRECOGNIZED", error: "Endpoint not implemented" });
737
+ }
738
+ }
739
+ onThirdpartyProtocol(req, res) {
740
+ if (!this.isAuthed(req)) {
741
+ res.status(401).json({ errcode: "AUTH_FAILED", error: "Authentication failed" });
742
+ return;
743
+ }
744
+ const protocol = req.params["protocol"];
745
+ if (!this.registration.protocols.includes(protocol)) {
746
+ res.status(404).json({
747
+ errcode: "PROTOCOL_NOT_HANDLED",
748
+ error: "Protocol is not handled by this appservice",
749
+ });
750
+ return;
751
+ }
752
+ this.emit("thirdparty.protocol", protocol, (protocolResponse) => {
753
+ res.status(200).json(protocolResponse);
754
+ });
755
+ }
756
+ handleThirdpartyObject(req, res, objType, matrixId) {
757
+ if (!this.isAuthed(req)) {
758
+ res.status(401).json({ errcode: "AUTH_FAILED", error: "Authentication failed" });
759
+ return;
760
+ }
761
+ const protocol = req.params["protocol"];
762
+ const responseFunc = (items) => {
763
+ if (items && items.length > 0) {
764
+ res.status(200).json(items);
765
+ return;
766
+ }
767
+ res.status(404).json({
768
+ errcode: "NO_MAPPING_FOUND",
769
+ error: "No mappings found",
770
+ });
771
+ };
772
+ // Lookup remote objects(s)
773
+ if (protocol) { // If protocol is given, we are looking up a objects based on fields
774
+ if (!this.registration.protocols.includes(protocol)) {
775
+ res.status(404).json({
776
+ errcode: "PROTOCOL_NOT_HANDLED",
777
+ error: "Protocol is not handled by this appservice",
778
+ });
779
+ return;
780
+ }
781
+ // Remove the access_token
782
+ delete req.query.access_token;
783
+ this.emit(`thirdparty.${objType}.remote`, protocol, req.query, responseFunc);
784
+ return;
785
+ }
786
+ else if (matrixId) { // If a user ID is given, we are looking up a remote objects based on a id
787
+ this.emit(`thirdparty.${objType}.matrix`, matrixId, responseFunc);
788
+ return;
789
+ }
790
+ res.status(400).json({
791
+ errcode: "INVALID_PARAMETERS",
792
+ error: "Invalid parameters given",
793
+ });
794
+ }
795
+ onThirdpartyUser(req, res) {
796
+ return this.handleThirdpartyObject(req, res, "user", req.query["userid"]);
797
+ }
798
+ onThirdpartyLocation(req, res) {
799
+ return this.handleThirdpartyObject(req, res, "location", req.query["alias"]);
800
+ }
801
+ }
802
+ exports.Appservice = Appservice;
803
+ //# sourceMappingURL=Appservice.js.map