async-matrix 2.0.1-aarch64-mingw-ucrt
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 +133 -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/discord/api/path_tree.rb +127 -0
- data/lib/async/discord/api.rb +151 -0
- data/lib/async/discord/client.rb +283 -0
- data/lib/async/discord/error.rb +84 -0
- data/lib/async/discord/gateway.rb +359 -0
- data/lib/async/discord.rb +15 -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 +578 -0
- data/lib/async/matrix/api/concat.rb +101 -0
- data/lib/async/matrix/api/path_tree.rb +205 -0
- data/lib/async/matrix/api.rb +200 -0
- data/lib/async/matrix/application_service/bot.rb +232 -0
- data/lib/async/matrix/application_service/config/schema/analytics.json +21 -0
- data/lib/async/matrix/application_service/config/schema/appservice.json +82 -0
- data/lib/async/matrix/application_service/config/schema/backfill.json +91 -0
- data/lib/async/matrix/application_service/config/schema/bridge.json +209 -0
- data/lib/async/matrix/application_service/config/schema/config.json +61 -0
- data/lib/async/matrix/application_service/config/schema/database.json +38 -0
- data/lib/async/matrix/application_service/config/schema/direct_media.json +35 -0
- data/lib/async/matrix/application_service/config/schema/double_puppet.json +24 -0
- data/lib/async/matrix/application_service/config/schema/encryption.json +164 -0
- data/lib/async/matrix/application_service/config/schema/homeserver.json +58 -0
- data/lib/async/matrix/application_service/config/schema/logging.json +50 -0
- data/lib/async/matrix/application_service/config/schema/management_room_texts.json +25 -0
- data/lib/async/matrix/application_service/config/schema/matrix.json +45 -0
- data/lib/async/matrix/application_service/config/schema/permissions.json +54 -0
- data/lib/async/matrix/application_service/config/schema/provisioning.json +23 -0
- data/lib/async/matrix/application_service/config/schema/public_media.json +39 -0
- data/lib/async/matrix/application_service/config/schema/relay.json +43 -0
- data/lib/async/matrix/application_service/config/vivify.rb +109 -0
- data/lib/async/matrix/application_service/config.rb +225 -0
- data/lib/async/matrix/application_service/dispatcher.rb +185 -0
- data/lib/async/matrix/application_service/error_response.rb +37 -0
- data/lib/async/matrix/application_service/event.rb +285 -0
- data/lib/async/matrix/application_service/server.rb +430 -0
- data/lib/async/matrix/application_service/transaction.rb +66 -0
- data/lib/async/matrix/application_service/transaction_handler.rb +185 -0
- data/lib/async/matrix/application_service/transaction_store.rb +80 -0
- data/lib/async/matrix/bridge/discord/db/connection.rb +141 -0
- data/lib/async/matrix/bridge/discord/db/file.rb +118 -0
- data/lib/async/matrix/bridge/discord/db/guild.rb +120 -0
- data/lib/async/matrix/bridge/discord/db/message.rb +160 -0
- data/lib/async/matrix/bridge/discord/db/migrations/001_create_users.rb +14 -0
- data/lib/async/matrix/bridge/discord/db/migrations/002_create_guilds.rb +14 -0
- data/lib/async/matrix/bridge/discord/db/migrations/003_create_portals.rb +23 -0
- data/lib/async/matrix/bridge/discord/db/migrations/004_create_puppets.rb +19 -0
- data/lib/async/matrix/bridge/discord/db/migrations/005_create_messages.rb +20 -0
- data/lib/async/matrix/bridge/discord/db/migrations/006_create_reactions.rb +19 -0
- data/lib/async/matrix/bridge/discord/db/migrations/007_create_files.rb +18 -0
- data/lib/async/matrix/bridge/discord/db/portal.rb +150 -0
- data/lib/async/matrix/bridge/discord/db/puppet.rb +128 -0
- data/lib/async/matrix/bridge/discord/db/reaction.rb +165 -0
- data/lib/async/matrix/bridge/discord/db/schema.rb +18 -0
- data/lib/async/matrix/bridge/discord/db/user.rb +112 -0
- data/lib/async/matrix/bridge/discord/db.rb +138 -0
- data/lib/async/matrix/client.rb +934 -0
- data/lib/async/matrix/connection.rb +19 -0
- data/lib/async/matrix/double_puppet_client.rb +82 -0
- data/lib/async/matrix/e2ee.rb +92 -0
- data/lib/async/matrix/endpoint.rb +57 -0
- data/lib/async/matrix/error.rb +67 -0
- data/lib/async/matrix/media_client.rb +170 -0
- data/lib/async/matrix/notifier.rb +104 -0
- data/lib/async/matrix/schema/registry.rb +354 -0
- data/lib/async/matrix/schema/validation_error.rb +225 -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 +22 -0
- metadata +587 -0
|
@@ -0,0 +1,19 @@
|
|
|
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"
|
|
7
|
+
|
|
8
|
+
module Async
|
|
9
|
+
module Matrix
|
|
10
|
+
module Connection
|
|
11
|
+
include Async::HTTP::Protocol::HTTP2::Connection
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
__END__
|
|
17
|
+
it "includes Async::HTTP::Protocol::HTTP2::Connection" do
|
|
18
|
+
Async::Matrix::Connection.ancestors.should.include Async::HTTP::Protocol::HTTP2::Connection
|
|
19
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
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_relative "client"
|
|
7
|
+
|
|
8
|
+
module Async
|
|
9
|
+
module Matrix
|
|
10
|
+
# A Client subclass that authenticates with a user's double puppet token
|
|
11
|
+
# instead of the appservice's as_token.
|
|
12
|
+
#
|
|
13
|
+
# This allows the bridge to send events as the real Matrix user rather
|
|
14
|
+
# than as the appservice bot or a ghost user.
|
|
15
|
+
#
|
|
16
|
+
# puppet = DoublePuppetClient.new(config, double_puppet_token: "syt_...")
|
|
17
|
+
# puppet.send_text("!room:example.com", "sent as the real user")
|
|
18
|
+
# puppet.whoami # => {"user_id" => "@alice:example.com"}
|
|
19
|
+
#
|
|
20
|
+
class DoublePuppetClient < Client
|
|
21
|
+
def initialize(config, double_puppet_token:, **kwargs)
|
|
22
|
+
super(config, **kwargs)
|
|
23
|
+
@headers[0] = ["authorization", "Bearer #{double_puppet_token}"]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
__END__
|
|
30
|
+
describe "Async::Matrix::DoublePuppetClient" do
|
|
31
|
+
def make_config
|
|
32
|
+
Async::Matrix::ApplicationService::Config.new({
|
|
33
|
+
"homeserver" => { "address" => "http://localhost:8008", "domain" => "localhost" },
|
|
34
|
+
"appservice" => { "as_token" => "as_token_value", "hs_token" => "hs_secret", "bot" => { "username" => "bot" } }
|
|
35
|
+
})
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "uses the double_puppet_token for authorization" do
|
|
39
|
+
puppet = Async::Matrix::DoublePuppetClient.new(make_config, double_puppet_token: "syt_puppet_token")
|
|
40
|
+
auth_header = puppet.instance_variable_get(:@headers).find { |k, _| k == "authorization" }
|
|
41
|
+
auth_header[1].should == "Bearer syt_puppet_token"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "does not use the as_token from config" do
|
|
45
|
+
puppet = Async::Matrix::DoublePuppetClient.new(make_config, double_puppet_token: "syt_puppet_token")
|
|
46
|
+
auth_header = puppet.instance_variable_get(:@headers).find { |k, _| k == "authorization" }
|
|
47
|
+
auth_header[1].should.not.include "as_token_value"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "inherits retry defaults from Client" do
|
|
51
|
+
puppet = Async::Matrix::DoublePuppetClient.new(make_config, double_puppet_token: "syt_puppet_token")
|
|
52
|
+
puppet.config.appservice.as_token.should == "as_token_value"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "accepts custom retry configuration" do
|
|
56
|
+
puppet = Async::Matrix::DoublePuppetClient.new(
|
|
57
|
+
make_config,
|
|
58
|
+
double_puppet_token: "syt_puppet_token",
|
|
59
|
+
max_retries: 5,
|
|
60
|
+
retry_base_delay: 1.0,
|
|
61
|
+
max_retry_delay: 60
|
|
62
|
+
)
|
|
63
|
+
auth_header = puppet.instance_variable_get(:@headers).find { |k, _| k == "authorization" }
|
|
64
|
+
auth_header[1].should == "Bearer syt_puppet_token"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "responds to all Client methods" do
|
|
68
|
+
puppet = Async::Matrix::DoublePuppetClient.new(make_config, double_puppet_token: "syt_puppet_token")
|
|
69
|
+
puppet.should.respond_to :send_text
|
|
70
|
+
puppet.should.respond_to :send_html
|
|
71
|
+
puppet.should.respond_to :send_notice
|
|
72
|
+
puppet.should.respond_to :join_room
|
|
73
|
+
puppet.should.respond_to :leave_room
|
|
74
|
+
puppet.should.respond_to :whoami
|
|
75
|
+
puppet.should.respond_to :api
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "is a subclass of Client" do
|
|
79
|
+
puppet = Async::Matrix::DoublePuppetClient.new(make_config, double_puppet_token: "syt_puppet_token")
|
|
80
|
+
puppet.should.be.kind_of Async::Matrix::Client
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the Apache License, Version 2.0.
|
|
4
|
+
# Copyright, 2026, by General Intelligence Systems.
|
|
5
|
+
|
|
6
|
+
# Loads the native vodozemac binding (ext/async_matrix_e2ee) and namespaces the
|
|
7
|
+
# Olm/Megolm primitives under Async::Matrix::E2EE.
|
|
8
|
+
#
|
|
9
|
+
# The native classes (Account, Session, GroupSession, InboundGroupSession) and
|
|
10
|
+
# the module function verify_signature are defined by the Rust #[magnus::init].
|
|
11
|
+
# This file only locates and requires the compiled object.
|
|
12
|
+
#
|
|
13
|
+
# account = Async::Matrix::E2EE::Account.new
|
|
14
|
+
# account.curve25519_key # => base64 string
|
|
15
|
+
# group = Async::Matrix::E2EE::GroupSession.new
|
|
16
|
+
# msg = group.encrypt("hello") # => base64 megolm message
|
|
17
|
+
# inbound = Async::Matrix::E2EE::InboundGroupSession.new(group.session_key)
|
|
18
|
+
# inbound.decrypt(msg) # => ["hello", 0]
|
|
19
|
+
|
|
20
|
+
module Async
|
|
21
|
+
module Matrix
|
|
22
|
+
module E2EE
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Precompiled ("fat") gems ship one .so per Ruby minor version under a versioned
|
|
28
|
+
# subdir (lib/async/matrix/3.3/async_matrix_e2ee.so). A locally source-compiled
|
|
29
|
+
# build lands flat, alongside this file. Try the versioned path first, then fall
|
|
30
|
+
# back to the flat one.
|
|
31
|
+
begin
|
|
32
|
+
RUBY_VERSION =~ /(\d+\.\d+)/
|
|
33
|
+
require_relative "#{Regexp.last_match(1)}/async_matrix_e2ee"
|
|
34
|
+
rescue LoadError
|
|
35
|
+
require_relative "async_matrix_e2ee"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
__END__
|
|
39
|
+
describe "Async::Matrix::E2EE" do
|
|
40
|
+
it "exposes account identity keys as base64" do
|
|
41
|
+
account = Async::Matrix::E2EE::Account.new
|
|
42
|
+
account.curve25519_key.should.be.kind_of String
|
|
43
|
+
account.ed25519_key.should.be.kind_of String
|
|
44
|
+
account.curve25519_key.length.should.be > 0
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "round-trips a megolm group message" do
|
|
48
|
+
group = Async::Matrix::E2EE::GroupSession.new
|
|
49
|
+
inbound = Async::Matrix::E2EE::InboundGroupSession.new(group.session_key)
|
|
50
|
+
|
|
51
|
+
message = group.encrypt("hello world")
|
|
52
|
+
plaintext, index = inbound.decrypt(message)
|
|
53
|
+
|
|
54
|
+
plaintext.should == "hello world"
|
|
55
|
+
index.should == 0
|
|
56
|
+
inbound.session_id.should == group.session_id
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "round-trips an olm 1:1 message" do
|
|
60
|
+
alice = Async::Matrix::E2EE::Account.new
|
|
61
|
+
bob = Async::Matrix::E2EE::Account.new
|
|
62
|
+
bob.generate_one_time_keys(1)
|
|
63
|
+
bob_otk = bob.one_time_keys.values.first
|
|
64
|
+
|
|
65
|
+
outbound = alice.create_outbound_session(bob.curve25519_key, bob_otk)
|
|
66
|
+
type, body = outbound.encrypt("yo g")
|
|
67
|
+
type.should == 0 # pre-key message
|
|
68
|
+
|
|
69
|
+
session, plaintext = bob.create_inbound_session(alice.curve25519_key, body)
|
|
70
|
+
plaintext.should == "yo g"
|
|
71
|
+
|
|
72
|
+
reply_type, reply_body = session.encrypt("hello back")
|
|
73
|
+
outbound.decrypt(reply_type, reply_body).should == "hello back"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "verifies a valid ed25519 signature and rejects a bad one" do
|
|
77
|
+
account = Async::Matrix::E2EE::Account.new
|
|
78
|
+
signature = account.sign("payload")
|
|
79
|
+
|
|
80
|
+
Async::Matrix::E2EE.verify_signature(account.ed25519_key, "payload", signature).should == true
|
|
81
|
+
Async::Matrix::E2EE.verify_signature(account.ed25519_key, "tampered", signature).should == false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "survives a pickle round-trip" do
|
|
85
|
+
key = "0" * 32
|
|
86
|
+
group = Async::Matrix::E2EE::GroupSession.new
|
|
87
|
+
pickled = group.pickle(key)
|
|
88
|
+
|
|
89
|
+
restored = Async::Matrix::E2EE::GroupSession.from_pickle(pickled, key)
|
|
90
|
+
restored.session_id.should == group.session_id
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
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 "json"
|
|
7
|
+
require "async/http"
|
|
8
|
+
|
|
9
|
+
module Async
|
|
10
|
+
module Matrix
|
|
11
|
+
# Extends Async::HTTP::Endpoint with Matrix well-known discovery.
|
|
12
|
+
# spec.matrix.org/v1.9/client-server-api/#well-known-uri
|
|
13
|
+
#
|
|
14
|
+
# A server at example.com may serve clients from a completely
|
|
15
|
+
# different origin — e.g. https://matrix.example.com:8448.
|
|
16
|
+
# #discover resolves that indirection as a proper async I/O
|
|
17
|
+
# operation before constructing the Endpoint, so every downstream
|
|
18
|
+
# caller gets a correctly-pointed connection pool for free.
|
|
19
|
+
class Endpoint < Async::HTTP::Endpoint
|
|
20
|
+
WELL_KNOWN = "/.well-known/matrix/client"
|
|
21
|
+
|
|
22
|
+
# Resolves homeserver base URL, falls back to https://domain.
|
|
23
|
+
# Must be called inside an Async block — uses the running scheduler.
|
|
24
|
+
def self.discover(domain, **options)
|
|
25
|
+
internet = Async::HTTP::Internet.new
|
|
26
|
+
data = JSON.parse(internet.get("https://#{domain}#{WELL_KNOWN}").read)
|
|
27
|
+
base_url = data.dig("m.homeserver", "base_url") || "https://#{domain}"
|
|
28
|
+
parse(base_url, **options)
|
|
29
|
+
rescue StandardError
|
|
30
|
+
# Well-known is optional per spec — fall back gracefully
|
|
31
|
+
parse("https://#{domain}", **options)
|
|
32
|
+
ensure
|
|
33
|
+
internet&.close
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
__END__
|
|
40
|
+
it "defines the WELL_KNOWN constant" do
|
|
41
|
+
Async::Matrix::Endpoint::WELL_KNOWN.should == "/.well-known/matrix/client"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "responds to .discover" do
|
|
45
|
+
Async::Matrix::Endpoint.should.respond_to :discover
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "inherits from Async::HTTP::Endpoint" do
|
|
49
|
+
Async::Matrix::Endpoint.ancestors.should.include Async::HTTP::Endpoint
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "falls back to https://domain when well-known fails" do
|
|
53
|
+
Async do
|
|
54
|
+
endpoint = Async::Matrix::Endpoint.discover("nonexistent.invalid")
|
|
55
|
+
endpoint.to_s.should =~ /nonexistent\.invalid/
|
|
56
|
+
end.wait
|
|
57
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
|
|
18
|
+
class NotFoundError < Error; end
|
|
19
|
+
class BadJsonError < Error; end
|
|
20
|
+
class AuthError < Error; end
|
|
21
|
+
class HomeserverError < Error; end
|
|
22
|
+
class InvalidEndpointError < Error; end
|
|
23
|
+
class ResponseTooLargeError < Error; end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
__END__
|
|
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
|
|
34
|
+
|
|
35
|
+
it "stores optional status" do
|
|
36
|
+
err = Async::Matrix::Error.new("M_UNKNOWN", "bad", status: 400)
|
|
37
|
+
err.status.should == 400
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "defaults status to nil" do
|
|
41
|
+
Async::Matrix::Error.new("M_UNKNOWN", "bad").status.should.be.nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "is a StandardError" do
|
|
45
|
+
Async::Matrix::Error.new("M_UNKNOWN", "bad").should.be.kind_of StandardError
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
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
|
|
52
|
+
|
|
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
|
|
56
|
+
|
|
57
|
+
it "AuthError inherits from Error" do
|
|
58
|
+
Async::Matrix::AuthError.new("M_FORBIDDEN", "denied").should.be.kind_of Async::Matrix::Error
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "HomeserverError inherits from Error" do
|
|
62
|
+
Async::Matrix::HomeserverError.new("M_UNKNOWN", "upstream").should.be.kind_of Async::Matrix::Error
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "ResponseTooLargeError inherits from Error" do
|
|
66
|
+
Async::Matrix::ResponseTooLargeError.new("M_TOO_LARGE", "too big").should.be.kind_of Async::Matrix::Error
|
|
67
|
+
end
|
|
@@ -0,0 +1,170 @@
|
|
|
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(method, url, headers, body)
|
|
53
|
+
status = response.status
|
|
54
|
+
|
|
55
|
+
unless (200..299).cover?(status)
|
|
56
|
+
payload = read_limited(response, ERROR_RESPONSE_SIZE_LIMIT)
|
|
57
|
+
parsed = ApplicationService::ErrorResponse.new(
|
|
58
|
+
begin; JSON.parse(payload); rescue; {} end
|
|
59
|
+
)
|
|
60
|
+
Console.error(self) { "Matrix media upload #{status}: #{parsed.errcode} — #{parsed.error}" }
|
|
61
|
+
raise HomeserverError.new(
|
|
62
|
+
parsed.errcode || "UNKNOWN",
|
|
63
|
+
parsed.error || payload.to_s[0..200],
|
|
64
|
+
status: status
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
payload = read_limited(response, UPLOAD_RESPONSE_SIZE_LIMIT)
|
|
69
|
+
payload && !payload.empty? ? JSON.parse(payload) : {}
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Download from the content repository.
|
|
73
|
+
#
|
|
74
|
+
# Returns the raw HTTP response object so the caller has access to
|
|
75
|
+
# both the body and response metadata:
|
|
76
|
+
#
|
|
77
|
+
# response = media_client.download(path)
|
|
78
|
+
# response.read # raw bytes (String, Encoding::BINARY)
|
|
79
|
+
# response.headers["content-type"] # "image/png"
|
|
80
|
+
# response.headers["content-disposition"] # "inline; filename=\"photo.jpg\""
|
|
81
|
+
# response.body.each { |chunk| ... } # streaming
|
|
82
|
+
#
|
|
83
|
+
# @param path [String] URL path (already URL-encoded, may include query string)
|
|
84
|
+
# @return [Protocol::HTTP::Response] the HTTP response
|
|
85
|
+
def download(path)
|
|
86
|
+
url = "#{@base}#{path}"
|
|
87
|
+
|
|
88
|
+
Console.debug(self) { "DOWNLOAD #{path}" }
|
|
89
|
+
|
|
90
|
+
response = internet.call("GET", url, @auth_headers, nil)
|
|
91
|
+
status = response.status
|
|
92
|
+
|
|
93
|
+
unless (200..299).cover?(status)
|
|
94
|
+
payload = response.read
|
|
95
|
+
parsed = ApplicationService::ErrorResponse.new(
|
|
96
|
+
begin; JSON.parse(payload); rescue; {} end
|
|
97
|
+
)
|
|
98
|
+
Console.error(self) { "Matrix media download #{status}: #{parsed.errcode} — #{parsed.error}" }
|
|
99
|
+
raise HomeserverError.new(
|
|
100
|
+
parsed.errcode || "UNKNOWN",
|
|
101
|
+
parsed.error || payload.to_s[0..200],
|
|
102
|
+
status: status
|
|
103
|
+
)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
response
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def close
|
|
110
|
+
@internet&.close
|
|
111
|
+
@internet = nil
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def internet
|
|
117
|
+
@internet ||= Async::HTTP::Internet.new
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Read response body with a size limit. Raises ResponseTooLargeError
|
|
121
|
+
# if the body exceeds the limit.
|
|
122
|
+
def read_limited(response, limit)
|
|
123
|
+
body = response.body
|
|
124
|
+
return nil unless body
|
|
125
|
+
|
|
126
|
+
if body.respond_to?(:length) && body.length && body.length > limit
|
|
127
|
+
body.close
|
|
128
|
+
raise ResponseTooLargeError.new(
|
|
129
|
+
"M_TOO_LARGE",
|
|
130
|
+
"Response Content-Length #{body.length} bytes exceeds limit of #{limit} bytes"
|
|
131
|
+
)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
buffer = String.new(encoding: Encoding::BINARY)
|
|
135
|
+
body.each do |chunk|
|
|
136
|
+
buffer << chunk
|
|
137
|
+
if buffer.bytesize > limit
|
|
138
|
+
body.close
|
|
139
|
+
raise ResponseTooLargeError.new(
|
|
140
|
+
"M_TOO_LARGE",
|
|
141
|
+
"Response body exceeds limit of #{limit} bytes"
|
|
142
|
+
)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
buffer.empty? ? nil : buffer
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
__END__
|
|
152
|
+
describe "Async::Matrix::MediaClient" do
|
|
153
|
+
def make_config
|
|
154
|
+
Async::Matrix::ApplicationService::Config.new({
|
|
155
|
+
"homeserver" => { "address" => "http://localhost:8008", "domain" => "localhost" },
|
|
156
|
+
"appservice" => { "as_token" => "test_token", "hs_token" => "hs_secret", "bot" => { "username" => "bot" } }
|
|
157
|
+
})
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "responds to upload and download" do
|
|
161
|
+
client = Async::Matrix::MediaClient.new(make_config)
|
|
162
|
+
client.should.respond_to :upload
|
|
163
|
+
client.should.respond_to :download
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "can be closed without error" do
|
|
167
|
+
client = Async::Matrix::MediaClient.new(make_config)
|
|
168
|
+
lambda { client.close }.should.not.raise
|
|
169
|
+
end
|
|
170
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
return result if result
|
|
41
|
+
|
|
42
|
+
remaining = deadline - Time.now
|
|
43
|
+
return result if remaining <= 0
|
|
44
|
+
|
|
45
|
+
begin
|
|
46
|
+
Async::Task.current.with_timeout(remaining) do
|
|
47
|
+
@condition.wait
|
|
48
|
+
end
|
|
49
|
+
rescue Async::TimeoutError
|
|
50
|
+
return yield
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
__END__
|
|
59
|
+
it "can be instantiated" do
|
|
60
|
+
notifier = Async::Matrix::Notifier.new
|
|
61
|
+
notifier.should.be.kind_of Async::Matrix::Notifier
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "responds to #signal" do
|
|
65
|
+
Async::Matrix::Notifier.new.should.respond_to :signal
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "responds to #wait" do
|
|
69
|
+
Async::Matrix::Notifier.new.should.respond_to :wait
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "returns truthy block value immediately without waiting" do
|
|
73
|
+
Async do
|
|
74
|
+
notifier = Async::Matrix::Notifier.new
|
|
75
|
+
result = notifier.wait(timeout: 1) { :data }
|
|
76
|
+
result.should == :data
|
|
77
|
+
end.wait
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "returns falsy block value on timeout" do
|
|
81
|
+
Async do
|
|
82
|
+
notifier = Async::Matrix::Notifier.new
|
|
83
|
+
result = notifier.wait(timeout: 0.05) { nil }
|
|
84
|
+
result.should.be.nil
|
|
85
|
+
end.wait
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "wakes waiting fibers on signal" do
|
|
89
|
+
result = nil
|
|
90
|
+
Async do |task|
|
|
91
|
+
notifier = Async::Matrix::Notifier.new
|
|
92
|
+
signalled = false
|
|
93
|
+
|
|
94
|
+
task.async do
|
|
95
|
+
result = notifier.wait(timeout: 5) { signalled }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
task.async do
|
|
99
|
+
signalled = true
|
|
100
|
+
notifier.signal
|
|
101
|
+
end
|
|
102
|
+
end.wait
|
|
103
|
+
result.should == true
|
|
104
|
+
end
|