# Copyright © 2018 Damir Jelić # Copyright © 2020-2021 Famedly GmbH # # Permission to use, copy, modify, and/or distribute this software for # any purpose with or without fee is hereby granted, provided that the # above copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER # RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF # CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. import re from jsonschema import Draft4Validator, FormatChecker, validators RoomRegex = "^!.+:.+$" UserIdRegex = "^@.*:.+$" EventTypeRegex = r"^.+\..+" Base64Regex = r"[^-A-Za-z0-9+/=]|=[^=]|={3,}$" KeyRegex = r"(ed25519|curve25519):.+" SignedCurveRegex = r"(signed_curve25519|curve25519):.+" def extend_with_default(validator_class): validate_properties = validator_class.VALIDATORS["properties"] def set_defaults(validator, properties, instance, schema): for property, subschema in properties.items(): if "default" in subschema: instance.setdefault(property, subschema["default"]) yield from validate_properties(validator, properties, instance, schema) return validators.extend(validator_class, {"properties": set_defaults}) Validator = extend_with_default(Draft4Validator) Checker = FormatChecker() @Checker.checks("user_id", ValueError) def check_user_id(value: str) -> bool: if not value.startswith("@"): raise ValueError("UserIDs start with @") if ":" not in value: raise ValueError("UserIDs must have a domain component, separated by a :") return True @Checker.checks("http_url", ValueError) def check_http_url(value: str) -> bool: if not re.match(r"^https?://.+", value): raise ValueError("Must be http://... or https://... URL") return True def validate_json(instance, schema): Validator(schema, format_checker=Checker).validate(instance) class Schemas: room_message = { "type": "object", "properties": { "content": { "type": "object", "properties": {"msgtype": {"type": "string"}}, "required": ["msgtype"], } }, "not": {"required": ["state_key"]}, } room_message_text = { "type": "object", "properties": { "content": { "type": "object", "properties": { "msgtype": {"type": "string", "const": "m.text"}, "body": {"type": "string"}, "formatted_body": {"type": "string"}, "format": {"type": "string"}, }, "required": ["msgtype", "body"], } }, } room_message_emote = { "type": "object", "properties": { "content": { "type": "object", "properties": { "msgtype": {"type": "string", "const": "m.emote"}, "body": {"type": "string"}, "formatted_body": {"type": "string"}, "format": {"type": "string"}, }, "required": ["msgtype", "body"], } }, } room_message_notice = { "type": "object", "properties": { "content": { "type": "object", "properties": { "msgtype": {"type": "string", "const": "m.notice"}, "body": {"type": "string"}, "formatted_body": {"type": "string"}, "format": {"type": "string"}, }, "required": ["msgtype", "body"], }, }, } room_message_media = { "type": "object", "properties": { "content": { "type": "object", "properties": { "body": {"type": "string"}, "url": {"type": "string"}, "msgtype": { "type": "string", "enum": ["m.image", "m.audio", "m.video", "m.file"], }, }, "required": ["body", "url", "msgtype"], } }, } room_encrypted_media = { "type": "object", "properties": { "content": { "type": "object", "properties": { "body": {"type": "string"}, "msgtype": { "type": "string", "enum": ["m.image", "m.audio", "m.video", "m.file"], }, "file": { "type": "object", "properties": { "url": {"type": "string"}, "hashes": { "type": "object", "properties": {"sha256": {"type": "string"}}, }, "iv": {"type": "string"}, "key": { "type": "object", "properties": { "alg": {"type": "string"}, "k": {"type": "string"}, }, "required": ["alg", "k"], }, }, "required": ["url", "hashes", "iv", "key"], }, "info": { "type": "object", "properties": { "thumbnail_file": { "type": "object", "properties": { "url": {"type": "string"}, "hashes": { "type": "object", "properties": {"sha256": {"type": "string"}}, }, "iv": {"type": "string"}, "key": { "type": "object", "properties": { "alg": {"type": "string"}, "k": {"type": "string"}, }, "required": ["alg", "k"], }, }, "required": ["url", "hashes", "iv", "key"], }, }, }, }, "required": ["body", "file", "msgtype"], } }, "required": ["content"], } redacted_event = { "type": "object", "properties": { "unsigned": { "type": "object", "properties": { "redacted_because": { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "content": { "type": "object", "properties": {"reason": {"type": "string"}}, }, }, "required": ["sender", "content"], } }, "required": ["redacted_because"], } }, "required": ["unsigned"], } register = { "type": "object", "properties": { "user_id": {"type": "string", "format": "user_id"}, "device_id": {"type": "string"}, "access_token": {"type": "string"}, }, "required": ["user_id", "device_id", "access_token"], } register_flows = { "type": "object", "properties": { "flows": { "type": "array", "items": { "type": "object", "properties": { "stages": { "type": "array", "items": {"type": "string"}, } }, "required": ["stages"], }, }, "params": {"type": "object"}, "session": {"type": "string"}, "completed": {"type": "array", "items": {"type": "string"}}, "user_id": {"type": "string", "format": "user_id"}, "device_id": {"type": "string"}, "access_token": {"type": "string"}, }, "required": ["flows", "params", "session"], } login = { "type": "object", "properties": { "user_id": {"type": "string", "format": "user_id"}, "device_id": {"type": "string"}, "access_token": {"type": "string"}, }, "required": ["user_id", "device_id", "access_token"], } discovery_info = { "type": "object", "properties": { "m.homeserver": { "type": "object", "properties": { "base_url": {"type": "string", "format": "http_url"}, }, "required": ["base_url"], }, "m.identity_server": { "type": "object", "properties": { "base_url": {"type": "string", "format": "http_url"}, }, "required": ["base_url"], }, }, "required": ["m.homeserver"], } login_info = { "type": "object", "properties": { "flows": { "type": "array", "items": { "type": "object", "properties": {"type": {"type": "string"}}, "required": ["type"], }, }, }, "required": ["flows"], } error = { "type": "object", "properties": { "error": {"type": "string"}, "errcode": {"type": "string"}, "retry_after_ms": {"type": "integer"}, }, "required": ["error", "errcode"], } room_timeline = { "type": "object", "properties": { "events": {"type": "array"}, "limited": {"type": "boolean"}, "prev_batch": {"type": "string"}, }, "required": ["events"], } sync = { "type": "object", "properties": { "device_one_time_keys_count": { "type": "object", "default": {}, "properties": { "curve25519": {"type": "integer"}, "signed_curve25519": {"type": "integer"}, }, }, "device_lists": { "type": "object", "default": {}, "properties": { "changed": {"type": "array", "items": {"type": "string"}}, "left": {"type": "array", "items": {"type": "string"}}, }, }, "next_batch": {"type": "string"}, "rooms": { "type": "object", "default": {}, "properties": { "invite": { "type": "object", "default": {}, "patternProperties": { RoomRegex: { "type": "object", "properties": { "invite_state": { "type": "object", "default": {}, "properties": { "events": { "type": "array", "default": [], } }, } }, } }, }, "join": { "type": "object", "default": {}, "patternProperties": { RoomRegex: { "type": "object", "properties": { "timeline": room_timeline, "state": { "type": "object", "default": {}, "properties": { "events": { "type": "array", "default": [], }, }, }, "ephemeral": { "type": "object", "default": {}, "properties": { "events": { "type": "array", "default": [], } }, }, "summary": { "type": "object", "properties": { "m.invited_member_count": { "type": "integer" }, "m.joined_member_count": { "type": "integer" }, "m.heroes": { "type": "array", "items": {"type": "string"}, }, }, }, "account_data": { "type": "object", "default": {}, "properties": { "events": { "type": "array", "default": [], }, }, }, }, } }, }, "leave": { "type": "object", "default": {}, "patternProperties": { RoomRegex: { "type": "object", "properties": { "timeline": { "type": "object", "default": {}, "properties": { "events": { "type": "array", "default": [], }, }, }, "state": { "type": "object", "default": {}, "properties": { "events": { "type": "array", "default": [], }, }, }, }, } }, }, }, }, "to_device": { "type": "object", "default": {}, "properties": {"events": {"type": "array", "default": []}}, }, "presence": { "type": "object", "default": {}, "properties": { "events": {"type": "array", "default": []}, }, }, }, "required": ["next_batch"], } room_event = { "type": "object", "properties": { "event_id": {"type": "string"}, "sender": {"type": "string", "format": "user_id"}, "type": {"type": "string"}, "origin_server_ts": {"type": "integer", "minimum": 0}, "unsigned": { "type": "object", "properties": { "transaction_id": {"type": "string"}, }, }, }, "required": ["event_id", "sender", "type", "origin_server_ts"], } state_event = { "type": "object", "properties": { "event_id": {"type": "string"}, "sender": {"type": "string", "format": "user_id"}, "type": {"type": "string"}, "state_key": {"type": "string"}, "origin_server_ts": {"type": "integer", "minimum": 0}, "unsigned": { "type": "object", "properties": { "transaction_id": {"type": "string"}, }, }, }, "required": ["event_id", "sender", "type", "state_key", "origin_server_ts"], } room_state = { "type": "array", "items": state_event, } sync_room_state = { "type": "object", "properties": {"events": {"type": "array"}}, "required": ["events"], } to_device = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "type": {"type": "string"}, "content": {"type": "object"}, }, "required": ["sender", "type", "content"], } room_encrypted = { "type": "object", "properties": { "content": { "type": "object", "properties": { "sender_key": {"type": "string"}, "algorithm": {"type": "string"}, }, "required": ["sender_key", "algorithm"], } }, "required": ["content"], } room_olm_encrypted = { "type": "object", "properties": { "type": {"type": "string", "enum": ["m.room.encrypted"]}, "content": { "type": "object", "properties": { "sender_key": {"type": "string"}, "algorithm": { "type": "string", "enum": ["m.olm.v1.curve25519-aes-sha2"], }, "ciphertext": { "type": "object", "patternProperties": { Base64Regex: { "type": "object", "properties": { "body": {"type": "string"}, "type": {"type": "integer"}, }, "required": ["type", "body"], } }, }, }, "required": ["sender_key", "algorithm", "ciphertext"], }, }, "required": [ "type", "content", ], } room_megolm_decrypted = { "type": "object", "properties": {"type": {"type": "string"}, "content": {"type": "object"}}, "required": [ "type", "content", ], } room_megolm_encrypted = { "type": "object", "properties": { "type": {"type": "string", "enum": ["m.room.encrypted"]}, "event_id": {"type": "string"}, "sender": {"type": "string", "format": "user_id"}, "origin_server_ts": {"type": "integer", "minimum": 0}, "room_id": {"type": "string"}, "content": { "type": "object", "properties": { "sender_key": {"type": "string"}, "algorithm": {"type": "string", "enum": ["m.megolm.v1.aes-sha2"]}, "ciphertext": {"type": "string"}, "session_id": {"type": "string"}, "device_id": {"type": "string"}, }, "required": [ "sender_key", "algorithm", "ciphertext", "session_id", "device_id", ], }, }, "required": ["type", "content", "event_id", "sender", "origin_server_ts"], } olm_event = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "sender_device": {"type": "string"}, "keys": { "type": "object", "properties": {"ed25519": {"type": "string"}}, }, "recipient": {"type": "string", "format": "user_id"}, "recipient_keys": { "type": "object", "properties": {"ed25519": {"type": "string"}}, }, "type": {"type": "string"}, "content": {"type": "object"}, }, "required": [ "type", "sender", "keys", "recipient", "recipient_keys", "content", ], } dummy_event = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "sender_device": {"type": "string"}, "type": {"type": "string", "enum": ["m.dummy"]}, "content": { "type": "object", }, "keys": {"type": "object"}, }, "required": ["type", "sender", "keys", "sender_device"], } room_key_request = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "type": {"type": "string", "enum": ["m.room_key_request"]}, "content": { "type": "object", "properties": { "body": { "type": "object", "properties": { "algorithm": {"type": "string"}, "room_id": {"type": "string", "format": "room_id"}, "sender_key": {"type": "string"}, "session_id": {"type": "string"}, }, "required": [ "algorithm", "room_id", "sender_key", "session_id", ], }, "requesting_device_id": {"type": "string"}, "action": { "type": "string", "enum": ["request", "request_cancellation"], }, "request_id": {"type": "string"}, }, "required": ["requesting_device_id", "request_id", "action", "body"], }, }, "required": ["type", "sender", "content"], } room_key_request_cancel = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "type": {"type": "string", "enum": ["m.room_key_request"]}, "content": { "type": "object", "properties": { "requesting_device_id": {"type": "string"}, "action": { "type": "string", "enum": ["request", "request_cancellation"], }, "request_id": {"type": "string"}, }, "required": ["requesting_device_id", "request_id", "action"], }, }, "required": ["type", "sender", "content"], } room_key_event = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "sender_device": {"type": "string"}, "type": {"type": "string", "enum": ["m.room_key"]}, "content": { "type": "object", "properties": { "algorithm": {"type": "string"}, "room_id": {"type": "string", "format": "room_id"}, "session_id": {"type": "string"}, "session_key": {"type": "string"}, }, "required": [ "algorithm", "room_id", "session_id", "session_key", ], }, "keys": {"type": "object"}, }, "required": ["type", "sender", "content", "keys"], } forwarded_room_key_event = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "sender_device": {"type": "string"}, "type": {"type": "string", "enum": ["m.forwarded_room_key"]}, "content": { "type": "object", "properties": { "algorithm": {"type": "string"}, "room_id": {"type": "string", "format": "room_id"}, "sender_key": {"type": "string"}, "sender_claimed_ed25519_key": {"type": "string"}, "forwarding_curve25519_key_chain": { "type": "array", "items": {"type": "string"}, }, "session_id": {"type": "string"}, "session_key": {"type": "string"}, }, "required": [ "algorithm", "room_id", "session_id", "session_key", "sender_key", "sender_claimed_ed25519_key", "forwarding_curve25519_key_chain", ], }, }, "required": ["type", "sender", "content"], } room_create = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": { "m.federate": {"type": "boolean", "default": True}, "room_version": {"type": "string", "default": "1"}, "type": {"type": "string", "default": ""}, "predecessor": { "type": "object", "properties": { "event_id": {"type": "string"}, "room_id": {"type": "string", "format": "room_id"}, }, "required": ["event_id", "room_id"], }, }, "required": [], }, }, "required": ["type", "sender", "content", "state_key"], } room_guest_access = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": { "guest_access": { "type": "string", "enum": ["can_join", "forbidden"], "default": "forbidden", }, }, "required": ["guest_access"], }, }, "required": ["type", "sender", "content", "state_key"], } room_join_rules = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": { "join_rule": { "type": "string", "enum": [ "public", "knock", "invite", "private", "restricted", "knock_restricted", ], "default": "invite", }, }, "required": ["join_rule"], }, }, "required": ["type", "sender", "content", "state_key"], } room_history_visibility = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": { "history_visibility": { "type": "string", "enum": [ "invited", "joined", "shared", "world_readable", ], "default": "shared", }, }, "required": ["history_visibility"], }, }, "required": ["type", "sender", "content", "state_key"], } room_get_chunked_messages = { "type": "object", "properties": { "chunk": { "type": "array", "items": { "type": "object", "properties": { "content": {"type": "object"}, "event_id": {"type": "string"}, "origin_server_ts": {"type": "integer"}, "room_id": {"type": "string"}, "sender": {"type": "string"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "unsigned": { "type": "object", "properties": { "age": {"type": "integer"}, "prev_content": {"type": "object"}, "redacted_because": {"type": "object"}, "transaction_id": {"type": "string"}, }, }, }, "required": [ "content", "event_id", "origin_server_ts", "room_id", "sender", "type", ], }, }, "prev_batch": {"type": "string"}, "next_batch": {"type": "string"}, }, "required": ["chunk"], } room_canonical_alias = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": {"alias": {"type": ["string", "null"]}}, "required": [], }, }, "required": ["type", "sender", "content", "state_key"], } room_name = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": {"name": {"type": "string"}}, "required": ["name"], }, }, "required": ["type", "sender", "content", "state_key"], } room_encryption = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", }, }, "required": ["type", "sender", "content", "state_key"], } room_topic = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": {"topic": {"type": "string"}}, "required": ["topic"], }, }, "required": ["type", "sender", "content", "state_key"], } room_space_parent = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": { "canonical": {"type": "boolean", "default": False}, "via": {"type": "array", "items": {"type": "string"}}, }, }, }, "required": ["type", "sender", "content", "state_key"], } room_space_child = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": { "suggested": {"type": "boolean", "default": False}, "via": {"type": "array", "items": {"type": "string"}}, "order": {"type": "string"}, }, }, }, "required": ["type", "sender", "content", "state_key"], } room_avatar = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": { "info": { "h": {"type": "integer"}, "w": {"type": "integer"}, "mimetype": {"type", "string"}, "size": {"type": "integer"}, }, "url": {"type": "string"}, }, "required": [], }, }, "required": ["type", "sender", "content", "state_key"], } room_power_levels = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string"}, "type": {"type": "string"}, "content": { "type": "object", "properties": { "ban": {"type": "integer", "default": 50}, "kick": {"type": "integer", "default": 50}, "invite": {"type": "integer", "default": 50}, "redact": {"type": "integer", "default": 50}, "users_default": {"type": "integer", "default": 0}, "events_default": {"type": "integer", "default": 0}, "state_default": {"type": "integer", "default": 50}, "events": { "type": "object", "default": {}, "patternProperties": {EventTypeRegex: {"type": "integer"}}, }, "users": { "type": "object", "default": {}, "patternProperties": {UserIdRegex: {"type": "integer"}}, }, "notifications": { "type": "object", "default": {}, "properties": { "room": {"type": "integer", "default": 50}, }, }, }, }, }, "required": ["type", "sender", "content", "state_key"], } room_membership = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "state_key": {"type": "string", "format": "user_id"}, "type": {"type": "string", "enum": ["m.room.member"]}, "prev_content": { "type": "object", "properties": { "membership": { "type": "string", "enum": ["invite", "join", "knock", "leave", "ban"], }, "avatar_url": {"type": ["string", "null"]}, "displayname": {"type": ["string", "null"]}, }, "required": ["membership"], }, "content": { "type": "object", "properties": { "membership": { "type": "string", "enum": ["invite", "join", "knock", "leave", "ban"], }, "reason": {"type": ["string", "null"]}, "avatar_url": {"type": ["string", "null"]}, "displayname": {"type": ["string", "null"]}, }, "required": ["membership"], }, }, "required": ["type", "sender", "state_key", "content"], } room_redaction = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "redacts": {"type": "string"}, "content": { "type": "object", "properties": {"reason": {"type": "string"}}, }, }, "required": ["sender", "redacts"], } sticker = { "type": "object", "properties": { "sender": {"type": "string", "format": "user_id"}, "content": { "type": "object", "properties": { "body": {"type": "string"}, "url": {"type": "string"}, }, "required": ["body", "url"], }, }, "required": ["sender"], } reaction = { "type": "object", "properties": { "sender": { "type": "string", "format": "user_id", }, "content": { "type": "object", "properties": { "m.relates_to": { "type": "object", "properties": { "rel_type": { "type": "string", "const": "m.annotation", }, "event_id": {"type": "string"}, "key": {"type": "string"}, }, "required": ["rel_type", "event_id", "key"], }, }, "required": ["m.relates_to"], }, }, "required": ["sender", "content"], } room_resolve_alias = { "type": "object", "properties": { "room_id": {"type": "string"}, "servers": {"type": "array", "items": {"type": "string"}}, }, "required": ["room_id", "servers"], } room_get_visibility = { "type": "object", "properties": { "room_id": {"type": "string"}, "visibility": {"type": "string", "enum": ["private", "public"]}, }, "required": ["visibility"], } room_event_id = { "type": "object", "properties": {"event_id": {"type": "string"}}, "required": ["event_id"], } room_id = { "type": "object", "properties": {"room_id": {"type": "string"}}, "required": ["room_id"], } room_create_response = { "type": "object", "properties": {"room_id": {"type": "string"}}, "required": ["room_id"], } room_messages = { "type": "object", "properties": { "chunk": {"type": "array"}, "start": {"type": "string"}, "end": {"type": "string"}, }, "required": ["chunk", "start"], } room_context = { "type": "object", "properties": { "start": {"type": "string"}, "end": {"type": "string"}, "state": {"type": "array"}, "events_before": {"type": "array"}, "events_after": {"type": "array"}, "event": {"type": "object"}, }, # As per https://spec.matrix.org/v1.1/client-server-api/#get_matrixclientv3roomsroomidcontexteventid # Everything _SHOULD_ be optional *but* `event` is so necessary that we still put it as required. "required": ["event"], } invite_event = { "type": "object", "properties": {"content": {"type": "object"}, "type": {"type": "string"}}, "required": ["content", "type"], } ephemeral_event = { "type": "object", "properties": {"content": {"type": "object"}, "type": {"type": "string"}}, "required": ["content", "type"], } m_typing = { "type": "object", "properties": { "content": { "type": "object", "properties": { "user_ids": {"type": "array", "items": {"type": "string"}} }, "required": ["user_ids"], }, "type": {"type": "string"}, "room_id": {"type": "string"}, }, "required": ["content", "type"], } _receipt = { "type": "object", "patternProperties": { UserIdRegex: { "type": ["object", "string"], "properties": { "ts": {"type": "integer"}, "thread_id": {"type": "string"}, }, "required": ["ts"], } }, } m_receipt = { "type": "object", "properties": { "content": { "type": "object", "patternProperties": { r".*": { "type": "object", "properties": { "m.read": _receipt, "m.read.private": _receipt, }, } }, }, "type": {"type": "string"}, "room_id": {"type": "string"}, }, "required": ["content", "type"], } get_openid_token = { "type": "object", "properties": { "access_token": {"type": "string"}, "expires_in": {"type": "integer"}, "matrix_server_name": {"type": "string"}, "token_type": {"type": "string"}, }, "required": ["access_token", "expires_in", "matrix_server_name", "token_type"], } keys_upload = { "type": "object", "properties": { "one_time_key_counts": { "type": "object", "properties": { "curve25519": {"type": "integer", "default": 0}, "signed_curve25519": {"type": "integer", "default": 0}, }, }, }, "required": ["one_time_key_counts"], } keys_query = { "type": "object", "properties": { "device_keys": { "type": "object", "patternProperties": { UserIdRegex: { "type": "object", "patternProperties": { r".+": { "type": "object", "properties": { "algorithms": { "type": "array", "items": {"type": "string"}, }, "device_id": {"type": "string"}, "user_id": {"type": "string"}, "keys": { "type": "object", "patternProperties": { KeyRegex: {"type": "string"} }, }, "signatures": { "type": "object", "patternProperties": { UserIdRegex: { "type": "object", "patternProperties": { KeyRegex: {"type": "string"} }, } }, }, }, "required": ["algorithms", "device_id", "keys"], } }, } }, }, "failures": {"type": "object"}, }, "required": ["device_keys"], } keys_claim = { "type": "object", "properties": { "one_time_keys": { "type": "object", "patternProperties": { UserIdRegex: { "type": "object", "patternProperties": { r".+": { "type": "object", "properties": { "patternProperties": { SignedCurveRegex: { "type": "object", "properties": { "key": {"type": "str"}, "signatures": { "type": "object", "patternProperties": { UserIdRegex: { "type": "object", "patternProperties": { KeyRegex: { "type": "string" } }, } }, }, }, "required": ["key", "signatures"], } }, }, } }, } }, }, "failures": {"type": "object"}, }, "required": ["one_time_keys"], } devices = { "type": "object", "properties": { "devices": { "type": "array", "items": { "type": "object", "properties": { "device_id": {"type": "string"}, "display_name": {"type": ["string", "null"]}, "last_seen_ip": {"type": ["string", "null"]}, "last_seen_ts": {"type": ["integer", "null"]}, }, "required": [ "device_id", "display_name", "last_seen_ip", "last_seen_ts", ], }, }, }, "required": ["devices"], } delete_devices = { "type": "object", "properties": { "session": {"type": "string"}, "flows": { "type": "array", "items": { "type": "object", "properties": { "stages": {"type": "array", "items": {"type": "string"}}, "required": ["stages"], }, }, }, "params": { "type": "object", "patternProperties": { r".+": { "type": "object", "patternProperties": {r".+": {"type": "string"}}, } }, }, "required": ["session", "flows", "params"], }, } joined_members = { "type": "object", "properties": { "joined": { "type": "object", "patternProperties": { UserIdRegex: { "type": "object", "properties": { "avatar_url": {"type": ["string", "null"]}, "display_name": {"type": ["string", "null"]}, }, "required": [], } }, } }, "required": ["joined"], } joined_rooms = { "type": "object", "properties": {"joined_rooms": {"type": "array", "items": {"type": "string"}}}, "required": ["joined_rooms"], } call_invite = { "type": "object", "properties": { "type": {"type": "string"}, "content": { "type": "object", "properties": { "call_id": {"type": "string"}, "lifetime": {"type": "integer"}, "version": {"type": ["integer", "string"]}, "offer": { "type": "object", "properties": { "type": {"type": "string", "enum": ["offer"]}, "sdp": {"type": "string"}, }, "required": ["type", "sdp"], }, }, "required": [ "call_id", "lifetime", "version", "offer", ], }, }, "required": [ "type", "content", ], } call_answer = { "type": "object", "properties": { "type": {"type": "string"}, "content": { "type": "object", "properties": { "call_id": {"type": "string"}, "version": {"type": ["integer", "string"]}, "answer": { "type": "object", "properties": { "type": {"type": "string", "enum": ["answer"]}, "sdp": {"type": "string"}, }, "required": ["type", "sdp"], }, }, "required": [ "call_id", "version", "answer", ], }, }, "required": [ "type", "content", ], } call_hangup = { "type": "object", "properties": { "type": {"type": "string"}, "content": { "type": "object", "properties": { "call_id": {"type": "string"}, "version": {"type": ["integer", "string"]}, }, "required": [ "call_id", "version", ], }, }, "required": [ "type", "content", ], } call_candidates = { "type": "object", "properties": { "type": {"type": "string"}, "content": { "type": "object", "properties": { "call_id": {"type": "string"}, "version": {"type": ["integer", "string"]}, "candidates": { "type": "array", "items": { "type": "object", "properties": { "candidate": {"type": "string"}, "sdpMLineIndex": {"type": "integer"}, "sdpMid": {"type": "string"}, }, "required": ["candidate", "sdpMLineIndex", "sdpMid"], }, }, }, "required": ["call_id", "version", "candidates"], }, }, "required": [ "type", "content", ], } account_data = { "type": "object", "properties": {"type": {"type": "string"}, "content": {"type": "object"}}, "required": [ "type", "content", ], } fully_read = { "type": "object", "properties": { "type": {"type": "string"}, "content": { "type": "object", "properties": { "event_id": {"type": "string"}, }, "required": [ "event_id", ], }, }, "required": [ "type", "content", ], } tags = { "type": "object", "properties": { "type": {"type": "string"}, "content": { "type": "object", "properties": { "tags": { "type:": "object", "patternProperties": { r".*": { "type": "object", "properties": {"order": {"type": "number"}}, }, }, }, }, "required": ["tags"], }, }, "required": [ "type", "content", ], } push_rules = { "type": "object", "properties": { "type": { "type": "string", "const": "m.push_rules", }, "content": { "type": "object", "properties": { "global": {"type": "object"}, "device": {"type": "object"}, }, "required": ["global"], }, }, "required": ["type", "content"], } push_ruleset = { "type": "object", "properties": { "override": {"type": "array", "items": {"type": "object"}}, "content": {"type": "array", "items": {"type": "object"}}, "room": {"type": "array", "items": {"type": "object"}}, "sender": {"type": "array", "items": {"type": "object"}}, "underride": {"type": "array", "items": {"type": "object"}}, }, } push_rule = { "type": "object", "properties": { "rule_id": {"type": "string"}, "default": {"type": "boolean", "default": False}, "enabled": {"type": "boolean"}, "pattern": {"type": "string"}, "conditions": { "type": "array", "items": { "type": "object", "properties": { "kind": {"type": "string"}, "key": {"type": "string"}, "pattern": {"type": "string"}, "is": { "type": "string", "pattern": r"(==|<=|>=|<|>)?[0-9.-]+", }, }, "required": ["kind"], }, }, "actions": { "type": "array", "items": {"type": ["string", "object"]}, }, }, "required": ["rule_id", "default", "enabled", "actions"], } upload = { "type": "object", "properties": {"content_uri": {"type": "string"}}, "required": ["content_uri"], } content_repository_config = { "type": "object", "properties": {"m.upload.size": {"type": ["number", "null"]}}, } megolm_key_import = { "type": "array", "items": { "type": "object", "properties": { "algorithm": {"type": "string"}, "session_key": {"type": "string"}, "sender_key": {"type": "string"}, "room_id": {"type": "string"}, "sender_claimed_keys": { "type": "object", "properties": { "ed25519": {"type": "string"}, }, "required": ["ed25519"], }, "forwarding_curve25519_key_chain": { "type": "array", "items": {"type": "string"}, }, }, "required": [ "algorithm", "session_key", "sender_key", "room_id", "sender_claimed_keys", "forwarding_curve25519_key_chain", ], }, } get_profile = { "type": "object", "properties": { "displayname": {"type": "string"}, "avatar_url": {"type": "string"}, }, "not": {"required": ["errcode"]}, } get_displayname = { "type": "object", "properties": { "displayname": {"type": ["string", "null"]}, }, "required": ["displayname"], } get_avatar = { "type": "object", "properties": { "avatar_url": {"type": ["string", "null"]}, }, "required": ["avatar_url"], } key_verification_start = { "type": "object", "properties": { "sender": {"type": "string"}, "content": { "type": "object", "properties": { "transaction_id": {"type": "string"}, "from_device": {"type": "string"}, "method": {"type": "string"}, "key_agreement_protocols": { "type": "array", "items": {"type": "string"}, }, "hashes": {"type": "array", "items": {"type": "string"}}, "message_authentication_codes": { "type": "array", "items": {"type": "string"}, }, "short_authentication_string": { "type": "array", "items": {"type": "string"}, }, }, "required": [ "transaction_id", "from_device", "method", "key_agreement_protocols", "hashes", "message_authentication_codes", "short_authentication_string", ], }, }, "required": [ "sender", "content", ], } key_verification_accept = { "type": "object", "properties": { "sender": {"type": "string"}, "content": { "type": "object", "properties": { "transaction_id": {"type": "string"}, "commitment": {"type": "string"}, "key_agreement_protocol": {"type": "string"}, "hash": {"type": "string"}, "message_authentication_code": {"type": "string"}, "short_authentication_string": { "type": "array", "items": {"type": "string"}, }, }, "required": [ "transaction_id", "commitment", "key_agreement_protocol", "hash", "message_authentication_code", "short_authentication_string", ], }, }, "required": [ "sender", "content", ], } key_verification_key = { "type": "object", "properties": { "sender": {"type": "string"}, "content": { "type": "object", "properties": { "transaction_id": {"type": "string"}, "key": {"type": "string"}, }, "required": [ "transaction_id", "key", ], }, }, "required": [ "sender", "content", ], } key_verification_mac = { "type": "object", "properties": { "sender": {"type": "string"}, "content": { "type": "object", "properties": { "mac": { "type": "object", "patternProperties": {r".+": {"type": "string"}}, }, "keys": {"type": "string"}, }, "required": [ "transaction_id", "mac", "keys", ], }, }, "required": [ "sender", "content", ], } key_verification_cancel = { "type": "object", "properties": { "sender": {"type": "string"}, "content": { "type": "object", "properties": { "transaction_id": {"type": "string"}, "code": {"type": "string"}, "reason": {"type": "string"}, }, "required": [ "transaction_id", "code", "reason", ], }, }, "required": ["sender", "content"], } presence = { "type": "object", "properties": { "sender": {"type": "string"}, "type": {"type": "string", "const": "m.presence"}, "content": { "type": "object", "properties": { "presence": {"type": "string"}, "currently_active": {"type": "boolean"}, "last_active_ago": {"type": "integer"}, "status_msg": {"type": "string"}, }, "required": [ "presence", ], }, }, "required": ["sender", "type", "content"], } get_presence = { "type": "object", "properties": { "presence": {"type": "string"}, "last_active_ago": {"type": "integer"}, "status_msg": {"type": "string"}, "currently_active": {"type": "boolean"}, }, "required": [ "presence", ], } empty = {"type": "object", "properties": {}, "additionalProperties": False} upload_filter = { "type": "object", "properties": {"filter_id": {"type": "string"}}, "required": ["filter_id"], } whoami = { "type": "object", "properties": { "user_id": {"type": "string", "format": "user_id"}, "device_id": {"type": "string"}, "is_guest": {"type": "boolean"}, }, "required": ["user_id"], } room_tombstone = { "type": "object", "properties": { "type": {"type": "string", "const": "m.room.tombstone"}, "state_key": {"type": "string", "const": ""}, "content": { "type": "object", "properties": { "body": {"type": "string"}, "replacement_room": {"type": "string", "format": "room_id"}, }, "required": [ "body", "replacement_room", ], }, }, "required": [ "sender", "type", "content", "state_key", ], } space_hierarchy = { "type": "object", "properties": { "next_batch": {"type": "string"}, "rooms": { "type": "array", "items": { "type": "object", "properties": { "avatar_url": {"type": "string"}, "canonical_alias": {"type": "string"}, "children_state": { "type": "array", "items": { "type": "object", "properties": { "content": { "type": "object", "properties": { "via": { "type": "array", "items": {"type": "string"}, }, }, "required": ["via"], }, "origin_server_ts": {"type": "integer"}, "sender": {"type": "string"}, "state_key": {"type": "string"}, "type": {"type": "string"}, }, "required": [ "content", "origin_server_ts", "sender", "state_key", "type", ], }, }, "guest_can_join": {"type": "boolean"}, "join_rule": {"type": "string"}, "name": {"type": "string"}, "num_joined_members": {"type": "integer"}, "room_id": {"type": "string"}, "room_type": {"type": "string"}, "topic": {"type": "string"}, "world_readable": {"type": "boolean"}, }, "required": [ "children_state", "guest_can_join", "num_joined_members", "room_id", "world_readable", ], }, }, }, "required": ["rooms"], } public_rooms_chunk = { "type": "object", "properties": { "avatar_url": {"type": "string"}, "canonical_alias": {"type": "string"}, "guest_can_join": {"type": "boolean"}, "join_rule": {"type": "string"}, "name": {"type": "string"}, "num_joined_members": {"type": "integer"}, "room_id": {"type": "string"}, "room_type": {"type": "string"}, "topic": {"type": "string"}, "world_readable": {"type": "boolean"}, }, "required": [ "guest_can_join", "num_joined_members", "room_id", "world_readable", ], } public_rooms_response = { "type": "object", "properties": { "chunk": {"type": "array", "items": public_rooms_chunk}, "next_batch": {"type": "string"}, "prev_batch": {"type": "string"}, "total_room_count_estimate": {"type": "integer"}, }, "required": ["chunk"], }