async-matrix 3.0.0-arm-linux-musl
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.
- checksums.yaml +7 -0
- data/LICENSE +200 -0
- data/README.md +108 -0
- data/data/discord-api-spec/openapi.json +40404 -0
- data/data/matrix-spec/api/client-server/account-data.yaml +389 -0
- data/data/matrix-spec/api/client-server/account_deactivation.yaml +149 -0
- data/data/matrix-spec/api/client-server/admin.yaml +512 -0
- data/data/matrix-spec/api/client-server/administrative_contact.yaml +620 -0
- data/data/matrix-spec/api/client-server/appservice_ping.yaml +183 -0
- data/data/matrix-spec/api/client-server/appservice_room_directory.yaml +104 -0
- data/data/matrix-spec/api/client-server/authed-content-repo.yaml +590 -0
- data/data/matrix-spec/api/client-server/banning.yaml +177 -0
- data/data/matrix-spec/api/client-server/capabilities.yaml +235 -0
- data/data/matrix-spec/api/client-server/content-repo.yaml +887 -0
- data/data/matrix-spec/api/client-server/create_room.yaml +306 -0
- data/data/matrix-spec/api/client-server/cross_signing.yaml +300 -0
- data/data/matrix-spec/api/client-server/definitions/auth_data.yaml +34 -0
- data/data/matrix-spec/api/client-server/definitions/auth_response.yaml +62 -0
- data/data/matrix-spec/api/client-server/definitions/client_device.yaml +44 -0
- data/data/matrix-spec/api/client-server/definitions/client_event.yaml +49 -0
- data/data/matrix-spec/api/client-server/definitions/client_event_without_room_id.yaml +147 -0
- data/data/matrix-spec/api/client-server/definitions/cross_signing_key.yaml +57 -0
- data/data/matrix-spec/api/client-server/definitions/device_keys.yaml +70 -0
- data/data/matrix-spec/api/client-server/definitions/errors/error.yaml +26 -0
- data/data/matrix-spec/api/client-server/definitions/errors/rate_limited.yaml +34 -0
- data/data/matrix-spec/api/client-server/definitions/event_batch.yaml +22 -0
- data/data/matrix-spec/api/client-server/definitions/event_filter.yaml +55 -0
- data/data/matrix-spec/api/client-server/definitions/invite_3pid.yaml +45 -0
- data/data/matrix-spec/api/client-server/definitions/key_backup_auth_data.yaml +36 -0
- data/data/matrix-spec/api/client-server/definitions/key_backup_data.yaml +50 -0
- data/data/matrix-spec/api/client-server/definitions/key_backup_session_data.yaml +57 -0
- data/data/matrix-spec/api/client-server/definitions/m.login.terms_params.yaml +83 -0
- data/data/matrix-spec/api/client-server/definitions/m.mentions.yaml +33 -0
- data/data/matrix-spec/api/client-server/definitions/m.oauth_params.yaml +30 -0
- data/data/matrix-spec/api/client-server/definitions/m.relates_to.yaml +45 -0
- data/data/matrix-spec/api/client-server/definitions/megolm_export_session_data.yaml +39 -0
- data/data/matrix-spec/api/client-server/definitions/olm_payload.yaml +88 -0
- data/data/matrix-spec/api/client-server/definitions/one_time_keys.yaml +27 -0
- data/data/matrix-spec/api/client-server/definitions/openid_token.yaml +37 -0
- data/data/matrix-spec/api/client-server/definitions/protocol.yaml +44 -0
- data/data/matrix-spec/api/client-server/definitions/public_rooms_chunk.yaml +74 -0
- data/data/matrix-spec/api/client-server/definitions/public_rooms_response.yaml +59 -0
- data/data/matrix-spec/api/client-server/definitions/push_condition.yaml +53 -0
- data/data/matrix-spec/api/client-server/definitions/push_rule.yaml +53 -0
- data/data/matrix-spec/api/client-server/definitions/push_ruleset.yaml +206 -0
- data/data/matrix-spec/api/client-server/definitions/recent_emoji.yaml +29 -0
- data/data/matrix-spec/api/client-server/definitions/request_email_validation.yaml +36 -0
- data/data/matrix-spec/api/client-server/definitions/request_msisdn_validation.yaml +36 -0
- data/data/matrix-spec/api/client-server/definitions/request_token_response.yaml +46 -0
- data/data/matrix-spec/api/client-server/definitions/room_event_filter.yaml +60 -0
- data/data/matrix-spec/api/client-server/definitions/room_key_backup.yaml +37 -0
- data/data/matrix-spec/api/client-server/definitions/room_summary.yaml +44 -0
- data/data/matrix-spec/api/client-server/definitions/security.yaml +47 -0
- data/data/matrix-spec/api/client-server/definitions/sso_login_flow.yaml +98 -0
- data/data/matrix-spec/api/client-server/definitions/state_event_batch.yaml +21 -0
- data/data/matrix-spec/api/client-server/definitions/sync_filter.yaml +86 -0
- data/data/matrix-spec/api/client-server/definitions/tag.yaml +24 -0
- data/data/matrix-spec/api/client-server/definitions/third_party_signed.yaml +45 -0
- data/data/matrix-spec/api/client-server/definitions/timeline_batch.yaml +36 -0
- data/data/matrix-spec/api/client-server/definitions/user_identifier.yaml +27 -0
- data/data/matrix-spec/api/client-server/definitions/wellknown/full.yaml +38 -0
- data/data/matrix-spec/api/client-server/definitions/wellknown/homeserver.yaml +25 -0
- data/data/matrix-spec/api/client-server/definitions/wellknown/identity_server.yaml +25 -0
- data/data/matrix-spec/api/client-server/device_management.yaml +314 -0
- data/data/matrix-spec/api/client-server/directory.yaml +318 -0
- data/data/matrix-spec/api/client-server/event_context.yaml +161 -0
- data/data/matrix-spec/api/client-server/filter.yaml +224 -0
- data/data/matrix-spec/api/client-server/inviting.yaml +149 -0
- data/data/matrix-spec/api/client-server/joining.yaml +238 -0
- data/data/matrix-spec/api/client-server/key_backup.yaml +993 -0
- data/data/matrix-spec/api/client-server/keys.yaml +482 -0
- data/data/matrix-spec/api/client-server/kicking.yaml +110 -0
- data/data/matrix-spec/api/client-server/knocking.yaml +152 -0
- data/data/matrix-spec/api/client-server/leaving.yaml +163 -0
- data/data/matrix-spec/api/client-server/list_joined_rooms.yaml +68 -0
- data/data/matrix-spec/api/client-server/list_public_rooms.yaml +280 -0
- data/data/matrix-spec/api/client-server/login.yaml +321 -0
- data/data/matrix-spec/api/client-server/login_token.yaml +138 -0
- data/data/matrix-spec/api/client-server/logout.yaml +86 -0
- data/data/matrix-spec/api/client-server/message_pagination.yaml +194 -0
- data/data/matrix-spec/api/client-server/notifications.yaml +152 -0
- data/data/matrix-spec/api/client-server/oauth_server_metadata.yaml +238 -0
- data/data/matrix-spec/api/client-server/old_sync.yaml +379 -0
- data/data/matrix-spec/api/client-server/openid.yaml +98 -0
- data/data/matrix-spec/api/client-server/password_management.yaml +246 -0
- data/data/matrix-spec/api/client-server/peeking_events.yaml +122 -0
- data/data/matrix-spec/api/client-server/policy_server.yaml +82 -0
- data/data/matrix-spec/api/client-server/presence.yaml +169 -0
- data/data/matrix-spec/api/client-server/profile.yaml +366 -0
- data/data/matrix-spec/api/client-server/pusher.yaml +303 -0
- data/data/matrix-spec/api/client-server/pushrules.yaml +633 -0
- data/data/matrix-spec/api/client-server/read_markers.yaml +103 -0
- data/data/matrix-spec/api/client-server/receipts.yaml +139 -0
- data/data/matrix-spec/api/client-server/redaction.yaml +116 -0
- data/data/matrix-spec/api/client-server/refresh.yaml +119 -0
- data/data/matrix-spec/api/client-server/registration.yaml +488 -0
- data/data/matrix-spec/api/client-server/registration_tokens.yaml +93 -0
- data/data/matrix-spec/api/client-server/relations.yaml +382 -0
- data/data/matrix-spec/api/client-server/report_content.yaml +283 -0
- data/data/matrix-spec/api/client-server/room_event_by_timestamp.yaml +147 -0
- data/data/matrix-spec/api/client-server/room_initial_sync.yaml +188 -0
- data/data/matrix-spec/api/client-server/room_send.yaml +130 -0
- data/data/matrix-spec/api/client-server/room_state.yaml +159 -0
- data/data/matrix-spec/api/client-server/room_summary.yaml +138 -0
- data/data/matrix-spec/api/client-server/room_upgrades.yaml +130 -0
- data/data/matrix-spec/api/client-server/rooms.yaml +380 -0
- data/data/matrix-spec/api/client-server/search.yaml +385 -0
- data/data/matrix-spec/api/client-server/space_hierarchy.yaml +237 -0
- data/data/matrix-spec/api/client-server/sso_login_redirect.yaml +135 -0
- data/data/matrix-spec/api/client-server/support.yaml +142 -0
- data/data/matrix-spec/api/client-server/sync.yaml +692 -0
- data/data/matrix-spec/api/client-server/tags.yaml +183 -0
- data/data/matrix-spec/api/client-server/third_party_lookup.yaml +324 -0
- data/data/matrix-spec/api/client-server/third_party_membership.yaml +139 -0
- data/data/matrix-spec/api/client-server/threads_list.yaml +167 -0
- data/data/matrix-spec/api/client-server/to_device.yaml +104 -0
- data/data/matrix-spec/api/client-server/typing.yaml +103 -0
- data/data/matrix-spec/api/client-server/users.yaml +136 -0
- data/data/matrix-spec/api/client-server/versions.yaml +108 -0
- data/data/matrix-spec/api/client-server/voip.yaml +93 -0
- data/data/matrix-spec/api/client-server/wellknown.yaml +60 -0
- data/data/matrix-spec/api/client-server/whoami.yaml +121 -0
- data/data/matrix-spec/event-schemas/examples/core/event.json +6 -0
- data/data/matrix-spec/event-schemas/examples/core/room_edu.json +3 -0
- data/data/matrix-spec/event-schemas/examples/core/room_event.json +11 -0
- data/data/matrix-spec/event-schemas/examples/core/state_event.json +4 -0
- data/data/matrix-spec/event-schemas/examples/invite_room_state.json +18 -0
- data/data/matrix-spec/event-schemas/examples/knock_room_state.json +18 -0
- data/data/matrix-spec/event-schemas/examples/m.accepted_terms.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.call.answer.yaml +21 -0
- data/data/matrix-spec/event-schemas/examples/m.call.candidates.yaml +16 -0
- data/data/matrix-spec/event-schemas/examples/m.call.hangup.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.call.invite.yaml +22 -0
- data/data/matrix-spec/event-schemas/examples/m.call.negotiate.yaml +22 -0
- data/data/matrix-spec/event-schemas/examples/m.call.reject.yaml +9 -0
- data/data/matrix-spec/event-schemas/examples/m.call.sdp_stream_metadata_changed.yaml +16 -0
- data/data/matrix-spec/event-schemas/examples/m.call.select_answer.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.direct.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.dummy.yaml +4 -0
- data/data/matrix-spec/event-schemas/examples/m.forwarded_room_key.yaml +14 -0
- data/data/matrix-spec/event-schemas/examples/m.fully_read.yaml +7 -0
- data/data/matrix-spec/event-schemas/examples/m.identity_server.yaml +7 -0
- data/data/matrix-spec/event-schemas/examples/m.ignored_user_list.yaml +9 -0
- data/data/matrix-spec/event-schemas/examples/m.invite_permission_config.yaml +7 -0
- data/data/matrix-spec/event-schemas/examples/m.key.verification.accept.yaml +12 -0
- data/data/matrix-spec/event-schemas/examples/m.key.verification.cancel.yaml +8 -0
- data/data/matrix-spec/event-schemas/examples/m.key.verification.done.yaml +6 -0
- data/data/matrix-spec/event-schemas/examples/m.key.verification.key.yaml +7 -0
- data/data/matrix-spec/event-schemas/examples/m.key.verification.mac.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.key.verification.ready.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.key.verification.request.yaml +11 -0
- data/data/matrix-spec/event-schemas/examples/m.key.verification.start$m.sas.v1.yaml +12 -0
- data/data/matrix-spec/event-schemas/examples/m.key.verification.start.yaml +8 -0
- data/data/matrix-spec/event-schemas/examples/m.key_backup.yaml +7 -0
- data/data/matrix-spec/event-schemas/examples/m.marked_unread.yaml +7 -0
- data/data/matrix-spec/event-schemas/examples/m.policy.rule.room.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.policy.rule.server.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.policy.rule.user.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.presence.yaml +12 -0
- data/data/matrix-spec/event-schemas/examples/m.push_rules.yaml +177 -0
- data/data/matrix-spec/event-schemas/examples/m.reaction.yaml +11 -0
- data/data/matrix-spec/event-schemas/examples/m.receipt.yaml +18 -0
- data/data/matrix-spec/event-schemas/examples/m.recent_emoji.yaml +16 -0
- data/data/matrix-spec/event-schemas/examples/m.room.avatar.yaml +14 -0
- data/data/matrix-spec/event-schemas/examples/m.room.canonical_alias.yaml +12 -0
- data/data/matrix-spec/event-schemas/examples/m.room.create.yaml +13 -0
- data/data/matrix-spec/event-schemas/examples/m.room.encrypted$megolm.yaml +11 -0
- data/data/matrix-spec/event-schemas/examples/m.room.encrypted$olm.yaml +14 -0
- data/data/matrix-spec/event-schemas/examples/m.room.encryption.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.room.guest_access.yaml +8 -0
- data/data/matrix-spec/event-schemas/examples/m.room.history_visibility.yaml +8 -0
- data/data/matrix-spec/event-schemas/examples/m.room.join_rules$restricted.yaml +18 -0
- data/data/matrix-spec/event-schemas/examples/m.room.join_rules.yaml +8 -0
- data/data/matrix-spec/event-schemas/examples/m.room.member$invite_room_state.yaml +15 -0
- data/data/matrix-spec/event-schemas/examples/m.room.member$join_authorised_via_users_server.yaml +12 -0
- data/data/matrix-spec/event-schemas/examples/m.room.member$knock_room_state.yaml +15 -0
- data/data/matrix-spec/event-schemas/examples/m.room.member$third_party_invite.yaml +20 -0
- data/data/matrix-spec/event-schemas/examples/m.room.member.yaml +12 -0
- data/data/matrix-spec/event-schemas/examples/m.room.message$m.audio.yaml +14 -0
- data/data/matrix-spec/event-schemas/examples/m.room.message$m.emote.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.room.message$m.file.yaml +14 -0
- data/data/matrix-spec/event-schemas/examples/m.room.message$m.image.yaml +16 -0
- data/data/matrix-spec/event-schemas/examples/m.room.message$m.key.verification.request.yaml +19 -0
- data/data/matrix-spec/event-schemas/examples/m.room.message$m.location.yaml +18 -0
- data/data/matrix-spec/event-schemas/examples/m.room.message$m.notice.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.room.message$m.server_notice.yaml +11 -0
- data/data/matrix-spec/event-schemas/examples/m.room.message$m.text.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.room.message$m.video.yaml +23 -0
- data/data/matrix-spec/event-schemas/examples/m.room.name.yaml +8 -0
- data/data/matrix-spec/event-schemas/examples/m.room.pinned_events.yaml +8 -0
- data/data/matrix-spec/event-schemas/examples/m.room.policy.yaml +11 -0
- data/data/matrix-spec/event-schemas/examples/m.room.power_levels.yaml +24 -0
- data/data/matrix-spec/event-schemas/examples/m.room.redaction.yaml +8 -0
- data/data/matrix-spec/event-schemas/examples/m.room.server_acl.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.room.third_party_invite.yaml +14 -0
- data/data/matrix-spec/event-schemas/examples/m.room.tombstone.yaml +9 -0
- data/data/matrix-spec/event-schemas/examples/m.room.topic.yaml +16 -0
- data/data/matrix-spec/event-schemas/examples/m.room_key.withheld.yaml +12 -0
- data/data/matrix-spec/event-schemas/examples/m.room_key.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.room_key_request$cancel_request.yaml +8 -0
- data/data/matrix-spec/event-schemas/examples/m.room_key_request$request.yaml +14 -0
- data/data/matrix-spec/event-schemas/examples/m.secret.request.yaml +9 -0
- data/data/matrix-spec/event-schemas/examples/m.secret.send.yaml +7 -0
- data/data/matrix-spec/event-schemas/examples/m.space.child.yaml +10 -0
- data/data/matrix-spec/event-schemas/examples/m.space.parent.yaml +9 -0
- data/data/matrix-spec/event-schemas/examples/m.sticker.yaml +22 -0
- data/data/matrix-spec/event-schemas/examples/m.tag.yaml +9 -0
- data/data/matrix-spec/event-schemas/examples/m.typing.yaml +7 -0
- data/data/matrix-spec/event-schemas/moderation_policy_rule.yaml +32 -0
- data/data/matrix-spec/event-schemas/schema/components/m_text_content_block.yaml +28 -0
- data/data/matrix-spec/event-schemas/schema/components/sdp_stream_metadata.yaml +43 -0
- data/data/matrix-spec/event-schemas/schema/components/signed_third_party_invite.yaml +48 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/call_event.yaml +27 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/event.yaml +16 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/msgtype_infos/avatar_info.yaml +30 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/msgtype_infos/image_info.yaml +52 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/msgtype_infos/thumbnail_info.yaml +22 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/room_event.yaml +17 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/state_event.yaml +8 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/stripped_state.yaml +48 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/sync_room_event.yaml +49 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/sync_state_event.yaml +36 -0
- data/data/matrix-spec/event-schemas/schema/core-event-schema/unsigned_prop.yaml +23 -0
- data/data/matrix-spec/event-schemas/schema/m.accepted_terms.yaml +25 -0
- data/data/matrix-spec/event-schemas/schema/m.call.answer.yaml +44 -0
- data/data/matrix-spec/event-schemas/schema/m.call.candidates.yaml +52 -0
- data/data/matrix-spec/event-schemas/schema/m.call.hangup.yaml +57 -0
- data/data/matrix-spec/event-schemas/schema/m.call.invite.yaml +53 -0
- data/data/matrix-spec/event-schemas/schema/m.call.negotiate.yaml +78 -0
- data/data/matrix-spec/event-schemas/schema/m.call.reject.yaml +29 -0
- data/data/matrix-spec/event-schemas/schema/m.call.sdp_stream_metadata_changed.yaml +24 -0
- data/data/matrix-spec/event-schemas/schema/m.call.select_answer.yaml +29 -0
- data/data/matrix-spec/event-schemas/schema/m.direct.yaml +29 -0
- data/data/matrix-spec/event-schemas/schema/m.dummy.yaml +25 -0
- data/data/matrix-spec/event-schemas/schema/m.forwarded_room_key.yaml +70 -0
- data/data/matrix-spec/event-schemas/schema/m.fully_read.yaml +26 -0
- data/data/matrix-spec/event-schemas/schema/m.identity_server.yaml +28 -0
- data/data/matrix-spec/event-schemas/schema/m.ignored_user_list.yaml +30 -0
- data/data/matrix-spec/event-schemas/schema/m.invite_permission_config.yaml +21 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.accept.yaml +63 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.cancel.yaml +72 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.done.yaml +24 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.key.yaml +31 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.m.relates_to.yaml +23 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.mac.yaml +43 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.ready.yaml +41 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.request.yaml +47 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.start$m.reciprocate.v1.yaml +45 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.start$m.sas.v1.yaml +76 -0
- data/data/matrix-spec/event-schemas/schema/m.key.verification.start.yaml +46 -0
- data/data/matrix-spec/event-schemas/schema/m.key_backup.yaml +24 -0
- data/data/matrix-spec/event-schemas/schema/m.marked_unread.yaml +26 -0
- data/data/matrix-spec/event-schemas/schema/m.policy.rule.room.yaml +17 -0
- data/data/matrix-spec/event-schemas/schema/m.policy.rule.server.yaml +17 -0
- data/data/matrix-spec/event-schemas/schema/m.policy.rule.user.yaml +17 -0
- data/data/matrix-spec/event-schemas/schema/m.presence.yaml +50 -0
- data/data/matrix-spec/event-schemas/schema/m.push_rules.yaml +23 -0
- data/data/matrix-spec/event-schemas/schema/m.reaction.yaml +45 -0
- data/data/matrix-spec/event-schemas/schema/m.receipt.yaml +65 -0
- data/data/matrix-spec/event-schemas/schema/m.recent_emoji.yaml +29 -0
- data/data/matrix-spec/event-schemas/schema/m.room.avatar.yaml +29 -0
- data/data/matrix-spec/event-schemas/schema/m.room.canonical_alias.yaml +40 -0
- data/data/matrix-spec/event-schemas/schema/m.room.create.yaml +86 -0
- data/data/matrix-spec/event-schemas/schema/m.room.encrypted.yaml +91 -0
- data/data/matrix-spec/event-schemas/schema/m.room.encryption.yaml +38 -0
- data/data/matrix-spec/event-schemas/schema/m.room.guest_access.yaml +28 -0
- data/data/matrix-spec/event-schemas/schema/m.room.history_visibility.yaml +30 -0
- data/data/matrix-spec/event-schemas/schema/m.room.join_rules.yaml +78 -0
- data/data/matrix-spec/event-schemas/schema/m.room.member.yaml +174 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message$m.audio.yaml +73 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message$m.emote.yaml +36 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message$m.file.yaml +85 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message$m.image.yaml +63 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message$m.key.verification.request.yaml +70 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message$m.location.yaml +50 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message$m.notice.yaml +36 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message$m.server_notice.yaml +41 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message$m.text.yaml +36 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message$m.video.yaml +95 -0
- data/data/matrix-spec/event-schemas/schema/m.room.message.yaml +25 -0
- data/data/matrix-spec/event-schemas/schema/m.room.name.yaml +35 -0
- data/data/matrix-spec/event-schemas/schema/m.room.pinned_events.yaml +27 -0
- data/data/matrix-spec/event-schemas/schema/m.room.policy.yaml +41 -0
- data/data/matrix-spec/event-schemas/schema/m.room.power_levels.yaml +139 -0
- data/data/matrix-spec/event-schemas/schema/m.room.redaction.yaml +29 -0
- data/data/matrix-spec/event-schemas/schema/m.room.server_acl.yaml +88 -0
- data/data/matrix-spec/event-schemas/schema/m.room.third_party_invite.yaml +79 -0
- data/data/matrix-spec/event-schemas/schema/m.room.tombstone.yaml +29 -0
- data/data/matrix-spec/event-schemas/schema/m.room.topic.yaml +53 -0
- data/data/matrix-spec/event-schemas/schema/m.room_key.withheld.yaml +88 -0
- data/data/matrix-spec/event-schemas/schema/m.room_key.yaml +38 -0
- data/data/matrix-spec/event-schemas/schema/m.room_key_request.yaml +73 -0
- data/data/matrix-spec/event-schemas/schema/m.secret.request.yaml +42 -0
- data/data/matrix-spec/event-schemas/schema/m.secret.send.yaml +35 -0
- data/data/matrix-spec/event-schemas/schema/m.space.child.yaml +50 -0
- data/data/matrix-spec/event-schemas/schema/m.space.parent.yaml +36 -0
- data/data/matrix-spec/event-schemas/schema/m.sticker.yaml +36 -0
- data/data/matrix-spec/event-schemas/schema/m.tag.yaml +28 -0
- data/data/matrix-spec/event-schemas/schema/m.typing.yaml +29 -0
- data/lib/async/matrix/3.3/async_matrix_e2ee.so +0 -0
- data/lib/async/matrix/3.4/async_matrix_e2ee.so +0 -0
- data/lib/async/matrix/4.0/async_matrix_e2ee.so +0 -0
- data/lib/async/matrix/api/chain.rb +604 -0
- data/lib/async/matrix/api/concat.rb +107 -0
- data/lib/async/matrix/api/path_tree.rb +232 -0
- data/lib/async/matrix/api.rb +205 -0
- data/lib/async/matrix/auth_error.rb +20 -0
- data/lib/async/matrix/bad_json_error.rb +20 -0
- data/lib/async/matrix/client.rb +966 -0
- data/lib/async/matrix/config/vivify.rb +107 -0
- data/lib/async/matrix/config.rb +184 -0
- data/lib/async/matrix/connection.rb +19 -0
- data/lib/async/matrix/content.rb +106 -0
- data/lib/async/matrix/double_puppet_client.rb +82 -0
- data/lib/async/matrix/e2ee.rb +129 -0
- data/lib/async/matrix/endpoint.rb +57 -0
- data/lib/async/matrix/error.rb +40 -0
- data/lib/async/matrix/error_response.rb +37 -0
- data/lib/async/matrix/event.rb +197 -0
- data/lib/async/matrix/homeserver_error.rb +20 -0
- data/lib/async/matrix/invalid_endpoint_error.rb +20 -0
- data/lib/async/matrix/media_client.rb +181 -0
- data/lib/async/matrix/not_found_error.rb +20 -0
- data/lib/async/matrix/notifier.rb +108 -0
- data/lib/async/matrix/response_too_large_error.rb +20 -0
- data/lib/async/matrix/schema/registry.rb +381 -0
- data/lib/async/matrix/schema/validation_error.rb +232 -0
- data/lib/async/matrix/schema.rb +170 -0
- data/lib/async/matrix/server.rb +18 -0
- data/lib/async/matrix/stream.rb +18 -0
- data/lib/async/matrix/version.rb +10 -0
- data/lib/async/matrix.rb +15 -0
- metadata +494 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the Apache License, Version 2.0.
|
|
4
|
+
# Copyright, 2026, by General Intelligence Systems.
|
|
5
|
+
|
|
6
|
+
module Async
|
|
7
|
+
module Matrix
|
|
8
|
+
class Error < StandardError
|
|
9
|
+
attr_reader :errcode, :status
|
|
10
|
+
|
|
11
|
+
def initialize(errcode, message, status: nil)
|
|
12
|
+
@errcode = errcode
|
|
13
|
+
@status = status
|
|
14
|
+
super(message)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
__END__
|
|
21
|
+
describe "Async::Matrix::Error" do
|
|
22
|
+
it "stores errcode and message" do
|
|
23
|
+
err = Async::Matrix::Error.new("M_UNKNOWN", "something broke")
|
|
24
|
+
err.errcode.should == "M_UNKNOWN"
|
|
25
|
+
err.message.should == "something broke"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "stores optional status" do
|
|
29
|
+
err = Async::Matrix::Error.new("M_UNKNOWN", "bad", status: 400)
|
|
30
|
+
err.status.should == 400
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "defaults status to nil" do
|
|
34
|
+
Async::Matrix::Error.new("M_UNKNOWN", "bad").status.should.be.nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "is a StandardError" do
|
|
38
|
+
Async::Matrix::Error.new("M_UNKNOWN", "bad").should.be.kind_of StandardError
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the Apache License, Version 2.0.
|
|
4
|
+
# Copyright, 2026, by General Intelligence Systems.
|
|
5
|
+
|
|
6
|
+
module Async
|
|
7
|
+
module Matrix
|
|
8
|
+
# A Matrix standard error response body: `{"errcode": ..., "error": ...}`.
|
|
9
|
+
# Both {Client} and {MediaClient} parse failed responses into one of these.
|
|
10
|
+
class ErrorResponse
|
|
11
|
+
attr_reader :errcode, :error
|
|
12
|
+
|
|
13
|
+
def initialize(data)
|
|
14
|
+
@errcode = data["errcode"]
|
|
15
|
+
@error = data["error"]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
__END__
|
|
22
|
+
describe "Async::Matrix::ErrorResponse" do
|
|
23
|
+
it "parses errcode and error" do
|
|
24
|
+
resp = Async::Matrix::ErrorResponse.new({
|
|
25
|
+
"errcode" => "M_FORBIDDEN",
|
|
26
|
+
"error" => "Access denied"
|
|
27
|
+
})
|
|
28
|
+
resp.errcode.should == "M_FORBIDDEN"
|
|
29
|
+
resp.error.should == "Access denied"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "handles missing fields" do
|
|
33
|
+
resp = Async::Matrix::ErrorResponse.new({})
|
|
34
|
+
resp.errcode.should.be.nil
|
|
35
|
+
resp.error.should.be.nil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the Apache License, Version 2.0.
|
|
4
|
+
# Copyright, 2026, by General Intelligence Systems.
|
|
5
|
+
|
|
6
|
+
module Async
|
|
7
|
+
module Matrix
|
|
8
|
+
# Represents a Matrix event, however it arrived — a /sync response, an
|
|
9
|
+
# application service transaction, or a hash you built yourself.
|
|
10
|
+
#
|
|
11
|
+
# Provides typed accessors for all envelope fields plus schema-driven
|
|
12
|
+
# validation using the official Matrix spec YAML schemas.
|
|
13
|
+
#
|
|
14
|
+
# event = Event.new(raw_hash)
|
|
15
|
+
# event.type # => "m.room.message"
|
|
16
|
+
# event.sender # => "@alice:example.org"
|
|
17
|
+
# event.content.body # => "hello"
|
|
18
|
+
# event.valid? # => true
|
|
19
|
+
# event.valid! # => true (or raises Schema::ValidationError)
|
|
20
|
+
#
|
|
21
|
+
class Event
|
|
22
|
+
attr_reader :type,
|
|
23
|
+
:sender,
|
|
24
|
+
:room_id,
|
|
25
|
+
:state_key,
|
|
26
|
+
:content,
|
|
27
|
+
:event_id,
|
|
28
|
+
:origin_server_ts,
|
|
29
|
+
:unsigned,
|
|
30
|
+
:raw
|
|
31
|
+
|
|
32
|
+
def initialize(data)
|
|
33
|
+
@raw = data
|
|
34
|
+
@type = data["type"]
|
|
35
|
+
@sender = data["sender"]
|
|
36
|
+
@room_id = data["room_id"]
|
|
37
|
+
@state_key = data["state_key"]
|
|
38
|
+
@event_id = data["event_id"]
|
|
39
|
+
@origin_server_ts = data["origin_server_ts"]
|
|
40
|
+
@unsigned = data["unsigned"]
|
|
41
|
+
@content = Content.new(data["content"] || {})
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# The JSONSchemer::Schema for this event's type, or nil if unknown.
|
|
45
|
+
def schema = Schema[@type]
|
|
46
|
+
|
|
47
|
+
# Validate this event against its schema.
|
|
48
|
+
# Returns true if valid or if no schema exists (lenient).
|
|
49
|
+
def valid? = Schema.valid?(@raw)
|
|
50
|
+
|
|
51
|
+
# Validate this event against its schema.
|
|
52
|
+
# Raises Schema::ValidationError with detailed errors on failure.
|
|
53
|
+
# Returns true if valid or if no schema exists.
|
|
54
|
+
def valid!
|
|
55
|
+
errors = Schema.validate(@raw)
|
|
56
|
+
|
|
57
|
+
unless errors.empty?
|
|
58
|
+
raise Schema::ValidationError.new(
|
|
59
|
+
errors,
|
|
60
|
+
event_type: @type,
|
|
61
|
+
event_id: @event_id,
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Content property names defined by the schema for this event type.
|
|
69
|
+
# @return [Array<String>]
|
|
70
|
+
def content_properties = Schema.content_properties(@type)
|
|
71
|
+
|
|
72
|
+
# Is this a state event? (has a state_key)
|
|
73
|
+
def state_event? = !@state_key.nil?
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
__END__
|
|
79
|
+
describe "Async::Matrix::Event" do
|
|
80
|
+
it "parses all event fields" do
|
|
81
|
+
event = Async::Matrix::Event.new({
|
|
82
|
+
"type" => "m.room.message",
|
|
83
|
+
"sender" => "@alice:example.com",
|
|
84
|
+
"room_id" => "!abc:example.com",
|
|
85
|
+
"state_key" => "",
|
|
86
|
+
"event_id" => "$evt1",
|
|
87
|
+
"origin_server_ts" => 1234567890,
|
|
88
|
+
"unsigned" => {"age" => 1000},
|
|
89
|
+
"content" => {"msgtype" => "m.text", "body" => "hi"}
|
|
90
|
+
})
|
|
91
|
+
event.type.should == "m.room.message"
|
|
92
|
+
event.sender.should == "@alice:example.com"
|
|
93
|
+
event.room_id.should == "!abc:example.com"
|
|
94
|
+
event.state_key.should == ""
|
|
95
|
+
event.event_id.should == "$evt1"
|
|
96
|
+
event.origin_server_ts.should == 1234567890
|
|
97
|
+
event.unsigned.should == {"age" => 1000}
|
|
98
|
+
event.content.should.be.kind_of Async::Matrix::Content
|
|
99
|
+
event.content.body.should == "hi"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "defaults content to empty Content when missing" do
|
|
103
|
+
event = Async::Matrix::Event.new({"type" => "m.room.message"})
|
|
104
|
+
event.content.should.be.kind_of Async::Matrix::Content
|
|
105
|
+
event.content.body.should.be.nil
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "exposes the raw hash" do
|
|
109
|
+
data = {"type" => "m.room.message", "content" => {"body" => "hi", "msgtype" => "m.text"}}
|
|
110
|
+
event = Async::Matrix::Event.new(data)
|
|
111
|
+
event.raw.should.equal data
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "detects state events" do
|
|
115
|
+
state = Async::Matrix::Event.new({"type" => "m.room.member", "state_key" => "@a:b"})
|
|
116
|
+
state.state_event?.should == true
|
|
117
|
+
|
|
118
|
+
msg = Async::Matrix::Event.new({"type" => "m.room.message"})
|
|
119
|
+
msg.state_event?.should == false
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "returns the schema for known event types" do
|
|
123
|
+
event = Async::Matrix::Event.new({"type" => "m.room.message", "content" => {}})
|
|
124
|
+
event.schema.should.not.be.nil
|
|
125
|
+
event.schema.should.be.kind_of JSONSchemer::Schema
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "returns nil schema for unknown event types" do
|
|
129
|
+
event = Async::Matrix::Event.new({"type" => "m.custom.event", "content" => {}})
|
|
130
|
+
event.schema.should.be.nil
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "validates a correct event" do
|
|
134
|
+
event = Async::Matrix::Event.new({
|
|
135
|
+
"type" => "m.room.message",
|
|
136
|
+
"content" => {"msgtype" => "m.text", "body" => "hello"},
|
|
137
|
+
"event_id" => "$abc123",
|
|
138
|
+
"sender" => "@alice:example.org",
|
|
139
|
+
"origin_server_ts" => 1234567890,
|
|
140
|
+
"room_id" => "!room:example.org"
|
|
141
|
+
})
|
|
142
|
+
event.valid?.should == true
|
|
143
|
+
event.valid!.should == true
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "rejects an invalid event" do
|
|
147
|
+
event = Async::Matrix::Event.new({
|
|
148
|
+
"type" => "m.room.message",
|
|
149
|
+
"content" => {"msgtype" => "m.text"},
|
|
150
|
+
"event_id" => "$abc123",
|
|
151
|
+
"sender" => "@alice:example.org",
|
|
152
|
+
"origin_server_ts" => 1234567890,
|
|
153
|
+
"room_id" => "!room:example.org"
|
|
154
|
+
})
|
|
155
|
+
event.valid?.should == false
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "raises ValidationError from valid!" do
|
|
159
|
+
event = Async::Matrix::Event.new({
|
|
160
|
+
"type" => "m.room.member",
|
|
161
|
+
"content" => {"membership" => "invalid_state"},
|
|
162
|
+
"state_key" => "@alice:example.org",
|
|
163
|
+
"event_id" => "$abc123",
|
|
164
|
+
"sender" => "@alice:example.org",
|
|
165
|
+
"origin_server_ts" => 1234567890,
|
|
166
|
+
"room_id" => "!room:example.org"
|
|
167
|
+
})
|
|
168
|
+
begin
|
|
169
|
+
event.valid!
|
|
170
|
+
raise "should have raised"
|
|
171
|
+
rescue Async::Matrix::Schema::ValidationError => e
|
|
172
|
+
e.message.should.include "m.room.member"
|
|
173
|
+
e.message.should.include "$abc123"
|
|
174
|
+
e.errors.should.not.be.empty
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it "is lenient with unknown event types" do
|
|
179
|
+
event = Async::Matrix::Event.new({
|
|
180
|
+
"type" => "com.custom.event",
|
|
181
|
+
"content" => {"anything" => "goes"},
|
|
182
|
+
"event_id" => "$x",
|
|
183
|
+
"sender" => "@a:b"
|
|
184
|
+
})
|
|
185
|
+
event.valid?.should == true
|
|
186
|
+
event.valid!.should == true
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it "returns content properties for known types" do
|
|
190
|
+
event = Async::Matrix::Event.new({
|
|
191
|
+
"type" => "m.room.member",
|
|
192
|
+
"content" => {"membership" => "join"}
|
|
193
|
+
})
|
|
194
|
+
props = event.content_properties
|
|
195
|
+
props.should.include "membership"
|
|
196
|
+
end
|
|
197
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the Apache License, Version 2.0.
|
|
4
|
+
# Copyright, 2026, by General Intelligence Systems.
|
|
5
|
+
|
|
6
|
+
# Async::Matrix::Error is this class's superclass, so it has to exist before
|
|
7
|
+
# this file finishes loading — the glob in async/matrix.rb sorts
|
|
8
|
+
# alphabetically and would otherwise get here first.
|
|
9
|
+
require_relative "error"
|
|
10
|
+
|
|
11
|
+
module Async
|
|
12
|
+
module Matrix
|
|
13
|
+
class HomeserverError < Error; end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
__END__
|
|
18
|
+
it "HomeserverError inherits from Error" do
|
|
19
|
+
Async::Matrix::HomeserverError.new("M_UNKNOWN", "upstream").should.be.kind_of Async::Matrix::Error
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the Apache License, Version 2.0.
|
|
4
|
+
# Copyright, 2026, by General Intelligence Systems.
|
|
5
|
+
|
|
6
|
+
# Async::Matrix::Error is this class's superclass, so it has to exist before
|
|
7
|
+
# this file finishes loading — the glob in async/matrix.rb sorts
|
|
8
|
+
# alphabetically and would otherwise get here first.
|
|
9
|
+
require_relative "error"
|
|
10
|
+
|
|
11
|
+
module Async
|
|
12
|
+
module Matrix
|
|
13
|
+
class InvalidEndpointError < Error; end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
__END__
|
|
18
|
+
it "InvalidEndpointError inherits from Error" do
|
|
19
|
+
Async::Matrix::InvalidEndpointError.new("M_UNRECOGNIZED", "no such route").should.be.kind_of Async::Matrix::Error
|
|
20
|
+
end
|
|
@@ -0,0 +1,181 @@
|
|
|
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 "async/http/internet"
|
|
7
|
+
require "json"
|
|
8
|
+
require "console"
|
|
9
|
+
|
|
10
|
+
module Async
|
|
11
|
+
module Matrix
|
|
12
|
+
# Async HTTP client for binary Matrix media operations.
|
|
13
|
+
#
|
|
14
|
+
# Handles raw byte uploads and downloads against the Matrix content
|
|
15
|
+
# repository. Unlike the JSON-only Client, this never wraps request
|
|
16
|
+
# bodies in JSON.generate and can return raw binary response bodies.
|
|
17
|
+
#
|
|
18
|
+
# Not intended to be used directly — the Chain dispatches here
|
|
19
|
+
# automatically when the request path matches a BINARY_ROUTES entry.
|
|
20
|
+
#
|
|
21
|
+
# media_client = Async::Matrix::MediaClient.new(config)
|
|
22
|
+
# media_client.upload("POST", path, bytes, "image/png")
|
|
23
|
+
# bytes = media_client.download(path)
|
|
24
|
+
#
|
|
25
|
+
class MediaClient
|
|
26
|
+
# Upload JSON responses are small; error bodies are even smaller.
|
|
27
|
+
UPLOAD_RESPONSE_SIZE_LIMIT = 1 * 1024 * 1024 # 1 MiB
|
|
28
|
+
ERROR_RESPONSE_SIZE_LIMIT = 512 * 1024 # 512 KiB
|
|
29
|
+
|
|
30
|
+
def initialize(config)
|
|
31
|
+
@config = config
|
|
32
|
+
@base = config.homeserver.address
|
|
33
|
+
@auth_headers = [
|
|
34
|
+
["authorization", "Bearer #{config.appservice.as_token}"],
|
|
35
|
+
["user-agent", "AsyncMatrix/#{Async::Matrix::VERSION}"]
|
|
36
|
+
]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Upload raw bytes to the content repository.
|
|
40
|
+
#
|
|
41
|
+
# @param method [String] HTTP method ("POST" or "PUT")
|
|
42
|
+
# @param path [String] URL path (already URL-encoded)
|
|
43
|
+
# @param body [String] raw bytes to upload
|
|
44
|
+
# @param content_type [String] MIME type of the body
|
|
45
|
+
# @return [Hash] parsed JSON response (e.g. {"content_uri" => "mxc://..."})
|
|
46
|
+
def upload(method, path, body, content_type = "application/octet-stream")
|
|
47
|
+
url = "#{@base}#{path}"
|
|
48
|
+
headers = @auth_headers + [["content-type", content_type]]
|
|
49
|
+
|
|
50
|
+
Console.debug(self) { "UPLOAD #{method} #{path} (#{content_type}, #{body.bytesize} bytes)" }
|
|
51
|
+
|
|
52
|
+
response = internet.call(
|
|
53
|
+
method,
|
|
54
|
+
url,
|
|
55
|
+
headers,
|
|
56
|
+
body,
|
|
57
|
+
)
|
|
58
|
+
status = response.status
|
|
59
|
+
|
|
60
|
+
unless (200..299).cover?(status)
|
|
61
|
+
payload = read_limited(response, ERROR_RESPONSE_SIZE_LIMIT)
|
|
62
|
+
parsed = ErrorResponse.new(
|
|
63
|
+
begin; JSON.parse(payload); rescue; {} end,
|
|
64
|
+
)
|
|
65
|
+
Console.error(self) { "Matrix media upload #{status}: #{parsed.errcode} — #{parsed.error}" }
|
|
66
|
+
raise HomeserverError.new(
|
|
67
|
+
parsed.errcode || "UNKNOWN",
|
|
68
|
+
parsed.error || payload.to_s[0..200],
|
|
69
|
+
status: status,
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
payload = read_limited(response, UPLOAD_RESPONSE_SIZE_LIMIT)
|
|
74
|
+
payload && !payload.empty? ? JSON.parse(payload) : {}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Download from the content repository.
|
|
78
|
+
#
|
|
79
|
+
# Returns the raw HTTP response object so the caller has access to
|
|
80
|
+
# both the body and response metadata:
|
|
81
|
+
#
|
|
82
|
+
# response = media_client.download(path)
|
|
83
|
+
# response.read # raw bytes (String, Encoding::BINARY)
|
|
84
|
+
# response.headers["content-type"] # "image/png"
|
|
85
|
+
# response.headers["content-disposition"] # "inline; filename=\"photo.jpg\""
|
|
86
|
+
# response.body.each { |chunk| ... } # streaming
|
|
87
|
+
#
|
|
88
|
+
# @param path [String] URL path (already URL-encoded, may include query string)
|
|
89
|
+
# @return [Protocol::HTTP::Response] the HTTP response
|
|
90
|
+
def download(path)
|
|
91
|
+
url = "#{@base}#{path}"
|
|
92
|
+
|
|
93
|
+
Console.debug(self) { "DOWNLOAD #{path}" }
|
|
94
|
+
|
|
95
|
+
response = internet.call(
|
|
96
|
+
"GET",
|
|
97
|
+
url,
|
|
98
|
+
@auth_headers,
|
|
99
|
+
nil,
|
|
100
|
+
)
|
|
101
|
+
status = response.status
|
|
102
|
+
|
|
103
|
+
unless (200..299).cover?(status)
|
|
104
|
+
payload = response.read
|
|
105
|
+
parsed = ErrorResponse.new(
|
|
106
|
+
begin; JSON.parse(payload); rescue; {} end,
|
|
107
|
+
)
|
|
108
|
+
Console.error(self) { "Matrix media download #{status}: #{parsed.errcode} — #{parsed.error}" }
|
|
109
|
+
raise HomeserverError.new(
|
|
110
|
+
parsed.errcode || "UNKNOWN",
|
|
111
|
+
parsed.error || payload.to_s[0..200],
|
|
112
|
+
status: status,
|
|
113
|
+
)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
response
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def close
|
|
120
|
+
@internet&.close
|
|
121
|
+
@internet = nil
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
private
|
|
125
|
+
|
|
126
|
+
def internet
|
|
127
|
+
@internet ||= Async::HTTP::Internet.new
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Read response body with a size limit. Raises ResponseTooLargeError
|
|
131
|
+
# if the body exceeds the limit.
|
|
132
|
+
def read_limited(response, limit)
|
|
133
|
+
body = response.body
|
|
134
|
+
if body
|
|
135
|
+
if body.respond_to?(:length) && body.length && body.length > limit
|
|
136
|
+
body.close
|
|
137
|
+
raise ResponseTooLargeError.new(
|
|
138
|
+
"M_TOO_LARGE",
|
|
139
|
+
"Response Content-Length #{body.length} bytes exceeds limit of #{limit} bytes",
|
|
140
|
+
)
|
|
141
|
+
end
|
|
142
|
+
buffer = String.new(encoding: Encoding::BINARY)
|
|
143
|
+
body.each do |chunk|
|
|
144
|
+
buffer << chunk
|
|
145
|
+
if buffer.bytesize > limit
|
|
146
|
+
body.close
|
|
147
|
+
raise ResponseTooLargeError.new(
|
|
148
|
+
"M_TOO_LARGE",
|
|
149
|
+
"Response body exceeds limit of #{limit} bytes",
|
|
150
|
+
)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
buffer.empty? ? nil : buffer
|
|
154
|
+
else
|
|
155
|
+
nil
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
__END__
|
|
163
|
+
describe "Async::Matrix::MediaClient" do
|
|
164
|
+
def make_config
|
|
165
|
+
Async::Matrix::Config.new({
|
|
166
|
+
"homeserver" => { "address" => "http://localhost:8008", "domain" => "localhost" },
|
|
167
|
+
"appservice" => { "as_token" => "test_token", "hs_token" => "hs_secret", "bot" => { "username" => "bot" } }
|
|
168
|
+
})
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "responds to upload and download" do
|
|
172
|
+
client = Async::Matrix::MediaClient.new(make_config)
|
|
173
|
+
client.should.respond_to :upload
|
|
174
|
+
client.should.respond_to :download
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "can be closed without error" do
|
|
178
|
+
client = Async::Matrix::MediaClient.new(make_config)
|
|
179
|
+
lambda { client.close }.should.not.raise
|
|
180
|
+
end
|
|
181
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the Apache License, Version 2.0.
|
|
4
|
+
# Copyright, 2026, by General Intelligence Systems.
|
|
5
|
+
|
|
6
|
+
# Async::Matrix::Error is this class's superclass, so it has to exist before
|
|
7
|
+
# this file finishes loading — the glob in async/matrix.rb sorts
|
|
8
|
+
# alphabetically and would otherwise get here first.
|
|
9
|
+
require_relative "error"
|
|
10
|
+
|
|
11
|
+
module Async
|
|
12
|
+
module Matrix
|
|
13
|
+
class NotFoundError < Error; end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
__END__
|
|
18
|
+
it "NotFoundError inherits from Error" do
|
|
19
|
+
Async::Matrix::NotFoundError.new("M_NOT_FOUND", "gone").should.be.kind_of Async::Matrix::Error
|
|
20
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
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 "async"
|
|
7
|
+
require "async/condition"
|
|
8
|
+
|
|
9
|
+
module Async
|
|
10
|
+
module Matrix
|
|
11
|
+
# Waitable event bus. Signal it when events arrive;
|
|
12
|
+
# /sync handlers wait on it with a timeout.
|
|
13
|
+
#
|
|
14
|
+
# notifier = Async::Matrix::Notifier.new
|
|
15
|
+
#
|
|
16
|
+
# # In a /sync handler fiber (blocks until signalled or timeout):
|
|
17
|
+
# notifier.wait(timeout: 30) { check_for_events() }
|
|
18
|
+
#
|
|
19
|
+
# # After persisting an event (wakes all waiting fibers):
|
|
20
|
+
# notifier.signal
|
|
21
|
+
#
|
|
22
|
+
class Notifier
|
|
23
|
+
def initialize
|
|
24
|
+
@condition = Async::Condition.new
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Wake all waiting fibers.
|
|
28
|
+
def signal
|
|
29
|
+
@condition.signal
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Block up to +timeout+ seconds. Yields to check for data after
|
|
33
|
+
# each wake-up; returns the block's value as soon as it is truthy.
|
|
34
|
+
# Returns the block's value (possibly nil/false) when time runs out.
|
|
35
|
+
def wait(timeout: 30, &block)
|
|
36
|
+
deadline = Time.now + timeout
|
|
37
|
+
|
|
38
|
+
loop do
|
|
39
|
+
result = yield
|
|
40
|
+
if result
|
|
41
|
+
break result
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
remaining = deadline - Time.now
|
|
45
|
+
if remaining <= 0
|
|
46
|
+
break result
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
begin
|
|
50
|
+
Async::Task.current.with_timeout(remaining) do
|
|
51
|
+
@condition.wait
|
|
52
|
+
end
|
|
53
|
+
rescue Async::TimeoutError
|
|
54
|
+
break yield
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
__END__
|
|
63
|
+
it "can be instantiated" do
|
|
64
|
+
notifier = Async::Matrix::Notifier.new
|
|
65
|
+
notifier.should.be.kind_of Async::Matrix::Notifier
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "responds to #signal" do
|
|
69
|
+
Async::Matrix::Notifier.new.should.respond_to :signal
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "responds to #wait" do
|
|
73
|
+
Async::Matrix::Notifier.new.should.respond_to :wait
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "returns truthy block value immediately without waiting" do
|
|
77
|
+
Async do
|
|
78
|
+
notifier = Async::Matrix::Notifier.new
|
|
79
|
+
result = notifier.wait(timeout: 1) { :data }
|
|
80
|
+
result.should == :data
|
|
81
|
+
end.wait
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "returns falsy block value on timeout" do
|
|
85
|
+
Async do
|
|
86
|
+
notifier = Async::Matrix::Notifier.new
|
|
87
|
+
result = notifier.wait(timeout: 0.05) { nil }
|
|
88
|
+
result.should.be.nil
|
|
89
|
+
end.wait
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "wakes waiting fibers on signal" do
|
|
93
|
+
result = nil
|
|
94
|
+
Async do |task|
|
|
95
|
+
notifier = Async::Matrix::Notifier.new
|
|
96
|
+
signalled = false
|
|
97
|
+
|
|
98
|
+
task.async do
|
|
99
|
+
result = notifier.wait(timeout: 5) { signalled }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
task.async do
|
|
103
|
+
signalled = true
|
|
104
|
+
notifier.signal
|
|
105
|
+
end
|
|
106
|
+
end.wait
|
|
107
|
+
result.should == true
|
|
108
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the Apache License, Version 2.0.
|
|
4
|
+
# Copyright, 2026, by General Intelligence Systems.
|
|
5
|
+
|
|
6
|
+
# Async::Matrix::Error is this class's superclass, so it has to exist before
|
|
7
|
+
# this file finishes loading — the glob in async/matrix.rb sorts
|
|
8
|
+
# alphabetically and would otherwise get here first.
|
|
9
|
+
require_relative "error"
|
|
10
|
+
|
|
11
|
+
module Async
|
|
12
|
+
module Matrix
|
|
13
|
+
class ResponseTooLargeError < Error; end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
__END__
|
|
18
|
+
it "ResponseTooLargeError inherits from Error" do
|
|
19
|
+
Async::Matrix::ResponseTooLargeError.new("M_TOO_LARGE", "too big").should.be.kind_of Async::Matrix::Error
|
|
20
|
+
end
|