async-matrix 0.1.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +131 -0
  3. data/data/discord-api-spec/openapi.json +40404 -0
  4. data/data/matrix-spec/api/client-server/account-data.yaml +389 -0
  5. data/data/matrix-spec/api/client-server/account_deactivation.yaml +149 -0
  6. data/data/matrix-spec/api/client-server/admin.yaml +512 -0
  7. data/data/matrix-spec/api/client-server/administrative_contact.yaml +620 -0
  8. data/data/matrix-spec/api/client-server/appservice_ping.yaml +183 -0
  9. data/data/matrix-spec/api/client-server/appservice_room_directory.yaml +104 -0
  10. data/data/matrix-spec/api/client-server/authed-content-repo.yaml +590 -0
  11. data/data/matrix-spec/api/client-server/banning.yaml +177 -0
  12. data/data/matrix-spec/api/client-server/capabilities.yaml +235 -0
  13. data/data/matrix-spec/api/client-server/content-repo.yaml +887 -0
  14. data/data/matrix-spec/api/client-server/create_room.yaml +306 -0
  15. data/data/matrix-spec/api/client-server/cross_signing.yaml +300 -0
  16. data/data/matrix-spec/api/client-server/definitions/auth_data.yaml +34 -0
  17. data/data/matrix-spec/api/client-server/definitions/auth_response.yaml +62 -0
  18. data/data/matrix-spec/api/client-server/definitions/client_device.yaml +44 -0
  19. data/data/matrix-spec/api/client-server/definitions/client_event.yaml +49 -0
  20. data/data/matrix-spec/api/client-server/definitions/client_event_without_room_id.yaml +147 -0
  21. data/data/matrix-spec/api/client-server/definitions/cross_signing_key.yaml +57 -0
  22. data/data/matrix-spec/api/client-server/definitions/device_keys.yaml +70 -0
  23. data/data/matrix-spec/api/client-server/definitions/errors/error.yaml +26 -0
  24. data/data/matrix-spec/api/client-server/definitions/errors/rate_limited.yaml +34 -0
  25. data/data/matrix-spec/api/client-server/definitions/event_batch.yaml +22 -0
  26. data/data/matrix-spec/api/client-server/definitions/event_filter.yaml +55 -0
  27. data/data/matrix-spec/api/client-server/definitions/invite_3pid.yaml +45 -0
  28. data/data/matrix-spec/api/client-server/definitions/key_backup_auth_data.yaml +36 -0
  29. data/data/matrix-spec/api/client-server/definitions/key_backup_data.yaml +50 -0
  30. data/data/matrix-spec/api/client-server/definitions/key_backup_session_data.yaml +57 -0
  31. data/data/matrix-spec/api/client-server/definitions/m.login.terms_params.yaml +83 -0
  32. data/data/matrix-spec/api/client-server/definitions/m.mentions.yaml +33 -0
  33. data/data/matrix-spec/api/client-server/definitions/m.oauth_params.yaml +30 -0
  34. data/data/matrix-spec/api/client-server/definitions/m.relates_to.yaml +45 -0
  35. data/data/matrix-spec/api/client-server/definitions/megolm_export_session_data.yaml +39 -0
  36. data/data/matrix-spec/api/client-server/definitions/olm_payload.yaml +88 -0
  37. data/data/matrix-spec/api/client-server/definitions/one_time_keys.yaml +27 -0
  38. data/data/matrix-spec/api/client-server/definitions/openid_token.yaml +37 -0
  39. data/data/matrix-spec/api/client-server/definitions/protocol.yaml +44 -0
  40. data/data/matrix-spec/api/client-server/definitions/public_rooms_chunk.yaml +74 -0
  41. data/data/matrix-spec/api/client-server/definitions/public_rooms_response.yaml +59 -0
  42. data/data/matrix-spec/api/client-server/definitions/push_condition.yaml +53 -0
  43. data/data/matrix-spec/api/client-server/definitions/push_rule.yaml +53 -0
  44. data/data/matrix-spec/api/client-server/definitions/push_ruleset.yaml +206 -0
  45. data/data/matrix-spec/api/client-server/definitions/recent_emoji.yaml +29 -0
  46. data/data/matrix-spec/api/client-server/definitions/request_email_validation.yaml +36 -0
  47. data/data/matrix-spec/api/client-server/definitions/request_msisdn_validation.yaml +36 -0
  48. data/data/matrix-spec/api/client-server/definitions/request_token_response.yaml +46 -0
  49. data/data/matrix-spec/api/client-server/definitions/room_event_filter.yaml +60 -0
  50. data/data/matrix-spec/api/client-server/definitions/room_key_backup.yaml +37 -0
  51. data/data/matrix-spec/api/client-server/definitions/room_summary.yaml +44 -0
  52. data/data/matrix-spec/api/client-server/definitions/security.yaml +47 -0
  53. data/data/matrix-spec/api/client-server/definitions/sso_login_flow.yaml +98 -0
  54. data/data/matrix-spec/api/client-server/definitions/state_event_batch.yaml +21 -0
  55. data/data/matrix-spec/api/client-server/definitions/sync_filter.yaml +86 -0
  56. data/data/matrix-spec/api/client-server/definitions/tag.yaml +24 -0
  57. data/data/matrix-spec/api/client-server/definitions/third_party_signed.yaml +45 -0
  58. data/data/matrix-spec/api/client-server/definitions/timeline_batch.yaml +36 -0
  59. data/data/matrix-spec/api/client-server/definitions/user_identifier.yaml +27 -0
  60. data/data/matrix-spec/api/client-server/definitions/wellknown/full.yaml +38 -0
  61. data/data/matrix-spec/api/client-server/definitions/wellknown/homeserver.yaml +25 -0
  62. data/data/matrix-spec/api/client-server/definitions/wellknown/identity_server.yaml +25 -0
  63. data/data/matrix-spec/api/client-server/device_management.yaml +314 -0
  64. data/data/matrix-spec/api/client-server/directory.yaml +318 -0
  65. data/data/matrix-spec/api/client-server/event_context.yaml +161 -0
  66. data/data/matrix-spec/api/client-server/filter.yaml +224 -0
  67. data/data/matrix-spec/api/client-server/inviting.yaml +149 -0
  68. data/data/matrix-spec/api/client-server/joining.yaml +238 -0
  69. data/data/matrix-spec/api/client-server/key_backup.yaml +993 -0
  70. data/data/matrix-spec/api/client-server/keys.yaml +482 -0
  71. data/data/matrix-spec/api/client-server/kicking.yaml +110 -0
  72. data/data/matrix-spec/api/client-server/knocking.yaml +152 -0
  73. data/data/matrix-spec/api/client-server/leaving.yaml +163 -0
  74. data/data/matrix-spec/api/client-server/list_joined_rooms.yaml +68 -0
  75. data/data/matrix-spec/api/client-server/list_public_rooms.yaml +280 -0
  76. data/data/matrix-spec/api/client-server/login.yaml +321 -0
  77. data/data/matrix-spec/api/client-server/login_token.yaml +138 -0
  78. data/data/matrix-spec/api/client-server/logout.yaml +86 -0
  79. data/data/matrix-spec/api/client-server/message_pagination.yaml +194 -0
  80. data/data/matrix-spec/api/client-server/notifications.yaml +152 -0
  81. data/data/matrix-spec/api/client-server/oauth_server_metadata.yaml +238 -0
  82. data/data/matrix-spec/api/client-server/old_sync.yaml +379 -0
  83. data/data/matrix-spec/api/client-server/openid.yaml +98 -0
  84. data/data/matrix-spec/api/client-server/password_management.yaml +246 -0
  85. data/data/matrix-spec/api/client-server/peeking_events.yaml +122 -0
  86. data/data/matrix-spec/api/client-server/policy_server.yaml +82 -0
  87. data/data/matrix-spec/api/client-server/presence.yaml +169 -0
  88. data/data/matrix-spec/api/client-server/profile.yaml +366 -0
  89. data/data/matrix-spec/api/client-server/pusher.yaml +303 -0
  90. data/data/matrix-spec/api/client-server/pushrules.yaml +633 -0
  91. data/data/matrix-spec/api/client-server/read_markers.yaml +103 -0
  92. data/data/matrix-spec/api/client-server/receipts.yaml +139 -0
  93. data/data/matrix-spec/api/client-server/redaction.yaml +116 -0
  94. data/data/matrix-spec/api/client-server/refresh.yaml +119 -0
  95. data/data/matrix-spec/api/client-server/registration.yaml +488 -0
  96. data/data/matrix-spec/api/client-server/registration_tokens.yaml +93 -0
  97. data/data/matrix-spec/api/client-server/relations.yaml +382 -0
  98. data/data/matrix-spec/api/client-server/report_content.yaml +283 -0
  99. data/data/matrix-spec/api/client-server/room_event_by_timestamp.yaml +147 -0
  100. data/data/matrix-spec/api/client-server/room_initial_sync.yaml +188 -0
  101. data/data/matrix-spec/api/client-server/room_send.yaml +130 -0
  102. data/data/matrix-spec/api/client-server/room_state.yaml +159 -0
  103. data/data/matrix-spec/api/client-server/room_summary.yaml +138 -0
  104. data/data/matrix-spec/api/client-server/room_upgrades.yaml +130 -0
  105. data/data/matrix-spec/api/client-server/rooms.yaml +380 -0
  106. data/data/matrix-spec/api/client-server/search.yaml +385 -0
  107. data/data/matrix-spec/api/client-server/space_hierarchy.yaml +237 -0
  108. data/data/matrix-spec/api/client-server/sso_login_redirect.yaml +135 -0
  109. data/data/matrix-spec/api/client-server/support.yaml +142 -0
  110. data/data/matrix-spec/api/client-server/sync.yaml +692 -0
  111. data/data/matrix-spec/api/client-server/tags.yaml +183 -0
  112. data/data/matrix-spec/api/client-server/third_party_lookup.yaml +324 -0
  113. data/data/matrix-spec/api/client-server/third_party_membership.yaml +139 -0
  114. data/data/matrix-spec/api/client-server/threads_list.yaml +167 -0
  115. data/data/matrix-spec/api/client-server/to_device.yaml +104 -0
  116. data/data/matrix-spec/api/client-server/typing.yaml +103 -0
  117. data/data/matrix-spec/api/client-server/users.yaml +136 -0
  118. data/data/matrix-spec/api/client-server/versions.yaml +108 -0
  119. data/data/matrix-spec/api/client-server/voip.yaml +93 -0
  120. data/data/matrix-spec/api/client-server/wellknown.yaml +60 -0
  121. data/data/matrix-spec/api/client-server/whoami.yaml +121 -0
  122. data/data/matrix-spec/event-schemas/examples/core/event.json +6 -0
  123. data/data/matrix-spec/event-schemas/examples/core/room_edu.json +3 -0
  124. data/data/matrix-spec/event-schemas/examples/core/room_event.json +11 -0
  125. data/data/matrix-spec/event-schemas/examples/core/state_event.json +4 -0
  126. data/data/matrix-spec/event-schemas/examples/invite_room_state.json +18 -0
  127. data/data/matrix-spec/event-schemas/examples/knock_room_state.json +18 -0
  128. data/data/matrix-spec/event-schemas/examples/m.accepted_terms.yaml +10 -0
  129. data/data/matrix-spec/event-schemas/examples/m.call.answer.yaml +21 -0
  130. data/data/matrix-spec/event-schemas/examples/m.call.candidates.yaml +16 -0
  131. data/data/matrix-spec/event-schemas/examples/m.call.hangup.yaml +10 -0
  132. data/data/matrix-spec/event-schemas/examples/m.call.invite.yaml +22 -0
  133. data/data/matrix-spec/event-schemas/examples/m.call.negotiate.yaml +22 -0
  134. data/data/matrix-spec/event-schemas/examples/m.call.reject.yaml +9 -0
  135. data/data/matrix-spec/event-schemas/examples/m.call.sdp_stream_metadata_changed.yaml +16 -0
  136. data/data/matrix-spec/event-schemas/examples/m.call.select_answer.yaml +10 -0
  137. data/data/matrix-spec/event-schemas/examples/m.direct.yaml +10 -0
  138. data/data/matrix-spec/event-schemas/examples/m.dummy.yaml +4 -0
  139. data/data/matrix-spec/event-schemas/examples/m.forwarded_room_key.yaml +14 -0
  140. data/data/matrix-spec/event-schemas/examples/m.fully_read.yaml +7 -0
  141. data/data/matrix-spec/event-schemas/examples/m.identity_server.yaml +7 -0
  142. data/data/matrix-spec/event-schemas/examples/m.ignored_user_list.yaml +9 -0
  143. data/data/matrix-spec/event-schemas/examples/m.invite_permission_config.yaml +7 -0
  144. data/data/matrix-spec/event-schemas/examples/m.key.verification.accept.yaml +12 -0
  145. data/data/matrix-spec/event-schemas/examples/m.key.verification.cancel.yaml +8 -0
  146. data/data/matrix-spec/event-schemas/examples/m.key.verification.done.yaml +6 -0
  147. data/data/matrix-spec/event-schemas/examples/m.key.verification.key.yaml +7 -0
  148. data/data/matrix-spec/event-schemas/examples/m.key.verification.mac.yaml +10 -0
  149. data/data/matrix-spec/event-schemas/examples/m.key.verification.ready.yaml +10 -0
  150. data/data/matrix-spec/event-schemas/examples/m.key.verification.request.yaml +11 -0
  151. data/data/matrix-spec/event-schemas/examples/m.key.verification.start$m.sas.v1.yaml +12 -0
  152. data/data/matrix-spec/event-schemas/examples/m.key.verification.start.yaml +8 -0
  153. data/data/matrix-spec/event-schemas/examples/m.key_backup.yaml +7 -0
  154. data/data/matrix-spec/event-schemas/examples/m.marked_unread.yaml +7 -0
  155. data/data/matrix-spec/event-schemas/examples/m.policy.rule.room.yaml +10 -0
  156. data/data/matrix-spec/event-schemas/examples/m.policy.rule.server.yaml +10 -0
  157. data/data/matrix-spec/event-schemas/examples/m.policy.rule.user.yaml +10 -0
  158. data/data/matrix-spec/event-schemas/examples/m.presence.yaml +12 -0
  159. data/data/matrix-spec/event-schemas/examples/m.push_rules.yaml +177 -0
  160. data/data/matrix-spec/event-schemas/examples/m.reaction.yaml +11 -0
  161. data/data/matrix-spec/event-schemas/examples/m.receipt.yaml +18 -0
  162. data/data/matrix-spec/event-schemas/examples/m.recent_emoji.yaml +16 -0
  163. data/data/matrix-spec/event-schemas/examples/m.room.avatar.yaml +14 -0
  164. data/data/matrix-spec/event-schemas/examples/m.room.canonical_alias.yaml +12 -0
  165. data/data/matrix-spec/event-schemas/examples/m.room.create.yaml +13 -0
  166. data/data/matrix-spec/event-schemas/examples/m.room.encrypted$megolm.yaml +11 -0
  167. data/data/matrix-spec/event-schemas/examples/m.room.encrypted$olm.yaml +14 -0
  168. data/data/matrix-spec/event-schemas/examples/m.room.encryption.yaml +10 -0
  169. data/data/matrix-spec/event-schemas/examples/m.room.guest_access.yaml +8 -0
  170. data/data/matrix-spec/event-schemas/examples/m.room.history_visibility.yaml +8 -0
  171. data/data/matrix-spec/event-schemas/examples/m.room.join_rules$restricted.yaml +18 -0
  172. data/data/matrix-spec/event-schemas/examples/m.room.join_rules.yaml +8 -0
  173. data/data/matrix-spec/event-schemas/examples/m.room.member$invite_room_state.yaml +15 -0
  174. data/data/matrix-spec/event-schemas/examples/m.room.member$join_authorised_via_users_server.yaml +12 -0
  175. data/data/matrix-spec/event-schemas/examples/m.room.member$knock_room_state.yaml +15 -0
  176. data/data/matrix-spec/event-schemas/examples/m.room.member$third_party_invite.yaml +20 -0
  177. data/data/matrix-spec/event-schemas/examples/m.room.member.yaml +12 -0
  178. data/data/matrix-spec/event-schemas/examples/m.room.message$m.audio.yaml +14 -0
  179. data/data/matrix-spec/event-schemas/examples/m.room.message$m.emote.yaml +10 -0
  180. data/data/matrix-spec/event-schemas/examples/m.room.message$m.file.yaml +14 -0
  181. data/data/matrix-spec/event-schemas/examples/m.room.message$m.image.yaml +16 -0
  182. data/data/matrix-spec/event-schemas/examples/m.room.message$m.key.verification.request.yaml +19 -0
  183. data/data/matrix-spec/event-schemas/examples/m.room.message$m.location.yaml +18 -0
  184. data/data/matrix-spec/event-schemas/examples/m.room.message$m.notice.yaml +10 -0
  185. data/data/matrix-spec/event-schemas/examples/m.room.message$m.server_notice.yaml +11 -0
  186. data/data/matrix-spec/event-schemas/examples/m.room.message$m.text.yaml +10 -0
  187. data/data/matrix-spec/event-schemas/examples/m.room.message$m.video.yaml +23 -0
  188. data/data/matrix-spec/event-schemas/examples/m.room.name.yaml +8 -0
  189. data/data/matrix-spec/event-schemas/examples/m.room.pinned_events.yaml +8 -0
  190. data/data/matrix-spec/event-schemas/examples/m.room.policy.yaml +11 -0
  191. data/data/matrix-spec/event-schemas/examples/m.room.power_levels.yaml +24 -0
  192. data/data/matrix-spec/event-schemas/examples/m.room.redaction.yaml +8 -0
  193. data/data/matrix-spec/event-schemas/examples/m.room.server_acl.yaml +10 -0
  194. data/data/matrix-spec/event-schemas/examples/m.room.third_party_invite.yaml +14 -0
  195. data/data/matrix-spec/event-schemas/examples/m.room.tombstone.yaml +9 -0
  196. data/data/matrix-spec/event-schemas/examples/m.room.topic.yaml +16 -0
  197. data/data/matrix-spec/event-schemas/examples/m.room_key.withheld.yaml +12 -0
  198. data/data/matrix-spec/event-schemas/examples/m.room_key.yaml +10 -0
  199. data/data/matrix-spec/event-schemas/examples/m.room_key_request$cancel_request.yaml +8 -0
  200. data/data/matrix-spec/event-schemas/examples/m.room_key_request$request.yaml +14 -0
  201. data/data/matrix-spec/event-schemas/examples/m.secret.request.yaml +9 -0
  202. data/data/matrix-spec/event-schemas/examples/m.secret.send.yaml +7 -0
  203. data/data/matrix-spec/event-schemas/examples/m.space.child.yaml +10 -0
  204. data/data/matrix-spec/event-schemas/examples/m.space.parent.yaml +9 -0
  205. data/data/matrix-spec/event-schemas/examples/m.sticker.yaml +22 -0
  206. data/data/matrix-spec/event-schemas/examples/m.tag.yaml +9 -0
  207. data/data/matrix-spec/event-schemas/examples/m.typing.yaml +7 -0
  208. data/data/matrix-spec/event-schemas/moderation_policy_rule.yaml +32 -0
  209. data/data/matrix-spec/event-schemas/schema/components/m_text_content_block.yaml +28 -0
  210. data/data/matrix-spec/event-schemas/schema/components/sdp_stream_metadata.yaml +43 -0
  211. data/data/matrix-spec/event-schemas/schema/components/signed_third_party_invite.yaml +48 -0
  212. data/data/matrix-spec/event-schemas/schema/core-event-schema/call_event.yaml +27 -0
  213. data/data/matrix-spec/event-schemas/schema/core-event-schema/event.yaml +16 -0
  214. data/data/matrix-spec/event-schemas/schema/core-event-schema/msgtype_infos/avatar_info.yaml +30 -0
  215. data/data/matrix-spec/event-schemas/schema/core-event-schema/msgtype_infos/image_info.yaml +52 -0
  216. data/data/matrix-spec/event-schemas/schema/core-event-schema/msgtype_infos/thumbnail_info.yaml +22 -0
  217. data/data/matrix-spec/event-schemas/schema/core-event-schema/room_event.yaml +17 -0
  218. data/data/matrix-spec/event-schemas/schema/core-event-schema/state_event.yaml +8 -0
  219. data/data/matrix-spec/event-schemas/schema/core-event-schema/stripped_state.yaml +48 -0
  220. data/data/matrix-spec/event-schemas/schema/core-event-schema/sync_room_event.yaml +49 -0
  221. data/data/matrix-spec/event-schemas/schema/core-event-schema/sync_state_event.yaml +36 -0
  222. data/data/matrix-spec/event-schemas/schema/core-event-schema/unsigned_prop.yaml +23 -0
  223. data/data/matrix-spec/event-schemas/schema/m.accepted_terms.yaml +25 -0
  224. data/data/matrix-spec/event-schemas/schema/m.call.answer.yaml +44 -0
  225. data/data/matrix-spec/event-schemas/schema/m.call.candidates.yaml +52 -0
  226. data/data/matrix-spec/event-schemas/schema/m.call.hangup.yaml +57 -0
  227. data/data/matrix-spec/event-schemas/schema/m.call.invite.yaml +53 -0
  228. data/data/matrix-spec/event-schemas/schema/m.call.negotiate.yaml +78 -0
  229. data/data/matrix-spec/event-schemas/schema/m.call.reject.yaml +29 -0
  230. data/data/matrix-spec/event-schemas/schema/m.call.sdp_stream_metadata_changed.yaml +24 -0
  231. data/data/matrix-spec/event-schemas/schema/m.call.select_answer.yaml +29 -0
  232. data/data/matrix-spec/event-schemas/schema/m.direct.yaml +29 -0
  233. data/data/matrix-spec/event-schemas/schema/m.dummy.yaml +25 -0
  234. data/data/matrix-spec/event-schemas/schema/m.forwarded_room_key.yaml +70 -0
  235. data/data/matrix-spec/event-schemas/schema/m.fully_read.yaml +26 -0
  236. data/data/matrix-spec/event-schemas/schema/m.identity_server.yaml +28 -0
  237. data/data/matrix-spec/event-schemas/schema/m.ignored_user_list.yaml +30 -0
  238. data/data/matrix-spec/event-schemas/schema/m.invite_permission_config.yaml +21 -0
  239. data/data/matrix-spec/event-schemas/schema/m.key.verification.accept.yaml +63 -0
  240. data/data/matrix-spec/event-schemas/schema/m.key.verification.cancel.yaml +72 -0
  241. data/data/matrix-spec/event-schemas/schema/m.key.verification.done.yaml +24 -0
  242. data/data/matrix-spec/event-schemas/schema/m.key.verification.key.yaml +31 -0
  243. data/data/matrix-spec/event-schemas/schema/m.key.verification.m.relates_to.yaml +23 -0
  244. data/data/matrix-spec/event-schemas/schema/m.key.verification.mac.yaml +43 -0
  245. data/data/matrix-spec/event-schemas/schema/m.key.verification.ready.yaml +41 -0
  246. data/data/matrix-spec/event-schemas/schema/m.key.verification.request.yaml +47 -0
  247. data/data/matrix-spec/event-schemas/schema/m.key.verification.start$m.reciprocate.v1.yaml +45 -0
  248. data/data/matrix-spec/event-schemas/schema/m.key.verification.start$m.sas.v1.yaml +76 -0
  249. data/data/matrix-spec/event-schemas/schema/m.key.verification.start.yaml +46 -0
  250. data/data/matrix-spec/event-schemas/schema/m.key_backup.yaml +24 -0
  251. data/data/matrix-spec/event-schemas/schema/m.marked_unread.yaml +26 -0
  252. data/data/matrix-spec/event-schemas/schema/m.policy.rule.room.yaml +17 -0
  253. data/data/matrix-spec/event-schemas/schema/m.policy.rule.server.yaml +17 -0
  254. data/data/matrix-spec/event-schemas/schema/m.policy.rule.user.yaml +17 -0
  255. data/data/matrix-spec/event-schemas/schema/m.presence.yaml +50 -0
  256. data/data/matrix-spec/event-schemas/schema/m.push_rules.yaml +23 -0
  257. data/data/matrix-spec/event-schemas/schema/m.reaction.yaml +45 -0
  258. data/data/matrix-spec/event-schemas/schema/m.receipt.yaml +65 -0
  259. data/data/matrix-spec/event-schemas/schema/m.recent_emoji.yaml +29 -0
  260. data/data/matrix-spec/event-schemas/schema/m.room.avatar.yaml +29 -0
  261. data/data/matrix-spec/event-schemas/schema/m.room.canonical_alias.yaml +40 -0
  262. data/data/matrix-spec/event-schemas/schema/m.room.create.yaml +86 -0
  263. data/data/matrix-spec/event-schemas/schema/m.room.encrypted.yaml +91 -0
  264. data/data/matrix-spec/event-schemas/schema/m.room.encryption.yaml +38 -0
  265. data/data/matrix-spec/event-schemas/schema/m.room.guest_access.yaml +28 -0
  266. data/data/matrix-spec/event-schemas/schema/m.room.history_visibility.yaml +30 -0
  267. data/data/matrix-spec/event-schemas/schema/m.room.join_rules.yaml +78 -0
  268. data/data/matrix-spec/event-schemas/schema/m.room.member.yaml +174 -0
  269. data/data/matrix-spec/event-schemas/schema/m.room.message$m.audio.yaml +73 -0
  270. data/data/matrix-spec/event-schemas/schema/m.room.message$m.emote.yaml +36 -0
  271. data/data/matrix-spec/event-schemas/schema/m.room.message$m.file.yaml +85 -0
  272. data/data/matrix-spec/event-schemas/schema/m.room.message$m.image.yaml +63 -0
  273. data/data/matrix-spec/event-schemas/schema/m.room.message$m.key.verification.request.yaml +70 -0
  274. data/data/matrix-spec/event-schemas/schema/m.room.message$m.location.yaml +50 -0
  275. data/data/matrix-spec/event-schemas/schema/m.room.message$m.notice.yaml +36 -0
  276. data/data/matrix-spec/event-schemas/schema/m.room.message$m.server_notice.yaml +41 -0
  277. data/data/matrix-spec/event-schemas/schema/m.room.message$m.text.yaml +36 -0
  278. data/data/matrix-spec/event-schemas/schema/m.room.message$m.video.yaml +95 -0
  279. data/data/matrix-spec/event-schemas/schema/m.room.message.yaml +25 -0
  280. data/data/matrix-spec/event-schemas/schema/m.room.name.yaml +35 -0
  281. data/data/matrix-spec/event-schemas/schema/m.room.pinned_events.yaml +27 -0
  282. data/data/matrix-spec/event-schemas/schema/m.room.policy.yaml +41 -0
  283. data/data/matrix-spec/event-schemas/schema/m.room.power_levels.yaml +139 -0
  284. data/data/matrix-spec/event-schemas/schema/m.room.redaction.yaml +29 -0
  285. data/data/matrix-spec/event-schemas/schema/m.room.server_acl.yaml +88 -0
  286. data/data/matrix-spec/event-schemas/schema/m.room.third_party_invite.yaml +79 -0
  287. data/data/matrix-spec/event-schemas/schema/m.room.tombstone.yaml +29 -0
  288. data/data/matrix-spec/event-schemas/schema/m.room.topic.yaml +53 -0
  289. data/data/matrix-spec/event-schemas/schema/m.room_key.withheld.yaml +88 -0
  290. data/data/matrix-spec/event-schemas/schema/m.room_key.yaml +38 -0
  291. data/data/matrix-spec/event-schemas/schema/m.room_key_request.yaml +73 -0
  292. data/data/matrix-spec/event-schemas/schema/m.secret.request.yaml +42 -0
  293. data/data/matrix-spec/event-schemas/schema/m.secret.send.yaml +35 -0
  294. data/data/matrix-spec/event-schemas/schema/m.space.child.yaml +50 -0
  295. data/data/matrix-spec/event-schemas/schema/m.space.parent.yaml +36 -0
  296. data/data/matrix-spec/event-schemas/schema/m.sticker.yaml +36 -0
  297. data/data/matrix-spec/event-schemas/schema/m.tag.yaml +28 -0
  298. data/data/matrix-spec/event-schemas/schema/m.typing.yaml +29 -0
  299. data/lib/async/discord/api/path_tree.rb +130 -0
  300. data/lib/async/discord/api.rb +156 -0
  301. data/lib/async/discord/client.rb +286 -0
  302. data/lib/async/discord/error.rb +88 -0
  303. data/lib/async/discord/gateway.rb +362 -0
  304. data/lib/async/discord.rb +16 -0
  305. data/lib/async/matrix/api/chain.rb +584 -0
  306. data/lib/async/matrix/api/concat.rb +105 -0
  307. data/lib/async/matrix/api/path_tree.rb +208 -0
  308. data/lib/async/matrix/api.rb +204 -0
  309. data/lib/async/matrix/application_service/bot.rb +235 -0
  310. data/lib/async/matrix/application_service/config/schema/analytics.json +21 -0
  311. data/lib/async/matrix/application_service/config/schema/appservice.json +82 -0
  312. data/lib/async/matrix/application_service/config/schema/backfill.json +91 -0
  313. data/lib/async/matrix/application_service/config/schema/bridge.json +209 -0
  314. data/lib/async/matrix/application_service/config/schema/config.json +61 -0
  315. data/lib/async/matrix/application_service/config/schema/database.json +38 -0
  316. data/lib/async/matrix/application_service/config/schema/direct_media.json +35 -0
  317. data/lib/async/matrix/application_service/config/schema/double_puppet.json +24 -0
  318. data/lib/async/matrix/application_service/config/schema/encryption.json +164 -0
  319. data/lib/async/matrix/application_service/config/schema/homeserver.json +58 -0
  320. data/lib/async/matrix/application_service/config/schema/logging.json +50 -0
  321. data/lib/async/matrix/application_service/config/schema/management_room_texts.json +25 -0
  322. data/lib/async/matrix/application_service/config/schema/matrix.json +45 -0
  323. data/lib/async/matrix/application_service/config/schema/permissions.json +54 -0
  324. data/lib/async/matrix/application_service/config/schema/provisioning.json +23 -0
  325. data/lib/async/matrix/application_service/config/schema/public_media.json +39 -0
  326. data/lib/async/matrix/application_service/config/schema/relay.json +43 -0
  327. data/lib/async/matrix/application_service/config/vivify.rb +113 -0
  328. data/lib/async/matrix/application_service/config.rb +214 -123
  329. data/lib/async/matrix/application_service/dispatcher.rb +115 -113
  330. data/lib/async/matrix/application_service/error_response.rb +26 -26
  331. data/lib/async/matrix/application_service/event.rb +206 -1
  332. data/lib/async/matrix/application_service/server.rb +286 -215
  333. data/lib/async/matrix/application_service/transaction.rb +52 -52
  334. data/lib/async/matrix/application_service/transaction_store.rb +62 -62
  335. data/lib/async/matrix/bridge/discord/db/connection.rb +143 -0
  336. data/lib/async/matrix/bridge/discord/db/file.rb +120 -0
  337. data/lib/async/matrix/bridge/discord/db/guild.rb +122 -0
  338. data/lib/async/matrix/bridge/discord/db/message.rb +162 -0
  339. data/lib/async/matrix/bridge/discord/db/migrations/001_create_users.rb +14 -0
  340. data/lib/async/matrix/bridge/discord/db/migrations/002_create_guilds.rb +14 -0
  341. data/lib/async/matrix/bridge/discord/db/migrations/003_create_portals.rb +23 -0
  342. data/lib/async/matrix/bridge/discord/db/migrations/004_create_puppets.rb +19 -0
  343. data/lib/async/matrix/bridge/discord/db/migrations/005_create_messages.rb +20 -0
  344. data/lib/async/matrix/bridge/discord/db/migrations/006_create_reactions.rb +19 -0
  345. data/lib/async/matrix/bridge/discord/db/migrations/007_create_files.rb +18 -0
  346. data/lib/async/matrix/bridge/discord/db/portal.rb +152 -0
  347. data/lib/async/matrix/bridge/discord/db/puppet.rb +130 -0
  348. data/lib/async/matrix/bridge/discord/db/reaction.rb +167 -0
  349. data/lib/async/matrix/bridge/discord/db/user.rb +114 -0
  350. data/lib/async/matrix/bridge/discord/db.rb +140 -0
  351. data/lib/async/matrix/client.rb +919 -179
  352. data/lib/async/matrix/connection.rb +8 -8
  353. data/lib/async/matrix/double_puppet_client.rb +84 -0
  354. data/lib/async/matrix/endpoint.rb +45 -45
  355. data/lib/async/matrix/error.rb +49 -43
  356. data/lib/async/matrix/media_client.rb +173 -0
  357. data/lib/async/matrix/notifier.rb +92 -92
  358. data/lib/async/matrix/schema/registry.rb +355 -0
  359. data/lib/async/matrix/schema/validation_error.rb +226 -0
  360. data/lib/async/matrix/schema.rb +174 -0
  361. data/lib/async/matrix/server.rb +8 -7
  362. data/lib/async/matrix/stream.rb +7 -7
  363. data/lib/async/matrix/version.rb +1 -1
  364. data/lib/async/matrix.rb +4 -2
  365. metadata +419 -1
@@ -0,0 +1,208 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the Apache License, Version 2.0.
4
+ # Copyright, 2026, by General Intelligence Systems.
5
+
6
+ require "bundler/setup"
7
+ require "async/matrix"
8
+ require "yaml"
9
+ require "pathname"
10
+
11
+ module Async
12
+ module Matrix
13
+ module Api
14
+ # A trie of valid Matrix API paths, built from OpenAPI 3.1.0 YAML schemas.
15
+ #
16
+ # Each leaf node stores the set of HTTP methods valid at that path.
17
+ # Template segments like {roomId} become wildcard nodes that match any value.
18
+ #
19
+ # Example:
20
+ # tree = PathTree.load
21
+ # tree.match(["_matrix", "client", "v3", "rooms", "!abc:ex.com", "ban"], "POST")
22
+ # # => { valid: true, operation_id: "ban", methods: ["post"] }
23
+ #
24
+ class PathTree
25
+ SCHEMA_DIR = Pathname.new(File.expand_path("../../../../data/matrix-spec/api/client-server", __dir__))
26
+
27
+ Node = Struct.new(:children, :wildcard, :methods, :operation_ids, keyword_init: true) do
28
+ def initialize(**)
29
+ super
30
+ self.children ||= {}
31
+ self.methods ||= []
32
+ self.operation_ids ||= {}
33
+ end
34
+ end
35
+
36
+ attr_reader :root
37
+
38
+ def initialize
39
+ @root = Node.new
40
+ end
41
+
42
+ # Load all OpenAPI schemas from data/ and build the tree.
43
+ def self.load(schema_dir: SCHEMA_DIR)
44
+ tree = new
45
+ Pathname.glob(schema_dir / "*.yaml").each do |path|
46
+ tree.load_schema(path)
47
+ end
48
+ tree
49
+ end
50
+
51
+ # Parse a single OpenAPI YAML file and insert its paths into the tree.
52
+ def load_schema(path)
53
+ doc = YAML.safe_load(File.read(path), permitted_classes: [Symbol], aliases: true)
54
+ return unless doc.is_a?(Hash)
55
+
56
+ base_path = extract_base_path(doc)
57
+ paths = doc["paths"]
58
+ return unless paths.is_a?(Hash)
59
+
60
+ paths.each do |path_template, methods_hash|
61
+ next unless methods_hash.is_a?(Hash)
62
+
63
+ # Build full path: basePath + path_template
64
+ full_path = "#{base_path}#{path_template.strip}"
65
+ segments = full_path.split("/").reject(&:empty?)
66
+
67
+ methods_hash.each do |method, operation|
68
+ next unless %w[get post put delete patch head].include?(method)
69
+ operation_id = operation.is_a?(Hash) ? operation["operationId"] : nil
70
+ insert(segments, method, operation_id)
71
+ end
72
+ end
73
+ end
74
+
75
+ # Insert a path (as array of segments) with an HTTP method into the trie.
76
+ def insert(segments, method, operation_id = nil)
77
+ node = @root
78
+ segments.each do |segment|
79
+ if segment.start_with?("{") && segment.end_with?("}")
80
+ # Wildcard segment — matches any value
81
+ node.wildcard ||= Node.new
82
+ node = node.wildcard
83
+ else
84
+ node.children[segment] ||= Node.new
85
+ node = node.children[segment]
86
+ end
87
+ end
88
+ node.methods << method.downcase unless node.methods.include?(method.downcase)
89
+ node.operation_ids[method.downcase] = operation_id if operation_id
90
+ end
91
+
92
+ # Match a concrete path (array of segments) against the trie.
93
+ # Returns a result hash.
94
+ def match(segments, method = nil)
95
+ node = @root
96
+ segments.each do |segment|
97
+ if node.children.key?(segment)
98
+ node = node.children[segment]
99
+ elsif node.wildcard
100
+ node = node.wildcard
101
+ else
102
+ return {valid: false, methods: [], operation_id: nil}
103
+ end
104
+ end
105
+
106
+ if method
107
+ method_down = method.downcase
108
+ valid = node.methods.include?(method_down)
109
+ {valid: valid, methods: node.methods, operation_id: node.operation_ids[method_down]}
110
+ else
111
+ {valid: node.methods.any?, methods: node.methods, operation_id: nil}
112
+ end
113
+ end
114
+
115
+ private
116
+
117
+ def extract_base_path(doc)
118
+ servers = doc["servers"]
119
+ return "" unless servers.is_a?(Array) && servers.first.is_a?(Hash)
120
+
121
+ server = servers.first
122
+ variables = server["variables"] || {}
123
+ base_path_var = variables["basePath"]
124
+ return "" unless base_path_var.is_a?(Hash)
125
+
126
+ base_path_var["default"] || ""
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ test do
134
+ describe "Async::Matrix::Api::PathTree" do
135
+ def make_tree
136
+ tree = Async::Matrix::Api::PathTree.new
137
+ # Simulate a few endpoints manually
138
+ tree.insert(%w[_matrix client v3 account whoami], "get", "getAccountWhoami")
139
+ tree.insert(%w[_matrix client v3 createRoom], "post", "createRoom")
140
+ tree.insert(%w[_matrix client v3 rooms {roomId} ban], "post", "ban")
141
+ tree.insert(%w[_matrix client v3 rooms {roomId} unban], "post", "unban")
142
+ tree.insert(%w[_matrix client v3 rooms {roomId} state {eventType} {stateKey}], "get", "getRoomStateWithKey")
143
+ tree.insert(%w[_matrix client v3 rooms {roomId} state {eventType} {stateKey}], "put", "setRoomStateWithKey")
144
+ tree.insert(%w[_matrix client v3 rooms {roomId} messages], "get", "getRoomMessages")
145
+ tree.insert(%w[_matrix client v3 profile {userId} displayname], "get", "getDisplayName")
146
+ tree.insert(%w[_matrix client v3 profile {userId} displayname], "put", "setDisplayName")
147
+ tree
148
+ end
149
+
150
+ it "matches a simple path" do
151
+ tree = make_tree
152
+ result = tree.match(%w[_matrix client v3 account whoami], "GET")
153
+ result[:valid].should == true
154
+ result[:operation_id].should == "getAccountWhoami"
155
+ end
156
+
157
+ it "rejects unknown paths" do
158
+ tree = make_tree
159
+ result = tree.match(%w[_matrix client v3 account foobar], "GET")
160
+ result[:valid].should == false
161
+ end
162
+
163
+ it "matches wildcard segments" do
164
+ tree = make_tree
165
+ result = tree.match(%w[_matrix client v3 rooms !abc:ex.com ban], "POST")
166
+ result[:valid].should == true
167
+ result[:operation_id].should == "ban"
168
+ end
169
+
170
+ it "matches deep wildcard paths" do
171
+ tree = make_tree
172
+ result = tree.match(%w[_matrix client v3 rooms !abc:ex.com state m.room.name some_key], "GET")
173
+ result[:valid].should == true
174
+ result[:operation_id].should == "getRoomStateWithKey"
175
+ end
176
+
177
+ it "rejects wrong HTTP method" do
178
+ tree = make_tree
179
+ result = tree.match(%w[_matrix client v3 account whoami], "POST")
180
+ result[:valid].should == false
181
+ end
182
+
183
+ it "reports available methods" do
184
+ tree = make_tree
185
+ result = tree.match(%w[_matrix client v3 profile @user:ex.com displayname])
186
+ result[:valid].should == true
187
+ result[:methods].should.include "get"
188
+ result[:methods].should.include "put"
189
+ end
190
+
191
+ it "loads from real schema files" do
192
+ skip "schemas not present" unless Async::Matrix::Api::PathTree::SCHEMA_DIR.exist?
193
+ tree = Async::Matrix::Api::PathTree.load
194
+ # createRoom should exist
195
+ result = tree.match(%w[_matrix client v3 createRoom], "POST")
196
+ result[:valid].should == true
197
+ # rooms/{id}/ban should exist
198
+ result = tree.match(%w[_matrix client v3 rooms !test:ex.com ban], "POST")
199
+ result[:valid].should == true
200
+ # sync should exist
201
+ result = tree.match(%w[_matrix client v3 sync], "GET")
202
+ result[:valid].should == true
203
+ # nonsense should not
204
+ result = tree.match(%w[_matrix client v3 totallyFake], "GET")
205
+ result[:valid].should == false
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,204 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the Apache License, Version 2.0.
4
+ # Copyright, 2026, by General Intelligence Systems.
5
+
6
+ require "bundler/setup"
7
+ require "async/matrix"
8
+
9
+ module Async
10
+ module Matrix
11
+ # Runtime-generated Matrix Client-Server API built from official OpenAPI schemas.
12
+ #
13
+ # Loads the OpenAPI 3.1.0 YAML files from data/matrix-spec/api/client-server/
14
+ # at require-time and builds a PathTree trie of all valid endpoints. API calls
15
+ # are constructed via StringBuilder method chains, validated against the tree,
16
+ # and terminated by .get(), .post(), .put(), or .delete().
17
+ #
18
+ # Usage:
19
+ # # Via Client:
20
+ # client.api.account.whoami.get
21
+ # client.api.createRoom.post(name: "Pub", preset: "public_chat")
22
+ # client.api.rooms("!room:ex.com").ban.post(user_id: "@bad:ex.com")
23
+ # client.api.rooms("!room:ex.com").messages.get(dir: "b", limit: 10)
24
+ #
25
+ # # Standalone (for inspection):
26
+ # gateway = Async::Matrix::Api::Gateway.new(client)
27
+ # chain = gateway.chain
28
+ # chain.rooms("!room:ex.com").state("m.room.name", "").get
29
+ #
30
+ module Api
31
+ # The shared PathTree instance, loaded once from the bundled schemas.
32
+ def self.path_tree
33
+ @path_tree ||= PathTree.load
34
+ end
35
+
36
+ # Reset the cached path tree (useful for testing or reloading schemas).
37
+ def self.reset!
38
+ @path_tree = nil
39
+ end
40
+
41
+ # Gateway produces Chain instances bound to a specific Client.
42
+ # Each call to a method on the Gateway starts a new chain.
43
+ class Gateway
44
+ def initialize(client, prefix: %w[_matrix client v3])
45
+ @client = client
46
+ @prefix = prefix
47
+ end
48
+
49
+ # Start a fresh chain. Every method call on the gateway creates
50
+ # a new chain so chains are never reused.
51
+ def chain
52
+ Chain.new(client: @client, path_tree: Api.path_tree, prefix: @prefix)
53
+ end
54
+
55
+ # Forward all unknown methods to a fresh chain, starting the path.
56
+ def method_missing(name, *args, **kwargs, &block)
57
+ if name.start_with?("to_")
58
+ super
59
+ else
60
+ chain.__send__(name, *args, **kwargs, &block)
61
+ end
62
+ end
63
+
64
+ def respond_to_missing?(name, include_private = false)
65
+ !name.start_with?("to_") || super
66
+ end
67
+
68
+ def inspect
69
+ "#<#{self.class} prefix=/#{@prefix.join("/")}>"
70
+ end
71
+ end
72
+ end
73
+
74
+ end
75
+ end
76
+
77
+ test do
78
+ describe "Async::Matrix::Api::Gateway" do
79
+ # Stub client that records calls instead of making HTTP requests.
80
+ StubClient = Struct.new(:calls) do
81
+ def initialize
82
+ super([])
83
+ end
84
+
85
+ def get(path, max_retries: nil)
86
+ calls << [:get, path, {max_retries: max_retries}]
87
+ {"stub" => true}
88
+ end
89
+
90
+ def post(path, body = {}, max_retries: nil)
91
+ calls << [:post, path, body, {max_retries: max_retries}]
92
+ {"stub" => true}
93
+ end
94
+
95
+ def put(path, body = {}, max_retries: nil)
96
+ calls << [:put, path, body, {max_retries: max_retries}]
97
+ {"stub" => true}
98
+ end
99
+
100
+ def request(method, path, body = nil, max_retries: nil)
101
+ calls << [method.downcase.to_sym, path, body, {max_retries: max_retries}]
102
+ {"stub" => true}
103
+ end
104
+ end
105
+
106
+ def make_gateway
107
+ client = StubClient.new
108
+ # Build a small tree manually for deterministic tests
109
+ tree = Async::Matrix::Api::PathTree.new
110
+ tree.insert(%w[_matrix client v3 account whoami], "get")
111
+ tree.insert(%w[_matrix client v3 createRoom], "post")
112
+ tree.insert(%w[_matrix client v3 rooms {roomId} ban], "post")
113
+ tree.insert(%w[_matrix client v3 rooms {roomId} messages], "get")
114
+ tree.insert(%w[_matrix client v3 rooms {roomId} send {eventType} {txnId}], "put")
115
+ tree.insert(%w[_matrix client v3 profile {userId} displayname], "put")
116
+ tree.insert(%w[_matrix client v3 join {roomIdOrAlias}], "post")
117
+ tree.insert(%w[_matrix client v3 rooms {roomId} leave], "post")
118
+
119
+ # Inject our test tree
120
+ Async::Matrix::Api.instance_variable_set(:@path_tree, tree)
121
+
122
+ gateway = Async::Matrix::Api::Gateway.new(client)
123
+ [gateway, client]
124
+ end
125
+
126
+ it "GET /account/whoami" do
127
+ gw, client = make_gateway
128
+ gw.account.whoami.get
129
+ client.calls.last[0].should == :get
130
+ client.calls.last[1].should == "/_matrix/client/v3/account/whoami"
131
+ end
132
+
133
+ it "POST /createRoom with body" do
134
+ gw, client = make_gateway
135
+ gw.createRoom.post(name: "Pub", preset: "public_chat")
136
+ client.calls.last[0].should == :post
137
+ client.calls.last[1].should == "/_matrix/client/v3/createRoom"
138
+ client.calls.last[2].should == {name: "Pub", preset: "public_chat"}
139
+ end
140
+
141
+ it "POST /rooms/{roomId}/ban with body" do
142
+ gw, client = make_gateway
143
+ gw.rooms("!abc:ex.com").ban.post(user_id: "@bad:ex.com", reason: "spam")
144
+ client.calls.last[0].should == :post
145
+ client.calls.last[1].should == "/_matrix/client/v3/rooms/%21abc%3Aex.com/ban"
146
+ client.calls.last[2].should == {user_id: "@bad:ex.com", reason: "spam"}
147
+ end
148
+
149
+ it "GET /rooms/{roomId}/messages with query params" do
150
+ gw, client = make_gateway
151
+ gw.rooms("!abc:ex.com").messages.get(dir: "b", limit: 10)
152
+ call = client.calls.last
153
+ call[0].should == :get
154
+ call[1].should.include "/_matrix/client/v3/rooms/%21abc%3Aex.com/messages?"
155
+ call[1].should.include "dir=b"
156
+ call[1].should.include "limit=10"
157
+ end
158
+
159
+ it "PUT /rooms/{roomId}/send/{eventType}/{txnId}" do
160
+ gw, client = make_gateway
161
+ gw.rooms("!abc:ex.com").send("m.room.message", "txn-1").put(msgtype: "m.text", body: "hi")
162
+ call = client.calls.last
163
+ call[0].should == :put
164
+ call[1].should == "/_matrix/client/v3/rooms/%21abc%3Aex.com/send/m.room.message/txn-1"
165
+ call[2].should == {msgtype: "m.text", body: "hi"}
166
+ end
167
+
168
+ it "PUT /profile/{userId}/displayname" do
169
+ gw, client = make_gateway
170
+ gw.profile("@user:ex.com").displayname.put(displayname: "Bob")
171
+ call = client.calls.last
172
+ call[0].should == :put
173
+ call[1].should == "/_matrix/client/v3/profile/%40user%3Aex.com/displayname"
174
+ call[2].should == {displayname: "Bob"}
175
+ end
176
+
177
+ it "POST /join/{roomIdOrAlias}" do
178
+ gw, client = make_gateway
179
+ gw.join("!abc:ex.com").post
180
+ call = client.calls.last
181
+ call[0].should == :post
182
+ call[1].should == "/_matrix/client/v3/join/%21abc%3Aex.com"
183
+ end
184
+
185
+ it "raises InvalidEndpointError for unknown path" do
186
+ gw, _ = make_gateway
187
+ lambda { gw.totally.bogus.endpoint.get }.should.raise Async::Matrix::InvalidEndpointError
188
+ end
189
+
190
+ it "raises InvalidEndpointError for wrong method" do
191
+ gw, _ = make_gateway
192
+ lambda { gw.account.whoami.post }.should.raise Async::Matrix::InvalidEndpointError
193
+ end
194
+
195
+ it "each gateway method call starts a fresh chain" do
196
+ gw, client = make_gateway
197
+ gw.account.whoami.get
198
+ gw.createRoom.post(name: "test")
199
+ client.calls.length.should == 2
200
+ client.calls[0][1].should == "/_matrix/client/v3/account/whoami"
201
+ client.calls[1][1].should == "/_matrix/client/v3/createRoom"
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,235 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the Apache License, Version 2.0.
4
+ # Copyright, 2026, by General Intelligence Systems.
5
+
6
+ require "bundler/setup"
7
+ require "console"
8
+ require "async/matrix"
9
+
10
+ module Async
11
+ module Matrix
12
+ module ApplicationService
13
+ # DSL wrapper that pairs a Client with event handlers.
14
+ #
15
+ # A Bot produces handler objects that conform to the Dispatcher's
16
+ # duck-type contract (#event_types, #call). Register a bot on a
17
+ # Server (or Dispatcher) the same way you would register a plain handler.
18
+ #
19
+ # bot = Bot.new(client) do
20
+ # on "m.room.member" do |event|
21
+ # join_room(event.room_id) if event.content.membership == "invite"
22
+ # end
23
+ #
24
+ # on "m.room.message", msgtype: "m.text", not_from: :self do |event|
25
+ # send_notice event.room_id, "Echo: #{event.content.body}"
26
+ # end
27
+ # end
28
+ #
29
+ # server.register(bot)
30
+ #
31
+ class Bot
32
+ attr_reader :client, :handlers
33
+
34
+ def initialize(client, &block)
35
+ @client = client
36
+ @handlers = []
37
+
38
+ instance_eval(&block) if block
39
+ end
40
+
41
+ # Register a handler block for one or more event types.
42
+ #
43
+ # Filters (all optional):
44
+ # msgtype: — only dispatch when content.msgtype matches (e.g. "m.text")
45
+ # not_from: — :self skips events sent by this bot's own MXID
46
+ #
47
+ def on(*event_types, msgtype: nil, not_from: nil, &block)
48
+ raise ArgumentError, "on requires at least one event type" if event_types.empty?
49
+ raise ArgumentError, "on requires a block" unless block
50
+
51
+ handler = Handler.new(
52
+ bot: self,
53
+ event_types: event_types.flatten,
54
+ msgtype: msgtype,
55
+ not_from: not_from,
56
+ block: block
57
+ )
58
+
59
+ @handlers << handler
60
+ handler
61
+ end
62
+
63
+ # Internal handler object produced by the #on DSL method.
64
+ # Conforms to the Dispatcher duck-type: #event_types, #call.
65
+ class Handler
66
+ attr_reader :event_types
67
+
68
+ def initialize(bot:, event_types:, msgtype:, not_from:, block:)
69
+ @bot = bot
70
+ @event_types = event_types
71
+ @msgtype = msgtype
72
+ @not_from = not_from
73
+ @block = block
74
+ end
75
+
76
+ def call(event)
77
+ return if @msgtype && event.content&.msgtype != @msgtype
78
+ return if @not_from == :self && event.sender == @bot.client.config.bot_mxid
79
+
80
+ # Execute the block in a context that has helper methods
81
+ Context.new(@bot.client).execute(event, &@block)
82
+ end
83
+ end
84
+
85
+ # Execution context for handler blocks.
86
+ # Provides helper methods so blocks can call send_notice, join_room, etc.
87
+ # directly without holding a reference to the client.
88
+ class Context
89
+ def initialize(client)
90
+ @client = client
91
+ end
92
+
93
+ def execute(event, &block)
94
+ @event = event
95
+ instance_exec(event, &block)
96
+ end
97
+
98
+ def send_text(room_id, text)
99
+ @client.send_text(room_id, text)
100
+ end
101
+
102
+ def send_html(room_id, html, plaintext = nil)
103
+ @client.send_html(room_id, html, plaintext)
104
+ end
105
+
106
+ def send_notice(room_id, text)
107
+ @client.send_notice(room_id, text)
108
+ end
109
+
110
+ def join_room(room_id)
111
+ @client.join_room(room_id)
112
+ end
113
+
114
+ def leave_room(room_id)
115
+ @client.leave_room(room_id)
116
+ end
117
+
118
+ def set_display_name(name, user_id = nil)
119
+ @client.set_display_name(name, user_id)
120
+ end
121
+
122
+ def client
123
+ @client
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ test do
132
+ describe "Async::Matrix::ApplicationService::Bot" do
133
+ def make_config
134
+ Async::Matrix::ApplicationService::Config.new({
135
+ "homeserver" => { "address" => "http://localhost:8008", "domain" => "localhost" },
136
+ "appservice" => { "as_token" => "token_secret", "hs_token" => "hs_secret", "bot" => { "username" => "bot" } }
137
+ })
138
+ end
139
+
140
+ def make_event(type:, sender: "@user:localhost", msgtype: nil, body: nil, membership: nil, state_key: nil)
141
+ data = {"type" => type, "sender" => sender, "room_id" => "!room:localhost"}
142
+ content = {}
143
+ content["msgtype"] = msgtype if msgtype
144
+ content["body"] = body if body
145
+ content["membership"] = membership if membership
146
+ data["state_key"] = state_key if state_key
147
+ data["content"] = content
148
+ Async::Matrix::ApplicationService::Event.new(data)
149
+ end
150
+
151
+ it "registers handlers via the on DSL" do
152
+ config = make_config
153
+ client = Async::Matrix::Client.new(config)
154
+
155
+ bot = Async::Matrix::ApplicationService::Bot.new(client) do
156
+ on "m.room.message" do |event|
157
+ # no-op
158
+ end
159
+ end
160
+
161
+ bot.handlers.length.should == 1
162
+ bot.handlers.first.event_types.should == ["m.room.message"]
163
+ end
164
+
165
+ it "registers multiple event types on a single handler" do
166
+ config = make_config
167
+ client = Async::Matrix::Client.new(config)
168
+
169
+ bot = Async::Matrix::ApplicationService::Bot.new(client) do
170
+ on "m.room.message", "m.room.member" do |event|
171
+ # no-op
172
+ end
173
+ end
174
+
175
+ bot.handlers.first.event_types.should == ["m.room.message", "m.room.member"]
176
+ end
177
+
178
+ it "filters by msgtype" do
179
+ config = make_config
180
+ client = Async::Matrix::Client.new(config)
181
+ received = []
182
+
183
+ bot = Async::Matrix::ApplicationService::Bot.new(client) do
184
+ on "m.room.message", msgtype: "m.text" do |event|
185
+ received << event.content.body
186
+ end
187
+ end
188
+
189
+ handler = bot.handlers.first
190
+ handler.call(make_event(type: "m.room.message", msgtype: "m.text", body: "hello"))
191
+ handler.call(make_event(type: "m.room.message", msgtype: "m.notice", body: "ignored"))
192
+
193
+ received.should == ["hello"]
194
+ end
195
+
196
+ it "filters out self with not_from: :self" do
197
+ config = make_config
198
+ client = Async::Matrix::Client.new(config)
199
+ received = []
200
+
201
+ bot = Async::Matrix::ApplicationService::Bot.new(client) do
202
+ on "m.room.message", not_from: :self do |event|
203
+ received << event.content.body
204
+ end
205
+ end
206
+
207
+ handler = bot.handlers.first
208
+ handler.call(make_event(type: "m.room.message", sender: "@user:localhost", msgtype: "m.text", body: "yes"))
209
+ handler.call(make_event(type: "m.room.message", sender: "@bot:localhost", msgtype: "m.text", body: "no"))
210
+
211
+ received.should == ["yes"]
212
+ end
213
+
214
+ it "raises if on is called without event types" do
215
+ config = make_config
216
+ client = Async::Matrix::Client.new(config)
217
+
218
+ lambda {
219
+ Async::Matrix::ApplicationService::Bot.new(client) do
220
+ on do |event|; end
221
+ end
222
+ }.should.raise(ArgumentError)
223
+ end
224
+
225
+ it "raises if on is called without a block" do
226
+ config = make_config
227
+ client = Async::Matrix::Client.new(config)
228
+
229
+ lambda {
230
+ bot = Async::Matrix::ApplicationService::Bot.new(client)
231
+ bot.on "m.room.message"
232
+ }.should.raise(ArgumentError)
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "analytics.json",
4
+ "description": "Analytics/telemetry settings. Maps to mautrix bridgev2/bridgeconfig.AnalyticsConfig.",
5
+ "type": "object",
6
+ "properties": {
7
+ "token": {
8
+ "type": "string",
9
+ "description": "Analytics token for the telemetry backend."
10
+ },
11
+ "url": {
12
+ "type": "string",
13
+ "description": "URL of the analytics/telemetry endpoint."
14
+ },
15
+ "user_id": {
16
+ "type": "string",
17
+ "description": "User ID to associate with analytics events."
18
+ }
19
+ },
20
+ "additionalProperties": false
21
+ }