Add 'ruma-client-api/' from commit '632eb9d520028816c5fb7224bd0aca8d1e3793f1'
git-subtree-dir: ruma-client-api git-subtree-mainline: e5233c49f610f866e3c9bf8529a0613171fc2fe4 git-subtree-split: 632eb9d520028816c5fb7224bd0aca8d1e3793f1
This commit is contained in:
commit
6329cd471e
30
ruma-client-api/.builds/beta.yml
Normal file
30
ruma-client-api/.builds/beta.yml
Normal file
@ -0,0 +1,30 @@
|
||||
image: archlinux
|
||||
packages:
|
||||
- rustup
|
||||
sources:
|
||||
- https://github.com/ruma/ruma-client-api
|
||||
tasks:
|
||||
- rustup: |
|
||||
# We specify --profile minimal because we'd otherwise download docs
|
||||
rustup toolchain install beta --profile minimal -c rustfmt -c clippy
|
||||
rustup default beta
|
||||
- test: |
|
||||
cd ruma-client-api
|
||||
|
||||
# We don't want the build to stop on individual failure of independent
|
||||
# tools, so capture tool exit codes and set the task exit code manually
|
||||
set +e
|
||||
|
||||
cargo fmt -- --check
|
||||
fmt_exit=$?
|
||||
|
||||
cargo clippy --all-targets --all-features -- -D warnings
|
||||
clippy_exit=$?
|
||||
|
||||
cargo test --no-default-features --verbose
|
||||
test1_exit=$?
|
||||
|
||||
cargo test --all-features --verbose
|
||||
test2_exit=$?
|
||||
|
||||
exit $(( $fmt_exit || $clippy_exit || $test1_exit || $test2_exit ))
|
26
ruma-client-api/.builds/msrv.yml
Normal file
26
ruma-client-api/.builds/msrv.yml
Normal file
@ -0,0 +1,26 @@
|
||||
image: archlinux
|
||||
packages:
|
||||
- rustup
|
||||
sources:
|
||||
- https://github.com/ruma/ruma-client-api
|
||||
tasks:
|
||||
- rustup: |
|
||||
# We specify --profile minimal because we'd otherwise download docs
|
||||
rustup toolchain install 1.40.0 --profile minimal
|
||||
rustup default 1.40.0
|
||||
- test: |
|
||||
cd ruma-client-api
|
||||
|
||||
# We don't want the build to stop on individual failure of independent
|
||||
# tools, so capture tool exit codes and set the task exit code manually
|
||||
set +e
|
||||
|
||||
# Only make sure the code builds with the MSRV. Tests can require later
|
||||
# Rust versions, don't compile or run them.
|
||||
cargo build --no-default-features --verbose
|
||||
build1_exit=$?
|
||||
|
||||
cargo build --all-features --verbose
|
||||
build2_exit=$?
|
||||
|
||||
exit $(( $build1_exit || $build2_exit ))
|
32
ruma-client-api/.builds/nightly.yml
Normal file
32
ruma-client-api/.builds/nightly.yml
Normal file
@ -0,0 +1,32 @@
|
||||
image: archlinux
|
||||
packages:
|
||||
- rustup
|
||||
sources:
|
||||
- https://github.com/ruma/ruma-client-api
|
||||
tasks:
|
||||
- rustup: |
|
||||
rustup toolchain install nightly --profile minimal
|
||||
rustup default nightly
|
||||
|
||||
# Try installing rustfmt & clippy for nightly, but don't fail the build
|
||||
# if they are not available
|
||||
rustup component add rustfmt || true
|
||||
rustup component add clippy || true
|
||||
- test: |
|
||||
cd ruma-client-api
|
||||
|
||||
# We don't want the build to stop on individual failure of independent
|
||||
# tools, so capture tool exit codes and set the task exit code manually
|
||||
set +e
|
||||
|
||||
if ( rustup component list | grep -q rustfmt ); then
|
||||
cargo fmt -- --check
|
||||
fi
|
||||
fmt_exit=$?
|
||||
|
||||
if ( rustup component list | grep -q clippy ); then
|
||||
cargo clippy --all-targets --all-features -- -D warnings
|
||||
fi
|
||||
clippy_exit=$?
|
||||
|
||||
exit $(( $fmt_exit || $clippy_exit ))
|
32
ruma-client-api/.builds/stable.yml
Normal file
32
ruma-client-api/.builds/stable.yml
Normal file
@ -0,0 +1,32 @@
|
||||
image: archlinux
|
||||
packages:
|
||||
- rustup
|
||||
sources:
|
||||
- https://github.com/ruma/ruma-client-api
|
||||
tasks:
|
||||
- rustup: |
|
||||
# We specify --profile minimal because we'd otherwise download docs
|
||||
rustup toolchain install stable --profile minimal -c rustfmt -c clippy
|
||||
rustup default stable
|
||||
- test: |
|
||||
cd ruma-client-api
|
||||
|
||||
# We don't want the build to stop on individual failure of independent
|
||||
# tools, so capture tool exit codes and set the task exit code manually
|
||||
set +e
|
||||
|
||||
cargo fmt -- --check
|
||||
fmt_exit=$?
|
||||
|
||||
cargo clippy --all-targets --all-features -- -D warnings
|
||||
clippy_exit=$?
|
||||
|
||||
cargo test --no-default-features --verbose
|
||||
test1_exit=$?
|
||||
|
||||
cargo test --all-features --verbose
|
||||
test2_exit=$?
|
||||
|
||||
exit $(( $fmt_exit || $clippy_exit || $test1_exit || $test2_exit ))
|
||||
# TODO: Add audit task once cargo-audit binary releases are available.
|
||||
# See https://github.com/RustSec/cargo-audit/issues/66
|
2
ruma-client-api/.gitignore
vendored
Normal file
2
ruma-client-api/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
Cargo.lock
|
||||
target
|
202
ruma-client-api/CHANGELOG.md
Normal file
202
ruma-client-api/CHANGELOG.md
Normal file
@ -0,0 +1,202 @@
|
||||
# [unreleased]
|
||||
|
||||
Breaking changes:
|
||||
|
||||
* Make `avatar_url` in `r0::profile::set_avatar_url::Request` an `Option`
|
||||
* Update type of `canonical_alias` in `r0::directory::PublicRoomsChunk` from
|
||||
`Option<String>` to `Option<RoomAliasId>`
|
||||
* Update `r0::room::create_room::CreationContent`
|
||||
* Change `federated`s type from `Option<bool>` to `bool`
|
||||
* Add `predecessor` field
|
||||
* Update `r0::push::get_pushrules_all` and `r0::push::get_pushrules_global_scope` to use the
|
||||
`Ruleset` type from `ruma_events`
|
||||
* Fix event types in `r0::context::get_context`
|
||||
|
||||
Improvements:
|
||||
|
||||
* Add method `into_event_content` for `r0::room::create_room::CreationContent`
|
||||
* Add room visibility endpoints: `r0::directory::{get_room_visibility, set_room_visibility}`.
|
||||
|
||||
Deprecations:
|
||||
|
||||
* `r0::sync::sync_events::SetPresence` has been renamed to `PresenceState`. It is still available
|
||||
under its previous name, but only for one release.
|
||||
|
||||
# 0.9.0
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Fix (de)serialization for `r0::media::get_content_thumnail::Response`
|
||||
* Make `r0::device::get_devices::Response::devices` public
|
||||
|
||||
Breaking changes:
|
||||
|
||||
* The `event_id` in the response for the message and state sending endpoints is now required
|
||||
* r0.6.0 doesn't say they are required, but this has been fixed for the next version of the spec
|
||||
* Updated the type of `r0::sync::sync_events::DeviceLists` fields
|
||||
* Change `r0::device::Device` fields according to the spec
|
||||
|
||||
Improvements:
|
||||
|
||||
* `r0::keys::AlgorithmAndDeviceId` now implements `Display`
|
||||
|
||||
# 0.8.0
|
||||
|
||||
Breaking changes:
|
||||
|
||||
* Update all endpoints to r0.6.0
|
||||
* Some of the changes from that might not be listed below, but it should be
|
||||
easy to figure out what changed from the documentation and compiler errors
|
||||
if you are using any of the affected endpoints.
|
||||
* Add `server_name` parameter to `r0::join::join_room_by_id_or_alias`
|
||||
* Modify `r0::account::AuthenticationData`:
|
||||
* Rename to `AuthData`
|
||||
* Change to an enum to facilitate fallback auth acknowledgements
|
||||
* Add `auth_parameters` field
|
||||
* Move to `r0::uiaa` module
|
||||
* Add `room_network` parameter to `r0::directory::get_public_rooms_filtered` to
|
||||
represent `include_all_networks` and `third_party_instance_id` Matrix fields
|
||||
* Update `r0::account::register` endpoint:
|
||||
* Remove `bind_email` request field (removed in r0.6.0)
|
||||
* Remove `inhibit_login` request field, make `access_token` and `device_id` response fields optional (added in r0.4.0)
|
||||
* Remove deprecated `home_server` response field (removed in r0.4.0)
|
||||
* Update `r0::contact::get_contacts` endpoint to r0.6.0
|
||||
* Change `UInt` timestamps to `SystemTime` in:
|
||||
* `media::get_media_preview::Request`
|
||||
* `push::get_notifications::Notification`
|
||||
* `server::get_user_info::ConnectionInfo`
|
||||
* `device::Device`
|
||||
* Change all usages of `HashMap` to `BTreeMap`
|
||||
* Change the messages type that gets sent out using the `r0::client_exchange::send_event_to_device`
|
||||
request.
|
||||
* Add `M_USER_DEACTIVATED` to `error::ErrorKind`
|
||||
* Make `display_name` field of `r0::membership::joined_events::RoomMember` optional
|
||||
* Update `r0::search::search_events` to r0.6.0
|
||||
* Add `account_data` field to `r0::sync::sync_events`
|
||||
* Rename `r0::client_exchange` to `r0::to_device`
|
||||
|
||||
Improvements:
|
||||
|
||||
* Add types for User-Interactive Authentication API: `r0::uiaa::{AuthFlow, UiaaInfo, UiaaResponse}`
|
||||
* Add missing serde attributes to `get_content_thumbnail` query parameters
|
||||
* Add missing `state` response field to `r0::message::get_message_events`
|
||||
* Normalize `serde_json` imports
|
||||
* Remove dependeny on the `url` crate
|
||||
|
||||
# 0.7.2
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Fix `create_room` requests without an `initial_state` field failing deserialization
|
||||
* Fix `sync_events` responses without a `device_one_time_keys_count` field failing deserialization
|
||||
|
||||
# 0.7.1
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Fix deserialization of `sync_events::Request`
|
||||
* Fix (de)serialization of `sync_events::RoomSummary`
|
||||
|
||||
# 0.7.0
|
||||
|
||||
Breaking changes:
|
||||
|
||||
* Update ruma-api to 0.15.0
|
||||
* Update ruma-events to 0.18.0
|
||||
* Fix `r0::session::get_login_types`
|
||||
* Add `allow_remote` parameter to `r0::media::get_content`
|
||||
* Add missing parameters for `r0::room::create_room`
|
||||
* Moved `r0::room::create_room::Invite3pid` to `r0::membership::Invite3pid`
|
||||
* Replaced `user_id` parameter of `r0::membership::invite_user` with `recipient`
|
||||
to allow invitation of users by either Matrix or third party identifiers.
|
||||
* Remove deprecated endpoint `r0::contact::create_contact` (deprecated in r0.6.0)
|
||||
* Add lazy-loading options to `r0::filter::RoomEventFilter` (introduced in r0.5.0)
|
||||
* Change type for `limit` request parameter of `r0::context::get_context` from `u8` to `Option<js_int::UInt>`
|
||||
* Use `std::time::Duration` for appropriate fields on several endpoints:
|
||||
```
|
||||
r0::{
|
||||
account::request_openid_token,
|
||||
keys::{claim_keys, get_keys},
|
||||
presence::get_presence,
|
||||
sync::sync_events,
|
||||
typing::create_typing_event,
|
||||
voip::get_turn_server_info
|
||||
}
|
||||
```
|
||||
|
||||
Improvements:
|
||||
|
||||
* Add an `Error` type that represents the well-known errors in the client-server API
|
||||
* the response deserialization code will try to create an instance of this type from http responses that indicate an error
|
||||
* Add OpenID token request endpoint.
|
||||
* Add `r0::client_exchange::send_event_to_device` (introduced in r0.3.0)
|
||||
* Add endpoints to retrieve account_data (introduced in r0.5.0)
|
||||
* Add media endpoints: `r0::media::{get_media_config, get_media_preview, get_content_as_filename}`
|
||||
* Add `unstable_features` to `unversioned::get_supported_versions` (introduced in r0.5.0)
|
||||
* Add request and response parameters for `r0::account::deactivate`
|
||||
* Add `r0::session::sso_login` (introduced in r0.5.0)
|
||||
* Add `filter` type for `r0::context::get_context`
|
||||
|
||||
# 0.6.0
|
||||
|
||||
Breaking changes:
|
||||
|
||||
* Update ruma-api to 0.13.0
|
||||
* Our Minimum Supported Rust Version is now 1.40.0
|
||||
* Remove presence list endpoints `r0::presence::{get_subscribed_presences, update_presence_subscriptions}` (removed in r0.5.0)
|
||||
* Refactor `r0::send` endpoints and remove module:
|
||||
* Move `r0::send::send_message_event` to `r0::message::create_message_event`
|
||||
* Move `r0::send::send_state_event_for_empty_key` to `r0::state:create_state_event_for_empty_key`
|
||||
* Move `r0::send::send_state_event_for_key` to `r0::state:create_state_event_for_key`
|
||||
* Refactor `r0::sync` endpoints:
|
||||
* Move `r0::sync::get_member_events` to `r0::membership::get_member_events`
|
||||
* Move `r0::sync::get_message_events` to `r0::message::get_message_events`
|
||||
* Move `r0::sync::get_state_events` to `r0::state::get_state_events`
|
||||
* Move `r0::sync::get_state_events_for_empty_key` to `r0::state::get_state_events_for_empty_key`
|
||||
* Move `r0::sync::get_state_events_for_key` to `r0::state::get_state_events_for_key`
|
||||
* Update endpoints for requesting account management tokens via email:
|
||||
* Move `r0::account::request_password_change_token` to `r0::account::request_password_change_token_via_email`
|
||||
* Move `r0::account::request_register_token` to `r0::account::request_registration_token_via_email`
|
||||
* Modify `r0::account::request_registration_token_via_email` not to be rate-limited and require authentication
|
||||
* Merge duplicate enums `r0::contact::get_contact::Medium` and `r0::session::login::Medium` and move them to `r0::thirdparty`
|
||||
|
||||
Improvements:
|
||||
|
||||
* Add `r0::device` endpoints
|
||||
* Add `r0::room::get_room_event` (introduced in r0.4.0)
|
||||
* Add `r0::read_marker::set_read_marker` (introduced in r0.4.0)
|
||||
* Add `r0::capabilities::get_capabilities` (introduced in r0.5.0)
|
||||
* Add `r0::keys` endpoints (introduced in r0.3.0)
|
||||
* Add `r0::session::get_login_types` (introduced in r0.4.0)
|
||||
* Add `r0::account::get_username_availability` (introduced in r0.4.0)
|
||||
* Add endpoints to request management tokens (introduced upstream in r0.4.0):
|
||||
* `r0::account::request_3pid_management_token_via_msisdn`
|
||||
* `r0::account::request_password_change_token_via_msisdn`
|
||||
* `r0::account::request_registration_token_via_msisdn`
|
||||
* `r0::acount::request_3pid_management_token_via_email`
|
||||
* Update `r0::presence_get_presence` from r0.4.0 to r0.6.0
|
||||
* Add `r0::account::bind_3pid`
|
||||
* Add `r0::account::delete_3pid`
|
||||
* Add `r0::account::unbind_3pid`
|
||||
* Add `r0::push` endpoints
|
||||
* Add `r0::room::upgrade_room` (introduced upstream in r0.5.0)
|
||||
|
||||
# 0.5.0
|
||||
|
||||
Breaking changes:
|
||||
|
||||
* Our Minimum Supported Rust Version is now 1.39.0
|
||||
* Update ruma-api from 0.11.0 to 0.12.0
|
||||
* Move `r0::directory::get_public_rooms::PublicRoomsChunk` to `r0::directory::PublicRoomsChunk`
|
||||
* Move `r0::room::create_room::Visibility` to `r0::room::Visibility`
|
||||
* Move `r0::account::register::AuthenticationData` to `r0::account::AuthenticationData`
|
||||
|
||||
Improvements:
|
||||
|
||||
* Update `r0::directory::get_public_rooms` from r0.3.0 to r0.6.0
|
||||
* Add `r0::directory::get_public_rooms_filtered` (introduced upstream in r0.3.0)
|
||||
* Add `filter` optional parameter to `r0::sync::get_message_events` (introduced upstream in r0.3.0)
|
||||
* Add `r0::appservice::set_room_visibility` (part of application service extensions for the client-server API)
|
||||
* Add `contains_url` to `r0::filter::RoomEventFilter` (introduced upstream in r0.3.0)
|
||||
* Update `r0::account::change_password` from r0.3.0 to r0.6.0
|
||||
* Add optional `auth` field
|
203
ruma-client-api/CONTRIBUTING.md
Normal file
203
ruma-client-api/CONTRIBUTING.md
Normal file
@ -0,0 +1,203 @@
|
||||
Welcome! Thanks for looking into contributing to our project!
|
||||
|
||||
# Table of Contents
|
||||
|
||||
- [Looking for Help?](#looking-for-help)
|
||||
- [Documentation](#documentation)
|
||||
- [Chat Rooms](#chat-rooms)
|
||||
- [Reporting Issues](#reporting-issues)
|
||||
- [Submitting Code](#submitting-code)
|
||||
- [Coding Style](#coding-style)
|
||||
- [Modifying Endpoints](#modifying-endpoints)
|
||||
- [Submitting PRs](#submitting-prs)
|
||||
- [Where do I start?](#where-do-i-start)
|
||||
- [Testing](#testing)
|
||||
- [Contact](#contact)
|
||||
|
||||
# Looking for Help?
|
||||
|
||||
Here is a list of helpful resources you can consult:
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Matrix spec Documentation](https://matrix.org/docs/spec/client_server/latest)
|
||||
- Documentation to other Ruma modules:
|
||||
- [ruma-events](https://docs.rs/ruma-events/)
|
||||
- [ruma-api](https://docs.rs/ruma-api/)
|
||||
- [ruma-client](https://docs.rs/ruma-client/)
|
||||
|
||||
## Chat Rooms
|
||||
|
||||
- Ruma Matrix room: [#ruma:matrix.org](https://matrix.to/#/#ruma:matrix.org)
|
||||
- Matrix Developer room: [#matrix-dev:matrix.org](https://matrix.to/#/#matrix-dev:matrix.org)
|
||||
|
||||
# Reporting Issues
|
||||
|
||||
If you find any bugs, inconsistencies or other problems, feel free to submit
|
||||
a GitHub [issue](issues).
|
||||
|
||||
If you have a quick question, it may be easier to leave a message on
|
||||
[#ruma:matrix.org](https://matrix.to/#/#ruma:matrix.org).
|
||||
|
||||
Also, if you have trouble getting on board, let us know so we can help future
|
||||
contributors to the project overcome that hurdle too.
|
||||
|
||||
# Submitting Code
|
||||
|
||||
Ready to write some code? Great! Here are some guidelines to follow to
|
||||
help you on your way:
|
||||
|
||||
## Coding Style
|
||||
|
||||
### Common types
|
||||
|
||||
When writing endpoint definitions, use the following mapping from request /
|
||||
response field types listed in the specification to Rust types:
|
||||
|
||||
Specification type | Rust type
|
||||
-------------------|---------------------------------------------------------------------------------------------------------------------
|
||||
`boolean` | `bool`
|
||||
`integer` | `js_int::UInt` (unless denoted as signed, then `js_int::Int`)
|
||||
`string` | If for an identifier (e.g. user ID, room ID), use one of the types from `ruma-identifiers`. Otherwise, use `String`.
|
||||
`object` | `serde_json::Value`
|
||||
`[…]` | `Vec<…>`
|
||||
`{string: …}` | `BTreeMap<String, …>` (or `BTreeMap<SomeId, …>`)
|
||||
|
||||
### Import Formatting
|
||||
|
||||
Organize your imports into three groups separated by blank lines:
|
||||
|
||||
1. `std` imports
|
||||
1. External imports (from other crates)
|
||||
1. Local imports (`self::`, `super::`, `crate::` and things like `LocalType::*`)
|
||||
|
||||
For example,
|
||||
|
||||
```rust
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::MyType;
|
||||
```
|
||||
|
||||
Also, group imports by module. For example, do this:
|
||||
|
||||
```rust
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
convert::TryFrom,
|
||||
fmt::{self, Debug, Display, Formatter},
|
||||
};
|
||||
```
|
||||
|
||||
as opposed to:
|
||||
|
||||
```rust
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
```
|
||||
|
||||
### Serde Imports
|
||||
|
||||
When importing methods and types from `serde_json`, methods should be such as
|
||||
`serde_json::{from,to}_{slice,string,value,vec}` should be imported as
|
||||
`{from,to}_json_{slice,string,value,vec}`.
|
||||
|
||||
For example:
|
||||
|
||||
```rust
|
||||
use serde_json::{
|
||||
from_value as from_json_value,
|
||||
to_str as to_json_str,
|
||||
};
|
||||
```
|
||||
|
||||
Also, `serde_json::Value` should be imported as `JsonValue`.
|
||||
|
||||
### Code Formatting and Linting
|
||||
|
||||
Use `rustfmt` to format your code and `clippy` to lint your code. Before
|
||||
committing your changes, go ahead and run `cargo fmt` and `cargo clippy
|
||||
--all-targets --all-features` on the repository to make sure that the
|
||||
formatting and linting checks pass in CI. Note that `clippy` warnings are
|
||||
reported as errors in CI builds, so make sure to handle those before
|
||||
comitting as well. (To install the tools, run `rustup component add rustfmt
|
||||
clippy`.)
|
||||
|
||||
### Commit Messages
|
||||
|
||||
Write commit messages using the imperative mood, as if completing the sentence:
|
||||
"If applied, this commit will \_\_\_." For example, use "Fix some bug" instead
|
||||
of "Fixed some bug" or "Add a feature" instead of "Added a feature".
|
||||
|
||||
(Take a look at this
|
||||
[blog post](https://www.freecodecamp.org/news/writing-good-commit-messages-a-practical-guide/)
|
||||
for more information on writing good commit messages.)
|
||||
|
||||
## Modifying Endpoints
|
||||
|
||||
### Matrix Spec Version
|
||||
|
||||
Use the latest r0.x.x documentation when adding or modifying code. We target
|
||||
the latest minor version of the Matrix specification. (Note: We might
|
||||
reconsider this when the Client-Server API hits r1.0.0.)
|
||||
|
||||
### Endpoint Documentation Header
|
||||
|
||||
Add a comment to the top of each endpoint file that includes the path
|
||||
and a link to the documentation of the spec. You can use the latest
|
||||
version at the time of the commit. For example:
|
||||
|
||||
```rust
|
||||
//! [GET /.well-known/matrix/client](https://matrix.org/docs/spec/client_server/r0.4.0#get-well-known-matrix-client)
|
||||
```
|
||||
|
||||
### Naming Endpoints
|
||||
|
||||
When adding new endpoints, select the module that fits the purpose of the
|
||||
endpoint. When naming the endpoint itself, you can use the following
|
||||
guidelines:
|
||||
- The name should be a verb describing what the client is requesting, e.g.
|
||||
`get_some_resource`.
|
||||
- Endpoints which are basic CRUD operations should use the prefixes
|
||||
`create`, `get`, `update`, and `delete`.
|
||||
- The prefix `set` is preferred to create if the resource is a singleton.
|
||||
In other words, when there's no distinction between `create` and `update`.
|
||||
- Try to use names that are as descriptive as possible and distinct from
|
||||
other endpoints in all other modules. (For example, instead of
|
||||
`r0::room::get_event`, use `r0::room::get_room_event`).
|
||||
- If you're not sure what to name it, pick any name and we can help you
|
||||
with it.
|
||||
|
||||
### Tracking Changes
|
||||
|
||||
Add your changes to the [change log](CHANGELOG.md). If possible, try to
|
||||
find and denote the version of the spec that included the change you are
|
||||
making.
|
||||
|
||||
## Submitting PRs
|
||||
|
||||
Once you're ready to submit your code, create a pull request, and one of our
|
||||
maintainers will review it. Once your PR has passed review, a maintainer will
|
||||
merge the request and you're done! 🎉
|
||||
|
||||
## Where do I start?
|
||||
|
||||
If this is your first contribution to the project, we recommend taking a look
|
||||
at one of the [open issues][] we've marked for new contributors.
|
||||
|
||||
It may be helpful to peruse some of the documentation for `ruma-events` and
|
||||
`ruma-api` listed above for some context.
|
||||
|
||||
[open issues]: https://github.com/ruma/ruma-client-api/issues?q=is%3Aopen+is%3Aissue+label%3Aeffort%2Feasy
|
||||
|
||||
# Testing
|
||||
|
||||
Before committing, run `cargo check` to make sure that your changes can build, as well as running the formatting and linting tools [mentioned above](#code-formatting-and-linting).
|
||||
|
||||
# Contact
|
||||
|
||||
Thanks again for being a contributor! If you have any questions, join us at
|
||||
[#ruma:matrix.org](https://matrix.to/#/#ruma:matrix.org).
|
33
ruma-client-api/Cargo.toml
Normal file
33
ruma-client-api/Cargo.toml
Normal file
@ -0,0 +1,33 @@
|
||||
[package]
|
||||
authors = [
|
||||
"Jimmy Cuadra <jimmy@jimmycuadra.com>",
|
||||
"Jonas Platte <jplatte@posteo.de>",
|
||||
"Isaiah Inuwa <isaiah.inuwa@gmail.com>",
|
||||
]
|
||||
categories = ["api-bindings", "web-programming"]
|
||||
description = "Types for the endpoints in the Matrix client-server API."
|
||||
documentation = "https://docs.rs/ruma-client-api"
|
||||
homepage = "https://github.com/ruma/ruma-client-api"
|
||||
keywords = ["matrix", "chat", "messaging", "ruma"]
|
||||
license = "MIT"
|
||||
name = "ruma-client-api"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/ruma/ruma-client-api"
|
||||
version = "0.9.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
http = "0.2.1"
|
||||
js_int = { version = "0.1.5", features = ["serde"] }
|
||||
ruma-api = "0.16.1"
|
||||
ruma-common = "0.1.3"
|
||||
ruma-events = { git = "https://github.com/ruma/ruma-events", rev = "c1ee72d" }
|
||||
ruma-identifiers = "0.16.2"
|
||||
ruma-serde = "0.2.2"
|
||||
serde = { version = "1.0.111", features = ["derive"] }
|
||||
serde_json = "1.0.53"
|
||||
strum = { version = "0.18.0", features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
maplit = "1.0.2"
|
||||
matches = "0.1.8"
|
19
ruma-client-api/LICENSE
Normal file
19
ruma-client-api/LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2016 Jimmy Cuadra
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
17
ruma-client-api/README.md
Normal file
17
ruma-client-api/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# ruma-client-api
|
||||
|
||||
[](https://crates.io/crates/ruma-client-api)
|
||||
[](https://docs.rs/ruma-client-api/)
|
||||
[](https://travis-ci.org/ruma/ruma-client-api)
|
||||

|
||||
|
||||
**ruma-client-api** contains serializable types for the requests and responses for each endpoint in the [Matrix](https://matrix.org/) client API specification.
|
||||
These types can be shared by client and server code.
|
||||
|
||||
## Minimum Rust version
|
||||
|
||||
ruma-client-api requires Rust 1.40.0 or later.
|
||||
|
||||
## Contributing
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
245
ruma-client-api/src/error.rs
Normal file
245
ruma-client-api/src/error.rs
Normal file
@ -0,0 +1,245 @@
|
||||
//! Errors that can be sent from the homeserver.
|
||||
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use ruma_api::{error::ResponseDeserializationError, EndpointError};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{from_slice as from_json_slice, to_vec as to_json_vec};
|
||||
use strum::{AsRefStr, Display, EnumString};
|
||||
|
||||
/// An enum for the error kind. Items may contain additional information.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, AsRefStr, Display, EnumString)]
|
||||
#[serde(tag = "errcode")]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub enum ErrorKind {
|
||||
/// M_FORBIDDEN
|
||||
#[serde(rename = "M_FORBIDDEN")]
|
||||
#[strum(to_string = "M_FORBIDDEN")]
|
||||
Forbidden,
|
||||
|
||||
/// M_UNKNOWN_TOKEN
|
||||
#[serde(rename = "M_UNKNOWN_TOKEN")]
|
||||
#[strum(to_string = "M_UNKNOWN_TOKEN")]
|
||||
UnknownToken,
|
||||
|
||||
/// M_MISSING_TOKEN
|
||||
#[serde(rename = "M_MISSING_TOKEN")]
|
||||
#[strum(to_string = "M_MISSING_TOKEN")]
|
||||
MissingToken,
|
||||
|
||||
/// M_BAD_JSON
|
||||
#[serde(rename = "M_BAD_JSON")]
|
||||
#[strum(to_string = "M_BAD_JSON")]
|
||||
BadJson,
|
||||
|
||||
/// M_NOT_JSON
|
||||
#[serde(rename = "M_NOT_JSON")]
|
||||
#[strum(to_string = "M_NOT_JSON")]
|
||||
NotJson,
|
||||
|
||||
/// M_NOT_FOUND
|
||||
#[serde(rename = "M_NOT_FOUND")]
|
||||
#[strum(to_string = "M_NOT_FOUND")]
|
||||
NotFound,
|
||||
|
||||
/// M_LIMIT_EXCEEDED
|
||||
#[serde(rename = "M_LIMIT_EXCEEDED")]
|
||||
#[strum(to_string = "M_LIMIT_EXCEEDED")]
|
||||
LimitExceeded,
|
||||
|
||||
/// M_UNKNOWN
|
||||
#[serde(rename = "M_UNKNOWN")]
|
||||
#[strum(to_string = "M_UNKNOWN")]
|
||||
Unknown,
|
||||
|
||||
/// M_UNRECOGNIZED
|
||||
#[serde(rename = "M_UNRECOGNIZED")]
|
||||
#[strum(to_string = "M_UNRECOGNIZED")]
|
||||
Unrecognized,
|
||||
|
||||
/// M_UNAUTHORIZED
|
||||
#[serde(rename = "M_UNAUTHORIZED")]
|
||||
#[strum(to_string = "M_UNAUTHORIZED")]
|
||||
Unauthorized,
|
||||
|
||||
/// M_USER_DEACTIVATED
|
||||
#[serde(rename = "M_USER_DEACTIVATED")]
|
||||
#[strum(to_string = "M_USER_DEACTIVATED")]
|
||||
UserDeactivated,
|
||||
|
||||
/// M_USER_IN_USE
|
||||
#[serde(rename = "M_USER_IN_USE")]
|
||||
#[strum(to_string = "M_USER_IN_USE")]
|
||||
UserInUse,
|
||||
|
||||
/// M_INVALID_USERNAME
|
||||
#[serde(rename = "M_INVALID_USERNAME")]
|
||||
#[strum(to_string = "M_INVALID_USERNAME")]
|
||||
InvalidUsername,
|
||||
|
||||
/// M_ROOM_IN_USE
|
||||
#[serde(rename = "M_ROOM_IN_USE")]
|
||||
#[strum(to_string = "M_ROOM_IN_USE")]
|
||||
RoomInUse,
|
||||
|
||||
/// M_INVALID_ROOM_STATE
|
||||
#[serde(rename = "M_INVALID_ROOM_STATE")]
|
||||
#[strum(to_string = "M_INVALID_ROOM_STATE")]
|
||||
InvalidRoomState,
|
||||
|
||||
/// M_THREEPID_IN_USE
|
||||
#[serde(rename = "M_THREEPID_IN_USE")]
|
||||
#[strum(to_string = "M_THREEPID_IN_USE")]
|
||||
ThreepidInUse,
|
||||
|
||||
/// M_THREEPID_NOT_FOUND
|
||||
#[serde(rename = "M_THREEPID_NOT_FOUND")]
|
||||
#[strum(to_string = "M_THREEPID_NOT_FOUND")]
|
||||
ThreepidNotFound,
|
||||
|
||||
/// M_THREEPID_AUTH_FAILED
|
||||
#[serde(rename = "M_THREEPID_AUTH_FAILED")]
|
||||
#[strum(to_string = "M_THREEPID_AUTH_FAILED")]
|
||||
ThreepidAuthFailed,
|
||||
|
||||
/// M_THREEPID_DENIED
|
||||
#[serde(rename = "M_THREEPID_DENIED")]
|
||||
#[strum(to_string = "M_THREEPID_DENIED")]
|
||||
ThreepidDenied,
|
||||
|
||||
/// M_SERVER_NOT_TRUSTED
|
||||
#[serde(rename = "M_SERVER_NOT_TRUSTED")]
|
||||
#[strum(to_string = "M_SERVER_NOT_TRUSTED")]
|
||||
ServerNotTrusted,
|
||||
|
||||
/// M_UNSUPPORTED_ROOM_VERSION
|
||||
#[serde(rename = "M_UNSUPPORTED_ROOM_VERSION")]
|
||||
#[strum(to_string = "M_UNSUPPORTED_ROOM_VERSION")]
|
||||
UnsupportedRoomVersion,
|
||||
|
||||
/// M_INCOMPATIBLE_ROOM_VERSION
|
||||
#[serde(rename = "M_INCOMPATIBLE_ROOM_VERSION")]
|
||||
#[strum(to_string = "M_INCOMPATIBLE_ROOM_VERSION")]
|
||||
IncompatibleRoomVersion,
|
||||
|
||||
/// M_BAD_STATE
|
||||
#[serde(rename = "M_BAD_STATE")]
|
||||
#[strum(to_string = "M_BAD_STATE")]
|
||||
BadState,
|
||||
|
||||
/// M_GUEST_ACCESS_FORBIDDEN
|
||||
#[serde(rename = "M_GUEST_ACCESS_FORBIDDEN")]
|
||||
#[strum(to_string = "M_GUEST_ACCESS_FORBIDDEN")]
|
||||
GuestAccessForbidden,
|
||||
|
||||
/// M_CAPTCHA_NEEDED
|
||||
#[serde(rename = "M_CAPTCHA_NEEDED")]
|
||||
#[strum(to_string = "M_CAPTCHA_NEEDED")]
|
||||
CaptchaNeeded,
|
||||
|
||||
/// M_CAPTCHA_INVALID
|
||||
#[serde(rename = "M_CAPTCHA_INVALID")]
|
||||
#[strum(to_string = "M_CAPTCHA_INVALID")]
|
||||
CaptchaInvalid,
|
||||
|
||||
/// M_MISSING_PARAM
|
||||
#[serde(rename = "M_MISSING_PARAM")]
|
||||
#[strum(to_string = "M_MISSING_PARAM")]
|
||||
MissingParam,
|
||||
|
||||
/// M_INVALID_PARAM
|
||||
#[serde(rename = "M_INVALID_PARAM")]
|
||||
#[strum(to_string = "M_INVALID_PARAM")]
|
||||
InvalidParam,
|
||||
|
||||
/// M_TOO_LARGE
|
||||
#[serde(rename = "M_TOO_LARGE")]
|
||||
#[strum(to_string = "M_TOO_LARGE")]
|
||||
TooLarge,
|
||||
|
||||
/// M_EXCLUSIVE
|
||||
#[serde(rename = "M_EXCLUSIVE")]
|
||||
#[strum(to_string = "M_EXCLUSIVE")]
|
||||
Exclusive,
|
||||
}
|
||||
|
||||
/// A Matrix Error without a status code
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub struct ErrorBody {
|
||||
/// A value which can be used to handle an error message
|
||||
#[serde(flatten)]
|
||||
pub kind: ErrorKind,
|
||||
|
||||
/// A human-readable error message, usually a sentence explaining what went wrong.
|
||||
#[serde(rename = "error")]
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
/// A Matrix Error
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Error {
|
||||
/// A value which can be used to handle an error message
|
||||
pub kind: ErrorKind,
|
||||
|
||||
/// A human-readable error message, usually a sentence explaining what went wrong.
|
||||
pub message: String,
|
||||
|
||||
/// The http status code
|
||||
pub status_code: http::StatusCode,
|
||||
}
|
||||
|
||||
impl EndpointError for Error {
|
||||
fn try_from_response(
|
||||
response: http::Response<Vec<u8>>,
|
||||
) -> Result<Self, ResponseDeserializationError> {
|
||||
match from_json_slice::<ErrorBody>(response.body()) {
|
||||
Ok(error_body) => Ok(error_body.into_error(response.status())),
|
||||
Err(de_error) => Err(ResponseDeserializationError::new(de_error, response)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"[{} / {}] {}",
|
||||
self.status_code.as_u16(),
|
||||
self.kind,
|
||||
self.message
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
impl From<Error> for ErrorBody {
|
||||
fn from(error: Error) -> Self {
|
||||
Self {
|
||||
kind: error.kind,
|
||||
message: error.message,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorBody {
|
||||
/// Convert the ErrorBody into an Error by adding the http status code.
|
||||
pub fn into_error(self, status_code: http::StatusCode) -> Error {
|
||||
Error {
|
||||
kind: self.kind,
|
||||
message: self.message,
|
||||
status_code,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for http::Response<Vec<u8>> {
|
||||
fn from(error: Error) -> http::Response<Vec<u8>> {
|
||||
http::Response::builder()
|
||||
.header(http::header::CONTENT_TYPE, "application/json")
|
||||
.status(error.status_code)
|
||||
.body(to_json_vec(&ErrorBody::from(error)).unwrap())
|
||||
.unwrap()
|
||||
}
|
||||
}
|
15
ruma-client-api/src/lib.rs
Normal file
15
ruma-client-api/src/lib.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//! Crate ruma_client_api contains serializable types for the requests and responses for each
|
||||
//! endpoint in the [Matrix](https://matrix.org/) client API specification. These types can be
|
||||
//! shared by client and server code.
|
||||
|
||||
#![deny(
|
||||
missing_copy_implementations,
|
||||
missing_debug_implementations,
|
||||
missing_docs
|
||||
)]
|
||||
|
||||
pub mod error;
|
||||
pub mod r0;
|
||||
pub mod unversioned;
|
||||
|
||||
pub use error::Error;
|
35
ruma-client-api/src/r0.rs
Normal file
35
ruma-client-api/src/r0.rs
Normal file
@ -0,0 +1,35 @@
|
||||
//! Endpoints for the r0.x.x versions of the client API specification.
|
||||
|
||||
pub mod account;
|
||||
pub mod alias;
|
||||
pub mod appservice;
|
||||
pub mod capabilities;
|
||||
pub mod config;
|
||||
pub mod contact;
|
||||
pub mod context;
|
||||
pub mod device;
|
||||
pub mod directory;
|
||||
pub mod filter;
|
||||
pub mod keys;
|
||||
pub mod media;
|
||||
pub mod membership;
|
||||
pub mod message;
|
||||
pub mod presence;
|
||||
pub mod profile;
|
||||
pub mod push;
|
||||
pub mod read_marker;
|
||||
pub mod receipt;
|
||||
pub mod redact;
|
||||
pub mod room;
|
||||
pub mod search;
|
||||
pub mod server;
|
||||
pub mod session;
|
||||
pub mod state;
|
||||
pub mod sync;
|
||||
pub mod tag;
|
||||
pub mod thirdparty;
|
||||
pub mod to_device;
|
||||
pub mod typing;
|
||||
pub mod uiaa;
|
||||
pub mod user_directory;
|
||||
pub mod voip;
|
43
ruma-client-api/src/r0/account.rs
Normal file
43
ruma-client-api/src/r0/account.rs
Normal file
@ -0,0 +1,43 @@
|
||||
//! Endpoints for account registration and management.
|
||||
|
||||
pub mod bind_3pid;
|
||||
pub mod change_password;
|
||||
pub mod deactivate;
|
||||
pub mod delete_3pid;
|
||||
pub mod get_username_availability;
|
||||
pub mod register;
|
||||
pub mod request_3pid_management_token_via_email;
|
||||
pub mod request_3pid_management_token_via_msisdn;
|
||||
pub mod request_openid_token;
|
||||
pub mod request_password_change_token_via_email;
|
||||
pub mod request_password_change_token_via_msisdn;
|
||||
pub mod request_registration_token_via_email;
|
||||
pub mod request_registration_token_via_msisdn;
|
||||
pub mod unbind_3pid;
|
||||
|
||||
pub mod whoami;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Additional authentication information for requestToken endpoints.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct IdentityServerInfo {
|
||||
/// The ID server to send the onward request to as a hostname with an
|
||||
/// appended colon and port number if the port is not the default.
|
||||
pub id_server: String,
|
||||
|
||||
/// Access token previously registered with identity server.
|
||||
pub id_access_token: String,
|
||||
}
|
||||
|
||||
/// Possible values for deleting or unbinding 3PIDs
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum ThirdPartyIdRemovalStatus {
|
||||
/// Either the homeserver couldn't determine the right identity server to contact, or the
|
||||
/// identity server refused the operation.
|
||||
NoSupport,
|
||||
|
||||
/// Success.
|
||||
Success,
|
||||
}
|
32
ruma-client-api/src/r0/account/add_3pid.rs
Normal file
32
ruma-client-api/src/r0/account/add_3pid.rs
Normal file
@ -0,0 +1,32 @@
|
||||
//! [POST /_matrix/client/r0/account/3pid/add](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-add)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Add contact information to a user's account",
|
||||
method: POST,
|
||||
name: "add_3pid",
|
||||
path: "/_matrix/client/r0/account/3pid/add",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Additional information for the User-Interactive Authentication API.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auth: Option<AuthData>,
|
||||
|
||||
/// Client-generated secret string used to protect this session.
|
||||
pub client_secret: String,
|
||||
|
||||
/// The session identifier given by the identity server.
|
||||
pub sid: String,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: UiaaResponse
|
||||
}
|
33
ruma-client-api/src/r0/account/bind_3pid.rs
Normal file
33
ruma-client-api/src/r0/account/bind_3pid.rs
Normal file
@ -0,0 +1,33 @@
|
||||
//! [POST /_matrix/client/r0/account/3pid/bind](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-bind)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::IdentityServerInfo;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Bind a 3PID to a user's account on an identity server",
|
||||
method: POST,
|
||||
name: "bind_3pid",
|
||||
path: "/_matrix/client/r0/account/3pid/bind",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Client-generated secret string used to protect this session.
|
||||
pub client_secret: String,
|
||||
|
||||
/// The ID server to send the onward request to as a hostname with an
|
||||
/// appended colon and port number if the port is not the default.
|
||||
#[serde(flatten)]
|
||||
pub identity_server_info: IdentityServerInfo,
|
||||
|
||||
/// The session identifier given by the identity server.
|
||||
pub sid: String,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
28
ruma-client-api/src/r0/account/change_password.rs
Normal file
28
ruma-client-api/src/r0/account/change_password.rs
Normal file
@ -0,0 +1,28 @@
|
||||
//! [POST /_matrix/client/r0/account/password](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Change the password of the current user's account.",
|
||||
method: POST,
|
||||
name: "change_password",
|
||||
path: "/_matrix/client/r0/account/password",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The new password for the account.
|
||||
pub new_password: String,
|
||||
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
pub auth: Option<AuthData>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: UiaaResponse
|
||||
}
|
36
ruma-client-api/src/r0/account/deactivate.rs
Normal file
36
ruma-client-api/src/r0/account/deactivate.rs
Normal file
@ -0,0 +1,36 @@
|
||||
//! [POST /_matrix/client/r0/account/deactivate](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-deactivate)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
use super::ThirdPartyIdRemovalStatus;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Deactivate the current user's account.",
|
||||
method: POST,
|
||||
name: "deactivate",
|
||||
path: "/_matrix/client/r0/account/deactivate",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auth: Option<AuthData>,
|
||||
|
||||
/// Identity server from which to unbind the user's third party
|
||||
/// identifier.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub id_server: Option<String>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// Result of unbind operation.
|
||||
pub id_server_unbind_result: ThirdPartyIdRemovalStatus,
|
||||
}
|
||||
|
||||
error: UiaaResponse
|
||||
}
|
37
ruma-client-api/src/r0/account/delete_3pid.rs
Normal file
37
ruma-client-api/src/r0/account/delete_3pid.rs
Normal file
@ -0,0 +1,37 @@
|
||||
//! [POST /_matrix/client/r0/account/3pid/delete](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-delete)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::ThirdPartyIdRemovalStatus;
|
||||
use crate::r0::thirdparty::Medium;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Delete a 3PID from a user's account on an identity server.",
|
||||
method: POST,
|
||||
name: "delete_3pid",
|
||||
path: "/_matrix/client/r0/account/3pid/delete",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Identity server to delete from.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub id_server: Option<String>,
|
||||
|
||||
/// Medium of the 3PID to be removed.
|
||||
pub medium: Medium,
|
||||
|
||||
/// Third-party address being removed.
|
||||
pub address: String,
|
||||
}
|
||||
|
||||
response {
|
||||
/// Result of unbind operation.
|
||||
pub id_server_unbind_result: ThirdPartyIdRemovalStatus,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
|
||||
}
|
28
ruma-client-api/src/r0/account/get_username_availability.rs
Normal file
28
ruma-client-api/src/r0/account/get_username_availability.rs
Normal file
@ -0,0 +1,28 @@
|
||||
//! [GET /_matrix/client/r0/register/available](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-register-available)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Checks to see if a username is available, and valid, for the server.",
|
||||
method: GET,
|
||||
name: "get_username_availability",
|
||||
path: "/_matrix/client/r0/register/available",
|
||||
rate_limited: true,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The username to check the availability of.
|
||||
#[ruma_api(query)]
|
||||
pub username: String,
|
||||
}
|
||||
|
||||
response {
|
||||
/// A flag to indicate that the username is available.
|
||||
/// This should always be true when the server replies with 200 OK.
|
||||
pub available: bool
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
98
ruma-client-api/src/r0/account/register.rs
Normal file
98
ruma-client-api/src/r0/account/register.rs
Normal file
@ -0,0 +1,98 @@
|
||||
//! [POST /_matrix/client/r0/register](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{DeviceId, UserId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Register an account on this homeserver.",
|
||||
method: POST,
|
||||
name: "register",
|
||||
path: "/_matrix/client/r0/register",
|
||||
rate_limited: true,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The desired password for the account.
|
||||
///
|
||||
/// May be empty for accounts that should not be able to log in again
|
||||
/// with a password, e.g., for guest or application service accounts.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub password: Option<String>,
|
||||
|
||||
/// local part of the desired Matrix ID.
|
||||
///
|
||||
/// If omitted, the homeserver MUST generate a Matrix ID local part.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub username: Option<String>,
|
||||
|
||||
/// ID of the client device.
|
||||
///
|
||||
/// If this does not correspond to a known client device, a new device will be created.
|
||||
/// The server will auto-generate a device_id if this is not specified.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub device_id: Option<DeviceId>,
|
||||
|
||||
/// A display name to assign to the newly-created device.
|
||||
///
|
||||
/// Ignored if `device_id` corresponds to a known device.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub initial_device_display_name: Option<String>,
|
||||
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
///
|
||||
/// Note that this information is not used to define how the registered user should be
|
||||
/// authenticated, but is instead used to authenticate the register call itself.
|
||||
/// It should be left empty, or omitted, unless an earlier call returned an response
|
||||
/// with status code 401.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auth: Option<AuthData>,
|
||||
|
||||
/// Kind of account to register
|
||||
///
|
||||
/// Defaults to `User` if omitted.
|
||||
#[ruma_api(query)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub kind: Option<RegistrationKind>,
|
||||
|
||||
/// If `true`, an `access_token` and `device_id` should not be returned
|
||||
/// from this call, therefore preventing an automatic login.
|
||||
#[serde(default, skip_serializing_if = "ruma_serde::is_default")]
|
||||
pub inhibit_login: bool,
|
||||
}
|
||||
|
||||
response {
|
||||
/// An access token for the account.
|
||||
///
|
||||
/// This access token can then be used to authorize other requests.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub access_token: Option<String>,
|
||||
|
||||
/// The fully-qualified Matrix ID that has been registered.
|
||||
pub user_id: UserId,
|
||||
|
||||
/// ID of the registered device.
|
||||
///
|
||||
/// Will be the same as the corresponding parameter in the request, if one was specified.
|
||||
pub device_id: Option<DeviceId>,
|
||||
}
|
||||
|
||||
error: UiaaResponse
|
||||
}
|
||||
|
||||
/// The kind of account being registered.
|
||||
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum RegistrationKind {
|
||||
/// A guest account
|
||||
///
|
||||
/// These accounts may have limited permissions and may not be supported by all servers.
|
||||
Guest,
|
||||
|
||||
/// A regular user account
|
||||
User,
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
//! [POST /_matrix/client/r0/account/3pid/email/requestToken](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-email-requesttoken)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::IdentityServerInfo;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Request a 3PID management token with a 3rd party email.",
|
||||
method: POST,
|
||||
name: "request_3pid_association_token_via_email",
|
||||
path: "/_matrix/client/r0/account/3pid/email/requestToken",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Client-generated secret string used to protect this session.
|
||||
pub client_secret: String,
|
||||
|
||||
/// The email address.
|
||||
pub email: String,
|
||||
|
||||
/// Used to distinguish protocol level retries from requests to re-send the email.
|
||||
pub send_attempt: UInt,
|
||||
|
||||
/// Return URL for identity server to redirect the client back to.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next_link: Option<String>,
|
||||
|
||||
/// Optional identity server hostname and access token. Deprecated since r0.6.0.
|
||||
#[serde(flatten)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub identity_server_info: Option<IdentityServerInfo>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The session identifier given by the identity server.
|
||||
pub sid: String,
|
||||
|
||||
/// URL to submit validation token to. If omitted, verification happens without client.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub submit_url: Option<String>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
//! [POST /_matrix/client/r0/account/3pid/msisdn/requestToken](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-msisdn-requesttoken)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::IdentityServerInfo;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Request a 3PID management token with a phone number.",
|
||||
method: POST,
|
||||
name: "request_3pid_association_token_via_msisdn",
|
||||
path: "/_matrix/client/r0/account/3pid/msisdn/requestToken",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Client-generated secret string used to protect this session.
|
||||
pub client_secret: String,
|
||||
|
||||
/// Two-letter ISO 3166 country code for the phone number.
|
||||
pub country: String,
|
||||
|
||||
/// Phone number to validate.
|
||||
pub phone_number: String,
|
||||
|
||||
/// Used to distinguish protocol level retries from requests to re-send the SMS.
|
||||
pub send_attempt: UInt,
|
||||
|
||||
/// Return URL for identity server to redirect the client back to.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next_link: Option<String>,
|
||||
|
||||
/// Optional identity server hostname and access token. Deprecated since r0.6.0.
|
||||
#[serde(flatten)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub identity_server_info: Option<IdentityServerInfo>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The session identifier given by the identity server.
|
||||
pub sid: String,
|
||||
|
||||
/// URL to submit validation token to. If omitted, verification happens without client.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub submit_url: Option<String>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
48
ruma-client-api/src/r0/account/request_openid_token.rs
Normal file
48
ruma-client-api/src/r0/account/request_openid_token.rs
Normal file
@ -0,0 +1,48 @@
|
||||
//! [POST /_matrix/client/r0/user/{userId}/openid/request_token](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-user-userid-openid-request-token)
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Request an OpenID 1.0 token to verify identity with a third party.",
|
||||
name: "request_openid_token",
|
||||
method: POST,
|
||||
path: "/_matrix/client/r0/user/:user_id/openid/request_token",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// User ID of authenticated user.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
}
|
||||
|
||||
response {
|
||||
/// Access token for verifying user's identity.
|
||||
pub access_token: String,
|
||||
|
||||
/// Access token type.
|
||||
pub token_type: TokenType,
|
||||
|
||||
/// Homeserver domain for verification of user's identity.
|
||||
pub matrix_server_name: String,
|
||||
|
||||
/// Seconds until token expiration.
|
||||
#[serde(with = "ruma_serde::duration::secs")]
|
||||
pub expires_in: Duration,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
/// Access token types.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub enum TokenType {
|
||||
/// Bearer token type
|
||||
Bearer,
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
//! [POST /_matrix/client/r0/account/password/email/requestToken](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password-email-requesttoken)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::IdentityServerInfo;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Request that a password change token is sent to the given email address.",
|
||||
method: POST,
|
||||
name: "request_password_change_token_via_email",
|
||||
path: "/_matrix/client/r0/account/password/email/requestToken",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Client-generated secret string used to protect this session.
|
||||
pub client_secret: String,
|
||||
|
||||
/// The email address.
|
||||
pub email: String,
|
||||
|
||||
/// Used to distinguish protocol level retries from requests to re-send the email.
|
||||
pub send_attempt: UInt,
|
||||
|
||||
/// Return URL for identity server to redirect the client back to.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next_link: Option<String>,
|
||||
|
||||
/// Optional identity server hostname and access token. Deprecated since r0.6.0.
|
||||
#[serde(flatten)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub identity_server_info: Option<IdentityServerInfo>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The session identifier given by the identity server.
|
||||
pub sid: String,
|
||||
|
||||
/// URL to submit validation token to. If omitted, verification happens without client.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub submit_url: Option<String>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
//! [POST /_matrix/client/r0/account/password/msisdn/requestToken](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password-msisdn-requesttoken)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Request that a password change token is sent to the given phone number.",
|
||||
method: POST,
|
||||
name: "request_password_change_token_via_msisdn",
|
||||
path: "/_matrix/client/r0/account/password/msisdn/requestToken",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Client-generated secret string used to protect this session.
|
||||
pub client_secret: String,
|
||||
|
||||
/// Two-letter ISO 3166 country code for the phone number.
|
||||
pub country: String,
|
||||
|
||||
/// Phone number to validate.
|
||||
pub phone_number: String,
|
||||
|
||||
/// Used to distinguish protocol level retries from requests to re-send the SMS.
|
||||
pub send_attempt: UInt,
|
||||
|
||||
/// Return URL for identity server to redirect the client back to.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next_link: Option<String>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The session identifier given by the identity server.
|
||||
pub sid: String,
|
||||
|
||||
/// URL to submit validation token to. If omitted, verification happens without client.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub submit_url: Option<String>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
//! [POST /_matrix/client/r0/register/email/requestToken](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register-email-requesttoken)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::IdentityServerInfo;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Request a registration token with a 3rd party email.",
|
||||
method: POST,
|
||||
name: "request_registration_token_via_email",
|
||||
path: "/_matrix/client/r0/register/email/requestToken",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Client-generated secret string used to protect this session.
|
||||
pub client_secret: String,
|
||||
|
||||
/// The email address.
|
||||
pub email: String,
|
||||
|
||||
/// Used to distinguish protocol level retries from requests to re-send the email.
|
||||
pub send_attempt: UInt,
|
||||
|
||||
/// Return URL for identity server to redirect the client back to.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next_link: Option<String>,
|
||||
|
||||
/// Optional identity server hostname and access token. Deprecated since r0.6.0.
|
||||
#[serde(flatten)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub identity_server_info: Option<IdentityServerInfo>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The session identifier given by the identity server.
|
||||
pub sid: String,
|
||||
|
||||
/// URL to submit validation token to. If omitted, verification happens without client.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub submit_url: Option<String>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
//! [POST /_matrix/client/r0/register/msisdn/requestToken](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-register-msisdn-requesttoken)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::IdentityServerInfo;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Request a registration token with a phone number.",
|
||||
method: POST,
|
||||
name: "request_registration_token_via_msisdn",
|
||||
path: "/_matrix/client/r0/register/msisdn/requestToken",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Client-generated secret string used to protect this session.
|
||||
pub client_secret: String,
|
||||
|
||||
/// Two-letter ISO 3166 country code for the phone number.
|
||||
pub country: String,
|
||||
|
||||
/// Phone number to validate.
|
||||
pub phone_number: String,
|
||||
|
||||
/// Return URL for identity server to redirect the client back to.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next_link: Option<String>,
|
||||
|
||||
/// Used to distinguish protocol level retries from requests to re-send the SMS.
|
||||
pub send_attempt: UInt,
|
||||
|
||||
/// Optional identity server hostname and access token. Deprecated since r0.6.0.
|
||||
#[serde(flatten)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub identity_server_info: Option<IdentityServerInfo>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The session identifier given by the identity server.
|
||||
pub sid: String,
|
||||
|
||||
/// URL to submit validation token to. If omitted, verification happens without client.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub submit_url: Option<String>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
36
ruma-client-api/src/r0/account/unbind_3pid.rs
Normal file
36
ruma-client-api/src/r0/account/unbind_3pid.rs
Normal file
@ -0,0 +1,36 @@
|
||||
//! [POST /_matrix/client/r0/account/3pid/unbind](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-unbind)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::ThirdPartyIdRemovalStatus;
|
||||
use crate::r0::thirdparty::Medium;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Unbind a 3PID from a user's account on an identity server.",
|
||||
method: POST,
|
||||
name: "unbind_3pid",
|
||||
path: "/_matrix/client/r0/account/3pid/unbind",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Identity server to unbind from.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub id_server: Option<String>,
|
||||
|
||||
/// Medium of the 3PID to be removed.
|
||||
pub medium: Medium,
|
||||
|
||||
/// Third-party address being removed.
|
||||
pub address: String,
|
||||
}
|
||||
|
||||
response {
|
||||
/// Result of unbind operation.
|
||||
pub id_server_unbind_result: ThirdPartyIdRemovalStatus,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
23
ruma-client-api/src/r0/account/whoami.rs
Normal file
23
ruma-client-api/src/r0/account/whoami.rs
Normal file
@ -0,0 +1,23 @@
|
||||
//! [GET /_matrix/client/r0/account/whoami](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-account-whoami)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get information about the owner of a given access token.",
|
||||
method: GET,
|
||||
name: "whoami",
|
||||
path: "/_matrix/client/r0/account/whoami",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {}
|
||||
|
||||
response {
|
||||
/// The id of the user that owns the access token.
|
||||
pub user_id: String,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
5
ruma-client-api/src/r0/alias.rs
Normal file
5
ruma-client-api/src/r0/alias.rs
Normal file
@ -0,0 +1,5 @@
|
||||
//! Endpoints for room aliases.
|
||||
|
||||
pub mod create_alias;
|
||||
pub mod delete_alias;
|
||||
pub mod get_alias;
|
28
ruma-client-api/src/r0/alias/create_alias.rs
Normal file
28
ruma-client-api/src/r0/alias/create_alias.rs
Normal file
@ -0,0 +1,28 @@
|
||||
//! [PUT /_matrix/client/r0/directory/room/{roomAlias}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-directory-room-roomalias)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{RoomAliasId, RoomId};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Add an alias to a room.",
|
||||
method: PUT,
|
||||
name: "create_alias",
|
||||
path: "/_matrix/client/r0/directory/room/:room_alias",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room alias to set.
|
||||
#[ruma_api(path)]
|
||||
pub room_alias: RoomAliasId,
|
||||
|
||||
/// The room ID to set.
|
||||
pub room_id: RoomId,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
25
ruma-client-api/src/r0/alias/delete_alias.rs
Normal file
25
ruma-client-api/src/r0/alias/delete_alias.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//! [DELETE /_matrix/client/r0/directory/room/{roomAlias}](https://matrix.org/docs/spec/client_server/r0.6.0#delete-matrix-client-r0-directory-room-roomalias)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::RoomAliasId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Remove an alias from a room.",
|
||||
method: DELETE,
|
||||
name: "delete_alias",
|
||||
path: "/_matrix/client/r0/directory/room/:room_alias",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room alias to remove.
|
||||
#[ruma_api(path)]
|
||||
pub room_alias: RoomAliasId,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
31
ruma-client-api/src/r0/alias/get_alias.rs
Normal file
31
ruma-client-api/src/r0/alias/get_alias.rs
Normal file
@ -0,0 +1,31 @@
|
||||
//! [GET /_matrix/client/r0/directory/room/{roomAlias}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-directory-room-roomalias)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{RoomAliasId, RoomId};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Resolve a room alias to a room ID.",
|
||||
method: GET,
|
||||
name: "get_alias",
|
||||
path: "/_matrix/client/r0/directory/room/:room_alias",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room alias.
|
||||
#[ruma_api(path)]
|
||||
pub room_alias: RoomAliasId,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The room ID for this room alias.
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// A list of servers that are aware of this room ID.
|
||||
pub servers: Vec<String>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
3
ruma-client-api/src/r0/appservice.rs
Normal file
3
ruma-client-api/src/r0/appservice.rs
Normal file
@ -0,0 +1,3 @@
|
||||
//! Endpoints part of the application service extension of the client-server API
|
||||
|
||||
pub mod set_room_visibility;
|
34
ruma-client-api/src/r0/appservice/set_room_visibility.rs
Normal file
34
ruma-client-api/src/r0/appservice/set_room_visibility.rs
Normal file
@ -0,0 +1,34 @@
|
||||
//! [PUT /_matrix/client/r0/directory/list/appservice/{networkId}/{roomId}](https://matrix.org/docs/spec/application_service/r0.1.2#put-matrix-client-r0-directory-list-appservice-networkid-roomid)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::RoomId;
|
||||
|
||||
use crate::r0::room::Visibility;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Updates the visibility of a given room on the application service's room directory.",
|
||||
method: PUT,
|
||||
name: "set_room_visibility",
|
||||
path: "/_matrix/client/r0/directory/list/appservice/:network_id/:room_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The protocol (network) ID to update the room list for.
|
||||
#[ruma_api(path)]
|
||||
pub network_id: String,
|
||||
|
||||
/// The room ID to add to the directory.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// Whether the room should be visible (public) in the directory or not (private).
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
3
ruma-client-api/src/r0/capabilities.rs
Normal file
3
ruma-client-api/src/r0/capabilities.rs
Normal file
@ -0,0 +1,3 @@
|
||||
//! Endpoints for querying the server's supported feature set
|
||||
|
||||
pub mod get_capabilities;
|
73
ruma-client-api/src/r0/capabilities/get_capabilities.rs
Normal file
73
ruma-client-api/src/r0/capabilities/get_capabilities.rs
Normal file
@ -0,0 +1,73 @@
|
||||
//! [GET /_matrix/client/r0/capabilities](https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-capabilities)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::RoomVersionId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Gets information about the server's supported feature set and other relevant capabilities.",
|
||||
method: GET,
|
||||
name: "get_capabilities",
|
||||
path: "/_matrix/client/r0/capabilities",
|
||||
rate_limited: true,
|
||||
requires_authentication: true
|
||||
}
|
||||
|
||||
request {}
|
||||
|
||||
response {
|
||||
/// The capabilities the server supports
|
||||
pub capabilities: Capabilities,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
/// Contains information about all the capabilities that the server supports.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Capabilities {
|
||||
/// Capability to indicate if the user can change their password.
|
||||
#[serde(rename = "m.change_password", skip_serializing_if = "Option::is_none")]
|
||||
pub change_password: Option<ChangePasswordCapability>,
|
||||
|
||||
/// The room versions the server supports.
|
||||
#[serde(rename = "m.room_versions", skip_serializing_if = "Option::is_none")]
|
||||
pub room_versions: Option<RoomVersionsCapability>,
|
||||
|
||||
/// Any other custom capabilities that the server supports outside of the specification,
|
||||
/// labeled using the Java package naming convention and stored as arbitrary JSON values.
|
||||
#[serde(flatten)]
|
||||
pub custom_capabilities: BTreeMap<String, JsonValue>,
|
||||
}
|
||||
|
||||
/// Information about the m.change_password capability
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub struct ChangePasswordCapability {
|
||||
/// True if the user can change their password, false otherwise.
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
/// Information about the m.room_versions capability
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RoomVersionsCapability {
|
||||
/// The default room version the server is using for new rooms.
|
||||
pub default: String,
|
||||
|
||||
/// A detailed description of the room versions the server supports.
|
||||
pub available: BTreeMap<RoomVersionId, RoomVersionStability>,
|
||||
}
|
||||
|
||||
/// The stability of a room version
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub enum RoomVersionStability {
|
||||
/// Support for the given version is stable.
|
||||
#[serde(rename = "stable")]
|
||||
Stable,
|
||||
|
||||
/// Support for the given version is unstable.
|
||||
#[serde(rename = "unstable")]
|
||||
Unstable,
|
||||
}
|
6
ruma-client-api/src/r0/config.rs
Normal file
6
ruma-client-api/src/r0/config.rs
Normal file
@ -0,0 +1,6 @@
|
||||
//! Endpoints for client configuration.
|
||||
|
||||
pub mod get_global_account_data;
|
||||
pub mod get_room_account_data;
|
||||
pub mod set_global_account_data;
|
||||
pub mod set_room_account_data;
|
34
ruma-client-api/src/r0/config/get_global_account_data.rs
Normal file
34
ruma-client-api/src/r0/config/get_global_account_data.rs
Normal file
@ -0,0 +1,34 @@
|
||||
//! [GET /_matrix/client/r0/user/{userId}/account_data/{type}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-user-userid-account-data-type)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_events::{collections::only, EventJson};
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Gets global account data for a user.",
|
||||
name: "get_global_account_data",
|
||||
method: GET,
|
||||
path: "/_matrix/client/r0/user/:user_id/account_data/:event_type",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// User ID of user for whom to retrieve data.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
|
||||
/// Type of data to retrieve.
|
||||
#[ruma_api(path)]
|
||||
pub event_type: String,
|
||||
}
|
||||
|
||||
response {
|
||||
/// Account data content for the given type.
|
||||
#[ruma_api(body)]
|
||||
pub account_data: EventJson<only::Event>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
38
ruma-client-api/src/r0/config/get_room_account_data.rs
Normal file
38
ruma-client-api/src/r0/config/get_room_account_data.rs
Normal file
@ -0,0 +1,38 @@
|
||||
//! [GET /_matrix/client/r0/user/{userId}/rooms/{roomId}/account_data/{type}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-user-userid-rooms-roomid-account-data-type)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_events::{collections::only, EventJson};
|
||||
use ruma_identifiers::{RoomId, UserId};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Gets account data room for a user for a given room",
|
||||
name: "get_room_account_data",
|
||||
method: GET,
|
||||
path: "/_matrix/client/r0/user/:user_id/rooms/:room_id/account_data/:event_type",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// User ID of user for whom to retrieve data.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
|
||||
/// Room ID for which to retrieve data.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// Type of data to retrieve.
|
||||
#[ruma_api(path)]
|
||||
pub event_type: String,
|
||||
}
|
||||
|
||||
response {
|
||||
/// Account data content for the given type.
|
||||
#[ruma_api(body)]
|
||||
pub account_data: EventJson<only::Event>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
40
ruma-client-api/src/r0/config/set_global_account_data.rs
Normal file
40
ruma-client-api/src/r0/config/set_global_account_data.rs
Normal file
@ -0,0 +1,40 @@
|
||||
//! [PUT /_matrix/client/r0/user/{userId}/account_data/{type}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-user-userid-account-data-type)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Sets global account data.",
|
||||
method: PUT,
|
||||
name: "set_global_account_data",
|
||||
path: "/_matrix/client/r0/user/:user_id/account_data/:event_type",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Arbitrary JSON to store as config data.
|
||||
///
|
||||
/// To create a `Box<RawJsonValue>`, use `serde_json::value::to_raw_value`.
|
||||
#[ruma_api(body)]
|
||||
pub data: Box<RawJsonValue>,
|
||||
|
||||
/// The event type of the account_data to set.
|
||||
///
|
||||
/// Custom types should be namespaced to avoid clashes.
|
||||
#[ruma_api(path)]
|
||||
pub event_type: String,
|
||||
|
||||
/// The ID of the user to set account_data for.
|
||||
///
|
||||
/// The access token must be authorized to make requests for this user ID.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
44
ruma-client-api/src/r0/config/set_room_account_data.rs
Normal file
44
ruma-client-api/src/r0/config/set_room_account_data.rs
Normal file
@ -0,0 +1,44 @@
|
||||
//! [PUT /_matrix/client/r0/user/{userId}/rooms/{roomId}/account_data/{type}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-user-userid-rooms-roomid-account-data-type)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{RoomId, UserId};
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Associate account data with a room.",
|
||||
method: PUT,
|
||||
name: "set_room_account_data",
|
||||
path: "/_matrix/client/r0/user/:user_id/rooms/:room_id/account_data/:event_type",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Arbitrary JSON to store as config data.
|
||||
///
|
||||
/// To create a `Box<RawJsonValue>`, use `serde_json::value::to_raw_value`.
|
||||
#[ruma_api(body)]
|
||||
pub data: Box<RawJsonValue>,
|
||||
|
||||
/// The event type of the account_data to set.
|
||||
///
|
||||
/// Custom types should be namespaced to avoid clashes.
|
||||
#[ruma_api(path)]
|
||||
pub event_type: String,
|
||||
|
||||
/// The ID of the room to set account_data on.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The ID of the user to set account_data for.
|
||||
///
|
||||
/// The access token must be authorized to make requests for this user ID.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
4
ruma-client-api/src/r0/contact.rs
Normal file
4
ruma-client-api/src/r0/contact.rs
Normal file
@ -0,0 +1,4 @@
|
||||
//! Endpoints for account contact information.
|
||||
|
||||
pub mod get_contacts;
|
||||
pub mod request_contact_verification_token;
|
84
ruma-client-api/src/r0/contact/get_contacts.rs
Normal file
84
ruma-client-api/src/r0/contact/get_contacts.rs
Normal file
@ -0,0 +1,84 @@
|
||||
//! [GET /_matrix/client/r0/account/3pid](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-account-3pid)
|
||||
|
||||
use std::time::SystemTime;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::r0::thirdparty::Medium;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get a list of 3rd party contacts associated with the user's account.",
|
||||
method: GET,
|
||||
name: "get_contacts",
|
||||
path: "/_matrix/client/r0/account/3pid",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {}
|
||||
|
||||
response {
|
||||
/// A list of third party identifiers the homeserver has associated with the user's
|
||||
/// account.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub threepids: Vec<ThirdPartyIdentifier>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
/// An identifier external to Matrix.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub struct ThirdPartyIdentifier {
|
||||
/// The third party identifier address.
|
||||
pub address: String,
|
||||
|
||||
/// The medium of third party identifier.
|
||||
pub medium: Medium,
|
||||
|
||||
/// The time when the identifier was validated by the identity server.
|
||||
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||
pub validated_at: SystemTime,
|
||||
|
||||
/// The time when the homeserver associated the third party identifier with the user.
|
||||
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||
pub added_at: SystemTime,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||
|
||||
use super::{Medium, ThirdPartyIdentifier};
|
||||
|
||||
#[test]
|
||||
fn third_party_identifier_serde() {
|
||||
let third_party_id = ThirdPartyIdentifier {
|
||||
address: "monkey@banana.island".into(),
|
||||
medium: Medium::Email,
|
||||
validated_at: UNIX_EPOCH + Duration::from_millis(1_535_176_800_000),
|
||||
added_at: UNIX_EPOCH + Duration::from_millis(1_535_336_848_756),
|
||||
};
|
||||
|
||||
let third_party_id_serialized = json!({
|
||||
"medium": "email",
|
||||
"address": "monkey@banana.island",
|
||||
"validated_at": 1_535_176_800_000u64,
|
||||
"added_at": 1_535_336_848_756u64
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
to_json_value(third_party_id.clone()).unwrap(),
|
||||
third_party_id_serialized
|
||||
);
|
||||
assert_eq!(
|
||||
third_party_id,
|
||||
from_json_value(third_party_id_serialized).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
//! [POST /_matrix/client/r0/account/3pid/email/requestToken](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-email-requesttoken)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Ask for a verification token for a given 3rd party ID.",
|
||||
method: POST,
|
||||
name: "request_contact_verification_token",
|
||||
path: "/_matrix/client/r0/account/3pid/email/requestToken",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Client-generated secret string used to protect this session.
|
||||
pub client_secret: String,
|
||||
|
||||
/// The email address.
|
||||
pub email: String,
|
||||
|
||||
/// A URL for the identity server to redirect the user to after
|
||||
/// validation is completed.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next_link: Option<String>,
|
||||
|
||||
/// Used to distinguish protocol level retries from requests to re-send
|
||||
/// the email.
|
||||
pub send_attempt: UInt,
|
||||
|
||||
/// The identity server to send the onward request to as a hostname with
|
||||
/// an appended colon and port number if the port is not the default.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub id_server: Option<String>,
|
||||
|
||||
/// An access token previously registered with the identity server.
|
||||
///
|
||||
/// Required if an `id_server` is supplied.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub id_access_token: Option<String>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
3
ruma-client-api/src/r0/context.rs
Normal file
3
ruma-client-api/src/r0/context.rs
Normal file
@ -0,0 +1,3 @@
|
||||
//! Endpoints for event context.
|
||||
|
||||
pub mod get_context;
|
84
ruma-client-api/src/r0/context/get_context.rs
Normal file
84
ruma-client-api/src/r0/context/get_context.rs
Normal file
@ -0,0 +1,84 @@
|
||||
//! [GET /_matrix/client/r0/rooms/{roomId}/context/{eventId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-context-eventid)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_events::{collections::all, EventJson};
|
||||
use ruma_identifiers::{EventId, RoomId};
|
||||
|
||||
use crate::r0::filter::RoomEventFilter;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get the events immediately preceding and following a given event.",
|
||||
method: GET,
|
||||
path: "/_matrix/client/r0/rooms/:room_id/context/:event_id",
|
||||
name: "get_context",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room to get events from.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The event to get context around.
|
||||
#[ruma_api(path)]
|
||||
pub event_id: EventId,
|
||||
|
||||
/// The maximum number of events to return.
|
||||
///
|
||||
/// Defaults to 10.
|
||||
#[ruma_api(query)]
|
||||
#[serde(default = "default_limit", skip_serializing_if = "is_default_limit")]
|
||||
pub limit: UInt,
|
||||
|
||||
/// A RoomEventFilter to filter returned events with.
|
||||
#[ruma_api(query)]
|
||||
#[serde(
|
||||
with = "ruma_serde::json_string",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub filter: Option<RoomEventFilter>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// A token that can be used to paginate backwards with.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub start: Option<String>,
|
||||
|
||||
/// A token that can be used to paginate forwards with.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub end: Option<String>,
|
||||
|
||||
/// A list of room events that happened just before the requested event,
|
||||
/// in reverse-chronological order.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub events_before: Vec<EventJson<all::RoomEvent>>,
|
||||
|
||||
/// Details of the requested event.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub event: Option<EventJson<all::RoomEvent>>,
|
||||
|
||||
/// A list of room events that happened just after the requested event,
|
||||
/// in chronological order.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub events_after: Vec<EventJson<all::RoomEvent>>,
|
||||
|
||||
/// The state of the room at the last event returned.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub state: Vec<EventJson<all::StateEvent>>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
fn default_limit() -> UInt {
|
||||
UInt::from(10u32)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
fn is_default_limit(val: &UInt) -> bool {
|
||||
*val == default_limit()
|
||||
}
|
33
ruma-client-api/src/r0/device.rs
Normal file
33
ruma-client-api/src/r0/device.rs
Normal file
@ -0,0 +1,33 @@
|
||||
//! Endpoints for managing devices.
|
||||
|
||||
use std::time::SystemTime;
|
||||
|
||||
use ruma_identifiers::DeviceId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod delete_device;
|
||||
pub mod delete_devices;
|
||||
pub mod get_device;
|
||||
pub mod get_devices;
|
||||
pub mod update_device;
|
||||
|
||||
/// Information about a registered device.
|
||||
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
|
||||
pub struct Device {
|
||||
/// Device ID
|
||||
pub device_id: DeviceId,
|
||||
|
||||
/// Public display name of the device.
|
||||
pub display_name: Option<String>,
|
||||
|
||||
/// Most recently seen IP address of the session.
|
||||
pub last_seen_ip: Option<String>,
|
||||
|
||||
/// Unix timestamp that the session was last active.
|
||||
#[serde(
|
||||
with = "ruma_serde::time::opt_ms_since_unix_epoch",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub last_seen_ts: Option<SystemTime>,
|
||||
}
|
31
ruma-client-api/src/r0/device/delete_device.rs
Normal file
31
ruma-client-api/src/r0/device/delete_device.rs
Normal file
@ -0,0 +1,31 @@
|
||||
//! [DELETE /_matrix/client/r0/devices/{deviceId}](https://matrix.org/docs/spec/client_server/r0.6.0#delete-matrix-client-r0-devices-deviceid)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::DeviceId;
|
||||
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Delete a device for authenticated user.",
|
||||
method: DELETE,
|
||||
name: "delete_device",
|
||||
path: "/_matrix/client/r0/devices/:device_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The device to delete.
|
||||
#[ruma_api(path)]
|
||||
pub device_id: DeviceId,
|
||||
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auth: Option<AuthData>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: UiaaResponse
|
||||
}
|
30
ruma-client-api/src/r0/device/delete_devices.rs
Normal file
30
ruma-client-api/src/r0/device/delete_devices.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//! [POST /_matrix/client/r0/delete_devices](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-delete-devices)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::DeviceId;
|
||||
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Delete specified devices.",
|
||||
method: POST,
|
||||
path: "/_matrix/client/r0/delete_devices",
|
||||
name: "delete_devices",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// List of devices to delete.
|
||||
pub devices: Vec<DeviceId>,
|
||||
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auth: Option<AuthData>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: UiaaResponse
|
||||
}
|
30
ruma-client-api/src/r0/device/get_device.rs
Normal file
30
ruma-client-api/src/r0/device/get_device.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//! [GET /_matrix/client/r0/devices/{deviceId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-devices-deviceid)
|
||||
|
||||
use super::Device;
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::DeviceId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get a device for authenticated user.",
|
||||
method: GET,
|
||||
name: "get_device",
|
||||
path: "/_matrix/client/r0/devices/:device_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The device to retrieve.
|
||||
#[ruma_api(path)]
|
||||
pub device_id: DeviceId,
|
||||
}
|
||||
|
||||
response {
|
||||
/// Information about the device.
|
||||
#[ruma_api(body)]
|
||||
pub device: Device,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
24
ruma-client-api/src/r0/device/get_devices.rs
Normal file
24
ruma-client-api/src/r0/device/get_devices.rs
Normal file
@ -0,0 +1,24 @@
|
||||
//! [GET /_matrix/client/r0/devices](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-devices)
|
||||
|
||||
use super::Device;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get registered devices for authenticated user.",
|
||||
method: GET,
|
||||
name: "get_devices",
|
||||
path: "/_matrix/client/r0/devices",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {}
|
||||
|
||||
response {
|
||||
/// A list of all registered devices for this user
|
||||
pub devices: Vec<Device>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
30
ruma-client-api/src/r0/device/update_device.rs
Normal file
30
ruma-client-api/src/r0/device/update_device.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//! [PUT /_matrix/client/r0/devices/{deviceId}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-devices-deviceid)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::DeviceId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Update metadata for a device.",
|
||||
method: PUT,
|
||||
name: "update_device",
|
||||
path: "/_matrix/client/r0/devices/:device_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The device to update.
|
||||
#[ruma_api(path)]
|
||||
pub device_id: DeviceId,
|
||||
|
||||
/// The new display name for this device. If this is `None`, the display name won't be
|
||||
/// changed.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub display_name: Option<String>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
48
ruma-client-api/src/r0/directory.rs
Normal file
48
ruma-client-api/src/r0/directory.rs
Normal file
@ -0,0 +1,48 @@
|
||||
//! Endpoints for the public room directory.
|
||||
|
||||
pub mod get_public_rooms;
|
||||
pub mod get_public_rooms_filtered;
|
||||
pub mod get_room_visibility;
|
||||
pub mod set_room_visibility;
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_identifiers::{RoomAliasId, RoomId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A chunk of a room list response, describing one room
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct PublicRoomsChunk {
|
||||
/// Aliases of the room.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub aliases: Vec<RoomAliasId>,
|
||||
|
||||
/// The canonical alias of the room, if any.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub canonical_alias: Option<RoomAliasId>,
|
||||
|
||||
/// The name of the room, if any.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>,
|
||||
|
||||
/// The number of members joined to the room.
|
||||
pub num_joined_members: UInt,
|
||||
|
||||
/// The ID of the room.
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The topic of the room, if any.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub topic: Option<String>,
|
||||
|
||||
/// Whether the room may be viewed by guest users without joining.
|
||||
pub world_readable: bool,
|
||||
|
||||
/// Whether guest users may join the room and participate in it.
|
||||
///
|
||||
/// If they can, they will be subject to ordinary power level rules like any other user.
|
||||
pub guest_can_join: bool,
|
||||
|
||||
/// The URL for the room's avatar, if one is set.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub avatar_url: Option<String>,
|
||||
}
|
52
ruma-client-api/src/r0/directory/get_public_rooms.rs
Normal file
52
ruma-client-api/src/r0/directory/get_public_rooms.rs
Normal file
@ -0,0 +1,52 @@
|
||||
//! [GET /_matrix/client/r0/publicRooms](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-publicrooms)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::PublicRoomsChunk;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get the list of rooms in this homeserver's public directory.",
|
||||
method: GET,
|
||||
name: "get_public_rooms",
|
||||
path: "/_matrix/client/r0/publicRooms",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Limit for the number of results to return.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[ruma_api(query)]
|
||||
pub limit: Option<UInt>,
|
||||
|
||||
/// Pagination token from a previous request.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[ruma_api(query)]
|
||||
pub since: Option<String>,
|
||||
|
||||
/// The server to fetch the public room lists from.
|
||||
///
|
||||
/// `None` means the server this request is sent to.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[ruma_api(query)]
|
||||
pub server: Option<String>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// A paginated chunk of public rooms.
|
||||
pub chunk: Vec<PublicRoomsChunk>,
|
||||
|
||||
/// A pagination token for the response.
|
||||
pub next_batch: Option<String>,
|
||||
|
||||
/// A pagination token that allows fetching previous results.
|
||||
pub prev_batch: Option<String>,
|
||||
|
||||
/// An estimate on the total number of public rooms, if the server has an estimate.
|
||||
pub total_room_count_estimate: Option<UInt>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
255
ruma-client-api/src/r0/directory/get_public_rooms_filtered.rs
Normal file
255
ruma-client-api/src/r0/directory/get_public_rooms_filtered.rs
Normal file
@ -0,0 +1,255 @@
|
||||
//! [POST /_matrix/client/r0/publicRooms](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-publicrooms)
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
use serde::{
|
||||
de::{MapAccess, Visitor},
|
||||
ser::SerializeStruct,
|
||||
Deserialize, Deserializer, Serialize, Serializer,
|
||||
};
|
||||
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
use super::PublicRoomsChunk;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get the list of rooms in this homeserver's public directory.",
|
||||
method: POST,
|
||||
name: "get_public_rooms_filtered",
|
||||
path: "/_matrix/client/r0/publicRooms",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The server to fetch the public room lists from.
|
||||
///
|
||||
/// `None` means the server this request is sent to.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[ruma_api(query)]
|
||||
pub server: Option<String>,
|
||||
|
||||
/// Limit for the number of results to return.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub limit: Option<UInt>,
|
||||
|
||||
/// Pagination token from a previous request.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub since: Option<String>,
|
||||
|
||||
/// Filter to apply to the results.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub filter: Option<Filter>,
|
||||
|
||||
/// Network to fetch the public room lists from.
|
||||
#[serde(flatten, skip_serializing_if = "ruma_serde::is_default")]
|
||||
pub room_network: RoomNetwork,
|
||||
}
|
||||
|
||||
response {
|
||||
/// A paginated chunk of public rooms.
|
||||
pub chunk: Vec<PublicRoomsChunk>,
|
||||
|
||||
/// A pagination token for the response.
|
||||
pub next_batch: Option<String>,
|
||||
|
||||
/// A pagination token that allows fetching previous results.
|
||||
pub prev_batch: Option<String>,
|
||||
|
||||
/// An estimate on the total number of public rooms, if the server has an estimate.
|
||||
pub total_room_count_estimate: Option<UInt>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
/// A filter for public rooms lists
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Filter {
|
||||
/// A string to search for in the room metadata, e.g. name, topic, canonical alias etc.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub generic_search_term: Option<String>,
|
||||
}
|
||||
|
||||
/// Information about which networks/protocols from application services on the
|
||||
/// homeserver from which to request rooms.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum RoomNetwork {
|
||||
/// Return rooms from the Matrix network.
|
||||
Matrix,
|
||||
|
||||
/// Return rooms from all the networks/protocols the homeserver knows about.
|
||||
All,
|
||||
|
||||
/// Return rooms from a specific third party network/protocol.
|
||||
ThirdParty(String),
|
||||
}
|
||||
|
||||
impl Default for RoomNetwork {
|
||||
fn default() -> Self {
|
||||
RoomNetwork::Matrix
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for RoomNetwork {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state;
|
||||
match self {
|
||||
Self::Matrix => {
|
||||
state = serializer.serialize_struct("RoomNetwork", 0)?;
|
||||
}
|
||||
Self::All => {
|
||||
state = serializer.serialize_struct("RoomNetwork", 1)?;
|
||||
state.serialize_field("include_all_networks", &true)?;
|
||||
}
|
||||
Self::ThirdParty(network) => {
|
||||
state = serializer.serialize_struct("RoomNetwork", 1)?;
|
||||
state.serialize_field("third_party_instance_id", network)?;
|
||||
}
|
||||
}
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for RoomNetwork {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_map(RoomNetworkVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct RoomNetworkVisitor;
|
||||
impl<'de> Visitor<'de> for RoomNetworkVisitor {
|
||||
type Value = RoomNetwork;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("Network selection")
|
||||
}
|
||||
|
||||
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
let mut include_all_networks = false;
|
||||
let mut third_party_instance_id = None;
|
||||
while let Some((key, value)) = access.next_entry::<String, JsonValue>()? {
|
||||
match key.as_str() {
|
||||
"include_all_networks" => {
|
||||
include_all_networks = match value.as_bool() {
|
||||
Some(b) => b,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
"third_party_instance_id" => {
|
||||
third_party_instance_id = value.as_str().map(|v| v.to_owned())
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
if include_all_networks {
|
||||
if third_party_instance_id.is_none() {
|
||||
Ok(RoomNetwork::All)
|
||||
} else {
|
||||
Err(M::Error::custom(
|
||||
"`include_all_networks = true` and `third_party_instance_id` are mutually exclusive.",
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Ok(match third_party_instance_id {
|
||||
Some(network) => RoomNetwork::ThirdParty(network),
|
||||
None => RoomNetwork::Matrix,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||
|
||||
use super::RoomNetwork;
|
||||
|
||||
#[test]
|
||||
fn test_serialize_matrix_network_only() {
|
||||
let json = json!({});
|
||||
assert_eq!(to_json_value(RoomNetwork::Matrix).unwrap(), json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_matrix_network_only() {
|
||||
let json = json!({ "include_all_networks": false });
|
||||
assert_eq!(
|
||||
from_json_value::<RoomNetwork>(json).unwrap(),
|
||||
RoomNetwork::Matrix
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_default_network_is_empty() {
|
||||
let json = json!({});
|
||||
assert_eq!(to_json_value(RoomNetwork::default()).unwrap(), json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_empty_network_is_default() {
|
||||
let json = json!({});
|
||||
assert_eq!(
|
||||
from_json_value::<RoomNetwork>(json).unwrap(),
|
||||
RoomNetwork::default()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_include_all_networks() {
|
||||
let json = json!({ "include_all_networks": true });
|
||||
assert_eq!(to_json_value(RoomNetwork::All).unwrap(), json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_include_all_networks() {
|
||||
let json = json!({ "include_all_networks": true });
|
||||
assert_eq!(
|
||||
from_json_value::<RoomNetwork>(json).unwrap(),
|
||||
RoomNetwork::All
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_third_party_network() {
|
||||
let json = json!({ "third_party_instance_id": "freenode" });
|
||||
assert_eq!(
|
||||
to_json_value(RoomNetwork::ThirdParty("freenode".to_string())).unwrap(),
|
||||
json
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_third_party_network() {
|
||||
let json = json!({ "third_party_instance_id": "freenode" });
|
||||
assert_eq!(
|
||||
from_json_value::<RoomNetwork>(json).unwrap(),
|
||||
RoomNetwork::ThirdParty("freenode".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_include_all_networks_and_third_party_exclusivity() {
|
||||
let json = json!({ "include_all_networks": true, "third_party_instance_id": "freenode" });
|
||||
assert_eq!(
|
||||
from_json_value::<RoomNetwork>(json)
|
||||
.unwrap_err()
|
||||
.to_string()
|
||||
.as_str(),
|
||||
"`include_all_networks = true` and `third_party_instance_id` are mutually exclusive."
|
||||
);
|
||||
}
|
||||
}
|
30
ruma-client-api/src/r0/directory/get_room_visibility.rs
Normal file
30
ruma-client-api/src/r0/directory/get_room_visibility.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//! [GET /_matrix/client/r0/directory/list/room/{roomId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-directory-list-room-roomid)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::RoomId;
|
||||
|
||||
use crate::r0::room::Visibility;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get the visibility of a public room on a directory.",
|
||||
name: "get_room_visibility",
|
||||
method: GET,
|
||||
path: "/_matrix/client/r0/directory/list/room/:room_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The ID of the room of which to request the visibility.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
}
|
||||
|
||||
response {
|
||||
/// Visibility of the room.
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
30
ruma-client-api/src/r0/directory/set_room_visibility.rs
Normal file
30
ruma-client-api/src/r0/directory/set_room_visibility.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//! [PUT /_matrix/client/r0/directory/list/room/{roomId}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-directory-list-room-roomid)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::RoomId;
|
||||
|
||||
use crate::r0::room::Visibility;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Set the visibility of a public room on a directory.",
|
||||
name: "set_room_visibility",
|
||||
method: PUT,
|
||||
path: "/_matrix/client/r0/directory/list/room/:room_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The ID of the room of which to set the visibility.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// New visibility setting for the room.
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
381
ruma-client-api/src/r0/filter.rs
Normal file
381
ruma-client-api/src/r0/filter.rs
Normal file
@ -0,0 +1,381 @@
|
||||
//! Endpoints for event filters.
|
||||
|
||||
pub mod create_filter;
|
||||
pub mod get_filter;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_identifiers::{RoomId, UserId};
|
||||
use serde::{
|
||||
de::{MapAccess, Visitor},
|
||||
ser::SerializeStruct,
|
||||
Deserialize, Deserializer, Serialize, Serializer,
|
||||
};
|
||||
|
||||
/// Format to use for returned events
|
||||
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum EventFormat {
|
||||
/// Client format, as described in the Client API.
|
||||
Client,
|
||||
|
||||
/// Raw events from federation.
|
||||
Federation,
|
||||
}
|
||||
|
||||
/// Filters to be applied to room events
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct RoomEventFilter {
|
||||
/// A list of event types to exclude.
|
||||
///
|
||||
/// If this list is absent then no event types are excluded. A matching type will be excluded
|
||||
/// even if it is listed in the 'types' filter. A '*' can be used as a wildcard to match any
|
||||
/// sequence of characters.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub not_types: Vec<String>,
|
||||
|
||||
/// A list of room IDs to exclude.
|
||||
///
|
||||
/// If this list is absent then no rooms are excluded. A matching room will be excluded even if
|
||||
/// it is listed in the 'rooms' filter.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub not_rooms: Vec<String>,
|
||||
|
||||
/// The maximum number of events to return.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub limit: Option<UInt>,
|
||||
|
||||
/// A list of room IDs to include.
|
||||
///
|
||||
/// If this list is absent then all rooms are included.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub rooms: Option<Vec<RoomId>>,
|
||||
|
||||
/// A list of sender IDs to exclude.
|
||||
///
|
||||
/// If this list is absent then no senders are excluded. A matching sender will be excluded even
|
||||
/// if it is listed in the 'senders' filter.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub not_senders: Vec<UserId>,
|
||||
|
||||
/// A list of senders IDs to include.
|
||||
///
|
||||
/// If this list is absent then all senders are included.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub senders: Option<Vec<UserId>>,
|
||||
|
||||
/// A list of event types to include.
|
||||
///
|
||||
/// If this list is absent then all event types are included. A '*' can be used as a wildcard to
|
||||
/// match any sequence of characters.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub types: Option<Vec<String>>,
|
||||
|
||||
/// If `true` include only events with a URL key in their content.
|
||||
/// If `false`, exclude such events.
|
||||
///
|
||||
/// If this item is absent then all event types are included.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub contains_url: Option<bool>,
|
||||
|
||||
/// Options to control lazy-loading of membership events.
|
||||
#[serde(flatten)]
|
||||
pub lazy_load_options: LazyLoadOptions,
|
||||
}
|
||||
|
||||
impl RoomEventFilter {
|
||||
/// A filter that can be used to ignore all room events
|
||||
pub fn ignore_all() -> Self {
|
||||
Self {
|
||||
types: Some(vec![]),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Filters to be applied to room data
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct RoomFilter {
|
||||
/// Include rooms that the user has left in the sync.
|
||||
///
|
||||
/// Defaults to false if not included.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub include_leave: Option<bool>,
|
||||
|
||||
/// The per user account data to include for rooms.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub account_data: Option<RoomEventFilter>,
|
||||
|
||||
/// The message and state update events to include for rooms.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub timeline: Option<RoomEventFilter>,
|
||||
|
||||
/// The events that aren't recorded in the room history, e.g. typing and receipts, to include
|
||||
/// for rooms.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub ephemeral: Option<RoomEventFilter>,
|
||||
|
||||
/// The state events to include for rooms.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub state: Option<RoomEventFilter>,
|
||||
|
||||
/// A list of room IDs to exclude.
|
||||
///
|
||||
/// If this list is absent then no rooms are excluded. A matching room will be excluded even if
|
||||
/// it is listed in the 'rooms' filter. This filter is applied before the filters in
|
||||
/// `ephemeral`, `state`, `timeline` or `account_data`.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub not_rooms: Vec<RoomId>,
|
||||
|
||||
/// A list of room IDs to include.
|
||||
///
|
||||
/// If this list is absent then all rooms are included. This filter is applied before the
|
||||
/// filters in `ephemeral`, `state`, `timeline` or `account_data`.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub rooms: Option<Vec<RoomId>>,
|
||||
}
|
||||
|
||||
impl RoomFilter {
|
||||
/// A filter that can be used to ignore all room events (of any type)
|
||||
pub fn ignore_all() -> Self {
|
||||
Self {
|
||||
rooms: Some(vec![]),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Filter for not-room data
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct Filter {
|
||||
/// A list of event types to exclude.
|
||||
///
|
||||
/// If this list is absent then no event types are excluded. A matching type will be excluded
|
||||
/// even if it is listed in the 'types' filter. A '*' can be used as a wildcard to match any
|
||||
/// sequence of characters.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub not_types: Vec<String>,
|
||||
|
||||
/// The maximum number of events to return.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub limit: Option<UInt>,
|
||||
|
||||
/// A list of senders IDs to include.
|
||||
///
|
||||
/// If this list is absent then all senders are included.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub senders: Option<Vec<UserId>>,
|
||||
|
||||
/// A list of event types to include.
|
||||
///
|
||||
/// If this list is absent then all event types are included. A '*' can be used as a wildcard to
|
||||
/// match any sequence of characters.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub types: Option<Vec<String>>,
|
||||
|
||||
/// A list of sender IDs to exclude.
|
||||
///
|
||||
/// If this list is absent then no senders are excluded. A matching sender will be excluded even
|
||||
/// if it is listed in the 'senders' filter.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub not_senders: Vec<UserId>,
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
/// A filter that can be used to ignore all events
|
||||
pub fn ignore_all() -> Self {
|
||||
Self {
|
||||
types: Some(vec![]),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A filter definition
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct FilterDefinition {
|
||||
/// List of event fields to include.
|
||||
///
|
||||
/// If this list is absent then all fields are included. The entries may include '.' charaters
|
||||
/// to indicate sub-fields. So ['content.body'] will include the 'body' field of the 'content'
|
||||
/// object. A literal '.' character in a field name may be escaped using a '\'. A server may
|
||||
/// include more fields than were requested.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub event_fields: Option<Vec<String>>,
|
||||
|
||||
/// The format to use for events.
|
||||
///
|
||||
/// 'client' will return the events in a format suitable for clients. 'federation' will return
|
||||
/// the raw event as received over federation. The default is 'client'.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub event_format: Option<EventFormat>,
|
||||
|
||||
/// The presence updates to include.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub presence: Option<Filter>,
|
||||
|
||||
/// The user account data that isn't associated with rooms to include.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub account_data: Option<Filter>,
|
||||
|
||||
/// Filters to be applied to room data.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub room: Option<RoomFilter>,
|
||||
}
|
||||
|
||||
impl FilterDefinition {
|
||||
/// A filter that can be used to ignore all events
|
||||
pub fn ignore_all() -> Self {
|
||||
Self {
|
||||
account_data: Some(Filter::ignore_all()),
|
||||
room: Some(RoomFilter::ignore_all()),
|
||||
presence: Some(Filter::ignore_all()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies options for [lazy-loading membership events][lazy-loading] on
|
||||
/// supported endpoints
|
||||
///
|
||||
/// [lazy-loading]: https://matrix.org/docs/spec/client_server/r0.6.0#lazy-loading-room-members
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum LazyLoadOptions {
|
||||
/// Disables lazy-loading of membership events.
|
||||
Disabled,
|
||||
|
||||
/// Enables lazy-loading of events.
|
||||
Enabled {
|
||||
/// If `true`, sends all membership events for all events, even if they have
|
||||
/// already been sent to the client. Defaults to `false`.
|
||||
include_redundant_members: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl Serialize for LazyLoadOptions {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state;
|
||||
match *self {
|
||||
Self::Enabled {
|
||||
include_redundant_members: true,
|
||||
} => {
|
||||
state = serializer.serialize_struct("LazyLoad", 2)?;
|
||||
state.serialize_field("lazy_load_members", &true)?;
|
||||
state.serialize_field("include_redundant_members", &true)?;
|
||||
}
|
||||
Self::Enabled { .. } => {
|
||||
state = serializer.serialize_struct("LazyLoad", 1)?;
|
||||
state.serialize_field("lazy_load_members", &true)?;
|
||||
}
|
||||
_ => {
|
||||
state = serializer.serialize_struct("LazyLoad", 0)?;
|
||||
}
|
||||
}
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LazyLoadOptions {
|
||||
fn default() -> Self {
|
||||
Self::Disabled
|
||||
}
|
||||
}
|
||||
|
||||
struct LazyLoadOptionsVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for LazyLoadOptionsVisitor {
|
||||
type Value = LazyLoadOptions;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("Lazy load options")
|
||||
}
|
||||
|
||||
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
let mut lazy_load_members = false;
|
||||
let mut include_redundant_members = false;
|
||||
while let Some((key, value)) = access.next_entry::<String, bool>()? {
|
||||
match &*key {
|
||||
"lazy_load_members" => lazy_load_members = value,
|
||||
"include_redundant_members" => include_redundant_members = value,
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(if lazy_load_members {
|
||||
LazyLoadOptions::Enabled {
|
||||
include_redundant_members,
|
||||
}
|
||||
} else {
|
||||
LazyLoadOptions::Disabled
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for LazyLoadOptions {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_map(LazyLoadOptionsVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||
|
||||
use super::LazyLoadOptions;
|
||||
|
||||
#[test]
|
||||
fn test_serializing_disabled_lazy_load() {
|
||||
let lazy_load_options = LazyLoadOptions::Disabled;
|
||||
assert_eq!(to_json_value(lazy_load_options).unwrap(), json!({}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serializing_lazy_load_no_redundant() {
|
||||
let lazy_load_options = LazyLoadOptions::Enabled {
|
||||
include_redundant_members: false,
|
||||
};
|
||||
assert_eq!(
|
||||
to_json_value(lazy_load_options).unwrap(),
|
||||
json!({ "lazy_load_members": true })
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serializing_lazy_load_with_redundant() {
|
||||
let lazy_load_options = LazyLoadOptions::Enabled {
|
||||
include_redundant_members: true,
|
||||
};
|
||||
assert_eq!(
|
||||
to_json_value(lazy_load_options).unwrap(),
|
||||
json!({ "lazy_load_members": true, "include_redundant_members": true })
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserializing_no_lazy_load() {
|
||||
let json = json!({});
|
||||
assert_eq!(
|
||||
from_json_value::<LazyLoadOptions>(json).unwrap(),
|
||||
LazyLoadOptions::Disabled,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserializing_ignore_redundant_members_when_no_lazy_load() {
|
||||
let json = json!({ "include_redundant_members": true });
|
||||
assert_eq!(
|
||||
from_json_value::<LazyLoadOptions>(json).unwrap(),
|
||||
LazyLoadOptions::Disabled,
|
||||
);
|
||||
}
|
||||
}
|
36
ruma-client-api/src/r0/filter/create_filter.rs
Normal file
36
ruma-client-api/src/r0/filter/create_filter.rs
Normal file
@ -0,0 +1,36 @@
|
||||
//! [POST /_matrix/client/r0/user/{userId}/filter](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-user-userid-filter)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
use super::FilterDefinition;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Create a new filter for event retrieval.",
|
||||
method: POST,
|
||||
name: "create_filter",
|
||||
path: "/_matrix/client/r0/user/:user_id/filter",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The ID of the user uploading the filter.
|
||||
///
|
||||
/// The access token must be authorized to make requests for this user ID.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
|
||||
/// The filter definition.
|
||||
#[ruma_api(body)]
|
||||
pub filter: FilterDefinition,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The ID of the filter that was created.
|
||||
pub filter_id: String,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
35
ruma-client-api/src/r0/filter/get_filter.rs
Normal file
35
ruma-client-api/src/r0/filter/get_filter.rs
Normal file
@ -0,0 +1,35 @@
|
||||
//! [GET /_matrix/client/r0/user/{userId}/filter/{filterId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-user-userid-filter-filterid)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
use super::FilterDefinition;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Retrieve a previously created filter.",
|
||||
method: GET,
|
||||
name: "get_filter",
|
||||
path: "/_matrix/client/r0/user/:user_id/filter/:filter_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The user ID to download a filter for.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
|
||||
/// The ID of the filter to download.
|
||||
#[ruma_api(path)]
|
||||
pub filter_id: String,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The filter definition.
|
||||
#[ruma_api(body)]
|
||||
pub filter: FilterDefinition,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
164
ruma-client-api/src/r0/keys.rs
Normal file
164
ruma-client-api/src/r0/keys.rs
Normal file
@ -0,0 +1,164 @@
|
||||
//! Endpoints for key management
|
||||
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
convert::TryFrom,
|
||||
fmt::{self, Debug, Display, Formatter},
|
||||
};
|
||||
|
||||
use ruma_events::Algorithm;
|
||||
use ruma_identifiers::{DeviceId, UserId};
|
||||
use serde::{
|
||||
de::{self, Unexpected},
|
||||
Deserialize, Deserializer, Serialize, Serializer,
|
||||
};
|
||||
|
||||
pub mod claim_keys;
|
||||
pub mod get_key_changes;
|
||||
pub mod get_keys;
|
||||
pub mod upload_keys;
|
||||
|
||||
/// The basic key algorithms in the specification
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub enum KeyAlgorithm {
|
||||
/// The Ed25519 signature algorithm.
|
||||
#[serde(rename = "ed25519")]
|
||||
Ed25519,
|
||||
|
||||
/// The Curve25519 ECDH algorithm.
|
||||
#[serde(rename = "curve25519")]
|
||||
Curve25519,
|
||||
|
||||
/// The Curve25519 ECDH algorithm, but the key also contains signatures
|
||||
#[serde(rename = "signed_curve25519")]
|
||||
SignedCurve25519,
|
||||
}
|
||||
|
||||
impl Display for KeyAlgorithm {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
let algorithm_str = match *self {
|
||||
KeyAlgorithm::Ed25519 => "ed25519",
|
||||
KeyAlgorithm::Curve25519 => "curve25519",
|
||||
KeyAlgorithm::SignedCurve25519 => "signed_curve25519",
|
||||
};
|
||||
write!(f, "{}", algorithm_str)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&'_ str> for KeyAlgorithm {
|
||||
type Error = &'static str;
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
match s {
|
||||
"ed25519" => Ok(KeyAlgorithm::Ed25519),
|
||||
"curve25519" => Ok(KeyAlgorithm::Curve25519),
|
||||
"signed_curve25519" => Ok(KeyAlgorithm::SignedCurve25519),
|
||||
_ => Err("Unknown algorithm"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A key algorithm and a device id, combined with a ':'
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct AlgorithmAndDeviceId(pub KeyAlgorithm, pub DeviceId);
|
||||
|
||||
impl Display for AlgorithmAndDeviceId {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}:{}", self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for AlgorithmAndDeviceId {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for AlgorithmAndDeviceId {
|
||||
#[allow(clippy::comparison_chain)]
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let value = String::deserialize(deserializer)?;
|
||||
let parts = value.split(':').collect::<Vec<_>>();
|
||||
|
||||
const EXPECTED: &str = "a string composed of an algorithm and a device id separated by ':'";
|
||||
|
||||
if parts.len() < 2 {
|
||||
return Err(de::Error::invalid_type(
|
||||
Unexpected::Other("string without a ':' separator"),
|
||||
&EXPECTED,
|
||||
));
|
||||
} else if parts.len() > 2 {
|
||||
return Err(de::Error::invalid_type(
|
||||
Unexpected::Other("string with more than one ':' separator"),
|
||||
&EXPECTED,
|
||||
));
|
||||
}
|
||||
|
||||
let algorithm_result = KeyAlgorithm::try_from(parts[0]);
|
||||
match algorithm_result {
|
||||
Ok(algorithm) => Ok(AlgorithmAndDeviceId(algorithm, parts[1].to_string())),
|
||||
Err(_) => Err(de::Error::invalid_value(
|
||||
Unexpected::Str(parts[0]),
|
||||
&"valid key algorithm",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Identity keys for a device.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DeviceKeys {
|
||||
/// The ID of the user the device belongs to. Must match the user ID used when logging in.
|
||||
pub user_id: UserId,
|
||||
|
||||
/// The ID of the device these keys belong to. Must match the device ID used when logging in.
|
||||
pub device_id: DeviceId,
|
||||
|
||||
/// The encryption algorithms supported by this device.
|
||||
pub algorithms: Vec<Algorithm>,
|
||||
|
||||
/// Public identity keys.
|
||||
pub keys: BTreeMap<AlgorithmAndDeviceId, String>,
|
||||
|
||||
/// Signatures for the device key object.
|
||||
pub signatures: BTreeMap<UserId, BTreeMap<AlgorithmAndDeviceId, String>>,
|
||||
|
||||
/// Additional data added to the device key information by intermediate servers, and
|
||||
/// not covered by the signatures.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub unsigned: Option<UnsignedDeviceInfo>,
|
||||
}
|
||||
|
||||
/// Additional data added to device key information by intermediate servers.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UnsignedDeviceInfo {
|
||||
/// The display name which the user set on the device.
|
||||
pub device_display_name: Option<String>,
|
||||
}
|
||||
|
||||
/// A key for the SignedCurve25519 algorithm
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SignedKey {
|
||||
/// Base64-encoded 32-byte Curve25519 public key.
|
||||
pub key: String,
|
||||
|
||||
/// Signatures for the key object.
|
||||
pub signatures: BTreeMap<UserId, BTreeMap<AlgorithmAndDeviceId, String>>,
|
||||
}
|
||||
|
||||
/// A one-time public key for "pre-key" messages.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum OneTimeKey {
|
||||
/// A key containing signatures, for the SignedCurve25519 algorithm.
|
||||
SignedKey(SignedKey),
|
||||
|
||||
/// A string-valued key, for the Ed25519 and Curve25519 algorithms.
|
||||
Key(String),
|
||||
}
|
47
ruma-client-api/src/r0/keys/claim_keys.rs
Normal file
47
ruma-client-api/src/r0/keys/claim_keys.rs
Normal file
@ -0,0 +1,47 @@
|
||||
//! [POST /_matrix/client/r0/keys/claim](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-keys-claim)
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{DeviceId, UserId};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
use super::{AlgorithmAndDeviceId, KeyAlgorithm, OneTimeKey};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Claims one-time keys for use in pre-key messages.",
|
||||
method: POST,
|
||||
name: "claim_keys",
|
||||
path: "/_matrix/client/r0/keys/claim",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The time (in milliseconds) to wait when downloading keys from remote servers.
|
||||
/// 10 seconds is the recommended default.
|
||||
#[serde(
|
||||
with = "ruma_serde::duration::opt_ms",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
)]
|
||||
pub timeout: Option<Duration>,
|
||||
|
||||
/// The keys to be claimed.
|
||||
pub one_time_keys: BTreeMap<UserId, BTreeMap<DeviceId, KeyAlgorithm>>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// If any remote homeservers could not be reached, they are recorded here.
|
||||
/// The names of the properties are the names of the unreachable servers.
|
||||
pub failures: BTreeMap<String, JsonValue>,
|
||||
|
||||
/// One-time keys for the queried devices.
|
||||
pub one_time_keys: BTreeMap<UserId, BTreeMap<DeviceId, BTreeMap<AlgorithmAndDeviceId, OneTimeKey>>>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
38
ruma-client-api/src/r0/keys/get_key_changes.rs
Normal file
38
ruma-client-api/src/r0/keys/get_key_changes.rs
Normal file
@ -0,0 +1,38 @@
|
||||
//! [GET /_matrix/client/r0/keys/changes](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-keys-changes)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Gets a list of users who have updated their device identity keys since a previous sync token.",
|
||||
method: GET,
|
||||
name: "get_key_changes",
|
||||
path: "/_matrix/client/r0/keys/changes",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The desired start point of the list.
|
||||
/// Should be the next_batch field from a response to an earlier call to /sync.
|
||||
#[ruma_api(query)]
|
||||
pub from: String,
|
||||
|
||||
/// The desired end point of the list.
|
||||
/// Should be the next_batch field from a recent call to /sync - typically the most recent such call.
|
||||
#[ruma_api(query)]
|
||||
pub to: String,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The Matrix User IDs of all users who updated their device identity keys.
|
||||
pub changed: Vec<UserId>,
|
||||
|
||||
/// The Matrix User IDs of all users who may have left all the end-to-end
|
||||
/// encrypted rooms they previously shared with the user.
|
||||
pub left: Vec<UserId>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
55
ruma-client-api/src/r0/keys/get_keys.rs
Normal file
55
ruma-client-api/src/r0/keys/get_keys.rs
Normal file
@ -0,0 +1,55 @@
|
||||
//! [POST /_matrix/client/r0/keys/query](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-keys-query)
|
||||
|
||||
use std::{collections::BTreeMap, time::Duration};
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{DeviceId, UserId};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
use super::DeviceKeys;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Returns the current devices and identity keys for the given users.",
|
||||
method: POST,
|
||||
name: "get_keys",
|
||||
path: "/_matrix/client/r0/keys/query",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The time (in milliseconds) to wait when downloading keys from remote
|
||||
/// servers. 10 seconds is the recommended default.
|
||||
#[serde(
|
||||
with = "ruma_serde::duration::opt_ms",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
)]
|
||||
pub timeout: Option<Duration>,
|
||||
|
||||
/// The keys to be downloaded. An empty list indicates all devices for
|
||||
/// the corresponding user.
|
||||
pub device_keys: BTreeMap<UserId, Vec<DeviceId>>,
|
||||
|
||||
/// If the client is fetching keys as a result of a device update
|
||||
/// received in a sync request, this should be the 'since' token of that
|
||||
/// sync request, or any later sync token. This allows the server to
|
||||
/// ensure its response contains the keys advertised by the notification
|
||||
/// in that sync.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub token: Option<String>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// If any remote homeservers could not be reached, they are recorded
|
||||
/// here. The names of the properties are the names of the unreachable
|
||||
/// servers.
|
||||
pub failures: BTreeMap<String, JsonValue>,
|
||||
|
||||
/// Information on the queried devices.
|
||||
pub device_keys: BTreeMap<UserId, BTreeMap<DeviceId, DeviceKeys>>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
37
ruma-client-api/src/r0/keys/upload_keys.rs
Normal file
37
ruma-client-api/src/r0/keys/upload_keys.rs
Normal file
@ -0,0 +1,37 @@
|
||||
//! [POST /_matrix/client/r0/keys/upload](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-keys-upload)
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::{AlgorithmAndDeviceId, DeviceKeys, KeyAlgorithm, OneTimeKey};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Publishes end-to-end encryption keys for the device.",
|
||||
method: POST,
|
||||
name: "upload_keys",
|
||||
path: "/_matrix/client/r0/keys/upload",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Identity keys for the device. May be absent if no new identity keys are required.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub device_keys: Option<DeviceKeys>,
|
||||
|
||||
/// One-time public keys for "pre-key" messages.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub one_time_keys: Option<BTreeMap<AlgorithmAndDeviceId, OneTimeKey>>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// For each key algorithm, the number of unclaimed one-time keys of that
|
||||
/// type currently held on the server for this device.
|
||||
pub one_time_key_counts: BTreeMap<KeyAlgorithm, UInt>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
8
ruma-client-api/src/r0/media.rs
Normal file
8
ruma-client-api/src/r0/media.rs
Normal file
@ -0,0 +1,8 @@
|
||||
//! Endpoints for the media repository.
|
||||
|
||||
pub mod create_content;
|
||||
pub mod get_content;
|
||||
pub mod get_content_as_filename;
|
||||
pub mod get_content_thumbnail;
|
||||
pub mod get_media_config;
|
||||
pub mod get_media_preview;
|
37
ruma-client-api/src/r0/media/create_content.rs
Normal file
37
ruma-client-api/src/r0/media/create_content.rs
Normal file
@ -0,0 +1,37 @@
|
||||
//! [POST /_matrix/media/r0/upload](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-media-r0-upload)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Upload content to the media store.",
|
||||
method: POST,
|
||||
name: "create_media_content",
|
||||
path: "/_matrix/media/r0/upload",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The name of the file being uploaded.
|
||||
#[ruma_api(query)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub filename: Option<String>,
|
||||
|
||||
/// The content type of the file being uploaded.
|
||||
// TODO: This should be optional.
|
||||
#[ruma_api(header = CONTENT_TYPE)]
|
||||
pub content_type: String,
|
||||
|
||||
/// The file contents to upload.
|
||||
#[ruma_api(raw_body)]
|
||||
pub file: Vec<u8>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The MXC URI for the uploaded content.
|
||||
pub content_uri: String,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
45
ruma-client-api/src/r0/media/get_content.rs
Normal file
45
ruma-client-api/src/r0/media/get_content.rs
Normal file
@ -0,0 +1,45 @@
|
||||
//! [GET /_matrix/media/r0/download/{serverName}/{mediaId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-media-r0-download-servername-mediaid)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Retrieve content from the media store.",
|
||||
method: GET,
|
||||
name: "get_media_content",
|
||||
path: "/_matrix/media/r0/download/:server_name/:media_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The media ID from the mxc:// URI (the path component).
|
||||
#[ruma_api(path)]
|
||||
pub media_id: String,
|
||||
|
||||
/// The server name from the mxc:// URI (the authoritory component).
|
||||
#[ruma_api(path)]
|
||||
pub server_name: String,
|
||||
|
||||
/// Whether to fetch media deemed remote.
|
||||
/// Used to prevent routing loops. Defaults to `true`.
|
||||
#[ruma_api(query)]
|
||||
pub allow_remote: Option<bool>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The content that was previously uploaded.
|
||||
#[ruma_api(raw_body)]
|
||||
pub file: Vec<u8>,
|
||||
|
||||
/// The content type of the file that was previously uploaded.
|
||||
#[ruma_api(header = CONTENT_TYPE)]
|
||||
pub content_type: String,
|
||||
|
||||
/// The name of the file that was previously uploaded, if set.
|
||||
#[ruma_api(header = CONTENT_DISPOSITION)]
|
||||
pub content_disposition: String,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
49
ruma-client-api/src/r0/media/get_content_as_filename.rs
Normal file
49
ruma-client-api/src/r0/media/get_content_as_filename.rs
Normal file
@ -0,0 +1,49 @@
|
||||
//! [GET /_matrix/media/r0/download/{serverName}/{mediaId}/{fileName}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-media-r0-download-servername-mediaid-filename)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Retrieve content from the media store, specifying a filename to return.",
|
||||
method: GET,
|
||||
name: "get_media_content_as_filename",
|
||||
path: "/_matrix/media/r0/download/:server_name/:media_id/:filename",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The media ID from the mxc:// URI (the path component).
|
||||
#[ruma_api(path)]
|
||||
pub media_id: String,
|
||||
|
||||
/// The server name from the mxc:// URI (the authoritory component).
|
||||
#[ruma_api(path)]
|
||||
pub server_name: String,
|
||||
|
||||
/// The filename to return in the `Content-Disposition` header.
|
||||
#[ruma_api(path)]
|
||||
pub filename: String,
|
||||
|
||||
/// Whether to fetch media deemed remote.
|
||||
/// Used to prevent routing loops. Defaults to `true`.
|
||||
#[ruma_api(query)]
|
||||
pub allow_remote: Option<bool>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The content that was previously uploaded.
|
||||
#[ruma_api(raw_body)]
|
||||
pub file: Vec<u8>,
|
||||
|
||||
/// The content type of the file that was previously uploaded.
|
||||
#[ruma_api(header = CONTENT_TYPE)]
|
||||
pub content_type: String,
|
||||
|
||||
/// The name of the file that was previously uploaded, if set.
|
||||
#[ruma_api(header = CONTENT_DISPOSITION)]
|
||||
pub content_disposition: String,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
71
ruma-client-api/src/r0/media/get_content_thumbnail.rs
Normal file
71
ruma-client-api/src/r0/media/get_content_thumbnail.rs
Normal file
@ -0,0 +1,71 @@
|
||||
//! [GET /_matrix/media/r0/thumbnail/{serverName}/{mediaId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-media-r0-thumbnail-servername-mediaid)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The desired resizing method.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Method {
|
||||
/// Crop the original to produce the requested image dimensions.
|
||||
Crop,
|
||||
|
||||
/// Maintain the original aspect ratio of the source image.
|
||||
Scale,
|
||||
}
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get a thumbnail of content from the media store.",
|
||||
method: GET,
|
||||
name: "get_content_thumbnail",
|
||||
path: "/_matrix/media/r0/thumbnail/:server_name/:media_id",
|
||||
rate_limited: true,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Whether to fetch media deemed remote.
|
||||
///
|
||||
/// Used to prevent routing loops. Defaults to `true`.
|
||||
#[ruma_api(query)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub allow_remote: Option<bool>,
|
||||
|
||||
/// The media ID from the mxc:// URI (the path component).
|
||||
#[ruma_api(path)]
|
||||
pub media_id: String,
|
||||
|
||||
/// The server name from the mxc:// URI (the authoritory component).
|
||||
#[ruma_api(path)]
|
||||
pub server_name: String,
|
||||
|
||||
/// The *desired* height of the thumbnail. The actual thumbnail may not match the size
|
||||
/// specified.
|
||||
#[ruma_api(query)]
|
||||
pub height: UInt,
|
||||
|
||||
/// The desired resizing method.
|
||||
#[ruma_api(query)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub method: Option<Method>,
|
||||
|
||||
/// The *desired* width of the thumbnail. The actual thumbnail may not match the size
|
||||
/// specified.
|
||||
#[ruma_api(query)]
|
||||
pub width: UInt,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The content type of the thumbnail.
|
||||
#[ruma_api(header = CONTENT_TYPE)]
|
||||
pub content_type: String,
|
||||
|
||||
/// A thumbnail of the requested content.
|
||||
#[ruma_api(raw_body)]
|
||||
pub file: Vec<u8>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
25
ruma-client-api/src/r0/media/get_media_config.rs
Normal file
25
ruma-client-api/src/r0/media/get_media_config.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//! [GET /_matrix/media/r0/config](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-media-r0-config)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Gets the config for the media repository.",
|
||||
method: GET,
|
||||
path: "/_matrix/media/r0/config",
|
||||
name: "get_media_config",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {}
|
||||
|
||||
response {
|
||||
/// Maximum size of upload in bytes.
|
||||
#[serde(rename = "m.upload.size")]
|
||||
pub upload_size: UInt,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
73
ruma-client-api/src/r0/media/get_media_preview.rs
Normal file
73
ruma-client-api/src/r0/media/get_media_preview.rs
Normal file
@ -0,0 +1,73 @@
|
||||
//! [GET /_matrix/media/r0/preview_url](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-media-r0-preview-url)
|
||||
|
||||
use std::time::SystemTime;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get a preview for a URL.",
|
||||
name: "get_media_preview",
|
||||
method: GET,
|
||||
path: "/_matrix/media/r0/preview_url",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// URL to get a preview of.
|
||||
#[ruma_api(query)]
|
||||
pub url: String,
|
||||
|
||||
/// Preferred point in time (in milliseconds) to return a preview for.
|
||||
#[ruma_api(query)]
|
||||
#[serde(with = "ruma_serde::time::ms_since_unix_epoch")]
|
||||
pub ts: SystemTime,
|
||||
}
|
||||
|
||||
response {
|
||||
/// OpenGraph-like data for the URL.
|
||||
///
|
||||
/// Differences from OpenGraph: the image size in bytes is added to the `matrix:image:size`
|
||||
/// field, and `og:image` returns the MXC URI to the image, if any.
|
||||
#[ruma_api(body)]
|
||||
pub data: Option<Box<RawJsonValue>>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::{
|
||||
from_value as from_json_value, json,
|
||||
value::{to_raw_value as to_raw_json_value, RawValue as RawJsonValue},
|
||||
};
|
||||
|
||||
// Since BTreeMap<String, Box<RawJsonValue>> deserialization doesn't seem to
|
||||
// work, test that Option<RawJsonValue> works
|
||||
#[test]
|
||||
fn raw_json_deserialize() {
|
||||
type OptRawJson = Option<Box<RawJsonValue>>;
|
||||
|
||||
assert!(from_json_value::<OptRawJson>(json!(null))
|
||||
.unwrap()
|
||||
.is_none());
|
||||
assert!(from_json_value::<OptRawJson>(json!("test"))
|
||||
.unwrap()
|
||||
.is_some());
|
||||
assert!(from_json_value::<OptRawJson>(json!({ "a": "b" }))
|
||||
.unwrap()
|
||||
.is_some());
|
||||
}
|
||||
|
||||
// For completeness sake, make sure serialization works too
|
||||
#[test]
|
||||
fn raw_json_serialize() {
|
||||
assert!(to_raw_json_value(&json!(null)).is_ok());
|
||||
assert!(to_raw_json_value(&json!("string")).is_ok());
|
||||
assert!(to_raw_json_value(&json!({})).is_ok());
|
||||
assert!(to_raw_json_value(&json!({ "a": "b" })).is_ok());
|
||||
}
|
||||
}
|
52
ruma-client-api/src/r0/membership.rs
Normal file
52
ruma-client-api/src/r0/membership.rs
Normal file
@ -0,0 +1,52 @@
|
||||
//! Endpoints for room membership.
|
||||
|
||||
pub mod ban_user;
|
||||
pub mod forget_room;
|
||||
pub mod get_member_events;
|
||||
pub mod invite_user;
|
||||
pub mod join_room_by_id;
|
||||
pub mod join_room_by_id_or_alias;
|
||||
pub mod joined_members;
|
||||
pub mod joined_rooms;
|
||||
pub mod kick_user;
|
||||
pub mod leave_room;
|
||||
pub mod unban_user;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::r0::thirdparty::Medium;
|
||||
|
||||
/// A signature of an `m.third_party_invite` token to prove that this user owns a third party
|
||||
/// identity which has been invited to the room.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct ThirdPartySigned {
|
||||
/// The Matrix ID of the user who issued the invite.
|
||||
pub sender: String,
|
||||
|
||||
/// The Matrix ID of the invitee.
|
||||
pub mxid: String,
|
||||
|
||||
/// The state key of the m.third_party_invite event.
|
||||
pub token: String,
|
||||
|
||||
/// A signatures object containing a signature of the entire signed object.
|
||||
pub signatures: BTreeMap<String, BTreeMap<String, String>>,
|
||||
}
|
||||
|
||||
/// Represents third party IDs to invite to the room.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct Invite3pid {
|
||||
/// Hostname and port of identity server to be used for account lookups.
|
||||
pub id_server: String,
|
||||
|
||||
/// An access token registered with the identity server.
|
||||
pub id_access_token: String,
|
||||
|
||||
/// Type of third party ID.
|
||||
pub medium: Medium,
|
||||
|
||||
/// Third party identifier.
|
||||
pub address: String,
|
||||
}
|
32
ruma-client-api/src/r0/membership/ban_user.rs
Normal file
32
ruma-client-api/src/r0/membership/ban_user.rs
Normal file
@ -0,0 +1,32 @@
|
||||
//! [POST /_matrix/client/r0/rooms/{roomId}/ban](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-rooms-roomid-ban)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{RoomId, UserId};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Ban a user from a room.",
|
||||
method: POST,
|
||||
name: "ban_user",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/ban",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room to kick the user from.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The user to ban.
|
||||
pub user_id: UserId,
|
||||
|
||||
/// The reason for banning the user.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub reason: Option<String>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
25
ruma-client-api/src/r0/membership/forget_room.rs
Normal file
25
ruma-client-api/src/r0/membership/forget_room.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//! [POST /_matrix/client/r0/rooms/{roomId}/forget](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-rooms-roomid-forget)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::RoomId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Forget a room.",
|
||||
method: POST,
|
||||
name: "forget_room",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/forget",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room to forget.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
66
ruma-client-api/src/r0/membership/get_member_events.rs
Normal file
66
ruma-client-api/src/r0/membership/get_member_events.rs
Normal file
@ -0,0 +1,66 @@
|
||||
//! [GET /_matrix/client/r0/rooms/{roomId}/members](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-members)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_events::{room::member::MemberEvent, EventJson};
|
||||
use ruma_identifiers::RoomId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get membership events for a room.",
|
||||
method: GET,
|
||||
name: "get_member_events",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/members",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room to get the member events for.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The point in time (pagination token) to return members for in the room. This token can
|
||||
/// be obtained from a prev_batch token returned for each room by the sync API.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[ruma_api(query)]
|
||||
pub at: Option<String>,
|
||||
|
||||
/// The kind of memberships to filter for. Defaults to no filtering if unspecified. When
|
||||
/// specified alongside not_membership, the two parameters create an 'or' condition: either
|
||||
/// the membership is the same as membership or is not the same as not_membership.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[ruma_api(query)]
|
||||
pub membership: Option<MembershipEventFilter>,
|
||||
|
||||
/// The kind of memberships to *exclude* from the results. Defaults to no filtering if
|
||||
/// unspecified.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[ruma_api(query)]
|
||||
pub not_membership: Option<MembershipEventFilter>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// A list of member events.
|
||||
pub chunk: Vec<EventJson<MemberEvent>>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
/// The kind of membership events to filter for.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum MembershipEventFilter {
|
||||
/// The user has joined.
|
||||
Join,
|
||||
|
||||
/// The user has been invited.
|
||||
Invite,
|
||||
|
||||
/// The user has left.
|
||||
Leave,
|
||||
|
||||
/// The user has been banned.
|
||||
Ban,
|
||||
}
|
90
ruma-client-api/src/r0/membership/invite_user.rs
Normal file
90
ruma-client-api/src/r0/membership/invite_user.rs
Normal file
@ -0,0 +1,90 @@
|
||||
//! [POST /_matrix/client/r0/rooms/{roomId}/invite][invite-by-user-id]
|
||||
//!
|
||||
//! This endpoint has two forms: one to invite a user
|
||||
//! [by their Matrix identifier][invite-by-user-id], and one to invite a user
|
||||
//! [by their third party identifier][invite-by-3pid].
|
||||
//!
|
||||
//! [invite-by-user-id]: https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-rooms-roomid-invite
|
||||
//! [invite-by-3pid]: https://matrix.org/docs/spec/client_server/r0.6.0#id101
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{RoomId, UserId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::Invite3pid;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Invite a user to a room.",
|
||||
method: POST,
|
||||
name: "invite_user",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/invite",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room where the user should be invited.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The user to invite.
|
||||
#[ruma_api(body)]
|
||||
pub recipient: InvitationRecipient,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
/// Distinguishes between invititations by Matrix or third party identifiers.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum InvitationRecipient {
|
||||
/// Used to invite user by their Matrix identifer.
|
||||
UserId {
|
||||
/// Matrix identifier of user.
|
||||
user_id: UserId,
|
||||
},
|
||||
|
||||
/// Used to invite user by a third party identifer.
|
||||
ThirdPartyId(Invite3pid),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use ruma_identifiers::UserId;
|
||||
use serde_json::{from_value as from_json_value, json};
|
||||
|
||||
use super::InvitationRecipient;
|
||||
use crate::r0::{membership::Invite3pid, thirdparty::Medium};
|
||||
#[test]
|
||||
fn deserialize_invite_by_user_id() {
|
||||
let incoming =
|
||||
from_json_value::<InvitationRecipient>(json!({ "user_id": "@carl:example.org" }))
|
||||
.unwrap();
|
||||
let user_id = UserId::try_from("@carl:example.org").unwrap();
|
||||
let recipient = InvitationRecipient::UserId { user_id };
|
||||
assert_eq!(incoming, recipient);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_invite_by_3pid() {
|
||||
let incoming = from_json_value::<InvitationRecipient>(json!({
|
||||
"id_server": "example.org",
|
||||
"id_access_token": "abcdefghijklmnop",
|
||||
"medium": "email",
|
||||
"address": "carl@example.org"
|
||||
}))
|
||||
.unwrap();
|
||||
let recipient = InvitationRecipient::ThirdPartyId(Invite3pid {
|
||||
id_server: "example.org".to_string(),
|
||||
id_access_token: "abcdefghijklmnop".to_string(),
|
||||
medium: Medium::Email,
|
||||
address: "carl@example.org".to_string(),
|
||||
});
|
||||
assert_eq!(incoming, recipient);
|
||||
}
|
||||
}
|
35
ruma-client-api/src/r0/membership/join_room_by_id.rs
Normal file
35
ruma-client-api/src/r0/membership/join_room_by_id.rs
Normal file
@ -0,0 +1,35 @@
|
||||
//! [POST /_matrix/client/r0/rooms/{roomId}/join](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-rooms-roomid-join)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::RoomId;
|
||||
|
||||
use super::ThirdPartySigned;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Join a room using its ID.",
|
||||
method: POST,
|
||||
name: "join_room_by_id",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/join",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room where the user should be invited.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The signature of a `m.third_party_invite` token to prove that this user owns a third
|
||||
/// party identity which has been invited to the room.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub third_party_signed: Option<ThirdPartySigned>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The room that the user joined.
|
||||
pub room_id: RoomId,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
//! [POST /_matrix/client/r0/join/{roomIdOrAlias}](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-join-roomidoralias)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{RoomId, RoomIdOrAliasId};
|
||||
|
||||
use super::ThirdPartySigned;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Join a room using its ID or one of its aliases.",
|
||||
method: POST,
|
||||
name: "join_room_by_id_or_alias",
|
||||
path: "/_matrix/client/r0/join/:room_id_or_alias",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room where the user should be invited.
|
||||
#[ruma_api(path)]
|
||||
pub room_id_or_alias: RoomIdOrAliasId,
|
||||
|
||||
/// The servers to attempt to join the room through. One of the servers
|
||||
/// must be participating in the room.
|
||||
#[ruma_api(query)]
|
||||
#[serde(default)]
|
||||
pub server_name: Vec<String>,
|
||||
|
||||
/// The signature of a `m.third_party_invite` token to prove that this user owns a third
|
||||
/// party identity which has been invited to the room.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub third_party_signed: Option<ThirdPartySigned>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The room that the user joined.
|
||||
pub room_id: RoomId,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
44
ruma-client-api/src/r0/membership/joined_members.rs
Normal file
44
ruma-client-api/src/r0/membership/joined_members.rs
Normal file
@ -0,0 +1,44 @@
|
||||
//! [GET /_matrix/client/r0/rooms/{roomId}/joined_members](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-joined-members)
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{RoomId, UserId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get a map of user ids to member info objects for members of the room. Primarily for use in Application Services.",
|
||||
method: GET,
|
||||
name: "joined_members",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/joined_members",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room to get the members of.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
}
|
||||
|
||||
response {
|
||||
/// A list of the rooms the user is in, i.e.
|
||||
/// the ID of each room in which the user has joined membership.
|
||||
pub joined: BTreeMap<UserId, RoomMember>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
/// Information about a room member.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct RoomMember {
|
||||
/// The display name of the user.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub display_name: Option<String>,
|
||||
|
||||
/// The mxc avatar url of the user.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub avatar_url: Option<String>,
|
||||
}
|
25
ruma-client-api/src/r0/membership/joined_rooms.rs
Normal file
25
ruma-client-api/src/r0/membership/joined_rooms.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//! [GET /_matrix/client/r0/joined_rooms](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-joined-rooms)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::RoomId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get a list of the user's current rooms.",
|
||||
method: GET,
|
||||
name: "joined_rooms",
|
||||
path: "/_matrix/client/r0/joined_rooms",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {}
|
||||
|
||||
response {
|
||||
/// A list of the rooms the user is in, i.e. the ID of each room in
|
||||
/// which the user has joined membership.
|
||||
pub joined_rooms: Vec<RoomId>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
32
ruma-client-api/src/r0/membership/kick_user.rs
Normal file
32
ruma-client-api/src/r0/membership/kick_user.rs
Normal file
@ -0,0 +1,32 @@
|
||||
//! [POST /_matrix/client/r0/rooms/{roomId}/kick](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-rooms-roomid-kick)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{RoomId, UserId};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Kick a user from a room.",
|
||||
method: POST,
|
||||
name: "kick_user",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/kick",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room to kick the user from.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The user to kick.
|
||||
pub user_id: UserId,
|
||||
|
||||
/// The reason for kicking the user.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub reason: Option<String>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
25
ruma-client-api/src/r0/membership/leave_room.rs
Normal file
25
ruma-client-api/src/r0/membership/leave_room.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//! [POST /_matrix/client/r0/rooms/{roomId}/leave](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-rooms-roomid-leave)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::RoomId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Leave a room.",
|
||||
method: POST,
|
||||
name: "leave_room",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/leave",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room to leave.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
28
ruma-client-api/src/r0/membership/unban_user.rs
Normal file
28
ruma-client-api/src/r0/membership/unban_user.rs
Normal file
@ -0,0 +1,28 @@
|
||||
//! [POST /_matrix/client/r0/rooms/{roomId}/unban](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-rooms-roomid-unban)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{RoomId, UserId};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Unban a user from a room.",
|
||||
method: POST,
|
||||
name: "unban_user",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/unban",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room to unban the user from.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The user to unban.
|
||||
pub user_id: UserId,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
4
ruma-client-api/src/r0/message.rs
Normal file
4
ruma-client-api/src/r0/message.rs
Normal file
@ -0,0 +1,4 @@
|
||||
//! Enpoints for sending and receiving messages
|
||||
|
||||
pub mod create_message_event;
|
||||
pub mod get_message_events;
|
50
ruma-client-api/src/r0/message/create_message_event.rs
Normal file
50
ruma-client-api/src/r0/message/create_message_event.rs
Normal file
@ -0,0 +1,50 @@
|
||||
//! [PUT /_matrix/client/r0/rooms/{roomId}/send/{eventType}/{txnId}](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_events::EventType;
|
||||
use ruma_identifiers::{EventId, RoomId};
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Send a message event to a room.",
|
||||
method: PUT,
|
||||
name: "create_message_event",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/send/:event_type/:txn_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room to send the event to.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The type of event to send.
|
||||
#[ruma_api(path)]
|
||||
pub event_type: EventType,
|
||||
|
||||
/// The transaction ID for this event.
|
||||
///
|
||||
/// Clients should generate an ID unique across requests with the
|
||||
/// same access token; it will be used by the server to ensure
|
||||
/// idempotency of requests.
|
||||
#[ruma_api(path)]
|
||||
pub txn_id: String,
|
||||
|
||||
/// The event's content. The type for this field will be updated in a
|
||||
/// future release, until then you can create a value using
|
||||
/// `serde_json::value::to_raw_value`.
|
||||
#[ruma_api(body)]
|
||||
pub data: Box<RawJsonValue>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// A unique identifier for the event.
|
||||
// This is not declared required in r0.6.0, but that was a bug that has now been fixed:
|
||||
// https://github.com/matrix-org/matrix-doc/pull/2525
|
||||
pub event_id: EventId,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
176
ruma-client-api/src/r0/message/get_message_events.rs
Normal file
176
ruma-client-api/src/r0/message/get_message_events.rs
Normal file
@ -0,0 +1,176 @@
|
||||
//! [GET /_matrix/client/r0/rooms/{roomId}/messages](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-rooms-roomid-messages)
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_events::{
|
||||
collections::all::{RoomEvent, StateEvent},
|
||||
EventJson,
|
||||
};
|
||||
use ruma_identifiers::RoomId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::r0::filter::RoomEventFilter;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get message events for a room.",
|
||||
method: GET,
|
||||
name: "get_message_events",
|
||||
path: "/_matrix/client/r0/rooms/:room_id/messages",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The room to get events from.
|
||||
#[ruma_api(path)]
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The token to start returning events from.
|
||||
///
|
||||
/// This token can be obtained from a
|
||||
/// prev_batch token returned for each room by the sync API, or from a start or end token
|
||||
/// returned by a previous request to this endpoint.
|
||||
#[ruma_api(query)]
|
||||
pub from: String,
|
||||
|
||||
/// The token to stop returning events at.
|
||||
///
|
||||
/// This token can be obtained from a prev_batch
|
||||
/// token returned for each room by the sync endpoint, or from a start or end token returned
|
||||
/// by a previous request to this endpoint.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[ruma_api(query)]
|
||||
pub to: Option<String>,
|
||||
|
||||
/// The direction to return events from.
|
||||
#[ruma_api(query)]
|
||||
pub dir: Direction,
|
||||
|
||||
/// The maximum number of events to return.
|
||||
///
|
||||
/// Default: 10.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[ruma_api(query)]
|
||||
pub limit: Option<UInt>,
|
||||
|
||||
/// A RoomEventFilter to filter returned events with.
|
||||
#[ruma_api(query)]
|
||||
#[serde(
|
||||
with = "ruma_serde::json_string",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub filter: Option<RoomEventFilter>,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The token the pagination starts from.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub start: Option<String>,
|
||||
|
||||
/// The token the pagination ends at.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub end: Option<String>,
|
||||
|
||||
/// A list of room events.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub chunk: Vec<EventJson<RoomEvent>>,
|
||||
|
||||
/// A list of state events relevant to showing the `chunk`.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub state: Vec<EventJson<StateEvent>>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
||||
|
||||
/// The direction to return events from.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||
pub enum Direction {
|
||||
/// Return events backwards in time from the requested `from` token.
|
||||
#[serde(rename = "b")]
|
||||
Backward,
|
||||
|
||||
/// Return events forwards in time from the requested `from` token.
|
||||
#[serde(rename = "f")]
|
||||
Forward,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Direction, Request};
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
use js_int::UInt;
|
||||
use ruma_identifiers::RoomId;
|
||||
|
||||
use crate::r0::filter::{LazyLoadOptions, RoomEventFilter};
|
||||
|
||||
#[test]
|
||||
fn test_serialize_some_room_event_filter() {
|
||||
let room_id = RoomId::try_from("!roomid:example.org").unwrap();
|
||||
let filter = RoomEventFilter {
|
||||
lazy_load_options: LazyLoadOptions::Enabled {
|
||||
include_redundant_members: true,
|
||||
},
|
||||
rooms: Some(vec![room_id.clone()]),
|
||||
not_rooms: vec!["room".into(), "room2".into(), "room3".into()],
|
||||
not_types: vec!["type".into()],
|
||||
..Default::default()
|
||||
};
|
||||
let req = Request {
|
||||
room_id,
|
||||
from: "token".into(),
|
||||
to: Some("token2".into()),
|
||||
dir: Direction::Backward,
|
||||
limit: Some(UInt::from(0u32)),
|
||||
filter: Some(filter),
|
||||
};
|
||||
|
||||
let request: http::Request<Vec<u8>> = req.try_into().unwrap();
|
||||
assert_eq!(
|
||||
"from=token&to=token2&dir=b&limit=0&filter=%7B%22not_types%22%3A%5B%22type%22%5D%2C%22not_rooms%22%3A%5B%22room%22%2C%22room2%22%2C%22room3%22%5D%2C%22rooms%22%3A%5B%22%21roomid%3Aexample.org%22%5D%2C%22lazy_load_members%22%3Atrue%2C%22include_redundant_members%22%3Atrue%7D",
|
||||
request.uri().query().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_none_room_event_filter() {
|
||||
let room_id = RoomId::try_from("!roomid:example.org").unwrap();
|
||||
let req = Request {
|
||||
room_id,
|
||||
from: "token".into(),
|
||||
to: Some("token2".into()),
|
||||
dir: Direction::Backward,
|
||||
limit: Some(UInt::from(0u32)),
|
||||
filter: None,
|
||||
};
|
||||
|
||||
let request: http::Request<Vec<u8>> = req.try_into().unwrap();
|
||||
assert_eq!(
|
||||
"from=token&to=token2&dir=b&limit=0",
|
||||
request.uri().query().unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_default_room_event_filter() {
|
||||
let room_id = RoomId::try_from("!roomid:example.org").unwrap();
|
||||
let req = Request {
|
||||
room_id,
|
||||
from: "token".into(),
|
||||
to: Some("token2".into()),
|
||||
dir: Direction::Backward,
|
||||
limit: Some(UInt::from(0u32)),
|
||||
filter: Some(RoomEventFilter::default()),
|
||||
};
|
||||
|
||||
let request: http::Request<Vec<u8>> = req.try_into().unwrap();
|
||||
assert_eq!(
|
||||
"from=token&to=token2&dir=b&limit=0&filter=%7B%7D",
|
||||
request.uri().query().unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
4
ruma-client-api/src/r0/presence.rs
Normal file
4
ruma-client-api/src/r0/presence.rs
Normal file
@ -0,0 +1,4 @@
|
||||
//! Endpoints for user presence.
|
||||
|
||||
pub mod get_presence;
|
||||
pub mod set_presence;
|
47
ruma-client-api/src/r0/presence/get_presence.rs
Normal file
47
ruma-client-api/src/r0/presence/get_presence.rs
Normal file
@ -0,0 +1,47 @@
|
||||
//! [GET /_matrix/client/r0/presence/{userId}/status](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-presence-userid-status)
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_events::presence::PresenceState;
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get presence status for this user.",
|
||||
method: GET,
|
||||
name: "get_presence",
|
||||
path: "/_matrix/client/r0/presence/:user_id/status",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The user whose presence state will be retrieved.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The state message for this user if one was set.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub status_msg: Option<String>,
|
||||
|
||||
/// Whether or not the user is currently active.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub currently_active: Option<bool>,
|
||||
|
||||
/// The length of time in milliseconds since an action was performed by the user.
|
||||
#[serde(
|
||||
with = "ruma_serde::duration::opt_ms",
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
)]
|
||||
pub last_active_ago: Option<Duration>,
|
||||
|
||||
/// The user's presence state.
|
||||
pub presence: PresenceState,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
33
ruma-client-api/src/r0/presence/set_presence.rs
Normal file
33
ruma-client-api/src/r0/presence/set_presence.rs
Normal file
@ -0,0 +1,33 @@
|
||||
//! [PUT /_matrix/client/r0/presence/{userId}/status](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-presence-userid-status)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_events::presence::PresenceState;
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Set presence status for this user.",
|
||||
method: PUT,
|
||||
name: "set_presence",
|
||||
path: "/_matrix/client/r0/presence/:user_id/status",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The user whose presence state will be updated.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
|
||||
/// The new presence state.
|
||||
pub presence: PresenceState,
|
||||
|
||||
/// The status message to attach to this state.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub status_msg: Option<String>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
7
ruma-client-api/src/r0/profile.rs
Normal file
7
ruma-client-api/src/r0/profile.rs
Normal file
@ -0,0 +1,7 @@
|
||||
//! Endpoints for user profiles.
|
||||
|
||||
pub mod get_avatar_url;
|
||||
pub mod get_display_name;
|
||||
pub mod get_profile;
|
||||
pub mod set_avatar_url;
|
||||
pub mod set_display_name;
|
29
ruma-client-api/src/r0/profile/get_avatar_url.rs
Normal file
29
ruma-client-api/src/r0/profile/get_avatar_url.rs
Normal file
@ -0,0 +1,29 @@
|
||||
//! [GET /_matrix/client/r0/profile/{userId}/avatar_url](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-profile-userid-avatar-url)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get the avatar URL of a user.",
|
||||
method: GET,
|
||||
name: "get_avatar_url",
|
||||
path: "/_matrix/client/r0/profile/:user_id/avatar_url",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The user whose avatar URL will be retrieved.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId
|
||||
}
|
||||
|
||||
response {
|
||||
/// The user's avatar URL, if set.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub avatar_url: Option<String>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
29
ruma-client-api/src/r0/profile/get_display_name.rs
Normal file
29
ruma-client-api/src/r0/profile/get_display_name.rs
Normal file
@ -0,0 +1,29 @@
|
||||
//! [GET /_matrix/client/r0/profile/{userId}/displayname](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-profile-userid-displayname)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get the display name of a user.",
|
||||
method: GET,
|
||||
name: "get_display_name",
|
||||
path: "/_matrix/client/r0/profile/:user_id/displayname",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The user whose display name will be retrieved.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId
|
||||
}
|
||||
|
||||
response {
|
||||
/// The user's display name, if set.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub displayname: Option<String>
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
33
ruma-client-api/src/r0/profile/get_profile.rs
Normal file
33
ruma-client-api/src/r0/profile/get_profile.rs
Normal file
@ -0,0 +1,33 @@
|
||||
//! [GET /_matrix/client/r0/profile/{userId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-profile-userid)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Get all profile information of an user.",
|
||||
method: GET,
|
||||
name: "get_profile",
|
||||
path: "/_matrix/client/r0/profile/:user_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: false,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The user whose profile will be retrieved.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
}
|
||||
|
||||
response {
|
||||
/// The user's avatar URL, if set.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub avatar_url: Option<String>,
|
||||
|
||||
/// The user's display name, if set.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub displayname: Option<String>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
}
|
30
ruma-client-api/src/r0/profile/set_avatar_url.rs
Normal file
30
ruma-client-api/src/r0/profile/set_avatar_url.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//! [PUT /_matrix/client/r0/profile/{userId}/avatar_url](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-profile-userid-avatar-url)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Set the avatar URL of the user.",
|
||||
method: PUT,
|
||||
name: "set_avatar_url",
|
||||
path: "/_matrix/client/r0/profile/:user_id/avatar_url",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The user whose avatar URL will be set.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
|
||||
/// The new avatar URL for the user.
|
||||
///
|
||||
/// `None` is used to unset the avatar.
|
||||
pub avatar_url: Option<String>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
29
ruma-client-api/src/r0/profile/set_display_name.rs
Normal file
29
ruma-client-api/src/r0/profile/set_display_name.rs
Normal file
@ -0,0 +1,29 @@
|
||||
//! [PUT /_matrix/client/r0/profile/{userId}/displayname](https://matrix.org/docs/spec/client_server/r0.6.0#put-matrix-client-r0-profile-userid-displayname)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::UserId;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Set the display name of the user.",
|
||||
method: PUT,
|
||||
name: "set_display_name",
|
||||
path: "/_matrix/client/r0/profile/:user_id/displayname",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The user whose display name will be set.
|
||||
#[ruma_api(path)]
|
||||
pub user_id: UserId,
|
||||
|
||||
/// The new display name for the user.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub displayname: Option<String>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
140
ruma-client-api/src/r0/push.rs
Normal file
140
ruma-client-api/src/r0/push.rs
Normal file
@ -0,0 +1,140 @@
|
||||
//! Endpoints for push notifications.
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumString};
|
||||
|
||||
pub mod delete_pushrule;
|
||||
pub mod get_notifications;
|
||||
pub mod get_pushers;
|
||||
pub mod get_pushrule;
|
||||
pub mod get_pushrule_actions;
|
||||
pub mod get_pushrule_enabled;
|
||||
pub mod get_pushrules_all;
|
||||
pub mod get_pushrules_global_scope;
|
||||
pub mod set_pusher;
|
||||
pub mod set_pushrule;
|
||||
pub mod set_pushrule_actions;
|
||||
pub mod set_pushrule_enabled;
|
||||
|
||||
pub use ruma_common::push::Action;
|
||||
pub use ruma_events::push_rules::PushCondition;
|
||||
|
||||
/// The kinds of push rules that are available
|
||||
#[derive(
|
||||
Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Display, EnumString,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum RuleKind {
|
||||
/// User-configured rules that override all other kinds
|
||||
Override,
|
||||
|
||||
/// Lowest priority user-defined rules
|
||||
Underride,
|
||||
|
||||
/// Sender-specific rules
|
||||
Sender,
|
||||
|
||||
/// Room-specific rules
|
||||
Room,
|
||||
|
||||
/// Content-specific rules
|
||||
Content,
|
||||
}
|
||||
|
||||
impl TryFrom<&'_ str> for RuleKind {
|
||||
type Error = strum::ParseError;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
/// A push rule
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct PushRule {
|
||||
/// The actions to perform when this rule is matched.
|
||||
pub actions: Vec<Action>,
|
||||
|
||||
/// Whether this is a default rule, or has been set explicitly.
|
||||
pub default: bool,
|
||||
|
||||
/// Whether the push rule is enabled or not.
|
||||
pub enabled: bool,
|
||||
|
||||
/// The ID of this rule.
|
||||
pub rule_id: String,
|
||||
|
||||
/// The conditions that must hold true for an event in order for a rule to be applied to an event. A rule with no conditions always matches.
|
||||
/// Only applicable to underride and override rules.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub conditions: Option<Vec<PushCondition>>,
|
||||
|
||||
/// The glob-style pattern to match against. Only applicable to content rules.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub pattern: Option<String>,
|
||||
}
|
||||
|
||||
/// Defines a pusher
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Pusher {
|
||||
/// This is a unique identifier for this pusher. Max length, 512 bytes.
|
||||
pub pushkey: String,
|
||||
|
||||
/// The kind of the pusher. If set to None in a call to set_pusher, this
|
||||
/// will delete the pusher
|
||||
pub kind: Option<PusherKind>,
|
||||
|
||||
/// This is a reverse-DNS style identifier for the application. Max length, 64 chars.
|
||||
pub app_id: String,
|
||||
|
||||
/// A string that will allow the user to identify what application owns this pusher.
|
||||
pub app_display_name: String,
|
||||
|
||||
/// A string that will allow the user to identify what device owns this pusher.
|
||||
pub device_display_name: String,
|
||||
|
||||
/// This string determines which set of device specific rules this pusher executes.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub profile_tag: Option<String>,
|
||||
|
||||
/// The preferred language for receiving notifications (e.g. 'en' or 'en-US')
|
||||
pub lang: String,
|
||||
|
||||
/// Information for the pusher implementation itself.
|
||||
pub data: PusherData,
|
||||
}
|
||||
|
||||
/// Which kind a pusher is
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PusherKind {
|
||||
/// A pusher that sends HTTP pokes.
|
||||
Http,
|
||||
|
||||
/// A pusher that emails the user with unread notifications.
|
||||
Email,
|
||||
}
|
||||
|
||||
/// Information for the pusher implementation itself.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct PusherData {
|
||||
/// Required if the pusher's kind is http. The URL to use to send notifications to.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub url: Option<String>,
|
||||
|
||||
/// The format to use when sending notifications to the Push Gateway.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub format: Option<PushFormat>,
|
||||
}
|
||||
|
||||
/// A special format that the homeserver should use when sending notifications to a Push Gateway.
|
||||
/// Currently, only "event_id_only" is supported as of [Push Gateway API r0.1.1](https://matrix.org/docs/spec/push_gateway/r0.1.1#homeserver-behaviour)
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PushFormat {
|
||||
/// Require the homeserver to only send a reduced set of fields in the push.
|
||||
EventIdOnly,
|
||||
}
|
34
ruma-client-api/src/r0/push/delete_pushrule.rs
Normal file
34
ruma-client-api/src/r0/push/delete_pushrule.rs
Normal file
@ -0,0 +1,34 @@
|
||||
//! [DELETE /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}](https://matrix.org/docs/spec/client_server/r0.6.0#delete-matrix-client-r0-pushrules-scope-kind-ruleid)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::RuleKind;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "This endpoint removes the push rule defined in the path.",
|
||||
method: DELETE,
|
||||
name: "delete_pushrule",
|
||||
path: "/_matrix/client/r0/pushrules/:scope/:kind/:rule_id",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// The scope to delete from. 'global' to specify global rules.
|
||||
#[ruma_api(path)]
|
||||
pub scope: String,
|
||||
|
||||
/// The kind of rule
|
||||
#[ruma_api(path)]
|
||||
pub kind: RuleKind,
|
||||
|
||||
/// The identifier for the rule.
|
||||
#[ruma_api(path)]
|
||||
pub rule_id: String,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user