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
@@ -8,15 +8,15 @@ require "async/http"
8
8
  require "async/matrix"
9
9
 
10
10
  module Async
11
- module Matrix
12
- module Connection
13
- include Async::HTTP::Protocol::HTTP2::Connection
14
- end
15
- end
11
+ module Matrix
12
+ module Connection
13
+ include Async::HTTP::Protocol::HTTP2::Connection
14
+ end
15
+ end
16
16
  end
17
17
 
18
18
  test do
19
- it "includes Async::HTTP::Protocol::HTTP2::Connection" do
20
- Async::Matrix::Connection.ancestors.should.include Async::HTTP::Protocol::HTTP2::Connection
21
- end
19
+ it "includes Async::HTTP::Protocol::HTTP2::Connection" do
20
+ Async::Matrix::Connection.ancestors.should.include Async::HTTP::Protocol::HTTP2::Connection
21
+ end
22
22
  end
@@ -0,0 +1,84 @@
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
+ # A Client subclass that authenticates with a user's double puppet token
12
+ # instead of the appservice's as_token.
13
+ #
14
+ # This allows the bridge to send events as the real Matrix user rather
15
+ # than as the appservice bot or a ghost user.
16
+ #
17
+ # puppet = DoublePuppetClient.new(config, double_puppet_token: "syt_...")
18
+ # puppet.send_text("!room:example.com", "sent as the real user")
19
+ # puppet.whoami # => {"user_id" => "@alice:example.com"}
20
+ #
21
+ class DoublePuppetClient < Client
22
+ def initialize(config, double_puppet_token:, **kwargs)
23
+ super(config, **kwargs)
24
+ @headers[0] = ["authorization", "Bearer #{double_puppet_token}"]
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ test do
31
+ describe "Async::Matrix::DoublePuppetClient" do
32
+ def make_config
33
+ Async::Matrix::ApplicationService::Config.new({
34
+ "homeserver" => { "address" => "http://localhost:8008", "domain" => "localhost" },
35
+ "appservice" => { "as_token" => "as_token_value", "hs_token" => "hs_secret", "bot" => { "username" => "bot" } }
36
+ })
37
+ end
38
+
39
+ it "uses the double_puppet_token for authorization" do
40
+ puppet = Async::Matrix::DoublePuppetClient.new(make_config, double_puppet_token: "syt_puppet_token")
41
+ auth_header = puppet.instance_variable_get(:@headers).find { |k, _| k == "authorization" }
42
+ auth_header[1].should == "Bearer syt_puppet_token"
43
+ end
44
+
45
+ it "does not use the as_token from config" do
46
+ puppet = Async::Matrix::DoublePuppetClient.new(make_config, double_puppet_token: "syt_puppet_token")
47
+ auth_header = puppet.instance_variable_get(:@headers).find { |k, _| k == "authorization" }
48
+ auth_header[1].should.not.include "as_token_value"
49
+ end
50
+
51
+ it "inherits retry defaults from Client" do
52
+ puppet = Async::Matrix::DoublePuppetClient.new(make_config, double_puppet_token: "syt_puppet_token")
53
+ puppet.config.appservice.as_token.should == "as_token_value"
54
+ end
55
+
56
+ it "accepts custom retry configuration" do
57
+ puppet = Async::Matrix::DoublePuppetClient.new(
58
+ make_config,
59
+ double_puppet_token: "syt_puppet_token",
60
+ max_retries: 5,
61
+ retry_base_delay: 1.0,
62
+ max_retry_delay: 60
63
+ )
64
+ auth_header = puppet.instance_variable_get(:@headers).find { |k, _| k == "authorization" }
65
+ auth_header[1].should == "Bearer syt_puppet_token"
66
+ end
67
+
68
+ it "responds to all Client methods" do
69
+ puppet = Async::Matrix::DoublePuppetClient.new(make_config, double_puppet_token: "syt_puppet_token")
70
+ puppet.should.respond_to :send_text
71
+ puppet.should.respond_to :send_html
72
+ puppet.should.respond_to :send_notice
73
+ puppet.should.respond_to :join_room
74
+ puppet.should.respond_to :leave_room
75
+ puppet.should.respond_to :whoami
76
+ puppet.should.respond_to :api
77
+ end
78
+
79
+ it "is a subclass of Client" do
80
+ puppet = Async::Matrix::DoublePuppetClient.new(make_config, double_puppet_token: "syt_puppet_token")
81
+ puppet.should.be.kind_of Async::Matrix::Client
82
+ end
83
+ end
84
+ end
@@ -9,52 +9,52 @@ require "async/http"
9
9
  require "async/matrix"
10
10
 
11
11
  module Async
12
- module Matrix
13
- # Extends Async::HTTP::Endpoint with Matrix well-known discovery.
14
- # spec.matrix.org/v1.9/client-server-api/#well-known-uri
15
- #
16
- # A server at example.com may serve clients from a completely
17
- # different origin — e.g. https://matrix.example.com:8448.
18
- # #discover resolves that indirection as a proper async I/O
19
- # operation before constructing the Endpoint, so every downstream
20
- # caller gets a correctly-pointed connection pool for free.
21
- class Endpoint < Async::HTTP::Endpoint
22
- WELL_KNOWN = "/.well-known/matrix/client"
23
-
24
- # Resolves homeserver base URL, falls back to https://domain.
25
- # Must be called inside an Async block — uses the running scheduler.
26
- def self.discover(domain, **options)
27
- internet = Async::HTTP::Internet.new
28
- data = JSON.parse(internet.get("https://#{domain}#{WELL_KNOWN}").read)
29
- base_url = data.dig("m.homeserver", "base_url") || "https://#{domain}"
30
- parse(base_url, **options)
31
- rescue StandardError
32
- # Well-known is optional per spec — fall back gracefully
33
- parse("https://#{domain}", **options)
34
- ensure
35
- internet&.close
36
- end
37
- end
38
- end
12
+ module Matrix
13
+ # Extends Async::HTTP::Endpoint with Matrix well-known discovery.
14
+ # spec.matrix.org/v1.9/client-server-api/#well-known-uri
15
+ #
16
+ # A server at example.com may serve clients from a completely
17
+ # different origin — e.g. https://matrix.example.com:8448.
18
+ # #discover resolves that indirection as a proper async I/O
19
+ # operation before constructing the Endpoint, so every downstream
20
+ # caller gets a correctly-pointed connection pool for free.
21
+ class Endpoint < Async::HTTP::Endpoint
22
+ WELL_KNOWN = "/.well-known/matrix/client"
23
+
24
+ # Resolves homeserver base URL, falls back to https://domain.
25
+ # Must be called inside an Async block — uses the running scheduler.
26
+ def self.discover(domain, **options)
27
+ internet = Async::HTTP::Internet.new
28
+ data = JSON.parse(internet.get("https://#{domain}#{WELL_KNOWN}").read)
29
+ base_url = data.dig("m.homeserver", "base_url") || "https://#{domain}"
30
+ parse(base_url, **options)
31
+ rescue StandardError
32
+ # Well-known is optional per spec — fall back gracefully
33
+ parse("https://#{domain}", **options)
34
+ ensure
35
+ internet&.close
36
+ end
37
+ end
38
+ end
39
39
  end
40
40
 
41
41
  test do
42
- it "defines the WELL_KNOWN constant" do
43
- Async::Matrix::Endpoint::WELL_KNOWN.should == "/.well-known/matrix/client"
44
- end
45
-
46
- it "responds to .discover" do
47
- Async::Matrix::Endpoint.should.respond_to :discover
48
- end
49
-
50
- it "inherits from Async::HTTP::Endpoint" do
51
- Async::Matrix::Endpoint.ancestors.should.include Async::HTTP::Endpoint
52
- end
53
-
54
- it "falls back to https://domain when well-known fails" do
55
- Async do
56
- endpoint = Async::Matrix::Endpoint.discover("nonexistent.invalid")
57
- endpoint.to_s.should =~ /nonexistent\.invalid/
58
- end.wait
59
- end
42
+ it "defines the WELL_KNOWN constant" do
43
+ Async::Matrix::Endpoint::WELL_KNOWN.should == "/.well-known/matrix/client"
44
+ end
45
+
46
+ it "responds to .discover" do
47
+ Async::Matrix::Endpoint.should.respond_to :discover
48
+ end
49
+
50
+ it "inherits from Async::HTTP::Endpoint" do
51
+ Async::Matrix::Endpoint.ancestors.should.include Async::HTTP::Endpoint
52
+ end
53
+
54
+ it "falls back to https://domain when well-known fails" do
55
+ Async do
56
+ endpoint = Async::Matrix::Endpoint.discover("nonexistent.invalid")
57
+ endpoint.to_s.should =~ /nonexistent\.invalid/
58
+ end.wait
59
+ end
60
60
  end
@@ -6,59 +6,65 @@
6
6
  require "bundler/setup"
7
7
 
8
8
  module Async
9
- module Matrix
10
- class Error < StandardError
11
- attr_reader :errcode, :status
9
+ module Matrix
10
+ class Error < StandardError
11
+ attr_reader :errcode, :status
12
12
 
13
- def initialize(errcode, message, status: nil)
14
- @errcode = errcode
15
- @status = status
16
- super(message)
17
- end
18
- end
13
+ def initialize(errcode, message, status: nil)
14
+ @errcode = errcode
15
+ @status = status
16
+ super(message)
17
+ end
18
+ end
19
19
 
20
- class NotFoundError < Error; end
21
- class BadJsonError < Error; end
22
- class AuthError < Error; end
23
- class HomeserverError < Error; end
24
- end
20
+ class NotFoundError < Error; end
21
+ class BadJsonError < Error; end
22
+ class AuthError < Error; end
23
+ class HomeserverError < Error; end
24
+ class InvalidEndpointError < Error; end
25
+ class ResponseTooLargeError < Error; end
26
+ end
25
27
  end
26
28
 
27
29
  test do
28
- describe "Async::Matrix::Error" do
29
- it "stores errcode and message" do
30
- err = Async::Matrix::Error.new("M_UNKNOWN", "something broke")
31
- err.errcode.should == "M_UNKNOWN"
32
- err.message.should == "something broke"
33
- end
30
+ describe "Async::Matrix::Error" do
31
+ it "stores errcode and message" do
32
+ err = Async::Matrix::Error.new("M_UNKNOWN", "something broke")
33
+ err.errcode.should == "M_UNKNOWN"
34
+ err.message.should == "something broke"
35
+ end
34
36
 
35
- it "stores optional status" do
36
- err = Async::Matrix::Error.new("M_UNKNOWN", "bad", status: 400)
37
- err.status.should == 400
38
- end
37
+ it "stores optional status" do
38
+ err = Async::Matrix::Error.new("M_UNKNOWN", "bad", status: 400)
39
+ err.status.should == 400
40
+ end
39
41
 
40
- it "defaults status to nil" do
41
- Async::Matrix::Error.new("M_UNKNOWN", "bad").status.should.be.nil
42
- end
42
+ it "defaults status to nil" do
43
+ Async::Matrix::Error.new("M_UNKNOWN", "bad").status.should.be.nil
44
+ end
43
45
 
44
- it "is a StandardError" do
45
- Async::Matrix::Error.new("M_UNKNOWN", "bad").should.be.kind_of StandardError
46
- end
47
- end
46
+ it "is a StandardError" do
47
+ Async::Matrix::Error.new("M_UNKNOWN", "bad").should.be.kind_of StandardError
48
+ end
49
+ end
48
50
 
49
- it "NotFoundError inherits from Error" do
50
- Async::Matrix::NotFoundError.new("M_NOT_FOUND", "gone").should.be.kind_of Async::Matrix::Error
51
- end
51
+ it "NotFoundError inherits from Error" do
52
+ Async::Matrix::NotFoundError.new("M_NOT_FOUND", "gone").should.be.kind_of Async::Matrix::Error
53
+ end
52
54
 
53
- it "BadJsonError inherits from Error" do
54
- Async::Matrix::BadJsonError.new("M_BAD_JSON", "invalid").should.be.kind_of Async::Matrix::Error
55
- end
55
+ it "BadJsonError inherits from Error" do
56
+ Async::Matrix::BadJsonError.new("M_BAD_JSON", "invalid").should.be.kind_of Async::Matrix::Error
57
+ end
56
58
 
57
- it "AuthError inherits from Error" do
58
- Async::Matrix::AuthError.new("M_FORBIDDEN", "denied").should.be.kind_of Async::Matrix::Error
59
- end
59
+ it "AuthError inherits from Error" do
60
+ Async::Matrix::AuthError.new("M_FORBIDDEN", "denied").should.be.kind_of Async::Matrix::Error
61
+ end
60
62
 
61
- it "HomeserverError inherits from Error" do
62
- Async::Matrix::HomeserverError.new("M_UNKNOWN", "upstream").should.be.kind_of Async::Matrix::Error
63
- end
63
+ it "HomeserverError inherits from Error" do
64
+ Async::Matrix::HomeserverError.new("M_UNKNOWN", "upstream").should.be.kind_of Async::Matrix::Error
65
+ end
66
+
67
+ it "ResponseTooLargeError inherits from Error" do
68
+ Async::Matrix::ResponseTooLargeError.new("M_TOO_LARGE", "too big").should.be.kind_of Async::Matrix::Error
69
+ end
64
70
  end
@@ -0,0 +1,173 @@
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/http/internet"
8
+ require "async/matrix"
9
+ require "json"
10
+ require "console"
11
+
12
+ module Async
13
+ module Matrix
14
+ # Async HTTP client for binary Matrix media operations.
15
+ #
16
+ # Handles raw byte uploads and downloads against the Matrix content
17
+ # repository. Unlike the JSON-only Client, this never wraps request
18
+ # bodies in JSON.generate and can return raw binary response bodies.
19
+ #
20
+ # Not intended to be used directly — the Chain dispatches here
21
+ # automatically when the request path matches a BINARY_ROUTES entry.
22
+ #
23
+ # media_client = Async::Matrix::MediaClient.new(config)
24
+ # media_client.upload("POST", path, bytes, "image/png")
25
+ # bytes = media_client.download(path)
26
+ #
27
+ class MediaClient
28
+ # Upload JSON responses are small; error bodies are even smaller.
29
+ UPLOAD_RESPONSE_SIZE_LIMIT = 1 * 1024 * 1024 # 1 MiB
30
+ ERROR_RESPONSE_SIZE_LIMIT = 512 * 1024 # 512 KiB
31
+
32
+ def initialize(config)
33
+ @config = config
34
+ @base = config.homeserver.address
35
+ @auth_headers = [
36
+ ["authorization", "Bearer #{config.appservice.as_token}"],
37
+ ["user-agent", "AsyncMatrix/#{Async::Matrix::VERSION}"]
38
+ ]
39
+ end
40
+
41
+ # Upload raw bytes to the content repository.
42
+ #
43
+ # @param method [String] HTTP method ("POST" or "PUT")
44
+ # @param path [String] URL path (already URL-encoded)
45
+ # @param body [String] raw bytes to upload
46
+ # @param content_type [String] MIME type of the body
47
+ # @return [Hash] parsed JSON response (e.g. {"content_uri" => "mxc://..."})
48
+ def upload(method, path, body, content_type = "application/octet-stream")
49
+ url = "#{@base}#{path}"
50
+ headers = @auth_headers + [["content-type", content_type]]
51
+
52
+ Console.debug(self) { "UPLOAD #{method} #{path} (#{content_type}, #{body.bytesize} bytes)" }
53
+
54
+ response = internet.call(method, url, headers, body)
55
+ status = response.status
56
+
57
+ unless (200..299).cover?(status)
58
+ payload = read_limited(response, ERROR_RESPONSE_SIZE_LIMIT)
59
+ parsed = ApplicationService::ErrorResponse.new(
60
+ begin; JSON.parse(payload); rescue; {} end
61
+ )
62
+ Console.error(self) { "Matrix media upload #{status}: #{parsed.errcode} — #{parsed.error}" }
63
+ raise HomeserverError.new(
64
+ parsed.errcode || "UNKNOWN",
65
+ parsed.error || payload.to_s[0..200],
66
+ status: status
67
+ )
68
+ end
69
+
70
+ payload = read_limited(response, UPLOAD_RESPONSE_SIZE_LIMIT)
71
+ payload && !payload.empty? ? JSON.parse(payload) : {}
72
+ end
73
+
74
+ # Download from the content repository.
75
+ #
76
+ # Returns the raw HTTP response object so the caller has access to
77
+ # both the body and response metadata:
78
+ #
79
+ # response = media_client.download(path)
80
+ # response.read # raw bytes (String, Encoding::BINARY)
81
+ # response.headers["content-type"] # "image/png"
82
+ # response.headers["content-disposition"] # "inline; filename=\"photo.jpg\""
83
+ # response.body.each { |chunk| ... } # streaming
84
+ #
85
+ # @param path [String] URL path (already URL-encoded, may include query string)
86
+ # @return [Protocol::HTTP::Response] the HTTP response
87
+ def download(path)
88
+ url = "#{@base}#{path}"
89
+
90
+ Console.debug(self) { "DOWNLOAD #{path}" }
91
+
92
+ response = internet.call("GET", url, @auth_headers, nil)
93
+ status = response.status
94
+
95
+ unless (200..299).cover?(status)
96
+ payload = response.read
97
+ parsed = ApplicationService::ErrorResponse.new(
98
+ begin; JSON.parse(payload); rescue; {} end
99
+ )
100
+ Console.error(self) { "Matrix media download #{status}: #{parsed.errcode} — #{parsed.error}" }
101
+ raise HomeserverError.new(
102
+ parsed.errcode || "UNKNOWN",
103
+ parsed.error || payload.to_s[0..200],
104
+ status: status
105
+ )
106
+ end
107
+
108
+ response
109
+ end
110
+
111
+ def close
112
+ @internet&.close
113
+ @internet = nil
114
+ end
115
+
116
+ private
117
+
118
+ def internet
119
+ @internet ||= Async::HTTP::Internet.new
120
+ end
121
+
122
+ # Read response body with a size limit. Raises ResponseTooLargeError
123
+ # if the body exceeds the limit.
124
+ def read_limited(response, limit)
125
+ body = response.body
126
+ return nil unless body
127
+
128
+ if body.respond_to?(:length) && body.length && body.length > limit
129
+ body.close
130
+ raise ResponseTooLargeError.new(
131
+ "M_TOO_LARGE",
132
+ "Response Content-Length #{body.length} bytes exceeds limit of #{limit} bytes"
133
+ )
134
+ end
135
+
136
+ buffer = String.new(encoding: Encoding::BINARY)
137
+ body.each do |chunk|
138
+ buffer << chunk
139
+ if buffer.bytesize > limit
140
+ body.close
141
+ raise ResponseTooLargeError.new(
142
+ "M_TOO_LARGE",
143
+ "Response body exceeds limit of #{limit} bytes"
144
+ )
145
+ end
146
+ end
147
+ buffer.empty? ? nil : buffer
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ test do
154
+ describe "Async::Matrix::MediaClient" do
155
+ def make_config
156
+ Async::Matrix::ApplicationService::Config.new({
157
+ "homeserver" => { "address" => "http://localhost:8008", "domain" => "localhost" },
158
+ "appservice" => { "as_token" => "test_token", "hs_token" => "hs_secret", "bot" => { "username" => "bot" } }
159
+ })
160
+ end
161
+
162
+ it "responds to upload and download" do
163
+ client = Async::Matrix::MediaClient.new(make_config)
164
+ client.should.respond_to :upload
165
+ client.should.respond_to :download
166
+ end
167
+
168
+ it "can be closed without error" do
169
+ client = Async::Matrix::MediaClient.new(make_config)
170
+ lambda { client.close }.should.not.raise
171
+ end
172
+ end
173
+ end